|
|
8446b7 |
From d7504df2a5d8985f2a8b04f17acff5e324572c39 Mon Sep 17 00:00:00 2001
|
|
|
8446b7 |
From: Richard Leach <richardleach@users.noreply.github.com>
|
|
|
8446b7 |
Date: Sun, 11 Oct 2020 12:26:27 +0100
|
|
|
8446b7 |
Subject: [PATCH] pp_split: no SWITCHSTACK in @ary = split(...) optimisation
|
|
|
8446b7 |
MIME-Version: 1.0
|
|
|
8446b7 |
Content-Type: text/plain; charset=UTF-8
|
|
|
8446b7 |
Content-Transfer-Encoding: 8bit
|
|
|
8446b7 |
|
|
|
8446b7 |
Petr Písař: 607eaf26a99ff76ab48877e68f1d7b005dc51575 ported to 5.32.0.
|
|
|
8446b7 |
|
|
|
8446b7 |
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
|
|
8446b7 |
---
|
|
|
8446b7 |
pp.c | 89 +++++++++++++++++++++++++++++-----------------------
|
|
|
8446b7 |
t/op/split.t | 23 +++++++++++++-
|
|
|
8446b7 |
2 files changed, 72 insertions(+), 40 deletions(-)
|
|
|
8446b7 |
|
|
|
8446b7 |
diff --git a/pp.c b/pp.c
|
|
|
8446b7 |
index df80830..e4863d3 100644
|
|
|
8446b7 |
--- a/pp.c
|
|
|
8446b7 |
+++ b/pp.c
|
|
|
8446b7 |
@@ -5985,6 +5985,7 @@ PP(pp_split)
|
|
|
8446b7 |
|
|
|
8446b7 |
/* handle @ary = split(...) optimisation */
|
|
|
8446b7 |
if (PL_op->op_private & OPpSPLIT_ASSIGN) {
|
|
|
8446b7 |
+ realarray = 1;
|
|
|
8446b7 |
if (!(PL_op->op_flags & OPf_STACKED)) {
|
|
|
8446b7 |
if (PL_op->op_private & OPpSPLIT_LEX) {
|
|
|
8446b7 |
if (PL_op->op_private & OPpLVAL_INTRO)
|
|
|
8446b7 |
@@ -6007,26 +6008,10 @@ PP(pp_split)
|
|
|
8446b7 |
oldsave = PL_savestack_ix;
|
|
|
8446b7 |
}
|
|
|
8446b7 |
|
|
|
8446b7 |
- realarray = 1;
|
|
|
8446b7 |
- PUTBACK;
|
|
|
8446b7 |
- av_extend(ary,0);
|
|
|
8446b7 |
- (void)sv_2mortal(SvREFCNT_inc_simple_NN(sv));
|
|
|
8446b7 |
- av_clear(ary);
|
|
|
8446b7 |
- SPAGAIN;
|
|
|
8446b7 |
if ((mg = SvTIED_mg((const SV *)ary, PERL_MAGIC_tied))) {
|
|
|
8446b7 |
PUSHMARK(SP);
|
|
|
8446b7 |
XPUSHs(SvTIED_obj(MUTABLE_SV(ary), mg));
|
|
|
8446b7 |
- }
|
|
|
8446b7 |
- else {
|
|
|
8446b7 |
- if (!AvREAL(ary)) {
|
|
|
8446b7 |
- I32 i;
|
|
|
8446b7 |
- AvREAL_on(ary);
|
|
|
8446b7 |
- AvREIFY_off(ary);
|
|
|
8446b7 |
- for (i = AvFILLp(ary); i >= 0; i--)
|
|
|
8446b7 |
- AvARRAY(ary)[i] = &PL_sv_undef; /* don't free mere refs */
|
|
|
8446b7 |
- }
|
|
|
8446b7 |
- /* temporarily switch stacks */
|
|
|
8446b7 |
- SAVESWITCHSTACK(PL_curstack, ary);
|
|
|
8446b7 |
+ } else {
|
|
|
8446b7 |
make_mortal = 0;
|
|
|
8446b7 |
}
|
|
|
8446b7 |
}
|
|
|
8446b7 |
@@ -6358,29 +6343,56 @@ PP(pp_split)
|
|
|
8446b7 |
LEAVE_SCOPE(oldsave); /* may undo an earlier SWITCHSTACK */
|
|
|
8446b7 |
SPAGAIN;
|
|
|
8446b7 |
if (realarray) {
|
|
|
8446b7 |
- if (!mg) {
|
|
|
8446b7 |
- if (SvSMAGICAL(ary)) {
|
|
|
8446b7 |
- PUTBACK;
|
|
|
8446b7 |
+ if (!mg) {
|
|
|
8446b7 |
+ PUTBACK;
|
|
|
8446b7 |
+ if(AvREAL(ary)) {
|
|
|
8446b7 |
+ if (av_count(ary) > 0)
|
|
|
8446b7 |
+ av_clear(ary);
|
|
|
8446b7 |
+ } else {
|
|
|
8446b7 |
+ AvREAL_on(ary);
|
|
|
8446b7 |
+ AvREIFY_off(ary);
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+ if (AvMAX(ary) > -1) {
|
|
|
8446b7 |
+ /* don't free mere refs */
|
|
|
8446b7 |
+ Zero(AvARRAY(ary), AvMAX(ary), SV*);
|
|
|
8446b7 |
+ }
|
|
|
8446b7 |
+ }
|
|
|
8446b7 |
+ if(AvMAX(ary) < iters)
|
|
|
8446b7 |
+ av_extend(ary,iters);
|
|
|
8446b7 |
+ SPAGAIN;
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+ /* Need to copy the SV*s from the stack into ary */
|
|
|
8446b7 |
+ Copy(SP + 1 - iters, AvARRAY(ary), iters, SV*);
|
|
|
8446b7 |
+ AvFILLp(ary) = iters - 1;
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+ if (SvSMAGICAL(ary)) {
|
|
|
8446b7 |
+ PUTBACK;
|
|
|
8446b7 |
mg_set(MUTABLE_SV(ary));
|
|
|
8446b7 |
SPAGAIN;
|
|
|
8446b7 |
- }
|
|
|
8446b7 |
- if (gimme == G_ARRAY) {
|
|
|
8446b7 |
- EXTEND(SP, iters);
|
|
|
8446b7 |
- Copy(AvARRAY(ary), SP + 1, iters, SV*);
|
|
|
8446b7 |
- SP += iters;
|
|
|
8446b7 |
- RETURN;
|
|
|
8446b7 |
- }
|
|
|
8446b7 |
+ }
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+ if (gimme != G_ARRAY) {
|
|
|
8446b7 |
+ /* SP points to the final SV* pushed to the stack. But the SV* */
|
|
|
8446b7 |
+ /* are not going to be used from the stack. Point SP to below */
|
|
|
8446b7 |
+ /* the first of these SV*. */
|
|
|
8446b7 |
+ SP -= iters;
|
|
|
8446b7 |
+ PUTBACK;
|
|
|
8446b7 |
+ }
|
|
|
8446b7 |
}
|
|
|
8446b7 |
else {
|
|
|
8446b7 |
- PUTBACK;
|
|
|
8446b7 |
- ENTER_with_name("call_PUSH");
|
|
|
8446b7 |
- call_sv(SV_CONST(PUSH),G_SCALAR|G_DISCARD|G_METHOD_NAMED);
|
|
|
8446b7 |
- LEAVE_with_name("call_PUSH");
|
|
|
8446b7 |
- SPAGAIN;
|
|
|
8446b7 |
+ PUTBACK;
|
|
|
8446b7 |
+ av_extend(ary,iters);
|
|
|
8446b7 |
+ av_clear(ary);
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+ ENTER_with_name("call_PUSH");
|
|
|
8446b7 |
+ call_sv(SV_CONST(PUSH),G_SCALAR|G_DISCARD|G_METHOD_NAMED);
|
|
|
8446b7 |
+ LEAVE_with_name("call_PUSH");
|
|
|
8446b7 |
+ SPAGAIN;
|
|
|
8446b7 |
+
|
|
|
8446b7 |
if (gimme == G_ARRAY) {
|
|
|
8446b7 |
SSize_t i;
|
|
|
8446b7 |
/* EXTEND should not be needed - we just popped them */
|
|
|
8446b7 |
- EXTEND(SP, iters);
|
|
|
8446b7 |
+ EXTEND_SKIP(SP, iters);
|
|
|
8446b7 |
for (i=0; i < iters; i++) {
|
|
|
8446b7 |
SV **svp = av_fetch(ary, i, FALSE);
|
|
|
8446b7 |
PUSHs((svp) ? *svp : &PL_sv_undef);
|
|
|
8446b7 |
@@ -6389,13 +6401,12 @@ PP(pp_split)
|
|
|
8446b7 |
}
|
|
|
8446b7 |
}
|
|
|
8446b7 |
}
|
|
|
8446b7 |
- else {
|
|
|
8446b7 |
- if (gimme == G_ARRAY)
|
|
|
8446b7 |
- RETURN;
|
|
|
8446b7 |
- }
|
|
|
8446b7 |
|
|
|
8446b7 |
- GETTARGET;
|
|
|
8446b7 |
- XPUSHi(iters);
|
|
|
8446b7 |
+ if (gimme != G_ARRAY) {
|
|
|
8446b7 |
+ GETTARGET;
|
|
|
8446b7 |
+ XPUSHi(iters);
|
|
|
8446b7 |
+ }
|
|
|
8446b7 |
+
|
|
|
8446b7 |
RETURN;
|
|
|
8446b7 |
}
|
|
|
8446b7 |
|
|
|
8446b7 |
diff --git a/t/op/split.t b/t/op/split.t
|
|
|
8446b7 |
index 14f9158..7f37512 100644
|
|
|
8446b7 |
--- a/t/op/split.t
|
|
|
8446b7 |
+++ b/t/op/split.t
|
|
|
8446b7 |
@@ -7,7 +7,7 @@ BEGIN {
|
|
|
8446b7 |
set_up_inc('../lib');
|
|
|
8446b7 |
}
|
|
|
8446b7 |
|
|
|
8446b7 |
-plan tests => 176;
|
|
|
8446b7 |
+plan tests => 182;
|
|
|
8446b7 |
|
|
|
8446b7 |
$FS = ':';
|
|
|
8446b7 |
|
|
|
8446b7 |
@@ -648,6 +648,19 @@ is "@a", '1 2 3', 'assignment to split-to-array (stacked)';
|
|
|
8446b7 |
is (+@a, 0, "empty utf8 string");
|
|
|
8446b7 |
}
|
|
|
8446b7 |
|
|
|
8446b7 |
+# correct stack adjustments (gh#18232)
|
|
|
8446b7 |
+{
|
|
|
8446b7 |
+ sub foo { return @_ }
|
|
|
8446b7 |
+ my @a = foo(1, scalar split " ", "a b");
|
|
|
8446b7 |
+ is(join('', @a), "12", "Scalar split to a sub parameter");
|
|
|
8446b7 |
+}
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+{
|
|
|
8446b7 |
+ sub foo { return @_ }
|
|
|
8446b7 |
+ my @a = foo(1, scalar(@x = split " ", "a b"));
|
|
|
8446b7 |
+ is(join('', @a), "12", "Split to @x then use scalar result as a sub parameter");
|
|
|
8446b7 |
+}
|
|
|
8446b7 |
+
|
|
|
8446b7 |
fresh_perl_is(<<'CODE', '', {}, "scalar split stack overflow");
|
|
|
8446b7 |
map{int"";split//.0>60for"0000000000000000"}split// for"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
|
|
8446b7 |
CODE
|
|
|
8446b7 |
@@ -667,3 +680,11 @@ CODE
|
|
|
8446b7 |
ok(eq_array(\@result,['a','b']), "Resulting in ('a','b')");
|
|
|
8446b7 |
}
|
|
|
8446b7 |
}
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+# check that the (@ary = split) optimisation survives @ary being modified
|
|
|
8446b7 |
+
|
|
|
8446b7 |
+fresh_perl_is('my @ary; @ary = split(/\w(?{ @ary[1000] = 1 })/, "abc");',
|
|
|
8446b7 |
+ '',{},'(@ary = split ...) survives @ary being Renew()ed');
|
|
|
8446b7 |
+fresh_perl_is('my @ary; @ary = split(/\w(?{ undef @ary })/, "abc");',
|
|
|
8446b7 |
+ '',{},'(@ary = split ...) survives an (undef @ary)');
|
|
|
8446b7 |
+
|
|
|
8446b7 |
--
|
|
|
8446b7 |
2.25.4
|
|
|
8446b7 |
|