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_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);
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);
}
}
register char* str;
I32 i;
/* Localise the effects of the TAINT_NOT inside the loop. */
- const bool was = PL_tainted;
+ bool was = PL_tainted;
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;
*(char**)ptr = str;
}
break;
+ case SAVEt_GVSV: /* scalar slot in GV */
+ value = MUTABLE_SV(SSPOPPTR);
+ gv = MUTABLE_GV(SSPOPPTR);
+ ptr = &GvSV(gv);
+ goto restore_svp;
case SAVEt_GENERIC_SVREF: /* generic sv */
value = MUTABLE_SV(SSPOPPTR);
ptr = SSPOPPTR;
+ restore_svp:
sv = *(SV**)ptr;
*(SV**)ptr = value;
SvREFCNT_dec(sv);
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 (ptr == &PL_tainted) {
+ /* 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;
+ }
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));
if (SvTHINKFIRST(sv))
sv_force_normal_flags(sv, SV_IMMEDIATE_UNREF);
+ if (SvTYPE(sv) == SVt_PVHV)
+ Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
if (SvMAGICAL(sv))
+ sv_unmagic(sv, PERL_MAGIC_backref),
mg_free(sv);
switch (SvTYPE(sv)) {
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);
+ 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;
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;
+ SvFLAGS(*(SV**)ptr) |= (SVs_PADMY|SVs_PADSTALE);
}
break;
case SAVEt_DELETE:
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);
}
}
* 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:
*/