Ticket #1549: native_pcc_method.patch

File native_pcc_method.patch, 13.9 KB (added by plobsing, 4 years ago)
  • src/multidispatch.c

     
    4343#include "parrot/oplib/ops.h" 
    4444#include "multidispatch.str" 
    4545#include "pmc/pmc_nci.h" 
     46#include "pmc/pmc_nativepccmethod.h" 
    4647#include "pmc/pmc_sub.h" 
    4748#include "pmc/pmc_callcontext.h" 
    4849 
     
    590591    Parrot_Sub_attributes *sub; 
    591592    INTVAL      args, dist, i, j, n, m; 
    592593 
    593     /* has to be a builtin multi method */ 
    594     if (pmc->vtable->base_type == enum_class_NCI) { 
     594    if (pmc->vtable->base_type == enum_class_NativePCCMethod) { 
     595        GETATTR_NativePCCMethod_mmd_multi_sig(interp, pmc, multi_sig); 
     596        if (PMC_IS_NULL(multi_sig)) { 
     597            STRING *long_sig; 
     598 
     599            GETATTR_NativePCCMethod_mmd_long_signature(interp, pmc, long_sig); 
     600            multi_sig = mmd_build_type_tuple_from_long_sig(interp, long_sig); 
     601            SETATTR_NativePCCMethod_mmd_multi_sig(interp, pmc, multi_sig); 
     602        } 
     603    } 
     604    else if (pmc->vtable->base_type == enum_class_NCI) { 
    595605        GETATTR_NCI_multi_sig(interp, pmc, multi_sig); 
    596606        if (PMC_IS_NULL(multi_sig)) { 
    597607            STRING *long_sig; 
     
    602612        } 
    603613    } 
    604614    else { 
    605         /* not a multi; no distance */ 
    606615        PMC_get_sub(interp, pmc, sub); 
     616 
    607617        if (!sub->multi_signature) 
    608             return 0; 
     618            return 0; /* not a multi; no distance */ 
    609619 
    610620        multi_sig = Parrot_mmd_get_cached_multi_sig(interp, pmc); 
    611621    } 
     
    970980    /* Attach a type tuple array to the sub for multi dispatch */ 
    971981    PMC    *multi_sig = mmd_build_type_tuple_from_type_list(interp, type_list); 
    972982 
    973     if (sub_obj->vtable->base_type == enum_class_NCI) { 
     983    if (sub_obj->vtable->base_type == enum_class_NativePCCMethod) { 
     984        SETATTR_NativePCCMethod_mmd_multi_sig(interp, sub_obj, multi_sig); 
     985    } 
     986    else if (sub_obj->vtable->base_type == enum_class_NCI) { 
    974987        SETATTR_NCI_multi_sig(interp, sub_obj, multi_sig); 
    975988    } 
    976989    else if (VTABLE_isa(interp, sub_obj, sub_str) 
  • src/oo.c

     
    998998        class_name = _class->vtable->whoami; 
    999999 
    10001000    if (sub) { 
    1001         if (sub->vtable->base_type == enum_class_NCI) 
     1001        if (sub->vtable->base_type == enum_class_NativePCCMethod) 
     1002            result = "NativePCCMethod"; 
     1003        else if (sub->vtable->base_type == enum_class_NCI) 
    10021004            result = "NCI"; 
    10031005        else 
    10041006            result = "Sub"; 
  • src/pmc/nativepccmethod.pmc

     
     1/* 
     2Copyright (C) 2010, Parrot Foundation. 
     3$Id$ 
     4 
     5=head1 NAME 
     6 
     7src/pmc/nativepccmethod.pmc - Native PCC Method PMC 
     8 
     9=head1 DESCRIPTION 
     10 
     11Container for native functions that handle PCC on their own. 
     12 
     13=head2 Methods 
     14 
     15=over 4 
     16 
     17=cut 
     18 
     19*/ 
     20 
     21/* HEADERIZER HFILE: none */ 
     22 
     23pmclass NativePCCMethod auto_attrs { 
     24    ATTR STRING *signature; 
     25    ATTR void   *func; 
     26 
     27    /* MMD fields */ 
     28    ATTR STRING *mmd_long_signature; 
     29    ATTR PMC    *mmd_multi_sig; 
     30 
     31/* 
     32 
     33=item C<void init()> 
     34 
     35Initializes the PMC with a C<NULL> function pointer. 
     36 
     37=cut 
     38 
     39*/ 
     40 
     41    VTABLE void init() { 
     42        Parrot_NativePCCMethod_attributes *attrs = PARROT_NATIVEPCCMETHOD(SELF); 
     43 
     44        attrs->func               = NULL; 
     45        attrs->signature          = STRINGNULL; 
     46        attrs->mmd_long_signature = STRINGNULL; 
     47        attrs->mmd_multi_sig      = PMCNULL; 
     48 
     49        PObj_custom_mark_SET(SELF); 
     50    } 
     51 
     52/* 
     53 
     54=item C<void *get_pointer()> 
     55 
     56Get the pointer to the native function. 
     57 
     58=item C<void set_pointer_keyed_str(STRING *sig, void *func)> 
     59 
     60Set the pointer to the native function and the PCC signature. 
     61 
     62=cut 
     63 
     64*/ 
     65 
     66 
     67    VTABLE void *get_pointer() { 
     68        return PARROT_NATIVEPCCMETHOD(SELF)->func; 
     69    } 
     70 
     71    VTABLE void set_pointer_keyed_str(STRING *sig, void *func) { 
     72        PARROT_NATIVEPCCMETHOD(SELF)->signature = sig; 
     73        PARROT_NATIVEPCCMETHOD(SELF)->func = func; 
     74    } 
     75 
     76/* 
     77 
     78=item C<INTVAL defined()> 
     79 
     80=item C<INTVAL get_bool()> 
     81 
     82NULLness check. 
     83 
     84=cut 
     85 
     86*/ 
     87 
     88    VTABLE INTVAL defined() { 
     89        return !! PARROT_NATIVEPCCMETHOD(SELF)->func; 
     90    } 
     91 
     92    VTABLE INTVAL get_bool() { 
     93        return STATICSELF.defined(); 
     94    } 
     95 
     96/* 
     97 
     98=item C<opcode_t *invoke(void *next)> 
     99 
     100Call the function pointer. 
     101 
     102=cut 
     103 
     104*/ 
     105 
     106    VTABLE opcode_t *invoke(void *next) { 
     107        void                *func; 
     108        native_pcc_method_t  fptr; 
     109 
     110        GET_ATTR_func(INTERP, SELF, func); 
     111        if (!func) 
     112            Parrot_ex_throw_from_c_args(INTERP, NULL, 
     113                    EXCEPTION_INVALID_OPERATION, 
     114                    "attempt to call NULL native function"); 
     115 
     116        fptr = D2FPTR(func); 
     117        fptr(INTERP); 
     118 
     119        /* 
     120         * If this function was tailcalled, the return result 
     121         * is already passed back to the caller of this frame. 
     122         * We therefore invoke the return continuation here, 
     123         * which gets rid of this frame and returns the real 
     124         * return address. 
     125         */ 
     126        { 
     127            PMC *cont = INTERP->current_cont; 
     128 
     129            if (cont && cont != NEED_CONTINUATION 
     130            && (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) { 
     131                cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp)); 
     132                next = VTABLE_invoke(INTERP, cont, next); 
     133            } 
     134        } 
     135 
     136        return (opcode_t *)next; 
     137    } 
     138 
     139/* 
     140 
     141=item C<void mark()> 
     142 
     143Mark contained elements for GC. 
     144 
     145=cut 
     146 
     147*/ 
     148 
     149    VTABLE void mark() { 
     150        Parrot_NativePCCMethod_attributes *attrs = PARROT_NATIVEPCCMETHOD(SELF); 
     151 
     152        Parrot_gc_mark_STRING_alive(interp, attrs->signature); 
     153        Parrot_gc_mark_STRING_alive(interp, attrs->mmd_long_signature); 
     154        Parrot_gc_mark_PMC_alive(interp,    attrs->mmd_multi_sig); 
     155    } 
     156 
     157/* 
     158 
     159=item C<PMC *clone()> 
     160 
     161Create a clone of this PMC. 
     162 
     163=cut 
     164 
     165*/ 
     166 
     167    VTABLE PMC *clone() { 
     168        PMC *ret = Parrot_pmc_new(INTERP, SELF->vtable->base_type); 
     169        Parrot_NativePCCMethod_attributes *self_attrs = PARROT_NATIVEPCCMETHOD(SELF); 
     170        Parrot_NativePCCMethod_attributes *ret_attrs  = PARROT_NATIVEPCCMETHOD(ret); 
     171 
     172        ret_attrs->func               = self_attrs->func; 
     173        ret_attrs->signature          = self_attrs->signature; 
     174        ret_attrs->mmd_long_signature = self_attrs->mmd_long_signature; 
     175        ret_attrs->mmd_multi_sig      = self_attrs->mmd_multi_sig; 
     176 
     177        return ret; 
     178    } 
     179} 
     180 
     181/* 
     182 
     183=back 
     184 
     185=head1 SEE ALSO 
     186 
     187F<docs/pdds/pdd03_calling_conventions.pod>. 
     188 
     189=cut 
     190 
     191*/ 
     192 
     193/* 
     194 * Local variables: 
     195 *   c-file-style: "parrot" 
     196 * End: 
     197 * vim: expandtab shiftwidth=4: 
     198 */ 
  • src/pmc/namespace.pmc

     
    3232        __attribute__nonnull__(2) 
    3333        __attribute__nonnull__(3); 
    3434 
    35 static void add_nci_to_namespace(PARROT_INTERP, 
     35static void add_native_to_namespace(PARROT_INTERP, 
    3636    ARGIN(PMC *SELF), 
    3737    ARGIN(STRING *key), 
    3838    ARGIN_NULLOK(PMC *value)) 
     
    7676       PARROT_ASSERT_ARG(interp) \ 
    7777    , PARROT_ASSERT_ARG(SELF) \ 
    7878    , PARROT_ASSERT_ARG(key)) 
    79 #define ASSERT_ARGS_add_nci_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     79#define ASSERT_ARGS_add_native_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    8080       PARROT_ASSERT_ARG(interp) \ 
    8181    , PARROT_ASSERT_ARG(SELF) \ 
    8282    , PARROT_ASSERT_ARG(key)) 
     
    199199} 
    200200 
    201201static void 
    202 add_nci_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key), 
     202add_native_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key), 
    203203        ARGIN_NULLOK(PMC *value)) 
    204204{ 
    205     ASSERT_ARGS(add_nci_to_namespace) 
     205    ASSERT_ARGS(add_native_to_namespace) 
    206206 
    207     STRING * const nci_str = CONST_STRING(interp, "NCI"); 
    208  
    209207    if (!PMC_IS_NULL(value) 
    210     &&   VTABLE_isa(interp, value, nci_str)) { 
     208    && (value->vtable->base_type == enum_class_NativePCCMethod || 
     209        value->vtable->base_type == enum_class_NCI)) { 
    211210        Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF); 
    212211        PMC * const classobj = VTABLE_get_class(interp, SELF); 
    213212 
     
    388387        if (maybe_add_sub_to_namespace(INTERP, SELF, key, value)) 
    389388            return; 
    390389 
    391         /* If it's an NCI method */ 
    392         add_nci_to_namespace(INTERP, SELF, key, value); 
     390        /* If it's an native method */ 
     391        add_native_to_namespace(INTERP, SELF, key, value); 
    393392 
    394393        /* If it's a multi-sub and the first in this NS... */ 
    395394        add_multi_to_namespace(INTERP, SELF, key, value); 
  • src/interp/inter_misc.c

     
    6868 
    6969/* 
    7070 
    71 =item C<void register_raw_nci_method_in_ns(PARROT_INTERP, const int type, void 
    72 *func, STRING *name)> 
     71=item C<void register_native_pcc_method_in_ns(PARROT_INTERP, const int type, 
     72void *func, STRING *name, STRING *signature)> 
    7373 
    7474Create an entry in the C<nci_method_table> for the given raw NCI method 
    7575of PMC class C<type>. 
     
    8080 
    8181PARROT_EXPORT 
    8282void 
    83 register_raw_nci_method_in_ns(PARROT_INTERP, const int type, ARGIN(void *func), 
    84         ARGIN(STRING *name)) 
     83register_native_pcc_method_in_ns(PARROT_INTERP, const int type, ARGIN(void *func), 
     84        ARGIN(STRING *name), ARGIN(STRING *signature)) 
    8585{ 
    86     ASSERT_ARGS(register_raw_nci_method_in_ns) 
    87     PMC    * const method      = Parrot_pmc_new(interp, enum_class_NCI); 
     86    ASSERT_ARGS(register_native_pcc_method_in_ns) 
     87    PMC * method = Parrot_pmc_new(interp, enum_class_NativePCCMethod); 
    8888 
    8989    /* setup call func */ 
    90     VTABLE_set_pointer(interp, method, func); 
     90    VTABLE_set_pointer_keyed_str(interp, method, signature, func); 
    9191 
    9292    /* insert it into namespace */ 
    9393    VTABLE_set_pmc_keyed_str(interp, interp->vtables[type]->_namespace, 
  • lib/Parrot/Pmc2c/PMCEmitter.pm

     
    666666        next unless $method->type eq Parrot::Pmc2c::Method::NON_VTABLE; 
    667667 
    668668        #these differ for METHODs 
    669         my $method_name = $method->name; 
    670         my $symbol_name = $method->symbol; 
     669        my $method_name     = $method->name; 
     670        my $symbol_name     = $method->symbol; 
     671        my ($pcc_signature) = $method->pcc_signature; 
    671672 
    672673        $cout .= <<"EOC"; 
    673         register_raw_nci_method_in_ns(interp, entry, F2DPTR(Parrot_${classname}_${method_name}), CONST_STRING_GEN(interp, "$symbol_name")); 
     674        { 
     675            STRING *method_name = CONST_STRING_GEN(interp, "$symbol_name"); 
     676            STRING *signature   = CONST_STRING_GEN(interp, "$pcc_signature"); 
     677            register_native_pcc_method_in_ns(interp, entry, 
     678                F2DPTR(Parrot_${classname}_${method_name}), 
     679                method_name, signature); 
     680        } 
    674681EOC 
    675682        if ( $method->{attrs}{write} ) { 
    676683            $cout .= <<"EOC"; 
  • include/parrot/interpreter.h

     
    503503        __attribute__nonnull__(3); 
    504504 
    505505PARROT_EXPORT 
    506 void register_nci_method(PARROT_INTERP, 
     506void register_native_pcc_method_in_ns(PARROT_INTERP, 
    507507    const int type, 
    508508    ARGIN(void *func), 
    509     ARGIN(const char *name), 
    510     ARGIN(const char *proto)) 
     509    ARGIN(STRING *name), 
     510    ARGIN(STRING *signature)) 
    511511        __attribute__nonnull__(1) 
    512512        __attribute__nonnull__(3) 
    513513        __attribute__nonnull__(4) 
    514514        __attribute__nonnull__(5); 
    515515 
    516516PARROT_EXPORT 
    517 void register_raw_nci_method_in_ns(PARROT_INTERP, 
     517void register_nci_method(PARROT_INTERP, 
    518518    const int type, 
    519519    ARGIN(void *func), 
    520     ARGIN(STRING *name)) 
     520    ARGIN(const char *name), 
     521    ARGIN(const char *proto)) 
    521522        __attribute__nonnull__(1) 
    522523        __attribute__nonnull__(3) 
    523         __attribute__nonnull__(4); 
     524        __attribute__nonnull__(4) 
     525        __attribute__nonnull__(5); 
    524526 
    525527PARROT_WARN_UNUSED_RESULT 
    526528INTVAL sysinfo_i(SHIM_INTERP, INTVAL info_wanted); 
     
    547549#define ASSERT_ARGS_Parrot_mark_method_writes __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    548550       PARROT_ASSERT_ARG(interp) \ 
    549551    , PARROT_ASSERT_ARG(name)) 
     552#define ASSERT_ARGS_register_native_pcc_method_in_ns \ 
     553     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     554       PARROT_ASSERT_ARG(interp) \ 
     555    , PARROT_ASSERT_ARG(func) \ 
     556    , PARROT_ASSERT_ARG(name) \ 
     557    , PARROT_ASSERT_ARG(signature)) 
    550558#define ASSERT_ARGS_register_nci_method __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    551559       PARROT_ASSERT_ARG(interp) \ 
    552560    , PARROT_ASSERT_ARG(func) \ 
    553561    , PARROT_ASSERT_ARG(name) \ 
    554562    , PARROT_ASSERT_ARG(proto)) 
    555 #define ASSERT_ARGS_register_raw_nci_method_in_ns __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    556        PARROT_ASSERT_ARG(interp) \ 
    557     , PARROT_ASSERT_ARG(func) \ 
    558     , PARROT_ASSERT_ARG(name)) 
    559563#define ASSERT_ARGS_sysinfo_i __attribute__unused__ int _ASSERT_ARGS_CHECK = (0) 
    560564#define ASSERT_ARGS_sysinfo_s __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    561565       PARROT_ASSERT_ARG(interp)) 
  • include/parrot/nci.h

     
    1717 
    1818typedef PMC *(*nci_fb_func_t)(PARROT_INTERP, PMC *user_data, STRING *signature); 
    1919typedef void (*nci_thunk_t)(PARROT_INTERP, PMC *, PMC *); 
     20typedef void (*native_pcc_method_t)(PARROT_INTERP); 
    2021 
    2122void Parrot_nci_load_core_thunks(PARROT_INTERP); 
    2223void Parrot_nci_load_extra_thunks(PARROT_INTERP);