@@ -1585,30 +1585,50 @@ 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+ objspace -> id_to_obj_tbl = st_init_table_with_size (& object_id_hash_type , st_table_size (objspace -> obj_to_id_tbl ));
1615+ st_foreach (objspace -> obj_to_id_tbl , build_id_to_obj_i , (st_data_t )objspace -> id_to_obj_tbl );
1616+ }
1617+
16011618 VALUE obj ;
1602- if (st_lookup (objspace -> id_to_obj_tbl , object_id , & obj ) &&
1603- !rb_gc_impl_garbage_object_p (objspace , obj )) {
1619+ bool found = st_lookup (objspace -> id_to_obj_tbl , object_id , & obj ) && !rb_gc_impl_garbage_object_p (objspace , obj );
1620+
1621+ rb_gc_vm_unlock (lev );
1622+
1623+ if (found ) {
16041624 return obj ;
16051625 }
16061626
16071627 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 )));
1628+ rb_raise (rb_eRangeError , "%+" PRIsVALUE " is not an id value" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
16091629 }
16101630 else {
1611- rb_raise (rb_eRangeError , "%+" PRIsVALUE " is recycled object" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
1631+ rb_raise (rb_eRangeError , "%+" PRIsVALUE " is a recycled object" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
16121632 }
16131633}
16141634
@@ -2644,7 +2664,9 @@ obj_free_object_id(rb_objspace_t *objspace, VALUE obj)
26442664
26452665 if (st_delete (objspace -> obj_to_id_tbl , & o , & id )) {
26462666 GC_ASSERT (id );
2647- st_delete (objspace -> id_to_obj_tbl , & id , NULL );
2667+ if (RB_UNLIKELY (objspace -> id_to_obj_tbl )) {
2668+ st_delete (objspace -> id_to_obj_tbl , & id , NULL );
2669+ }
26482670 }
26492671 else {
26502672 rb_bug ("Object ID seen, but not in mapping table: %s" , rb_obj_info (obj ));
@@ -7168,7 +7190,9 @@ gc_update_references(rb_objspace_t *objspace)
71687190 }
71697191 }
71707192 gc_ref_update_table_values_only (objspace -> obj_to_id_tbl );
7171- gc_update_table_refs (objspace -> id_to_obj_tbl );
7193+ if (RB_UNLIKELY (objspace -> id_to_obj_tbl )) {
7194+ gc_update_table_refs (objspace -> id_to_obj_tbl );
7195+ }
71727196 gc_update_table_refs (finalizer_table );
71737197
71747198 rb_gc_update_vm_references ((void * )objspace );
@@ -9282,7 +9306,10 @@ rb_gc_impl_objspace_free(void *objspace_ptr)
92829306 heap -> total_slots = 0 ;
92839307 }
92849308
9285- st_free_table (objspace -> id_to_obj_tbl );
9309+
9310+ if (objspace -> id_to_obj_tbl ) {
9311+ st_free_table (objspace -> id_to_obj_tbl );
9312+ }
92869313 st_free_table (objspace -> obj_to_id_tbl );
92879314
92889315 free_stack_chunks (& objspace -> mark_stack );
@@ -9423,7 +9450,7 @@ rb_gc_impl_objspace_init(void *objspace_ptr)
94239450 heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP ;
94249451#endif
94259452 objspace -> next_object_id = OBJ_ID_INITIAL ;
9426- objspace -> id_to_obj_tbl = st_init_table ( & object_id_hash_type ) ;
9453+ objspace -> id_to_obj_tbl = NULL ;
94279454 objspace -> obj_to_id_tbl = st_init_numtable ();
94289455#if RGENGC_ESTIMATE_OLDMALLOC
94299456 objspace -> rgengc .oldmalloc_increase_limit = gc_params .oldmalloc_limit_min ;
0 commit comments