This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
clear_defarray(): clear @_ if possible
authorDavid Mitchell <davem@iabyn.com>
Sat, 11 Jul 2015 10:05:55 +0000 (11:05 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 3 Feb 2016 08:59:35 +0000 (08:59 +0000)
clear_defarray() is called during sub exit to clean up @_ in the
less common case where @_ has somehow gotten reified.

At the moment it just frees the old @_, then creates a new AV and
sticks it in pad[0].

This commit changes it so that for the reasonably common case of a reified
@_ where it's not magical and only has a reference count of 1, just call
av_clear() on it, rather than freeing and recreating.

Typical code that will benefit from this change is be something like:

    sub f { push @_, ...; ... }

which causes the AV to be reified, but not to become otherwise visible.

pp_hot.c

index c2ee827..f719b40 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -3340,11 +3340,15 @@ Perl_clear_defarray(pTHX_ AV* av, bool abandon)
 
     PERL_ARGS_ASSERT_CLEAR_DEFARRAY;
 
-    SvREFCNT_dec_NN(av);
-    av = newAV();
-    av_extend(av, fill);
+    if (LIKELY(!abandon && SvREFCNT(av) == 1 && !SvMAGICAL(av)))
+        av_clear(av);
+    else {
+        SvREFCNT_dec_NN(av);
+        av = newAV();
+        PAD_SVl(0) = MUTABLE_SV(av);
+        av_extend(av, fill);
+    }
     AvREIFY_only(av);
-    PAD_SVl(0) = MUTABLE_SV(av);
 }