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

ruby-changes:57568

From: Aaron <ko1@a...>
Date: Fri, 6 Sep 2019 02:20:05 +0900 (JST)
Subject: [ruby-changes:57568] 581fcde088 (master): Directly mark node objects instead of using a mark array

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

From 581fcde0884e493206b04b3e6b7a069b941dfe46 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Thu, 29 Aug 2019 15:22:41 -0700
Subject: Directly mark node objects instead of using a mark array

This patch changes the AST mark function so that it will walk through
nodes in the NODE buffer marking Ruby objects rather than using a mark
array to guarantee liveness.  The reason I want to do this is so that
when compaction happens on major GCs, node objects will have their
references pinned (or possibly we can update them correctly).

diff --git a/node.c b/node.c
index f4df845..61926ad 100644
--- a/node.c
+++ b/node.c
@@ -1116,6 +1116,7 @@ rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2) https://github.com/ruby/ruby/blob/trunk/node.c#L1116
 
 typedef struct node_buffer_elem_struct {
     struct node_buffer_elem_struct *next;
+    long len;
     NODE buf[FLEX_ARY_LEN];
 } node_buffer_elem_t;
 
@@ -1133,6 +1134,7 @@ rb_node_buffer_new(void) https://github.com/ruby/ruby/blob/trunk/node.c#L1134
     nb->idx = 0;
     nb->len = NODE_BUF_DEFAULT_LEN;
     nb->head = nb->last = (node_buffer_elem_t*) &nb[1];
+    nb->head->len = nb->len;
     nb->head->next = NULL;
     nb->mark_ary = rb_ary_tmp_new(0);
     return nb;
@@ -1159,6 +1161,7 @@ rb_ast_newnode(rb_ast_t *ast) https://github.com/ruby/ruby/blob/trunk/node.c#L1161
 	long n = nb->len * 2;
 	node_buffer_elem_t *nbe;
 	nbe = xmalloc(offsetof(node_buffer_elem_t, buf) + n * sizeof(NODE));
+        nbe->len = n;
 	nb->idx = 0;
 	nb->len = n;
 	nbe->next = nb->head;
@@ -1185,11 +1188,58 @@ rb_ast_new(void) https://github.com/ruby/ruby/blob/trunk/node.c#L1188
     return ast;
 }
 
+typedef void node_itr_t(void *ctx, NODE * node);
+
+static void
+iterate_buffer_elements(node_buffer_elem_t *nbe, long len, node_itr_t *func, void *ctx)
+{
+    long cursor;
+    for (cursor = 0; cursor < len; cursor++) {
+        func(ctx, &nbe->buf[cursor]);
+    }
+}
+
+static void
+iterate_node_values(node_buffer_t *nb, node_itr_t * func, void *ctx)
+{
+    node_buffer_elem_t *nbe = nb->head;
+
+    /* iterate over the head first because it's not full */
+    iterate_buffer_elements(nbe, nb->idx, func, ctx);
+
+    nbe = nbe->next;
+    while (nbe) {
+        iterate_buffer_elements(nbe, nbe->len, func, ctx);
+        nbe = nbe->next;
+    }
+}
+
+static void
+mark_ast_value(void *ctx, NODE * node)
+{
+    switch (nd_type(node)) {
+        case NODE_LIT:
+        case NODE_STR:
+        case NODE_XSTR:
+        case NODE_DSTR:
+        case NODE_DXSTR:
+        case NODE_DREGX:
+        case NODE_DSYM:
+            rb_gc_mark(node->nd_lit);
+            break;
+    }
+}
+
 void
 rb_ast_mark(rb_ast_t *ast)
 {
     if (ast->node_buffer) rb_gc_mark(ast->node_buffer->mark_ary);
     if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option);
+    if (ast->node_buffer) {
+        node_buffer_t *nb = ast->node_buffer;
+
+        iterate_node_values(nb, mark_ast_value, NULL);
+    }
 }
 
 void
diff --git a/parse.y b/parse.y
index 63d8f53..3cf485d 100644
--- a/parse.y
+++ b/parse.y
@@ -299,7 +299,7 @@ struct parser_params { https://github.com/ruby/ruby/blob/trunk/parse.y#L299
 };
 
 #define new_tmpbuf() \
-    (rb_imemo_tmpbuf_t *)add_mark_object(p, rb_imemo_tmpbuf_auto_free_pointer(NULL))
+    (rb_imemo_tmpbuf_t *)add_tmpbuf_mark_object(p, rb_imemo_tmpbuf_auto_free_pointer(NULL))
 
 #define intern_cstr(n,l,en) rb_intern3(n,l,en)
 
@@ -337,6 +337,13 @@ rb_discard_node(struct parser_params *p, NODE *n) https://github.com/ruby/ruby/blob/trunk/parse.y#L337
 {
     rb_ast_delete_node(p->ast, n);
 }
+
+static inline VALUE
+add_tmpbuf_mark_object(struct parser_params *p, VALUE obj)
+{
+    rb_ast_add_mark_object(p->ast, obj);
+    return obj;
+}
 #endif
 
 static inline VALUE
@@ -347,7 +354,11 @@ add_mark_object(struct parser_params *p, VALUE obj) https://github.com/ruby/ruby/blob/trunk/parse.y#L354
 	&& !RB_TYPE_P(obj, T_NODE) /* Ripper jumbles NODE objects and other objects... */
 #endif
     ) {
+#ifdef RIPPER
 	rb_ast_add_mark_object(p->ast, obj);
+#else
+        RB_OBJ_WRITTEN(p->ast, Qundef, obj);
+#endif
     }
     return obj;
 }
-- 
cgit v0.10.2


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

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