diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-07-07 17:35:10 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-09-15 22:44:59 -0700 |
commit | b290562ef436d5316a2f75513def7f4f18c4ef34 (patch) | |
tree | cf17255810711fb72c2702959076b99265b56068 | |
parent | 97b03d64e557578d3dbfeb6e6ca37ba57d57e858 (diff) | |
download | perl-b290562ef436d5316a2f75513def7f4f18c4ef34.tar.gz |
Allow CVs to point to HEKs rather than GVs
This will allow named lexical subs to exist independent of GVs.
-rw-r--r-- | cv.h | 22 | ||||
-rw-r--r-- | ext/B/B.xs | 6 | ||||
-rw-r--r-- | gv.c | 4 | ||||
-rw-r--r-- | pad.c | 7 | ||||
-rw-r--r-- | pp.c | 8 | ||||
-rw-r--r-- | sv.c | 11 | ||||
-rw-r--r-- | sv.h | 5 |
7 files changed, 53 insertions, 10 deletions
@@ -49,7 +49,7 @@ See L<perlguts/Autoloading with XSUBs>. #define CvROOT(sv) ((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_root_u.xcv_root #define CvXSUB(sv) ((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_root_u.xcv_xsub #define CvXSUBANY(sv) ((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_start_u.xcv_xsubany -#define CvGV(sv) (0+((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_gv) +#define CvGV(sv) S_CvGV((CV *)(sv)) #define CvGV_set(cv,gv) Perl_cvgv_set(aTHX_ cv, gv) #define CvFILE(sv) ((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_file #ifdef USE_ITHREADS @@ -103,6 +103,7 @@ See L<perlguts/Autoloading with XSUBs>. #define CVf_DYNFILE 0x1000 /* The filename isn't static */ #define CVf_AUTOLOAD 0x2000 /* SvPVX contains AUTOLOADed sub name */ #define CVf_HASEVAL 0x4000 /* contains string eval */ +#define CVf_NAMED 0x8000 /* Has a name HEK */ /* This symbol for optimised communication between toke.c and op.c: */ #define CVf_BUILTIN_ATTRS (CVf_METHOD|CVf_LVALUE) @@ -180,9 +181,28 @@ See L<perlguts/Autoloading with XSUBs>. #define CvHASEVAL_on(cv) (CvFLAGS(cv) |= CVf_HASEVAL) #define CvHASEVAL_off(cv) (CvFLAGS(cv) &= ~CVf_HASEVAL) +#define CvNAMED(cv) (CvFLAGS(cv) & CVf_NAMED) +#define CvNAMED_on(cv) (CvFLAGS(cv) |= CVf_NAMED) +#define CvNAMED_off(cv) (CvFLAGS(cv) &= ~CVf_NAMED) + /* Flags for newXS_flags */ #define XS_DYNAMIC_FILENAME 0x01 /* The filename isn't static */ +PERL_STATIC_INLINE GV * +S_CvGV(CV *sv) +{ + return CvNAMED(sv) + ? 0 + : ((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_gv_u.xcv_gv; +} +PERL_STATIC_INLINE HEK * +CvNAME_HEK(CV *sv) +{ + return CvNAMED(sv) + ? ((XPVCV*)MUTABLE_PTR(SvANY(sv)))->xcv_gv_u.xcv_hek + : 0; +} + /* =head1 CV reference counts and CvOUTSIDE diff --git a/ext/B/B.xs b/ext/B/B.xs index 69c4aaed7b..ad839b5a2b 100644 --- a/ext/B/B.xs +++ b/ext/B/B.xs @@ -1452,7 +1452,11 @@ MODULE = B PACKAGE = B::IV #define PVAV_max_ix sv_SSize_tp | offsetof(struct xpvav, xav_max) #define PVCV_stash_ix sv_SVp | offsetof(struct xpvcv, xcv_stash) -#define PVCV_gv_ix sv_SVp | offsetof(struct xpvcv, xcv_gv) +#if PERL_VERSION > 17 || (PERL_VERSION == 17 && PERL_SUBVERSION >= 3) +# define PVCV_gv_ix sv_SVp | offsetof(struct xpvcv, xcv_gv_u.xcv_gv) +#else +# define PVCV_gv_ix sv_SVp | offsetof(struct xpvcv, xcv_gv) +#endif #define PVCV_file_ix sv_char_pp | offsetof(struct xpvcv, xcv_file) #define PVCV_outside_ix sv_SVp | offsetof(struct xpvcv, xcv_outside) #define PVCV_outside_seq_ix sv_U32p | offsetof(struct xpvcv, xcv_outside_seq) @@ -207,6 +207,7 @@ void Perl_cvgv_set(pTHX_ CV* cv, GV* gv) { GV * const oldgv = CvGV(cv); + HEK *hek; PERL_ARGS_ASSERT_CVGV_SET; if (oldgv == gv) @@ -221,8 +222,9 @@ Perl_cvgv_set(pTHX_ CV* cv, GV* gv) sv_del_backref(MUTABLE_SV(oldgv), MUTABLE_SV(cv)); } } + else if ((hek = CvNAME_HEK(cv))) unshare_hek(hek); - SvANY(cv)->xcv_gv = gv; + SvANY(cv)->xcv_gv_u.xcv_gv = gv; assert(!CvCVGV_RC(cv)); if (!gv) @@ -381,7 +381,8 @@ Perl_cv_undef(pTHX_ CV *cv) #endif SvPOK_off(MUTABLE_SV(cv)); /* forget prototype */ sv_unmagic((SV *)cv, PERL_MAGIC_checkcall); - CvGV_set(cv, NULL); + if (CvNAMED(cv)) unshare_hek(CvNAME_HEK(cv)); + else CvGV_set(cv, NULL); /* This statement and the subsequence if block was pad_undef(). */ pad_peg("pad_undef"); @@ -1989,7 +1990,9 @@ Perl_cv_clone(pTHX_ CV *proto) CvFILE(cv) = CvDYNFILE(proto) ? savepv(CvFILE(proto)) : CvFILE(proto); - CvGV_set(cv,CvGV(proto)); + if (CvNAMED(proto)) + SvANY(cv)->xcv_gv_u.xcv_hek = share_hek_hek(CvNAME_HEK(proto)); + else CvGV_set(cv,CvGV(proto)); CvSTASH_set(cv, CvSTASH(proto)); OP_REFCNT_LOCK; CvROOT(cv) = OpREFCNT_inc(CvROOT(proto)); @@ -935,8 +935,14 @@ PP(pp_undef) { /* let user-undef'd sub keep its identity */ GV* const gv = CvGV((const CV *)sv); + HEK * const hek = CvNAME_HEK((CV *)sv); + if (hek) share_hek_hek(hek); cv_undef(MUTABLE_CV(sv)); - CvGV_set(MUTABLE_CV(sv), gv); + if (gv) CvGV_set(MUTABLE_CV(sv), gv); + else if (hek) { + SvANY((CV *)sv)->xcv_gv_u.xcv_hek = hek; + CvNAMED_on(sv); + } } break; case SVt_PVGV: @@ -5906,10 +5906,11 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv) assert(GvGP(gv)); assert(!CvANON(cv)); assert(CvGV(cv) == gv); + assert(!CvNAMED(cv)); /* will the CV shortly be freed by gp_free() ? */ if (GvCV(gv) == cv && GvGP(gv)->gp_refcnt < 2 && SvREFCNT(cv) < 2) { - SvANY(cv)->xcv_gv = NULL; + SvANY(cv)->xcv_gv_u.xcv_gv = NULL; return; } @@ -5923,7 +5924,7 @@ S_anonymise_cv_maybe(pTHX_ GV *gv, CV* cv) CvANON_on(cv); CvCVGV_RC_on(cv); - SvANY(cv)->xcv_gv = MUTABLE_GV(SvREFCNT_inc(anongv)); + SvANY(cv)->xcv_gv_u.xcv_gv = MUTABLE_GV(SvREFCNT_inc(anongv)); } @@ -12159,9 +12160,13 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) } assert(!CvSLABBED(dstr)); if (CvDYNFILE(dstr)) CvFILE(dstr) = SAVEPV(CvFILE(dstr)); + if (CvNAMED(dstr)) + SvANY((CV *)dstr)->xcv_gv_u.xcv_hek = + share_hek_hek(CvNAME_HEK((CV *)sstr)); /* don't dup if copying back - CvGV isn't refcounted, so the * duped GV may never be freed. A bit of a hack! DAPM */ - SvANY(MUTABLE_CV(dstr))->xcv_gv = + else + SvANY(MUTABLE_CV(dstr))->xcv_gv_u.xcv_gv = CvCVGV_RC(dstr) ? gv_dup_inc(CvGV(sstr), param) : (param->flags & CLONEf_JOIN_IN) @@ -459,7 +459,10 @@ typedef U16 cv_flags_t; OP * xcv_root; \ void (*xcv_xsub) (pTHX_ CV*); \ } xcv_root_u; \ - GV * xcv_gv; \ + union { \ + GV * xcv_gv; \ + HEK * xcv_hek; \ + } xcv_gv_u; \ char * xcv_file; \ PADLIST * xcv_padlist; \ CV * xcv_outside; \ |