/* XXX should tmps_floor live in cxstack? */
const I32 myfloor = PL_tmps_floor;
while (PL_tmps_ix > myfloor) { /* clean up after last statement */
- SV* const sv = PL_tmps_stack[PL_tmps_ix];
- PL_tmps_stack[PL_tmps_ix--] = NULL;
+ SV* const sv = PL_tmps_stack[PL_tmps_ix--];
+#ifdef PERL_POISON
+ PoisonWith(PL_tmps_stack + PL_tmps_ix + 1, 1, SV *, 0xAB);
+#endif
if (sv && sv != &PL_sv_undef) {
SvTEMP_off(sv);
SvREFCNT_dec(sv); /* note, can modify tmps_ix!!! */
{
dVAR;
SV * osv;
- register SV *sv;
+ SV *sv;
PERL_ARGS_ASSERT_SAVE_SCALAR_AT;
osv = *sptr;
sv = (flags & SAVEf_KEEPOLDELEM) ? osv : (*sptr = newSV(0));
- if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv) && SvTYPE(osv) != SVt_PVGV) {
+ if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv)) {
if (SvGMAGICAL(osv)) {
- const bool oldtainted = PL_tainted;
SvFLAGS(osv) |= (SvFLAGS(osv) &
(SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
- PL_tainted = oldtainted;
}
if (!(flags & SAVEf_KEEPOLDELEM))
- mg_localize(osv, sv, (flags & SAVEf_SETMAGIC) != 0);
+ mg_localize(osv, sv, cBOOL(flags & SAVEf_SETMAGIC));
}
return sv;
PERL_ARGS_ASSERT_SAVE_GP;
- SSCHECK(4);
- SSPUSHINT(SvFAKE(gv));
- SSPUSHPTR(GvGP(gv));
- SSPUSHPTR(SvREFCNT_inc(gv));
- SSPUSHUV(SAVEt_GP);
-
- /* Don't let the localized GV coerce into non-glob, otherwise we would
- * not be able to restore GP upon leave from context if that happened */
- SvFAKE_off(gv);
+ save_pushptrptr(SvREFCNT_inc(gv), GvGP(gv), SAVEt_GP);
if (empty) {
GP *gp = Perl_newGP(aTHX_ gv);
gp->gp_io = newIO();
IoFLAGS(gp->gp_io) |= IOf_ARGV|IOf_START;
}
-#ifdef PERL_DONT_CREATE_GVSV
- if (gv == PL_errgv) {
- /* We could scatter this logic everywhere by changing the
- definition of ERRSV from GvSV() to GvSVn(), but it seems more
- efficient to do this check once here. */
- gp->gp_sv = newSV(0);
- }
-#endif
- GvGP(gv) = gp;
+ GvGP_set(gv,gp);
}
else {
gp_ref(GvGP(gv));
if (!AvREAL(oav) && AvREIFY(oav))
av_reify(oav);
- save_pushptrptr(gv, oav, SAVEt_AV);
+ save_pushptrptr(SvREFCNT_inc_simple_NN(gv), oav, SAVEt_AV);
GvAV(gv) = NULL;
av = GvAVn(gv);
PERL_ARGS_ASSERT_SAVE_HASH;
- save_pushptrptr(gv, (ohv = GvHVn(gv)), SAVEt_HV);
+ save_pushptrptr(
+ SvREFCNT_inc_simple_NN(gv), (ohv = GvHVn(gv)), SAVEt_HV
+ );
GvHV(gv) = NULL;
hv = GvHVn(gv);
}
void
-Perl_save_item(pTHX_ register SV *item)
+Perl_save_item(pTHX_ SV *item)
{
dVAR;
- register SV * const sv = newSVsv(item);
+ SV * const sv = newSVsv(item);
PERL_ARGS_ASSERT_SAVE_ITEM;
PERL_ARGS_ASSERT_SAVE_CLEARSV;
ASSERT_CURPAD_ACTIVE("save_clearsv");
+ SvPADSTALE_off(*svp); /* mark lexical as active */
if ((offset_shifted >> SAVE_TIGHT_SHIFT) != offset)
Perl_croak(aTHX_ "panic: pad offset %"UVuf" out of range (%p-%p)",
offset, svp, PL_curpad);
SSCHECK(1);
SSPUSHUV(offset_shifted | SAVEt_CLEARSV);
- SvPADSTALE_off(*svp); /* mark lexical as active */
}
void
Perl_save_hints(pTHX)
{
dVAR;
- if (PL_compiling.cop_hints_hash) {
- HINTS_REFCNT_LOCK;
- PL_compiling.cop_hints_hash->refcounted_he_refcnt++;
- HINTS_REFCNT_UNLOCK;
- }
+ COPHH *save_cophh = cophh_copy(CopHINTHASH_get(&PL_compiling));
if (PL_hints & HINT_LOCALIZE_HH) {
- save_pushptri32ptr(GvHV(PL_hintgv), PL_hints,
- PL_compiling.cop_hints_hash, SAVEt_HINTS);
- GvHV(PL_hintgv) = Perl_hv_copy_hints_hv(aTHX_ GvHV(PL_hintgv));
+ HV *oldhh = GvHV(PL_hintgv);
+ save_pushptri32ptr(oldhh, PL_hints, save_cophh, SAVEt_HINTS);
+ GvHV(PL_hintgv) = NULL; /* in case copying dies */
+ GvHV(PL_hintgv) = hv_copy_hints_hv(oldhh);
} else {
- save_pushi32ptr(PL_hints, PL_compiling.cop_hints_hash, SAVEt_HINTS);
+ save_pushi32ptr(PL_hints, save_cophh, SAVEt_HINTS);
}
}
SvGETMAGIC(*sptr);
save_pushptri32ptr(SvREFCNT_inc_simple(av), idx, SvREFCNT_inc(*sptr),
SAVEt_AELEM);
- /* if it gets reified later, the restore will have the wrong refcnt */
+ /* The array needs to hold a reference count on its new element, so it
+ must be AvREAL. */
if (!AvREAL(av) && AvREIFY(av))
- SvREFCNT_inc_void(*sptr);
+ av_reify(av);
save_scalar_at(sptr, flags); /* XXX - FIXME - see #60360 */
if (flags & SAVEf_KEEPOLDELEM)
return;
Perl_save_alloc(pTHX_ I32 size, I32 pad)
{
dVAR;
- register const I32 start = pad + ((char*)&PL_savestack[PL_savestack_ix]
- - (char*)PL_savestack);
+ const I32 start = pad + ((char*)&PL_savestack[PL_savestack_ix]
+ - (char*)PL_savestack);
const UV elems = 1 + ((size + pad - 1) / sizeof(*PL_savestack));
const UV elems_shifted = elems << SAVE_TIGHT_SHIFT;
Perl_leave_scope(pTHX_ I32 base)
{
dVAR;
- register SV *sv;
- register SV *value;
- register GV *gv;
- register AV *av;
- register HV *hv;
+ SV *sv;
+ SV *value;
+ GV *gv;
+ AV *av;
+ HV *hv;
void* ptr;
- register char* str;
+ char* str;
I32 i;
/* Localise the effects of the TAINT_NOT inside the loop. */
- const bool was = PL_tainted;
+ bool was = TAINT_get;
if (base < -1)
- Perl_croak(aTHX_ "panic: corrupt saved stack index");
+ Perl_croak(aTHX_ "panic: corrupt saved stack index %ld", (long) base);
DEBUG_l(Perl_deb(aTHX_ "savestack: releasing items %ld -> %ld\n",
(long)PL_savestack_ix, (long)base));
while (PL_savestack_ix > base) {
SvSETMAGIC(value);
PL_localizing = 0;
SvREFCNT_dec(value);
- if (av) /* actually an av, hv or gv */
- SvREFCNT_dec(av);
+ SvREFCNT_dec(av); /* av may actually be an AV, HV or GV */
break;
case SAVEt_GENERIC_PVREF: /* generic pv */
ptr = SSPOPPTR;
SvSETMAGIC(MUTABLE_SV(av));
PL_localizing = 0;
}
+ SvREFCNT_dec(gv);
break;
case SAVEt_HV: /* hash reference */
hv = MUTABLE_HV(SSPOPPTR);
SvSETMAGIC(MUTABLE_SV(hv));
PL_localizing = 0;
}
+ SvREFCNT_dec(gv);
break;
case SAVEt_INT_SMALL:
ptr = SSPOPPTR;
case SAVEt_BOOL: /* bool reference */
ptr = SSPOPPTR;
*(bool*)ptr = cBOOL(uv >> 8);
+#if !NO_TAINT_SUPPORT
+ if (ptr == &(TAINT_get)) {
+ /* If we don't update <was>, to reflect what was saved on the
+ * stack for PL_tainted, then we will overwrite this attempt to
+ * restore it when we exit this routine. Note that this won't
+ * work if this value was saved in a wider-than necessary type,
+ * such as I32 */
+ was = *(bool*)ptr;
+ }
+#endif
break;
case SAVEt_I32_SMALL:
ptr = SSPOPPTR;
*(AV**)ptr = MUTABLE_AV(SSPOPPTR);
break;
case SAVEt_GP: /* scalar reference */
+ ptr = SSPOPPTR;
gv = MUTABLE_GV(SSPOPPTR);
gp_free(gv);
- GvGP(gv) = (GP*)SSPOPPTR;
- if (SSPOPINT)
- SvFAKE_on(gv);
+ GvGP_set(gv, (GP*)ptr);
/* putting a method back into circulation ("local")*/
- if (GvCVu(gv) && (hv=GvSTASH(gv)) && HvNAME_get(hv))
+ if (GvCVu(gv) && (hv=GvSTASH(gv)) && HvENAME_get(hv))
mro_method_changed_in(hv);
SvREFCNT_dec(gv);
break;
ptr = SSPOPPTR;
SvREFCNT_dec(MUTABLE_SV(ptr));
break;
+ case SAVEt_FREECOPHH:
+ ptr = SSPOPPTR;
+ cophh_free((COPHH *)ptr);
+ break;
case SAVEt_MORTALIZESV:
ptr = SSPOPPTR;
sv_2mortal(MUTABLE_SV(ptr));
break;
case SAVEt_FREEOP:
ptr = SSPOPPTR;
- ASSERT_CURPAD_LEGAL("SAVEt_FREEOP"); /* XXX DAPM tmp */
+ ASSERT_CURPAD_LEGAL("SAVEt_FREEOP");
op_free((OP*)ptr);
break;
case SAVEt_FREEPV:
ptr = SSPOPPTR;
Safefree(ptr);
break;
- case SAVEt_CLEARSV:
- ptr = (void*)&PL_curpad[uv >> SAVE_TIGHT_SHIFT];
- sv = *(SV**)ptr;
- DEBUG_Xv(PerlIO_printf(Perl_debug_log,
- "Pad 0x%"UVxf"[0x%"UVxf"] clearsv: %ld sv=0x%"UVxf"<%"IVdf"> %s\n",
- PTR2UV(PL_comppad), PTR2UV(PL_curpad),
- (long)((SV **)ptr-PL_curpad), PTR2UV(sv), (IV)SvREFCNT(sv),
- (SvREFCNT(sv) <= 1 && !SvOBJECT(sv)) ? "clear" : "abandon"
- ));
-
- /* Can clear pad variable in place? */
- if (SvREFCNT(sv) <= 1 && !SvOBJECT(sv)) {
- /*
- * if a my variable that was made readonly is going out of
- * scope, we want to remove the readonlyness so that it can
- * go out of scope quietly
- */
- if (SvPADMY(sv) && !SvFAKE(sv))
- SvREADONLY_off(sv);
-
- if (SvTHINKFIRST(sv))
- sv_force_normal_flags(sv, SV_IMMEDIATE_UNREF);
- if (SvMAGICAL(sv))
- mg_free(sv);
-
- switch (SvTYPE(sv)) {
- case SVt_NULL:
- break;
- case SVt_PVAV:
- av_clear(MUTABLE_AV(sv));
- break;
- case SVt_PVHV:
- hv_clear(MUTABLE_HV(sv));
- break;
- case SVt_PVCV:
- Perl_croak(aTHX_ "panic: leave_scope pad code");
- default:
- SvOK_off(sv);
- break;
- }
- SvPADSTALE_on(sv); /* mark as no longer live */
- }
- else { /* Someone has a claim on this, so abandon it. */
- const U32 padflags = SvFLAGS(sv) & (SVs_PADMY|SVs_PADTMP);
- switch (SvTYPE(sv)) { /* Console ourselves with a new value */
- case SVt_PVAV: *(SV**)ptr = MUTABLE_SV(newAV()); break;
- case SVt_PVHV: *(SV**)ptr = MUTABLE_SV(newHV()); break;
- default: *(SV**)ptr = newSV(0); break;
- }
- SvREFCNT_dec(sv); /* Cast current value to the winds. */
- /* preserve pad nature, but also mark as not live
- * for any closure capturing */
- SvFLAGS(*(SV**)ptr) |= padflags | SVs_PADSTALE;
- }
+ {
+ SV **svp;
+ case SAVEt_CLEARPADRANGE:
+ i = (I32)((uv >> SAVE_TIGHT_SHIFT) & OPpPADRANGE_COUNTMASK);
+ svp = &PL_curpad[uv >>
+ (OPpPADRANGE_COUNTSHIFT + SAVE_TIGHT_SHIFT)] + i - 1;
+ goto clearsv;
+ case SAVEt_CLEARSV:
+ svp = &PL_curpad[uv >> SAVE_TIGHT_SHIFT];
+ i = 1;
+ clearsv:
+ for (; i; i--, svp--) {
+ sv = *svp;
+
+ DEBUG_Xv(PerlIO_printf(Perl_debug_log,
+ "Pad 0x%"UVxf"[0x%"UVxf"] clearsv: %ld sv=0x%"UVxf"<%"IVdf"> %s\n",
+ PTR2UV(PL_comppad), PTR2UV(PL_curpad),
+ (long)(svp-PL_curpad), PTR2UV(sv), (IV)SvREFCNT(sv),
+ (SvREFCNT(sv) <= 1 && !SvOBJECT(sv)) ? "clear" : "abandon"
+ ));
+
+ /* Can clear pad variable in place? */
+ if (SvREFCNT(sv) <= 1 && !SvOBJECT(sv)) {
+ /*
+ * if a my variable that was made readonly is going out of
+ * scope, we want to remove the readonlyness so that it can
+ * go out of scope quietly
+ */
+ if (SvPADMY(sv) && !SvFAKE(sv))
+ SvREADONLY_off(sv);
+
+ if (SvTHINKFIRST(sv))
+ sv_force_normal_flags(sv, SV_IMMEDIATE_UNREF
+ |SV_COW_DROP_PV);
+ if (SvTYPE(sv) == SVt_PVHV)
+ Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
+ if (SvMAGICAL(sv))
+ {
+ sv_unmagic(sv, PERL_MAGIC_backref);
+ if (SvTYPE(sv) != SVt_PVCV)
+ mg_free(sv);
+ }
+
+ switch (SvTYPE(sv)) {
+ case SVt_NULL:
+ break;
+ case SVt_PVAV:
+ av_clear(MUTABLE_AV(sv));
+ break;
+ case SVt_PVHV:
+ hv_clear(MUTABLE_HV(sv));
+ break;
+ case SVt_PVCV:
+ {
+ HEK * const hek = CvNAME_HEK((CV *)sv);
+ assert(hek);
+ share_hek_hek(hek);
+ cv_undef((CV *)sv);
+ CvNAME_HEK_set(sv, hek);
+ break;
+ }
+ default:
+ SvOK_off(sv);
+ break;
+ }
+ SvPADSTALE_on(sv); /* mark as no longer live */
+ }
+ else { /* Someone has a claim on this, so abandon it. */
+ assert( SvFLAGS(sv) & SVs_PADMY);
+ assert(!(SvFLAGS(sv) & SVs_PADTMP));
+ switch (SvTYPE(sv)) { /* Console ourselves with a new value */
+ case SVt_PVAV: *svp = MUTABLE_SV(newAV()); break;
+ case SVt_PVHV: *svp = MUTABLE_SV(newHV()); break;
+ case SVt_PVCV:
+ {
+ /* Create a stub */
+ *svp = newSV_type(SVt_PVCV);
+
+ /* Share name */
+ assert(CvNAMED(sv));
+ CvNAME_HEK_set(*svp,
+ share_hek_hek(CvNAME_HEK((CV *)sv)));
+ break;
+ }
+ default: *svp = newSV(0); break;
+ }
+ SvREFCNT_dec(sv); /* Cast current value to the winds. */
+ /* preserve pad nature, but also mark as not live
+ * for any closure capturing */
+ SvFLAGS(*svp) |= (SVs_PADMY|SVs_PADSTALE);
+ }
+ }
break;
+ }
case SAVEt_DELETE:
ptr = SSPOPPTR;
hv = MUTABLE_HV(ptr);
PL_op = (OP*)SSPOPPTR;
break;
case SAVEt_HINTS:
- if ((PL_hints & HINT_LOCALIZE_HH) && GvHV(PL_hintgv)) {
- SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
+ if ((PL_hints & HINT_LOCALIZE_HH)) {
+ while (GvHV(PL_hintgv)) {
+ HV *hv = GvHV(PL_hintgv);
GvHV(PL_hintgv) = NULL;
+ SvREFCNT_dec(MUTABLE_SV(hv));
+ }
}
- Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
- PL_compiling.cop_hints_hash = (struct refcounted_he *) SSPOPPTR;
+ cophh_free(CopHINTHASH_get(&PL_compiling));
+ CopHINTHASH_set(&PL_compiling, (COPHH*)SSPOPPTR);
*(I32*)&PL_hints = (I32)SSPOPINT;
if (PL_hints & HINT_LOCALIZE_HH) {
SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
GvHV(PL_hintgv) = MUTABLE_HV(SSPOPPTR);
- assert(GvHV(PL_hintgv));
- } else if (!GvHV(PL_hintgv)) {
- /* Need to add a new one manually, else gv_fetchpv() can
- add one in this code:
-
- if (SvTYPE(gv) == SVt_PVGV) {
- if (add) {
- GvMULTI_on(gv);
- gv_init_sv(gv, sv_type);
- if (*name=='!' && sv_type == SVt_PVHV && len==1)
- require_errno(gv);
- }
- return gv;
- }
-
- and it won't have the magic set. */
-
+ }
+ if (!GvHV(PL_hintgv)) {
+ /* Need to add a new one manually, else rv2hv can
+ add one via GvHVn and it won't have the magic set. */
HV *const hv = newHV();
hv_magic(hv, NULL, PERL_MAGIC_hints);
GvHV(PL_hintgv) = hv;
ptr = SSPOPPTR;
(*SSPOPDPTR)(ptr);
break;
- case SAVEt_COP_ARYBASE:
- ptr = SSPOPPTR;
- i = SSPOPINT;
- CopARYBASE_set((COP *)ptr, i);
- break;
case SAVEt_COMPILE_WARNINGS:
ptr = SSPOPPTR;
- SAVESTACK_ALLOC_FOR_RE_SAVE_STATE);
PL_savestack_ix -= SAVESTACK_ALLOC_FOR_RE_SAVE_STATE;
- if (PL_reg_start_tmp != state->re_state_reg_start_tmp) {
- Safefree(PL_reg_start_tmp);
- }
if (PL_reg_poscache != state->re_state_reg_poscache) {
Safefree(PL_reg_poscache);
}
parser_free((yy_parser *) ptr);
break;
default:
- Perl_croak(aTHX_ "panic: leave_scope inconsistency");
+ Perl_croak(aTHX_ "panic: leave_scope inconsistency %u", type);
}
}
- PL_tainted = was;
+ TAINT_set(was);
PERL_ASYNC_CHECK();
}
#ifdef DEBUGGING
PerlIO_printf(Perl_debug_log, "CX %ld = %s\n", (long)(cx - cxstack), PL_block_type[CxTYPE(cx)]);
if (CxTYPE(cx) != CXt_SUBST) {
+ const char *gimme_text;
PerlIO_printf(Perl_debug_log, "BLK_OLDSP = %ld\n", (long)cx->blk_oldsp);
PerlIO_printf(Perl_debug_log, "BLK_OLDCOP = 0x%"UVxf"\n",
PTR2UV(cx->blk_oldcop));
PerlIO_printf(Perl_debug_log, "BLK_OLDSCOPESP = %ld\n", (long)cx->blk_oldscopesp);
PerlIO_printf(Perl_debug_log, "BLK_OLDPM = 0x%"UVxf"\n",
PTR2UV(cx->blk_oldpm));
- PerlIO_printf(Perl_debug_log, "BLK_GIMME = %s\n", cx->blk_gimme ? "LIST" : "SCALAR");
+ switch (cx->blk_gimme) {
+ case G_VOID:
+ gimme_text = "VOID";
+ break;
+ case G_SCALAR:
+ gimme_text = "SCALAR";
+ break;
+ case G_ARRAY:
+ gimme_text = "LIST";
+ break;
+ default:
+ gimme_text = "UNKNOWN";
+ break;
+ }
+ PerlIO_printf(Perl_debug_log, "BLK_GIMME = %s\n", gimme_text);
}
switch (CxTYPE(cx)) {
case CXt_NULL:
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
* End:
*
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
*/