diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml index 8f2ca884b16ef8..3da1080be96a09 100644 --- a/.github/workflows/zjit-macos.yml +++ b/.github/workflows/zjit-macos.yml @@ -51,6 +51,7 @@ jobs: RUN_OPTS: ${{ matrix.run_opts }} SPECOPTS: ${{ matrix.specopts }} TESTOPTS: ${{ matrix.testopts }} + ZJIT_RB_BUG: 1 runs-on: macos-14 diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml index 3dfa8260a80fc1..14b9eab0423105 100644 --- a/.github/workflows/zjit-ubuntu.yml +++ b/.github/workflows/zjit-ubuntu.yml @@ -75,6 +75,7 @@ jobs: RUBY_DEBUG: ci BUNDLE_JOBS: 8 # for yjit-bench RUST_BACKTRACE: 1 + ZJIT_RB_BUG: 1 runs-on: ubuntu-22.04 diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index 0024c780b909d3..73db7237109322 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -388,7 +388,7 @@ There are multiple test suites: - `make test-all` - `make test-spec` - `make check` runs all of the above -- `make yjit-smoke-test` runs quick checks to see that YJIT is working correctly +- `make yjit-check` runs quick checks to see that YJIT is working correctly The tests can be run in parallel like this: diff --git a/doc/zjit.md b/doc/zjit.md index b5b605d5cb0855..4eedcca3ba7ac9 100644 --- a/doc/zjit.md +++ b/doc/zjit.md @@ -110,6 +110,49 @@ You can also run a single test case by matching the method name: make test-all TESTS="test/ruby/test_zjit.rb -n TestZJIT#test_putobject" ``` +## Statistics Collection + +ZJIT provides detailed statistics about JIT compilation and execution behavior. + +### Basic Stats + +Run with basic statistics printed on exit: + +```bash +./miniruby --zjit-stats script.rb +``` + +Collect stats without printing (access via `RubyVM::ZJIT.stats` in Ruby): + +```bash +./miniruby --zjit-stats=quiet script.rb +``` + +### Accessing Stats in Ruby + +```ruby +# Check if stats are enabled +if RubyVM::ZJIT.stats_enabled? + stats = RubyVM::ZJIT.stats + puts "Compiled ISEQs: #{stats[:compiled_iseq_count]}" + puts "Failed ISEQs: #{stats[:failed_iseq_count]}" + + # You can also reset stats during execution + RubyVM::ZJIT.reset_stats! +end +``` + +### Performance Ratio + +The `ratio_in_zjit` stat shows the percentage of Ruby instructions executed in JIT code vs interpreter. This metric only appears when ZJIT is built with `--enable-zjit=stats` (which enables `rb_vm_insn_count` tracking) and represents a key performance indicator for ZJIT effectiveness. + +To build with stats support: + +```bash +./configure --enable-zjit=stats +make -j +``` + ## ZJIT Glossary This glossary contains terms that are helpful for understanding ZJIT. diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index 3b6cc1178df221..4f6c62dc35c174 100644 --- a/test/ruby/test_require.rb +++ b/test/ruby/test_require.rb @@ -857,7 +857,7 @@ def to_str def to_path = @path end - def create_ruby_file = Tempfile.create(["test", ".rb"]).path + def create_ruby_file = Tempfile.open(["test", ".rb"]).path require MyString.new(create_ruby_file) $LOADED_FEATURES.unshift(create_ruby_file) diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index 5f59f9fc02b240..2db45453b5fc50 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -439,6 +439,21 @@ def entry = [test(1), test(3, 4)] }, call_threshold: 2 end + def test_forwardable_iseq + assert_compiles '1', %q{ + def test(...) = 1 + test + } + end + + def test_sendforward + assert_runs '[1, 2]', %q{ + def callee(a, b) = [a, b] + def test(...) = callee(...) + test(1, 2) + }, insns: [:sendforward] + end + def test_iseq_with_optional_arguments assert_compiles '[[1, 2], [3, 4]]', %q{ def test(a, b = 2) = [a, b] @@ -2569,6 +2584,46 @@ def test(x) }, insns: [:opt_case_dispatch] end + def test_invokeblock + assert_compiles '42', %q{ + def test + yield + end + test { 42 } + }, insns: [:invokeblock] + end + + def test_invokeblock_with_args + assert_compiles '3', %q{ + def test(x, y) + yield x, y + end + test(1, 2) { |a, b| a + b } + }, insns: [:invokeblock] + end + + def test_invokeblock_no_block_given + assert_compiles ':error', %q{ + def test + yield rescue :error + end + test + }, insns: [:invokeblock] + end + + def test_invokeblock_multiple_yields + assert_compiles "[1, 2, 3]", %q{ + results = [] + def test + yield 1 + yield 2 + yield 3 + end + test { |x| results << x } + results + }, insns: [:invokeblock] + end + private # Assert that every method call in `test_script` can be compiled by ZJIT diff --git a/vm_insnhelper.c b/vm_insnhelper.c index cc22e4a2e0e59d..362af31188813b 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -6139,26 +6139,29 @@ rb_vm_opt_send_without_block(rb_execution_context_t *ec, rb_control_frame_t *reg VALUE rb_vm_invokesuper(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq) +{ + stack_check(ec); + + VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, true); + VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super); + + VM_EXEC(ec, val); + return val; +} + +VALUE +rb_vm_invokesuperforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq) { stack_check(ec); struct rb_forwarding_call_data adjusted_cd; struct rb_callinfo adjusted_ci; - VALUE bh; - VALUE val; - - if (vm_ci_flag(cd->ci) & VM_CALL_FORWARDING) { - bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq, true, &adjusted_cd, &adjusted_ci); + VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq, true, &adjusted_cd, &adjusted_ci); - val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super); + VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super); - if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) { - RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc); - } - } - else { - bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, true); - val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super); + if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) { + RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc); } VM_EXEC(ec, val); diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index e243270af635ca..cd057359ac2427 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -9731,7 +9731,7 @@ fn gen_invokesuper( return Some(status); } - // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of send + // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of invokesuper let blockiseq = jit.get_arg(1).as_iseq(); gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { extern "C" { @@ -9748,7 +9748,23 @@ fn gen_invokesuperforward( jit: &mut JITState, asm: &mut Assembler, ) -> Option { - return gen_invokesuper(jit, asm); + // Generate specialized code if possible + let cd = jit.get_arg(0).as_ptr(); + if let Some(status) = gen_invokesuper_specialized(jit, asm, cd) { + return Some(status); + } + + // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of invokesuperforward + let blockiseq = jit.get_arg(1).as_iseq(); + gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| { + extern "C" { + fn rb_vm_invokesuperforward(ec: EcPtr, cfp: CfpPtr, cd: VALUE, blockiseq: IseqPtr) -> VALUE; + } + asm.ccall( + rb_vm_invokesuperforward as *const u8, + vec![EC, CFP, (cd as usize).into(), VALUE(blockiseq as usize).into()], + ) + }) } fn gen_invokesuper_specialized( diff --git a/yjit/yjit.mk b/yjit/yjit.mk index 39587928d4d18b..6b22a15960c1f3 100644 --- a/yjit/yjit.mk +++ b/yjit/yjit.mk @@ -34,8 +34,8 @@ endif RUST_VERSION = +1.58.0 # Gives quick feedback about YJIT. Not a replacement for a full test run. -.PHONY: yjit-smoke-test -yjit-smoke-test: +.PHONY: yjit-check +yjit-check: ifneq ($(strip $(CARGO)),) $(CARGO) test --all-features -q --manifest-path='$(top_srcdir)/yjit/Cargo.toml' endif diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index ca25084d950999..8c435cc854f61e 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -369,6 +369,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio gen_send_without_block(jit, asm, *cd, &function.frame_state(*state)), Insn::SendWithoutBlockDirect { cme, iseq, self_val, args, state, .. } => gen_send_without_block_direct(cb, jit, asm, *cme, *iseq, opnd!(self_val), opnds!(args), &function.frame_state(*state)), &Insn::InvokeSuper { cd, blockiseq, state, .. } => gen_invokesuper(jit, asm, cd, blockiseq, &function.frame_state(state)), + Insn::InvokeBlock { cd, state, .. } => gen_invoke_block(jit, asm, *cd, &function.frame_state(*state)), // Ensure we have enough room fit ec, self, and arguments // TODO remove this check when we have stack args (we can use Time.new to test it) Insn::InvokeBuiltin { bf, state, .. } if bf.argc + 2 > (C_ARG_OPNDS.len() as i32) => return Err(*state), @@ -1093,6 +1094,31 @@ fn gen_send_without_block_direct( ret } +/// Compile for invokeblock +fn gen_invoke_block( + jit: &mut JITState, + asm: &mut Assembler, + cd: *const rb_call_data, + state: &FrameState, +) -> lir::Opnd { + gen_incr_counter(asm, Counter::dynamic_send_count); + + // Save PC and SP, spill locals and stack + gen_prepare_call_with_gc(asm, state); + gen_save_sp(asm, state.stack().len()); + gen_spill_locals(jit, asm, state); + gen_spill_stack(jit, asm, state); + + asm_comment!(asm, "call invokeblock"); + unsafe extern "C" { + fn rb_vm_invokeblock(ec: EcPtr, cfp: CfpPtr, cd: VALUE) -> VALUE; + } + asm.ccall( + rb_vm_invokeblock as *const u8, + vec![EC, CFP, (cd as usize).into()], + ) +} + /// Compile a dynamic dispatch for `super` fn gen_invokesuper( jit: &mut JITState, diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index b7674b6a8c7058..27bfe1fc7b92be 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -583,8 +583,9 @@ pub enum Insn { /// Un-optimized fallback implementation (dynamic dispatch) for send-ish instructions /// Ignoring keyword arguments etc for now SendWithoutBlock { self_val: InsnId, cd: *const rb_call_data, args: Vec, state: InsnId }, - Send { self_val: InsnId, cd: *const rb_call_data, blockiseq: IseqPtr, args: Vec, state: InsnId }, - InvokeSuper { self_val: InsnId, cd: *const rb_call_data, blockiseq: IseqPtr, args: Vec, state: InsnId }, + Send { cd: *const rb_call_data, blockiseq: IseqPtr, args: Vec, state: InsnId }, + InvokeSuper { cd: *const rb_call_data, blockiseq: IseqPtr, args: Vec, state: InsnId }, + InvokeBlock { cd: *const rb_call_data, args: Vec, state: InsnId }, /// Optimized ISEQ call SendWithoutBlockDirect { @@ -828,18 +829,25 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { } Ok(()) } - Insn::Send { self_val, cd, args, blockiseq, .. } => { + Insn::Send { cd, args, blockiseq, .. } => { // For tests, we want to check HIR snippets textually. Addresses change // between runs, making tests fail. Instead, pick an arbitrary hex value to // use as a "pointer" so we can check the rest of the HIR. - write!(f, "Send {self_val}, {:p}, :{}", self.ptr_map.map_ptr(blockiseq), ruby_call_method_name(*cd))?; + write!(f, "Send {:p}, :{}", self.ptr_map.map_ptr(blockiseq), ruby_call_method_name(*cd))?; for arg in args { write!(f, ", {arg}")?; } Ok(()) } - Insn::InvokeSuper { self_val, blockiseq, args, .. } => { - write!(f, "InvokeSuper {self_val}, {:p}", self.ptr_map.map_ptr(blockiseq))?; + Insn::InvokeSuper { blockiseq, args, .. } => { + write!(f, "InvokeSuper {:p}", self.ptr_map.map_ptr(blockiseq))?; + for arg in args { + write!(f, ", {arg}")?; + } + Ok(()) + } + Insn::InvokeBlock { args, .. } => { + write!(f, "InvokeBlock")?; for arg in args { write!(f, ", {arg}")?; } @@ -1335,20 +1343,23 @@ impl Function { args: find_vec!(args), state, }, - &Send { self_val, cd, blockiseq, ref args, state } => Send { - self_val: find!(self_val), + &Send { cd, blockiseq, ref args, state } => Send { cd, blockiseq, args: find_vec!(args), state, }, - &InvokeSuper { self_val, cd, blockiseq, ref args, state } => InvokeSuper { - self_val: find!(self_val), + &InvokeSuper { cd, blockiseq, ref args, state } => InvokeSuper { cd, blockiseq, args: find_vec!(args), state, }, + &InvokeBlock { cd, ref args, state } => InvokeBlock { + cd, + args: find_vec!(args), + state, + }, &InvokeBuiltin { bf, ref args, state, return_type } => InvokeBuiltin { bf, args: find_vec!(args), state, return_type }, &ArrayDup { val, state } => ArrayDup { val: find!(val), state }, &HashDup { val, state } => HashDup { val: find!(val), state }, @@ -1463,6 +1474,7 @@ impl Function { Insn::SendWithoutBlockDirect { .. } => types::BasicObject, Insn::Send { .. } => types::BasicObject, Insn::InvokeSuper { .. } => types::BasicObject, + Insn::InvokeBlock { .. } => types::BasicObject, Insn::InvokeBuiltin { return_type, .. } => return_type.unwrap_or(types::BasicObject), Insn::Defined { pushval, .. } => Type::from_value(*pushval).union(types::NilClass), Insn::DefinedIvar { .. } => types::BasicObject, @@ -2268,15 +2280,16 @@ impl Function { worklist.push_back(val); worklist.push_back(state); } - &Insn::Send { self_val, ref args, state, .. } | &Insn::SendWithoutBlock { self_val, ref args, state, .. } - | &Insn::SendWithoutBlockDirect { self_val, ref args, state, .. } - | &Insn::InvokeSuper { self_val, ref args, state, .. } => { + | &Insn::SendWithoutBlockDirect { self_val, ref args, state, .. } => { worklist.push_back(self_val); worklist.extend(args); worklist.push_back(state); } - &Insn::InvokeBuiltin { ref args, state, .. } => { + &Insn::InvokeSuper { ref args, state, .. } + | &Insn::Send { ref args, state, .. } + | &Insn::InvokeBuiltin { ref args, state, .. } + | &Insn::InvokeBlock { ref args, state, .. } => { worklist.extend(args); worklist.push_back(state) } @@ -2965,17 +2978,9 @@ pub enum CallType { Forwarding, } -#[derive(Clone, Debug, PartialEq)] -pub enum ParameterType { - /// For example, `foo(...)`. Interaction of JIT - /// calling convention and side exits currently unsolved. - Forwardable, -} - #[derive(Clone, Debug, PartialEq)] pub enum ParseError { StackUnderflow(FrameState), - UnknownParameterType(ParameterType), MalformedIseq(u32), // insn_idx into iseq_encoded Validation(ValidationError), NotAllowed, @@ -3049,17 +3054,11 @@ impl ProfileOracle { /// The index of the self parameter in the HIR function pub const SELF_PARAM_IDX: usize = 0; -fn filter_unknown_parameter_type(iseq: *const rb_iseq_t) -> Result<(), ParseError> { - if unsafe { rb_get_iseq_flags_forwardable(iseq) } { return Err(ParseError::UnknownParameterType(ParameterType::Forwardable)); } - Ok(()) -} - /// Compile ISEQ into High-level IR pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { if !ZJITState::can_compile_iseq(iseq) { return Err(ParseError::NotAllowed); } - filter_unknown_parameter_type(iseq)?; let payload = get_or_create_iseq_payload(iseq); let mut profiles = ProfileOracle::new(payload); let mut fun = Function::new(iseq); @@ -3623,9 +3622,9 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { let argc = unsafe { vm_ci_argc((*cd).ci) }; let args = state.stack_pop_n(argc as usize)?; - let recv = state.stack_pop()?; + let _recv = state.stack_pop()?; let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); - let send = fun.push_insn(block, Insn::Send { self_val: recv, cd, blockiseq, args, state: exit_id }); + let send = fun.push_insn(block, Insn::Send { cd, blockiseq, args, state: exit_id }); state.stack_push(send); // Reload locals that may have been modified by the blockiseq. @@ -3648,10 +3647,10 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { } let argc = unsafe { vm_ci_argc((*cd).ci) }; let args = state.stack_pop_n(argc as usize)?; - let recv = state.stack_pop()?; + let _recv = state.stack_pop()?; let blockiseq: IseqPtr = get_arg(pc, 1).as_ptr(); let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); - let result = fun.push_insn(block, Insn::InvokeSuper { self_val: recv, cd, blockiseq, args, state: exit_id }); + let result = fun.push_insn(block, Insn::InvokeSuper { cd, blockiseq, args, state: exit_id }); state.stack_push(result); if !blockiseq.is_null() { @@ -3665,6 +3664,21 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { } } } + YARVINSN_invokeblock => { + let cd: *const rb_call_data = get_arg(pc, 0).as_ptr(); + let call_info = unsafe { rb_get_call_data_ci(cd) }; + if let Err(call_type) = unknown_call_type(unsafe { rb_vm_ci_flag(call_info) }) { + // Unknown call type; side-exit into the interpreter + let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); + fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnhandledCallType(call_type) }); + break; // End the block + } + let argc = unsafe { vm_ci_argc((*cd).ci) }; + let args = state.stack_pop_n(argc as usize)?; + let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); + let result = fun.push_insn(block, Insn::InvokeBlock { cd, args, state: exit_id }); + state.stack_push(result); + } YARVINSN_getglobal => { let id = ID(get_arg(pc, 0).as_u64()); let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); @@ -5049,7 +5063,7 @@ mod tests { fn test@:3: bb0(v0:BasicObject, v1:BasicObject): v5:BasicObject = GetLocal l0, EP@3 - v7:BasicObject = Send v5, 0x1000, :each + v7:BasicObject = Send 0x1000, :each v8:BasicObject = GetLocal l0, EP@3 CheckInterrupts Return v7 @@ -5160,7 +5174,7 @@ mod tests { assert_snapshot!(hir_string("test"), @r" fn test@:2: bb0(v0:BasicObject): - v5:BasicObject = InvokeSuper v0, 0x1000 + v5:BasicObject = InvokeSuper 0x1000 CheckInterrupts Return v5 "); @@ -5174,7 +5188,7 @@ mod tests { assert_snapshot!(hir_string("test"), @r" fn test@:2: bb0(v0:BasicObject): - v5:BasicObject = InvokeSuper v0, 0x1000 + v5:BasicObject = InvokeSuper 0x1000 CheckInterrupts Return v5 "); @@ -5198,13 +5212,23 @@ mod tests { eval(" def test(...) = super(...) "); - assert_compile_fails("test", ParseError::UnknownParameterType(ParameterType::Forwardable)); + assert_snapshot!(hir_string("test"), @r" + fn test@:2: + bb0(v0:BasicObject, v1:BasicObject): + SideExit UnhandledYARVInsn(invokesuperforward) + "); } #[test] - fn test_cant_compile_forwardable() { + fn test_compile_forwardable() { eval("def forwardable(...) = nil"); - assert_compile_fails("forwardable", ParseError::UnknownParameterType(ParameterType::Forwardable)); + assert_snapshot!(hir_string("forwardable"), @r" + fn forwardable@:1: + bb0(v0:BasicObject, v1:BasicObject): + v5:NilClass = Const Value(nil) + CheckInterrupts + Return v5 + "); } // TODO(max): Figure out how to generate a call with OPT_SEND flag @@ -5249,7 +5273,11 @@ mod tests { eval(" def test(...) = foo(...) "); - assert_compile_fails("test", ParseError::UnknownParameterType(ParameterType::Forwardable)); + assert_snapshot!(hir_string("test"), @r" + fn test@:2: + bb0(v0:BasicObject, v1:BasicObject): + SideExit UnhandledYARVInsn(sendforward) + "); } #[test] @@ -5835,11 +5863,14 @@ mod tests { v19:CBool = Test v16 IfFalse v19, bb1(v0, v1, v2, v3, v4, v10) PatchPoint NoEPEscape(open) - SideExit UnhandledYARVInsn(invokeblock) - bb1(v27:BasicObject, v28:BasicObject, v29:BasicObject, v30:BasicObject, v31:BasicObject, v32:BasicObject): + v26:BasicObject = InvokeBlock, v10 + v30:BasicObject = InvokeBuiltin dir_s_close, v0, v10 + CheckInterrupts + Return v26 + bb1(v36:BasicObject, v37:BasicObject, v38:BasicObject, v39:BasicObject, v40:BasicObject, v41:BasicObject): PatchPoint NoEPEscape(open) CheckInterrupts - Return v32 + Return v41 "); } @@ -6028,6 +6059,38 @@ mod tests { Throw TAG_BREAK, v6 "); } + + #[test] + fn test_invokeblock() { + eval(r#" + def test + yield + end + "#); + assert_snapshot!(hir_string("test"), @r" + fn test@:3: + bb0(v0:BasicObject): + v5:BasicObject = InvokeBlock + CheckInterrupts + Return v5 + "); + } + + #[test] + fn test_invokeblock_with_args() { + eval(r#" + def test(x, y) + yield x, y + end + "#); + assert_snapshot!(hir_string("test"), @r" + fn test@:3: + bb0(v0:BasicObject, v1:BasicObject, v2:BasicObject): + v7:BasicObject = InvokeBlock, v1, v2 + CheckInterrupts + Return v7 + "); + } } #[cfg(test)] @@ -7735,7 +7798,7 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:3: bb0(v0:BasicObject): - v5:BasicObject = Send v0, 0x1000, :foo + v5:BasicObject = Send 0x1000, :foo CheckInterrupts Return v5 "); @@ -7759,7 +7822,7 @@ mod opt_tests { v1:NilClass = Const Value(nil) v5:Fixnum[1] = Const Value(1) SetLocal l0, EP@3, v5 - v10:BasicObject = Send v0, 0x1000, :foo + v10:BasicObject = Send 0x1000, :foo v11:BasicObject = GetLocal l0, EP@3 v14:BasicObject = GetLocal l0, EP@3 CheckInterrupts diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs index 67edfe3d2d4014..471704bc06a38e 100644 --- a/zjit/src/stats.rs +++ b/zjit/src/stats.rs @@ -130,7 +130,6 @@ make_counters! { compile_error_parse_malformed_iseq, compile_error_parse_validation, compile_error_parse_not_allowed, - compile_error_parse_parameter_type_forwardable, // The number of times YARV instructions are executed on JIT code zjit_insn_count, @@ -196,7 +195,6 @@ pub enum CompileError { /// Return a raw pointer to the exit counter for a given CompileError pub fn exit_counter_for_compile_error(compile_error: &CompileError) -> Counter { use crate::hir::ParseError::*; - use crate::hir::ParameterType::*; use crate::stats::CompileError::*; use crate::stats::Counter::*; match compile_error { @@ -210,9 +208,6 @@ pub fn exit_counter_for_compile_error(compile_error: &CompileError) -> Counter { MalformedIseq(_) => compile_error_parse_malformed_iseq, Validation(_) => compile_error_parse_validation, NotAllowed => compile_error_parse_not_allowed, - UnknownParameterType(parameter_type) => match parameter_type { - Forwardable => compile_error_parse_parameter_type_forwardable, - } } } }