summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--benchmark/vm_iclass_super.yml20
-rw-r--r--vm_insnhelper.c16
2 files changed, 34 insertions, 2 deletions
diff --git a/benchmark/vm_iclass_super.yml b/benchmark/vm_iclass_super.yml
new file mode 100644
index 0000000000..21bb7db247
--- /dev/null
+++ b/benchmark/vm_iclass_super.yml
@@ -0,0 +1,20 @@
+prelude: |
+ class C
+ def m
+ 1
+ end
+
+ ("A".."M").each do |module_name|
+ eval <<-EOM
+ module #{module_name}
+ def m; super; end
+ end
+ prepend #{module_name}
+ EOM
+ end
+ end
+
+ obj = C.new
+benchmark:
+ vm_iclass_super: obj.m
+loop_count: 6000000
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index ec1b143633..30177b7a19 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -673,8 +673,19 @@ rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
}
+static rb_iseq_t *
+method_entry_iseqptr(const rb_callable_method_entry_t *me)
+{
+ switch (me->def->type) {
+ case VM_METHOD_TYPE_ISEQ:
+ return me->def->body.iseq.iseqptr;
+ default:
+ return NULL;
+ }
+}
+
static rb_cref_t *
-method_entry_cref(rb_callable_method_entry_t *me)
+method_entry_cref(const rb_callable_method_entry_t *me)
{
switch (me->def->type) {
case VM_METHOD_TYPE_ISEQ:
@@ -3263,7 +3274,7 @@ static inline VALUE
vm_search_normal_superclass(VALUE klass)
{
if (BUILTIN_TYPE(klass) == T_ICLASS &&
- FL_TEST(RBASIC(klass)->klass, RMODULE_IS_REFINEMENT)) {
+ FL_TEST_RAW(RBASIC(klass)->klass, RMODULE_IS_REFINEMENT)) {
klass = RBASIC(klass)->klass;
}
klass = RCLASS_ORIGIN(klass);
@@ -3296,6 +3307,7 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
if (BUILTIN_TYPE(current_defined_class) != T_MODULE &&
!FL_TEST(current_defined_class, RMODULE_INCLUDED_INTO_REFINEMENT) &&
+ reg_cfp->iseq != method_entry_iseqptr(me) &&
!rb_obj_is_kind_of(recv, current_defined_class)) {
VALUE m = RB_TYPE_P(current_defined_class, T_ICLASS) ?
RCLASS_INCLUDER(current_defined_class) : current_defined_class;