summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mjit_compile.c17
-rw-r--r--tool/ruby_vm/views/_mjit_compile_send.erb4
2 files changed, 20 insertions, 1 deletions
diff --git a/mjit_compile.c b/mjit_compile.c
index fe75b45141..589ac50c85 100644
--- a/mjit_compile.c
+++ b/mjit_compile.c
@@ -114,6 +114,23 @@ fastpath_applied_iseq_p(const CALL_INFO ci, const CALL_CACHE cc, const rb_iseq_t
&& vm_call_iseq_optimizable_p(ci, cc); // CC_SET_FASTPATH condition
}
+// Return true if an object of the klass may be a special const. See: rb_class_of
+static bool
+maybe_special_const_class_p(const VALUE klass)
+{
+ if (klass == rb_cFalseClass
+ || klass == rb_cNilClass
+ || klass == rb_cTrueClass
+ || klass == rb_cInteger
+ || klass == rb_cSymbol
+ || klass == rb_cFloat) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static int
compile_case_dispatch_each(VALUE key, VALUE value, VALUE arg)
{
diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb
index d1f4692b5f..8c1c1c094d 100644
--- a/tool/ruby_vm/views/_mjit_compile_send.erb
+++ b/tool/ruby_vm/views/_mjit_compile_send.erb
@@ -34,9 +34,11 @@
fprintf(f, "{\n");
% # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
+ bool opt_class_of = !maybe_special_const_class_p(captured_cc->klass); // If true, use RBASIC_CLASS instead of CLASS_OF to reduce code size
fprintf(f, " const struct rb_callcache *cc = (const struct rb_callcache *)0x%"PRIxVALUE";\n", (VALUE)captured_cc);
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 + sp_inc - 1);
+ fprintf(f, " const VALUE recv = stack[%d];\n", b->stack_size + sp_inc - 1);
+ fprintf(f, " if (UNLIKELY(%s || !vm_cc_valid_p(cc, cc_cme, %s(recv)))) {\n", opt_class_of ? "RB_SPECIAL_CONST_P(recv)" : "false", opt_class_of ? "RBASIC_CLASS" : "CLASS_OF");
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");