mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
merge revision(s) db02a6b3ab
: [Backport #21103]
[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
feb4a688a2
commit
e5403bd137
3 changed files with 106 additions and 4 deletions
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
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||
#define RUBY_VERSION_TEENY 1
|
||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||
#define RUBY_PATCHLEVEL 22
|
||||
#define RUBY_PATCHLEVEL 23
|
||||
|
||||
#include "ruby/version.h"
|
||||
#include "ruby/internal/abi.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue