summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c47
1 files changed, 43 insertions, 4 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index e186376b24..e08ba34082 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -3029,6 +3029,12 @@ vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_c
return vm_setivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, val, NULL, NULL, cc, 1);
}
+bool
+rb_vm_call_ivar_attrset_p(const vm_call_handler ch)
+{
+ return (ch == vm_call_ivar || ch == vm_call_attrset);
+}
+
static inline VALUE
vm_call_bmethod_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
{
@@ -3484,16 +3490,40 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
rb_check_arity(calling->argc, 1, 1);
vm_cc_attr_index_set(cc, 0);
- CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG)));
- return vm_call_attrset(ec, cfp, calling);
+ if (UNLIKELY(ruby_vm_event_flags & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN))) {
+ const struct rb_callinfo *ci = calling->ci;
+ VALUE v;
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id,
+ vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef);
+ v = vm_call_attrset(ec, cfp, calling);
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id,
+ vm_ci_mid(ci), vm_cc_cme(cc)->owner, v);
+ return v;
+ }
+ else {
+ CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG)));
+ return vm_call_attrset(ec, cfp, calling);
+ }
case VM_METHOD_TYPE_IVAR:
CALLER_SETUP_ARG(cfp, calling, ci);
CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
rb_check_arity(calling->argc, 0, 0);
vm_cc_attr_index_set(cc, 0);
- CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT)));
- return vm_call_ivar(ec, cfp, calling);
+ if (UNLIKELY(ruby_vm_event_flags & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN))) {
+ const struct rb_callinfo *ci = calling->ci;
+ VALUE v;
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, calling->recv, vm_cc_cme(cc)->def->original_id,
+ vm_ci_mid(ci), vm_cc_cme(cc)->owner, Qundef);
+ v = vm_call_ivar(ec, cfp, calling);
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, calling->recv, vm_cc_cme(cc)->def->original_id,
+ vm_ci_mid(ci), vm_cc_cme(cc)->owner, v);
+ return v;
+ }
+ else {
+ CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT)));
+ return vm_call_ivar(ec, cfp, calling);
+ }
case VM_METHOD_TYPE_MISSING:
vm_cc_method_missing_reason_set(cc, 0);
@@ -3615,6 +3645,15 @@ vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
return vm_call_method(ec, reg_cfp, calling);
}
+void
+rb_vm_cc_general(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc != vm_cc_empty());
+
+ *(vm_call_handler *)&cc->call_ = vm_call_general;
+}
+
static VALUE
vm_call_super_method(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling)
{