[前][次][番号順一覧][スレッド一覧]

ruby-changes:63482

From: Koichi <ko1@a...>
Date: Sat, 31 Oct 2020 01:48:27 +0900 (JST)
Subject: [ruby-changes:63482] fd08927699 (master): Ractor's "will" doesn't need copying.

https://git.ruby-lang.org/ruby.git/commit/?id=fd08927699

From fd089276999393a6f6bb2a0b614ac76ca6151ab2 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Sat, 31 Oct 2020 00:40:04 +0900
Subject: Ractor's "will" doesn't need copying.

`r = Ractor.new{ expr }` generates the block return value from `expr`
and we can get this value by `r.take`. Ractor.yield and Ractor#take
passing values by copying on default. However, the block return value
(we named it "will" in the code) is not referred from the Ractor
because the Ractor is already dead. So we can pass the reference
of "will" to another ractor without copying. We can apply same story
for the propagated exception.

diff --git a/ractor.c b/ractor.c
index a89da04..203a4a8 100644
--- a/ractor.c
+++ b/ractor.c
@@ -445,7 +445,7 @@ static void https://github.com/ruby/ruby/blob/trunk/ractor.c#L445
 ractor_move_setup(struct rb_ractor_basket *b, VALUE obj)
 {
     if (rb_ractor_shareable_p(obj)) {
-        b->type = basket_type_shareable;
+        b->type = basket_type_ref;
         b->v = obj;
     }
     else {
@@ -463,35 +463,41 @@ ractor_basket_clear(struct rb_ractor_basket *b) https://github.com/ruby/ruby/blob/trunk/ractor.c#L463
     b->sender = Qfalse;
 }
 
+static void ractor_reset_belonging(VALUE obj); // in this file
+
 static VALUE
 ractor_basket_accept(struct rb_ractor_basket *b)
 {
     VALUE v;
     switch (b->type) {
-      case basket_type_shareable:
+      case basket_type_ref:
         VM_ASSERT(rb_ractor_shareable_p(b->v));
         v = b->v;
         break;
-      case basket_type_copy_marshal:
+      case basket_type_copy:
         v = rb_marshal_load(b->v);
         RB_GC_GUARD(b->v);
         break;
-      case basket_type_exception:
-        {
-            VALUE cause = rb_marshal_load(b->v);
-            VALUE err = rb_exc_new_cstr(rb_eRactorRemoteError, "thrown by remote Ractor.");
-            rb_ivar_set(err, rb_intern("@ractor"), b->sender);
-            ractor_basket_clear(b);
-            rb_ec_setup_exception(NULL, err, cause);
-            rb_exc_raise(err);
-        }
-        // unreachable
       case basket_type_move:
         v = ractor_moved_setup(b->v);
         break;
+      case basket_type_will:
+        v = b->v;
+        ractor_reset_belonging(v);
+        break;
       default:
         rb_bug("unreachable");
     }
+
+    if (b->exception) {
+        VALUE cause = v;
+        VALUE err = rb_exc_new_cstr(rb_eRactorRemoteError, "thrown by remote Ractor.");
+        rb_ivar_set(err, rb_intern("@ractor"), b->sender);
+        ractor_basket_clear(b);
+        rb_ec_setup_exception(NULL, err, cause);
+        rb_exc_raise(err);
+    }
+
     ractor_basket_clear(b);
     return v;
 }
@@ -500,18 +506,12 @@ static void https://github.com/ruby/ruby/blob/trunk/ractor.c#L506
 ractor_copy_setup(struct rb_ractor_basket *b, VALUE obj)
 {
     if (rb_ractor_shareable_p(obj)) {
-        b->type = basket_type_shareable;
+        b->type = basket_type_ref;
         b->v = obj;
     }
     else {
-#if 0
-        // TODO: consider custom copy protocol
-        switch (BUILTIN_TYPE(obj)) {
-
-        }
-#endif
         b->v = rb_marshal_dump(obj, Qnil);
-        b->type = basket_type_copy_marshal;
+        b->type = basket_type_copy;
     }
 }
 
@@ -778,27 +778,29 @@ ractor_send_basket(rb_execution_context_t *ec, rb_ractor_t *r, struct rb_ractor_ https://github.com/ruby/ruby/blob/trunk/ractor.c#L778
 }
 
 static void
-ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc)
+ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc, bool is_will)
 {
     basket->sender = rb_ec_ractor_ptr(ec)->self;
+    basket->exception = exc;
 
-    if (!RTEST(move)) {
+    if (is_will) {
+        basket->type = basket_type_will;
+        basket->v = obj;
+    }
+    else if (!RTEST(move)) {
         ractor_copy_setup(basket, obj);
     }
     else {
         ractor_move_setup(basket, obj);
     }
 
-    if (exc) {
-        basket->type = basket_type_exception;
-    }
 }
 
 static VALUE
 ractor_send(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move)
 {
     struct rb_ractor_basket basket;
-    ractor_basket_setup(ec, &basket, obj, move, false);
+    ractor_basket_setup(ec, &basket, obj, move, false, false);
     ractor_send_basket(ec, r, &basket);
     return r->self;
 }
@@ -942,7 +944,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield https://github.com/ruby/ruby/blob/trunk/ractor.c#L944
         wait_status |= wait_yielding;
         alen++;
 
-        ractor_basket_setup(ec, &cr->wait.yielded_basket, yielded_value, move, false);
+        ractor_basket_setup(ec, &cr->wait.yielded_basket, yielded_value, move, false, false);
     }
 
     // TODO: shuffle actions
