diff options
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 110 |
1 files changed, 69 insertions, 41 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 6bbb4bca9b..8a876851b9 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1856,6 +1856,7 @@ check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)()) static inline int vm_method_cfunc_is(const rb_iseq_t *iseq, CALL_DATA cd, VALUE recv, VALUE (*func)()) { + VM_ASSERT(iseq != NULL); const struct rb_callcache *cc = vm_search_method((VALUE)iseq, cd, recv); return check_cfunc(vm_cc_cme(cc), func); } @@ -1892,7 +1893,7 @@ FLONUM_2_P(VALUE a, VALUE b) } static VALUE -opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) +opt_equality_specialized(VALUE recv, VALUE obj) { if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) { goto compare_by_identity; @@ -1904,7 +1905,7 @@ opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) goto compare_by_identity; } else if (SPECIAL_CONST_P(recv)) { - goto compare_by_funcall; + // } else if (RBASIC_CLASS(recv) == rb_cFloat && RB_FLOAT_TYPE_P(obj) && EQ_UNREDEFINED_P(FLOAT)) { double a = RFLOAT_VALUE(recv); @@ -1934,11 +1935,7 @@ opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) return rb_str_eql_internal(obj, recv); } } - - compare_by_funcall: - if (! vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) { - return Qundef; - } + return Qundef; compare_by_identity: if (recv == obj) { @@ -1949,47 +1946,77 @@ opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) } } +static VALUE +opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) +{ + VM_ASSERT(cd_owner != NULL); + + VALUE val = opt_equality_specialized(recv, obj); + if (val != Qundef) return val; + + if (!vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) { + return Qundef; + } + else { + if (recv == obj) { + return Qtrue; + } + else { + return Qfalse; + } + } +} + #undef EQ_UNREDEFINED_P #ifndef MJIT_HEADER -VALUE -rb_equal_opt(VALUE obj1, VALUE obj2) + +static inline const struct rb_callcache *gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc); // vm_eval.c +NOINLINE(static VALUE opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid)); + +static VALUE +opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid) { - STATIC_ASSERT(idEq_is_embeddable, VM_CI_EMBEDDABLE_P(idEq, 0, 1, 0)); + const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, 1); -#if USE_EMBED_CI - static struct rb_call_data cd = { - .ci = vm_ci_new_id(idEq, 0, 1, 0), - }; -#else - struct rb_call_data cd = { - .ci = &VM_CI_ON_STACK(idEq, 0, 1, 0), - }; -#endif + if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) { + if (recv == obj) { + return Qtrue; + } + else { + return Qfalse; + } + } + else { + return Qundef; + } +} - cd.cc = &vm_empty_cc; - return opt_equality(NULL, obj1, obj2, &cd); +static VALUE +opt_equality_by_mid(VALUE recv, VALUE obj, ID mid) +{ + VALUE val = opt_equality_specialized(recv, obj); + if (val != Qundef) { + return val; + } + else { + return opt_equality_by_mid_slowpath(recv, obj, mid); + } } VALUE -rb_eql_opt(VALUE obj1, VALUE obj2) +rb_equal_opt(VALUE obj1, VALUE obj2) { - STATIC_ASSERT(idEqlP_is_embeddable, VM_CI_EMBEDDABLE_P(idEqlP, 0, 1, 0)); - -#if USE_EMBED_CI - static struct rb_call_data cd = { - .ci = vm_ci_new_id(idEqlP, 0, 1, 0), - }; -#else - struct rb_call_data cd = { - .ci = &VM_CI_ON_STACK(idEqlP, 0, 1, 0), - }; -#endif + return opt_equality_by_mid(obj1, obj2, idEq); +} - cd.cc = &vm_empty_cc; - return opt_equality(NULL, obj1, obj2, &cd); +VALUE +rb_eql_opt(VALUE obj1, VALUE obj2) +{ + return opt_equality_by_mid(obj1, obj2, idEqlP); } -#endif + +#endif // MJIT_HEADER extern VALUE rb_vm_call0(rb_execution_context_t *ec, VALUE, ID, int, const VALUE*, const rb_callable_method_entry_t *, int kw_splat); @@ -2362,6 +2389,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, { const struct rb_callinfo *ci = calling->ci; const struct rb_callcache *cc = calling->cc; + bool cacheable_ci = vm_ci_markable(ci); if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) { if (LIKELY(rb_simple_iseq_p(iseq))) { @@ -2375,7 +2403,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, VM_ASSERT(ci == calling->ci); VM_ASSERT(cc == calling->cc); - CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), vm_call_iseq_optimizable_p(ci, cc)); + CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), cacheable_ci && vm_call_iseq_optimizable_p(ci, cc)); return 0; } else if (rb_iseq_only_optparam_p(iseq)) { @@ -2395,12 +2423,12 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) { CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start, !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && - METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); } else { CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start, !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && - METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); } /* initialize opt vars for self-references */ @@ -2428,7 +2456,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, args_setup_kw_parameters(ec, iseq, ci_kws, ci_kw_len, ci_keywords, klocals); CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_kwarg, - METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); return 0; } @@ -2441,7 +2469,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, if (klocals[kw_param->num] == INT2FIX(0)) { /* copy from default_values */ CC_SET_FASTPATH(cc, vm_call_iseq_setup_kwparm_nokwarg, - METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); + cacheable_ci && METHOD_ENTRY_CACHEABLE(vm_cc_cme(cc))); } return 0; |