[Bug #21103] Fix local variable index calculation with forwarding
Forwarding argument is optimized not to packed when no other arguments and an internal object refers values before it. This size is decided at called time, calculate the local variable index from the fixed end point.
This commit is contained in:
parent
71f402c5d5
commit
db02a6b3ab
Notes:
git
2025-02-01 14:15:25 +00:00
8
proc.c
8
proc.c
@ -414,11 +414,11 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
|
||||
}
|
||||
|
||||
const rb_iseq_t *iseq = env->iseq;
|
||||
unsigned int i;
|
||||
|
||||
VM_ASSERT(rb_obj_is_iseq((VALUE)iseq));
|
||||
|
||||
for (i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) {
|
||||
const unsigned int local_table_size = ISEQ_BODY(iseq)->local_table_size;
|
||||
for (unsigned int i=0; i<local_table_size; i++) {
|
||||
if (ISEQ_BODY(iseq)->local_table[i] == lid) {
|
||||
if (ISEQ_BODY(iseq)->local_iseq == iseq &&
|
||||
ISEQ_BODY(iseq)->param.flags.has_block &&
|
||||
@ -431,7 +431,9 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
|
||||
}
|
||||
|
||||
*envp = env;
|
||||
return &env->env[i];
|
||||
unsigned int last_lvar = env->env_size+VM_ENV_INDEX_LAST_LVAR
|
||||
- 1 /* errinfo */;
|
||||
return &env->env[last_lvar - (local_table_size - i)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1439,6 +1439,46 @@ class TestMethod < Test::Unit::TestCase
|
||||
def foo
|
||||
a = b = c = a = b = c = 12345
|
||||
end
|
||||
|
||||
def binding_noarg
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_one_arg(x)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_optargs(x, y=42)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_anyargs(*x)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_keywords(x: 42)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_anykeywords(**x)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_forwarding(...)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
|
||||
def binding_forwarding1(x, ...)
|
||||
a = a = 12345
|
||||
binding
|
||||
end
|
||||
end
|
||||
|
||||
def test_to_proc_binding
|
||||
@ -1457,6 +1497,66 @@ class TestMethod < Test::Unit::TestCase
|
||||
assert_equal([:bar, :foo], b.local_variables.sort, bug11012)
|
||||
end
|
||||
|
||||
def test_method_binding
|
||||
c = C.new
|
||||
|
||||
b = c.binding_noarg
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
|
||||
b = c.binding_one_arg(0)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(0, b.local_variable_get(:x))
|
||||
|
||||
b = c.binding_anyargs()
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal([], b.local_variable_get(:x))
|
||||
b = c.binding_anyargs(0)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal([0], b.local_variable_get(:x))
|
||||
b = c.binding_anyargs(0, 1)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal([0, 1], b.local_variable_get(:x))
|
||||
|
||||
b = c.binding_optargs(0)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(0, b.local_variable_get(:x))
|
||||
assert_equal(42, b.local_variable_get(:y))
|
||||
b = c.binding_optargs(0, 1)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(0, b.local_variable_get(:x))
|
||||
assert_equal(1, b.local_variable_get(:y))
|
||||
|
||||
b = c.binding_keywords()
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(42, b.local_variable_get(:x))
|
||||
b = c.binding_keywords(x: 102)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(102, b.local_variable_get(:x))
|
||||
|
||||
b = c.binding_anykeywords()
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal({}, b.local_variable_get(:x))
|
||||
b = c.binding_anykeywords(foo: 999)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal({foo: 999}, b.local_variable_get(:x))
|
||||
|
||||
b = c.binding_forwarding()
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
b = c.binding_forwarding(0)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
b = c.binding_forwarding(0, 1)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
b = c.binding_forwarding(foo: 42)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
|
||||
b = c.binding_forwarding1(987)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(987, b.local_variable_get(:x))
|
||||
b = c.binding_forwarding1(987, 654)
|
||||
assert_equal(12345, b.local_variable_get(:a))
|
||||
assert_equal(987, b.local_variable_get(:x))
|
||||
end
|
||||
|
||||
MethodInMethodClass_Setup = -> do
|
||||
remove_const :MethodInMethodClass if defined? MethodInMethodClass
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user