refactor gv.c:Perl_newGP
authorDaniel Dragan <bulk88@hotmail.com>
Wed, 7 Nov 2012 23:03:10 +0000 (18:03 -0500)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 9 Nov 2012 05:20:23 +0000 (21:20 -0800)
This commit fixes a scenario was strlen("") was called unnecessarily.
Replaced with 0. Also various func calls were rearranged for more calls
to happen near the beginning to maximize use of volatile registers
towards the end for PERL_HASH. PERL_HASH was moved to be closer to the
first usage of var hash. Setting gp_line to 0 was removed since the block
was just calloced and is already 0. Filling of gp.gp_egv was moved early
so var gv on C stack might get reused by compiler optimizer to store
something else to decrease the stack frame size of Perl_newGP.
PERL_ARGS_ASSERT_NEWGP was moved to be outside of an ifdef.

Also see commits 128165928a7 , 19bad6733a8 , 1df5f7c1950 , f4890806d3 .

Porting/leakfinder.pl
gv.c
regcomp.c
t/op/svleak.t

index 91453bc..3c1c078 100644 (file)
@@ -24,6 +24,7 @@ for(`find .`) {
     next if /rm -rf/; # Could be an example from perlsec, e.g.
     next if /END\s*\{/; # Creating an END block creates SVs, obviously
     next if /^\s*(?:push|unshift)/;
+    next if /\bselect(?:\s*\()[^()]+,/; # 4-arg select hangs
     my $q = s/[\\']/sprintf "\\%02x", ord $&/gore
          =~ s/\0/'."\\0".'/grid;
     $prog = <<end;   
@@ -49,11 +50,11 @@ end
 
 BEGIN {
  @exceptions = split /^/, <<'end';
+$char++ while substr( $got, $char, 1 ) eq substr( $wanted, $char, 1 );
 do {$x[$x] = $x;} while ($x++) < 10;
 eval 'v23: $counter++; goto v23 unless $counter == 2';
 eval 'v23 : $counter++; goto v23 unless $counter == 2';
-my $select_ret = select($rout = $rin, undef, undef, $timeout);
-select(undef,undef,undef,$delay);
+sleep;
 end
  @exceptions{@exceptions} = ();
 }
diff --git a/gv.c b/gv.c
index 40f7c23..9de8886 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -162,17 +162,37 @@ Perl_newGP(pTHX_ GV *const gv)
 {
     GP *gp;
     U32 hash;
-#ifdef USE_ITHREADS
-    const char *const file
-       = (PL_curcop && CopFILE(PL_curcop)) ? CopFILE(PL_curcop) : "";
-    const STRLEN len = strlen(file);
-#else
-    SV *const temp_sv = CopFILESV(PL_curcop);
     const char *file;
     STRLEN len;
+#ifndef USE_ITHREADS
+    SV * temp_sv;
+#endif
 
     PERL_ARGS_ASSERT_NEWGP;
+    Newxz(gp, 1, GP);
+    gp->gp_egv = gv; /* allow compiler to reuse gv after this */
+#ifndef PERL_DONT_CREATE_GVSV
+    gp->gp_sv = newSV(0);
+#endif
 
+#ifdef USE_ITHREADS
+    if (PL_curcop) {
+       gp->gp_line = CopLINE(PL_curcop); /* 0 otherwise Newxz */
+       if (CopFILE(PL_curcop)) {
+           file = CopFILE(PL_curcop);
+           len = strlen(file);
+       }
+       else goto no_file;
+    }
+    else {
+       no_file:
+       file = "";
+       len = 0;
+    }
+#else
+    if(PL_curcop)
+       gp->gp_line = CopLINE(PL_curcop); /* 0 otherwise Newxz */
+    temp_sv = CopFILESV(PL_curcop);
     if (temp_sv) {
        file = SvPVX(temp_sv);
        len = SvCUR(temp_sv);
@@ -183,18 +203,7 @@ Perl_newGP(pTHX_ GV *const gv)
 #endif
 
     PERL_HASH(hash, file, len);
-
-    Newxz(gp, 1, GP);
-
-#ifndef PERL_DONT_CREATE_GVSV
-    gp->gp_sv = newSV(0);
-#endif
-
-    gp->gp_line = PL_curcop ? CopLINE(PL_curcop) : 0;
-    /* XXX Ideally this cast would be replaced with a change to const char*
-       in the struct.  */
     gp->gp_file_hek = share_hek(file, len, hash);
-    gp->gp_egv = gv;
     gp->gp_refcnt = 1;
 
     return gp;
index dbb8306..740bc94 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -11460,7 +11460,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
      * reg() gets called (recursively) on the rewritten version, and this
      * function will return what it constructs.  (Actually the <multi-fold>s
      * aren't physically removed from the [abcdefghi], it's just that they are
-     * ignored in the recursion by means of a a flag:
+     * ignored in the recursion by means of a flag:
      * <RExC_in_multi_char_class>.)
      *
      * ANYOF nodes contain a bit map for the first 256 characters, with the
@@ -13178,7 +13178,7 @@ parseit:
 
        av_store(av, 0, (HAS_NONLOCALE_RUNTIME_PROPERTY_DEFINITION)
                        ? listsv
-                       : &PL_sv_undef);
+                       : (SvREFCNT_dec(listsv), &PL_sv_undef));
        if (swash) {
            av_store(av, 1, swash);
            SvREFCNT_dec(cp_list);
index 129bd0a..964bcbb 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 
 use Config;
 
-plan tests => 56;
+plan tests => 58;
 
 # run some code N times. If the number of SVs at the end of loop N is
 # greater than (N-1)*delta at the end of loop 1, we've got a leak
@@ -175,6 +175,7 @@ leak(2, 0,
 
 eleak(2,0,'/[:]/');
 eleak(2,0,'/[\xdf]/i');
+eleak(2,0,'s![^/]!!');
 
 leak(2,0,sub { !$^V }, '[perl #109762] version object in boolean context');
 
@@ -208,6 +209,11 @@ eleak(2, !!$Config{mad}, 'no warnings; 2 2;BEGIN{}',
                 'implicit "use Errno" after syntax error');
 }
 eleak(2, 0, "\"\$\0\356\"", 'qq containing $ <null> something');
+{
+    local $::TODO = 'eval "END blah blah" still leaks';
+    eleak(2, 0, 'END OF TERMS AND CONDITIONS', 'END followed by words');
+}
+
 
 # [perl #114764] Attributes leak scalars
 leak(2, 0, sub { eval 'my $x : shared' }, 'my $x :shared used to leak');