@@ -491,7 +491,7 @@ pub enum SideExitReason {
491491 GuardType ( Type ) ,
492492 GuardTypeNot ( Type ) ,
493493 GuardShape ( ShapeId ) ,
494- GuardBitEquals ( Const ) ,
494+ ExpandArray ,
495495 GuardNotFrozen ,
496496 GuardNotShared ,
497497 GuardLess ,
@@ -580,7 +580,6 @@ impl std::fmt::Display for SideExitReason {
580580 SideExitReason :: UnhandledDuparraySend ( method_id) => write ! ( f, "UnhandledDuparraySend({method_id})" ) ,
581581 SideExitReason :: GuardType ( guard_type) => write ! ( f, "GuardType({guard_type})" ) ,
582582 SideExitReason :: GuardTypeNot ( guard_type) => write ! ( f, "GuardTypeNot({guard_type})" ) ,
583- SideExitReason :: GuardBitEquals ( value) => write ! ( f, "GuardBitEquals({})" , value. print( & PtrPrintMap :: identity( ) ) ) ,
584583 SideExitReason :: GuardNotShared => write ! ( f, "GuardNotShared" ) ,
585584 SideExitReason :: PatchPoint ( invariant) => write ! ( f, "PatchPoint({invariant})" ) ,
586585 _ => write ! ( f, "{self:?}" ) ,
@@ -954,7 +953,7 @@ pub enum Insn {
954953 GuardType { val : InsnId , guard_type : Type , state : InsnId } ,
955954 GuardTypeNot { val : InsnId , guard_type : Type , state : InsnId } ,
956955 /// Side-exit if val is not the expected Const.
957- GuardBitEquals { val : InsnId , expected : Const , state : InsnId } ,
956+ GuardBitEquals { val : InsnId , expected : Const , reason : SideExitReason , state : InsnId } ,
958957 /// Side-exit if val doesn't have the expected shape.
959958 GuardShape { val : InsnId , shape : ShapeId , state : InsnId } ,
960959 /// Side-exit if the block param has been modified or the block handler for the frame
@@ -1975,7 +1974,7 @@ impl Function {
19751974 & IfFalse { val, ref target } => IfFalse { val : find ! ( val) , target : find_branch_edge ! ( target) } ,
19761975 & GuardType { val, guard_type, state } => GuardType { val : find ! ( val) , guard_type, state } ,
19771976 & GuardTypeNot { val, guard_type, state } => GuardTypeNot { val : find ! ( val) , guard_type, state } ,
1978- & GuardBitEquals { val, expected, state } => GuardBitEquals { val : find ! ( val) , expected, state } ,
1977+ & GuardBitEquals { val, expected, reason , state } => GuardBitEquals { val : find ! ( val) , expected, reason , state } ,
19791978 & GuardShape { val, shape, state } => GuardShape { val : find ! ( val) , shape, state } ,
19801979 & GuardBlockParamProxy { level, state } => GuardBlockParamProxy { level, state : find ! ( state) } ,
19811980 & GuardNotFrozen { recv, state } => GuardNotFrozen { recv : find ! ( recv) , state } ,
@@ -3078,6 +3077,15 @@ impl Function {
30783077 } )
30793078 }
30803079
3080+ fn guard_shape ( & mut self , block : BlockId , val : InsnId , expected : ShapeId , state : InsnId ) -> InsnId {
3081+ self . push_insn ( block, Insn :: GuardBitEquals {
3082+ val,
3083+ expected : Const :: CShape ( expected) ,
3084+ reason : SideExitReason :: GuardShape ( expected) ,
3085+ state
3086+ } )
3087+ }
3088+
30813089 fn optimize_getivar ( & mut self ) {
30823090 for block in self . rpo ( ) {
30833091 let old_insns = std:: mem:: take ( & mut self . blocks [ block. 0 ] . insns ) ;
@@ -3104,7 +3112,7 @@ impl Function {
31043112 }
31053113 let self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : types:: HeapBasicObject , state } ) ;
31063114 let shape = self . load_shape ( block, self_val) ;
3107- self . push_insn ( block, Insn :: GuardBitEquals { val : shape, expected : Const :: CShape ( recv_type. shape ( ) ) , state } ) ;
3115+ self . guard_shape ( block, shape, recv_type. shape ( ) , state) ;
31083116 let mut ivar_index: u16 = 0 ;
31093117 let replacement = if ! unsafe { rb_shape_get_iv_index ( recv_type. shape ( ) . 0 , id, & mut ivar_index) } {
31103118 // If there is no IVAR index, then the ivar was undefined when we
@@ -3159,7 +3167,7 @@ impl Function {
31593167 }
31603168 let self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : types:: HeapBasicObject , state } ) ;
31613169 let shape = self . load_shape ( block, self_val) ;
3162- self . push_insn ( block, Insn :: GuardBitEquals { val : shape, expected : Const :: CShape ( recv_type. shape ( ) ) , state } ) ;
3170+ self . guard_shape ( block, shape, recv_type. shape ( ) , state) ;
31633171 let mut ivar_index: u16 = 0 ;
31643172 let replacement = if unsafe { rb_shape_get_iv_index ( recv_type. shape ( ) . 0 , id, & mut ivar_index) } {
31653173 self . push_insn ( block, Insn :: Const { val : Const :: Value ( pushval) } )
@@ -3231,7 +3239,7 @@ impl Function {
32313239 }
32323240 let self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : types:: HeapBasicObject , state } ) ;
32333241 let shape = self . load_shape ( block, self_val) ;
3234- self . push_insn ( block, Insn :: GuardBitEquals { val : shape, expected : Const :: CShape ( recv_type. shape ( ) ) , state } ) ;
3242+ self . guard_shape ( block, shape, recv_type. shape ( ) , state) ;
32353243 // Current shape contains this ivar
32363244 let ( ivar_storage, offset) = if recv_type. flags ( ) . is_embedded ( ) {
32373245 // See ROBJECT_FIELDS() from include/ruby/internal/core/robject.h
@@ -6273,7 +6281,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
62736281 let val = state. stack_pop ( ) ?;
62746282 let array = fun. push_insn ( block, Insn :: GuardType { val, guard_type : types:: ArrayExact , state : exit_id, } ) ;
62756283 let length = fun. push_insn ( block, Insn :: ArrayLength { array } ) ;
6276- fun. push_insn ( block, Insn :: GuardBitEquals { val : length, expected : Const :: CInt64 ( num as i64 ) , state : exit_id } ) ;
6284+ fun. push_insn ( block, Insn :: GuardBitEquals { val : length, expected : Const :: CInt64 ( num as i64 ) , reason : SideExitReason :: ExpandArray , state : exit_id } ) ;
62776285 for i in ( 0 ..num) . rev ( ) {
62786286 // TODO(max): Add a short-cut path for long indices into an array where the
62796287 // index is known to be in-bounds
0 commit comments