Fix gc_verify_internal_consistency error for pattern_matching in ripper

`gc_verify_internal_consistency` reports "found internal inconsistency"
for "test_pattern_matching.rb".

http://ci.rvm.jp/results/trunk-gc-asserts@ruby-sp2-docker/4501173

Ruby's parser manages objects by two different ways.

1. For parser

* markable node holds objects
* call `RB_OBJ_WRITTEN` with `p->ast` as parent
* `mark_ast_value` marks objects

2. For ripper

* unmarkable node, NODE_RIPPER/NODE_CDECL, holds objects
* call `rb_ast_add_mark_object`. This function calls `rb_hash_aset` then
  `RB_OBJ_WRITTEN` is called with `mark_hash` as parent
* `mark_hash` marks objects

However in current pattern_matching implementation

* markable node holds objects
* call `rb_ast_add_mark_object`

This commit fix it to be #2.

This was inconsistency however always `mark_hash` is
made young by `rb_ast_add_mark_object` call then objects
are not collected.
This commit is contained in:
yui-knk 2023-03-30 19:26:29 +09:00 committed by Yuichiro Kaneko
parent a8782c454c
commit 3488eda41d
Notes: git 2023-03-31 00:38:55 +00:00

35
parse.y
View File

@ -830,6 +830,8 @@ static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYP
#else /* RIPPER */
#define NODE_RIPPER NODE_CDECL
#define NEW_RIPPER(a,b,c,loc) (VALUE)NEW_CDECL(a,b,c,loc)
#define NODE_RIPPER2 NODE_OP_CDECL
#define NEW_RIPPER2(a,b,c,loc) (VALUE)NEW_OP_CDECL(a,c,b,loc)
static inline int ripper_is_node_yylval(VALUE n);
@ -842,6 +844,15 @@ ripper_new_yylval(struct parser_params *p, ID a, VALUE b, VALUE c)
return NEW_RIPPER(a, b, c, &NULL_LOC);
}
static inline VALUE
ripper_new_yylval2(struct parser_params *p, VALUE a, VALUE b, VALUE c)
{
add_mark_object(p, a);
add_mark_object(p, b);
add_mark_object(p, c);
return NEW_RIPPER2(a, b, c, &NULL_LOC);
}
static inline int
ripper_is_node_yylval(VALUE n)
{
@ -1115,14 +1126,7 @@ new_array_pattern(struct parser_params *p, VALUE constant, VALUE pre_arg, VALUE
static VALUE
new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest, VALUE rest_arg, VALUE post_args, const YYLTYPE *loc)
{
NODE *t;
t = rb_node_newnode(NODE_ARYPTN, pre_args, rest_arg, post_args, &NULL_LOC);
add_mark_object(p, pre_args);
add_mark_object(p, rest_arg);
add_mark_object(p, post_args);
return (VALUE)t;
return ripper_new_yylval2(p, pre_args, rest_arg, post_args);
}
static VALUE
@ -1137,13 +1141,7 @@ new_find_pattern(struct parser_params *p, VALUE constant, VALUE fndptn, const YY
static VALUE
new_find_pattern_tail(struct parser_params *p, VALUE pre_rest_arg, VALUE args, VALUE post_rest_arg, const YYLTYPE *loc)
{
NODE *t;
t = rb_node_newnode(NODE_FNDPTN, pre_rest_arg, args, post_rest_arg, &NULL_LOC);
add_mark_object(p, pre_rest_arg);
add_mark_object(p, args);
add_mark_object(p, post_rest_arg);
return (VALUE)t;
return ripper_new_yylval2(p, pre_rest_arg, args, post_rest_arg);
}
#define new_hash(p,h,l) rb_ary_new_from_args(0)
@ -1165,18 +1163,13 @@ new_hash_pattern(struct parser_params *p, VALUE constant, VALUE hshptn, const YY
static VALUE
new_hash_pattern_tail(struct parser_params *p, VALUE kw_args, VALUE kw_rest_arg, const YYLTYPE *loc)
{
NODE *t;
if (kw_rest_arg) {
kw_rest_arg = dispatch1(var_field, kw_rest_arg);
}
else {
kw_rest_arg = Qnil;
}
t = rb_node_newnode(NODE_HSHPTN, kw_args, kw_rest_arg, 0, &NULL_LOC);
add_mark_object(p, kw_args);
add_mark_object(p, kw_rest_arg);
return (VALUE)t;
return ripper_new_yylval2(p, kw_args, kw_rest_arg, Qnil);
}
#define new_defined(p,expr,loc) dispatch1(defined, (expr))