/* 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!!! */
if (empty) {
GP *gp = Perl_newGP(aTHX_ gv);
-
- if (GvCVu(gv))
- mro_method_changed_in(GvSTASH(gv)); /* taking a method out of circulation ("local")*/
+ HV * const stash = GvSTASH(gv);
+ bool isa_changed = 0;
+
+ if (stash && HvENAME(stash)) {
+ if (GvNAMELEN(gv) == 3 && strnEQ(GvNAME(gv), "ISA", 3))
+ isa_changed = TRUE;
+ else if (GvCVu(gv))
+ /* taking a method out of circulation ("local")*/
+ mro_method_changed_in(stash);
+ }
if (GvIOp(gv) && (IoFLAGS(GvIOp(gv)) & IOf_ARGV)) {
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_set(gv,gp);
+ if (isa_changed) mro_isa_changed_in(stash);
}
else {
gp_ref(GvGP(gv));
}
void
-Perl_save_item(pTHX_ register SV *item)
+Perl_save_item(pTHX_ SV *item)
{
dVAR;
SV * const sv = newSVsv(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
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;
char* str;
I32 i;
/* Localise the effects of the TAINT_NOT inside the loop. */
- bool was = PL_tainted;
+ bool was = TAINT_get;
if (base < -1)
Perl_croak(aTHX_ "panic: corrupt saved stack index %ld", (long) base);
case SAVEt_BOOL: /* bool reference */
ptr = SSPOPPTR;
*(bool*)ptr = cBOOL(uv >> 8);
-
- if (ptr == &PL_tainted) {
+#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
* such as I32 */
was = *(bool*)ptr;
}
+#endif
break;
case SAVEt_I32_SMALL:
ptr = SSPOPPTR;
gv = MUTABLE_GV(SSPOPPTR);
gp_free(gv);
GvGP_set(gv, (GP*)ptr);
- /* putting a method back into circulation ("local")*/
- if (GvCVu(gv) && (hv=GvSTASH(gv)) && HvENAME_get(hv))
- mro_method_changed_in(hv);
+ if ((hv=GvSTASH(gv)) && HvENAME_get(hv)) {
+ if (GvNAMELEN(gv) == 3 && strnEQ(GvNAME(gv), "ISA", 3))
+ mro_isa_changed_in(hv);
+ else if (GvCVu(gv))
+ /* putting a method back into circulation ("local")*/
+ gv_method_changed(gv);
+ }
SvREFCNT_dec(gv);
break;
case SAVEt_FREESV:
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
- |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: *(SV**)ptr = MUTABLE_SV(newAV()); break;
- case SVt_PVHV: *(SV**)ptr = MUTABLE_SV(newHV()); break;
- case SVt_PVCV:
- {
- SV ** const svp = (SV **)ptr;
- MAGIC *mg = SvMAGIC(sv);
- MAGIC **tomg = &SvMAGIC(sv);
-
- /* Create a stub */
- *svp = newSV_type(SVt_PVCV);
-
- /* Share name */
- assert(CvNAMED(sv));
- CvNAME_HEK_set(*svp,
- share_hek_hek(CvNAME_HEK((CV *)sv)));
-
- /* Steal magic */
- while (mg) {
- if (mg->mg_type == PERL_MAGIC_proto) break;
- mg = *(tomg = &mg->mg_moremagic);
- }
- assert(mg);
- *tomg = mg->mg_moremagic;
- mg->mg_moremagic = SvMAGIC(*svp);
- SvMAGIC(*svp) = mg;
- mg_magical(*svp);
- mg_magical(sv);
- 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) |= (SVs_PADMY|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_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: