diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-02-25 00:20:35 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-02-25 00:20:35 +0000 |
commit | 2c8cea84cc8daf54622eae6907d869eba6f4c422 (patch) | |
tree | 53b47cf53fa6080e7296d5aace52508bed614753 | |
parent | 0c3a0d6588c6fe44d43edbc54d3f92553a5a1705 (diff) | |
download | ruby-2c8cea84cc8daf54622eae6907d869eba6f4c422.tar.gz |
compile.c: unbalanced massign
* compile.c (compile_massign): adjust stack for unbalanced massign.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49730 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | compile.c | 22 |
1 files changed, 20 insertions, 2 deletions
@@ -2772,6 +2772,17 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret, return 1; } +static void +adjust_stack(rb_iseq_t *iseq, LINK_ANCHOR *ret, int line, int rlen, int llen) +{ + if (rlen < llen) { + do {ADD_INSN(ret, line, putnil);} while (++rlen < llen); + } + else if (rlen > llen) { + do {ADD_INSN(ret, line, pop);} while (--rlen > llen); + } +} + static int compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped) { @@ -2802,15 +2813,22 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped) INSN *last = (INSN*)ret->last; if (last->link.type == ISEQ_ELEMENT_INSN && last->insn_id == BIN(newarray) && - last->operand_size == 1 && - OPERAND_AT(last, 0) == INT2FIX(llen)) { + last->operand_size == 1) { + int rlen = FIX2INT(OPERAND_AT(last, 0)); /* special case: assign to aset or attrset */ if (llen == 2) { POP_ELEMENT(ret); + adjust_stack(iseq, ret, nd_line(node), rlen, llen); ADD_INSN(ret, nd_line(node), swap); expand = 0; } #if 0 + else if (llen > 2 && llen != rlen) { + POP_ELEMENT(ret); + adjust_stack(iseq, ret, nd_line(node), rlen, llen); + ADD_INSN1(ret, nd_line(node), reverse, INT2FIX(llen)); + expand = 0; + } else if (llen > 2) { last->insn_id = BIN(reverse); expand = 0; |