ZJIT: Optimize class guards by directly reading klass field (#14136)

Replace `rb_yarv_class_of` call with:
- a constant check for special constants (nil, fixnums, symbols, etc)
- a check for false
- direct memory read at offset 8 for regular heap objects for the class check
This commit is contained in:
Stan Lo 2025-08-07 23:38:02 +01:00 committed by GitHub
parent 96c9e1e93a
commit d25eb1eb5c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 43 additions and 7 deletions

View file

@ -1069,17 +1069,29 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard
asm.cmp(val, Qtrue.into());
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
} else if guard_type.is_subtype(types::FalseClass) {
assert!(Qfalse.as_i64() == 0);
asm.test(val, val);
asm.cmp(val, Qfalse.into());
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
} else if guard_type.is_immediate() {
// All immediate types' guard should have been handled above
panic!("unexpected immediate guard type: {guard_type}");
} else if let Some(expected_class) = guard_type.runtime_exact_ruby_class() {
asm_comment!(asm, "guard exact class");
asm_comment!(asm, "guard exact class for non-immediate types");
// Get the class of the value
let klass = asm.ccall(rb_yarv_class_of as *const u8, vec![val]);
let side_exit = side_exit(jit, state, GuardType(guard_type))?;
// Check if it's a special constant
asm.test(val, (RUBY_IMMEDIATE_MASK as u64).into());
asm.jnz(side_exit.clone());
// Check if it's false
asm.cmp(val, Qfalse.into());
asm.je(side_exit.clone());
// Load the class from the object's klass field
let klass = asm.load(Opnd::mem(64, val, RUBY_OFFSET_RBASIC_KLASS));
asm.cmp(klass, Opnd::Value(expected_class));
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
asm.jne(side_exit);
} else {
unimplemented!("unsupported type: {guard_type}");
}

View file

@ -497,7 +497,7 @@ impl Type {
}
}
fn is_immediate(&self) -> bool {
pub fn is_immediate(&self) -> bool {
self.is_subtype(types::Immediate)
}