@@ -1270,6 +1270,7 @@ rb_free_generic_ivar(VALUE obj)
12701270 xfree (fields_tbl );
12711271 }
12721272 }
1273+ FL_UNSET_RAW (obj , FL_EXIVAR );
12731274}
12741275
12751276size_t
@@ -1542,23 +1543,30 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
15421543
15431544 RUBY_ASSERT (removed_shape_id != INVALID_SHAPE_ID );
15441545
1545- attr_index_t new_fields_count = RSHAPE_LEN (next_shape_id );
1546-
15471546 attr_index_t removed_index = RSHAPE_INDEX (removed_shape_id );
15481547 val = fields [removed_index ];
1549- size_t trailing_fields = new_fields_count - removed_index ;
15501548
1551- MEMMOVE (& fields [removed_index ], & fields [removed_index + 1 ], VALUE , trailing_fields );
1552-
1553- if (RB_TYPE_P (obj , T_OBJECT ) &&
1554- !RB_FL_TEST_RAW (obj , ROBJECT_EMBED ) &&
1555- rb_obj_embedded_size (new_fields_count ) <= rb_gc_obj_slot_size (obj )) {
1556- // Re-embed objects when instances become small enough
1557- // This is necessary because YJIT assumes that objects with the same shape
1558- // have the same embeddedness for efficiency (avoid extra checks)
1559- RB_FL_SET_RAW (obj , ROBJECT_EMBED );
1560- MEMCPY (ROBJECT_FIELDS (obj ), fields , VALUE , new_fields_count );
1561- xfree (fields );
1549+ attr_index_t new_fields_count = RSHAPE_LEN (next_shape_id );
1550+ if (new_fields_count ) {
1551+ size_t trailing_fields = new_fields_count - removed_index ;
1552+
1553+ MEMMOVE (& fields [removed_index ], & fields [removed_index + 1 ], VALUE , trailing_fields );
1554+
1555+ if (RB_TYPE_P (obj , T_OBJECT ) &&
1556+ !RB_FL_TEST_RAW (obj , ROBJECT_EMBED ) &&
1557+ rb_obj_embedded_size (new_fields_count ) <= rb_gc_obj_slot_size (obj )) {
1558+ // Re-embed objects when instances become small enough
1559+ // This is necessary because YJIT assumes that objects with the same shape
1560+ // have the same embeddedness for efficiency (avoid extra checks)
1561+ RB_FL_SET_RAW (obj , ROBJECT_EMBED );
1562+ MEMCPY (ROBJECT_FIELDS (obj ), fields , VALUE , new_fields_count );
1563+ xfree (fields );
1564+ }
1565+ }
1566+ else {
1567+ if (FL_TEST_RAW (obj , FL_EXIVAR )) {
1568+ rb_free_generic_ivar (obj );
1569+ }
15621570 }
15631571 rb_obj_set_shape_id (obj , next_shape_id );
15641572
@@ -1881,8 +1889,8 @@ generic_ivar_set_set_shape_id(VALUE obj, shape_id_t shape_id, void *data)
18811889static shape_id_t
18821890generic_ivar_set_transition_too_complex (VALUE obj , void * _data )
18831891{
1884- shape_id_t new_shape_id = rb_evict_fields_to_hash (obj );
18851892 FL_SET_RAW (obj , FL_EXIVAR );
1893+ shape_id_t new_shape_id = rb_evict_fields_to_hash (obj );
18861894 return new_shape_id ;
18871895}
18881896
@@ -2407,9 +2415,9 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj)
24072415
24082416 clear :
24092417 if (FL_TEST (dest , FL_EXIVAR )) {
2410- RBASIC_SET_SHAPE_ID (dest , ROOT_SHAPE_ID );
24112418 rb_free_generic_ivar (dest );
24122419 FL_UNSET (dest , FL_EXIVAR );
2420+ RBASIC_SET_SHAPE_ID (dest , ROOT_SHAPE_ID );
24132421 }
24142422}
24152423
0 commit comments