diff --git a/compile.c b/compile.c index a2efc05438..f2701060d8 100644 --- a/compile.c +++ b/compile.c @@ -6198,8 +6198,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, argc += 1; } else { - ADD_INSN1(args, argn, splatarray, Qfalse); - ADD_INSN(args, argn, concatarray); + ADD_INSN(args, argn, concattoarray); } // f(..., *a, ..., k1:1, ...) #=> f(..., *[*a, ...], **{k1:1, ...}) diff --git a/insns.def b/insns.def index 5f6cb314ff..2b03e3eb47 100644 --- a/insns.def +++ b/insns.def @@ -505,7 +505,9 @@ expandarray vm_expandarray(GET_CFP(), ary, num, (int)flag); } -/* concat two arrays */ +/* concat two arrays, without modifying first array. + * attempts to convert both objects to arrays using to_a. + */ DEFINE_INSN concatarray () @@ -516,6 +518,20 @@ concatarray ary = vm_concat_array(ary1, ary2); } +/* concat second array to first array. + * first argument must already be an array. + * attempts to convert second object to array using to_a. + */ +DEFINE_INSN +concattoarray +() +(VALUE ary1, VALUE ary2) +(VALUE ary) +// attr bool leaf = false; /* has rb_check_array_type() */ +{ + ary = vm_concat_to_array(ary1, ary2); +} + /* call to_a on array ary to splat */ DEFINE_INSN splatarray diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 97776f7a69..55e79acdd8 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5204,15 +5204,29 @@ vm_concat_array(VALUE ary1, VALUE ary2st) if (NIL_P(tmp1)) { tmp1 = rb_ary_new3(1, ary1); } - - if (NIL_P(tmp2)) { - tmp2 = rb_ary_new3(1, ary2); - } - if (tmp1 == ary1) { tmp1 = rb_ary_dup(ary1); } - return rb_ary_concat(tmp1, tmp2); + + if (NIL_P(tmp2)) { + return rb_ary_push(tmp1, ary2); + } else { + return rb_ary_concat(tmp1, tmp2); + } +} + +static VALUE +vm_concat_to_array(VALUE ary1, VALUE ary2st) +{ + /* ary1 must be a newly created array */ + const VALUE ary2 = ary2st; + VALUE tmp2 = rb_check_to_array(ary2); + + if (NIL_P(tmp2)) { + return rb_ary_push(ary1, ary2); + } else { + return rb_ary_concat(ary1, tmp2); + } } // YJIT implementation is using the C function