diff options
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 104 |
1 files changed, 100 insertions, 4 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 4f39a0f5a3..5b90aea019 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2444,8 +2444,7 @@ vm_super_outside(void) } static void -vm_search_super_method(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, - struct rb_calling_info *calling, struct rb_call_info *ci, struct rb_call_cache *cc) +vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_info *ci, struct rb_call_cache *cc, VALUE recv) { VALUE current_defined_class, klass; const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp); @@ -2463,14 +2462,14 @@ vm_search_super_method(const rb_execution_context_t *ec, rb_control_frame_t *reg if (BUILTIN_TYPE(current_defined_class) != T_MODULE && BUILTIN_TYPE(current_defined_class) != T_ICLASS && /* bound UnboundMethod */ !FL_TEST(current_defined_class, RMODULE_INCLUDED_INTO_REFINEMENT) && - !rb_obj_is_kind_of(calling->recv, current_defined_class)) { + !rb_obj_is_kind_of(recv, current_defined_class)) { VALUE m = RB_TYPE_P(current_defined_class, T_ICLASS) ? RBASIC(current_defined_class)->klass : current_defined_class; rb_raise(rb_eTypeError, "self has wrong type to call super in this context: " "%"PRIsVALUE" (expected %"PRIsVALUE")", - rb_obj_class(calling->recv), m); + rb_obj_class(recv), m); } if (me->def->type == VM_METHOD_TYPE_BMETHOD && (ci->flag & VM_CALL_ZSUPER)) { @@ -3187,6 +3186,103 @@ vm_find_or_create_class_by_id(ID id, } } +static void +vm_search_method_wrap( + const struct rb_control_frame_struct *reg_cfp, + struct rb_call_info *ci, + struct rb_call_cache *cc, + VALUE recv) +{ + vm_search_method(ci, cc, recv); +} + +static void +vm_search_invokeblock( + const struct rb_control_frame_struct *reg_cfp, + struct rb_call_info *ci, + struct rb_call_cache *cc, + VALUE recv) +{ + /* Does nothing. */ +} + +static VALUE +vm_invokeblock_i( + struct rb_execution_context_struct *ec, + struct rb_control_frame_struct *reg_cfp, + struct rb_calling_info *calling, + const struct rb_call_info *ci, + struct rb_call_cache *cc) +{ + VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP()); + + if (block_handler == VM_BLOCK_HANDLER_NONE) { + rb_vm_localjump_error("no block given (yield)", Qnil, 0); + } + else { + return vm_invoke_block(ec, GET_CFP(), calling, ci, block_handler); + } +} + +static VALUE +vm_sendish( + struct rb_execution_context_struct *ec, + struct rb_control_frame_struct *reg_cfp, + struct rb_call_info *ci, + struct rb_call_cache *cc, + VALUE block_handler, + void (*method_explorer)( + const struct rb_control_frame_struct *reg_cfp, + struct rb_call_info *ci, + struct rb_call_cache *cc, + VALUE recv)) +{ + VALUE val; + int argc = ci->orig_argc; + VALUE recv = TOPN(argc); + struct rb_calling_info calling; + + calling.block_handler = block_handler; + calling.recv = recv; + calling.argc = argc; + + method_explorer(GET_CFP(), ci, cc, recv); + + val = cc->call(ec, GET_CFP(), &calling, ci, cc); + + if (val != Qundef) { + return val; /* CFUNC normal return */ + } + else { + RESTORE_REGS(); /* CFP pushed in cc->call() */ + } + +#ifdef MJIT_HEADER + /* When calling ISeq which may catch an exception from JIT-ed + code, we should not call mjit_exec directly to prevent the + caller frame from being canceled. That's because the caller + frame may have stack values in the local variables and the + cancelling the caller frame will purge them. But directly + calling mjit_exec is faster... */ + if (GET_ISEQ()->body->catch_except_p) { + VM_ENV_FLAGS_SET(GET_EP(), VM_FRAME_FLAG_FINISH); + return vm_exec(ec, true); + } + else if ((val = mjit_exec(ec)) == Qundef) { + VM_ENV_FLAGS_SET(GET_EP(), VM_FRAME_FLAG_FINISH); + return vm_exec(ec, false); + } + else { + return val; + } +#else + /* When calling from VM, longjmp in the callee won't purge any + JIT-ed caller frames. So it's safe to directly call + mjit_exec. */ + return mjit_exec(ec); +#endif +} + static VALUE vm_opt_str_freeze(VALUE str, int bop, ID id) { |