diff options
-rw-r--r-- | intrpvar.h | 3 | ||||
-rw-r--r-- | op.c | 21 | ||||
-rw-r--r-- | perl.c | 5 |
3 files changed, 20 insertions, 9 deletions
diff --git a/intrpvar.h b/intrpvar.h index d457028ec1..06014efc23 100644 --- a/intrpvar.h +++ b/intrpvar.h @@ -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 @@ -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); @@ -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 |