Skip to content

Commit 3a62d4f

Browse files
committed
ZJIT: Update state to count full frame cfunc calls
1 parent 6e21f26 commit 3a62d4f

4 files changed

Lines changed: 38 additions & 36 deletions

File tree

zjit.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ def stats_string
158158
print_counters_with_prefix(prefix: 'unspecialized_def_type_', prompt: 'not optimized method types', buf:, stats:, limit: 20)
159159
print_counters_with_prefix(prefix: 'not_optimized_yarv_insn_', prompt: 'not optimized instructions', buf:, stats:, limit: 20)
160160
print_counters_with_prefix(prefix: 'send_fallback_', prompt: 'send fallback reasons', buf:, stats:, limit: 20)
161+
print_counters_with_prefix(prefix: 'full_frame_cfuncs_', prompt: 'full frame C function calls', buf:, stats:, limit: 20)
161162

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

zjit/src/hir.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,9 +2266,9 @@ impl Function {
22662266
self_type: Type,
22672267
send: Insn,
22682268
send_insn_id: InsnId,
2269-
) -> Result<(), Option<*const rb_callable_method_entry_struct>> {
2269+
) -> Result<(), ()> {
22702270
let Insn::SendWithoutBlock { mut recv, cd, mut args, state, .. } = send else {
2271-
return Err(None);
2271+
return Err(());
22722272
};
22732273

22742274
let call_info = unsafe { (*cd).ci };
@@ -2280,20 +2280,20 @@ impl Function {
22802280
(class, None)
22812281
} else {
22822282
let iseq_insn_idx = fun.frame_state(state).insn_idx;
2283-
let Some(recv_type) = fun.profiled_type_of_at(recv, iseq_insn_idx) else { return Err(None) };
2283+
let Some(recv_type) = fun.profiled_type_of_at(recv, iseq_insn_idx) else { return Err(()) };
22842284
(recv_type.class(), Some(recv_type))
22852285
};
22862286

22872287
// Do method lookup
22882288
let method: *const rb_callable_method_entry_struct = unsafe { rb_callable_method_entry(recv_class, method_id) };
22892289
if method.is_null() {
2290-
return Err(None);
2290+
return Err(());
22912291
}
22922292

22932293
// Filter for C methods
22942294
let def_type = unsafe { get_cme_def_type(method) };
22952295
if def_type != VM_METHOD_TYPE_CFUNC {
2296-
return Err(None);
2296+
return Err(());
22972297
}
22982298

22992299
// Find the `argc` (arity) of the C method, which describes the parameters it expects
@@ -2305,13 +2305,13 @@ impl Function {
23052305
//
23062306
// Bail on argc mismatch
23072307
if argc != cfunc_argc as u32 {
2308-
return Err(Some(method));
2308+
return Err(());
23092309
}
23102310

23112311
let ci_flags = unsafe { vm_ci_flag(call_info) };
23122312

23132313
if ci_flags & VM_CALL_ARGS_SIMPLE == 0 {
2314-
return Err(Some(method));
2314+
return Err(());
23152315
}
23162316

23172317
gen_patch_points_for_optimized_ccall(fun, block, recv_class, method_id, method, state);
@@ -2334,6 +2334,9 @@ impl Function {
23342334
let ccall = fun.push_insn(block, Insn::CCall { cfun, args: cfunc_args, name: method_id, return_type, elidable });
23352335
fun.make_equal_to(send_insn_id, ccall);
23362336
} else {
2337+
if get_option!(stats) {
2338+
count_full_frame_cfunc(fun, block, method);
2339+
}
23372340
let ccall = fun.push_insn(block, Insn::CallCFunc { cfun, args: cfunc_args, cme: method, name: method_id, state });
23382341
fun.make_equal_to(send_insn_id, ccall);
23392342
}
@@ -2343,7 +2346,7 @@ impl Function {
23432346
// Variadic method
23442347
-1 => {
23452348
if unsafe { rb_zjit_method_tracing_currently_enabled() } {
2346-
return Err(None);
2349+
return Err(());
23472350
}
23482351
// The method gets a pointer to the first argument
23492352
// func(int argc, VALUE *argv, VALUE recv)
@@ -2383,7 +2386,20 @@ impl Function {
23832386
_ => unreachable!("unknown cfunc kind: argc={argc}")
23842387
}
23852388

2386-
Err(Some(method))
2389+
Err(())
2390+
}
2391+
2392+
fn count_full_frame_cfunc(fun: &mut Function, block: BlockId, cme: *const rb_callable_method_entry_t) {
2393+
let owner = unsafe { (*cme).owner };
2394+
let called_id = unsafe { (*cme).called_id };
2395+
let class_name = get_class_name(owner);
2396+
let method_name = called_id.contents_lossy();
2397+
let qualified_method_name = format!("{}#{}", class_name, method_name);
2398+
let full_frame_cfunc_counter_pointers = ZJITState::get_full_frame_cfunc_counter_pointers();
2399+
let counter_ptr = full_frame_cfunc_counter_pointers.entry(qualified_method_name.clone()).or_insert_with(|| Box::new(0));
2400+
let counter_ptr = &mut **counter_ptr as *mut u64;
2401+
2402+
fun.push_insn(block, Insn::IncrCounterPtr { counter_ptr });
23872403
}
23882404

23892405
for block in self.rpo() {
@@ -2392,23 +2408,8 @@ impl Function {
23922408
for insn_id in old_insns {
23932409
if let send @ Insn::SendWithoutBlock { recv, .. } = self.find(insn_id) {
23942410
let recv_type = self.type_of(recv);
2395-
match reduce_to_ccall(self, block, recv_type, send, insn_id) {
2396-
Ok(()) => continue,
2397-
Err(Some(cme)) => {
2398-
if get_option!(stats) {
2399-
let owner = unsafe { (*cme).owner };
2400-
let called_id = unsafe { (*cme).called_id };
2401-
let class_name = get_class_name(owner);
2402-
let method_name = called_id.contents_lossy();
2403-
let qualified_method_name = format!("{}#{}", class_name, method_name);
2404-
let unoptimized_cfunc_counter_pointers = ZJITState::get_unoptimized_cfunc_counter_pointers();
2405-
let counter_ptr = unoptimized_cfunc_counter_pointers.entry(qualified_method_name.clone()).or_insert_with(|| Box::new(0));
2406-
let counter_ptr = &mut **counter_ptr as *mut u64;
2407-
2408-
self.push_insn(block, Insn::IncrCounterPtr { counter_ptr });
2409-
}
2410-
}
2411-
_ => {}
2411+
if reduce_to_ccall(self, block, recv_type, send, insn_id).is_ok() {
2412+
continue;
24122413
}
24132414
}
24142415
self.push_insn_id(block, insn_id);

zjit/src/state.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ pub struct ZJITState {
5151
/// Trampoline to call function_stub_hit
5252
function_stub_hit_trampoline: CodePtr,
5353

54-
/// Counter pointers for unoptimized C functions
55-
unoptimized_cfunc_counter_pointers: HashMap<String, Box<u64>>,
54+
/// Counter pointers for full frame C functions
55+
full_frame_cfunc_counter_pointers: HashMap<String, Box<u64>>,
5656

5757
/// Locations of side exists within generated code
5858
exit_locations: Option<SideExitLocations>,
@@ -97,7 +97,7 @@ impl ZJITState {
9797
exit_trampoline,
9898
function_stub_hit_trampoline,
9999
exit_trampoline_with_counter: exit_trampoline,
100-
unoptimized_cfunc_counter_pointers: HashMap::new(),
100+
full_frame_cfunc_counter_pointers: HashMap::new(),
101101
exit_locations,
102102
};
103103
unsafe { ZJIT_STATE = Some(zjit_state); }
@@ -162,9 +162,9 @@ impl ZJITState {
162162
&mut ZJITState::get_instance().send_fallback_counters
163163
}
164164

165-
/// Get a mutable reference to unoptimized cfunc counter pointers
166-
pub fn get_unoptimized_cfunc_counter_pointers() -> &'static mut HashMap<String, Box<u64>> {
167-
&mut ZJITState::get_instance().unoptimized_cfunc_counter_pointers
165+
/// Get a mutable reference to full frame cfunc counter pointers
166+
pub fn get_full_frame_cfunc_counter_pointers() -> &'static mut HashMap<String, Box<u64>> {
167+
&mut ZJITState::get_instance().full_frame_cfunc_counter_pointers
168168
}
169169

170170
/// Was --zjit-save-compiled-iseqs specified?

zjit/src/stats.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -470,10 +470,10 @@ pub extern "C" fn rb_zjit_stats(_ec: EcPtr, _self: VALUE, target_key: VALUE) ->
470470
set_stat_f64!(hash, "ratio_in_zjit", 100.0 * zjit_insn_count as f64 / total_insn_count as f64);
471471
}
472472

473-
// Set unoptimized cfunc counters
474-
let unoptimized_cfuncs = ZJITState::get_unoptimized_cfunc_counter_pointers();
475-
for (signature, counter) in unoptimized_cfuncs.iter() {
476-
let key_string = format!("not_optimized_cfuncs_{}", signature);
473+
// Set full frame cfunc counters
474+
let full_frame_cfuncs = ZJITState::get_full_frame_cfunc_counter_pointers();
475+
for (signature, counter) in full_frame_cfuncs.iter() {
476+
let key_string = format!("full_frame_cfuncs_{}", signature);
477477
set_stat_usize!(hash, &key_string, **counter);
478478
}
479479

0 commit comments

Comments
 (0)