Skip to content

Commit db94a79

Browse files
authored
ZJIT: Count fallback reasons for set/get/definedivar (ruby#15324)
lobsters: ``` Top-4 setivar fallback reasons (100.0% of total 7,789,008): shape_transition: 6,074,085 (78.0%) not_monomorphic: 1,484,013 (19.1%) not_t_object: 172,629 ( 2.2%) too_complex: 58,281 ( 0.7%) Top-3 getivar fallback reasons (100.0% of total 9,348,832): not_t_object: 4,658,833 (49.8%) not_monomorphic: 4,542,316 (48.6%) too_complex: 147,683 ( 1.6%) Top-3 definedivar fallback reasons (100.0% of total 366,383): not_monomorphic: 361,389 (98.6%) too_complex: 3,062 ( 0.8%) not_t_object: 1,932 ( 0.5%) ``` railsbench: ``` Top-3 setivar fallback reasons (100.0% of total 15,119,057): shape_transition: 13,760,763 (91.0%) not_monomorphic: 982,368 ( 6.5%) not_t_object: 375,926 ( 2.5%) Top-2 getivar fallback reasons (100.0% of total 14,438,747): not_t_object: 7,643,870 (52.9%) not_monomorphic: 6,794,877 (47.1%) Top-2 definedivar fallback reasons (100.0% of total 209,613): not_monomorphic: 209,526 (100.0%) not_t_object: 87 ( 0.0%) ``` shipit: ``` Top-3 setivar fallback reasons (100.0% of total 14,516,254): shape_transition: 8,613,512 (59.3%) not_monomorphic: 5,761,398 (39.7%) not_t_object: 141,344 ( 1.0%) Top-2 getivar fallback reasons (100.0% of total 21,016,444): not_monomorphic: 11,313,482 (53.8%) not_t_object: 9,702,962 (46.2%) Top-2 definedivar fallback reasons (100.0% of total 290,382): not_monomorphic: 287,755 (99.1%) not_t_object: 2,627 ( 0.9%) ```
1 parent 52426a2 commit db94a79

File tree

5 files changed

+128
-11
lines changed

5 files changed

+128
-11
lines changed

zjit.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ def stats_string
183183
print_counters_with_prefix(prefix: 'unspecialized_send_without_block_def_type_', prompt: 'not optimized method types for send_without_block', buf:, stats:, limit: 20)
184184
print_counters_with_prefix(prefix: 'uncategorized_fallback_yarv_insn_', prompt: 'instructions with uncategorized fallback reason', buf:, stats:, limit: 20)
185185
print_counters_with_prefix(prefix: 'send_fallback_', prompt: 'send fallback reasons', buf:, stats:, limit: 20)
186+
print_counters_with_prefix(prefix: 'setivar_fallback_', prompt: 'setivar fallback reasons', buf:, stats:, limit: 5)
187+
print_counters_with_prefix(prefix: 'getivar_fallback_', prompt: 'getivar fallback reasons', buf:, stats:, limit: 5)
188+
print_counters_with_prefix(prefix: 'definedivar_fallback_', prompt: 'definedivar fallback reasons', buf:, stats:, limit: 5)
186189
print_counters_with_prefix(prefix: 'invokeblock_handler_', prompt: 'invokeblock handler', buf:, stats:, limit: 10)
187190

188191
# Show most popular unsupported call features. Because each call can
@@ -201,16 +204,16 @@ def stats_string
201204
:send_count,
202205
:dynamic_send_count,
203206
:optimized_send_count,
207+
:dynamic_setivar_count,
208+
:dynamic_getivar_count,
209+
:dynamic_definedivar_count,
204210
:iseq_optimized_send_count,
205211
:inline_cfunc_optimized_send_count,
206212
:inline_iseq_optimized_send_count,
207213
:non_variadic_cfunc_optimized_send_count,
208214
:variadic_cfunc_optimized_send_count,
209215
], buf:, stats:, right_align: true, base: :send_count)
210216
print_counters([
211-
:dynamic_getivar_count,
212-
:dynamic_setivar_count,
213-
214217
:compiled_iseq_count,
215218
:failed_iseq_count,
216219

zjit/src/codegen.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,6 @@ fn gen_ccall_variadic(
892892

893893
/// Emit an uncached instance variable lookup
894894
fn gen_getivar(jit: &mut JITState, asm: &mut Assembler, recv: Opnd, id: ID, ic: *const iseq_inline_iv_cache_entry) -> Opnd {
895-
gen_incr_counter(asm, Counter::dynamic_getivar_count);
896895
if ic.is_null() {
897896
asm_ccall!(asm, rb_ivar_get, recv, id.0.into())
898897
} else {
@@ -903,7 +902,6 @@ fn gen_getivar(jit: &mut JITState, asm: &mut Assembler, recv: Opnd, id: ID, ic:
903902

904903
/// Emit an uncached instance variable store
905904
fn gen_setivar(jit: &mut JITState, asm: &mut Assembler, recv: Opnd, id: ID, ic: *const iseq_inline_iv_cache_entry, val: Opnd, state: &FrameState) {
906-
gen_incr_counter(asm, Counter::dynamic_setivar_count);
907905
// Setting an ivar can raise FrozenError, so we need proper frame state for exception handling.
908906
gen_prepare_non_leaf_call(jit, asm, state);
909907
if ic.is_null() {

zjit/src/hir.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,19 +2806,23 @@ impl Function {
28062806
let frame_state = self.frame_state(state);
28072807
let Some(recv_type) = self.profiled_type_of_at(self_val, frame_state.insn_idx) else {
28082808
// No (monomorphic/skewed polymorphic) profile info
2809+
self.push_insn(block, Insn::IncrCounter(Counter::getivar_fallback_not_monomorphic));
28092810
self.push_insn_id(block, insn_id); continue;
28102811
};
28112812
if recv_type.flags().is_immediate() {
28122813
// Instance variable lookups on immediate values are always nil
2814+
self.push_insn(block, Insn::IncrCounter(Counter::getivar_fallback_immediate));
28132815
self.push_insn_id(block, insn_id); continue;
28142816
}
28152817
assert!(recv_type.shape().is_valid());
28162818
if !recv_type.flags().is_t_object() {
28172819
// Check if the receiver is a T_OBJECT
2820+
self.push_insn(block, Insn::IncrCounter(Counter::getivar_fallback_not_t_object));
28182821
self.push_insn_id(block, insn_id); continue;
28192822
}
28202823
if recv_type.shape().is_too_complex() {
28212824
// too-complex shapes can't use index access
2825+
self.push_insn(block, Insn::IncrCounter(Counter::getivar_fallback_too_complex));
28222826
self.push_insn_id(block, insn_id); continue;
28232827
}
28242828
let self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state });
@@ -2845,19 +2849,23 @@ impl Function {
28452849
let frame_state = self.frame_state(state);
28462850
let Some(recv_type) = self.profiled_type_of_at(self_val, frame_state.insn_idx) else {
28472851
// No (monomorphic/skewed polymorphic) profile info
2852+
self.push_insn(block, Insn::IncrCounter(Counter::definedivar_fallback_not_monomorphic));
28482853
self.push_insn_id(block, insn_id); continue;
28492854
};
28502855
if recv_type.flags().is_immediate() {
28512856
// Instance variable lookups on immediate values are always nil
2857+
self.push_insn(block, Insn::IncrCounter(Counter::definedivar_fallback_immediate));
28522858
self.push_insn_id(block, insn_id); continue;
28532859
}
28542860
assert!(recv_type.shape().is_valid());
28552861
if !recv_type.flags().is_t_object() {
28562862
// Check if the receiver is a T_OBJECT
2863+
self.push_insn(block, Insn::IncrCounter(Counter::definedivar_fallback_not_t_object));
28572864
self.push_insn_id(block, insn_id); continue;
28582865
}
28592866
if recv_type.shape().is_too_complex() {
28602867
// too-complex shapes can't use index access
2868+
self.push_insn(block, Insn::IncrCounter(Counter::definedivar_fallback_too_complex));
28612869
self.push_insn_id(block, insn_id); continue;
28622870
}
28632871
let self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state });
@@ -2877,28 +2885,34 @@ impl Function {
28772885
let frame_state = self.frame_state(state);
28782886
let Some(recv_type) = self.profiled_type_of_at(self_val, frame_state.insn_idx) else {
28792887
// No (monomorphic/skewed polymorphic) profile info
2888+
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_not_monomorphic));
28802889
self.push_insn_id(block, insn_id); continue;
28812890
};
28822891
if recv_type.flags().is_immediate() {
28832892
// Instance variable lookups on immediate values are always nil
2893+
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_immediate));
28842894
self.push_insn_id(block, insn_id); continue;
28852895
}
28862896
assert!(recv_type.shape().is_valid());
28872897
if !recv_type.flags().is_t_object() {
28882898
// Check if the receiver is a T_OBJECT
2899+
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_not_t_object));
28892900
self.push_insn_id(block, insn_id); continue;
28902901
}
28912902
if recv_type.shape().is_too_complex() {
28922903
// too-complex shapes can't use index access
2904+
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_too_complex));
28932905
self.push_insn_id(block, insn_id); continue;
28942906
}
28952907
if recv_type.shape().is_frozen() {
28962908
// Can't set ivars on frozen objects
2909+
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_frozen));
28972910
self.push_insn_id(block, insn_id); continue;
28982911
}
28992912
let mut ivar_index: u16 = 0;
29002913
if !unsafe { rb_shape_get_iv_index(recv_type.shape().0, id, &mut ivar_index) } {
29012914
// TODO(max): Shape transition
2915+
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_shape_transition));
29022916
self.push_insn_id(block, insn_id); continue;
29032917
}
29042918
let self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state });

