diff options
author | Takashi Kokubun <[email protected]> | 2025-03-05 13:47:25 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2025-04-18 21:52:59 +0900 |
commit | 22c73f1ccbe04b1e85ed5977f676f5afd31a2fcc () | |
tree | e8db568d8146a87be4854112ff2b7e13f695e412 | |
parent | bd41935b02c554589d29882d62a3a76c4afe2165 (diff) |
Implement FixnumAdd and stub Point/GuardType (https://.com/Shopify/zjit/pull/30)
* Implement FixnumAdd and stub Point/GuardType Co-authored-by: Max Bernstein <[email protected]> Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> * Clone Target for arm64 * Use $create instead of use create Co-authored-by: Alan Wu <[email protected]> * Fix misindentation from suggested changes * Drop an unneeded variable for mut * Load operand into a register only if necessary --------- Co-authored-by: Max Bernstein <[email protected]> Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Co-authored-by: Alan Wu <[email protected]>
Notes: Merged: https://.com/ruby/ruby/pull/13131
-rw-r--r-- | ./workflows/zjit-macos.yml | 4 | ||||
-rw-r--r-- | ./workflows/zjit-ubuntu.yml | 4 | ||||
-rw-r--r-- | bootstraptest/test_zjit.rb | 9 | ||||
-rw-r--r-- | vm.c | 1 | ||||
-rw-r--r-- | zjit.h | 2 | ||||
-rw-r--r-- | zjit/src/asm/x86_64/mod.rs | 6 | ||||
-rw-r--r-- | zjit/src/backend/arm64/mod.rs | 49 | ||||
-rw-r--r-- | zjit/src/backend/lir.rs | 102 | ||||
-rw-r--r-- | zjit/src/backend/x86_64/mod.rs | 22 | ||||
-rw-r--r-- | zjit/src/codegen.rs | 60 | ||||
-rw-r--r-- | zjit/src/hir.rs | 93 | ||||
-rw-r--r-- | zjit/src/invariants.rs | 14 | ||||
-rw-r--r-- | zjit/src/lib.rs | 6 | ||||
-rw-r--r-- | zjit/src/options.rs | 3 |
14 files changed, 193 insertions, 182 deletions
@@ -33,14 +33,14 @@ jobs: rust_version: 1.85.0 - test_task: 'btest' - zjit_opts: '--zjit-call-threshold=1' configure: '--enable-zjit=dev' btests: '../src/bootstraptest/test_zjit.rb' rust_version: 1.85.0 - test_task: 'check' # Test without ZJIT for now - #zjit_opts: '--zjit-call-threshold=1' configure: '--enable-zjit' rust_version: 1.85.0 @@ -39,14 +39,14 @@ jobs: rust_version: 1.85.0 - test_task: 'btest' - zjit_opts: '--zjit-call-threshold=1' configure: '--enable-zjit=dev' btests: '../src/bootstraptest/test_zjit.rb' rust_version: 1.85.0 - test_task: 'check' # Test without ZJIT for now - #zjit_opts: '--zjit-call-threshold=1' configure: '--enable-zjit' rust_version: 1.85.0 @@ -3,10 +3,15 @@ assert_equal 'nil', %q{ def test = nil - test.inspect } assert_equal '1', %q{ def test = 1 - test } @@ -2199,6 +2199,7 @@ rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass) rb_id2name(me->called_id) ); rb_yjit_bop_redefined(flag, (enum ruby_basic_operators)bop); ruby_vm_redefined_flag[bop] |= flag; } } @@ -10,10 +10,12 @@ extern uint64_t rb_zjit_call_threshold; void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception); void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec); void rb_zjit_profile_iseq(const rb_iseq_t *iseq); #else void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception) {} void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec) {} void rb_zjit_profile_iseq(const rb_iseq_t *iseq) {} #endif // #if USE_YJIT #endif // #ifndef ZJIT_H @@ -878,10 +878,7 @@ pub fn jmp_label(cb: &mut CodeBlock, label_idx: usize) { } /// Encode a relative jump to a pointer at a 32-bit offset (direct or conditional) -fn write_jcc_ptr(_cb: &mut CodeBlock, _op0: u8, _op1: u8, _dst_ptr: CodePtr) { - todo!(); - - /* // Write the opcode if op0 != 0xFF { cb.write_byte(op0); @@ -904,7 +901,6 @@ fn write_jcc_ptr(_cb: &mut CodeBlock, _op0: u8, _op1: u8, _dst_ptr: CodePtr) { //cb.dropped_bytes = true; panic!("we should refactor to avoid dropped_bytes"); } - */ } /// jcc - relative jumps to a pointer (32-bit offset) @@ -843,9 +843,9 @@ impl Assembler bcond(cb, CONDITION, InstructionOffset::from_bytes(bytes)); }); }, - //Target::SideExit { .. } => { - // unreachable!("Target::SideExit should have been compiled by compile_side_exit") - //}, }; } @@ -900,23 +900,6 @@ impl Assembler ldr_post(cb, opnd, A64Opnd::new_mem(64, C_SP_REG, C_SP_STEP)); } - /* - /// Compile a side exit if Target::SideExit is given. - fn compile_side_exit( - target: Target, - asm: &mut Assembler, - ocb: &mut Option<&mut OutlinedCb>, - ) -> Result<Target, EmitError> { - if let Target::SideExit { counter, context } = target { - let side_exit = asm.get_side_exit(&context.unwrap(), Some(counter), ocb.as_mut().unwrap()) - .ok_or(EmitError::OutOfMemory)?; - Ok(Target::SideExitPtr(side_exit)) - } else { - Ok(target) - } - } - */ - // dbg!(&self.insns); // List of GC offsets @@ -1220,40 +1203,40 @@ impl Assembler b(cb, InstructionOffset::from_bytes(bytes)); }); }, - //Target::SideExit { .. } => { - // unreachable!("Target::SideExit should have been compiled by compile_side_exit") - //}, }; }, Insn::Je(target) | Insn::Jz(target) => { - emit_conditional_jump::<{Condition::EQ}>(cb, *target); }, Insn::Jne(target) | Insn::Jnz(target) | Insn::JoMul(target) => { - emit_conditional_jump::<{Condition::NE}>(cb, *target); }, Insn::Jl(target) => { - emit_conditional_jump::<{Condition::LT}>(cb, *target); }, Insn::Jg(target) => { - emit_conditional_jump::<{Condition::GT}>(cb, *target); }, Insn::Jge(target) => { - emit_conditional_jump::<{Condition::GE}>(cb, *target); }, Insn::Jbe(target) => { - emit_conditional_jump::<{Condition::LS}>(cb, *target); }, Insn::Jb(target) => { - emit_conditional_jump::<{Condition::CC}>(cb, *target); }, Insn::Jo(target) => { - emit_conditional_jump::<{Condition::VS}>(cb, *target); }, Insn::Joz(opnd, target) => { - emit_cmp_zero_jump(cb, opnd.into(), true, *target); }, Insn::Jonz(opnd, target) => { - emit_cmp_zero_jump(cb, opnd.into(), false, *target); }, Insn::IncrCounter { mem: _, value: _ } => { /* @@ -1,6 +1,6 @@ use std::fmt; use std::mem::take; -use crate::cruby::VALUE; use crate::backend::current::*; use crate::virtualmem::CodePtr; use crate::asm::CodeBlock; @@ -290,13 +290,13 @@ impl From<VALUE> for Opnd { /// Branch target (something that we can jump to) /// for branch instructions -#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Target { /// Pointer to a piece of YJIT-generated code CodePtr(CodePtr), // Side exit with a counter - //SideExit { counter: Counter, context: Option<SideExitContext> }, /// Pointer to a side exit code SideExitPtr(CodePtr), /// A label within the generated code @@ -305,12 +305,6 @@ pub enum Target impl Target { - /* - pub fn side_exit(counter: Counter) -> Target { - Target::SideExit { counter, context: None } - } - */ - pub fn unwrap_label_idx(&self) -> usize { match self { Target::Label(idx) => *idx, @@ -966,56 +960,6 @@ impl fmt::Debug for Insn { } } -/// Set of variables used for generating side exits -/* -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct SideExitContext { - /// PC of the instruction being compiled - pub pc: *mut VALUE, - - /// Context fields used by get_generic_ctx() - pub stack_size: u8, - pub sp_offset: i8, - pub reg_mapping: RegMapping, - pub is_return_landing: bool, - pub is_deferred: bool, -} - -impl SideExitContext { - /// Convert PC and Context into SideExitContext - pub fn new(pc: *mut VALUE, ctx: Context) -> Self { - let exit_ctx = SideExitContext { - pc, - stack_size: ctx.get_stack_size(), - sp_offset: ctx.get_sp_offset(), - reg_mapping: ctx.get_reg_mapping(), - is_return_landing: ctx.is_return_landing(), - is_deferred: ctx.is_deferred(), - }; - if cfg!(debug_assertions) { - // Assert that we're not losing any mandatory metadata - assert_eq!(exit_ctx.get_ctx(), ctx.get_generic_ctx()); - } - exit_ctx - } - - /// Convert SideExitContext to Context - fn get_ctx(&self) -> Context { - let mut ctx = Context::default(); - ctx.set_stack_size(self.stack_size); - ctx.set_sp_offset(self.sp_offset); - ctx.set_reg_mapping(self.reg_mapping); - if self.is_return_landing { - ctx.set_as_return_landing(); - } - if self.is_deferred { - ctx.mark_as_deferred(); - } - ctx - } -} -*/ - /// Initial capacity for asm.insns vector const ASSEMBLER_INSNS_CAPACITY: usize = 256; @@ -1155,19 +1099,6 @@ impl Assembler } } - // Set a side exit context to Target::SideExit - /* - if let Some(Target::SideExit { context, .. }) = insn.target_mut() { - // We should skip this when this instruction is being copied from another Assembler. - if context.is_none() { - *context = Some(SideExitContext::new( - self.side_exit_pc.unwrap(), - self.ctx.with_stack_size(self.side_exit_stack_size.unwrap()), - )); - } - } - */ - self.insns.push(insn); self.live_ranges.push(insn_idx); } @@ -1635,8 +1566,10 @@ impl Assembler /// Compile the instructions down to machine code. /// Can fail due to lack of code memory and inopportune code placement, among other reasons. #[must_use] - pub fn compile(self, cb: &mut CodeBlock) -> Option<(CodePtr, Vec<u32>)> { #[cfg(feature = "disasm")] let start_addr = cb.get_write_ptr(); let alloc_regs = Self::get_alloc_regs(); @@ -1651,6 +1584,29 @@ impl Assembler ret } /* /// Compile with a limited number of registers. Used only for unit tests. #[cfg(test)] @@ -696,7 +696,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jmp_ptr(cb, code_ptr), Target::Label(label_idx) => jmp_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } } @@ -704,7 +704,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => je_ptr(cb, code_ptr), Target::Label(label_idx) => je_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } } @@ -712,7 +712,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jne_ptr(cb, code_ptr), Target::Label(label_idx) => jne_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } } @@ -720,7 +720,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jl_ptr(cb, code_ptr), Target::Label(label_idx) => jl_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } }, @@ -728,7 +728,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jg_ptr(cb, code_ptr), Target::Label(label_idx) => jg_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } }, @@ -736,7 +736,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jge_ptr(cb, code_ptr), Target::Label(label_idx) => jge_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } }, @@ -744,7 +744,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jbe_ptr(cb, code_ptr), Target::Label(label_idx) => jbe_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } }, @@ -752,7 +752,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jb_ptr(cb, code_ptr), Target::Label(label_idx) => jb_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } }, @@ -760,7 +760,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jz_ptr(cb, code_ptr), Target::Label(label_idx) => jz_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } } @@ -768,7 +768,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jnz_ptr(cb, code_ptr), Target::Label(label_idx) => jnz_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } } @@ -777,7 +777,7 @@ impl Assembler match *target { Target::CodePtr(code_ptr) | Target::SideExitPtr(code_ptr) => jo_ptr(cb, code_ptr), Target::Label(label_idx) => jo_label(cb, label_idx), - //Target::SideExit { .. } => unreachable!("Target::SideExit should have been compiled by compile_side_exit"), } } @@ -1,13 +1,6 @@ use crate::{ - asm::CodeBlock, - backend::lir::{EC, CFP, SP, C_ARG_OPNDS, Assembler, Opnd, asm_comment}, - cruby::*, - debug, - hir::{Function, InsnId, Insn, Const}, - virtualmem::CodePtr }; -#[cfg(feature = "disasm")] -use crate::get_option; /// Ephemeral code generation state struct JITState { @@ -40,15 +33,19 @@ pub fn gen_function(cb: &mut CodeBlock, function: &Function, iseq: IseqPtr) -> O if !matches!(*insn, Insn::Snapshot { .. }) { asm_comment!(asm, "Insn: {:04} {:?}", insn_idx, insn); } - match *insn { - Insn::Const { val: Const::Value(val) } => gen_const(&mut jit, insn_id, val), - Insn::Return { val } => gen_return(&jit, &mut asm, val)?, Insn::Snapshot { .. } => {}, // we don't need to do anything for this instruction at the moment _ => { debug!("ZJIT: gen_function: unexpected insn {:?}", insn); return None; } } } // Generate code if everything can be compiled @@ -105,3 +102,44 @@ fn gen_return(jit: &JITState, asm: &mut Assembler, val: InsnId) -> Option<()> { Some(()) } @@ -192,21 +192,21 @@ pub enum Insn { Return { val: InsnId }, /// Fixnum +, -, *, /, %, ==, !=, <, <=, >, >= - FixnumAdd { left: InsnId, right: InsnId }, - FixnumSub { left: InsnId, right: InsnId }, - FixnumMult { left: InsnId, right: InsnId }, - FixnumDiv { left: InsnId, right: InsnId }, - FixnumMod { left: InsnId, right: InsnId }, - FixnumEq { left: InsnId, right: InsnId }, - FixnumNeq { left: InsnId, right: InsnId }, - FixnumLt { left: InsnId, right: InsnId }, - FixnumLe { left: InsnId, right: InsnId }, - FixnumGt { left: InsnId, right: InsnId }, - FixnumGe { left: InsnId, right: InsnId }, /// Side-exist if val doesn't have the expected type. // TODO: Replace is_fixnum with the type lattice - GuardType { val: InsnId, guard_type: Type }, /// Generate no code (or padding if necessary) and insert a point /// that can be rewritten to a side exit when the Invariant is broken. @@ -422,18 +422,18 @@ impl<'a> std::fmt::Display for FunctionPrinter<'a> { } } Insn::Return { val } => { write!(f, "Return {val}")?; } - Insn::FixnumAdd { left, right } => { write!(f, "FixnumAdd {left}, {right}")?; }, - Insn::FixnumSub { left, right } => { write!(f, "FixnumSub {left}, {right}")?; }, - Insn::FixnumMult { left, right } => { write!(f, "FixnumMult {left}, {right}")?; }, - Insn::FixnumDiv { left, right } => { write!(f, "FixnumDiv {left}, {right}")?; }, - Insn::FixnumMod { left, right } => { write!(f, "FixnumMod {left}, {right}")?; }, - Insn::FixnumEq { left, right } => { write!(f, "FixnumEq {left}, {right}")?; }, - Insn::FixnumNeq { left, right } => { write!(f, "FixnumNeq {left}, {right}")?; }, - Insn::FixnumLt { left, right } => { write!(f, "FixnumLt {left}, {right}")?; }, - Insn::FixnumLe { left, right } => { write!(f, "FixnumLe {left}, {right}")?; }, - Insn::FixnumGt { left, right } => { write!(f, "FixnumGt {left}, {right}")?; }, - Insn::FixnumGe { left, right } => { write!(f, "FixnumGe {left}, {right}")?; }, - Insn::GuardType { val, guard_type } => { write!(f, "GuardType {val}, {guard_type}")?; }, Insn::Point(invariant) => { write!(f, "Point {invariant:}")?; }, insn => { write!(f, "{insn:?}")?; } } @@ -448,7 +448,7 @@ impl<'a> std::fmt::Display for FunctionPrinter<'a> { pub struct FrameState { iseq: IseqPtr, // Ruby bytecode instruction pointer - pc: VALUE, stack: Vec<InsnId>, locals: Vec<InsnId>, @@ -769,8 +769,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_plus | YARVINSN_zjit_opt_plus => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_PLUS })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumAdd { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -780,8 +781,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_minus | YARVINSN_zjit_opt_minus => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_MINUS })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumSub { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -791,8 +793,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_mult | YARVINSN_zjit_opt_mult => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_MULT })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumMult { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -802,8 +805,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_div | YARVINSN_zjit_opt_div => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_DIV })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumDiv { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -813,8 +817,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_mod | YARVINSN_zjit_opt_mod => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_MOD })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumMod { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -825,8 +830,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_eq | YARVINSN_zjit_opt_eq => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_EQ })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumEq { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -836,8 +842,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_neq | YARVINSN_zjit_opt_neq => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_NEQ })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumNeq { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -847,8 +854,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_lt | YARVINSN_zjit_opt_lt => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_LT })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumLt { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -858,8 +866,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_le | YARVINSN_zjit_opt_le => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_LE })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumLe { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -869,8 +878,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_gt | YARVINSN_zjit_opt_gt => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_GT })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumGt { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -880,8 +890,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_opt_ge | YARVINSN_zjit_opt_ge => { if payload.have_two_fixnums(current_insn_idx as usize) { fun.push_insn(block, Insn::Point(Invariant::BOPRedefined { klass: INTEGER_REDEFINED_OP_FLAG, bop: BOP_GE })); let (left, right) = guard_two_fixnums(&mut state, &mut fun, block)?; - state.push(fun.push_insn(block, Insn::FixnumGe { left, right })); } else { let right = state.pop()?; let left = state.pop()?; @@ -938,9 +949,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { } match get_option!(dump_hir) { - Some(DumpHIR::WithoutSnapshot) => print!("HIR:\n{}", FunctionPrinter::without_snapshot(&fun)), - Some(DumpHIR::All) => print!("HIR:\n{}", FunctionPrinter::with_snapshot(&fun)), - Some(DumpHIR::Raw) => print!("HIR:\n{:#?}", &fun), None => {}, } @@ -949,8 +960,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { /// Generate guards for two fixnum outputs fn guard_two_fixnums(state: &mut FrameState, fun: &mut Function, block: BlockId) -> Result<(InsnId, InsnId), ParseError> { - let left = fun.push_insn(block, Insn::GuardType { val: state.stack_opnd(1)?, guard_type: Fixnum }); - let right = fun.push_insn(block, Insn::GuardType { val: state.stack_opnd(0)?, guard_type: Fixnum }); // Pop operands after guards for side exits state.pop()?; @@ -0,0 +1,14 @@ @@ -19,6 +19,7 @@ mod backend; mod disasm; mod options; mod profile; use codegen::gen_function; use options::{debug, get_option, Options}; @@ -29,6 +30,11 @@ use crate::cruby::*; #[unsafe(no_mangle)] pub static mut rb_zjit_enabled_p: bool = false; /// Initialize ZJIT, given options allocated by rb_zjit_init_options() #[unsafe(no_mangle)] pub extern "C" fn rb_zjit_init(options: *const u8) { @@ -109,8 +109,7 @@ fn parse_option(options: &mut Options, str_ptr: *const std::os::raw::c_char) -> /// Macro to print a message only when --zjit-debug is given macro_rules! debug { ($($msg:tt)*) => { - use crate::options::get_option; - if get_option!(debug) { eprintln!($($msg)*); } }; |