/* pad.c
*
- * Copyright (C) 2002, 2003, 2004, 2005 by Larry Wall and others
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
The SVs in the names AV have their PV being the name of the variable.
NV+1..IV inclusive is a range of cop_seq numbers for which the name is
valid. For typed lexicals name SV is SVt_PVMG and SvSTASH points at the
-type. For C<our> lexicals, the type is SVt_PVGV, and GvSTASH points at the
-stash of the associated global (so that duplicate C<our> declarations in the
-same package can be detected). SvCUR is sometimes hijacked to
-store the generation number during compilation.
+type. For C<our> lexicals, the type is also SVt_PVMG, with the OURSTASH slot
+pointing at the stash of the associated global (so that duplicate C<our>
+declarations in the same package can be detected). SvCUR is sometimes
+hijacked to store the generation number during compilation.
If SvFAKE is set on the name SV, then that slot in the frame AV is
a REFCNT'ed reference to a lexical from "outside". In this case,
#include "EXTERN.h"
#define PERL_IN_PAD_C
#include "perl.h"
+#include "keywords.h"
#define PAD_MAX 999999999
-
+#ifdef PERL_MAD
+void pad_peg(const char* s) {
+ static int pegcnt;
+ pegcnt++;
+}
+#endif
/*
=for apidoc pad_new
PADLIST *
Perl_pad_new(pTHX_ int flags)
{
+ dVAR;
AV *padlist, *padname, *pad;
ASSERT_CURPAD_LEGAL("pad_new");
AvREIFY_only(a0);
}
else {
- av_store(pad, 0, Nullsv);
+ av_store(pad, 0, NULL);
}
AvREAL_off(padlist);
void
Perl_pad_undef(pTHX_ CV* cv)
{
+ dVAR;
I32 ix;
const PADLIST * const padlist = CvPADLIST(cv);
+ pad_peg("pad_undef");
if (!padlist)
return;
if (SvIS_FREED(padlist)) /* may be during global destruction */
CV * const innercv = (CV*)curpad[ix];
U32 inner_rc = SvREFCNT(innercv);
assert(inner_rc);
- namepad[ix] = Nullsv;
+ namepad[ix] = NULL;
SvREFCNT_dec(namesv);
if (SvREFCNT(comppad) < 2) { /* allow for /(?{ sub{} })/ */
- curpad[ix] = Nullsv;
+ curpad[ix] = NULL;
SvREFCNT_dec(innercv);
inner_rc--;
}
- if (inner_rc /* in use, not just a prototype */
- && CvOUTSIDE(innercv) == cv)
- {
+
+ /* in use, not just a prototype */
+ if (inner_rc && (CvOUTSIDE(innercv) == cv)) {
assert(CvWEAKOUTSIDE(innercv));
/* don't relink to grandfather if he's being freed */
if (outercv && SvREFCNT(outercv)) {
CvWEAKOUTSIDE_off(innercv);
CvOUTSIDE(innercv) = outercv;
CvOUTSIDE_SEQ(innercv) = seq;
- (void)SvREFCNT_inc(outercv);
+ SvREFCNT_inc_simple_void_NN(outercv);
}
else {
- CvOUTSIDE(innercv) = Nullcv;
+ CvOUTSIDE(innercv) = NULL;
}
-
}
-
}
}
}
ix = AvFILLp(padlist);
while (ix >= 0) {
- SV* const sv = AvARRAY(padlist)[ix--];
- if (!sv)
- continue;
- if (sv == (SV*)PL_comppad_name)
- PL_comppad_name = Nullav;
- else if (sv == (SV*)PL_comppad) {
- PL_comppad = Null(PAD*);
- PL_curpad = Null(SV**);
+ const SV* const sv = AvARRAY(padlist)[ix--];
+ if (sv) {
+ if (sv == (SV*)PL_comppad_name)
+ PL_comppad_name = NULL;
+ else if (sv == (SV*)PL_comppad) {
+ PL_comppad = NULL;
+ PL_curpad = NULL;
+ }
}
SvREFCNT_dec(sv);
}
SvREFCNT_dec((SV*)CvPADLIST(cv));
- CvPADLIST(cv) = Null(PADLIST*);
+ CvPADLIST(cv) = NULL;
}
If C<typestash> is valid, the name is for a typed lexical; set the
name's stash to that value.
If C<ourstash> is valid, it's an our lexical, set the name's
-GvSTASH to that value
+OURSTASH to that value
If fake, it means we're cloning an existing entry
*/
PADOFFSET
-Perl_pad_add_name(pTHX_ const char *name, HV* typestash, HV* ourstash, bool fake)
+Perl_pad_add_name(pTHX_ const char *name, HV* typestash, HV* ourstash, bool fake, bool state)
{
+ dVAR;
const PADOFFSET offset = pad_alloc(OP_PADSV, SVs_PADMY);
- SV* const namesv = NEWSV(1102, 0);
+ SV* const namesv = newSV(0);
ASSERT_CURPAD_ACTIVE("pad_add_name");
- sv_upgrade(namesv, ourstash ? SVt_PVGV : typestash ? SVt_PVMG : SVt_PVNV);
+ sv_upgrade(namesv, (ourstash || typestash) ? SVt_PVMG : SVt_PVNV);
sv_setpv(namesv, name);
if (typestash) {
- SvFLAGS(namesv) |= SVpad_TYPED;
- SvSTASH_set(namesv, (HV*)SvREFCNT_inc((SV*) typestash));
+ assert(SvTYPE(namesv) == SVt_PVMG);
+ SvPAD_TYPED_on(namesv);
+ SvSTASH_set(namesv, (HV*)SvREFCNT_inc_simple_NN((SV*)typestash));
}
if (ourstash) {
- SvFLAGS(namesv) |= SVpad_OUR;
- GvSTASH(namesv) = ourstash;
- Perl_sv_add_backref(aTHX_ (SV*)ourstash, namesv);
+ SvPAD_OUR_on(namesv);
+ OURSTASH_set(namesv, ourstash);
+ SvREFCNT_inc_simple_void_NN(ourstash);
+ }
+ else if (state) {
+ SvPAD_STATE_on(namesv);
}
av_store(PL_comppad_name, offset, namesv);
PADOFFSET
Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype)
{
+ dVAR;
SV *sv;
I32 retval;
+ PERL_UNUSED_ARG(optype);
ASSERT_CURPAD_ACTIVE("pad_alloc");
if (AvARRAY(PL_comppad) != PL_curpad)
PADOFFSET
Perl_pad_add_anon(pTHX_ SV* sv, OPCODE op_type)
{
+ dVAR;
PADOFFSET ix;
- SV* const name = NEWSV(1106, 0);
+ SV* const name = newSV(0);
+ pad_peg("add_anon");
sv_upgrade(name, SVt_PVNV);
sv_setpvn(name, "&", 1);
SvIV_set(name, -1);
void
Perl_pad_check_dup(pTHX_ const char *name, bool is_our, const HV *ourstash)
{
+ dVAR;
SV **svp;
PADOFFSET top, off;
&& (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
&& strEQ(name, SvPVX_const(sv)))
{
- if (is_our && (SvFLAGS(sv) & SVpad_OUR))
+ if (is_our && (SvPAD_OUR(sv)))
break; /* "our" masking "our" */
Perl_warner(aTHX_ packWARN(WARN_MISC),
"\"%s\" variable %s masks earlier declaration in same %s",
- (is_our ? "our" : "my"),
+ (is_our ? "our" : PL_in_my == KEY_my ? "my" : "state"),
name,
(SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
--off;
&& sv != &PL_sv_undef
&& !SvFAKE(sv)
&& (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
- && ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash)
+ && OURSTASH(sv) == ourstash
&& strEQ(name, SvPVX_const(sv)))
{
Perl_warner(aTHX_ packWARN(WARN_MISC),
PADOFFSET
Perl_pad_findmy(pTHX_ const char *name)
{
+ dVAR;
SV *out_sv;
int out_flags;
I32 offset;
const AV *nameav;
SV **name_svp;
- offset = pad_findlex(name, PL_compcv, PL_cop_seqmax, 1,
- Null(SV**), &out_sv, &out_flags);
- if (offset != NOT_IN_PAD)
+ pad_peg("pad_findmy");
+ offset = pad_findlex(name, PL_compcv, PL_cop_seqmax, 1,
+ NULL, &out_sv, &out_flags);
+ if ((PADOFFSET)offset != NOT_IN_PAD)
return offset;
/* look for an our that's being introduced; this allows
const SV * const namesv = name_svp[offset];
if (namesv && namesv != &PL_sv_undef
&& !SvFAKE(namesv)
- && (SvFLAGS(namesv) & SVpad_OUR)
+ && (SvPAD_OUR(namesv))
&& strEQ(SvPVX_const(namesv), name)
&& U_32(SvNVX(namesv)) == PAD_MAX /* min */
)
PADOFFSET
Perl_find_rundefsvoffset(pTHX)
{
+ dVAR;
SV *out_sv;
int out_flags;
return pad_findlex("$_", find_runcv(NULL), PL_curcop->cop_seq, 1,
- Null(SV**), &out_sv, &out_flags);
+ NULL, &out_sv, &out_flags);
}
/*
S_pad_findlex(pTHX_ const char *name, const CV* cv, U32 seq, int warn,
SV** out_capture, SV** out_name_sv, int *out_flags)
{
+ dVAR;
I32 offset, new_offset;
SV *new_capture;
SV **new_capturep;
if (out_capture) {
/* our ? */
- if ((SvFLAGS(*out_name_sv) & SVpad_OUR)) {
- *out_capture = Nullsv;
+ if (SvPAD_OUR(*out_name_sv)) {
+ *out_capture = NULL;
return offset;
}
if (warn && ckWARN(WARN_CLOSURE))
Perl_warner(aTHX_ packWARN(WARN_CLOSURE),
"Variable \"%s\" is not available", name);
- *out_capture = Nullsv;
+ *out_capture = NULL;
}
/* real value */
if (ckWARN(WARN_CLOSURE))
Perl_warner(aTHX_ packWARN(WARN_CLOSURE),
"Variable \"%s\" is not available", name);
- *out_capture = Nullsv;
+ *out_capture = NULL;
}
}
if (!*out_capture) {
if (!CvOUTSIDE(cv))
return NOT_IN_PAD;
-
+
/* out_capture non-null means caller wants us to capture lex; in
* addition we capture ourselves unless it's an ANON/format */
new_capturep = out_capture ? out_capture :
- CvLATE(cv) ? Null(SV**) : &new_capture;
+ CvLATE(cv) ? NULL : &new_capture;
offset = pad_findlex(name, CvOUTSIDE(cv), CvOUTSIDE_SEQ(cv), 1,
new_capturep, out_name_sv, out_flags);
- if (offset == NOT_IN_PAD)
+ if ((PADOFFSET)offset == NOT_IN_PAD)
return NOT_IN_PAD;
-
+
/* found in an outer CV. Add appropriate fake entry to this pad */
/* don't add new fake entries (via eval) to CVs that we have already
new_offset = pad_add_name(
SvPVX_const(*out_name_sv),
- (SvFLAGS(*out_name_sv) & SVpad_TYPED)
- ? SvSTASH(*out_name_sv) : Nullhv,
- (SvFLAGS(*out_name_sv) & SVpad_OUR)
- ? GvSTASH(*out_name_sv) : Nullhv,
- 1 /* fake */
+ SvPAD_TYPED(*out_name_sv)
+ ? SvSTASH(*out_name_sv) : NULL,
+ OURSTASH(*out_name_sv),
+ 1, /* fake */
+ 0 /* not a state variable */
);
new_namesv = AvARRAY(PL_comppad_name)[new_offset];
SvIV_set(new_namesv, *out_flags);
SvNV_set(new_namesv, (NV)0);
- if (SvFLAGS(new_namesv) & SVpad_OUR) {
- /* do nothing */
+ if (SvPAD_OUR(new_namesv)) {
+ NOOP; /* do nothing */
}
else if (CvLATE(cv)) {
/* delayed creation - just note the offset within parent pad */
PL_comppad_name = ocomppad_name;
PL_comppad = ocomppad;
- PL_curpad = ocomppad ? AvARRAY(ocomppad) : Null(SV **);
+ PL_curpad = ocomppad ? AvARRAY(ocomppad) : NULL;
}
return new_offset;
}
SV *
Perl_pad_sv(pTHX_ PADOFFSET po)
{
+ dVAR;
ASSERT_CURPAD_ACTIVE("pad_sv");
if (!po)
void
Perl_pad_setsv(pTHX_ PADOFFSET po, SV* sv)
{
+ dVAR;
ASSERT_CURPAD_ACTIVE("pad_setsv");
DEBUG_X(PerlIO_printf(Perl_debug_log,
void
Perl_pad_block_start(pTHX_ int full)
{
+ dVAR;
ASSERT_CURPAD_ACTIVE("pad_block_start");
SAVEI32(PL_comppad_name_floor);
PL_comppad_name_floor = AvFILLp(PL_comppad_name);
U32
Perl_intro_my(pTHX)
{
+ dVAR;
SV **svp;
I32 i;
void
Perl_pad_leavemy(pTHX)
{
+ dVAR;
I32 off;
SV * const * const svp = AvARRAY(PL_comppad_name);
if (sv && sv != &PL_sv_undef
&& !SvFAKE(sv) && ckWARN_d(WARN_INTERNAL))
Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
- "%"SVf" never introduced", sv);
+ "%"SVf" never introduced",
+ (void*)sv);
}
}
/* "Deintroduce" my variables that are leaving with this scope. */
void
Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust)
{
+ dVAR;
ASSERT_CURPAD_LEGAL("pad_swipe");
if (!PL_curpad)
return;
/* if pad tmps aren't shared between ops, then there's no need to
* create a new tmp when an existing op is freed */
#ifdef USE_BROKEN_PAD_RESET
- PL_curpad[po] = NEWSV(1107,0);
+ PL_curpad[po] = newSV(0);
SvPADTMP_on(PL_curpad[po]);
#else
PL_curpad[po] = &PL_sv_undef;
void
Perl_pad_reset(pTHX)
{
+ dVAR;
#ifdef USE_BROKEN_PAD_RESET
if (AvARRAY(PL_comppad) != PL_curpad)
Perl_croak(aTHX_ "panic: pad_reset curpad");
/* extend curpad to match namepad */
if (AvFILLp(PL_comppad_name) < AvFILLp(PL_comppad))
- av_store(PL_comppad_name, AvFILLp(PL_comppad), Nullsv);
+ av_store(PL_comppad_name, AvFILLp(PL_comppad), NULL);
if (type == padtidy_SUBCLONE) {
SV * const * const namep = AvARRAY(PL_comppad_name);
* pad are anonymous subs.
* The rest are created anew during cloning.
*/
- if (!((namesv = namep[ix]) != Nullsv &&
+ if (!((namesv = namep[ix]) != NULL &&
namesv != &PL_sv_undef &&
*SvPVX_const(namesv) == '&'))
{
SvREFCNT_dec(PL_curpad[ix]);
- PL_curpad[ix] = Nullsv;
+ PL_curpad[ix] = NULL;
}
}
}
void
Perl_pad_free(pTHX_ PADOFFSET po)
{
+ dVAR;
ASSERT_CURPAD_LEGAL("pad_free");
if (!PL_curpad)
return;
void
Perl_do_dump_pad(pTHX_ I32 level, PerlIO *file, PADLIST *padlist, int full)
{
+ dVAR;
const AV *pad_name;
const AV *pad;
SV **pname;
for (ix = 1; ix <= AvFILLp(pad_name); ix++) {
const SV *namesv = pname[ix];
if (namesv && namesv == &PL_sv_undef) {
- namesv = Nullsv;
+ namesv = NULL;
}
if (namesv) {
if (SvFAKE(namesv))
STATIC void
S_cv_dump(pTHX_ const CV *cv, const char *title)
{
+ dVAR;
const CV * const outside = CvOUTSIDE(cv);
AV* const padlist = CvPADLIST(cv);
ENTER;
SAVESPTR(PL_compcv);
- cv = PL_compcv = (CV*)NEWSV(1104, 0);
+ cv = PL_compcv = (CV*)newSV(0);
sv_upgrade((SV *)cv, SvTYPE(proto));
CvFLAGS(cv) = CvFLAGS(proto) & ~(CVf_CLONE|CVf_WEAKOUTSIDE);
CvCLONED_on(cv);
#ifdef USE_ITHREADS
- CvFILE(cv) = CvXSUB(proto) ? CvFILE(proto)
- : savepv(CvFILE(proto));
+ CvFILE(cv) = CvISXSUB(proto) ? CvFILE(proto)
+ : savepv(CvFILE(proto));
#else
CvFILE(cv) = CvFILE(proto);
#endif
CvROOT(cv) = OpREFCNT_inc(CvROOT(proto));
OP_REFCNT_UNLOCK;
CvSTART(cv) = CvSTART(proto);
- CvOUTSIDE(cv) = (CV*)SvREFCNT_inc(outside);
+ CvOUTSIDE(cv) = (CV*)SvREFCNT_inc_simple(outside);
CvOUTSIDE_SEQ(cv) = CvOUTSIDE_SEQ(proto);
if (SvPOK(proto))
outpad = AvARRAY(AvARRAY(CvPADLIST(outside))[depth]);
for (ix = fpad; ix > 0; ix--) {
- SV* const namesv = (ix <= fname) ? pname[ix] : Nullsv;
- SV *sv = Nullsv;
+ SV* const namesv = (ix <= fname) ? pname[ix] : NULL;
+ SV *sv = NULL;
if (namesv && namesv != &PL_sv_undef) { /* lexical */
if (SvFAKE(namesv)) { /* lexical from outside? */
sv = outpad[(I32)SvNVX(namesv)];
if (ckWARN(WARN_CLOSURE))
Perl_warner(aTHX_ packWARN(WARN_CLOSURE),
"Variable \"%s\" is not available", SvPVX_const(namesv));
- sv = Nullsv;
+ sv = NULL;
}
else {
assert(!SvPADSTALE(sv));
- sv = SvREFCNT_inc(sv);
+ SvREFCNT_inc_simple_void_NN(sv);
}
}
if (!sv) {
else if (sigil == '%')
sv = (SV*)newHV();
else
- sv = NEWSV(0, 0);
+ sv = newSV(0);
SvPADMY_on(sv);
}
}
else if (IS_PADGV(ppad[ix]) || IS_PADCONST(ppad[ix])) {
- sv = SvREFCNT_inc(ppad[ix]);
+ sv = SvREFCNT_inc_NN(ppad[ix]);
}
else {
- sv = NEWSV(0, 0);
+ sv = newSV(0);
SvPADTMP_on(sv);
}
PL_curpad[ix] = sv;
SV* const const_sv = op_const_sv(CvSTART(cv), cv);
if (const_sv) {
SvREFCNT_dec(cv);
- cv = newCONSTSUB(CvSTASH(proto), Nullch, const_sv);
+ cv = newCONSTSUB(CvSTASH(proto), NULL, const_sv);
}
else {
CvCONST_off(cv);
void
Perl_pad_fixup_inner_anons(pTHX_ PADLIST *padlist, CV *old_cv, CV *new_cv)
{
+ dVAR;
I32 ix;
AV * const comppad_name = (AV*)AvARRAY(padlist)[0];
AV * const comppad = (AV*)AvARRAY(padlist)[1];
SV ** const namepad = AvARRAY(comppad_name);
SV ** const curpad = AvARRAY(comppad);
+ PERL_UNUSED_ARG(old_cv);
+
for (ix = AvFILLp(comppad_name); ix > 0; ix--) {
const SV * const namesv = namepad[ix];
if (namesv && namesv != &PL_sv_undef
void
Perl_pad_push(pTHX_ PADLIST *padlist, int depth)
{
- if (depth <= AvFILLp(padlist))
- return;
-
- {
+ dVAR;
+ if (depth > AvFILLp(padlist)) {
SV** const svp = AvARRAY(padlist);
AV* const newpad = newAV();
SV** const oldpad = AvARRAY(svp[depth-1]);
else if (sigil == '%')
sv = (SV*)newHV();
else
- sv = NEWSV(0, 0);
+ sv = newSV(0);
av_store(newpad, ix, sv);
SvPADMY_on(sv);
}
}
else if (IS_PADGV(oldpad[ix]) || IS_PADCONST(oldpad[ix])) {
- av_store(newpad, ix, SvREFCNT_inc(oldpad[ix]));
+ av_store(newpad, ix, SvREFCNT_inc_NN(oldpad[ix]));
}
else {
/* save temporaries on recursion? */
- SV * const sv = NEWSV(0, 0);
+ SV * const sv = newSV(0);
av_store(newpad, ix, sv);
SvPADTMP_on(sv);
}
HV *
Perl_pad_compname_type(pTHX_ const PADOFFSET po)
{
+ dVAR;
SV* const * const av = av_fetch(PL_comppad_name, po, FALSE);
- if ( SvFLAGS(*av) & SVpad_TYPED ) {
+ if ( SvPAD_TYPED(*av) ) {
return SvSTASH(*av);
}
- return Nullhv;
+ return NULL;
}
/*