зеркало из https://github.com/github/ruby.git
use correct svar (#7225)
* use correct svar Without this patch, svar location is used "nearest Ruby frame". It is almost correct but it doesn't correct when the `each` method is written in Ruby. ```ruby class C include Enumerable def each %w(bar baz).each{|e| yield e} end end C.new.grep(/(b.)/){|e| p [$1, e]} ``` This patch fix this issue by traversing ifunc's cfp. Note that if cfp doesn't specify this Thread's cfp stack, reserved svar location (`ec->root_svar`) is used. * make yjit-bindgen --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
This commit is contained in:
Родитель
2675f2c864
Коммит
0a82bfe5e1
|
@ -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;
|
||||
|
|
2
proc.c
2
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;
|
||||
}
|
||||
|
||||
|
|
23
vm.c
23
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче