@@ -1585,30 +1585,55 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj)
15851585 objspace -> next_object_id += OBJ_ID_INCREMENT ;
15861586
15871587 st_insert (objspace -> obj_to_id_tbl , (st_data_t )obj , (st_data_t )id );
1588- st_insert (objspace -> id_to_obj_tbl , (st_data_t )id , (st_data_t )obj );
1588+ if (RB_UNLIKELY (objspace -> id_to_obj_tbl )) {
1589+ st_insert (objspace -> id_to_obj_tbl , (st_data_t )id , (st_data_t )obj );
1590+ }
15891591 FL_SET (obj , FL_SEEN_OBJ_ID );
15901592 }
15911593 rb_gc_vm_unlock (lev );
15921594
15931595 return id ;
15941596}
15951597
1598+ static int
1599+ build_id_to_obj_i (st_data_t key , st_data_t value , st_data_t data )
1600+ {
1601+ st_table * id_to_obj_tbl = (st_table * )data ;
1602+ st_insert (id_to_obj_tbl , value , key );
1603+ return ST_CONTINUE ;
1604+ }
1605+
15961606VALUE
15971607rb_gc_impl_object_id_to_ref (void * objspace_ptr , VALUE object_id )
15981608{
15991609 rb_objspace_t * objspace = objspace_ptr ;
16001610
1611+ unsigned int lev = rb_gc_vm_lock ();
1612+
1613+ if (!objspace -> id_to_obj_tbl ) {
1614+ {
1615+ rb_gc_vm_barrier (); // stop other ractors
1616+ if (!objspace -> id_to_obj_tbl ) {
1617+ objspace -> id_to_obj_tbl = st_init_table_with_size (& object_id_hash_type , st_table_size (objspace -> obj_to_id_tbl ));
1618+ st_foreach (objspace -> obj_to_id_tbl , build_id_to_obj_i , (st_data_t )objspace -> id_to_obj_tbl );
1619+ }
1620+ }
1621+ }
1622+
16011623 VALUE obj ;
1602- if (st_lookup (objspace -> id_to_obj_tbl , object_id , & obj ) &&
1603- !rb_gc_impl_garbage_object_p (objspace , obj )) {
1624+ bool found = st_lookup (objspace -> id_to_obj_tbl , object_id , & obj ) && !rb_gc_impl_garbage_object_p (objspace , obj );
1625+
1626+ rb_gc_vm_unlock (lev );
1627+
1628+ if (found ) {
16041629 return obj ;
16051630 }
16061631
16071632 if (rb_funcall (object_id , rb_intern (">=" ), 1 , ULL2NUM (objspace -> next_object_id ))) {
1608- rb_raise (rb_eRangeError , "%+" PRIsVALUE " is not id value" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
1633+ rb_raise (rb_eRangeError , "%+" PRIsVALUE " is not an id value" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
16091634 }
16101635 else {
1611- rb_raise (rb_eRangeError , "%+" PRIsVALUE " is recycled object" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
1636+ rb_raise (rb_eRangeError , "%+" PRIsVALUE " is a recycled object" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
16121637 }
16131638}
16141639
@@ -2644,7 +2669,9 @@ obj_free_object_id(rb_objspace_t *objspace, VALUE obj)
26442669
26452670 if (st_delete (objspace -> obj_to_id_tbl , & o , & id )) {
26462671 GC_ASSERT (id );
2647- st_delete (objspace -> id_to_obj_tbl , & id , NULL );
2672+ if (RB_UNLIKELY (objspace -> id_to_obj_tbl )) {
2673+ st_delete (objspace -> id_to_obj_tbl , & id , NULL );
2674+ }
26482675 }
26492676 else {
26502677 rb_bug ("Object ID seen, but not in mapping table: %s" , rb_obj_info (obj ));
@@ -7168,7 +7195,9 @@ gc_update_references(rb_objspace_t *objspace)
71687195 }
71697196 }
71707197 gc_ref_update_table_values_only (objspace -> obj_to_id_tbl );
7171- gc_update_table_refs (objspace -> id_to_obj_tbl );
7198+ if (RB_UNLIKELY (objspace -> id_to_obj_tbl )) {
7199+ gc_update_table_refs (objspace -> id_to_obj_tbl );
7200+ }
71727201 gc_update_table_refs (finalizer_table );
71737202
71747203 rb_gc_update_vm_references ((void * )objspace );
@@ -9282,7 +9311,10 @@ rb_gc_impl_objspace_free(void *objspace_ptr)
92829311 heap -> total_slots = 0 ;
92839312 }
92849313
9285- st_free_table (objspace -> id_to_obj_tbl );
9314+
9315+ if (objspace -> id_to_obj_tbl ) {
9316+ st_free_table (objspace -> id_to_obj_tbl );
9317+ }
92869318 st_free_table (objspace -> obj_to_id_tbl );
92879319
92889320 free_stack_chunks (& objspace -> mark_stack );
@@ -9423,7 +9455,7 @@ rb_gc_impl_objspace_init(void *objspace_ptr)
94239455 heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP ;
94249456#endif
94259457 objspace -> next_object_id = OBJ_ID_INITIAL ;
9426- objspace -> id_to_obj_tbl = st_init_table ( & object_id_hash_type ) ;
9458+ objspace -> id_to_obj_tbl = NULL ;
94279459 objspace -> obj_to_id_tbl = st_init_numtable ();
94289460#if RGENGC_ESTIMATE_OLDMALLOC
94299461 objspace -> rgengc .oldmalloc_increase_limit = gc_params .oldmalloc_limit_min ;
0 commit comments