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

ruby-changes:63500

From: Koichi <ko1@a...>
Date: Mon, 2 Nov 2020 01:37:55 +0900 (JST)
Subject: [ruby-changes:63500] db7a3b63ba (master): suppport Ractor.send(move: true) for more deta

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

From db7a3b63bae810a03b19b5577ded1403bb789185 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Sun, 1 Nov 2020 09:56:40 +0900
Subject: suppport Ractor.send(move: true) for more deta

This patch allows to move more data types.

diff --git a/gc.c b/gc.c
index 8d7449a..af7fcef 100644
--- a/gc.c
+++ b/gc.c
@@ -2292,18 +2292,6 @@ rb_newobj_of(VALUE klass, VALUE flags) https://github.com/ruby/ruby/blob/trunk/gc.c#L2292
     return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED);
 }
 
-VALUE
-rb_newobj_with(VALUE src)
-{
-    VALUE klass = RBASIC_CLASS(src);
-    VALUE flags = RBASIC(src)->flags;
-
-    VALUE v1 = RANY(src)->as.values.v1;
-    VALUE v2 = RANY(src)->as.values.v2;
-    VALUE v3 = RANY(src)->as.values.v3;
-    return newobj_of(klass, flags & ~FL_WB_PROTECTED, v1, v2, v3, flags & FL_WB_PROTECTED);
-}
-
 #define UNEXPECTED_NODE(func) \
     rb_bug(#func"(): GC does not handle T_NODE 0x%x(%p) 0x%"PRIxVALUE, \
 	   BUILTIN_TYPE(obj), (void*)(obj), RBASIC(obj)->flags)
diff --git a/ractor.c b/ractor.c
index 203a4a8..d3053ec 100644
--- a/ractor.c
+++ b/ractor.c
@@ -354,107 +354,6 @@ ractor_queue_enq(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_ba https://github.com/ruby/ruby/blob/trunk/ractor.c#L354
     // fprintf(stderr, "%s %p->cnt:%d\n", __func__, rq, rq->cnt);
 }
 
-VALUE rb_newobj_with(VALUE src); // gc.c
-
-static VALUE
-ractor_moving_new(VALUE obj)
-{
-    // create moving object
-    VALUE v = rb_newobj_with(obj);
-
-    // invalidate src object
-    struct RVALUE {
-        VALUE flags;
-        VALUE klass;
-        VALUE v1;
-        VALUE v2;
-        VALUE v3;
-    } *rv = (void *)obj;
-
-    rv->klass = rb_cRactorMovedObject;
-    rv->v1 = 0;
-    rv->v2 = 0;
-    rv->v3 = 0;
-
-    // TODO: record moved location
-    // TODO: check flags for each data types
-
-    return v;
-}
-
-static VALUE
-ractor_move_shallow_copy(VALUE obj)
-{
-    if (rb_ractor_shareable_p(obj)) {
-        return obj;
-    }
-    else {
-        switch (BUILTIN_TYPE(obj)) {
-          case T_STRING:
-          case T_FILE:
-            if (!FL_TEST_RAW(obj, RUBY_FL_EXIVAR)) {
-                return ractor_moving_new(obj);
-            }
-            break;
-          case T_ARRAY:
-            if (!FL_TEST_RAW(obj, RUBY_FL_EXIVAR)) {
-                VALUE ary = ractor_moving_new(obj);
-                long len = RARRAY_LEN(ary);
-                for (long i=0; i<len; i++) {
-                    VALUE e = RARRAY_AREF(ary, i);
-                    RARRAY_ASET(ary, i, ractor_move_shallow_copy(e)); // confirm WB
-                }
-                return ary;
-            }
-            break;
-          default:
-            break;
-        }
-
-        rb_raise(rb_eRactorError, "can't move this this kind of object:%"PRIsVALUE, obj);
-    }
-}
-
-static VALUE
-ractor_moved_setup(VALUE obj)
-{
-#if RACTOR_CHECK_MODE
-    switch (BUILTIN_TYPE(obj)) {
-      case T_STRING:
-      case T_FILE:
-        rb_ractor_setup_belonging(obj);
-        break;
-      case T_ARRAY:
-        rb_ractor_setup_belonging(obj);
-        long len = RARRAY_LEN(obj);
-        for (long i=0; i<len; i++) {
-            VALUE e = RARRAY_AREF(obj, i);
-            if (!rb_ractor_shareable_p(e)) {
-                ractor_moved_setup(e);
-            }
-        }
-        break;
-      default:
-        rb_bug("unreachable");
-    }
-#endif
-    return obj;
-}
-
-static void
-ractor_move_setup(struct rb_ractor_basket *b, VALUE obj)
-{
-    if (rb_ractor_shareable_p(obj)) {
-        b->type = basket_type_ref;
-        b->v = obj;
-    }
-    else {
-        b->type = basket_type_move;
-        b->v = ractor_move_shallow_copy(obj);
-        return;
-    }
-}
-
 static void
 ractor_basket_clear(struct rb_ractor_basket *b)
 {
@@ -463,7 +362,7 @@ ractor_basket_clear(struct rb_ractor_basket *b) https://github.com/ruby/ruby/blob/trunk/ractor.c#L362
     b->sender = Qfalse;
 }
 
