summaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-27 16:44:57 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-27 16:44:57 +0000
commite35fe8d11b889a5646a23df06bbecf16f88c518a (patch)
treed4346b34db86ab7c09ccb2db3f0e2803664e9421 /node.c
parent15270f48a9f3ccd7e57798d7eff4dd8d5d83c259 (diff)
Revert "Revert "Manage AST NODEs out of GC""
This re-introduces r60485. This reverts commit 5a176b75b1187cbd3861c387bde65ff66396a07c. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60488 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'node.c')
-rw-r--r--node.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/node.c b/node.c
index f6011d585d..d9c115ba3c 100644
--- a/node.c
+++ b/node.c
@@ -1211,3 +1211,107 @@ rb_gc_mark_node(NODE *obj)
}
return 0;
}
+
+typedef struct node_buffer_elem_struct {
+ struct node_buffer_elem_struct *next;
+ NODE buf[1];
+} node_buffer_elem_t;
+
+typedef struct node_buffer_struct {
+ long idx, len;
+ node_buffer_elem_t *head;
+ node_buffer_elem_t body;
+} node_buffer_t;
+
+node_buffer_t *
+rb_node_buffer_new()
+{
+ node_buffer_t *nb = xmalloc(sizeof(node_buffer_t) + 16 * sizeof(NODE));
+ nb->idx = 0;
+ nb->len = 16;
+ nb->head = &nb->body;
+ nb->head->next = NULL;
+ return nb;
+}
+
+void
+rb_node_buffer_free(node_buffer_t *nb)
+{
+ node_buffer_elem_t *nbe = nb->head;
+
+ while (nbe != &nb->body) {
+ void *buf = nbe;
+ nbe = nbe->next;
+ xfree(buf);
+ }
+ xfree(nb);
+}
+
+NODE *
+rb_ast_newnode(ast_t *ast)
+{
+ node_buffer_t *nb = ast->node_buffer;
+ if (nb->idx >= nb->len) {
+ long n = nb->len * 2;
+ node_buffer_elem_t *nbe;
+ nbe = xmalloc(sizeof(node_buffer_elem_t) + n * sizeof(NODE));
+ nb->idx = 0;
+ nb->len = n;
+ nbe->next = nb->head;
+ nb->head = nbe;
+ }
+ return &nb->head->buf[nb->idx++];
+}
+
+void
+rb_ast_delete_node(ast_t *ast, NODE *n)
+{
+ (void)ast;
+ (void)n;
+ /* should we implement freelist? */
+}
+
+ast_t *
+rb_ast_new(void)
+{
+ return (ast_t *)rb_imemo_new(imemo_ast, 0, (VALUE)rb_node_buffer_new(), rb_ary_tmp_new(0), 0);
+}
+
+void
+rb_ast_mark(ast_t *ast)
+{
+ if (ast->node_buffer) rb_gc_mark(ast->mark_ary);
+}
+
+void
+rb_ast_free(ast_t *ast)
+{
+ if (ast->node_buffer) rb_node_buffer_free(ast->node_buffer);
+ ast->node_buffer = 0;
+ ast->root = 0;
+ ast->mark_ary = 0;
+}
+
+void
+rb_ast_dispose(ast_t *ast)
+{
+ rb_ast_free(ast);
+ rb_gc_writebarrier_remember((VALUE)ast);
+}
+
+void
+rb_ast_add_mark_object(ast_t *ast, VALUE obj)
+{
+ rb_ary_push(ast->mark_ary, obj);
+}
+
+void
+rb_ast_delete_mark_object(ast_t *ast, VALUE obj)
+{
+ long i;
+ for (i = 0; i < RARRAY_LEN(ast->mark_ary); i++) {
+ if (obj == RARRAY_AREF(ast->mark_ary, i)) {
+ RARRAY_ASET(ast->mark_ary, i, Qnil);
+ }
+ }
+}