summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashi.kokubun@shopify.com>2025-11-10 16:29:50 -0800
committerGitHub <noreply@github.com>2025-11-10 16:29:50 -0800
commitd268a551865977160aba99429c29f61c8d7c0eb0 (patch)
tree086beef5c52cd91a0c8ca88c69f390bcefee62ab
parent6238b6f53e4b10a1833eb90320f002f60be72d42 (diff)
ZJIT: Split unhandled_hir_insn and unknown_newarray_send stats (#15127)
-rw-r--r--zjit.rb3
-rw-r--r--zjit/src/codegen.rs3
-rw-r--r--zjit/src/hir.rs22
-rw-r--r--zjit/src/hir/tests.rs6
-rw-r--r--zjit/src/stats.rs37
5 files changed, 51 insertions, 20 deletions
diff --git a/zjit.rb b/zjit.rb
index 9728551c3f..396f52d4b4 100644
--- a/zjit.rb
+++ b/zjit.rb
@@ -172,8 +172,9 @@ class << RubyVM::ZJIT
print_counters_with_prefix(prefix: 'complex_arg_pass_', prompt: 'popular complex argument-parameter features not optimized', buf:, stats:, limit: 10)
# Show exit counters, ordered by the typical amount of exits for the prefix at the time
- print_counters_with_prefix(prefix: 'unhandled_yarv_insn_', prompt: 'unhandled YARV insns', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'compile_error_', prompt: 'compile error reasons', buf:, stats:, limit: 20)
+ print_counters_with_prefix(prefix: 'unhandled_yarv_insn_', prompt: 'unhandled YARV insns', buf:, stats:, limit: 20)
+ print_counters_with_prefix(prefix: 'unhandled_hir_insn_', prompt: 'unhandled HIR insns', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'exit_', prompt: 'side exit reasons', buf:, stats:, limit: 20)
# Show no-prefix counters, having the most important stat `ratio_in_zjit` at the end
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index 0fc0b1ce47..5047de934d 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -15,7 +15,7 @@ use crate::invariants::{
use crate::gc::append_gc_offsets;
use crate::payload::{get_or_create_iseq_payload, get_or_create_iseq_payload_ptr, IseqCodePtrs, IseqPayload, IseqStatus};
use crate::state::ZJITState;
-use crate::stats::{send_fallback_counter, exit_counter_for_compile_error, incr_counter, incr_counter_by, send_fallback_counter_for_method_type, send_without_block_fallback_counter_for_method_type, send_without_block_fallback_counter_for_optimized_method_type, send_fallback_counter_ptr_for_opcode, CompileError};
+use crate::stats::{CompileError, exit_counter_for_compile_error, exit_counter_for_unhandled_hir_insn, incr_counter, incr_counter_by, send_fallback_counter, send_fallback_counter_for_method_type, send_fallback_counter_ptr_for_opcode, send_without_block_fallback_counter_for_method_type, send_without_block_fallback_counter_for_optimized_method_type};
use crate::stats::{counter_ptr, with_time_stat, Counter, Counter::{compile_time_ns, exit_compile_error}};
use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
use crate::backend::lir::{self, Assembler, C_ARG_OPNDS, C_RET_OPND, CFP, EC, NATIVE_BASE_PTR, NATIVE_STACK_PTR, Opnd, SP, SideExit, Target, asm_ccall, asm_comment};
@@ -280,6 +280,7 @@ fn gen_function(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function) -> Resul
let insn = function.find(insn_id);
if let Err(last_snapshot) = gen_insn(cb, &mut jit, &mut asm, function, insn_id, &insn) {
debug!("ZJIT: gen_function: Failed to compile insn: {insn_id} {insn}. Generating side-exit.");
+ gen_incr_counter(&mut asm, exit_counter_for_unhandled_hir_insn(&insn));
gen_side_exit(&mut jit, &mut asm, &SideExitReason::UnhandledHIRInsn(insn_id), &function.frame_state(last_snapshot));
// Don't bother generating code after a side-exit. We won't run it.
// TODO(max): Generate ud2 or equivalent.
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index 85e9bdb00a..a8eff79765 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -456,8 +456,8 @@ impl PtrPrintMap {
#[derive(Debug, Clone, Copy)]
pub enum SideExitReason {
- UnknownNewarraySend(vm_opt_newarray_send_type),
- UnknownDuparraySend(u64),
+ UnhandledNewarraySend(vm_opt_newarray_send_type),
+ UnhandledDuparraySend(u64),
UnknownSpecialVariable(u64),
UnhandledHIRInsn(InsnId),
UnhandledYARVInsn(u32),
@@ -547,13 +547,13 @@ impl std::fmt::Display for SideExitReason {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
SideExitReason::UnhandledYARVInsn(opcode) => write!(f, "UnhandledYARVInsn({})", insn_name(*opcode as usize)),
- SideExitReason::UnknownNewarraySend(VM_OPT_NEWARRAY_SEND_MAX) => write!(f, "UnknownNewarraySend(MAX)"),
- SideExitReason::UnknownNewarraySend(VM_OPT_NEWARRAY_SEND_MIN) => write!(f, "UnknownNewarraySend(MIN)"),
- SideExitReason::UnknownNewarraySend(VM_OPT_NEWARRAY_SEND_HASH) => write!(f, "UnknownNewarraySend(HASH)"),
- SideExitReason::UnknownNewarraySend(VM_OPT_NEWARRAY_SEND_PACK) => write!(f, "UnknownNewarraySend(PACK)"),
- SideExitReason::UnknownNewarraySend(VM_OPT_NEWARRAY_SEND_PACK_BUFFER) => write!(f, "UnknownNewarraySend(PACK_BUFFER)"),
- SideExitReason::UnknownNewarraySend(VM_OPT_NEWARRAY_SEND_INCLUDE_P) => write!(f, "UnknownNewarraySend(INCLUDE_P)"),
- SideExitReason::UnknownDuparraySend(method_id) => write!(f, "UnknownDuparraySend({})", method_id),
+ SideExitReason::UnhandledNewarraySend(VM_OPT_NEWARRAY_SEND_MAX) => write!(f, "UnhandledNewarraySend(MAX)"),
+ SideExitReason::UnhandledNewarraySend(VM_OPT_NEWARRAY_SEND_MIN) => write!(f, "UnhandledNewarraySend(MIN)"),
+ SideExitReason::UnhandledNewarraySend(VM_OPT_NEWARRAY_SEND_HASH) => write!(f, "UnhandledNewarraySend(HASH)"),
+ SideExitReason::UnhandledNewarraySend(VM_OPT_NEWARRAY_SEND_PACK) => write!(f, "UnhandledNewarraySend(PACK)"),
+ SideExitReason::UnhandledNewarraySend(VM_OPT_NEWARRAY_SEND_PACK_BUFFER) => write!(f, "UnhandledNewarraySend(PACK_BUFFER)"),
+ SideExitReason::UnhandledNewarraySend(VM_OPT_NEWARRAY_SEND_INCLUDE_P) => write!(f, "UnhandledNewarraySend(INCLUDE_P)"),
+ SideExitReason::UnhandledDuparraySend(method_id) => write!(f, "UnhandledDuparraySend({})", method_id),
SideExitReason::GuardType(guard_type) => write!(f, "GuardType({guard_type})"),
SideExitReason::GuardTypeNot(guard_type) => write!(f, "GuardTypeNot({guard_type})"),
SideExitReason::GuardBitEquals(value) => write!(f, "GuardBitEquals({})", value.print(&PtrPrintMap::identity())),
@@ -4658,7 +4658,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
},
_ => {
// Unknown opcode; side-exit into the interpreter
- fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnknownNewarraySend(method) });
+ fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnhandledNewarraySend(method) });
break; // End the block
},
};
@@ -4686,7 +4686,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
let bop = match method_id {
x if x == ID!(include_p).0 => BOP_INCLUDE_P,
_ => {
- fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnknownDuparraySend(method_id) });
+ fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnhandledDuparraySend(method_id) });
break;
},
};
diff --git a/zjit/src/hir/tests.rs b/zjit/src/hir/tests.rs
index b3230b71c8..4caf0f838f 100644
--- a/zjit/src/hir/tests.rs
+++ b/zjit/src/hir/tests.rs
@@ -1925,7 +1925,7 @@ pub mod hir_build_tests {
Jump bb2(v8, v9, v10, v11, v12)
bb2(v14:BasicObject, v15:BasicObject, v16:BasicObject, v17:NilClass, v18:NilClass):
v25:BasicObject = SendWithoutBlock v15, :+, v16
- SideExit UnknownNewarraySend(MIN)
+ SideExit UnhandledNewarraySend(MIN)
");
}
@@ -1957,7 +1957,7 @@ pub mod hir_build_tests {
Jump bb2(v8, v9, v10, v11, v12)
bb2(v14:BasicObject, v15:BasicObject, v16:BasicObject, v17:NilClass, v18:NilClass):
v25:BasicObject = SendWithoutBlock v15, :+, v16
- SideExit UnknownNewarraySend(HASH)
+ SideExit UnhandledNewarraySend(HASH)
");
}
@@ -1991,7 +1991,7 @@ pub mod hir_build_tests {
v25:BasicObject = SendWithoutBlock v15, :+, v16
v31:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
v32:StringExact = StringCopy v31
- SideExit UnknownNewarraySend(PACK)
+ SideExit UnhandledNewarraySend(PACK)
");
}
diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs
index 3b74cc4533..ec52662086 100644
--- a/zjit/src/stats.rs
+++ b/zjit/src/stats.rs
@@ -128,8 +128,12 @@ make_counters! {
exit {
// exit_: Side exits reasons
exit_compile_error,
- exit_unknown_newarray_send,
- exit_unknown_duparray_send,
+ exit_unhandled_newarray_send_min,
+ exit_unhandled_newarray_send_hash,
+ exit_unhandled_newarray_send_pack,
+ exit_unhandled_newarray_send_pack_buffer,
+ exit_unhandled_newarray_send_unknown,
+ exit_unhandled_duparray_send,
exit_unhandled_tailcall,
exit_unhandled_splat,
exit_unhandled_kwarg,
@@ -218,6 +222,13 @@ make_counters! {
compile_error_validation_type_check_failure,
compile_error_validation_misc_validation_error,
+ // unhandled_hir_insn_: Unhandled HIR instructions
+ unhandled_hir_insn_array_max,
+ unhandled_hir_insn_fixnum_div,
+ unhandled_hir_insn_throw,
+ unhandled_hir_insn_invokebuiltin,
+ unhandled_hir_insn_unknown,
+
// The number of times YARV instructions are executed on JIT code
zjit_insn_count,
@@ -377,14 +388,32 @@ pub fn exit_counter_for_compile_error(compile_error: &CompileError) -> Counter {
}
}
+pub fn exit_counter_for_unhandled_hir_insn(insn: &crate::hir::Insn) -> Counter {
+ use crate::hir::Insn::*;
+ use crate::stats::Counter::*;
+ match insn {
+ ArrayMax { .. } => unhandled_hir_insn_array_max,
+ FixnumDiv { .. } => unhandled_hir_insn_fixnum_div,
+ Throw { .. } => unhandled_hir_insn_throw,
+ InvokeBuiltin { .. } => unhandled_hir_insn_invokebuiltin,
+ _ => unhandled_hir_insn_unknown,
+ }
+}
+
pub fn side_exit_counter(reason: crate::hir::SideExitReason) -> Counter {
use crate::hir::SideExitReason::*;
use crate::hir::CallType::*;
use crate::hir::Invariant;
use crate::stats::Counter::*;
match reason {
- UnknownNewarraySend(_) => exit_unknown_newarray_send,
- UnknownDuparraySend(_) => exit_unknown_duparray_send,
+ UnhandledNewarraySend(send_type) => match send_type {
+ VM_OPT_NEWARRAY_SEND_MIN => exit_unhandled_newarray_send_min,
+ VM_OPT_NEWARRAY_SEND_HASH => exit_unhandled_newarray_send_hash,
+ VM_OPT_NEWARRAY_SEND_PACK => exit_unhandled_newarray_send_pack,
+ VM_OPT_NEWARRAY_SEND_PACK_BUFFER => exit_unhandled_newarray_send_pack_buffer,
+ _ => exit_unhandled_newarray_send_unknown,
+ }
+ UnhandledDuparraySend(_) => exit_unhandled_duparray_send,
UnhandledCallType(Tailcall) => exit_unhandled_tailcall,
UnhandledCallType(Splat) => exit_unhandled_splat,
UnhandledCallType(Kwarg) => exit_unhandled_kwarg,