summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bernstein <ruby@bernsteinbear.com>2025-08-27 15:15:08 -0400
committerMax Bernstein <tekknolagi@gmail.com>2025-08-27 15:56:13 -0700
commitfb3d2a2a1977e702e46723ab0ed691b1e9433e7f (patch)
tree6d9b5b810b99c06a76ca4694ce0717c9050bc16a
parent4652879f4360c5a7a9255e6a0dd75688f8ef47f9 (diff)
ZJIT: Increment specific counter on side-exit
-rw-r--r--zjit.rb1
-rw-r--r--zjit/src/backend/lir.rs12
-rw-r--r--zjit/src/stats.rs38
3 files changed, 51 insertions, 0 deletions
diff --git a/zjit.rb b/zjit.rb
index cf0896e107..3476c1cb38 100644
--- a/zjit.rb
+++ b/zjit.rb
@@ -59,6 +59,7 @@ class << RubyVM::ZJIT
:ratio_in_zjit,
], buf:, stats:)
print_counters_with_prefix(prefix: 'exit_', prompt: 'side exit reasons', buf:, stats:, limit: 20)
+ print_counters_with_prefix(prefix: 'specific_exit_', prompt: 'specific side exit reasons', buf:, stats:, limit: 20)
buf
end
diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs
index 7e317d4991..0639176fd6 100644
--- a/zjit/src/backend/lir.rs
+++ b/zjit/src/backend/lir.rs
@@ -1604,6 +1604,18 @@ impl Assembler
Opnd::mem(64, SCRATCH_OPND, 0)
};
self.incr_counter(counter_opnd, 1.into());
+
+ asm_comment!(self, "increment a specific exit counter");
+ let counter = crate::stats::side_exit_reason_counter(reason);
+ self.load_into(SCRATCH_OPND, Opnd::const_ptr(crate::stats::counter_ptr(counter)));
+ let counter_opnd = if cfg!(target_arch = "aarch64") { // See arm64_split()
+ // Using C_CRET_OPND since arm64_emit uses both SCRATCH0 and SCRATCH1 for IncrCounter.
+ self.lea_into(C_RET_OPND, Opnd::mem(64, SCRATCH_OPND, 0));
+ C_RET_OPND
+ } else { // x86_emit expects Opnd::Mem
+ Opnd::mem(64, SCRATCH_OPND, 0)
+ };
+ self.incr_counter(counter_opnd, 1.into());
}
asm_comment!(self, "exit to the interpreter");
diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs
index b754404a66..c6b1ed29d6 100644
--- a/zjit/src/stats.rs
+++ b/zjit/src/stats.rs
@@ -81,6 +81,23 @@ make_counters! {
// exit_: Side exit reasons (ExitCounters shares the same prefix)
exit_compilation_failure,
+
+ // specific_exit_: Side exits counted by type, not by PC
+ specific_exit_unknown_newarray_send,
+ specific_exit_unknown_call_type,
+ specific_exit_unknown_opcode,
+ specific_exit_unhandled_instruction,
+ specific_exit_fixnum_add_overflow,
+ specific_exit_fixnum_sub_overflow,
+ specific_exit_fixnum_mult_overflow,
+ specific_exit_guard_type_failure,
+ specific_exit_guard_bit_equals_failure,
+ specific_exit_patchpoint,
+ specific_exit_callee_side_exit,
+ specific_exit_obj_to_string_fallback,
+ specific_exit_unknown_special_variable,
+ specific_exit_unhandled_defined_type,
+ specific_exit_interrupt,
}
/// Increase a counter by a specified amount
@@ -107,6 +124,27 @@ pub fn exit_counter_ptr(pc: *const VALUE) -> *mut u64 {
unsafe { exit_counters.get_unchecked_mut(opcode as usize) }
}
+pub fn side_exit_reason_counter(reason: crate::hir::SideExitReason) -> Counter {
+ use crate::hir::SideExitReason;
+ match reason {
+ SideExitReason::UnknownNewarraySend(_) => Counter::specific_exit_unknown_newarray_send,
+ SideExitReason::UnknownCallType => Counter::specific_exit_unknown_call_type,
+ SideExitReason::UnknownOpcode(_) => Counter::specific_exit_unknown_opcode,
+ SideExitReason::UnhandledInstruction(_) => Counter::specific_exit_unhandled_instruction,
+ SideExitReason::FixnumAddOverflow => Counter::specific_exit_fixnum_add_overflow,
+ SideExitReason::FixnumSubOverflow => Counter::specific_exit_fixnum_sub_overflow,
+ SideExitReason::FixnumMultOverflow => Counter::specific_exit_fixnum_mult_overflow,
+ SideExitReason::GuardType(_) => Counter::specific_exit_guard_type_failure,
+ SideExitReason::GuardBitEquals(_) => Counter::specific_exit_guard_bit_equals_failure,
+ SideExitReason::PatchPoint(_) => Counter::specific_exit_patchpoint,
+ SideExitReason::CalleeSideExit => Counter::specific_exit_callee_side_exit,
+ SideExitReason::ObjToStringFallback => Counter::specific_exit_obj_to_string_fallback,
+ SideExitReason::UnknownSpecialVariable(_) => Counter::specific_exit_unknown_special_variable,
+ SideExitReason::UnhandledDefinedType(_) => Counter::specific_exit_unhandled_defined_type,
+ SideExitReason::Interrupt => Counter::specific_exit_interrupt,
+ }
+}
+
/// Return a Hash object that contains ZJIT statistics
#[unsafe(no_mangle)]
pub extern "C" fn rb_zjit_stats(_ec: EcPtr, _self: VALUE, target_key: VALUE) -> VALUE {