From 2c9d0b2c2560009ab1158e6fc6fce7527c452bcc Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 10 Apr 2025 11:53:39 +0200 Subject: [PATCH 1/2] Lazily create `objspace->id_to_obj_tbl` This inverse table is only useful if `ObjectSpace._id2ref` is used, which is extremely rare. The only notable exception is the `drb` gem and even then it has an option not to rely on `_id2ref`. So if we assume this table will never be looked up, we can just not maintain it, and if it turns out `_id2ref` is called, we can lock the VM and re-build it. ``` compare-ruby: ruby 3.5.0dev (2025-04-10T09:44:40Z master 684cfa42d7) +YJIT +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-04-10T10:13:43Z lazy-id-to-obj d3aa9626cc) +YJIT +PRISM [arm64-darwin24] warming up.. ``` --- gc/mmtk/mmtk.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 8416188..b844c8c 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))); } } From a2eaa7f6d50eeee531aaf33591a9bf1743f206bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 14:40:32 +0000 Subject: [PATCH 2/2] Bump crossbeam-channel from 0.5.13 to 0.5.15 in /gc/mmtk Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.13 to 0.5.15. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.13...crossbeam-channel-0.5.15) --- updated-dependencies: - dependency-name: crossbeam-channel dependency-version: 0.5.15 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- gc/mmtk/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gc/mmtk/Cargo.lock b/gc/mmtk/Cargo.lock index f909c3a..629cac3 100644 --- a/gc/mmtk/Cargo.lock +++ b/gc/mmtk/Cargo.lock @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ]