зеркало из https://github.com/github/ruby.git
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).
This commit is contained in:
Родитель
70d3596a4a
Коммит
581fcde088
50
node.c
50
node.c
|
@ -1116,6 +1116,7 @@ rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
|
|||
|
||||
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)
|
|||
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)
|
|||
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)
|
|||
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
|
||||
|
|
13
parse.y
13
parse.y
|
@ -299,7 +299,7 @@ struct parser_params {
|
|||
};
|
||||
|
||||
#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)
|
|||
{
|
||||
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)
|
|||
&& !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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче