mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 16:39:36 +00:00
Under ithreads, constants and GVs are stored in the pad. When names are looked up up in a pad, the search begins at the end and works its way toward the beginning, so that an $x declared later masks one declared earlier. If there are many constants at the end of the pad, which can happen for generated code such as lib/unicore/TestProp.pl (which has about 100,000 lines and over 500,000 pad entries for constants at the end of the file scope’s pad), it can take a long time to search through them all. Before commit 325e1816, constants used &PL_sv_undef ‘names’. Since that is the default value for array elements (when viewed directly through AvARRAY, rather than av_fetch), the pad allocation code did not even bother storing the ‘name’ for these. So the name pad (aka padnamelist) was not extended, leaving just 10 entries or so in the case of lib/unicore/TestProp.pl. Commit 325e1816 make pad constants have &PL_sv_no names, so the name pad would be implicitly extended as a result of storing &PL_sv_no, causing a huge slowdown in t/re/uniprops.t (which runs lib/unicore/TestProp.pl) under threaded builds. Now, normally the name pad *does* get extended to match the pad, in pad_tidy, but that is skipped for string eval (and required file scope, of course). Hence, wrapping the contents of lib/unicore/TestProp.pl in a sub or adding ‘my $x’ to end of it will cause the same slowdown before 325e1816. lib/unicore/TestProp.pl just happened to be written (ok, generated) in such a way that it ended up with a small name pad. This commit fixes things to make them as fast as before by recording the index of the last named variable in the pad. Anything following that is disregarded in pad lookup and search begins with the last named variable. (This actually does make things faster before for subs with many trailing constants in the pad.) This is not a complete fix. Adding ‘my $x’ to the end of a large file like lib/unicore/TestProp.pl will make it just as slow again. Ultimately we need another algorithm, such as a binary search.
109 lines
3.1 KiB
C
109 lines
3.1 KiB
C
/* av.h
|
|
*
|
|
* Copyright (C) 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000,
|
|
* 2001, 2002, 2005, 2006, 2007, 2008, by Larry Wall and others
|
|
*
|
|
* You may distribute under the terms of either the GNU General Public
|
|
* License or the Artistic License, as specified in the README file.
|
|
*
|
|
*/
|
|
|
|
struct xpvav {
|
|
HV* xmg_stash; /* class package */
|
|
union _xmgu xmg_u;
|
|
SSize_t xav_fill; /* Index of last element present */
|
|
SSize_t xav_max; /* max index for which array has space */
|
|
SV** xav_alloc; /* pointer to beginning of C array of SVs */
|
|
};
|
|
|
|
/* SV* xav_arylen; */
|
|
|
|
/* SVpav_REAL is set for all AVs whose xav_array contents are refcounted.
|
|
* Some things like "@_" and the scratchpad list do not set this, to
|
|
* indicate that they are cheating (for efficiency) by not refcounting
|
|
* the AV's contents.
|
|
*
|
|
* SVpav_REIFY is only meaningful on such "fake" AVs (i.e. where SVpav_REAL
|
|
* is not set). It indicates that the fake AV is capable of becoming
|
|
* real if the array needs to be modified in some way. Functions that
|
|
* modify fake AVs check both flags to call av_reify() as appropriate.
|
|
*
|
|
* Note that the Perl stack has neither flag set. (Thus,
|
|
* items that go on the stack are never refcounted.)
|
|
*
|
|
* These internal details are subject to change any time. AV
|
|
* manipulations external to perl should not care about any of this.
|
|
* GSAR 1999-09-10
|
|
*/
|
|
|
|
/*
|
|
=head1 Handy Values
|
|
|
|
=for apidoc AmU||Nullav
|
|
Null AV pointer.
|
|
|
|
(deprecated - use C<(AV *)NULL> instead)
|
|
|
|
=head1 Array Manipulation Functions
|
|
|
|
=for apidoc Am|int|AvFILL|AV* av
|
|
Same as C<av_top_index()>. Deprecated, use C<av_top_index()> instead.
|
|
|
|
=for apidoc Am|int|av_tindex|AV* av
|
|
Same as C<av_top_index()>.
|
|
|
|
=cut
|
|
*/
|
|
|
|
#ifndef PERL_CORE
|
|
# define Nullav Null(AV*)
|
|
#endif
|
|
|
|
#define AvARRAY(av) ((av)->sv_u.svu_array)
|
|
#define AvALLOC(av) ((XPVAV*) SvANY(av))->xav_alloc
|
|
#define AvMAX(av) ((XPVAV*) SvANY(av))->xav_max
|
|
#define AvFILLp(av) ((XPVAV*) SvANY(av))->xav_fill
|
|
#define AvARYLEN(av) (*Perl_av_arylen_p(aTHX_ MUTABLE_AV(av)))
|
|
|
|
#define AvREAL(av) (SvFLAGS(av) & SVpav_REAL)
|
|
#define AvREAL_on(av) (SvFLAGS(av) |= SVpav_REAL)
|
|
#define AvREAL_off(av) (SvFLAGS(av) &= ~SVpav_REAL)
|
|
#define AvREAL_only(av) (AvREIFY_off(av), SvFLAGS(av) |= SVpav_REAL)
|
|
#define AvREIFY(av) (SvFLAGS(av) & SVpav_REIFY)
|
|
#define AvREIFY_on(av) (SvFLAGS(av) |= SVpav_REIFY)
|
|
#define AvREIFY_off(av) (SvFLAGS(av) &= ~SVpav_REIFY)
|
|
#define AvREIFY_only(av) (AvREAL_off(av), SvFLAGS(av) |= SVpav_REIFY)
|
|
#define AvPAD_NAMELIST(av) (SvFLAGS(av) & SVpad_NAMELIST)
|
|
#define AvPAD_NAMELIST_on(av) (SvFLAGS(av) |= SVpad_NAMELIST)
|
|
|
|
|
|
#define AvREALISH(av) (SvFLAGS(av) & (SVpav_REAL|SVpav_REIFY))
|
|
|
|
#define AvFILL(av) ((SvRMAGICAL((const SV *) (av))) \
|
|
? mg_size(MUTABLE_SV(av)) : AvFILLp(av))
|
|
#define av_tindex(av) av_top_index(av)
|
|
|
|
#define NEGATIVE_INDICES_VAR "NEGATIVE_INDICES"
|
|
|
|
/*
|
|
=for apidoc newAV
|
|
|
|
Creates a new AV. The reference count is set to 1.
|
|
|
|
Perl equivalent: C<my @array;>.
|
|
|
|
=cut
|
|
*/
|
|
|
|
#define newAV() MUTABLE_AV(newSV_type(SVt_PVAV))
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indentation-style: bsd
|
|
* c-basic-offset: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* ex: set ts=8 sts=4 sw=4 et:
|
|
*/
|