-static void ractor_reset_belonging(VALUE obj); // in this file
+static VALUE ractor_reset_belonging(VALUE obj); // in this file
 
 static VALUE
 ractor_basket_accept(struct rb_ractor_basket *b)
@@ -479,11 +378,8 @@ ractor_basket_accept(struct rb_ractor_basket *b) https://github.com/ruby/ruby/blob/trunk/ractor.c#L378
         RB_GC_GUARD(b->v);
         break;
       case basket_type_move:
-        v = ractor_moved_setup(b->v);
-        break;
       case basket_type_will:
-        v = b->v;
-        ractor_reset_belonging(v);
+        v = ractor_reset_belonging(b->v);
         break;
       default:
         rb_bug("unreachable");
@@ -502,19 +398,6 @@ ractor_basket_accept(struct rb_ractor_basket *b) https://github.com/ruby/ruby/blob/trunk/ractor.c#L398
     return v;
 }
 
-static void
-ractor_copy_setup(struct rb_ractor_basket *b, VALUE obj)
-{
-    if (rb_ractor_shareable_p(obj)) {
-        b->type = basket_type_ref;
-        b->v = obj;
-    }
-    else {
-        b->v = rb_marshal_dump(obj, Qnil);
-        b->type = basket_type_copy;
-    }
-}
-
 static VALUE
 ractor_try_receive(rb_execution_context_t *ec, rb_ractor_t *r)
 {
@@ -777,6 +660,13 @@ ractor_send_basket(rb_execution_context_t *ec, rb_ractor_t *r, struct rb_ractor_ https://github.com/ruby/ruby/blob/trunk/ractor.c#L660
     }
 }
 
+static VALUE ractor_move(VALUE obj); // in this file
+static VALUE
+ractor_copy(VALUE obj)
+{
+    return rb_marshal_dump(obj, Qnil);
+}
+
 static void
 ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc, bool is_will)
 {
@@ -787,13 +677,18 @@ ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, https://github.com/ruby/ruby/blob/trunk/ractor.c#L677
         basket->type = basket_type_will;
         basket->v = obj;
     }
+    else if (rb_ractor_shareable_p(obj)) {
+        basket->type = basket_type_ref;
+        basket->v = obj;
+    }
     else if (!RTEST(move)) {
-        ractor_copy_setup(basket, obj);
+        basket->v = ractor_copy(obj);
+        basket->type = basket_type_copy;
     }
     else {
-        ractor_move_setup(basket, obj);
+        basket->type = basket_type_move;
+        basket->v = ractor_move(obj);
     }
-
 }
 
 static VALUE
@@ -2203,13 +2098,344 @@ null_leave(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ractor.c#L2098
 }
 #endif
 
