@@ -1596,9 +1596,8 @@ obj_transition_too_complex(VALUE obj, st_table *table)
15961596 break ;
15971597 case T_CLASS :
15981598 case T_MODULE :
1599- rb_shape_set_shape_id (obj , shape_id );
16001599 // FIXME: RCLASS_SET_FIELDS_HASH allocates, if GC trigger `table` might be corrupted.
1601- RCLASS_SET_FIELDS_HASH ( obj , table );
1600+ rb_bug ( "obj_transition_too_complex can't be used with T_CLASS/T_MODULE, see class_ivar_set_transition_too_complex" );
16021601 break ;
16031602 default :
16041603 RB_VM_LOCK_ENTER ();
@@ -2214,6 +2213,7 @@ struct iv_itr_data {
22142213 st_data_t arg ;
22152214 rb_ivar_foreach_callback_func * func ;
22162215 bool ivar_only ;
2216+ VALUE * fields ;
22172217};
22182218
22192219/*
@@ -2237,22 +2237,7 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu
22372237 return true;
22382238 }
22392239
2240- VALUE * iv_list ;
2241- switch (BUILTIN_TYPE (itr_data -> obj )) {
2242- case T_OBJECT :
2243- RUBY_ASSERT (!rb_shape_obj_too_complex_p (itr_data -> obj ));
2244- iv_list = ROBJECT_FIELDS (itr_data -> obj );
2245- break ;
2246- case T_CLASS :
2247- case T_MODULE :
2248- RUBY_ASSERT (!rb_shape_obj_too_complex_p (itr_data -> obj ));
2249- iv_list = RCLASS_PRIME_FIELDS (itr_data -> obj );
2250- break ;
2251- default :
2252- iv_list = itr_data -> fields_tbl -> as .shape .fields ;
2253- break ;
2254- }
2255- VALUE val = iv_list [shape -> next_field_index - 1 ];
2240+ VALUE val = itr_data -> fields [shape -> next_field_index - 1 ];
22562241 if (!UNDEF_P (val )) {
22572242 switch (callback (shape -> edge_name , val , itr_data -> arg )) {
22582243 case ST_CHECK :
@@ -2297,6 +2282,7 @@ obj_fields_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg, b
22972282 rb_st_foreach (ROBJECT_FIELDS_HASH (obj ), each_hash_iv , (st_data_t )& itr_data );
22982283 }
22992284 else {
2285+ itr_data .fields = ROBJECT_FIELDS (obj );
23002286 iterate_over_shapes_with_callback (shape , func , & itr_data );
23012287 }
23022288}
@@ -2320,6 +2306,7 @@ gen_fields_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg, b
23202306 rb_st_foreach (fields_tbl -> as .complex .table , each_hash_iv , (st_data_t )& itr_data );
23212307 }
23222308 else {
2309+ itr_data .fields = fields_tbl -> as .shape .fields ;
23232310 iterate_over_shapes_with_callback (shape , func , & itr_data );
23242311 }
23252312}
@@ -2330,6 +2317,8 @@ class_fields_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
23302317 RUBY_ASSERT (RB_TYPE_P (obj , T_CLASS ) || RB_TYPE_P (obj , T_MODULE ));
23312318
23322319 rb_shape_t * shape = rb_obj_shape (obj );
2320+ VALUE fields_obj = RCLASS_EXT_WRITABLE (obj )-> fields_obj ;
2321+
23332322 struct iv_itr_data itr_data = {
23342323 .obj = obj ,
23352324 .arg = arg ,
@@ -2338,11 +2327,13 @@ class_fields_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
23382327 };
23392328
23402329 if (rb_shape_obj_too_complex_p (obj )) {
2341- rb_st_foreach (RCLASS_WRITABLE_FIELDS_HASH ( obj ), each_hash_iv , (st_data_t )& itr_data );
2330+ rb_st_foreach (rb_imemo_class_fields_complex_tbl ( fields_obj ), each_hash_iv , (st_data_t )& itr_data );
23422331 }
23432332 else {
2333+ itr_data .fields = rb_imemo_class_fields_ptr (fields_obj );
23442334 iterate_over_shapes_with_callback (shape , func , & itr_data );
23452335 }
2336+ RB_GC_GUARD (fields_obj );
23462337}
23472338
23482339void
@@ -2488,12 +2479,7 @@ rb_field_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
24882479 break ;
24892480 case T_CLASS :
24902481 case T_MODULE :
2491- IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR (0 );
2492- RB_VM_LOCK_ENTER ();
2493- {
2494- class_fields_each (obj , func , arg , ivar_only );
2495- }
2496- RB_VM_LOCK_LEAVE ();
2482+ class_fields_each (obj , func , arg , ivar_only );
24972483 break ;
24982484 default :
24992485 if (FL_TEST (obj , FL_EXIVAR )) {
@@ -4765,7 +4751,21 @@ class_ivar_set_set_shape_id(VALUE obj, shape_id_t shape_id, void *_data)
47654751static void
47664752class_ivar_set_transition_too_complex (VALUE obj , void * _data )
47674753{
4768- rb_evict_fields_to_hash (obj );
4754+ void rb_obj_copy_fields_to_hash_table (VALUE obj , st_table * table );
4755+
4756+ RUBY_ASSERT (!rb_shape_obj_too_complex_p (obj ));
4757+
4758+ rb_shape_t * shape = rb_obj_shape (obj );
4759+ st_table * table = st_init_numtable_with_size (shape -> next_field_index );
4760+ VALUE fields_obj = rb_imemo_class_fields_new_complex (obj , table );
4761+ rb_obj_copy_fields_to_hash_table (obj , table );
4762+
4763+ shape_id_t shape_id = rb_shape_transition_complex (obj );
4764+ rb_shape_set_shape_id (obj , shape_id );
4765+ rb_shape_set_shape_id (fields_obj , RBASIC_SHAPE_ID (obj ));
4766+ RCLASSEXT_SET_FIELDS_OBJ (obj , RCLASS_EXT_PRIME (obj ), fields_obj );
4767+
4768+ RUBY_ASSERT (rb_shape_obj_too_complex_p (obj ));
47694769}
47704770
47714771static st_table *
0 commit comments