Ticket #1147: nci_pmc_fixup_minimal.patch
File nci_pmc_fixup_minimal.patch, 19.4 KB (added by plobsing, 12 years ago) |
---|
-
src/pmc/nci.pmc
18 18 19 19 */ 20 20 21 #include "parrot/nci.h" 22 21 23 typedef INTVAL (*nci_sub_t)(PARROT_INTERP, PMC *); 22 typedef INTVAL (*nci_jit_sub_t)(PARROT_INTERP, PMC *, char *);24 typedef nci_sub_t nci_jit_sub_t; 23 25 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 34 27 35 for (i = 1; i < sig_length; i++) { 28 STRING *pcc_sig_params(PARROT_INTERP, STRING *sig); 29 STRING *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++) { 36 36 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, 83 39 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); 86 41 } 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 } 87 88 } 88 89 89 PARROT_ASSERT(j <= sig_length); 90 return string_make(interp, param_buf, j, NULL, PObj_constant_FLAG); 91 } 90 92 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); 93 STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig); 94 STRING *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); 95 100 } 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 } 101 131 } 102 132 103 133 /* actually build the NCI thunk */ … … 106 136 static 107 137 nci_sub_t build_func(PARROT_INTERP, PMC *pmc, Parrot_NCI_attributes *nci_info) 108 138 { 109 STRING *key = nci_info->signature; 110 size_t key_length = Parrot_str_byte_length(interp, key); 139 STRING *key = nci_info->nci_signature; 111 140 int jitted = 0; 112 141 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 118 142 /* Build call function. */ 119 143 nci_info->func = (PMC *)(build_call_func(interp, pmc, key, &jitted)); 120 nci_info->jitted = jitted;121 144 122 145 return (nci_sub_t)nci_info->func; 123 146 } 124 147 125 148 126 149 pmclass 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 */ 136 154 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 137 165 /* 138 166 139 =item C< METHOD get_multisig()>167 =item C<void init()> 140 168 141 Return the MMD signature PMC, if any or a Null PMC.169 Initializes the NCI with a C<NULL> function pointer. 142 170 143 171 =cut 144 172 145 173 */ 146 174 147 METHOD get_multisig() { 148 PMC *sig; 149 GET_ATTR_multi_sig(INTERP, SELF, sig); 150 if (PMC_IS_NULL(sig)) 151 sig = PMCNULL; 152 RETURN(PMC *sig); 175 VTABLE void init() { 176 /* Mark that we're not a raw NCI */ 177 PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 178 /* Mark that we have a custom gc marker */ 179 PObj_custom_mark_SET(SELF); 153 180 } 154 181 155 182 /* 156 183 157 =item C< METHOD set_raw_nci_ptr(void *func)>184 =item C<void *get_pointer()> 158 185 159 Sets the specified function pointer and raw flag. 186 =item C<void set_pointer(void *ptr)> 160 187 188 Get/Set the pointer being wrapped. Setting through this interface sets 189 the raw flag. 190 161 191 =cut 162 192 163 193 */ 164 194 165 METHOD make_raw_nci(PMC *func) {166 VTABLE_set_pointer(interp, SELF, (void *)func);195 VTABLE void *get_pointer() { 196 return PARROT_NCI(SELF)->orig_func; 167 197 } 168 198 199 VTABLE void set_pointer(void *ptr) { 200 SET_ATTR_orig_func(INTERP, SELF, ptr); 201 PObj_get_FLAGS(SELF) |= NCI_raw_FLAG; 202 } 203 169 204 /* 170 205 171 =item C< void init()>206 =item C<STRING *get_string()> 172 207 173 Initializes the NCI with a C<NULL> function pointer. 208 =item C<void set_string(STRING *str)> 174 209 210 Get/Set the NCI signature. 211 175 212 =cut 176 213 177 214 */ 178 215 179 VTABLE void init() { 180 /* Mark that we're not a raw NCI. */ 181 PObj_flag_CLEAR(private2, SELF); 182 PObj_custom_mark_SET(SELF); 216 VTABLE STRING *get_string() { 217 return PARROT_NCI(SELF)->nci_signature; 183 218 } 184 219 220 VTABLE void set_string_native(STRING *str) { 221 if (!PObj_constant_TEST(str)) { 222 str = Parrot_str_copy(INTERP, str); 223 } 224 SET_ATTR_nci_signature(INTERP, SELF, str); 225 226 /* set up derivative attributes */ 227 SET_ATTR_pcc_signature_param(INTERP, SELF, pcc_sig_params(INTERP, str)); 228 SET_ATTR_pcc_signature_ret(INTERP, SELF, pcc_sig_ret(INTERP, str)); 229 /* Arity is length of the NCI signature minus one (the return type). */ 230 SET_ATTR_arity(INTERP, SELF, Parrot_str_byte_length(INTERP, str) - 1); 231 } 232 185 233 /* 186 234 187 235 =item C<void set_pointer_keyed_str(STRING *key, void *func)> 188 236 189 Sets the specified function pointer and signature (C<*key>). 237 Roughly equivalent to C<set_string(key)> and C<set_pointer(func)>. 238 Setting through this interface clears the raw flag. 190 239 191 240 =cut 192 241 193 242 */ 194 243 195 VTABLE void set_pointer(void *ptr) {196 SET_ATTR_orig_func(INTERP, SELF, ptr);197 PObj_flag_SET(private2, SELF);198 }199 200 VTABLE void *get_pointer() {201 return PARROT_NCI(SELF)->orig_func;202 }203 204 244 VTABLE void set_pointer_keyed_str(STRING *key, void *func) { 205 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 206 207 /* Store the original function and signature. */ 208 SET_ATTR_orig_func(INTERP, SELF, func); 209 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); 217 } 218 219 nci_info->signature = key; 245 SELF.set_string_native(key); 246 SELF.set_pointer(func); 247 PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 220 248 } 221 249 222 250 /* … … 232 260 if (PARROT_NCI(SELF)) { 233 261 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 234 262 235 Parrot_gc_mark_STRING_alive(interp, nci_info->signature); 236 Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature); 263 Parrot_gc_mark_STRING_alive(interp, nci_info->nci_signature); 264 Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_param); 265 Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_ret); 237 266 Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature); 238 267 Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig); 239 268 } … … 262 291 * ManagedStruct or Buffer? 263 292 */ 264 293 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; 294 nci_info_ret->orig_func = nci_info_self->orig_func; 295 nci_info_ret->nci_signature = nci_info_self->nci_signature; 296 nci_info_ret->pcc_signature_param = nci_info_self->pcc_signature_param; 297 nci_info_ret->pcc_signature_ret = nci_info_self->pcc_signature_ret; 298 nci_info_ret->long_signature = nci_info_self->long_signature; 299 nci_info_ret->multi_sig = nci_info_self->multi_sig; 268 300 nci_info_ret->arity = nci_info_self->arity; 269 nci_info_ret->jitted = nci_info_self->jitted;270 301 PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7); 271 302 272 303 return ret; … … 306 337 PMC *cont; 307 338 308 339 GET_ATTR_orig_func(INTERP, SELF, orig_func); 309 func = PObj_ flag_TEST(private2, SELF)340 func = PObj_get_FLAGS(SELF) & NCI_raw_FLAG 310 341 ? (nci_sub_t) D2FPTR(orig_func) 311 342 : (nci_sub_t) D2FPTR(nci_info->func); 312 343 … … 320 351 "attempt to call NULL function"); 321 352 } 322 353 323 if (nci_info->jitted) { 324 nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); 354 func(INTERP, SELF); 325 355 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 }340 356 cont = INTERP->current_cont; 341 357 342 358 /* … … 389 405 390 406 /* 391 407 408 =item C<METHOD get_multisig()> 409 410 Return the MMD signature PMC, if any or a Null PMC. 411 412 =cut 413 414 */ 415 416 METHOD get_multisig() { 417 PMC *sig; 418 GET_ATTR_multi_sig(INTERP, SELF, sig); 419 if (sig == NULL) { 420 sig = PMCNULL; 421 } 422 RETURN(PMC *sig); 423 } 424 425 /* 426 392 427 =item C<METHOD arity()> 393 428 394 429 Return the arity of the NCI (the number of arguments). … … 397 432 398 433 */ 399 434 METHOD arity() { 400 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 401 INTVAL arity = 0; 435 INTVAL arity; 436 GET_ATTR_arity(INTERP, SELF, arity); 437 RETURN(INTVAL arity); 438 } 402 439 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 } 440 /* 441 442 =item C<METHOD set_raw_nci_ptr(void *func)> 443 444 Sets the specified function pointer and raw flag. 445 446 =cut 447 448 */ 449 450 METHOD make_raw_nci(PMC *func) { 451 VTABLE_set_pointer(interp, SELF, (void *)func); 452 } 453 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 462 Accessors for all attributes of this class not otherwise accessible through VTABLES. 463 Integers are used for keys to make access easier for JIT. These are also available to 464 PIR from F<runtime/parrot/include/nci.pasm> 465 466 =over 467 468 =item INTVAL keys 469 470 C<PARROT_NCI_ARITY> 471 472 =item STRING keys 473 474 C<PARROT_NCI_PCC_SIGNATURE_PARAMS>, C<PARROT_NCI_PCC_SIGNATURE_RET>, 475 C<PARROT_LONG_SIGNATURE> 476 477 =item PMC keys 478 479 C<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()"); 410 495 } 496 } 411 497 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 } 415 511 } 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 } 416 528 } 417 529 418 530 /* -
include/parrot/nci.h
15 15 16 16 #include "parrot/parrot.h" 17 17 18 /* NCI PMC interface constants */ 19 /* &gen_from_enum(nci.pasm) */ 20 typedef 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 18 29 void *build_call_func(PARROT_INTERP, SHIM(PMC *pmc_nci), NOTNULL(STRING *signature), NOTNULL(int *jitted)); 19 30 20 31 #endif /* PARROT_NCI_H_GUARD */ -
config/gen/parrot_include.pm
39 39 include/parrot/library.h 40 40 include/parrot/longopt.h 41 41 include/parrot/multidispatch.h 42 include/parrot/nci.h 42 43 include/parrot/packfile.h 43 44 include/parrot/stat.h 44 45 include/parrot/string.h 45 46 include/parrot/pmc.h 46 47 include/parrot/warnings.h 47 48 include/parrot/gc_api.h 48 src/pmc/timer.pmc49 49 src/utils.c 50 50 ) ]; 51 51 $data{generated_files} = [ qw(