summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c110
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;