mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* compile.c, insns.def, parse.y: fix massign order. This change
causes performance problem. Try vm1_swap benchmark. [ruby-dev:31522] * insns.def, insnhelper.ci: move process body of expandarray insn to vm_expandarray(). * bootstraptest/test_knownbug.rb, bootstraptest/test_massign.rb: move a solved test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ac41d27749
commit
e39eb9dab5
7 changed files with 121 additions and 162 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
Thu Aug 23 16:04:11 2007 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* compile.c, insns.def, parse.y: fix massign order. This change
|
||||
causes performance problem. Try vm1_swap benchmark.
|
||||
[ruby-dev:31522]
|
||||
|
||||
* insns.def, insnhelper.ci: move process body of expandarray insn to
|
||||
vm_expandarray().
|
||||
|
||||
* bootstraptest/test_knownbug.rb, bootstraptest/test_massign.rb:
|
||||
move a solved test.
|
||||
|
||||
Thu Aug 23 15:51:19 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* parse.y (f_norm_arg): ripper has no shadowing check.
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#
|
||||
|
||||
# massign
|
||||
assert_equal '2', 'a, a = 1, 2; a', "[ruby-dev:31522]"
|
||||
assert_equal '[0,1,{2=>3}]', '[0,*[1],2=>3]', "[ruby-dev:31592]"
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ assert_equal '[[1], 2, 3]', '*v1,(*), (a, b) = [1,:x,[2, 3]]; [v1, a, b]'
|
|||
|
||||
assert_equal '[]', '*a = *nil; a'
|
||||
assert_equal '[nil]', '*a = nil; a'
|
||||
assert_equal '2', 'a, a = 1, 2; a', "[ruby-dev:31522]"
|
||||
|
||||
=begin
|
||||
# generated by this script:
|
||||
|
|
159
compile.c
159
compile.c
|
@ -1946,7 +1946,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, VALUE s
|
|||
}
|
||||
|
||||
static int
|
||||
make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
|
||||
compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
|
||||
{
|
||||
switch (nd_type(node)) {
|
||||
case NODE_ATTRASGN: {
|
||||
|
@ -1968,7 +1968,11 @@ make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
|
|||
break;
|
||||
}
|
||||
case NODE_MASGN: {
|
||||
COMPILE_POPED(ret, "nest masgn lhs", node);
|
||||
DECL_ANCHOR(anchor);
|
||||
INIT_ANCHOR(anchor);
|
||||
COMPILE_POPED(anchor, "nest masgn lhs", node);
|
||||
REMOVE_ELEM(FIRST_ELEMENT(anchor));
|
||||
ADD_SEQ(ret, anchor);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -1987,123 +1991,60 @@ make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
|
|||
}
|
||||
|
||||
static int
|
||||
compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret,
|
||||
NODE *rhsn, NODE *splatn, NODE *lhsn, int llen)
|
||||
compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
|
||||
{
|
||||
if (lhsn != 0) {
|
||||
compile_massign(iseq, ret, rhsn, splatn, lhsn->nd_next, llen + 1);
|
||||
make_masgn_lhs(iseq, ret, lhsn->nd_head);
|
||||
NODE *rhsn = node->nd_value;
|
||||
NODE *splatn = node->nd_args;
|
||||
NODE *lhsn = node->nd_head;
|
||||
int lhs_splat = (splatn && (VALUE)splatn != (VALUE)-1) ? 1 : 0;
|
||||
|
||||
if (!poped && 0) {
|
||||
/* optimized one */
|
||||
//compile_massign_opt(iseq, ret, rhsn, splatn, lhsn, llen);
|
||||
}
|
||||
else {
|
||||
int lhs_splat = 0;
|
||||
DECL_ANCHOR(lhsseq);
|
||||
int llen = 0;
|
||||
INIT_ANCHOR(lhsseq);
|
||||
|
||||
if (splatn && (VALUE)splatn != -1) {
|
||||
lhs_splat = 1;
|
||||
while (lhsn) {
|
||||
compile_massign_lhs(iseq, lhsseq, lhsn->nd_head);
|
||||
llen += 1;
|
||||
lhsn = lhsn->nd_next;
|
||||
}
|
||||
|
||||
if (rhsn) {
|
||||
switch (nd_type(rhsn)) {
|
||||
case NODE_ARRAY:{
|
||||
int rlen = rhsn->nd_alen;
|
||||
int max = rlen > llen ? rlen : llen;
|
||||
int i, si = 0;
|
||||
int rline = nd_line(rhsn);
|
||||
COMPILE(ret, "normal masgn rhs", rhsn);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (i < rlen && i < llen) {
|
||||
/* a, b = c, d */
|
||||
COMPILE(ret, "masgn val1", rhsn->nd_head);
|
||||
rline = nd_line(rhsn);
|
||||
rhsn = rhsn->nd_next;
|
||||
}
|
||||
else if (i < rlen) {
|
||||
if (lhs_splat) {
|
||||
while (rhsn) {
|
||||
/* a, *b = x, y, z */
|
||||
si++;
|
||||
COMPILE(ret, "masgn rhs for lhs splat",
|
||||
rhsn->nd_head);
|
||||
rline = nd_line(rhsn);
|
||||
rhsn = rhsn->nd_next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* a, b = c, d, e */
|
||||
COMPILE_POPED(ret, "masgn rhs (popped)",
|
||||
rhsn->nd_head);
|
||||
rhsn = rhsn->nd_next;
|
||||
}
|
||||
}
|
||||
else if (i < llen) {
|
||||
/* a, b, c = c, d */
|
||||
ADD_INSN(ret, rline, putnil);
|
||||
}
|
||||
}
|
||||
|
||||
if (lhs_splat) {
|
||||
ADD_INSN1(ret, rline, newarray, INT2FIX(si));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_TO_ARY:
|
||||
COMPILE(ret, "rhs to ary", rhsn->nd_head);
|
||||
ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen),
|
||||
INT2FIX(lhs_splat));
|
||||
break;
|
||||
|
||||
case NODE_SPLAT:
|
||||
COMPILE(ret, "rhs to ary (splat)", rhsn);
|
||||
ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
|
||||
break;
|
||||
|
||||
case NODE_ARGSCAT:
|
||||
COMPILE(ret, "rhs to argscat", rhsn);
|
||||
ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
|
||||
break;
|
||||
|
||||
default:
|
||||
COMPILE(ret, "rhs to ary (splat/default)", rhsn);
|
||||
ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* nested massign */
|
||||
ADD_INSN2(ret, 0, expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
|
||||
if (!poped) {
|
||||
ADD_INSN(ret, nd_line(node), dup);
|
||||
}
|
||||
|
||||
ADD_INSN2(ret, nd_line(node), expandarray,
|
||||
INT2FIX(llen), INT2FIX(lhs_splat));
|
||||
ADD_SEQ(ret, lhsseq);
|
||||
|
||||
if (lhs_splat) {
|
||||
if (nd_type(splatn) == NODE_POSTARG) {
|
||||
NODE *n = splatn->nd_2nd;
|
||||
int num = n->nd_alen;
|
||||
/*a, b, *r, p1, p2 */
|
||||
NODE *postn = splatn->nd_2nd;
|
||||
NODE *restn = splatn->nd_1st;
|
||||
int num = postn->nd_alen;
|
||||
int flag = 0x02 | (((VALUE)restn == (VALUE)-1) ? 0x00 : 0x01);
|
||||
|
||||
ADD_INSN (ret, nd_line(n), dup);
|
||||
ADD_INSN2(ret, nd_line(n), expandarray, INT2FIX(num), INT2FIX(2));
|
||||
ADD_INSN2(ret, nd_line(splatn), expandarray,
|
||||
INT2FIX(num), INT2FIX(flag));
|
||||
|
||||
while (n) {
|
||||
DECL_ANCHOR(lhs);
|
||||
|
||||
INIT_ANCHOR(lhs);
|
||||
COMPILE_POPED(lhs, "post", n->nd_head);
|
||||
|
||||
if (nd_type(n->nd_head) != NODE_MASGN) {
|
||||
REMOVE_ELEM(FIRST_ELEMENT(lhs));
|
||||
}
|
||||
|
||||
ADD_SEQ(ret, lhs);
|
||||
n = n->nd_next;
|
||||
if ((VALUE)restn != (VALUE)-1) {
|
||||
compile_massign_lhs(iseq, ret, restn);
|
||||
}
|
||||
|
||||
if (splatn->nd_1st == (NODE*)(VALUE)-1) {
|
||||
/* v1, *, v2 = expr */
|
||||
ADD_INSN(ret, nd_line(splatn), pop);
|
||||
}
|
||||
else {
|
||||
make_masgn_lhs(iseq, ret, splatn->nd_1st);
|
||||
while (postn) {
|
||||
compile_massign_lhs(iseq, ret, postn->nd_head);
|
||||
postn = postn->nd_next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
make_masgn_lhs(iseq, ret, splatn);
|
||||
/* a, b, *r */
|
||||
compile_massign_lhs(iseq, ret, splatn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3204,19 +3145,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
}
|
||||
|
||||
case NODE_MASGN:{
|
||||
if (poped) {
|
||||
compile_massign(iseq, ret,
|
||||
node->nd_value, /* rhsn */
|
||||
node->nd_args, /* splat */
|
||||
node->nd_head, /* lhsn */
|
||||
0);
|
||||
}
|
||||
else {
|
||||
COMPILE(ret, "masgn/value", node->nd_value);
|
||||
ADD_INSN(ret, nd_line(node), dup);
|
||||
compile_massign(iseq, ret, 0,
|
||||
node->nd_args, node->nd_head, 0);
|
||||
}
|
||||
compile_massign(iseq, ret, node, poped);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1321,6 +1321,64 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VAL
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
vm_expandarray(rb_control_frame_t *cfp, VALUE ary, int num, int flag)
|
||||
{
|
||||
int is_splat = flag & 0x01;
|
||||
int space_size = num + is_splat;
|
||||
VALUE *base = cfp->sp, *ptr;
|
||||
int len;
|
||||
|
||||
cfp->sp += space_size;
|
||||
|
||||
if (TYPE(ary) != T_ARRAY) {
|
||||
ary = rb_ary_to_ary(ary);
|
||||
}
|
||||
ptr = RARRAY_PTR(ary);
|
||||
len = RARRAY_LEN(ary);
|
||||
|
||||
if (flag & 0x02) {
|
||||
/* post: ..., nil ,ary[-1], ..., ary[0..-num] # top */
|
||||
int i = 0, j;
|
||||
|
||||
if (len < num) {
|
||||
for (i=0; i<num-len; i++) {
|
||||
*base++ = Qnil;
|
||||
}
|
||||
}
|
||||
for (j=0; i<num; i++, j++) {
|
||||
VALUE v = ptr[len - j - 1];
|
||||
*base++ = v;
|
||||
}
|
||||
if (is_splat) {
|
||||
*base = rb_ary_new4(len - j, ptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top */
|
||||
int i;
|
||||
VALUE *bptr = &base[space_size - 1];
|
||||
|
||||
for (i=0; i<num; i++) {
|
||||
if (len <= i) {
|
||||
for (; i<num; i++) {
|
||||
*bptr-- = Qnil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*bptr-- = ptr[i];
|
||||
}
|
||||
if (is_splat) {
|
||||
if (num > len) {
|
||||
*bptr = rb_ary_new();
|
||||
}
|
||||
else {
|
||||
*bptr = rb_ary_new4(len - num, ptr + num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
call_end_proc(VALUE data)
|
||||
{
|
||||
|
|
50
insns.def
50
insns.def
|
@ -446,57 +446,17 @@ duparray
|
|||
num以上の要素は切り捨てる。
|
||||
配列オブジェクトでなければ、num - 1 個の nil を積む。
|
||||
もし flag が真なら、残り要素の配列を積む
|
||||
flag: 0x01 - 最後を配列に
|
||||
flag: 0x02 - postarg 用
|
||||
flag: 0x04 - reverse?
|
||||
*/
|
||||
DEFINE_INSN
|
||||
expandarray
|
||||
(rb_num_t num, rb_num_t flag)
|
||||
(..., VALUE ary)
|
||||
(...) // inc += flag == 2 ? num : ((num > 0) ? num - 1 + (flag ? 1 : 0) : num + 1 - (flag ? 1 : 0));
|
||||
(...) // inc += flag == 0x02 ? num : ((num > 0) ? num - 1 + (flag ? 1 : 0) : num + 1 - (flag ? 1 : 0));
|
||||
{
|
||||
int i;
|
||||
|
||||
if (flag == 2) {
|
||||
VALUE *ptr = RARRAY_PTR(ary);
|
||||
int len = RARRAY_LEN(ary);
|
||||
int start = len - num;
|
||||
|
||||
if (start < 0) {
|
||||
for (i=0; i<num-len; i++) {
|
||||
PUSH(Qnil);
|
||||
}
|
||||
for (i=0; i<len; i++) {
|
||||
PUSH(ptr[len-i-1]);
|
||||
}
|
||||
rb_ary_clear(ary);
|
||||
}
|
||||
else {
|
||||
for (i=0; i<num; i++) {
|
||||
PUSH(ptr[len-i-1]);
|
||||
}
|
||||
RARRAY_LEN(ary) = len - num;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int len;
|
||||
if (TYPE(ary) != T_ARRAY) {
|
||||
ary = rb_ary_to_ary(ary);
|
||||
}
|
||||
len = RARRAY_LEN(ary);
|
||||
for (i = 0; i < len && i < num; i++) {
|
||||
PUSH(RARRAY_PTR(ary)[i]);
|
||||
}
|
||||
for (; i < num; i++) {
|
||||
PUSH(Qnil);
|
||||
}
|
||||
if (flag) {
|
||||
if (len > num) {
|
||||
PUSH(rb_ary_new4(len - num, &RARRAY_PTR(ary)[num]));
|
||||
}
|
||||
else {
|
||||
PUSH(rb_ary_new());
|
||||
}
|
||||
}
|
||||
}
|
||||
vm_expandarray(GET_CFP(), ary, num, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
2
parse.y
2
parse.y
|
@ -978,7 +978,7 @@ stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
|
|||
{
|
||||
/*%%%*/
|
||||
value_expr($3);
|
||||
$1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
|
||||
$1->nd_value = $3;
|
||||
$$ = $1;
|
||||
/*%
|
||||
$$ = dispatch2(massign, $1, $3);
|
||||
|
|
Loading…
Reference in a new issue