Skip to content

Commit 33c90ae

Browse files
committed
ZJIT: Inline guard type checks for some built-in types
This implements similar fast-path guard type checks as YJIT.
1 parent bd2d684 commit 33c90ae

1 file changed

Lines changed: 20 additions & 2 deletions

File tree

zjit/src/codegen.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
1111
use crate::backend::lir::{self, asm_comment, asm_ccall, Assembler, Opnd, SideExitContext, Target, CFP, C_ARG_OPNDS, C_RET_OPND, EC, NATIVE_STACK_PTR, SP};
1212
use crate::hir::{iseq_to_hir, Block, BlockId, BranchEdge, CallInfo, Invariant, RangeType, SideExitReason, SideExitReason::*, SpecialObjectType, SELF_PARAM_IDX};
1313
use crate::hir::{Const, FrameState, Function, Insn, InsnId};
14-
use crate::hir_type::{types::Fixnum, Type};
14+
use crate::hir_type::{types::{Fixnum, Flonum, StaticSymbol, NilClass, TrueClass, FalseClass}, Type};
1515
use crate::options::get_option;
1616

1717
/// Ephemeral code generation state
@@ -1047,9 +1047,27 @@ fn gen_test(asm: &mut Assembler, val: lir::Opnd) -> Option<lir::Opnd> {
10471047
/// Compile a type check with a side exit
10481048
fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard_type: Type, state: &FrameState) -> Option<lir::Opnd> {
10491049
if guard_type.is_subtype(Fixnum) {
1050-
// Check if opnd is Fixnum
10511050
asm.test(val, Opnd::UImm(RUBY_FIXNUM_FLAG as u64));
10521051
asm.jz(side_exit(jit, state, GuardType(guard_type))?);
1052+
} else if guard_type.is_subtype(Flonum) {
1053+
// Flonum: (val & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG
1054+
let masked = asm.and(val, Opnd::UImm(RUBY_FLONUM_MASK as u64));
1055+
asm.cmp(masked, Opnd::UImm(RUBY_FLONUM_FLAG as u64));
1056+
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
1057+
} else if guard_type.is_subtype(StaticSymbol) {
1058+
// Static symbols have (val & 0xff) == RUBY_SYMBOL_FLAG
1059+
// Use 8-bit comparison like YJIT does
1060+
asm.cmp(val.with_num_bits(8).unwrap(), Opnd::UImm(RUBY_SYMBOL_FLAG as u64));
1061+
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
1062+
} else if guard_type.is_subtype(NilClass) {
1063+
asm.cmp(val, Qnil.into());
1064+
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
1065+
} else if guard_type.is_subtype(TrueClass) {
1066+
asm.cmp(val, Qtrue.into());
1067+
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
1068+
} else if guard_type.is_subtype(FalseClass) {
1069+
asm.test(val, val);
1070+
asm.jne(side_exit(jit, state, GuardType(guard_type))?);
10531071
} else if let Some(expected_class) = guard_type.runtime_exact_ruby_class() {
10541072
asm_comment!(asm, "guard exact class");
10551073

0 commit comments

Comments
 (0)