@@ -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