ruby-changes:63799
From: Nobuyoshi <ko1@a...>
Date: Mon, 30 Nov 2020 16:08:00 +0900 (JST)
Subject: [ruby-changes:63799] 930a135524 (master): Fixed Ractor.shareable? on cross-recursive objects [Bug #17344]
https://git.ruby-lang.org/ruby.git/commit/?id=930a135524 From 930a135524382ddd80c0608a7593b6cdfceee846 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Mon, 30 Nov 2020 16:07:36 +0900 Subject: Fixed Ractor.shareable? on cross-recursive objects [Bug #17344] diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index d5d78d7..6bd00d5 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -975,6 +975,15 @@ assert_equal 'true', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_ractor.rb#L975 Ractor.shareable?(pr) } +# Ractor.shareable?(recursive_objects) +assert_equal '[false, false]', %q{ + y = [] + x = [y, {}].freeze + y << x + y.freeze + [Ractor.shareable?(x), Ractor.shareable?(y)] +} + # define_method() can invoke different Ractor's proc if the proc is shareable. assert_equal '1', %q{ class C diff --git a/ractor.c b/ractor.c index cb474d0..9a09312 100644 --- a/ractor.c +++ b/ractor.c @@ -1805,6 +1805,9 @@ enum obj_traverse_iterator_result { https://github.com/ruby/ruby/blob/trunk/ractor.c#L1805 typedef enum obj_traverse_iterator_result (*rb_obj_traverse_enter_func)(VALUE obj); typedef enum obj_traverse_iterator_result (*rb_obj_traverse_leave_func)(VALUE obj); +typedef enum obj_traverse_iterator_result (*rb_obj_traverse_final_func)(VALUE obj); + +static enum obj_traverse_iterator_result null_leave(VALUE obj); struct obj_traverse_data { rb_obj_traverse_enter_func enter_func; @@ -1979,12 +1982,29 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1982 } } +struct rb_obj_traverse_final_data { + rb_obj_traverse_final_func final_func; + int stopped; +}; + +static int +obj_traverse_final_i(st_data_t key, st_data_t val, st_data_t arg) +{ + struct rb_obj_traverse_final_data *data = (void *)arg; + if (data->final_func(key)) { + data->stopped = 1; + return ST_STOP; + } + return ST_CONTINUE; +} + // 0: traverse all // 1: stopped static int rb_obj_traverse(VALUE obj, rb_obj_traverse_enter_func enter_func, - rb_obj_traverse_leave_func leave_func) + rb_obj_traverse_leave_func leave_func, + rb_obj_traverse_final_func final_func) { struct obj_traverse_data data = { .enter_func = enter_func, @@ -1992,7 +2012,13 @@ rb_obj_traverse(VALUE obj, https://github.com/ruby/ruby/blob/trunk/ractor.c#L2012 .rec = NULL, }; - return obj_traverse_i(obj, &data); + if (obj_traverse_i(obj, &data)) return 1; + if (final_func && data.rec) { + struct rb_obj_traverse_final_data f = {final_func, 0}; + st_foreach(data.rec, obj_traverse_final_i, (st_data_t)&f); + return f.stopped; + } + return 0; } static int @@ -2063,7 +2089,7 @@ rb_ractor_make_shareable(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ractor.c#L2089 { rb_obj_traverse(obj, make_shareable_check_shareable, - mark_shareable); + mark_shareable, mark_shareable); return obj; } @@ -2092,7 +2118,7 @@ MJIT_FUNC_EXPORTED bool https://github.com/ruby/ruby/blob/trunk/ractor.c#L2118 rb_ractor_shareable_p_continue(VALUE obj) { if (rb_obj_traverse(obj, - shareable_p_enter, + shareable_p_enter, null_leave, mark_shareable)) { return false; } @@ -2113,20 +2139,20 @@ reset_belonging_enter(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ractor.c#L2139 return traverse_cont; } } +#endif static enum obj_traverse_iterator_result null_leave(VALUE obj) { return traverse_cont; } -#endif static VALUE ractor_reset_belonging(VALUE obj) { #if RACTOR_CHECK_MODE > 0 rp(obj); - rb_obj_traverse(obj, reset_belonging_enter, null_leave); + rb_obj_traverse(obj, reset_belonging_enter, null_leave, NULL); #endif return obj; } -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/