summaryrefslogtreecommitdiff
path: root/cop.h
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-06-04 14:04:03 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-06-04 18:14:53 -0700
commitd4d03940c58a0177edb93c8854929856e9975bf9 (patch)
tree3852b1f0c210b55ba9172c1edbef3040a6fbae36 /cop.h
parentf3ac9fb2631eb3706dcdd2fe0274a953da37486f (diff)
downloadperl-d4d03940c58a0177edb93c8854929856e9975bf9.tar.gz
[perl #78742] Store CopSTASH in a pad under threads
Before this commit, a pointer to the cop’s stash was stored in cop->cop_stash under non-threaded perls, and the name and name length were stored in cop->cop_stashpv and cop->cop_stashlen under ithreads. Consequently, eval "__PACKAGE__" would end up returning the wrong package name under threads if the current package had been assigned over. This commit changes the way cops store their stash under threads. Now it is an offset (cop->cop_stashoff) into the new PL_stashpad array (just a mallocked block), which holds pointers to all stashes that have code compiled in them. I didn’t use the lexical pads, because CopSTASH(cop) won’t work unless PL_curpad is holding the right pad. And things start to get very hairy in pp_caller, since the correct pad isn’t anywhere easily accessible on the context stack (oldcomppad actually referring to the current comppad). The approach I’ve followed uses far less code, too. In addition to fixing the bug, this also saves memory. Instead of allocating a separate PV for every single statement (to hold the stash name), now all lines of code in a package can share the same stashpad slot. So, on a 32-bit OS X, that’s 16 bytes less memory per COP for short package names. Since stashoff is the same size as stashpv, there is no difference there. Each package now needs just 4 bytes in the stashpad for storing a pointer. For speed’s sake PL_stashpadix stores the index of the last-used stashpad offset. So only when switching packages is there a linear search through the stashpad.
Diffstat (limited to 'cop.h')
-rw-r--r--cop.h49
1 files changed, 11 insertions, 38 deletions
diff --git a/cop.h b/cop.h
index dc52807841..f5afb61014 100644
--- a/cop.h
+++ b/cop.h
@@ -387,9 +387,8 @@ struct cop {
line_t cop_line; /* line # of this command */
/* label for this construct is now stored in cop_hints_hash */
#ifdef USE_ITHREADS
- char * cop_stashpv; /* package line was compiled in */
+ PADOFFSET cop_stashoff; /* package line was compiled in */
char * cop_file; /* file name the following line # is from */
- I32 cop_stashlen; /* negative for UTF8 */
#else
HV * cop_stash; /* package line was compiled in */
GV * cop_filegv; /* file the following line # is from */
@@ -426,41 +425,14 @@ struct cop {
# else
# define CopFILEAVx(c) (GvAV(gv_fetchfile(CopFILE(c))))
# endif
-# define CopSTASHPV(c) ((c)->cop_stashpv)
+# define CopSTASH(c) PL_stashpad[(c)->cop_stashoff]
+# define CopSTASH_set(c,hv) ((c)->cop_stashoff = (hv) \
+ ? alloccopstash(hv) \
+ : 0)
# ifdef NETWARE
-# define CopSTASHPV_set(c,pv,n) ((c)->cop_stashpv = \
- ((pv) ? savepvn(pv,n) : NULL))
-# else
-# define CopSTASHPV_set(c,pv,n) ((c)->cop_stashpv = (pv) \
- ? savesharedpvn(pv,n) : NULL)
-# endif
-
-# define CopSTASH_len_set(c,n) ((c)->cop_stashlen = (n))
-# define CopSTASH_len(c) ((c)->cop_stashlen)
-
-# define CopSTASH(c) (CopSTASHPV(c) \
- ? gv_stashpvn(CopSTASHPV(c), \
- CopSTASH_len(c) < 0 \
- ? -CopSTASH_len(c) \
- : CopSTASH_len(c), \
- GV_ADD|SVf_UTF8*(CopSTASH_len(c) < 0) \
- ) \
- : NULL)
-# define CopSTASH_set(c,hv) (CopSTASHPV_set(c, \
- (hv) ? HvNAME_get(hv) : NULL, \
- (hv) ? HvNAMELEN(hv) : 0), \
- CopSTASH_len_set(c, \
- (hv) ? HvNAMEUTF8(hv) \
- ? -HvNAMELEN(hv) \
- : HvNAMELEN(hv) \
- : 0))
-# define CopSTASH_eq(c,hv) ((hv) && stashpv_hvname_match(c,hv))
-# ifdef NETWARE
-# define CopSTASH_free(c) SAVECOPSTASH_FREE(c)
# define CopFILE_free(c) SAVECOPFILE_FREE(c)
# else
-# define CopSTASH_free(c) PerlMemShared_free(CopSTASHPV(c))
# define CopFILE_free(c) (PerlMemShared_free(CopFILE(c)),(CopFILE(c) = NULL))
# endif
#else
@@ -479,15 +451,16 @@ struct cop {
? SvPVX(GvSV(CopFILEGV(c))) : NULL)
# define CopSTASH(c) ((c)->cop_stash)
# define CopSTASH_set(c,hv) ((c)->cop_stash = (hv))
-# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME_get(CopSTASH(c)) : NULL)
- /* cop_stash is not refcounted */
-# define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD))
-# define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv))
-# define CopSTASH_free(c)
# define CopFILE_free(c) (SvREFCNT_dec(CopFILEGV(c)),(CopFILEGV(c) = NULL))
#endif /* USE_ITHREADS */
+#define CopSTASHPV(c) (CopSTASH(c) ? HvNAME_get(CopSTASH(c)) : NULL)
+ /* cop_stash is not refcounted */
+#define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD))
+#define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv))
+#define CopSTASH_free(c)
+
#define CopHINTHASH_get(c) ((COPHH*)((c)->cop_hints_hash))
#define CopHINTHASH_set(c,h) ((c)->cop_hints_hash = (h))