Skip to content

Commit ca2377f

Browse files
committed
WIP
1 parent fc6d031 commit ca2377f

4 files changed

Lines changed: 47 additions & 42 deletions

File tree

zjit.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def stats_string
4343
print_counters_with_prefix(prefix: 'dynamic_send_type_', prompt: 'dynamic send types', buf:, stats:, limit: 20)
4444
print_counters_with_prefix(prefix: 'unspecialized_def_type_', prompt: 'send fallback unspecialized def_types', buf:, stats:, limit: 20)
4545
print_counters_with_prefix(prefix: 'send_fallback_', prompt: 'dynamic send types', buf:, stats:, limit: 20)
46-
print_counters_with_prefix(prefix: 'not_optimized_cfuncs', prompt: 'Unoptimized C functions', buf:, stats:, limit: 20)
46+
print_counters_with_prefix(prefix: 'not_optimized_cfuncs_', prompt: 'Unoptimized C functions', buf:, stats:, limit: 20)
4747

4848
# Show exit counters, ordered by the typical amount of exits for the prefix at the time
4949
print_counters_with_prefix(prefix: 'unhandled_yarv_insn_', prompt: 'unhandled YARV insns', buf:, stats:, limit: 20)

zjit/src/codegen.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
415415
Insn::GetSpecialSymbol { symbol_type, state: _ } => gen_getspecial_symbol(asm, *symbol_type),
416416
Insn::GetSpecialNumber { nth, state } => gen_getspecial_number(asm, *nth, &function.frame_state(*state)),
417417
&Insn::IncrCounter(counter) => no_output!(gen_incr_counter(asm, counter)),
418-
&Insn::CountUnoptimizedCFunc { cme } => no_output!(gen_count_unoptimized_cfunc(asm, cme)),
418+
Insn::CountUnoptimizedCFunc { signature, counter_ptr } => no_output!(gen_count_unoptimized_cfunc(asm, signature, *counter_ptr)),
419419
Insn::ObjToString { val, cd, state, .. } => gen_objtostring(jit, asm, opnd!(val), *cd, &function.frame_state(*state)),
420420
&Insn::CheckInterrupts { state } => no_output!(gen_check_interrupts(jit, asm, &function.frame_state(state))),
421421
&Insn::HashDup { val, state } => { gen_hash_dup(asm, opnd!(val), &function.frame_state(state)) },
@@ -1577,13 +1577,13 @@ fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd,
15771577
}
15781578

