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

ruby-changes:58588

From: Aaron <ko1@a...>
Date: Wed, 6 Nov 2019 01:24:35 +0900 (JST)
Subject: [ruby-changes:58588] 7460c884fb (master): Use an identity hash for pinning Ripper objects

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

From 7460c884fb06a2c50a4a771761003ed78c8b28ce Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Mon, 4 Nov 2019 16:04:58 -0800
Subject: Use an identity hash for pinning Ripper objects

Ripper reuses parse.y for its implementation.  Ripper changes the
grammar productions to sometimes return Ruby objects.  This Ruby objects
are put in to the parser's stack, so they must be kept alive.  This is
where the "mark_ary" comes in.  The mark array ensures that Ruby objects
created and pushed on the stack during the course of parsing will stay
alive for the life of the parsing functions.

Unfortunately, Arrays do not prevent their contents from moving.  If the
compactor runs, objects on the parser stack could move because the array
won't prevent them from moving.  But the GC doesn't know about the
parser stack, so it can't update references in that stack (it will
update them in the array).

This commit changes the mark array to be an identity hash.  Since the
identity hash relies on memory addresses for the definition of identity,
the GC will not allow keys in an identity hash to move.  We can prevent
movement of objects in the parser stack by sticking them in an identity
hash.

diff --git a/node.c b/node.c
index cd8d731..6477446 100644
--- a/node.c
+++ b/node.c
@@ -1129,7 +1129,7 @@ typedef struct { https://github.com/ruby/ruby/blob/trunk/node.c#L1129
 struct node_buffer_struct {
     node_buffer_list_t unmarkable;
     node_buffer_list_t markable;
-    VALUE mark_ary;
+    VALUE mark_hash;
 };
 
 static void
@@ -1154,7 +1154,7 @@ rb_node_buffer_new(void) https://github.com/ruby/ruby/blob/trunk/node.c#L1154
     node_buffer_t *nb = ruby_xmalloc(alloc_size);
     init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1]);
     init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size));
-    nb->mark_ary = Qnil;
+    nb->mark_hash = Qnil;
     return nb;
 }
 
@@ -1350,7 +1350,7 @@ rb_ast_update_references(rb_ast_t *ast) https://github.com/ruby/ruby/blob/trunk/node.c#L1350
 void
 rb_ast_mark(rb_ast_t *ast)
 {
-    if (ast->node_buffer) rb_gc_mark(ast->node_buffer->mark_ary);
+    if (ast->node_buffer) rb_gc_mark(ast->node_buffer->mark_hash);
     if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option);
     if (ast->node_buffer) {
         node_buffer_t *nb = ast->node_buffer;
@@ -1403,8 +1403,8 @@ rb_ast_dispose(rb_ast_t *ast) https://github.com/ruby/ruby/blob/trunk/node.c#L1403
 void
 rb_ast_add_mark_object(rb_ast_t *ast, VALUE obj)
 {
-    if (NIL_P(ast->node_buffer->mark_ary)) {
-        RB_OBJ_WRITE(ast, &ast->node_buffer->mark_ary, rb_ary_tmp_new(0));
+    if (NIL_P(ast->node_buffer->mark_hash)) {
+        RB_OBJ_WRITE(ast, &ast->node_buffer->mark_hash, rb_ident_hash_new());
     }
-    rb_ary_push(ast->node_buffer->mark_ary, obj);
+    rb_hash_aset(ast->node_buffer->mark_hash, obj, Qtrue);
 }
-- 
cgit v0.10.2


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

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