ruby-changes:57574
From: Aaron <ko1@a...>
Date: Fri, 6 Sep 2019 04:45:15 +0900 (JST)
Subject: [ruby-changes:57574] 092f31e7e2 (master): Reverting node marking until I can fix GC problem.
https://git.ruby-lang.org/ruby.git/commit/?id=092f31e7e2 From 092f31e7e23c0ee04df987f0c0f979d036971804 Mon Sep 17 00:00:00 2001 From: Aaron Patterson <tenderlove@r...> Date: Thu, 5 Sep 2019 12:44:23 -0700 Subject: Reverting node marking until I can fix GC problem. Looks like we're getting WB misses during stressful GC on startup. I am investigating. diff --git a/node.c b/node.c index 64e2d8f..f4df845 100644 --- a/node.c +++ b/node.c @@ -1116,45 +1116,30 @@ 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; -typedef struct { +struct node_buffer_struct { long idx, len; node_buffer_elem_t *head; node_buffer_elem_t *last; -} node_buffer_list_t; - -struct node_buffer_struct { - node_buffer_list_t unmarkable; - node_buffer_list_t markable; VALUE mark_ary; }; -static void -init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head) +static node_buffer_t * +rb_node_buffer_new(void) { + node_buffer_t *nb = xmalloc(sizeof(node_buffer_t) + offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE)); nb->idx = 0; nb->len = NODE_BUF_DEFAULT_LEN; - nb->head = nb->last = head; - nb->head->len = nb->len; + nb->head = nb->last = (node_buffer_elem_t*) &nb[1]; nb->head->next = NULL; -} - -static node_buffer_t * -rb_node_buffer_new(void) -{ - size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE); - node_buffer_t *nb = xmalloc(sizeof(node_buffer_t) + (bucket_size * 2)); - 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_ary = rb_ary_tmp_new(0); return nb; } static void -node_buffer_list_free(node_buffer_list_t * nb) +rb_node_buffer_free(node_buffer_t *nb) { node_buffer_elem_t *nbe = nb->head; @@ -1163,24 +1148,17 @@ node_buffer_list_free(node_buffer_list_t * nb) https://github.com/ruby/ruby/blob/trunk/node.c#L1148 nbe = nbe->next; xfree(buf); } -} - -static void -rb_node_buffer_free(node_buffer_t *nb) -{ - node_buffer_list_free(&nb->unmarkable); - node_buffer_list_free(&nb->markable); xfree(nb); } -static NODE * -ast_newnode_in_bucket(node_buffer_list_t *nb) +NODE * +rb_ast_newnode(rb_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(offsetof(node_buffer_elem_t, buf) + n * sizeof(NODE)); - nbe->len = n; nb->idx = 0; nb->len = n; nbe->next = nb->head; @@ -1189,27 +1167,6 @@ ast_newnode_in_bucket(node_buffer_list_t *nb) https://github.com/ruby/ruby/blob/trunk/node.c#L1167 return &nb->head->buf[nb->idx++]; } -NODE * -rb_ast_newnode(rb_ast_t *ast, enum node_type type) -{ - node_buffer_t *nb = ast->node_buffer; - switch (type) { - case NODE_LIT: - case NODE_STR: - case NODE_XSTR: - case NODE_DSTR: - case NODE_DXSTR: - case NODE_DREGX: - case NODE_DSYM: - case NODE_ARGS: - case NODE_SCOPE: - case NODE_ARYPTN: - return ast_newnode_in_bucket(&nb->markable); - default: - return ast_newnode_in_bucket(&nb->unmarkable); - } -} - void rb_ast_delete_node(rb_ast_t *ast, NODE *n) { @@ -1222,85 +1179,17 @@ rb_ast_t * https://github.com/ruby/ruby/blob/trunk/node.c#L1179 rb_ast_new(void) { node_buffer_t *nb = rb_node_buffer_new(); + VALUE mark_ary = nb->mark_ary; rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (VALUE)nb); + RB_OBJ_WRITTEN(ast, Qnil, mark_ary); 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_list_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_SCOPE: - { - ID *buf = node->nd_tbl; - if (buf) { - unsigned int size = (unsigned int)*buf; - rb_gc_mark((VALUE)buf[size + 1]); - } - break; - } - case NODE_ARYPTN: - { - struct rb_ary_pattern_info *apinfo = node->nd_apinfo; - rb_gc_mark(apinfo->imemo); - break; - } - case NODE_ARGS: - { - struct rb_args_info *args = node->nd_ainfo; - rb_gc_mark(args->imemo); - break; - } - 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; - default: - rb_bug("unreachable"); - } -} - 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->markable, mark_ast_value, NULL); - } } void @@ -1312,18 +1201,6 @@ rb_ast_free(rb_ast_t *ast) https://github.com/ruby/ruby/blob/trunk/node.c#L1201 } } -static size_t -buffer_list_size(node_buffer_list_t *nb) -{ - size_t size = 0; - node_buffer_elem_t *nbe = nb->head; - while (nbe != nb->last) { - nbe = nbe->next; - size += offsetof(node_buffer_elem_t, buf) + nb->len * sizeof(NODE); - } - return size; -} - size_t rb_ast_memsize(const rb_ast_t *ast) { @@ -1332,8 +1209,11 @@ rb_ast_memsize(const rb_ast_t *ast) https://github.com/ruby/ruby/blob/trunk/node.c#L1209 if (nb) { size += sizeof(node_buffer_t) + offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE); - size += buffer_list_size(&nb->unmarkable); - size += buffer_list_size(&nb->markable); + node_buffer_elem_t *nbe = nb->head; + while (nbe != nb->last) { + nbe = nbe->next; + size += offsetof(node_buffer_elem_t, buf) + nb->len * sizeof(NODE); + } } return size; } @@ -1347,8 +1227,5 @@ rb_ast_dispose(rb_ast_t *ast) https://github.com/ruby/ruby/blob/trunk/node.c#L1227 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)); - } rb_ary_push(ast->node_buffer->mark_ary, obj); } diff --git a/node.h b/node.h index 220438e..dbc3162 100644 --- a/node.h +++ b/node.h @@ -409,7 +409,7 @@ void rb_ast_dispose(rb_ast_t*); https://github.com/ruby/ruby/blob/trunk/node.h#L409 void rb_ast_free(rb_ast_t*); size_t rb_ast_memsize(const rb_ast_t*); void rb_ast_add_mark_object(rb_ast_t*, VALUE); -NODE *rb_ast_newnode(rb_ast_t*, enum node_type type); +NODE *rb_ast_newnode(rb_ast_t*); void rb_ast_delete_node(rb_ast_t*, NODE *n); VALUE rb_parser_new(void); @@ -452,14 +452,12 @@ struct rb_args_info { https://github.com/ruby/ruby/blob/trunk/node.h#L452 NODE *opt_args; int no_kwarg; - VALUE imemo; }; struct rb_ary_pattern_info { NODE *pre_args; NODE *rest_arg; NODE *post_args; - VALUE imemo; }; struct parser_params; diff --git a/parse.y b/parse.y index 29b8628..63d8f53 100644 --- a/parse.y +++ b/parse.y @@ -298,6 +298,9 @@ struct parser_params { https://github.com/ruby/ruby/blob/trunk/parse.y#L298 #endif }; +#define new_tmpbuf() \ + (rb_imemo_tmpbuf_t *)add_mark_object(p, rb_imemo_tmpbuf_auto_free_pointer(NULL)) + #define intern_cstr(n,l,en) rb_intern3(n,l,en) #define STR_NEW(ptr,len) rb_enc_str_new((ptr),(len),p->enc) @@ -344,11 +347,7 @@ add_mark_object(struct parser_params *p, VALUE obj) https://github.com/ruby/ruby/blob/trunk/parse.y#L347 && !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; } @@ -2787,11 +2786,10 @@ primary : literal https://github.com/ruby/ruby/blob/trunk/parse.y#L2786 ID id = internal_id(p); NODE *m = NEW_ARGS_AUX(0, 0, &NULL_LOC); NODE *args, *scope, *internal_var = NEW_DVAR(id, &@2); - ID *tbl = ALLOC_N(ID, 3); - VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer(tbl); - RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf); + rb_imemo_tmpbuf_t *tmpbuf = new_tmpbuf(); + ID *tbl = ALLOC_N(ID, 2); tbl[0] = 1 /* length of local var table */; tbl[1] = id /* internal id */; - tbl[2] = tmpbuf; + tmpbuf->ptr = (VALUE *)tbl; switch (nd_type($2)) { case NODE_LASGN: @@ -9357,7 +9355,7 @@ yylex(YYSTYPE *lval, YYLTYPE *yylloc, struct parser_params *p) https://github.com/ruby/ruby/blob/trunk/parse.y#L9355 static NODE* node_newnode(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2, const rb_code_location_t *loc) { - NODE *n = rb_ast_newnode(p->ast, type); + NODE *n = rb_ast_newnode(p->ast); rb_node_init(n, type, a0, a1, a2); @@ -9611,7 +9609,9 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l https://github.c (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/