diff options
author | Father Chrysostomos <sprout@cpan.org> | 2014-08-26 23:05:16 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-08-28 13:04:17 -0700 |
commit | b54c5e14b7fb9ecbcf34d74dd140de12cb73ff78 (patch) | |
tree | 9ccbd5504fa7696c60ca2cfe7530d383b525a71c /pad.c | |
parent | 8ce2f624198802e520eba6523c32ad6429463198 (diff) | |
download | perl-b54c5e14b7fb9ecbcf34d74dd140de12cb73ff78.tar.gz |
Split PL_padix into two variables
PL_padix keeps track of the position in the pad when pad_alloc has to
start scanning for an available slot.
The availability of a slot is determined differently for targets
(which may reuse slots that are already targets from previous state-
ments, at least when pad_reset is enabled) and constants (which may
not reuse targets).
Having the same index for both may require scanning the entire pad for
allocating a constant or GV.
t/re/uniprops.t was running far too slowly under USE_BROKEN_PAD_RESET
because of this. pad_reset would reset PL_padix to point to the
beginning of a pad with a few hundred thousand entries. pad_alloc
would then have to scan the entire pad before adding a GV to the end.
It is still too slow, even with this commit, but for other reasons.
(This is just a partial fix.)
Diffstat (limited to 'pad.c')
-rw-r--r-- | pad.c | 26 |
1 files changed, 17 insertions, 9 deletions
@@ -230,6 +230,7 @@ Perl_pad_new(pTHX_ int flags) if (! (flags & padnew_CLONE)) { SAVESPTR(PL_comppad_name); SAVEI32(PL_padix); + SAVEI32(PL_constpadix); SAVEI32(PL_comppad_name_fill); SAVEI32(PL_min_intro_pending); SAVEI32(PL_max_intro_pending); @@ -286,6 +287,7 @@ Perl_pad_new(pTHX_ int flags) PL_comppad_name_fill = 0; PL_min_intro_pending = 0; PL_padix = 0; + PL_constpadix = 0; PL_cv_has_eval = 0; } @@ -731,9 +733,12 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype) else { /* For a tmp, scan the pad from PL_padix upwards * for a slot which has no name and no active value. + * For a constant, likewise, but use PL_constpadix. */ SV * const * const names = AvARRAY(PL_comppad_name); const SSize_t names_fill = AvFILLp(PL_comppad_name); + const bool konst = cBOOL(tmptype & SVf_READONLY); + retval = konst ? PL_constpadix : PL_padix; for (;;) { /* * Entries that close over unavailable variables @@ -741,13 +746,13 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype) * Thus we must skip, not just pad values that are * marked as current pad values, but also those with names. */ - if (++PL_padix <= names_fill && - (sv = names[PL_padix]) && sv != &PL_sv_undef) + if (++retval <= names_fill && + (sv = names[retval]) && sv != &PL_sv_undef) continue; - sv = *av_fetch(PL_comppad, PL_padix, TRUE); + sv = *av_fetch(PL_comppad, retval, TRUE); if (!(SvFLAGS(sv) & #ifdef USE_BROKEN_PAD_RESET - (SVs_PADMY|(tmptype & SVf_READONLY ? SVs_PADTMP : 0)) + (SVs_PADMY|(konst ? SVs_PADTMP : 0)) #else (SVs_PADMY|SVs_PADTMP) #endif @@ -755,12 +760,12 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype) !IS_PADGV(sv)) break; } - if (tmptype & SVf_READONLY) { - av_store(PL_comppad_name, PL_padix, &PL_sv_no); + if (konst) { + av_store(PL_comppad_name, retval, &PL_sv_no); tmptype &= ~SVf_READONLY; tmptype |= SVs_PADTMP; } - retval = PL_padix; + *(konst ? &PL_constpadix : &PL_padix) = retval; } SvFLAGS(sv) |= tmptype; PL_curpad = AvARRAY(PL_comppad); @@ -1630,8 +1635,11 @@ Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust) } PadnamelistARRAY(PL_comppad_name)[po] = &PL_sv_undef; } - if ((I32)po < PL_padix) - PL_padix = po - 1; + /* Use PL_constpadix here, not PL_padix. The latter may have been + reset by pad_reset. We don’t want pad_alloc to have to scan the + whole pad when allocating a constant. */ + if ((I32)po < PL_constpadix) + PL_constpadix = po - 1; } /* |