summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-07-05 22:51:50 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-08-05 02:23:28 -0700
commitc82ecf346a8512f22f25188e450d92938c245421 (patch)
tree4a8a85a9655bcb136136674dc3f838204bc9d202 /op.c
parent38be3d0038ef87b22af88f80db1fbeb0292ce53b (diff)
downloadperl-c82ecf346a8512f22f25188e450d92938c245421.tar.gz
[perl #117855] Store CopFILEGV in a pad under ithreads
This saves having to allocate a separate string buffer for every cop (control op; every statement has one). Under non-threaded builds, every cop has a pointer to the GV for that source file, namely *{"_<filename"}. Under threaded builds, the name of the GV used to be stored instead. Now we store an offset into the per-interpreter PL_filegvpad, which points to the GV. This makes no significant speed difference, but it reduces mem- ory usage.
Diffstat (limited to 'op.c')
-rw-r--r--op.c66
1 files changed, 51 insertions, 15 deletions
diff --git a/op.c b/op.c
index 622236c6c1..b69585beab 100644
--- a/op.c
+++ b/op.c
@@ -634,31 +634,64 @@ C<PL_stashpad> for the stash passed to it.
*/
#ifdef USE_ITHREADS
+
PADOFFSET
-Perl_alloccopstash(pTHX_ HV *hv)
+S_alloc_global_pad_slot(pTHX_ SV *sv, svtype type, SV ***padp,
+ PADOFFSET *ixp, PADOFFSET *maxp)
{
PADOFFSET off = 0, o = 1;
bool found_slot = FALSE;
+ SV **pad = *padp;
- PERL_ARGS_ASSERT_ALLOCCOPSTASH;
-
- if (PL_stashpad[PL_stashpadix] == hv) return PL_stashpadix;
+ if (pad[*ixp] == sv) return *ixp;
- for (; o < PL_stashpadmax; ++o) {
- if (PL_stashpad[o] == hv) return PL_stashpadix = o;
- if (!PL_stashpad[o] || SvTYPE(PL_stashpad[o]) != SVt_PVHV)
+ for (; o < *maxp; ++o) {
+ if (pad[o] == sv) return *ixp = o;
+ if (!pad[o] || SvTYPE(pad[o]) != type)
found_slot = TRUE, off = o;
}
if (!found_slot) {
- Renew(PL_stashpad, PL_stashpadmax + 10, HV *);
- Zero(PL_stashpad + PL_stashpadmax, 10, HV *);
- off = PL_stashpadmax;
- PL_stashpadmax += 10;
+ Renew(*padp, *maxp + 10, SV *);
+ pad = *padp;
+ Zero(pad + *maxp, 10, SV *);
+ off = *maxp;
+ *maxp += 10;
}
- PL_stashpad[PL_stashpadix = off] = hv;
+ pad[*ixp = off] = sv;
return off;
}
+
+PADOFFSET
+Perl_alloccopstash(pTHX_ HV *hv)
+{
+ PERL_ARGS_ASSERT_ALLOCCOPSTASH;
+ return S_alloc_global_pad_slot(aTHX_
+ (SV *)hv, SVt_PVHV, (SV ***)&PL_stashpad, &PL_stashpadix,
+ &PL_stashpadmax
+ );
+}
+#endif
+
+/*
+=for apidoc allocfilegv
+
+Available only under threaded builds, this function allocates an entry in
+C<PL_filegvpad> for the GV passed to it.
+
+=cut
+*/
+
+#ifdef USE_ITHREADS
+PADOFFSET
+Perl_allocfilegv(pTHX_ GV *gv)
+{
+ PERL_ARGS_ASSERT_ALLOCFILEGV;
+ return S_alloc_global_pad_slot(aTHX_
+ (SV *)gv, SVt_PVGV, (SV ***)&PL_filegvpad, &PL_filegvpadix,
+ &PL_filegvpadmax
+ );
+}
#endif
/* free the body of an op without examining its contents.
@@ -5723,7 +5756,10 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
PL_parser->copline = NOLINE;
}
#ifdef USE_ITHREADS
- CopFILE_set(cop, CopFILE(PL_curcop)); /* XXX share in a pvtable? */
+ /* While CopFILEGV_set does work under ithreads, this is faster, as it
+ avoids a linear scan of the filegv pad: */
+ if((cop->cop_filegvoff = PL_curcop->cop_filegvoff))
+ SvREFCNT_inc_void_NN(PL_filegvpad[cop->cop_filegvoff]);
#else
CopFILEGV_set(cop, CopFILEGV(PL_curcop));
#endif
@@ -10874,7 +10910,7 @@ Perl_rpeep(pTHX_ OP *o)
firstcop->cop_line = secondcop->cop_line;
#ifdef USE_ITHREADS
firstcop->cop_stashoff = secondcop->cop_stashoff;
- firstcop->cop_file = secondcop->cop_file;
+ firstcop->cop_filegvoff = secondcop->cop_filegvoff;
#else
firstcop->cop_stash = secondcop->cop_stash;
firstcop->cop_filegv = secondcop->cop_filegv;
@@ -10886,7 +10922,7 @@ Perl_rpeep(pTHX_ OP *o)
#ifdef USE_ITHREADS
secondcop->cop_stashoff = 0;
- secondcop->cop_file = NULL;
+ secondcop->cop_filegvoff = 0;
#else
secondcop->cop_stash = NULL;
secondcop->cop_filegv = NULL;