ruby-changes:56362
From: Nobuyoshi <ko1@a...>
Date: Thu, 4 Jul 2019 01:04:46 +0900 (JST)
Subject: [ruby-changes:56362] Nobuyoshi Nakada: d0cd0866d8 (master): Disable GC during rb_objspace_reachable_object_p
https://git.ruby-lang.org/ruby.git/commit/?id=d0cd0866d8 From d0cd0866d82a58933e5dccd073c753c0c2ad4eb5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 4 Jul 2019 00:58:52 +0900 Subject: Disable GC during rb_objspace_reachable_object_p Try to fix CI breakage by [Feature #15974]. diff --git a/gc.c b/gc.c index db830b9..94aa6ce 100644 --- a/gc.c +++ b/gc.c @@ -2954,39 +2954,7 @@ should_be_finalizable(VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L2954 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, https://github.com/ruby/ruby/blob/trunk/gc.c#L9337 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 ------------------------ */ -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/