Ticket #1147: nci_pmc_fixup_minimal_v2.patch

File nci_pmc_fixup_minimal_v2.patch, 18.2 KB (added by plobsing, 5 years ago)

removed code motion as best I could

  • src/pmc/nci.pmc

     
    1818 
    1919*/ 
    2020 
     21#include "parrot/nci.h" 
     22 
    2123typedef INTVAL (*nci_sub_t)(PARROT_INTERP, PMC *); 
    22 typedef INTVAL (*nci_jit_sub_t)(PARROT_INTERP, PMC *, char *); 
     24typedef nci_sub_t nci_jit_sub_t; 
    2325 
    24 void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info, 
    25                 size_t sig_length); 
    26 void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info, 
    27                 size_t sig_length) { 
    28     char    param_buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 
    29     char   *param_sig    = sig_length <= 7 
    30                          ? param_buf 
    31                          : mem_allocate_n_typed(sig_length, char); 
    32     size_t  j            = 0; 
    33     size_t  i; 
     26#define NCI_raw_FLAG    PObj_private0_FLAG 
    3427 
    35     for (i = 1; i < sig_length; i++) { 
     28STRING *pcc_sig_params(PARROT_INTERP, STRING *sig); 
     29STRING *pcc_sig_params(PARROT_INTERP, STRING *sig) { 
     30    size_t sig_len = Parrot_str_byte_length(interp, sig); 
     31    char param_buf[sig_len*2]; 
     32 
     33    size_t i, j; 
     34 
     35    for (i = 1, j = 0; i < sig_len; i++) { 
    3636        INTVAL c = Parrot_str_indexed(interp, sig, i); 
    37  
    38         switch (c) { 
    39             case (INTVAL)'0':    /* null ptr or such - doesn't consume a reg */ 
    40                 break; 
    41             case (INTVAL)'f': 
    42             case (INTVAL)'N': 
    43             case (INTVAL)'d': 
    44                 param_sig[j++] = 'N'; 
    45                 break; 
    46             case (INTVAL)'I':   /* INTVAL */ 
    47             case (INTVAL)'l':   /* long */ 
    48             case (INTVAL)'i':   /* int */ 
    49             case (INTVAL)'s':   /* short */ 
    50             case (INTVAL)'c':   /* char */ 
    51                 param_sig[j++] = 'I'; 
    52                 break; 
    53             case (INTVAL)'S': 
    54             case (INTVAL)'t':   /* string, pass a cstring */ 
    55                 param_sig[j++] = 'S'; 
    56                 break; 
    57             case (INTVAL)'J':   /* interpreter */ 
    58                 break; 
    59             case (INTVAL)'p':   /* push pmc->data */ 
    60             case (INTVAL)'O':   /* push PMC * object in P2 */ 
    61             case (INTVAL)'P':   /* push PMC * */ 
    62             case (INTVAL)'V':   /* push PMC * */ 
    63                 param_sig[j++] = 'P'; 
    64             case (INTVAL)'v': 
    65                 break; 
    66                 /* I have no idea how to handle these */ 
    67             case (INTVAL)'2': 
    68             case (INTVAL)'3': 
    69             case (INTVAL)'4': 
    70                 param_sig[j++] = 'I'; 
    71                 break; 
    72             case (INTVAL)'@': 
    73                 param_sig[j++] = '@'; 
    74                 break; 
    75             case (INTVAL)'b': /* buffer (void*) pass Buffer_bufstart(SReg) */ 
    76             case (INTVAL)'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */ 
    77                 param_sig[j++] = 'S'; 
    78                 break; 
    79             default: 
    80                 if (sig_length > 7) 
    81                     mem_sys_free(param_sig); 
    82                 Parrot_ex_throw_from_c_args(interp, NULL, 
     37        if (c > 127) { 
     38            Parrot_ex_throw_from_c_args(interp, NULL, 
    8339                    EXCEPTION_JIT_ERROR, 
    84                     "Unknown param Signature %c\n", (char)c); 
    85                 break; 
     40                    "Unknown param type at %d in signature '%S' (way too big)\n", i, sig); 
    8641        } 
     42        else { 
     43            switch ((char)c) { 
     44                case 'v': 
     45                case '0': 
     46                case 'J': 
     47                    break; 
     48                case 'N': 
     49                case 'd': 
     50                case 'f': 
     51                    param_buf[j++] = 'N'; 
     52                    break; 
     53                case 'I': 
     54                case 'l': 
     55                case 'i': 
     56                case 's': 
     57                case 'c': 
     58                    param_buf[j++] = 'I'; 
     59                    break; 
     60                case 'S': 
     61                case 't': 
     62                case 'b': 
     63                case 'B': 
     64                    param_buf[j++] = 'S'; 
     65                    break; 
     66                case 'P': 
     67                case 'p': 
     68                case 'V': 
     69                case '2': 
     70                case '3': 
     71                case '4': 
     72                    param_buf[j++] = 'P'; 
     73                    break; 
     74                case 'O': 
     75                    param_buf[j++] = 'P'; 
     76                    param_buf[j++] = 'i'; 
     77                    break; 
     78                case '@': 
     79                    param_buf[j++] = 'P'; 
     80                    param_buf[j++] = 's'; 
     81                    break; 
     82                default: 
     83                    Parrot_ex_throw_from_c_args(interp, NULL, 
     84                            EXCEPTION_JIT_ERROR, 
     85                            "Unknown param type at %d in signature '%S'\n", i, sig); 
     86            } 
     87        } 
    8788    } 
    8889 
    89     PARROT_ASSERT(j <= sig_length); 
     90    return string_make(interp, param_buf, j, NULL, PObj_constant_FLAG); 
     91} 
    9092 
    91     /* use only the signature-significant part of the string buffer */ 
    92     if (j) { 
    93         nci_info->pcc_params_signature = string_make(interp, param_sig, j, 
    94             NULL, PObj_constant_FLAG); 
     93STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig); 
     94STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig) { 
     95    INTVAL c = Parrot_str_indexed(interp, sig, 0); 
     96    if (c > 127) { 
     97        Parrot_ex_throw_from_c_args(interp, NULL, 
     98                EXCEPTION_JIT_ERROR, 
     99                "Unknown return type at %d in signature '%S' (way too big)\n", 0, sig); 
    95100    } 
    96     else 
    97         nci_info->pcc_params_signature = CONST_STRING(interp, ""); 
    98  
    99     if (sig_length > 7) 
    100         mem_sys_free(param_sig); 
     101    else { 
     102        switch ((char)c) { 
     103            case 'v': 
     104                return CONST_STRING(interp, "v"); 
     105            case 'N': 
     106            case 'f': 
     107            case 'd': 
     108                return CONST_STRING(interp, "N"); 
     109            case 'I': 
     110            case 'l': 
     111            case 'i': 
     112            case 's': 
     113            case 'c': 
     114                return CONST_STRING(interp, "I"); 
     115            case 'S': 
     116            case 't': 
     117                return CONST_STRING(interp, "S"); 
     118            case 'p': 
     119            case 'P': 
     120                return CONST_STRING(interp, "P"); 
     121            case '2': 
     122            case '3': 
     123            case '4': 
     124                return CONST_STRING(interp, "P"); 
     125            default: 
     126                Parrot_ex_throw_from_c_args(interp, NULL, 
     127                        EXCEPTION_JIT_ERROR, 
     128                        "Unknown return type at %d in signature '%S'\n", 0, sig); 
     129        } 
     130    } 
    101131} 
    102132 
    103133/* actually build the NCI thunk */ 
     
    106136static 
    107137nci_sub_t build_func(PARROT_INTERP, PMC *pmc, Parrot_NCI_attributes *nci_info) 
    108138{ 
    109     STRING    *key        = nci_info->signature; 
    110     size_t     key_length = Parrot_str_byte_length(interp, key); 
     139    STRING    *key        = nci_info->nci_signature; 
    111140    int       jitted      = 0; 
    112141 
    113     pcc_params(interp, key, nci_info, key_length); 
    114  
    115     /* Arity is length of that string minus one (the return type). */ 
    116     nci_info->arity       = key_length - 1; 
    117  
    118142    /* Build call function. */ 
    119143    nci_info->func        = (PMC *)(build_call_func(interp, pmc, key, &jitted)); 
    120     nci_info->jitted      = jitted; 
    121144 
    122145    return (nci_sub_t)nci_info->func; 
    123146} 
    124147 
    125148 
    126149pmclass NCI auto_attrs { 
    127     ATTR STRING    *signature;              /* The signature. */ 
    128     ATTR void      *func;                   /* Function pointer to call. */ 
    129     ATTR void      *orig_func;              /* Function pointer 
    130                                              * used to create func */ 
    131     ATTR STRING    *pcc_params_signature;   /* The signature. */ 
    132     ATTR STRING    *long_signature;         /* The full signature. */ 
    133     ATTR PMC       *multi_sig;              /* type tuple array (?) */ 
    134     ATTR INTVAL     arity;                  /* Cached arity of the NCI. */ 
    135     ATTR INTVAL     jitted;                 /* Is this a jitted NCI stub. */ 
     150    /* Signature Attributes */ 
     151    ATTR STRING    *nci_signature;          /* The NCI signature */ 
     152    ATTR STRING    *pcc_signature_ret;      /* The PCC return signature */ 
     153    ATTR STRING    *pcc_signature_param;    /* The PCC param signature */ 
    136154 
     155    /* Function Pointers */ 
     156    ATTR void      *func;                   /* Function pointer to call */ 
     157    ATTR void      *orig_func;              /* Function pointer being wrapped */ 
     158 
     159    /* Sub PMC Attributes */ 
     160    ATTR INTVAL     arity;                  /* Number of params taken */ 
     161    /* MMD Attributes */ 
     162    ATTR PMC       *multi_sig; 
     163    ATTR STRING    *long_signature; 
     164 
    137165/* 
    138166 
    139167=item C<METHOD get_multisig()> 
     
    147175    METHOD get_multisig() { 
    148176        PMC *sig; 
    149177        GET_ATTR_multi_sig(INTERP, SELF, sig); 
    150         if (PMC_IS_NULL(sig)) 
     178        if (sig == NULL) { 
    151179            sig = PMCNULL; 
     180        } 
    152181        RETURN(PMC *sig); 
    153182    } 
    154183 
     
    178207 
    179208    VTABLE void init() { 
    180209        /* Mark that we're not a raw NCI. */ 
    181         PObj_flag_CLEAR(private2, SELF); 
     210        PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 
     211        /* Mark that we have a custom gc marker */ 
    182212        PObj_custom_mark_SET(SELF); 
    183213    } 
    184214 
    185215/* 
    186216 
    187 =item C<void set_pointer_keyed_str(STRING *key, void *func)> 
     217=item C<void *get_pointer()> 
    188218 
    189 Sets the specified function pointer and signature (C<*key>). 
     219=item C<void set_pointer(void *ptr)> 
    190220 
     221Get/Set the pointer being wrapped. Setting through this interface sets 
     222the raw flag. 
     223 
    191224=cut 
    192225 
    193226*/ 
    194227 
    195228    VTABLE void set_pointer(void *ptr) { 
    196229        SET_ATTR_orig_func(INTERP, SELF, ptr); 
    197         PObj_flag_SET(private2, SELF); 
     230        PObj_get_FLAGS(SELF) |= NCI_raw_FLAG; 
    198231    } 
    199232 
    200233    VTABLE void *get_pointer() { 
    201234        return PARROT_NCI(SELF)->orig_func; 
    202235    } 
    203236 
     237/* 
     238 
     239=item C<void set_pointer_keyed_str(STRING *key, void *func)> 
     240 
     241Roughly equivalent to C<set_string(key)> and C<set_pointer(func)>. 
     242Setting through this interface clears the raw flag. 
     243 
     244=cut 
     245 
     246*/ 
     247 
    204248    VTABLE void set_pointer_keyed_str(STRING *key, void *func) { 
    205         Parrot_NCI_attributes * const nci_info   = PARROT_NCI(SELF); 
     249        SELF.set_string_native(key); 
     250        SELF.set_pointer(func); 
     251        PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 
     252    } 
    206253 
    207         /* Store the original function and signature. */ 
    208         SET_ATTR_orig_func(INTERP, SELF, func); 
     254/* 
    209255 
    210         /* ensure that the STRING signature is constant */ 
    211         if (!PObj_constant_TEST(key)) { 
    212             char * const key_c      = Parrot_str_to_cstring(INTERP, key); 
    213             size_t       key_length = Parrot_str_byte_length(interp, key); 
    214             key                     = string_make(interp, key_c, key_length, 
    215                                         NULL, PObj_constant_FLAG); 
    216             Parrot_str_free_cstring(key_c); 
     256=item C<STRING *get_string()> 
     257 
     258=item C<void set_string(STRING *str)> 
     259 
     260Get/Set the NCI signature. 
     261 
     262=cut 
     263 
     264*/ 
     265 
     266    VTABLE STRING *get_string() { 
     267        return PARROT_NCI(SELF)->nci_signature; 
     268    } 
     269 
     270    VTABLE void set_string_native(STRING *str) { 
     271        if (!PObj_constant_TEST(str)) { 
     272            str = Parrot_str_copy(INTERP, str); 
    217273        } 
     274        SET_ATTR_nci_signature(INTERP, SELF, str); 
    218275 
    219         nci_info->signature = key; 
     276        /* set up derivative attributes */ 
     277        SET_ATTR_pcc_signature_param(INTERP, SELF, pcc_sig_params(INTERP, str)); 
     278        SET_ATTR_pcc_signature_ret(INTERP, SELF, pcc_sig_ret(INTERP, str)); 
     279        /* Arity is length of the NCI signature minus one (the return type). */ 
     280        SET_ATTR_arity(INTERP, SELF, Parrot_str_byte_length(INTERP, str) - 1); 
    220281    } 
    221282 
    222283/* 
     
    232293        if (PARROT_NCI(SELF)) { 
    233294            Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 
    234295 
    235             Parrot_gc_mark_STRING_alive(interp, nci_info->signature); 
    236             Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature); 
     296            Parrot_gc_mark_STRING_alive(interp, nci_info->nci_signature); 
     297            Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_param); 
     298            Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_ret); 
    237299            Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature); 
    238300            Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig); 
    239301        } 
     
    262324         * ManagedStruct or Buffer? 
    263325         */ 
    264326        nci_info_ret->func                  = nci_info_self->func; 
    265         nci_info_ret->orig_func             = nci_info_self->orig_func; 
    266         nci_info_ret->signature             = nci_info_self->signature; 
    267         nci_info_ret->pcc_params_signature  = nci_info_self->pcc_params_signature; 
     327        nci_info_ret->orig_func              = nci_info_self->orig_func; 
     328        nci_info_ret->nci_signature         = nci_info_self->nci_signature; 
     329        nci_info_ret->pcc_signature_param   = nci_info_self->pcc_signature_param; 
     330        nci_info_ret->pcc_signature_ret     = nci_info_self->pcc_signature_ret; 
     331        nci_info_ret->long_signature        = nci_info_self->long_signature; 
     332        nci_info_ret->multi_sig             = nci_info_self->multi_sig; 
    268333        nci_info_ret->arity                 = nci_info_self->arity; 
    269         nci_info_ret->jitted                = nci_info_self->jitted; 
    270334        PObj_get_FLAGS(ret)                |= (PObj_get_FLAGS(SELF) & 0x7); 
    271335 
    272336        return ret; 
     
    306370        PMC                          *cont; 
    307371 
    308372        GET_ATTR_orig_func(INTERP, SELF, orig_func); 
    309         func = PObj_flag_TEST(private2, SELF) 
     373        func = PObj_get_FLAGS(SELF) & NCI_raw_FLAG 
    310374            ? (nci_sub_t) D2FPTR(orig_func) 
    311375            : (nci_sub_t) D2FPTR(nci_info->func); 
    312376 
     
    320384                    "attempt to call NULL function"); 
    321385        } 
    322386 
    323         if (nci_info->jitted) { 
    324             nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); 
     387        func(INTERP, SELF); 
    325388 
    326             /* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */ 
    327             sig_str = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature); 
    328             jit_func(INTERP, SELF, sig_str); 
    329             Parrot_str_free_cstring(sig_str); 
    330         } 
    331         else { 
    332             if (PObj_flag_TEST(private2, SELF)) { 
    333                 /* Parrot_eprintf(interp, "RAW NCI CALL\n"); */ 
    334             } 
    335             else { 
    336                 /* Parrot_eprintf(interp, "HACKED %S\n", nci_info->signature); */ 
    337             } 
    338             func(INTERP, SELF); 
    339         } 
    340389        cont = INTERP->current_cont; 
    341390 
    342391        /* 
     
    397446 
    398447*/ 
    399448    METHOD arity() { 
    400         Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 
    401         INTVAL arity = 0; 
     449        INTVAL arity; 
     450        GET_ATTR_arity(INTERP, SELF, arity); 
     451        RETURN(INTVAL arity); 
     452    } 
    402453 
    403         if (nci_info) { 
    404             if (!nci_info->func) 
    405                 build_func(INTERP, SELF, nci_info); 
    406             if (nci_info->func) { 
    407                 arity = nci_info->arity; 
    408                 RETURN(INTVAL arity); 
    409             } 
     454/* 
     455 
     456=item C<INTVAL get_integer_keyed_int(INTVAL key)> 
     457 
     458=item C<STRING *get_string_keyed_int(INTVAL key)> 
     459 
     460=item C<PMC *get_pmc_keyed_int(INTVAL key)> 
     461 
     462Accessors for all attributes of this class not otherwise accessible through VTABLES. 
     463Integers are used for keys to make access easier for JIT. These are also available to 
     464PIR from F<runtime/parrot/include/nci.pasm> 
     465 
     466=over 
     467 
     468=item INTVAL keys 
     469 
     470C<PARROT_NCI_ARITY> 
     471 
     472=item STRING keys 
     473 
     474C<PARROT_NCI_PCC_SIGNATURE_PARAMS>, C<PARROT_NCI_PCC_SIGNATURE_RET>, 
     475C<PARROT_LONG_SIGNATURE> 
     476 
     477=item PMC keys 
     478 
     479C<PARROT_NCI_MULTI_SIG> 
     480 
     481=back 
     482 
     483=cut 
     484 
     485*/ 
     486 
     487    VTABLE INTVAL get_integer_keyed_int(INTVAL key) { 
     488        switch (key) { 
     489            case PARROT_NCI_ARITY: 
     490                return PARROT_NCI(SELF)->arity; 
     491            default: 
     492                Parrot_ex_throw_from_c_args(INTERP, NULL, 
     493                    EXCEPTION_INVALID_OPERATION, 
     494                    "Bad index for NCI.get_integer_keyed_int()"); 
    410495        } 
     496    } 
    411497 
    412         Parrot_ex_throw_from_c_args(INTERP, NULL, 
    413             EXCEPTION_INVALID_OPERATION, 
    414             "You cannot get the arity of an undefined NCI."); 
     498    VTABLE STRING *get_string_keyed_int(INTVAL key) { 
     499        switch (key) { 
     500            case PARROT_NCI_PCC_SIGNATURE_PARAMS: 
     501                return PARROT_NCI(SELF)->pcc_signature_param; 
     502            case PARROT_NCI_PCC_SIGNATURE_RET: 
     503                return PARROT_NCI(SELF)->pcc_signature_ret; 
     504            case PARROT_NCI_LONG_SIGNATURE: 
     505                return PARROT_NCI(SELF)->long_signature; 
     506            default: 
     507                Parrot_ex_throw_from_c_args(INTERP, NULL, 
     508                    EXCEPTION_INVALID_OPERATION, 
     509                    "Bad index for NCI.get_string_keyed_int()"); 
     510        } 
    415511    } 
     512 
     513    VTABLE PMC *get_pmc_keyed_int(INTVAL key) { 
     514        PMC *retval; 
     515        switch (key) { 
     516            case PARROT_NCI_MULTI_SIG: 
     517                GET_ATTR_multi_sig(INTERP, SELF, retval); 
     518            default: 
     519                Parrot_ex_throw_from_c_args(INTERP, NULL, 
     520                    EXCEPTION_INVALID_OPERATION, 
     521                    "Bad index for NCI.get_pmc_keyed_int()"); 
     522        } 
     523        if (retval == NULL) { 
     524            retval = PMCNULL; 
     525        } 
     526        return retval; 
     527    } 
    416528} 
    417529 
    418530/* 
  • include/parrot/nci.h

     
    1515 
    1616#include "parrot/parrot.h" 
    1717 
     18/* NCI PMC interface constants */ 
     19/* &gen_from_enum(nci.pasm) */ 
     20typedef enum { 
     21    PARROT_NCI_ARITY, 
     22    PARROT_NCI_PCC_SIGNATURE_PARAMS, 
     23    PARROT_NCI_PCC_SIGNATURE_RET, 
     24    PARROT_NCI_LONG_SIGNATURE, 
     25    PARROT_NCI_MULTI_SIG, 
     26} parrot_nci_enum_t; 
     27/* &end_gen */ 
     28 
    1829void *build_call_func(PARROT_INTERP, SHIM(PMC *pmc_nci), NOTNULL(STRING *signature), NOTNULL(int *jitted)); 
    1930 
    2031#endif /* PARROT_NCI_H_GUARD */ 
  • config/gen/parrot_include.pm

     
    3939        include/parrot/library.h 
    4040        include/parrot/longopt.h 
    4141        include/parrot/multidispatch.h 
     42        include/parrot/nci.h 
    4243        include/parrot/packfile.h 
    4344        include/parrot/stat.h 
    4445        include/parrot/string.h 
    4546        include/parrot/pmc.h 
    4647        include/parrot/warnings.h 
    4748        include/parrot/gc_api.h 
    48         src/pmc/timer.pmc 
    4949        src/utils.c 
    5050    ) ]; 
    5151    $data{generated_files} = [ qw(