Skip to content

Commit 28c3582

Browse files
committed
ZJIT: Add Emitter::fallback to combine counter+keep pattern
1 parent 61498f3 commit 28c3582

1 file changed

Lines changed: 20 additions & 28 deletions

File tree

zjit/src/hir.rs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,6 +2447,12 @@ impl<'a> Emitter<'a> {
24472447
self.fun.make_equal_to(old, existing);
24482448
}
24492449

2450+
/// Count a fallback reason and keep the original instruction unchanged.
2451+
fn fallback(&mut self, insn_id: InsnId, counter: Counter) {
2452+
self.push_insn(Insn::IncrCounter(counter));
2453+
self.keep(insn_id);
2454+
}
2455+
24502456
/// Drop an instruction from the block entirely. Use for side-effect-free
24512457
/// instructions that are dead (e.g. a branch whose condition is statically
24522458
/// known to never trigger).
@@ -4507,19 +4513,16 @@ impl Function {
45074513
let frame_state = ctx.frame_state(state);
45084514
let Some(recv_type) = ctx.profiled_type_of_at(self_val, frame_state.insn_idx) else {
45094515
// No (monomorphic/skewed polymorphic) profile info
4510-
ctx.push_insn(Insn::IncrCounter(Counter::getivar_fallback_not_monomorphic));
4511-
ctx.keep(insn_id); continue;
4516+
ctx.fallback(insn_id, Counter::getivar_fallback_not_monomorphic); continue;
45124517
};
45134518
if recv_type.flags().is_immediate() {
45144519
// Instance variable lookups on immediate values are always nil
4515-
ctx.push_insn(Insn::IncrCounter(Counter::getivar_fallback_immediate));
4516-
ctx.keep(insn_id); continue;
4520+
ctx.fallback(insn_id, Counter::getivar_fallback_immediate); continue;
45174521
}
45184522
assert!(recv_type.shape().is_valid());
45194523
if recv_type.shape().is_too_complex() {
45204524
// too-complex shapes can't use index access
4521-
ctx.push_insn(Insn::IncrCounter(Counter::getivar_fallback_too_complex));
4522-
ctx.keep(insn_id); continue;
4525+
ctx.fallback(insn_id, Counter::getivar_fallback_too_complex); continue;
45234526
}
45244527
let self_val = ctx.push_insn(Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state });
45254528
let shape = ctx.load_shape(self_val);
@@ -4625,24 +4628,20 @@ impl Function {
46254628
let frame_state = ctx.frame_state(state);
46264629
let Some(recv_type) = ctx.profiled_type_of_at(self_val, frame_state.insn_idx) else {
46274630
// No (monomorphic/skewed polymorphic) profile info
4628-
ctx.push_insn(Insn::IncrCounter(Counter::definedivar_fallback_not_monomorphic));
4629-
ctx.keep(insn_id); continue;
4631+
ctx.fallback(insn_id, Counter::definedivar_fallback_not_monomorphic); continue;
46304632
};
46314633
if recv_type.flags().is_immediate() {
46324634
// Instance variable lookups on immediate values are always nil
4633-
ctx.push_insn(Insn::IncrCounter(Counter::definedivar_fallback_immediate));
4634-
ctx.keep(insn_id); continue;
4635+
ctx.fallback(insn_id, Counter::definedivar_fallback_immediate); continue;
46354636
}
46364637
assert!(recv_type.shape().is_valid());
46374638
if !recv_type.flags().is_t_object() {
46384639
// Check if the receiver is a T_OBJECT
4639-
ctx.push_insn(Insn::IncrCounter(Counter::definedivar_fallback_not_t_object));
4640-
ctx.keep(insn_id); continue;
4640+
ctx.fallback(insn_id, Counter::definedivar_fallback_not_t_object); continue;
46414641
}
46424642
if recv_type.shape().is_too_complex() {
46434643
// too-complex shapes can't use index access
4644-
ctx.push_insn(Insn::IncrCounter(Counter::definedivar_fallback_too_complex));
4645-
ctx.keep(insn_id); continue;
4644+
ctx.fallback(insn_id, Counter::definedivar_fallback_too_complex); continue;
46464645
}
46474646
let self_val = ctx.push_insn(Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state });
46484647
let shape = ctx.load_shape(self_val);
@@ -4662,29 +4661,24 @@ impl Function {
46624661
let frame_state = ctx.frame_state(state);
46634662
let Some(recv_type) = ctx.profiled_type_of_at(self_val, frame_state.insn_idx) else {
46644663
// No (monomorphic/skewed polymorphic) profile info
4665-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_not_monomorphic));
4666-
ctx.keep(insn_id); continue;
4664+
ctx.fallback(insn_id, Counter::setivar_fallback_not_monomorphic); continue;
46674665
};
46684666
if recv_type.flags().is_immediate() {
46694667
// Instance variable lookups on immediate values are always nil
4670-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_immediate));
4671-
ctx.keep(insn_id); continue;
4668+
ctx.fallback(insn_id, Counter::setivar_fallback_immediate); continue;
46724669
}
46734670
assert!(recv_type.shape().is_valid());
46744671
if !recv_type.flags().is_t_object() {
46754672
// Check if the receiver is a T_OBJECT
4676-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_not_t_object));
4677-
ctx.keep(insn_id); continue;
4673+
ctx.fallback(insn_id, Counter::setivar_fallback_not_t_object); continue;
46784674
}
46794675
if recv_type.shape().is_too_complex() {
46804676
// too-complex shapes can't use index access
4681-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_too_complex));
4682-
ctx.keep(insn_id); continue;
4677+
ctx.fallback(insn_id, Counter::setivar_fallback_too_complex); continue;
46834678
}
46844679
if recv_type.shape().is_frozen() {
46854680
// Can't set ivars on frozen objects
4686-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_frozen));
4687-
ctx.keep(insn_id); continue;
4681+
ctx.fallback(insn_id, Counter::setivar_fallback_frozen); continue;
46884682
}
46894683
let mut ivar_index: u16 = 0;
46904684
let mut next_shape_id = recv_type.shape();
@@ -4700,8 +4694,7 @@ impl Function {
47004694
let new_shape_too_complex = unsafe { rb_jit_shape_too_complex_p(next_shape_id.0) };
47014695
// TODO(max): Is it OK to bail out here after making a shape transition?
47024696
if new_shape_too_complex {
4703-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_new_shape_too_complex));
4704-
ctx.keep(insn_id); continue;
4697+
ctx.fallback(insn_id, Counter::setivar_fallback_new_shape_too_complex); continue;
47054698
}
47064699
let ivar_result = unsafe { rb_shape_get_iv_index(next_shape_id.0, id, &mut ivar_index) };
47074700
assert!(ivar_result, "New shape must have the ivar index");
@@ -4711,8 +4704,7 @@ impl Function {
47114704
// reallocate it.
47124705
let needs_extension = next_capacity != current_capacity;
47134706
if needs_extension {
4714-
ctx.push_insn(Insn::IncrCounter(Counter::setivar_fallback_new_shape_needs_extension));
4715-
ctx.keep(insn_id); continue;
4707+
ctx.fallback(insn_id, Counter::setivar_fallback_new_shape_needs_extension); continue;
47164708
}
47174709
// Fall through to emitting the ivar write
47184710
}

0 commit comments

Comments
 (0)