-static void
+static VALUE
 ractor_reset_belonging(VALUE obj)
 {
 #if RACTOR_CHECK_MODE > 0
     rb_obj_traverse(obj, reset_belonging_enter, null_leave);
-    
 #endif
+    return obj;
+}
+
+
+/// traverse and replace function
+
+// 2: stop search
+// 1: skip child
+// 0: continue
+
+struct obj_traverse_replace_data;
+static int obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data);
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_replace_enter_func)(VALUE obj, struct obj_traverse_replace_data *data);
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_replace_leave_func)(VALUE obj, struct obj_traverse_replace_data *data);
+
+struct obj_traverse_replace_data {
+    rb_obj_traverse_replace_enter_func enter_func;
+    rb_obj_traverse_replace_leave_func leave_func;
+
+    st_table *rec;
+    VALUE rec_hash;
+
+    VALUE replacement;
+};
+
+struct obj_traverse_replace_callback_data {
+    bool stop;
+    VALUE src;
+    struct obj_traverse_replace_data *data;
+};
+
+static int
+obj_hash_traverse_replace_foreach_i(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+    return ST_REPLACE;
+}
+
+static int
+obj_hash_traverse_replace_i(st_data_t *key, st_data_t *val, st_data_t ptr, int exists)
+{
+    struct obj_traverse_replace_callback_data *d = (struct obj_traverse_replace_callback_data *)ptr;
+    struct obj_traverse_replace_data *data = d->data;
+
+    if (obj_traverse_replace_i(*key, data)) {
+        d->stop = true;
+        return ST_STOP;
+    }
+    else if (*key != data->replacement) {
+        VALUE v = *key = data->replacement;
+        RB_OBJ_WRITTEN(d->src, Qundef, v);
+    }
+
+    if (obj_traverse_replace_i(*val, data)) {
+        d->stop = true;
+        return ST_STOP;
+    }
+    else if (*val != data->replacement) {
+        VALUE v = *val = data->replacement;
+        RB_OBJ_WRITTEN(d->src, Qundef, v);
+    }
+
+    return ST_CONTINUE;
+}
+
+static struct st_table *
+obj_traverse_replace_rec(struct obj_traverse_replace_data *data)
+{
+    if (UNLIKELY(!data->rec)) {
+        data->rec_hash = rb_ident_hash_new();
+        data->rec = rb_hash_st_table(data->rec_hash);
+    }
+    return data->rec;
+}
+
+static int
+obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
+{
+    VALUE replacement;
+
+    if (RB_SPECIAL_CONST_P(obj)) {
+        data->replacement = obj;
+        return 0;
+    }
+
+    switch (data->enter_func(obj, data)) {
+      case traverse_cont: break;
+      case traverse_skip: return 0; // skip children
+      case traverse_stop: return 1; // stop search
+    }
+
+    replacement = data->replacement;
+
+    if (UNLIKELY(st_lookup(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t *)&replacement))) {
+        data->replacement = replacement;
+        return 0;
+    }
+    else {
+        st_insert(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t)replacement);
+    }
+
+#define CHECK_AND_REPLACE(v) do { \
+    VALUE _val = (v); \
+    if (obj_traverse_replace_i(_val, data)) { return 1; } \
+    else if (data->replacement != _val)     { RB_OBJ_WRITE(obj, &v, data->replacement); } \
+} while (0)
+
+    if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
+        struct gen_ivtbl *ivtbl;
+        rb_ivar_generic_ivtbl_lookup(obj, &ivtbl);
+        for (uint32_t i = 0; i < ivtbl->numiv; i++) {
+            if (ivtbl->ivptr[i] != Qundef) {
+                CHECK_AND_REPLACE(ivtbl->ivptr[i]);
+            }
+        }
+    }
+
+    switch (BUILTIN_TYPE(obj)) {
+      // no child node
+      case T_STRING:
+      case T_FLOAT:
+      case T_BIGNUM:
+      case T_REGEXP:
+      case (... truncated)

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

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