summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-04-10 16:35:48 -0700
committerGitHub <noreply@github.com>2023-04-10 16:35:48 -0700
commit1ff14a855ab2389017a0de958702644233dbeb9f (patch)
tree223bf4002a63e16d7a3843c973b7cbf985170d30
parent4af9bd52cbb8cff7d149a8565012ab1153a4b5b1 (diff)
YJIT: Avoid using a register for unspecified_bits (#7685)
Fix [Bug #19586]
Notes
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
-rw-r--r--bootstraptest/test_yjit.rb19
-rw-r--r--yjit/src/codegen.rs1
2 files changed, 20 insertions, 0 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index c2916908b2..34cb87ed88 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -3822,3 +3822,22 @@ assert_equal '[true, true, true, true]', %q{
assert_equal '0', %q{
3[0, 0]
}
+
+# unspecified_bits + checkkeyword
+assert_equal '2', %q{
+ def callee = 1
+
+ # checkkeyword should see unspecified_bits=0 (use bar), not Integer 1 (set bar = foo).
+ def foo(foo, bar: foo) = bar
+
+ def entry(&block)
+ # write 1 at stack[3]. Calling #callee spills stack[3].
+ 1 + (1 + (1 + (1 + callee)))
+ # &block is written to a register instead of stack[3]. When &block is popped and
+ # unspecified_bits is pushed, it must be written to stack[3], not to a register.
+ foo(1, bar: 2, &block)
+ end
+
+ entry # call branch_stub_hit (spill temps)
+ entry # doesn't call branch_stub_hit (not spill temps)
+}
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index e54b2e2752..e5e6cca563 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -6172,6 +6172,7 @@ fn gen_send_iseq(
// pushed onto the stack that represents the parameters that weren't
// explicitly given a value and have a non-constant default.
let unspec_opnd = VALUE::fixnum_from_usize(unspecified_bits).as_u64();
+ asm.spill_temps(ctx); // avoid using a register for unspecified_bits
asm.mov(ctx.stack_opnd(-1), unspec_opnd.into());
}