@@ -2943,61 +2943,34 @@ impl Function {
29432943 self . push_insn_id ( block, insn_id) ; continue ;
29442944 }
29452945 let mut ivar_index: u16 = 0 ;
2946+ let mut next_shape_id = recv_type. shape ( ) ;
29462947 if !unsafe { rb_shape_get_iv_index ( recv_type. shape ( ) . 0 , id, & mut ivar_index) } {
29472948 // Current shape does not contain this ivar; do a shape transition.
29482949 let current_shape_id = recv_type. shape ( ) ;
29492950 let class = recv_type. class ( ) ;
29502951 // We're only looking at T_OBJECT so ignore all of the imemo stuff.
29512952 assert ! ( recv_type. flags( ) . is_t_object( ) ) ;
2952- let next_shape_id = unsafe { rb_shape_transition_add_ivar_no_warnings ( class, current_shape_id. 0 , id) } ;
2953- let ivar_result = unsafe { rb_shape_get_iv_index ( next_shape_id, id, & mut ivar_index) } ;
2953+ next_shape_id = ShapeId ( unsafe { rb_shape_transition_add_ivar_no_warnings ( class, current_shape_id. 0 , id) } ) ;
2954+ let ivar_result = unsafe { rb_shape_get_iv_index ( next_shape_id. 0 , id, & mut ivar_index) } ;
29542955 assert ! ( ivar_result, "New shape must have the ivar index" ) ;
29552956 // If the VM ran out of shapes, or this class generated too many leaf,
29562957 // it may be de-optimized into OBJ_TOO_COMPLEX_SHAPE (hash-table).
2957- let new_shape_too_complex = unsafe { rb_jit_shape_too_complex_p ( next_shape_id) } ;
2958+ let new_shape_too_complex = unsafe { rb_jit_shape_too_complex_p ( next_shape_id. 0 ) } ;
29582959 // TODO(max): Is it OK to bail out here after making a shape transition?
29592960 if new_shape_too_complex {
2960- // TODO(max): Handle too-complex case
29612961 self . push_insn ( block, Insn :: IncrCounter ( Counter :: setivar_fallback_new_shape_too_complex) ) ;
29622962 self . push_insn_id ( block, insn_id) ; continue ;
29632963 }
29642964 let current_capacity = unsafe { rb_jit_shape_capacity ( current_shape_id. 0 ) } ;
2965- let next_capacity = unsafe { rb_jit_shape_capacity ( next_shape_id) } ;
2965+ let next_capacity = unsafe { rb_jit_shape_capacity ( next_shape_id. 0 ) } ;
29662966 // If the new shape has a different capacity, or is TOO_COMPLEX, we'll have to
29672967 // reallocate it.
29682968 let needs_extension = next_capacity != current_capacity;
29692969 if needs_extension {
2970- // TODO(max): Handle needs-extension case
29712970 self . push_insn ( block, Insn :: IncrCounter ( Counter :: setivar_fallback_new_shape_needs_extension) ) ;
29722971 self . push_insn_id ( block, insn_id) ; continue ;
29732972 }
2974-
2975-
2976- let self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : types:: HeapBasicObject , state } ) ;
2977- let self_val = self . push_insn ( block, Insn :: GuardShape { val : self_val, shape : recv_type. shape ( ) , state } ) ;
2978- let ( ivar_storage, offset) = if recv_type. flags ( ) . is_embedded ( ) {
2979- // See ROBJECT_FIELDS() from include/ruby/internal/core/robject.h
2980- let offset = ROBJECT_OFFSET_AS_ARY as i32 + ( SIZEOF_VALUE * ivar_index. to_usize ( ) ) as i32 ;
2981- ( self_val, offset)
2982- } else {
2983- let as_heap = self . push_insn ( block, Insn :: LoadField { recv : self_val, id : ID ! ( _as_heap) , offset : ROBJECT_OFFSET_AS_HEAP_FIELDS as i32 , return_type : types:: CPtr } ) ;
2984- let offset = SIZEOF_VALUE_I32 * ivar_index as i32 ;
2985- ( as_heap, offset)
2986- } ;
2987- self . push_insn ( block, Insn :: StoreField { recv : ivar_storage, id, offset, val } ) ;
2988- self . push_insn ( block, Insn :: WriteBarrier { recv : self_val, val } ) ;
2989- // Write the new shape ID
2990- assert_eq ! ( SHAPE_ID_NUM_BITS , 32 ) ;
2991- let shape_id = self . push_insn ( block, Insn :: Const { val : Const :: CUInt32 ( next_shape_id) } ) ;
2992- let shape_id_offset = unsafe { rb_shape_id_offset ( ) } ;
2993- self . push_insn ( block, Insn :: StoreField { recv : self_val, id : ID ! ( _shape_id) , offset : shape_id_offset, val : shape_id } ) ;
2994- continue ;
2995-
2996-
2997-
2998- // // TODO(max): Shape transition
2999- // self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_shape_transition));
3000- // self.push_insn_id(block, insn_id); continue;
2973+ // Fall through to emitting the ivar write
30012974 }
30022975 let self_val = self . push_insn ( block, Insn :: GuardType { val : self_val, guard_type : types:: HeapBasicObject , state } ) ;
30032976 let self_val = self . push_insn ( block, Insn :: GuardShape { val : self_val, shape : recv_type. shape ( ) , state } ) ;
@@ -3011,9 +2984,15 @@ impl Function {
30112984 let offset = SIZEOF_VALUE_I32 * ivar_index as i32 ;
30122985 ( as_heap, offset)
30132986 } ;
3014- let replacement = self . push_insn ( block, Insn :: StoreField { recv : ivar_storage, id, offset, val } ) ;
2987+ self . push_insn ( block, Insn :: StoreField { recv : ivar_storage, id, offset, val } ) ;
30152988 self . push_insn ( block, Insn :: WriteBarrier { recv : self_val, val } ) ;
3016- self . make_equal_to ( insn_id, replacement) ;
2989+ if next_shape_id != recv_type. shape ( ) {
2990+ // Write the new shape ID
2991+ assert_eq ! ( SHAPE_ID_NUM_BITS , 32 ) ;
2992+ let shape_id = self . push_insn ( block, Insn :: Const { val : Const :: CUInt32 ( next_shape_id. 0 ) } ) ;
2993+ let shape_id_offset = unsafe { rb_shape_id_offset ( ) } ;
2994+ self . push_insn ( block, Insn :: StoreField { recv : self_val, id : ID ! ( _shape_id) , offset : shape_id_offset, val : shape_id } ) ;
2995+ }
30172996 }
30182997 _ => { self . push_insn_id ( block, insn_id) ; }
30192998 }
0 commit comments