@@ -366,7 +366,9 @@ rb_mmtk_update_obj_id_tables(void)
366
366
struct objspace * objspace = rb_gc_get_objspace ();
367
367
368
368
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
+ }
370
372
}
371
373
372
374
static int
@@ -1091,7 +1093,7 @@ static const struct st_hash_type object_id_hash_type = {
1091
1093
static void
1092
1094
objspace_obj_id_init (struct objspace * objspace )
1093
1095
{
1094
- objspace -> id_to_obj_tbl = st_init_table ( & object_id_hash_type ) ;
1096
+ objspace -> id_to_obj_tbl = NULL ;
1095
1097
objspace -> obj_to_id_tbl = st_init_numtable ();
1096
1098
objspace -> next_object_id = OBJ_ID_INITIAL ;
1097
1099
}
@@ -1119,30 +1121,51 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj)
1119
1121
objspace -> next_object_id += OBJ_ID_INCREMENT ;
1120
1122
1121
1123
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
+ }
1123
1127
FL_SET (obj , FL_SEEN_OBJ_ID );
1124
1128
}
1125
1129
rb_gc_vm_unlock (lev );
1126
1130
1127
1131
return id ;
1128
1132
}
1129
1133
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
+
1130
1142
VALUE
1131
1143
rb_gc_impl_object_id_to_ref (void * objspace_ptr , VALUE object_id )
1132
1144
{
1133
1145
struct objspace * objspace = objspace_ptr ;
1134
1146
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
+
1135
1155
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 ) {
1138
1161
return obj ;
1139
1162
}
1140
1163
1141
1164
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 )));
1143
1166
}
1144
1167
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 )));
1146
1169
}
1147
1170
}
1148
1171
0 commit comments