Ticket #1147: nci_pmc_fixup_minimal_v2.patch
File nci_pmc_fixup_minimal_v2.patch, 18.2 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 167 =item C<METHOD get_multisig()> … … 147 175 METHOD get_multisig() { 148 176 PMC *sig; 149 177 GET_ATTR_multi_sig(INTERP, SELF, sig); 150 if ( PMC_IS_NULL(sig))178 if (sig == NULL) { 151 179 sig = PMCNULL; 180 } 152 181 RETURN(PMC *sig); 153 182 } 154 183 … … 178 207 179 208 VTABLE void init() { 180 209 /* 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 */ 182 212 PObj_custom_mark_SET(SELF); 183 213 } 184 214 185 215 /* 186 216 187 =item C<void set_pointer_keyed_str(STRING *key, void *func)>217 =item C<void *get_pointer()> 188 218 189 Sets the specified function pointer and signature (C<*key>). 219 =item C<void set_pointer(void *ptr)> 190 220 221 Get/Set the pointer being wrapped. Setting through this interface sets 222 the raw flag. 223 191 224 =cut 192 225 193 226 */ 194 227 195 228 VTABLE void set_pointer(void *ptr) { 196 229 SET_ATTR_orig_func(INTERP, SELF, ptr); 197 PObj_ flag_SET(private2, SELF);230 PObj_get_FLAGS(SELF) |= NCI_raw_FLAG; 198 231 } 199 232 200 233 VTABLE void *get_pointer() { 201 234 return PARROT_NCI(SELF)->orig_func; 202 235 } 203 236 237 /* 238 239 =item C<void set_pointer_keyed_str(STRING *key, void *func)> 240 241 Roughly equivalent to C<set_string(key)> and C<set_pointer(func)>. 242 Setting through this interface clears the raw flag. 243 244 =cut 245 246 */ 247 204 248 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 } 206 253 207 /* Store the original function and signature. */ 208 SET_ATTR_orig_func(INTERP, SELF, func); 254 /* 209 255 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 260 Get/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); 217 273 } 274 SET_ATTR_nci_signature(INTERP, SELF, str); 218 275 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); 220 281 } 221 282 222 283 /* … … 232 293 if (PARROT_NCI(SELF)) { 233 294 Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 234 295 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); 237 299 Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature); 238 300 Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig); 239 301 } … … 262 324 * ManagedStruct or Buffer? 263 325 */ 264 326 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; 268 333 nci_info_ret->arity = nci_info_self->arity; 269 nci_info_ret->jitted = nci_info_self->jitted;270 334 PObj_get_FLAGS(ret) |= (PObj_get_FLAGS(SELF) & 0x7); 271 335 272 336 return ret; … … 306 370 PMC *cont; 307 371 308 372 GET_ATTR_orig_func(INTERP, SELF, orig_func); 309 func = PObj_ flag_TEST(private2, SELF)373 func = PObj_get_FLAGS(SELF) & NCI_raw_FLAG 310 374 ? (nci_sub_t) D2FPTR(orig_func) 311 375 : (nci_sub_t) D2FPTR(nci_info->func); 312 376 … … 320 384 "attempt to call NULL function"); 321 385 } 322 386 323 if (nci_info->jitted) { 324 nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); 387 func(INTERP, SELF); 325 388 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 389 cont = INTERP->current_cont; 341 390 342 391 /* … … 397 446 398 447 */ 399 448 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 } 402 453 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 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(