@@ -2141,13 +2141,9 @@ id2ref_tbl_unlock(void)
21412141static void
21422142id2ref_tbl_free (void * data )
21432143{
2144- id2ref_tbl_lock (true);
2145- {
2146- RUBY_ATOMIC_PTR_SET (id2ref_tbl , NULL ); // clear global ref
2147- st_table * table = (st_table * )data ;
2148- st_free_table (table );
2149- }
2150- id2ref_tbl_unlock ();
2144+ st_table * table = (st_table * )data ;
2145+ st_free_table (table );
2146+ RUBY_ATOMIC_PTR_SET (id2ref_tbl , NULL ); // clear global ref
21512147}
21522148
21532149static const rb_data_type_t id2ref_tbl_type = {
@@ -2159,7 +2155,7 @@ static const rb_data_type_t id2ref_tbl_type = {
21592155 // dcompact function not required because the table is reference updated
21602156 // in rb_gc_vm_weak_table_foreach
21612157 },
2162- .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_CONCURRENT_FREE_SAFE
2158+ .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
21632159};
21642160
21652161static VALUE
@@ -2270,36 +2266,26 @@ build_id2ref_i(VALUE obj, void *data)
22702266{
22712267 st_table * id2ref_tbl = (st_table * )data ;
22722268
2269+ if (rb_objspace_garbage_object_p (obj )) return ;
2270+
22732271 switch (BUILTIN_TYPE (obj )) {
22742272 case T_CLASS :
22752273 case T_MODULE :
22762274 RUBY_ASSERT (!rb_objspace_garbage_object_p (obj ));
22772275 if (RCLASS (obj )-> object_id ) {
2278- id2ref_tbl_lock (false);
2279- {
2280- st_insert (id2ref_tbl , RCLASS (obj )-> object_id , obj );
2281- }
2282- id2ref_tbl_unlock ();
2276+ st_insert (id2ref_tbl , RCLASS (obj )-> object_id , obj );
22832277 }
22842278 break ;
22852279 case T_IMEMO :
22862280 RUBY_ASSERT (!rb_objspace_garbage_object_p (obj ));
22872281 if (IMEMO_TYPE_P (obj , imemo_fields ) && rb_shape_obj_has_id (obj )) {
2288- id2ref_tbl_lock (false);
2289- {
2290- st_insert (id2ref_tbl , rb_obj_id (obj ), rb_imemo_fields_owner (obj ));
2291- }
2292- id2ref_tbl_unlock ();
2282+ st_insert (id2ref_tbl , rb_obj_id (obj ), rb_imemo_fields_owner (obj ));
22932283 }
22942284 break ;
22952285 case T_OBJECT :
22962286 RUBY_ASSERT (!rb_objspace_garbage_object_p (obj ));
22972287 if (rb_shape_obj_has_id (obj )) {
2298- id2ref_tbl_lock (false);
2299- {
2300- st_insert (id2ref_tbl , rb_obj_id (obj ), obj );
2301- }
2302- id2ref_tbl_unlock ();
2288+ st_insert (id2ref_tbl , rb_obj_id (obj ), obj );
23032289 }
23042290 break ;
23052291 default :
@@ -2317,24 +2303,30 @@ object_id_to_ref(void *objspace_ptr, VALUE object_id)
23172303
23182304 if (!RUBY_ATOMIC_PTR_LOAD (id2ref_tbl )) {
23192305 rb_gc_vm_barrier (); // stop other ractors, background sweeper could still be running
2306+ if (!RUBY_ATOMIC_PTR_LOAD (id2ref_tbl )) {
2307+
2308+ // GC Must not trigger while we build the table, otherwise if we end
2309+ // up freeing an object that had an ID, we might try to delete it from
2310+ // the table even though it wasn't inserted yet.
2311+ st_table * tmp_id2ref_tbl = st_init_table (& object_id_hash_type );
2312+ VALUE tmp_id2ref_value = TypedData_Wrap_Struct (0 , & id2ref_tbl_type , tmp_id2ref_tbl );
2313+
2314+ // build_id2ref_i will most certainly malloc, which could trigger GC and sweep
2315+ // objects we just added to the table.
2316+ // By calling rb_gc_disable() we also save having to handle potentially garbage objects.
2317+ bool gc_disabled = RTEST (rb_gc_disable ());
2318+ {
2319+ id2ref_value = tmp_id2ref_value ;
23202320
2321- // GC Must not trigger while we build the table, otherwise if we end
2322- // up freeing an object that had an ID, we might try to delete it from
2323- // the table even though it wasn't inserted yet.
2324- st_table * tmp_id2ref_tbl = st_init_table (& object_id_hash_type );
2325- VALUE tmp_id2ref_value = TypedData_Wrap_Struct (0 , & id2ref_tbl_type , tmp_id2ref_tbl );
2326-
2327- // build_id2ref_i will most certainly malloc, which could trigger GC and sweep
2328- // objects we just added to the table.
2329- // By calling rb_gc_disable() we also save having to handle potentially garbage objects.
2330- bool gc_disabled = RTEST (rb_gc_disable ());
2331- {
2332- id2ref_value = tmp_id2ref_value ;
2333-
2334- rb_gc_impl_each_object (objspace , build_id2ref_i , (void * )tmp_id2ref_tbl );
2335- RUBY_ATOMIC_PTR_SET (id2ref_tbl , tmp_id2ref_tbl );
2321+ id2ref_tbl_lock (false);
2322+ {
2323+ rb_gc_impl_each_object (objspace , build_id2ref_i , (void * )tmp_id2ref_tbl );
2324+ }
2325+ id2ref_tbl_unlock ();
2326+ RUBY_ATOMIC_PTR_SET (id2ref_tbl , tmp_id2ref_tbl );
2327+ }
2328+ if (!gc_disabled ) rb_gc_enable ();
23362329 }
2337- if (!gc_disabled ) rb_gc_enable ();
23382330 }
23392331
23402332 VALUE obj ;
0 commit comments