зеркало из 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) */
|
/*! IFUNC (Internal FUNCtion) */
|
||||||
struct vm_ifunc {
|
struct vm_ifunc {
|
||||||
VALUE flags;
|
VALUE flags;
|
||||||
VALUE reserved;
|
struct rb_control_frame_struct *owner_cfp;
|
||||||
rb_block_call_func_t func;
|
rb_block_call_func_t func;
|
||||||
const void *data;
|
const void *data;
|
||||||
struct vm_ifunc_argc argc;
|
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.min = min_argc;
|
||||||
arity.argc.max = max_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;
|
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 */
|
/* special variable */
|
||||||
|
|
||||||
static rb_control_frame_t *
|
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) {
|
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)) {
|
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cfp;
|
return cfp;
|
||||||
|
@ -1635,14 +1648,14 @@ vm_normal_frame(const rb_execution_context_t *ec, rb_control_frame_t *cfp)
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_cfp_svar_get(const rb_execution_context_t *ec, rb_control_frame_t *cfp, VALUE key)
|
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);
|
return lep_svar_get(ec, cfp ? VM_CF_LEP(cfp) : 0, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vm_cfp_svar_set(const rb_execution_context_t *ec, rb_control_frame_t *cfp, VALUE key, const VALUE val)
|
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);
|
lep_svar_set(ec, cfp ? VM_CF_LEP(cfp) : 0, key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -570,7 +570,7 @@ pub struct vm_ifunc_argc {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct vm_ifunc {
|
pub struct vm_ifunc {
|
||||||
pub flags: VALUE,
|
pub flags: VALUE,
|
||||||
pub reserved: VALUE,
|
pub owner_cfp: *mut rb_control_frame_struct,
|
||||||
pub func: rb_block_call_func_t,
|
pub func: rb_block_call_func_t,
|
||||||
pub data: *const ::std::os::raw::c_void,
|
pub data: *const ::std::os::raw::c_void,
|
||||||
pub argc: vm_ifunc_argc,
|
pub argc: vm_ifunc_argc,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче