|
19 | 19 | // Map from YARV opcodes to code generation functions |
20 | 20 | static codegen_fn gen_fns[VM_INSTRUCTION_SIZE] = { NULL }; |
21 | 21 |
|
| 22 | +// Map from method entries to code generation functions |
| 23 | +static st_table *yjit_method_codegen_table = NULL; |
| 24 | + |
22 | 25 | // Code block into which we write machine code |
23 | 26 | static codeblock_t block; |
24 | 27 | codeblock_t* cb = NULL; |
@@ -2270,7 +2273,7 @@ jit_protected_callee_ancestry_guard(jitstate_t *jit, codeblock_t *cb, const rb_c |
2270 | 2273 | } |
2271 | 2274 |
|
2272 | 2275 | // Return true when the codegen function generates code. |
2273 | | -typedef bool (*cfunc_codegen_t)(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc); |
| 2276 | +typedef bool (*method_codegen_t)(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const rb_callable_method_entry_t *cme, rb_iseq_t *block, const int32_t argc); |
2274 | 2277 |
|
2275 | 2278 | // Codegen for rb_obj_not(). |
2276 | 2279 | // Note, caller is responsible for generating all the right guards, including |
@@ -2302,11 +2305,12 @@ jit_rb_obj_not(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const |
2302 | 2305 | } |
2303 | 2306 |
|
2304 | 2307 | // Check if we know how to codegen for a particular cfunc method |
2305 | | -static cfunc_codegen_t |
2306 | | -lookup_cfunc_codegen(const rb_method_cfunc_t *cfunc) |
| 2308 | +static method_codegen_t |
| 2309 | +lookup_cfunc_codegen(const rb_method_definition_t *def) |
2307 | 2310 | { |
2308 | | - if (cfunc->func == rb_obj_not) { |
2309 | | - return jit_rb_obj_not; |
| 2311 | + method_codegen_t gen_fn; |
| 2312 | + if (st_lookup(yjit_method_codegen_table, def->method_serial, (st_data_t *)&gen_fn)) { |
| 2313 | + return gen_fn; |
2310 | 2314 | } |
2311 | 2315 | return NULL; |
2312 | 2316 | } |
@@ -2336,8 +2340,8 @@ gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const |
2336 | 2340 |
|
2337 | 2341 | // Delegate to codegen for C methods if we have it. |
2338 | 2342 | { |
2339 | | - cfunc_codegen_t known_cfunc_codegen; |
2340 | | - if ((known_cfunc_codegen = lookup_cfunc_codegen(cfunc))) { |
| 2343 | + method_codegen_t known_cfunc_codegen; |
| 2344 | + if ((known_cfunc_codegen = lookup_cfunc_codegen(cme->def))) { |
2341 | 2345 | if (known_cfunc_codegen(jit, ctx, ci, cme, block, argc)) { |
2342 | 2346 | // cfunc codegen generated code. Terminate the block so |
2343 | 2347 | // there isn't multiple calls in the same block. |
@@ -3280,6 +3284,23 @@ gen_opt_invokebuiltin_delegate(jitstate_t *jit, ctx_t *ctx) |
3280 | 3284 | return YJIT_KEEP_COMPILING; |
3281 | 3285 | } |
3282 | 3286 |
|
| 3287 | +static void |
| 3288 | +yjit_reg_method(VALUE klass, const char *mid_str, method_codegen_t gen_fn) |
| 3289 | +{ |
| 3290 | + ID mid = rb_intern(mid_str); |
| 3291 | + const rb_method_entry_t *me = rb_method_entry_at(klass, mid); |
| 3292 | + |
| 3293 | + if (!me) { |
| 3294 | + rb_bug("undefined optimized method: %s", rb_id2name(mid)); |
| 3295 | + } |
| 3296 | + |
| 3297 | + // For now, only cfuncs are supported |
| 3298 | + VM_ASSERT(me && me->def); |
| 3299 | + VM_ASSERT(me->def->type == VM_METHOD_TYPE_CFUNC); |
| 3300 | + |
| 3301 | + st_insert(yjit_method_codegen_table, (st_data_t)me->def->method_serial, (st_data_t)gen_fn); |
| 3302 | +} |
| 3303 | + |
3283 | 3304 | static void |
3284 | 3305 | yjit_reg_op(int opcode, codegen_fn gen_fn) |
3285 | 3306 | { |
@@ -3360,4 +3381,8 @@ yjit_init_codegen(void) |
3360 | 3381 | yjit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block); |
3361 | 3382 | yjit_reg_op(BIN(send), gen_send); |
3362 | 3383 | yjit_reg_op(BIN(leave), gen_leave); |
| 3384 | + |
| 3385 | + yjit_method_codegen_table = st_init_numtable(); |
| 3386 | + |
| 3387 | + yjit_reg_method(rb_cBasicObject, "!", jit_rb_obj_not); |
3363 | 3388 | } |
0 commit comments