diff options
-rw-r--r-- | iseq.c | 3 | ||||
-rw-r--r-- | tool/ruby_vm/views/_mjit_compile_send.erb | 5 | ||||
-rw-r--r-- | vm_callinfo.h | 5 |
3 files changed, 8 insertions, 5 deletions
@@ -364,8 +364,9 @@ rb_iseq_mark(const rb_iseq_t *iseq) for (unsigned int i=0; i<body->ci_size; i++) { const struct rb_callcache *cc = cc_entries[i]; if (cc != NULL) { - // Pin cc against GC.compact as the the address may be written in JIT-ed code. + // Pin `cc` and `cc->cme` against GC.compact as their addresses may be written in JIT-ed code. rb_gc_mark((VALUE)cc); + rb_gc_mark((VALUE)vm_cc_cme(cc)); } } } diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb index 9642e46d10..69352924bd 100644 --- a/tool/ruby_vm/views/_mjit_compile_send.erb +++ b/tool/ruby_vm/views/_mjit_compile_send.erb @@ -39,7 +39,8 @@ % # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things. fprintf(f, " const struct rb_callcache *cc = (const struct rb_callcache *)0x%"PRIxVALUE";\n", (VALUE)captured_cc); - fprintf(f, " if (UNLIKELY(!vm_cc_valid_p(cc, CLASS_OF(stack[%d])))) {\n", b->stack_size - 1 - argc); + fprintf(f, " const rb_callable_method_entry_t *cc_cme = (const rb_callable_method_entry_t *)0x%"PRIxVALUE";\n", (VALUE)vm_cc_cme(captured_cc)); + fprintf(f, " if (UNLIKELY(!vm_cc_valid_p(cc, cc_cme, CLASS_OF(stack[%d])))) {\n", b->stack_size - 1 - argc); fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); fprintf(f, " goto send_cancel;\n"); @@ -72,7 +73,7 @@ % # JIT: Special CALL_METHOD. Bypass captured_cc->call and inline vm_call_iseq_setup_normal for vm_call_iseq_setup_func FASTPATH. fprintf(f, " {\n"); fprintf(f, " VALUE v;\n"); - fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, vm_cc_cme(cc), 0, %d, %d);\n", + fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, cc_cme, 0, %d, %d);\n", param_size, iseq->body->local_table_size); // fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE if (iseq->body->catch_except_p) { fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); diff --git a/vm_callinfo.h b/vm_callinfo.h index 0f90d109b8..30c4f703ba 100644 --- a/vm_callinfo.h +++ b/vm_callinfo.h @@ -316,11 +316,12 @@ vm_cc_markable(const struct rb_callcache *cc) return FL_TEST_RAW(cc, VM_CALLCACHE_UNMARKABLE) == 0; } +// For MJIT. cc_cme is supposed to have inlined `vm_cc_cme(cc)`. static inline bool -vm_cc_valid_p(const struct rb_callcache *cc, VALUE klass) +vm_cc_valid_p(const struct rb_callcache *cc, const rb_callable_method_entry_t *cc_cme, VALUE klass) { VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache)); - if (cc->klass == klass && !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc))) { + if (cc->klass == klass && !METHOD_ENTRY_INVALIDATED(cc_cme)) { return 1; } else { |