Pack the recycled pad offsets into an SV at PL_regex_pad[0]. This will
Nicholas Clark [Fri, 11 Jan 2008 17:00:59 +0000 (17:00 +0000)]
use less memory than an AV.

p4raw-id: //depot/perl@32959

intrpvar.h
op.c
perl.c

index d457028..06014ef 100644 (file)
@@ -564,7 +564,8 @@ PERLVAR(Iregex_pad,     SV**)               /* Shortcut into the array of
                                           regex_padav */
 PERLVAR(Iregex_padav,   AV*)           /* All regex objects, indexed via the
                                           values in op_pmoffset of pmop.
-                                          Entry 0 is an array of IVs listing
+                                          Entry 0 is an SV whose PV is a
+                                          "packed" list of IVs listing
                                           the now-free slots in the array */
 #endif
 
diff --git a/op.c b/op.c
index 3903f53..e5fed9d 100644 (file)
--- a/op.c
+++ b/op.c
@@ -623,9 +623,11 @@ clear_pmop:
          */
 #ifdef USE_ITHREADS
        if(PL_regex_pad) {        /* We could be in destruction */
+           const IV offset = (cPMOPo)->op_pmoffset;
            ReREFCNT_dec(PM_GETRE(cPMOPo));
-            av_push((AV*) PL_regex_pad[0], newSViv((cPMOPo)->op_pmoffset));
-           PL_regex_pad[(cPMOPo)->op_pmoffset] = &PL_sv_undef;
+           PL_regex_pad[offset] = &PL_sv_undef;
+            sv_catpvn_nomg(PL_regex_pad[0], (const char *)&offset,
+                          sizeof(offset));
         }
 #else
        ReREFCNT_dec(PM_GETRE(cPMOPo));
@@ -3364,13 +3366,20 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags)
 
 
 #ifdef USE_ITHREADS
-    if (av_len((AV*) PL_regex_pad[0]) > -1) {
-       SV * const repointer = av_pop((AV*)PL_regex_pad[0]);
-       const IV offset = SvIV(repointer);
+    assert(SvPOK(PL_regex_pad[0]));
+    if (SvCUR(PL_regex_pad[0])) {
+       /* Pop off the "packed" IV from the end.  */
+       SV *const repointer_list = PL_regex_pad[0];
+       const char *p = SvEND(repointer_list) - sizeof(IV);
+       const IV offset = *((IV*)p);
+
+       assert(SvCUR(repointer_list) % sizeof(IV) == 0);
+
+       SvEND_set(repointer_list, p);
+
        pmop->op_pmoffset = offset;
        /* This slot should be free, so assert this:  */
        assert(PL_regex_pad[offset] == &PL_sv_undef);
-       SvREFCNT_dec(repointer);
     } else {
        SV * const repointer = &PL_sv_undef;
        av_push(PL_regex_padav, repointer);
diff --git a/perl.c b/perl.c
index 4397087..e8821a5 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -353,8 +353,9 @@ perl_construct(pTHXx)
     sv_setpvn(PERL_DEBUG_PAD(1), "", 0);       /* ext/re needs these */
     sv_setpvn(PERL_DEBUG_PAD(2), "", 0);       /* even without DEBUGGING. */
 #ifdef USE_ITHREADS
-    /* First entry is an array of empty elements */
-    Perl_av_create_and_push(aTHX_ &PL_regex_padav,(SV*)newAV());
+    /* First entry is a list of empty elements. It needs to be initialised
+       else all hell breaks loose in S_find_uninit_var().  */
+    Perl_av_create_and_push(aTHX_ &PL_regex_padav, newSVpvs(""));
     PL_regex_pad = AvARRAY(PL_regex_padav);
 #endif
 #ifdef USE_REENTRANT_API