15791579
/// Generate code that records unoptimized C functions if --zjit-stats is enabled
1580-
fn gen_count_unoptimized_cfunc(asm: &mut Assembler, cme: *const rb_callable_method_entry_struct) {
1580+
fn gen_count_unoptimized_cfunc(asm: &mut Assembler, signature: &str, counter_ptr: *mut u64) {
15811581
if get_option!(stats) {
15821582
unsafe extern "C" {
1583-
fn rb_zjit_count_unoptimized_cfunc(cme: *const rb_callable_method_entry_struct);
1583+
fn rb_zjit_count_unoptimized_cfunc(counter_ptr: *mut u64);
15841584
}
1585-
asm_comment!(asm, "count unoptimized cfunc");
1586-
asm_ccall!(asm, rb_zjit_count_unoptimized_cfunc, Opnd::const_ptr(cme));
1585+
asm_comment!(asm, "count unoptimized cfunc: {}", signature);
1586+
asm_ccall!(asm, rb_zjit_count_unoptimized_cfunc, Opnd::const_ptr(counter_ptr as *const u8));
15871587
}
15881588
}
15891589

zjit/src/hir.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::{
1414
use crate::hir_type::{Type, types};
1515
use crate::bitset::BitSet;
1616
use crate::profile::{TypeDistributionSummary, ProfiledType};
17-
use crate::stats::Counter;
17+
use crate::stats::{Counter, get_or_create_unoptimized_cfunc_counter_ptr};
1818

1919
/// An index of an [`Insn`] in a [`Function`]. This is a popular
2020
/// type since this effectively acts as a pointer to an [`Insn`].
@@ -698,7 +698,7 @@ pub enum Insn {
698698
IncrCounter(Counter),
699699

700700
/// Increment a counter in ZJIT stats for the given C function
701-
CountUnoptimizedCFunc { cme: *const rb_callable_method_entry_struct },
701+
CountUnoptimizedCFunc { signature: String, counter_ptr: *mut u64 },
702702

703703
/// Equivalent of RUBY_VM_CHECK_INTS. Automatically inserted by the compiler before jumps and
704704
/// return instructions.
@@ -959,7 +959,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
959959
}
960960
Ok(())
961961
},
962-
Insn::CountUnoptimizedCFunc { .. } => write!(f, "CountUnoptimizedCFunc"),
962+
Insn::CountUnoptimizedCFunc { signature, counter_ptr: _ } => write!(f, "CountUnoptimizedCFunc {}", signature),
963963
Insn::Snapshot { state } => write!(f, "Snapshot {}", state.print(self.ptr_map)),
964964
Insn::Defined { op_type, v, .. } => {
965965
// op_type (enum defined_type) printing logic from iseq.c.
@@ -2219,7 +2219,18 @@ impl Function {
22192219
match reduce_to_ccall(self, block, recv_type, send, insn_id) {
22202220
Ok(()) => continue,
22212221
Err(Some(cme)) => {
2222-
self.push_insn(block, Insn::CountUnoptimizedCFunc { cme });
2222+
// Extract class and method from CME to build signature
2223+
let class = unsafe { (*cme).owner };
2224+
let method = unsafe { (*cme).called_id };
2225+
2226+
let class_name = get_class_name(class);
2227+
let method_name = method.contents_lossy();
2228+
let signature = format!("{}#{}", class_name, method_name);
2229+
2230+
// Get or create counter pointer for this signature
2231+
let counter_ptr = get_or_create_unoptimized_cfunc_counter_ptr(signature.clone());
2232+
2233+
self.push_insn(block, Insn::CountUnoptimizedCFunc { signature, counter_ptr });
22232234
}
22242235
_ => {}
22252236
}
@@ -8088,7 +8099,7 @@ mod opt_tests {
80888099
bb0(v0:BasicObject):
80898100
v4:Fixnum[1] = Const Value(1)
80908101
v5:Fixnum[0] = Const Value(0)
8091-
CountUnoptimizedCFunc
8102+
CountUnoptimizedCFunc Unknown#itself
80928103
v7:BasicObject = SendWithoutBlock v4, :itself, v5
80938104
CheckInterrupts
80948105
Return v7
@@ -8726,7 +8737,7 @@ mod opt_tests {
87268737
fn test@<compiled>:2:
87278738
bb0(v0:BasicObject):
87288739
v5:HashExact = NewHash
8729-
CountUnoptimizedCFunc
8740+
CountUnoptimizedCFunc Unknown#dup
87308741
v7:BasicObject = SendWithoutBlock v5, :dup
87318742
v9:BasicObject = SendWithoutBlock v7, :freeze
87328743
CheckInterrupts
@@ -8744,7 +8755,7 @@ mod opt_tests {
87448755
bb0(v0:BasicObject):
87458756
v5:HashExact = NewHash
87468757
v6:NilClass = Const Value(nil)
8747-
CountUnoptimizedCFunc
8758+
CountUnoptimizedCFunc Hash#freeze
87488759
v8:BasicObject = SendWithoutBlock v5, :freeze, v6
87498760
CheckInterrupts
87508761
Return v8
@@ -8791,7 +8802,7 @@ mod opt_tests {
87918802
fn test@<compiled>:2:
87928803
bb0(v0:BasicObject):
87938804
v5:ArrayExact = NewArray
8794-
CountUnoptimizedCFunc
8805+
CountUnoptimizedCFunc Unknown#dup
87958806
v7:BasicObject = SendWithoutBlock v5, :dup
87968807
v9:BasicObject = SendWithoutBlock v7, :freeze
87978808
CheckInterrupts
@@ -8809,7 +8820,7 @@ mod opt_tests {
88098820
bb0(v0:BasicObject):
88108821
v5:ArrayExact = NewArray
88118822
v6:NilClass = Const Value(nil)
8812-
CountUnoptimizedCFunc
8823+
CountUnoptimizedCFunc Array#freeze
88138824
v8:BasicObject = SendWithoutBlock v5, :freeze, v6
88148825
CheckInterrupts
88158826
Return v8
@@ -8857,7 +8868,7 @@ mod opt_tests {
88578868
bb0(v0:BasicObject):
88588869
v4:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
88598870
v6:StringExact = StringCopy v4
8860-
CountUnoptimizedCFunc
8871+
CountUnoptimizedCFunc String#dup
88618872
v8:BasicObject = SendWithoutBlock v6, :dup
88628873
v10:BasicObject = SendWithoutBlock v8, :freeze
88638874
CheckInterrupts
@@ -8876,7 +8887,7 @@ mod opt_tests {
88768887
v4:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
88778888
v6:StringExact = StringCopy v4
88788889
v7:NilClass = Const Value(nil)
8879-
CountUnoptimizedCFunc
8890+
CountUnoptimizedCFunc String#freeze
88808891
v9:BasicObject = SendWithoutBlock v6, :freeze, v7
88818892
CheckInterrupts
88828893
Return v9
@@ -8924,7 +8935,7 @@ mod opt_tests {
89248935
bb0(v0:BasicObject):
89258936
v4:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
89268937
v6:StringExact = StringCopy v4
8927-
CountUnoptimizedCFunc
8938+
CountUnoptimizedCFunc String#dup
89288939
v8:BasicObject = SendWithoutBlock v6, :dup
89298940
v10:BasicObject = SendWithoutBlock v8, :-@
89308941
CheckInterrupts
@@ -9024,7 +9035,7 @@ mod opt_tests {
90249035
bb0(v0:BasicObject, v1:BasicObject):
90259036
v5:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
90269037
v17:BasicObject = GuardTypeNot v1, String
9027-
CountUnoptimizedCFunc
9038+
CountUnoptimizedCFunc Array#to_s
90289039
v18:BasicObject = SendWithoutBlock v1, :to_s
90299040
v9:String = AnyToString v1, str: v18
90309041
v11:StringExact = StringConcat v5, v9

zjit/src/stats.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -185,27 +185,21 @@ pub(crate) use incr_counter;
185185
/// The number of side exits from each YARV instruction
186186
pub type ExitCounters = [u64; VM_INSTRUCTION_SIZE as usize];
187187

188-
static SEND_FALLBACK_REASONS: LazyLock<Mutex<HashMap<String, u64>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
188+
/// Store signature ("Klass#method") to counter pointer mappings for unoptimized cfuncs
189+
pub static UNOPTIMIZED_CFUNC_COUNTER_POINTERS: LazyLock<Mutex<HashMap<String, Box<u64>>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
190+
191+
/// Get or create a counter pointer for the given signature
192+
pub fn get_or_create_unoptimized_cfunc_counter_ptr(signature: String) -> *mut u64 {
193+
let mut map = UNOPTIMIZED_CFUNC_COUNTER_POINTERS.lock().unwrap();
194+
let counter = map.entry(signature).or_insert_with(|| Box::new(0));
195+
&mut **counter as *mut u64
196+
}
189197

190198
#[unsafe(no_mangle)]
191-
pub extern "C" fn rb_zjit_count_unoptimized_cfunc(cme: *const rb_callable_method_entry_struct) {
192-
unsafe extern "C" {
193-
fn rb_class2name(klass: VALUE) -> *const std::ffi::c_char;
194-
fn rb_id2name(id: ID) -> *const std::ffi::c_char;
199+
pub extern "C" fn rb_zjit_count_unoptimized_cfunc(counter_ptr: *mut u64) {
200+
unsafe {
201+
*counter_ptr += 1;
195202
}
196-
197-
// Get class name and method name directly from cme
198-
let defined_class = unsafe { (*cme).defined_class };
199-
let called_id = unsafe { (*cme).called_id };
200-
201-
// Convert to C strings and then to Rust strings
202-
let class_str = unsafe { cstr_to_rust_string(rb_class2name(defined_class)) }.unwrap_or_else(|| "UnknownOwner".to_string());
203-
let method_str = unsafe { cstr_to_rust_string(rb_id2name(called_id)) }.unwrap_or_else(|| "UnknownMethod".to_string());
204-
205-
let reason_str = format!("{}#{}", class_str, method_str);
206-
207-
let mut map = SEND_FALLBACK_REASONS.lock().unwrap();
208-
*map.entry(reason_str).or_insert(0) += 1;
209203
}
210204

211205
/// Return a raw pointer to the exit counter for a given YARV opcode
@@ -395,11 +389,11 @@ pub extern "C" fn rb_zjit_stats(_ec: EcPtr, _self: VALUE, target_key: VALUE) ->
395389
set_stat_f64!(hash, "ratio_in_zjit", 100.0 * zjit_insn_count as f64 / total_insn_count as f64);
396390
}
397391

398-
// Set send fallback reasons
399-
let fallback_reasons = SEND_FALLBACK_REASONS.lock().unwrap();
400-
for (reason, count) in fallback_reasons.iter() {
401-
let key_string = "not_optimized_cfuncs".to_owned() + reason;
402-
set_stat_usize!(hash, &key_string, *count);
392+
// Set unoptimized cfunc counters
393+
let unoptimized_cfuncs = UNOPTIMIZED_CFUNC_COUNTER_POINTERS.lock().unwrap();
394+
for (signature, counter) in unoptimized_cfuncs.iter() {
395+
let key_string = format!("not_optimized_cfuncs_{}", signature);
396+
set_stat_usize!(hash, &key_string, **counter);
403397
}
404398

405399
hash

0 commit comments

Comments
 (0)