summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c5
-rw-r--r--insns.def6
-rw-r--r--iseq.c1
-rw-r--r--vm_core.h2
-rw-r--r--vm_insnhelper.c3
5 files changed, 9 insertions, 8 deletions
diff --git a/compile.c b/compile.c
index 5a458200ec..52d74da741 100644
--- a/compile.c
+++ b/compile.c
@@ -6624,11 +6624,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
}
}
- /* dummy receiver */
- ADD_INSN1(ret, line, putobject, type == NODE_ZSUPER ? Qfalse : Qtrue);
+ ADD_INSN(ret, line, putself);
ADD_SEQ(ret, args);
ADD_INSN3(ret, line, invokesuper,
- new_callinfo(iseq, 0, argc, flag | VM_CALL_SUPER | VM_CALL_FCALL, keywords, parent_block != NULL),
+ new_callinfo(iseq, 0, argc, flag | VM_CALL_SUPER | (type == NODE_ZSUPER ? VM_CALL_ZSUPER : 0) | VM_CALL_FCALL, keywords, parent_block != NULL),
Qnil, /* CALL_CACHE */
parent_block);
diff --git a/insns.def b/insns.def
index 75f522cd9b..1903da2068 100644
--- a/insns.def
+++ b/insns.def
@@ -716,7 +716,8 @@ send
struct rb_calling_info calling;
vm_caller_setup_arg_block(ec, reg_cfp, &calling, ci, blockiseq, FALSE);
- vm_search_method(ci, cc, calling.recv = TOPN(calling.argc = ci->orig_argc));
+ calling.recv = TOPN(calling.argc = ci->orig_argc);
+ vm_search_method(ci, cc, calling.recv);
CALL_METHOD(&calling, ci, cc);
}
@@ -783,10 +784,9 @@ invokesuper
// attr rb_snum_t sp_inc = - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));
{
struct rb_calling_info calling;
- calling.argc = ci->orig_argc;
vm_caller_setup_arg_block(ec, reg_cfp, &calling, ci, blockiseq, TRUE);
- calling.recv = GET_SELF();
+ calling.recv = TOPN(calling.argc = ci->orig_argc);
vm_search_super_method(ec, GET_CFP(), &calling, ci, cc);
CALL_METHOD(&calling, ci, cc);
}
diff --git a/iseq.c b/iseq.c
index 7744e3f54f..bb53518168 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1775,6 +1775,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
CALL_FLAG(BLOCKISEQ);
CALL_FLAG(TAILCALL);
CALL_FLAG(SUPER);
+ CALL_FLAG(ZSUPER);
CALL_FLAG(KWARG);
CALL_FLAG(KW_SPLAT);
CALL_FLAG(OPT_SEND); /* maybe not reachable */
diff --git a/vm_core.h b/vm_core.h
index 01bb74ccde..88b3ccbdcb 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -1018,6 +1018,7 @@ enum vm_call_flag_bits {
VM_CALL_KW_SPLAT_bit, /* m(**opts) */
VM_CALL_TAILCALL_bit, /* located at tail position */
VM_CALL_SUPER_bit, /* super */
+ VM_CALL_ZSUPER_bit, /* zsuper */
VM_CALL_OPT_SEND_bit, /* internal flag */
VM_CALL__END
};
@@ -1032,6 +1033,7 @@ enum vm_call_flag_bits {
#define VM_CALL_KW_SPLAT (0x01 << VM_CALL_KW_SPLAT_bit)
#define VM_CALL_TAILCALL (0x01 << VM_CALL_TAILCALL_bit)
#define VM_CALL_SUPER (0x01 << VM_CALL_SUPER_bit)
+#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit)
#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit)
enum vm_special_object_type {
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index b8a5112de7..fd892678a6 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2473,7 +2473,6 @@ vm_search_super_method(const rb_execution_context_t *ec, rb_control_frame_t *reg
struct rb_calling_info *calling, struct rb_call_info *ci, struct rb_call_cache *cc)
{
VALUE current_defined_class, klass;
- VALUE sigval = TOPN(calling->argc);
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
if (!me) {
@@ -2499,7 +2498,7 @@ vm_search_super_method(const rb_execution_context_t *ec, rb_control_frame_t *reg
rb_obj_class(calling->recv), m);
}
- if (me->def->type == VM_METHOD_TYPE_BMETHOD && !sigval) {
+ if (me->def->type == VM_METHOD_TYPE_BMETHOD && (ci->flag & VM_CALL_ZSUPER)) {
rb_raise(rb_eRuntimeError,
"implicit argument passing of super from method defined"
" by define_method() is not supported."