YJIT: Fix object movement bug in iseq guard for invokeblock

Since the compile-time iseq used in the guard was not marked and updated
during compaction, a runtime value reusing the address could falsely pass
the guard.

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
This commit is contained in:
Alan Wu 2023-09-15 19:03:48 -04:00 коммит произвёл GitHub
Родитель 1be64e34d0
Коммит 7cec7d14c3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 13 добавлений и 1 удалений

Просмотреть файл

@ -1,3 +1,15 @@
# regression test for invokeblock iseq guard
assert_equal 'ok', %q{
return :ok unless defined?(GC.compact)
def foo = yield
10.times do |i|
ret = eval("foo { #{i} }")
raise "failed at #{i}" unless ret == i
GC.compact
end
:ok
} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # Not yet working on RJIT
# regression test for overly generous guard elision
assert_equal '[0, :sum, 0, :sum]', %q{
# In faulty versions, the following happens:

Просмотреть файл

@ -7494,7 +7494,7 @@ fn gen_invokeblock_specialized(
asm_comment!(asm, "guard known ISEQ");
let captured_opnd = asm.and(block_handler_opnd, Opnd::Imm(!0x3));
let iseq_opnd = asm.load(Opnd::mem(64, captured_opnd, SIZEOF_VALUE_I32 * 2));
asm.cmp(iseq_opnd, (comptime_iseq as usize).into());
asm.cmp(iseq_opnd, VALUE::from(comptime_iseq).into());
jit_chain_guard(
JCC_JNE,
jit,