summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/imemo.h2
-rw-r--r--proc.c2
-rw-r--r--vm.c23
-rw-r--r--yjit/src/cruby_bindings.inc.rs2
4 files changed, 21 insertions, 8 deletions
diff --git a/internal/imemo.h b/internal/imemo.h
index ef07333a58..8d506dda7d 100644
--- a/internal/imemo.h
+++ b/internal/imemo.h
@@ -82,7 +82,7 @@ struct vm_ifunc_argc {
/*! IFUNC (Internal FUNCtion) */
struct vm_ifunc {
VALUE flags;
- VALUE reserved;
+ struct rb_control_frame_struct *owner_cfp;
rb_block_call_func_t func;
const void *data;
struct vm_ifunc_argc argc;
diff --git a/proc.c b/proc.c
index c31017128e..b4f602a4cb 100644
--- a/proc.c
+++ b/proc.c
@@ -752,7 +752,7 @@ rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int m
}
arity.argc.min = min_argc;
arity.argc.max = max_argc;
- VALUE ret = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)data, arity.packed, 0);
+ VALUE ret = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)data, arity.packed, (VALUE)GET_EC()->cfp);
return (struct vm_ifunc *)ret;
}
diff --git a/vm.c b/vm.c
index d009a5f64a..bca0992155 100644
--- a/vm.c
+++ b/vm.c
@@ -1621,12 +1621,25 @@ rb_vm_invoke_proc_with_self(rb_execution_context_t *ec, rb_proc_t *proc, VALUE s
/* special variable */
static rb_control_frame_t *
-vm_normal_frame(const rb_execution_context_t *ec, rb_control_frame_t *cfp)
+vm_svar_frame(const rb_execution_context_t *ec, rb_control_frame_t *cfp)
{
while (cfp->pc == 0) {
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC) {
+ struct vm_ifunc *ifunc = (struct vm_ifunc *)cfp->iseq;
+ rb_control_frame_t *owner_cfp = ifunc->owner_cfp;
+ if (cfp < owner_cfp) {
+ cfp = ifunc->owner_cfp;
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ }
+
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
- return 0;
+ return NULL;
}
}
return cfp;
@@ -1635,14 +1648,14 @@ vm_normal_frame(const rb_execution_context_t *ec, rb_control_frame_t *cfp)
static VALUE
vm_cfp_svar_get(const rb_execution_context_t *ec, rb_control_frame_t *cfp, VALUE key)
{
- cfp = vm_normal_frame(ec, cfp);
+ cfp = vm_svar_frame(ec, cfp);
return lep_svar_get(ec, cfp ? VM_CF_LEP(cfp) : 0, key);
}
static void
vm_cfp_svar_set(const rb_execution_context_t *ec, rb_control_frame_t *cfp, VALUE key, const VALUE val)
{
- cfp = vm_normal_frame(ec, cfp);
+ cfp = vm_svar_frame(ec, cfp);
lep_svar_set(ec, cfp ? VM_CF_LEP(cfp) : 0, key, val);
}
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index ea57ea67fd..128b249e3b 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -570,7 +570,7 @@ pub struct vm_ifunc_argc {
#[repr(C)]
pub struct vm_ifunc {
pub flags: VALUE,
- pub reserved: VALUE,
+ pub owner_cfp: *mut rb_control_frame_struct,
pub func: rb_block_call_func_t,
pub data: *const ::std::os::raw::c_void,
pub argc: vm_ifunc_argc,