diff options
author | Father Chrysostomos <sprout@cpan.org> | 2014-09-22 21:48:48 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-09-22 21:56:36 -0700 |
commit | 14d91147b4bfd5289f2548af3eb0d745d241b9f8 (patch) | |
tree | c0a9c91dc617c129c50f17e9d8e3819c27cb73e3 /pad.c | |
parent | 39ff6c37b02dc106ce36a529c4fdd80ac93c7ada (diff) | |
download | perl-14d91147b4bfd5289f2548af3eb0d745d241b9f8.tar.gz |
Stop flip from returning the same scalar each time
sub f {
for my $n (1..5) {
my $x = \scalar($n == 2 .. $n == 4);
$_ = $x if $n == 1;
print "$n: $$_\n";
}
print("-----\n"), f() if @_
}
f(1);
Output:
1:
2: 1
3: 2
4: 3E0
5:
-----
1:
2:
3:
4:
5:
When f() is called, it evaluates a flipflop five times. It takes a
reference to the return value the first time, and prints that same
scalar for each iteration.
Notice how the very same scalar is returned each time in the outer sub
call, but the recursive call hides that implementation detail.
.. should not be returning the same scalar each time, or at least that
implementation detail should not leak through. (Most operators do
reuse the same scalar, but the scalar is flagged such that \ will copy
it, hiding that fact.)
This was happening because of the eccentric way that the flipflop
targets are allocated in the pad. They are allocated as PADMY (i.e.,
like ‘my’ variables), but without a name. pad_push (which creates a
new pad for recursion) assumes that anything without a name is PADTMP
instead (copy on reference). So the recursive call behaves correctly.
I am not sure why the targets were allocated with PADMY to begin with.
(This goes back to perl 5.000.) But now the PADMY prevents the tar-
gets from being shared with other ops under USE_PAD_RESET builds.
The better way to allocate these targets is to use PADMY as before,
but actually give those slots names. The target that gets returned
needs to be marked PADTMP, so we also need to copy that flag
in pad_push.
Diffstat (limited to 'pad.c')
-rw-r--r-- | pad.c | 4 |
1 files changed, 4 insertions, 0 deletions
@@ -2375,7 +2375,11 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth) else if (sigil == '%') sv = MUTABLE_SV(newHV()); else + { sv = newSV(0); + /* For flip-flop targets: */ + if (SvPADTMP(oldpad[ix])) SvPADTMP_on(sv); + } av_store(newpad, ix, sv); SvPADMY_on(sv); } |