diff --git a/insns.def b/insns.def index b784d7c043..b33dcf20fb 100644 --- a/insns.def +++ b/insns.def @@ -498,10 +498,11 @@ expandarray (rb_num_t num, rb_num_t flag) (..., VALUE ary) (...) +// attr bool handles_sp = true; // attr bool leaf = false; /* has rb_check_array_type() */ // attr rb_snum_t sp_inc = (rb_snum_t)num - 1 + (flag & 1 ? 1 : 0); { - vm_expandarray(GET_SP(), ary, num, (int)flag); + vm_expandarray(GET_CFP(), ary, num, (int)flag); } /* concat two arrays */ diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 9352820b82..8e1ac27c51 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1866,11 +1866,9 @@ rb_vm_throw(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_nu } static inline void -vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag) +vm_expandarray(struct rb_control_frame_struct *cfp, VALUE ary, rb_num_t num, int flag) { int is_splat = flag & 0x01; - rb_num_t space_size = num + is_splat; - VALUE *base = sp - 1; const VALUE *ptr; rb_num_t len; const VALUE obj = ary; @@ -1885,7 +1883,7 @@ vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag) len = (rb_num_t)RARRAY_LEN(ary); } - if (space_size == 0) { + if (num + is_splat == 0) { /* no space left on stack */ } else if (flag & 0x02) { @@ -1893,41 +1891,48 @@ vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag) rb_num_t i = 0, j; if (len < num) { - for (i=0; isp++ = Qnil; } } - for (j=0; isp++ = v; } + if (is_splat) { - *base = rb_ary_new4(len - j, ptr); + *cfp->sp++ = rb_ary_new4(len - j, ptr); } } else { /* normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top */ - rb_num_t i; - VALUE *bptr = &base[space_size - 1]; - - for (i=0; i len) { - *bptr = rb_ary_new(); + *cfp->sp++ = rb_ary_new(); } else { - *bptr = rb_ary_new4(len - num, ptr + num); + *cfp->sp++ = rb_ary_new4(len - num, ptr + num); + } + } + + if (num > len) { + rb_num_t i = 0; + for (; i < num - len; i++) { + *cfp->sp++ = Qnil; + } + + for (rb_num_t j = 0; i < num; i++, j++) { + *cfp->sp++ = ptr[len - j - 1]; + } + } + else { + for (rb_num_t j = 0; j < num; j++) { + *cfp->sp++ = ptr[num - j - 1]; } } } + RB_GC_GUARD(ary); }