ruby-changes:59880
From: Nobuyoshi <ko1@a...>
Date: Thu, 30 Jan 2020 17:50:08 +0900 (JST)
Subject: [ruby-changes:59880] 3893a8dd42 (master): Optimized branches in pattern matching
https://git.ruby-lang.org/ruby.git/commit/?id=3893a8dd42 From 3893a8dd42fb3bbd71750648c3c0de118955a6ea Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 30 Jan 2020 17:47:09 +0900 Subject: Optimized branches in pattern matching diff --git a/compile.c b/compile.c index 0eb94da..39c6bc1 100644 --- a/compile.c +++ b/compile.c @@ -5485,8 +5485,10 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no https://github.com/ruby/ruby/blob/trunk/compile.c#L5485 return COMPILE_OK; } +static int iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, int in_alt_pattern); + static int -iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int in_alt_pattern) +iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, int in_alt_pattern) { const int line = nd_line(node); @@ -5539,12 +5541,11 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5541 * end * end * true - * goto fin + * goto matched * type_error: * FrozenCore.raise TypeError * match_failed: - * false - * fin: + * goto unmatched */ struct rb_ary_pattern_info *apinfo = node->nd_apinfo; const NODE *args = apinfo->pre_args; @@ -5555,11 +5556,10 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5556 const int use_rest_num = apinfo->rest_arg && (NODE_NAMED_REST_P(apinfo->rest_arg) || (!NODE_NAMED_REST_P(apinfo->rest_arg) && post_args_num > 0)); - LABEL *match_failed, *type_error, *fin; + LABEL *match_failed, *type_error; int i; match_failed = NEW_LABEL(line); type_error = NEW_LABEL(line); - fin = NEW_LABEL(line); if (use_rest_num) { ADD_INSN1(ret, line, putobject, INT2FIX(0)); /* allocate stack for rest_num */ @@ -5594,9 +5594,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5594 ADD_INSN(ret, line, dup); ADD_INSN1(ret, line, putobject, INT2FIX(i)); ADD_SEND(ret, line, idAREF, INT2FIX(1)); - iseq_compile_pattern_each(iseq, ret, args->nd_head, in_alt_pattern); + CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern)); args = args->nd_next; - ADD_INSNL(ret, line, branchunless, match_failed); } if (apinfo->rest_arg) { @@ -5610,8 +5609,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5609 ADD_INSN1(ret, line, setn, INT2FIX(4)); ADD_SEND(ret, line, idAREF, INT2FIX(2)); - iseq_compile_pattern_each(iseq, ret, apinfo->rest_arg, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); + CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_alt_pattern)); } else { if (post_args_num > 0) { @@ -5634,17 +5632,15 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5632 ADD_SEND(ret, line, idPLUS, INT2FIX(1)); ADD_SEND(ret, line, idAREF, INT2FIX(1)); - iseq_compile_pattern_each(iseq, ret, args->nd_head, in_alt_pattern); + CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern)); args = args->nd_next; - ADD_INSNL(ret, line, branchunless, match_failed); } ADD_INSN(ret, line, pop); if (use_rest_num) { ADD_INSN(ret, line, pop); } - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, fin); + ADD_INSNL(ret, line, jump, matched); ADD_LABEL(ret, type_error); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); @@ -5657,8 +5653,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5653 if (use_rest_num) { ADD_INSN(ret, line, pop); } - ADD_INSN1(ret, line, putobject, Qfalse); - ADD_LABEL(ret, fin); + ADD_INSNL(ret, line, jump, unmatched); break; } @@ -5717,19 +5712,17 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5712 * end * end * true - * goto fin + * goto matched * type_error: * FrozenCore.raise TypeError * match_failed: - * false - * fin: + * goto unmatched */ - LABEL *match_failed, *type_error, *fin; + LABEL *match_failed, *type_error; VALUE keys = Qnil; match_failed = NEW_LABEL(line); type_error = NEW_LABEL(line); - fin = NEW_LABEL(line); if (node->nd_pkwargs && !node->nd_pkwrestarg) { const NODE *kw_args = node->nd_pkwargs->nd_head; @@ -5796,8 +5789,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5789 ADD_INSN(match_values, line, dup); ADD_INSN1(match_values, line, putobject, key); ADD_SEND(match_values, line, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); - iseq_compile_pattern_each(iseq, match_values, value_node, in_alt_pattern); - ADD_INSNL(match_values, line, branchunless, match_failed); + CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_alt_pattern)); args = args->nd_next->nd_next; } ADD_SEQ(ret, match_values); @@ -5817,14 +5809,12 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5809 } else { ADD_INSN(ret, line, dup); - iseq_compile_pattern_each(iseq, ret, node->nd_pkwrestarg, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); + CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_alt_pattern)); } } ADD_INSN(ret, line, pop); - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, fin); + ADD_INSNL(ret, line, jump, matched); ADD_LABEL(ret, type_error); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); @@ -5834,9 +5824,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5824 ADD_LABEL(ret, match_failed); ADD_INSN(ret, line, pop); - ADD_INSN1(ret, line, putobject, Qfalse); - - ADD_LABEL(ret, fin); + ADD_INSNL(ret, line, jump, unmatched); break; } case NODE_LIT: @@ -5861,6 +5849,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5849 case NODE_COLON3: CHECK(COMPILE(ret, "case in literal", node)); ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); + ADD_INSNL(ret, line, branchif, matched); + ADD_INSNL(ret, line, jump, unmatched); break; case NODE_LASGN: { struct rb_iseq_constant_body *const body = iseq->body; @@ -5877,7 +5867,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5867 } ADD_SETLOCAL(ret, line, idx, get_lvar_level(iseq)); - ADD_INSN1(ret, line, putobject, Qtrue); + ADD_INSNL(ret, line, jump, matched); break; } case NODE_DASGN: @@ -5902,16 +5892,14 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5892 return COMPILE_NG; } ADD_SETLOCAL(ret, line, ls - idx, lv); - ADD_INSN1(ret, line, putobject, Qtrue); + ADD_INSNL(ret, line, jump, matched); break; } case NODE_IF: case NODE_UNLESS: { - LABEL *match_failed, *fin; - match_failed = NEW_LABEL(line); - fin = NEW_LABEL(line); - iseq_compile_pattern_each(iseq, ret, node->nd_body, in_alt_pattern); - ADD_INSNL(ret, line, branchunless, match_failed); + LABEL *match_failed; + match_failed = unmatched; + CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_alt_pattern)); CHECK(COMPILE(ret, "case in if", node->nd_cond)); if (nd_type(node) == NODE_IF) { ADD_INSNL(ret, line, branchunless, match_failed); @@ -5919,13 +5907,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L5907 else { ADD_INSNL(ret, line, branchif, match_failed); } - ADD_INSN1(ret, line, putobject, Qtrue); - ADD_INSNL(ret, line, jump, fin); - - ADD_LABEL(ret, match_failed); - ADD_INSN1(ret, line, putobject, Qfalse); - - ADD_LABEL(ret, fin); (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/