@@ -1371,55 +1371,59 @@ rb_attr_delete(VALUE obj, ID id)
13711371}
13721372
13731373void
1374- rb_evict_ivars_to_hash (VALUE obj )
1374+ rb_obj_convert_to_too_complex (VALUE obj , st_table * table )
13751375{
13761376 RUBY_ASSERT (!rb_shape_obj_too_complex (obj ));
13771377
1378- st_table * table = st_init_numtable_with_size (rb_ivar_count (obj ));
1379-
1380- // Evacuate all previous values from shape into id_table
1381- rb_ivar_foreach (obj , rb_obj_evacuate_ivs_to_hash_table , (st_data_t )table );
1378+ VALUE * old_ivptr = NULL ;
13821379
13831380 switch (BUILTIN_TYPE (obj )) {
1384- case T_OBJECT :
1385- rb_shape_set_too_complex (obj );
1386-
1387- if (!(RBASIC (obj )-> flags & ROBJECT_EMBED )) {
1388- xfree (ROBJECT (obj )-> as .heap .ivptr );
1389- }
1390-
1391- ROBJECT_SET_IV_HASH (obj , table );
1392- break ;
1393- case T_CLASS :
1394- case T_MODULE :
1395- rb_shape_set_too_complex (obj );
1396-
1397- xfree (RCLASS_IVPTR (obj ));
1398- RCLASS_SET_IV_HASH (obj , table );
1399- break ;
1400- default :
1401- RB_VM_LOCK_ENTER ();
1402- {
1403- struct st_table * gen_ivs = generic_ivtbl_no_ractor_check (obj );
1404- st_data_t old_ivtbl ;
1405- struct gen_ivtbl * ivtbl = NULL ;
1406-
1407- if (st_delete (gen_ivs , & obj , & old_ivtbl )) {
1408- ivtbl = (struct gen_ivtbl * )old_ivtbl ;
1409- }
1410-
1411- ivtbl = xrealloc (ivtbl , sizeof (struct gen_ivtbl ));
1412- ivtbl -> as .complex .table = table ;
1381+ case T_OBJECT :
1382+ if (!(RBASIC (obj )-> flags & ROBJECT_EMBED )) {
1383+ old_ivptr = ROBJECT_IVPTR (obj );
1384+ }
1385+ rb_shape_set_shape_id (obj , OBJ_TOO_COMPLEX_SHAPE_ID );
1386+ ROBJECT_SET_IV_HASH (obj , table );
1387+ break ;
1388+ case T_CLASS :
1389+ case T_MODULE :
1390+ old_ivptr = RCLASS_IVPTR (obj );
1391+ rb_shape_set_shape_id (obj , OBJ_TOO_COMPLEX_SHAPE_ID );
1392+ RCLASS_SET_IV_HASH (obj , table );
1393+ break ;
1394+ default :
1395+ RB_VM_LOCK_ENTER ();
1396+ {
1397+ struct st_table * gen_ivs = generic_ivtbl_no_ractor_check (obj );
1398+ st_lookup (gen_ivs , (st_data_t )& obj , (st_data_t * )& old_ivptr );
1399+
1400+ struct gen_ivtbl * ivtbl = xmalloc (sizeof (struct gen_ivtbl ));
1401+ ivtbl -> as .complex .table = table ;
14131402#if SHAPE_IN_BASIC_FLAGS
1414- rb_shape_set_too_complex (obj );
1403+ rb_shape_set_shape_id (obj , OBJ_TOO_COMPLEX_SHAPE_ID );
14151404#else
1416- ivtbl -> shape_id = OBJ_TOO_COMPLEX_SHAPE_ID ;
1405+ ivtbl -> shape_id = OBJ_TOO_COMPLEX_SHAPE_ID ;
14171406#endif
1407+ st_insert (gen_ivs , (st_data_t )obj , (st_data_t )ivtbl );
1408+ }
1409+ RB_VM_LOCK_LEAVE ();
1410+ }
14181411
1419- st_insert (gen_ivs , (st_data_t )obj , (st_data_t )ivtbl );
1420- }
1421- RB_VM_LOCK_LEAVE ();
1412+ if (old_ivptr ) {
1413+ xfree (old_ivptr );
14221414 }
1415+ }
1416+
1417+ void
1418+ rb_evict_ivars_to_hash (VALUE obj )
1419+ {
1420+ RUBY_ASSERT (!rb_shape_obj_too_complex (obj ));
1421+
1422+ st_table * table = st_init_numtable_with_size (rb_ivar_count (obj ));
1423+
1424+ // Evacuate all previous values from shape into id_table
1425+ rb_obj_copy_ivs_to_hash_table (obj , table );
1426+ rb_obj_convert_to_too_complex (obj , table );
14231427
14241428 RUBY_ASSERT (rb_shape_obj_too_complex (obj ));
14251429}
@@ -1637,12 +1641,18 @@ rb_ensure_iv_list_size(VALUE obj, uint32_t current_capacity, uint32_t new_capaci
16371641}
16381642
16391643int
1640- rb_obj_evacuate_ivs_to_hash_table (ID key , VALUE val , st_data_t arg )
1644+ rb_obj_copy_ivs_to_hash_table_i (ID key , VALUE val , st_data_t arg )
16411645{
16421646 st_insert ((st_table * )arg , (st_data_t )key , (st_data_t )val );
16431647 return ST_CONTINUE ;
16441648}
16451649
1650+ void
1651+ rb_obj_copy_ivs_to_hash_table (VALUE obj , st_table * table )
1652+ {
1653+ rb_ivar_foreach (obj , rb_obj_copy_ivs_to_hash_table_i , (st_data_t )table );
1654+ }
1655+
16461656static VALUE *
16471657obj_ivar_set_shape_ivptr (VALUE obj , void * _data )
16481658{
0 commit comments