diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-10-23 02:58:22 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-10-23 02:58:22 +0000 |
commit | df56684bb6f595e5c2bd7cc6eec0c4026534640f (patch) | |
tree | 5694e105b2b199b5830807dd0aca43c1461bdeba /compile.c | |
parent | acbe98da6057aa790fb89ee52f7669ea290b6979 (diff) | |
download | ruby-df56684bb6f595e5c2bd7cc6eec0c4026534640f.tar.gz |
compile.c: optimize method chain
* compile.c (iseq_peephole_optimize): optimize lengthy safe
navigation method chain. [Feature #11537]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 51 |
1 files changed, 27 insertions, 24 deletions
@@ -1967,33 +1967,36 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * if L2 */ INSN *nobj = (INSN *)get_destination_insn(iobj); - if (nobj->insn_id == BIN(jump)) { - OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0); - } + INSN *pobj = (INSN *)iobj->link.prev; + int prev_dup = (pobj && pobj->insn_id == BIN(dup)); - if (nobj->insn_id == BIN(dup)) { - /* - * dup - * if L1 - * ... - * L1: - * dup - * if L2 - * => - * dup - * if L2 - * ... - * L1: - * dup - * if L2 - */ - INSN *pobj = (INSN *)iobj->link.prev; - nobj = (INSN *)nobj->link.next; - /* basic blocks, with no labels in the middle */ - if ((pobj && pobj->insn_id == BIN(dup)) && - (nobj && nobj->insn_id == iobj->insn_id)) { + for (;;) { + if (nobj->insn_id == BIN(jump)) { + OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0); + } + else if (prev_dup && nobj->insn_id == BIN(dup) && + !!(nobj = (INSN *)nobj->link.next) && + /* basic blocks, with no labels in the middle */ + nobj->insn_id == iobj->insn_id) { + /* + * dup + * if L1 + * ... + * L1: + * dup + * if L2 + * => + * dup + * if L2 + * ... + * L1: + * dup + * if L2 + */ OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0); } + else break; + nobj = (INSN *)get_destination_insn(nobj); } } |