summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2025-08-08 17:24:58 +0200
committerJean Boussier <jean.boussier@gmail.com>2025-08-08 19:06:59 +0200
commit057d7c1c58eeaad9dbba4f07e9a390dcb6cafd8f (patch)
tree9b2858ad4390426463f229c0e3703b57b15b0564
parente4b386e090f00a6690511f2d14aff5fa7b80328d (diff)
object_id_to_ref: complete incremental GC before iterating
Otherwise dealing with garbage objects is tricky.
-rw-r--r--gc.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/gc.c b/gc.c
index 90f2b29bfa..3d0935ad1a 100644
--- a/gc.c
+++ b/gc.c
@@ -1755,7 +1755,6 @@ rb_gc_pointer_to_heap_p(VALUE obj)
#define LAST_OBJECT_ID() (object_id_counter * OBJ_ID_INCREMENT)
static VALUE id2ref_value = 0;
static st_table *id2ref_tbl = NULL;
-static bool id2ref_tbl_built = false;
#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
static size_t object_id_counter = 1;
@@ -1947,6 +1946,7 @@ build_id2ref_i(VALUE obj, void *data)
case T_CLASS:
case T_MODULE:
if (RCLASS(obj)->object_id) {
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(obj));
st_insert(id2ref_tbl, RCLASS(obj)->object_id, obj);
}
break;
@@ -1955,6 +1955,7 @@ build_id2ref_i(VALUE obj, void *data)
break;
default:
if (rb_shape_obj_has_id(obj)) {
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(obj));
st_insert(id2ref_tbl, rb_obj_id(obj), obj);
}
break;
@@ -1979,12 +1980,12 @@ object_id_to_ref(void *objspace_ptr, VALUE object_id)
// build_id2ref_i will most certainly malloc, which could trigger GC and sweep
// objects we just added to the table.
- bool gc_disabled = RTEST(rb_gc_disable_no_rest());
+ // By calling rb_gc_disable() we also save having to handle potentially garbage objects.
+ bool gc_disabled = RTEST(rb_gc_disable());
{
rb_gc_impl_each_object(objspace, build_id2ref_i, (void *)id2ref_tbl);
}
if (!gc_disabled) rb_gc_enable();
- id2ref_tbl_built = true;
}
VALUE obj;
@@ -2036,10 +2037,9 @@ obj_free_object_id(VALUE obj)
RUBY_ASSERT(FIXNUM_P(obj_id) || RB_TYPE_P(obj_id, T_BIGNUM));
if (!st_delete(id2ref_tbl, (st_data_t *)&obj_id, NULL)) {
- // If we're currently building the table then it's not a bug.
// The the object is a T_IMEMO/fields, then it's possible the actual object
// has been garbage collected already.
- if (id2ref_tbl_built && !RB_TYPE_P(obj, T_IMEMO)) {
+ if (!RB_TYPE_P(obj, T_IMEMO)) {
rb_bug("Object ID seen, but not in _id2ref table: object_id=%llu object=%s", NUM2ULL(obj_id), rb_obj_info(obj));
}
}