summaryrefslogtreecommitdiff
path: root/pad.h
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-11-27 22:30:54 -0800
committerFather Chrysostomos <sprout@cpan.org>2014-11-30 11:48:42 -0800
commit0f94cb1fe27e58a59d3391214dab34037ab184db (patch)
tree00f43fa153a153b7e2a1d1728b6a9880264fa132 /pad.h
parentb19cb98db58c735b4237857f7f69fd857d61934a (diff)
downloadperl-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.h151
1 files changed, 76 insertions, 75 deletions
diff --git a/pad.h b/pad.h
index 135f1d2143..e19c7a8e2a 100644
--- a/pad.h
+++ b/pad.h
@@ -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))
/*