summaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2019-11-04 16:04:58 -0800
committerAaron Patterson <tenderlove@ruby-lang.org>2019-11-05 08:24:14 -0800
commit7460c884fb06a2c50a4a771761003ed78c8b28ce (patch)
tree90df9fe2e0ecb4e60c85ea6c6066bca3110e4795 /node.c
parentd47b643428a5c19d5a0c2f2213c95ab03d63a24c (diff)
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.
Diffstat (limited to 'node.c')
-rw-r--r--node.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/node.c b/node.c
index cd8d73171e..6477446c7b 100644
--- a/node.c
+++ b/node.c
@@ -1129,7 +1129,7 @@ typedef struct {
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)
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)
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)
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);
}