@@ -1400,7 +1402,7 @@ ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool e https://github.com/ruby/ruby/blob/trunk/ractor.c#L1402
     ASSERT_ractor_unlocking(cr);
 
     struct rb_ractor_basket basket;
-    ractor_basket_setup(ec, &basket, v, Qfalse, exc);
+    ractor_basket_setup(ec, &basket, v, Qfalse, exc, true);
 
   retry:
     if (ractor_try_yield(ec, cr, &basket)) {
@@ -1921,7 +1923,7 @@ obj_hash_traverse_i(VALUE key, VALUE val, VALUE ptr) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1923
 }
 
 static void
-obj_tdata_traverse_i(VALUE obj, void *ptr)
+obj_traverse_reachable_i(VALUE obj, void *ptr)
 {
     struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr;
 
@@ -2031,12 +2033,13 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data) https://github.com/ruby/ruby/blob/trunk/ractor.c#L2033
         break;
 
       case T_DATA:
+      case T_IMEMO:
         {
             struct obj_traverse_callback_data d = {
                 .stop = false,
                 .data = data,
             };
-            rb_objspace_reachable_objects_from(obj, obj_tdata_traverse_i, &d);
+            rb_objspace_reachable_objects_from(obj, obj_traverse_reachable_i, &d);
             if (d.stop) return 1;
         }
         break;
@@ -2180,4 +2183,33 @@ rb_ractor_shareable_p_continue(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ractor.c#L2183
     }
 }
 
+#if RACTOR_CHECK_MODE > 0
+static enum obj_traverse_iterator_result
+reset_belonging_enter(VALUE obj)
+{
+    if (rb_ractor_shareable_p(obj)) {
+        return traverse_skip;
+    }
+    else {
+        rb_ractor_setup_belonging(obj);
+        return traverse_cont;
+    }
+}
+
+static enum obj_traverse_iterator_result
+null_leave(VALUE obj)
+{
+    return traverse_cont;
+}
+#endif
+
+static void
+ractor_reset_belonging(VALUE obj)
+{
+#if RACTOR_CHECK_MODE > 0
+    rb_obj_traverse(obj, reset_belonging_enter, null_leave);
+    
+#endif
+}
+
 #include "ractor.rbinc"
diff --git a/ractor.h b/ractor.h
index e3adeb8..6e2f09f 100644
--- a/ractor.h
+++ b/ractor.h
@@ -10,15 +10,15 @@ https://github.com/ruby/ruby/blob/trunk/ractor.h#L10
 
 enum rb_ractor_basket_type {
     basket_type_none,
-    basket_type_shareable,
-    basket_type_copy_marshal,
-    basket_type_copy_custom,
+    basket_type_ref,
+    basket_type_copy,
     basket_type_move,
-    basket_type_exception,
+    basket_type_will,
 };
 
 struct rb_ractor_basket {
     enum rb_ractor_basket_type type;
+    bool exception;
     VALUE v;
     VALUE sender;
 };
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]