diff options
-rw-r--r-- | benchmark/object_id.yml | 4 | ||||
-rw-r--r-- | gc.c | 6 | ||||
-rw-r--r-- | gc/default/default.c | 45 | ||||
-rw-r--r-- | gc/mmtk/mmtk.c | 37 | ||||
-rw-r--r-- | test/ruby/test_objectspace.rb | 2 |
5 files changed, 74 insertions, 20 deletions
diff --git a/benchmark/object_id.yml b/benchmark/object_id.yml new file mode 100644 index 0000000000..2bd52b923f --- /dev/null +++ b/benchmark/object_id.yml @@ -0,0 +1,4 @@ +benchmark: + baseline: "Object.new" + object_id: "Object.new.object_id" +# loop_count: 100000 @@ -1794,11 +1794,11 @@ id2ref(VALUE objid) return ptr; } else { - rb_raise(rb_eRangeError, "%p is not symbol id value", (void *)ptr); + rb_raise(rb_eRangeError, "%p is not a symbol id value", (void *)ptr); } } - rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_int2str(objid, 10)); + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not an id value", rb_int2str(objid, 10)); } } @@ -1807,7 +1807,7 @@ id2ref(VALUE objid) return obj; } else { - rb_raise(rb_eRangeError, "%+"PRIsVALUE" is id of the unshareable object on multi-ractor", rb_int2str(objid, 10)); + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is the id of an unshareable object on multi-ractor", rb_int2str(objid, 10)); } } diff --git a/gc/default/default.c b/gc/default/default.c index c7723a2275..447fe15b06 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -1585,7 +1585,9 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj) objspace->next_object_id += OBJ_ID_INCREMENT; st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id); - st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj); + if (RB_UNLIKELY(objspace->id_to_obj_tbl)) { + st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj); + } FL_SET(obj, FL_SEEN_OBJ_ID); } rb_gc_vm_unlock(lev); @@ -1593,22 +1595,40 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj) return id; } +static int +build_id_to_obj_i(st_data_t key, st_data_t value, st_data_t data) +{ + st_table *id_to_obj_tbl = (st_table *)data; + st_insert(id_to_obj_tbl, value, key); + return ST_CONTINUE; +} + VALUE rb_gc_impl_object_id_to_ref(void *objspace_ptr, VALUE object_id) { rb_objspace_t *objspace = objspace_ptr; + unsigned int lev = rb_gc_vm_lock(); + + if (!objspace->id_to_obj_tbl) { + objspace->id_to_obj_tbl = st_init_table_with_size(&object_id_hash_type, st_table_size(objspace->obj_to_id_tbl)); + st_foreach(objspace->obj_to_id_tbl, build_id_to_obj_i, (st_data_t)objspace->id_to_obj_tbl); + } + VALUE obj; - if (st_lookup(objspace->id_to_obj_tbl, object_id, &obj) && - !rb_gc_impl_garbage_object_p(objspace, obj)) { + bool found = st_lookup(objspace->id_to_obj_tbl, object_id, &obj) && !rb_gc_impl_garbage_object_p(objspace, obj); + + rb_gc_vm_unlock(lev); + + if (found) { return obj; } if (rb_funcall(object_id, rb_intern(">="), 1, ULL2NUM(objspace->next_object_id))) { - rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not an id value", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); } else { - rb_raise(rb_eRangeError, "%+"PRIsVALUE" is recycled object", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is a recycled object", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); } } @@ -2644,7 +2664,9 @@ obj_free_object_id(rb_objspace_t *objspace, VALUE obj) if (st_delete(objspace->obj_to_id_tbl, &o, &id)) { GC_ASSERT(id); - st_delete(objspace->id_to_obj_tbl, &id, NULL); + if (RB_UNLIKELY(objspace->id_to_obj_tbl)) { + st_delete(objspace->id_to_obj_tbl, &id, NULL); + } } else { 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) } } gc_ref_update_table_values_only(objspace->obj_to_id_tbl); - gc_update_table_refs(objspace->id_to_obj_tbl); + if (RB_UNLIKELY(objspace->id_to_obj_tbl)) { + gc_update_table_refs(objspace->id_to_obj_tbl); + } gc_update_table_refs(finalizer_table); rb_gc_update_vm_references((void *)objspace); @@ -9282,7 +9306,10 @@ rb_gc_impl_objspace_free(void *objspace_ptr) heap->total_slots = 0; } - st_free_table(objspace->id_to_obj_tbl); + + if (objspace->id_to_obj_tbl) { + st_free_table(objspace->id_to_obj_tbl); + } st_free_table(objspace->obj_to_id_tbl); free_stack_chunks(&objspace->mark_stack); @@ -9423,7 +9450,7 @@ rb_gc_impl_objspace_init(void *objspace_ptr) heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP; #endif objspace->next_object_id = OBJ_ID_INITIAL; - objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type); + objspace->id_to_obj_tbl = NULL; objspace->obj_to_id_tbl = st_init_numtable(); #if RGENGC_ESTIMATE_OLDMALLOC objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min; diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 84161885e9..b844c8c2a3 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -366,7 +366,9 @@ rb_mmtk_update_obj_id_tables(void) struct objspace *objspace = rb_gc_get_objspace(); st_foreach(objspace->obj_to_id_tbl, rb_mmtk_update_obj_id_tables_obj_to_id_i, 0); - st_foreach(objspace->id_to_obj_tbl, rb_mmtk_update_obj_id_tables_id_to_obj_i, 0); + if (objspace->id_to_obj_tbl) { + st_foreach(objspace->id_to_obj_tbl, rb_mmtk_update_obj_id_tables_id_to_obj_i, 0); + } } static int @@ -1091,7 +1093,7 @@ static const struct st_hash_type object_id_hash_type = { static void objspace_obj_id_init(struct objspace *objspace) { - objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type); + objspace->id_to_obj_tbl = NULL; objspace->obj_to_id_tbl = st_init_numtable(); objspace->next_object_id = OBJ_ID_INITIAL; } @@ -1119,7 +1121,9 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj) objspace->next_object_id += OBJ_ID_INCREMENT; st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id); - st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj); + if (RB_UNLIKELY(objspace->id_to_obj_tbl)) { + st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj); + } FL_SET(obj, FL_SEEN_OBJ_ID); } rb_gc_vm_unlock(lev); @@ -1127,22 +1131,41 @@ rb_gc_impl_object_id(void *objspace_ptr, VALUE obj) return id; } +static int +build_id_to_obj_i(st_data_t key, st_data_t value, st_data_t data) +{ + st_table *id_to_obj_tbl = (st_table *)data; + st_insert(id_to_obj_tbl, value, key); + return ST_CONTINUE; +} + VALUE rb_gc_impl_object_id_to_ref(void *objspace_ptr, VALUE object_id) { struct objspace *objspace = objspace_ptr; + + unsigned int lev = rb_gc_vm_lock(); + + if (!objspace->id_to_obj_tbl) { + objspace->id_to_obj_tbl = st_init_table_with_size(&object_id_hash_type, st_table_size(objspace->obj_to_id_tbl)); + st_foreach(objspace->obj_to_id_tbl, build_id_to_obj_i, (st_data_t)objspace->id_to_obj_tbl); + } + VALUE obj; - if (st_lookup(objspace->id_to_obj_tbl, object_id, &obj) && - !rb_gc_impl_garbage_object_p(objspace, obj)) { + bool found = st_lookup(objspace->id_to_obj_tbl, object_id, &obj) && !rb_gc_impl_garbage_object_p(objspace, obj); + + rb_gc_vm_unlock(lev); + + if (found) { return obj; } if (rb_funcall(object_id, rb_intern(">="), 1, ULL2NUM(objspace->next_object_id))) { - rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not an id value", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); } else { - rb_raise(rb_eRangeError, "%+"PRIsVALUE" is recycled object", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); + rb_raise(rb_eRangeError, "%+"PRIsVALUE" is a recycled object", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10))); } } diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index 5c79983b7e..d161d8079a 100644 --- a/test/ruby/test_objectspace.rb +++ b/test/ruby/test_objectspace.rb @@ -69,7 +69,7 @@ End # RB_STATIC_SYM_P checks for static symbols by checking that the bottom # 8 bits of the object is equal to RUBY_SYMBOL_FLAG, so we need to make # sure that the bottom 8 bits remain unchanged. - msg = /is not symbol id value/ + msg = /is not a symbol id value/ assert_raise_with_message(RangeError, msg) { ObjectSpace._id2ref(:a.object_id + 256) } end |