diff options
author | Nobuyoshi Nakada <[email protected]> | 2019-07-04 00:58:52 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2019-07-04 00:58:52 +0900 |
commit | d0cd0866d82a58933e5dccd073c753c0c2ad4eb5 (patch) | |
tree | ffb8d9eac66dbe6e296d05555ae56a0dc5e90e0c /gc.c | |
parent | 9f1d67a68f55fe7a16840960e0817d362b16d5b2 (diff) |
Disable GC during rb_objspace_reachable_object_p
Try to fix CI breakage by [Feature #15974].
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 87 |
1 files changed, 54 insertions, 33 deletions
@@ -2954,39 +2954,7 @@ should_be_finalizable(VALUE obj) rb_check_frozen(obj); } -struct reachable_object_data { - VALUE obj; - VALUE set; - bool found; -}; - -static void -reachable_object_callback(VALUE child, void *dp) -{ - struct reachable_object_data *data = dp; - if (child == data->obj) - data->found = true; - - if (data->found) - return; - - // Maintain a set of objects already searched, so that we don't follow a cycle - if (rb_hash_lookup2(data->set, child, Qfalse)) - return; - rb_hash_aset(data->set, child, Qtrue); - - rb_objspace_reachable_objects_from(child, reachable_object_callback, data); -} - -static int -rb_objspace_reachable_object_p(VALUE obj, VALUE root) -{ - struct reachable_object_data data = {obj, rb_ident_hash_new()}; - rb_obj_hide(data.set); - rb_objspace_reachable_objects_from(root, reachable_object_callback, &data); - rb_hash_clear(data.set); - return data.found; -} +static int rb_objspace_reachable_object_p(VALUE obj, VALUE root); /* * call-seq: @@ -9369,6 +9337,59 @@ rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, POP_MARK_FUNC_DATA(); } +struct reachable_object_data { + VALUE obj; + VALUE set; +}; + +static void +reachable_object_callback(VALUE child, void *dp) +{ + struct reachable_object_data *data = dp; + if (child == data->obj) { + rb_throw_obj(data->set, Qtrue); + } + + // Maintain a set of objects already searched, so that we don't follow a cycle + if (rb_hash_lookup2(data->set, child, Qfalse)) + return; + rb_hash_aset(data->set, child, Qtrue); + + rb_objspace_reachable_objects_from(child, reachable_object_callback, data); +} + +static VALUE +call_reachable_object(RB_BLOCK_CALL_FUNC_ARGLIST(set, arg)) +{ + struct reachable_object_data *data = (void *)arg; + VALUE obj = data->set; + data->set = rb_obj_hide(set); + gc_mark_children(&rb_objspace, obj); + rb_hash_clear(set); + return Qfalse; +} + +static int +rb_objspace_reachable_object_p(VALUE obj, VALUE root) +{ + rb_objspace_t *objspace = &rb_objspace; + int reachable = FALSE; + if (is_markable_object(objspace, obj)) { + struct reachable_object_data data = {obj, root}; + struct mark_func_data_struct mfd = {&data, reachable_object_callback}; + int prev_dont_gc = dont_gc; + enum ruby_tag_type state; + + dont_gc = TRUE; + PUSH_MARK_FUNC_DATA(&mfd); + reachable = RTEST(rb_catch_protect(rb_ident_hash_new(), call_reachable_object, (VALUE)&data, &state)); + POP_MARK_FUNC_DATA(); + dont_gc = prev_dont_gc; + if (state) EC_JUMP_TAG(GET_EC(), state); + } + return reachable; +} + /* ------------------------ Extended allocator ------------------------ */ |