diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-11-19 05:12:14 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-11-19 05:12:14 +0000 |
commit | d653c3fedd3ca509612ffba26eb716e4759f5aef (patch) | |
tree | 22b33073b0029a36f1218a741f989a9816a0d9e2 /compile.c | |
parent | ebcd21dcf0e324511ea724c475c04b39ca3e518b (diff) | |
download | ruby-d653c3fedd3ca509612ffba26eb716e4759f5aef.tar.gz |
compile.c: tailcall before specialize
* compile.c (iseq_tailcall_optimize): apply tail call optimization
before conversion to specialized instructions. when looking
back from `leave` instruction, `send` instructions have been
translated already.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52663 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 32 |
1 files changed, 25 insertions, 7 deletions
@@ -2100,7 +2100,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } - if (do_tailcallopt && iobj->insn_id == BIN(leave)) { + if (do_tailcallopt && + (iobj->insn_id == BIN(send) || + iobj->insn_id == BIN(invokesuper))) { /* * send ... * leave @@ -2108,13 +2110,29 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * send ..., ... | VM_CALL_TAILCALL, ... * leave # unreachable */ - INSN *piobj = (INSN *)get_prev_insn(iobj); - enum ruby_vminsn_type previ = piobj->insn_id; + INSN *piobj = NULL; + if (iobj->link.next) { + LINK_ELEMENT *next = iobj->link.next; + do { + if (next->type != ISEQ_ELEMENT_INSN) { + next = next->next; + continue; + } + switch (INSN_OF(next)) { + case BIN(nop): + /*case BIN(trace):*/ + next = next->next; + break; + case BIN(leave): + piobj = iobj; + default: + next = NULL; + break; + } + } while (next); + } - if (previ == BIN(send) || previ == BIN(opt_send_without_block) || - previ == BIN(invokesuper) || - previ == BIN(opt_aref) || previ == BIN(opt_aref_with) || - previ == BIN(opt_aset) || previ == BIN(opt_aset_with)) { + if (piobj) { struct rb_call_info *ci = (struct rb_call_info *)piobj->operands[0]; rb_iseq_t *blockiseq = (rb_iseq_t *)piobj->operands[1]; if (blockiseq == 0) { |