diff options
author | Father Chrysostomos <sprout@cpan.org> | 2014-11-27 22:30:54 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-11-30 11:48:42 -0800 |
commit | 0f94cb1fe27e58a59d3391214dab34037ab184db (patch) | |
tree | 00f43fa153a153b7e2a1d1728b6a9880264fa132 /pad.h | |
parent | b19cb98db58c735b4237857f7f69fd857d61934a (diff) | |
download | perl-0f94cb1fe27e58a59d3391214dab34037ab184db.tar.gz |
[perl #123223] Make PADNAME a separate type
distinct from SV. This should fix the CPAN modules that were failing
when the PadnameLVALUE flag was added, because it shared the same
bit as SVs_OBJECT and pad names were going through code paths not
designed to handle pad names.
Unfortunately, it will probably break other CPAN modules, but I think
this change is for the better, as it makes both pad names and SVs sim-
pler and makes pad names take less memory.
Diffstat (limited to 'pad.h')
-rw-r--r-- | pad.h | 151 |
1 files changed, 76 insertions, 75 deletions
@@ -45,6 +45,29 @@ struct padnamelist { U32 xpadnl_refcnt; }; +struct padname { + char * xpadn_pv; + HV * xpadn_ourstash; + union { + HV * xpadn_typestash; + CV * xpadn_protocv; + } xpadn_type_u; + U32 xpadn_low; + U32 xpadn_high; + U32 xpadn_refcnt; + int xpadn_gen; + U8 xpadn_len; + U8 xpadn_flags; +}; + +struct padname_with_str { + struct padname xpadn_padname; + char xpadn_str[1]; +}; + +#define PADNAME_FROM_PV(s) \ + ((PADNAME *)((s) - STRUCT_OFFSET(struct padname_with_str, xpadn_str))) + /* a value that PL_cop_seqmax is guaranteed never to be, * flagging that a lexical is being introduced, or has not yet left scope @@ -59,63 +82,10 @@ struct padnamelist { /* Low range end is exclusive (valid from the cop seq after this one) */ /* High range end is inclusive (valid up to this cop seq) */ -#if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) -# define COP_SEQ_RANGE_LOW(sv) \ - (({ const SV *const _sv_cop_seq_range_low = (const SV *) (sv); \ - assert(SvTYPE(_sv_cop_seq_range_low) == SVt_NV \ - || SvTYPE(_sv_cop_seq_range_low) >= SVt_PVNV); \ - assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVAV); \ - assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVHV); \ - assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVCV); \ - assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVFM); \ - assert(!isGV_with_GP(_sv_cop_seq_range_low)); \ - ((XPVNV*) MUTABLE_PTR(SvANY(_sv_cop_seq_range_low)))->xnv_u.xpad_cop_seq.xlow; \ - })) -# define COP_SEQ_RANGE_HIGH(sv) \ - (({ const SV *const _sv_cop_seq_range_high = (const SV *) (sv); \ - assert(SvTYPE(_sv_cop_seq_range_high) == SVt_NV \ - || SvTYPE(_sv_cop_seq_range_high) >= SVt_PVNV); \ - assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVAV); \ - assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVHV); \ - assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVCV); \ - assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVFM); \ - assert(!isGV_with_GP(_sv_cop_seq_range_high)); \ - ((XPVNV*) MUTABLE_PTR(SvANY(_sv_cop_seq_range_high)))->xnv_u.xpad_cop_seq.xhigh; \ - })) -# define PARENT_PAD_INDEX(sv) \ - (({ const SV *const _sv_parent_pad_index = (const SV *) (sv); \ - assert(SvTYPE(_sv_parent_pad_index) == SVt_NV \ - || SvTYPE(_sv_parent_pad_index) >= SVt_PVNV); \ - assert(SvTYPE(_sv_parent_pad_index) != SVt_PVAV); \ - assert(SvTYPE(_sv_parent_pad_index) != SVt_PVHV); \ - assert(SvTYPE(_sv_parent_pad_index) != SVt_PVCV); \ - assert(SvTYPE(_sv_parent_pad_index) != SVt_PVFM); \ - assert(!isGV_with_GP(_sv_parent_pad_index)); \ - ((XPVNV*) MUTABLE_PTR(SvANY(_sv_parent_pad_index)))->xnv_u.xpad_cop_seq.xlow; \ - })) -# define PARENT_FAKELEX_FLAGS(sv) \ - (({ const SV *const _sv_parent_fakelex_flags = (const SV *) (sv); \ - assert(SvTYPE(_sv_parent_fakelex_flags) == SVt_NV \ - || SvTYPE(_sv_parent_fakelex_flags) >= SVt_PVNV); \ - assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVAV); \ - assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVHV); \ - assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVCV); \ - assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVFM); \ - assert(!isGV_with_GP(_sv_parent_fakelex_flags)); \ - ((XPVNV*) MUTABLE_PTR(SvANY(_sv_parent_fakelex_flags)))->xnv_u.xpad_cop_seq.xhigh; \ - })) -#else -# define COP_SEQ_RANGE_LOW(sv) \ - (0 + (((XPVNV*) SvANY(sv))->xnv_u.xpad_cop_seq.xlow)) -# define COP_SEQ_RANGE_HIGH(sv) \ - (0 + (((XPVNV*) SvANY(sv))->xnv_u.xpad_cop_seq.xhigh)) - - -# define PARENT_PAD_INDEX(sv) \ - (0 + (((XPVNV*) SvANY(sv))->xnv_u.xpad_cop_seq.xlow)) -# define PARENT_FAKELEX_FLAGS(sv) \ - (0 + (((XPVNV*) SvANY(sv))->xnv_u.xpad_cop_seq.xhigh)) -#endif +#define COP_SEQ_RANGE_LOW(pn) (pn)->xpadn_low +#define COP_SEQ_RANGE_HIGH(pn) (pn)->xpadn_high +#define PARENT_PAD_INDEX(pn) (pn)->xpadn_low +#define PARENT_FAKELEX_FLAGS(pn) (pn)->xpadn_high /* Flags set in the SvIVX field of FAKE namesvs */ @@ -236,8 +206,7 @@ The length of the name. Whether PadnamePV is in UTF8. Currently, this is always true. =for apidoc Amx|SV *|PadnameSV|PADNAME pn -Returns the pad name as an SV. This is currently just C<pn>. It will -begin returning a new mortal SV if pad names ever stop being SVs. +Returns the pad name as a mortal SV. =for apidoc m|bool|PadnameIsOUR|PADNAME pn Whether this is an "our" variable. @@ -256,6 +225,12 @@ Whether this is a "state" variable. The stash associated with a typed lexical. This returns the %Foo:: hash for C<my Foo $bar>. +=for apidoc Amx|SSize_t|PadnameREFCNT|PADNAME pn +The reference count of the pad name. + +=for apidoc Amx|void|PadnameREFCNT_dec|PADNAME pn +Lowers the reference count of the pad name. + =for apidoc m|SV *|PAD_SETSV |PADOFFSET po|SV* sv Set the slot at offset C<po> in the current pad to C<sv> @@ -313,19 +288,45 @@ Restore the old pad saved into the local variable opad by PAD_SAVE_LOCAL() #define PadARRAY(pad) AvARRAY(pad) #define PadMAX(pad) AvFILLp(pad) -#define PadnamePV(pn) (SvPOKp(pn) ? SvPVX_const(pn) : NULL) -#define PadnameLEN(pn) ((SV*)(pn) == &PL_sv_undef ? 0 : SvCUR(pn)) -#define PadnameUTF8(pn) (assert_(SvUTF8(pn)) 1) -#define PadnameSV(pn) pn -#define PadnameIsOUR(pn) !!SvPAD_OUR(pn) -#define PadnameOURSTASH(pn) SvOURSTASH(pn) -#define PadnameOUTER(pn) !!SvFAKE(pn) -#define PadnameIsSTATE(pn) !!SvPAD_STATE(pn) -#define PadnameTYPE(pn) (SvPAD_TYPED(pn) ? SvSTASH(pn) : NULL) -#define PadnameLVALUE(pn) \ - ((SvFLAGS(pn) & (SVpad_NAME|SVpad_LVALUE))==(SVpad_NAME|SVpad_LVALUE)) - -#define PadnameLVALUE_on(pn) (SvFLAGS(pn) |= SVpad_NAME|SVpad_LVALUE) +#define PadnamePV(pn) (pn)->xpadn_pv +#define PadnameLEN(pn) (pn)->xpadn_len +#define PadnameUTF8(pn) 1 +#define PadnameSV(pn) \ + newSVpvn_flags(PadnamePV(pn), PadnameLEN(pn), SVs_TEMP|SVf_UTF8) +#define PadnameFLAGS(pn) (pn)->xpadn_flags +#define PadnameIsOUR(pn) (!!(pn)->xpadn_ourstash) +#define PadnameOURSTASH(pn) (pn)->xpadn_ourstash +#define PadnameTYPE(pn) (pn)->xpadn_type_u.xpadn_typestash +#define PadnamePROTOCV(pn) (pn)->xpadn_type_u.xpadn_protocv +#define PadnameREFCNT(pn) (pn)->xpadn_refcnt +#define PadnameREFCNT_dec(pn) Perl_padname_free(aTHX_ pn) +#define PadnameOURSTASH_set(pn,s) (PadnameOURSTASH(pn) = (s)) +#define PadnameTYPE_set(pn,s) (PadnameTYPE(pn) = (s)) +#define PadnameOUTER(pn) (PadnameFLAGS(pn) & PADNAMEt_OUTER) +#define PadnameIsSTATE(pn) (PadnameFLAGS(pn) & PADNAMEt_STATE) +#define PadnameLVALUE(pn) (PadnameFLAGS(pn) & PADNAMEt_LVALUE) + +#define PadnameLVALUE_on(pn) (PadnameFLAGS(pn) |= PADNAMEt_LVALUE) +#define PadnameIsSTATE_on(pn) (PadnameFLAGS(pn) |= PADNAMEt_STATE) + +#define PADNAMEt_OUTER 1 /* outer lexical var */ +#define PADNAMEt_STATE 2 /* state var */ +#define PADNAMEt_LVALUE 4 /* used as lvalue */ +#define PADNAMEt_TYPED 8 /* for B; unused by core */ +#define PADNAMEt_OUR 16 /* for B; unused by core */ + +/* backward compatibility */ +#define SvPAD_STATE PadnameIsSTATE +#define SvPAD_TYPED(pn) (!!PadnameTYPE(pn)) +#define SvPAD_OUR(pn) (!!PadnameOURSTASH(pn)) +#define SvPAD_STATE_on PadnameIsSTATE_on +#define SvPAD_TYPED_on(pn) (PadnameFLAGS(pn) |= PADNAMEt_TYPED) +#define SvPAD_OUR_on(pn) (PadnameFLAGS(pn) |= PADNAMEt_OUR) +#define SvOURSTASH PadnameOURSTASH +#define SvOURSTASH_set PadnameOURSTASH_set +#define SVpad_STATE PADNAMEt_STATE +#define SVpad_TYPED PADNAMEt_TYPED +#define SVpad_OUR PADNAMEt_OUR #ifdef DEBUGGING # define PAD_SV(po) pad_sv(po) @@ -423,7 +424,7 @@ ling pad (lvalue) to C<gen>. Note that C<SvUV_set> is hijacked for this purpose #define PAD_COMPNAME(po) PAD_COMPNAME_SV(po) #define PAD_COMPNAME_SV(po) (PadnamelistARRAY(PL_comppad_name)[(po)]) -#define PAD_COMPNAME_FLAGS(po) SvFLAGS(PAD_COMPNAME_SV(po)) +#define PAD_COMPNAME_FLAGS(po) PadnameFLAGS(PAD_COMPNAME(po)) #define PAD_COMPNAME_FLAGS_isOUR(po) SvPAD_OUR(PAD_COMPNAME_SV(po)) #define PAD_COMPNAME_PV(po) PadnamePV(PAD_COMPNAME(po)) @@ -433,10 +434,10 @@ ling pad (lvalue) to C<gen>. Note that C<SvUV_set> is hijacked for this purpose (SvOURSTASH(PAD_COMPNAME_SV(po))) #define PAD_COMPNAME_GEN(po) \ - ((STRLEN)SvUVX(PadnamelistARRAY(PL_comppad_name)[po])) + ((STRLEN)PadnamelistARRAY(PL_comppad_name)[po]->xpadn_gen) #define PAD_COMPNAME_GEN_set(po, gen) \ - SvUV_set(PadnamelistARRAY(PL_comppad_name)[po], (UV)(gen)) + (PadnamelistARRAY(PL_comppad_name)[po]->xpadn_gen = (gen)) /* |