YJIT: Avoid register allocation conflict with a higher stack_idx (#9143)

YJIT: Avoid register allocation conflict

with a higher stack_idx
This commit is contained in:
Takashi Kokubun 2023-12-06 12:19:43 -08:00 коммит произвёл GitHub
Родитель 9336bbb0b2
Коммит a439fc2f17
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 34 добавлений и 5 удалений

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

@ -4273,3 +4273,21 @@ assert_normal_exit %q{
Foo.class_eval "def initialize() #{ivars} end"
Foo.new
}
assert_equal '0', %q{
def spill
1.to_i # not inlined
end
def inline(_stack1, _stack2, _stack3, _stack4, _stack5)
0 # inlined
end
def entry
# RegTemps is 00111110 prior to the #inline call.
# Its return value goes to stack_idx=0, which conflicts with stack_idx=5.
inline(spill, 2, 3, 4, 5)
end
entry
}

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

@ -428,12 +428,12 @@ impl RegTemps {
/// Return true if there's a register that conflicts with a given stack_idx.
pub fn conflicts_with(&self, stack_idx: u8) -> bool {
let mut other_idx = stack_idx as isize - get_option!(num_temp_regs) as isize;
while other_idx >= 0 {
if self.get(other_idx as u8) {
let mut other_idx = stack_idx as usize % get_option!(num_temp_regs);
while other_idx < MAX_REG_TEMPS as usize {
if stack_idx as usize != other_idx && self.get(other_idx as u8) {
return true;
}
other_idx -= get_option!(num_temp_regs) as isize;
other_idx += get_option!(num_temp_regs);
}
false
}
@ -3450,7 +3450,7 @@ mod tests {
assert_eq!(reg_temps.get(stack_idx), false);
}
// Set 0, 2, 7
// Set 0, 2, 7 (RegTemps: 10100001)
reg_temps.set(0, true);
reg_temps.set(2, true);
reg_temps.set(3, true);
@ -3466,6 +3466,17 @@ mod tests {
assert_eq!(reg_temps.get(5), false);
assert_eq!(reg_temps.get(6), false);
assert_eq!(reg_temps.get(7), true);
// Test conflicts
assert_eq!(5, get_option!(num_temp_regs));
assert_eq!(reg_temps.conflicts_with(0), false); // already set, but no conflict
assert_eq!(reg_temps.conflicts_with(1), false);
assert_eq!(reg_temps.conflicts_with(2), true); // already set, and conflicts with 7
assert_eq!(reg_temps.conflicts_with(3), false);
assert_eq!(reg_temps.conflicts_with(4), false);
assert_eq!(reg_temps.conflicts_with(5), true); // not set, and will conflict with 0
assert_eq!(reg_temps.conflicts_with(6), false);
assert_eq!(reg_temps.conflicts_with(7), true); // already set, and conflicts with 2
}
#[test]