zjit/src/hir/opt_tests.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3343,6 +3343,7 @@ mod hir_opt_tests {
33433343
Jump bb2(v4)
33443344
bb2(v6:BasicObject):
33453345
PatchPoint SingleRactorMode
3346+
IncrCounter getivar_fallback_not_monomorphic
33463347
v11:BasicObject = GetIvar v6, :@foo
33473348
CheckInterrupts
33483349
Return v11
@@ -3366,6 +3367,7 @@ mod hir_opt_tests {
33663367
bb2(v6:BasicObject):
33673368
v10:Fixnum[1] = Const Value(1)
33683369
PatchPoint SingleRactorMode
3370+
IncrCounter setivar_fallback_not_monomorphic
33693371
SetIvar v6, :@foo, v10
33703372
CheckInterrupts
33713373
Return v10
@@ -3442,6 +3444,7 @@ mod hir_opt_tests {
34423444
EntryPoint JIT(0)
34433445
Jump bb2(v4)
34443446
bb2(v6:BasicObject):
3447+
IncrCounter definedivar_fallback_not_t_object
34453448
v10:StringExact|NilClass = DefinedIvar v6, :@a
34463449
CheckInterrupts
34473450
Return v10
@@ -3473,6 +3476,7 @@ mod hir_opt_tests {
34733476
EntryPoint JIT(0)
34743477
Jump bb2(v4)
34753478
bb2(v6:BasicObject):
3479+
IncrCounter definedivar_fallback_not_monomorphic
34763480
v10:StringExact|NilClass = DefinedIvar v6, :@a
34773481
CheckInterrupts
34783482
Return v10
@@ -3525,6 +3529,7 @@ mod hir_opt_tests {
35253529
bb2(v6:BasicObject):
35263530
v10:Fixnum[5] = Const Value(5)
35273531
PatchPoint SingleRactorMode
3532+
IncrCounter setivar_fallback_shape_transition
35283533
SetIvar v6, :@foo, v10
35293534
CheckInterrupts
35303535
Return v10
@@ -3554,6 +3559,7 @@ mod hir_opt_tests {
35543559
bb2(v6:BasicObject):
35553560
v10:Fixnum[5] = Const Value(5)
35563561
PatchPoint SingleRactorMode
3562+
IncrCounter setivar_fallback_not_t_object
35573563
SetIvar v6, :@a, v10
35583564
CheckInterrupts
35593565
Return v10
@@ -3587,6 +3593,7 @@ mod hir_opt_tests {
35873593
bb2(v6:BasicObject):
35883594
v10:Fixnum[5] = Const Value(5)
35893595
PatchPoint SingleRactorMode
3596+
IncrCounter setivar_fallback_not_monomorphic
35903597
SetIvar v6, :@a, v10
35913598
CheckInterrupts
35923599
Return v10
@@ -3618,6 +3625,7 @@ mod hir_opt_tests {
36183625
bb2(v6:BasicObject):
36193626
v10:Fixnum[5] = Const Value(5)
36203627
PatchPoint SingleRactorMode
3628+
IncrCounter setivar_fallback_shape_transition
36213629
SetIvar v6, :@a, v10
36223630
CheckInterrupts
36233631
Return v10
@@ -5527,6 +5535,7 @@ mod hir_opt_tests {
55275535
v16:Fixnum[5] = Const Value(5)
55285536
PatchPoint MethodRedefined(C@0x1000, foo=@0x1008, cme:0x1010)
55295537
v26:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C]
5538+
IncrCounter setivar_fallback_shape_transition
55305539
SetIvar v26, :@foo, v16
55315540
CheckInterrupts
55325541
Return v16
@@ -5558,6 +5567,7 @@ mod hir_opt_tests {
55585567
v16:Fixnum[5] = Const Value(5)
55595568
PatchPoint MethodRedefined(C@0x1000, foo=@0x1008, cme:0x1010)
55605569
v26:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C]
5570+
IncrCounter setivar_fallback_shape_transition
55615571
SetIvar v26, :@foo, v16
55625572
CheckInterrupts
55635573
Return v16
@@ -8609,17 +8619,18 @@ mod hir_opt_tests {
86098619
SetLocal l0, EP@3, v27
86108620
v39:BasicObject = GetLocal l0, EP@3
86118621
PatchPoint SingleRactorMode
8622+
IncrCounter setivar_fallback_shape_transition
86128623
SetIvar v14, :@formatted, v39
86138624
v45:Class[VMFrozenCore] = Const Value(VALUE(0x1000))
86148625
PatchPoint MethodRedefined(Class@0x1008, lambda@0x1010, cme:0x1018)
86158626
PatchPoint NoSingletonClass(Class@0x1008)
8616-
v59:BasicObject = CCallWithFrame RubyVM::FrozenCore.lambda@0x1040, v45, block=0x1048
8627+
v60:BasicObject = CCallWithFrame RubyVM::FrozenCore.lambda@0x1040, v45, block=0x1048
86178628
v48:BasicObject = GetLocal l0, EP@6
86188629
v49:BasicObject = GetLocal l0, EP@5
86198630
v50:BasicObject = GetLocal l0, EP@4
86208631
v51:BasicObject = GetLocal l0, EP@3
86218632
CheckInterrupts
8622-
Return v59
8633+
Return v60
86238634
");
86248635
}
86258636
}

0 commit comments

Comments
 (0)