YJIT: Fix false object collection when setting ivar

Previously, setinstancevariable could generate code that calls
`rb_ensure_iv_list_size()` without first updating `cfp->sp`. This means
in the event that a GC start from within said routine the top few
objects would not be marked, causing them to be falsly collected.

Call `jit_prepare_routine_call()` first.

[Bug #19601]
This commit is contained in:
Alan Wu 2023-04-14 15:04:55 -04:00
Родитель 4501fb8b46
Коммит 31e67a476f
2 изменённых файлов: 25 добавлений и 0 удалений

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

@ -1,3 +1,23 @@
# Regression test for GC mishap while doing shape transition
assert_equal '[:ok]', %q{
# [Bug #19601]
class RegressionTest
def initialize
@a = @b = @fourth_ivar_does_shape_transition = nil
end
def extender
@first_extended_ivar = [:ok]
end
end
GC.stress = true
# Used to crash due to GC run in rb_ensure_iv_list_size()
# not marking the newly allocated [:ok].
RegressionTest.new.extender.itself
}
assert_equal 'true', %q{
# regression test for tracking type of locals for too long
def local_setting_cmp(five)

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

@ -2290,6 +2290,11 @@ fn gen_setinstancevariable(
if needs_extension {
// Generate the C call so that runtime code will increase
// the capacity and set the buffer.
asm.comment("call rb_ensure_iv_list_size");
// It allocates so can trigger GC, which takes the VM lock
// so could yield to a different ractor.
jit_prepare_routine_call(jit, asm);
asm.spill_temps(); // for ccall
asm.ccall(rb_ensure_iv_list_size as *const u8,
vec![