@@ -366,7 +366,9 @@ rb_mmtk_update_obj_id_tables(void)
366366 struct objspace * objspace = rb_gc_get_objspace ();
367367
368368 st_foreach (objspace -> obj_to_id_tbl , rb_mmtk_update_obj_id_tables_obj_to_id_i , 0 );
369- st_foreach (objspace -> id_to_obj_tbl , rb_mmtk_update_obj_id_tables_id_to_obj_i , 0 );
369+ if (objspace -> id_to_obj_tbl ) {
370+ st_foreach (objspace -> id_to_obj_tbl , rb_mmtk_update_obj_id_tables_id_to_obj_i , 0 );
371+ }
370372}
371373
372374static int
@@ -1091,7 +1093,7 @@ static const struct st_hash_type object_id_hash_type = {
10911093static void
10921094objspace_obj_id_init (struct objspace * objspace )
10931095{
1094- objspace -> id_to_obj_tbl = st_init_table ( & object_id_hash_type ) ;
1096+ objspace -> id_to_obj_tbl = NULL ;
10951097 objspace -> obj_to_id_tbl = st_init_numtable ();
10961098 objspace -> next_object_id = OBJ_ID_INITIAL ;
10971099}
@@ -1119,30 +1121,51 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj)
11191121 objspace -> next_object_id += OBJ_ID_INCREMENT ;
11201122
11211123 st_insert (objspace -> obj_to_id_tbl , (st_data_t )obj , (st_data_t )id );
1122- st_insert (objspace -> id_to_obj_tbl , (st_data_t )id , (st_data_t )obj );
1124+ if (RB_UNLIKELY (objspace -> id_to_obj_tbl )) {
1125+ st_insert (objspace -> id_to_obj_tbl , (st_data_t )id , (st_data_t )obj );
1126+ }
11231127 FL_SET (obj , FL_SEEN_OBJ_ID );
11241128 }
11251129 rb_gc_vm_unlock (lev );
11261130
11271131 return id ;
11281132}
11291133
1134+ static int
1135+ build_id_to_obj_i (st_data_t key , st_data_t value , st_data_t data )
1136+ {
1137+ st_table * id_to_obj_tbl = (st_table * )data ;
1138+ st_insert (id_to_obj_tbl , value , key );
1139+ return ST_CONTINUE ;
1140+ }
1141+
11301142VALUE
11311143rb_gc_impl_object_id_to_ref (void * objspace_ptr , VALUE object_id )
11321144{
11331145 struct objspace * objspace = objspace_ptr ;
11341146
1147+
1148+ unsigned int lev = rb_gc_vm_lock ();
1149+
1150+ if (!objspace -> id_to_obj_tbl ) {
1151+ objspace -> id_to_obj_tbl = st_init_table_with_size (& object_id_hash_type , st_table_size (objspace -> obj_to_id_tbl ));
1152+ st_foreach (objspace -> obj_to_id_tbl , build_id_to_obj_i , (st_data_t )objspace -> id_to_obj_tbl );
1153+ }
1154+
11351155 VALUE obj ;
1136- if (st_lookup (objspace -> id_to_obj_tbl , object_id , & obj ) &&
1137- !rb_gc_impl_garbage_object_p (objspace , obj )) {
1156+ bool found = st_lookup (objspace -> id_to_obj_tbl , object_id , & obj ) && !rb_gc_impl_garbage_object_p (objspace , obj );
1157+
1158+ rb_gc_vm_unlock (lev );
1159+
1160+ if (found ) {
11381161 return obj ;
11391162 }
11401163
11411164 if (rb_funcall (object_id , rb_intern (">=" ), 1 , ULL2NUM (objspace -> next_object_id ))) {
1142- rb_raise (rb_eRangeError , "%+" PRIsVALUE " is not id value" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
1165+ rb_raise (rb_eRangeError , "%+" PRIsVALUE " is not an id value" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
11431166 }
11441167 else {
1145- rb_raise (rb_eRangeError , "%+" PRIsVALUE " is recycled object" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
1168+ rb_raise (rb_eRangeError , "%+" PRIsVALUE " is a recycled object" , rb_funcall (object_id , rb_intern ("to_s" ), 1 , INT2FIX (10 )));
11461169 }
11471170}
11481171
0 commit comments