X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=scope.c;h=6ee1254b60cbf06f4dabc69af0b40961d1a175b1;hb=2c09a866c8998f757d628460ed585e1cb8011792;hp=9f535496504627e097aa5799b3754a937a28e47a;hpb=da8315f8f4d9d4df8cbebe108ef0ddb4795856d7;p=p5sagit%2Fp5-mst-13.2.git diff --git a/scope.c b/scope.c index 9f53549..6ee1254 100644 --- a/scope.c +++ b/scope.c @@ -91,7 +91,13 @@ Perl_push_scope(pTHX) if (PL_scopestack_ix == PL_scopestack_max) { PL_scopestack_max = GROW(PL_scopestack_max); Renew(PL_scopestack, PL_scopestack_max, I32); +#ifdef DEBUGGING + Renew(PL_scopestack_name, PL_scopestack_max, const char*); +#endif } +#ifdef DEBUGGING + PL_scopestack_name[PL_scopestack_ix] = "unknown"; +#endif PL_scopestack[PL_scopestack_ix++] = PL_savestack_ix; } @@ -167,11 +173,14 @@ STATIC SV * S_save_scalar_at(pTHX_ SV **sptr, const U32 flags) { dVAR; - SV * const osv = *sptr; - register SV * const sv = *sptr = newSV(0); + SV * osv; + register 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 (SvGMAGICAL(osv)) { const bool oldtainted = PL_tainted; @@ -179,8 +188,10 @@ S_save_scalar_at(pTHX_ SV **sptr, const U32 flags) (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; PL_tainted = oldtainted; } - mg_localize(osv, sv, (flags & SAVEf_SETMAGIC) != 0); + if (!(flags & SAVEf_KEEPOLDELEM)) + mg_localize(osv, sv, (flags & SAVEf_SETMAGIC) != 0); } + return sv; } @@ -505,11 +516,33 @@ Perl_save_delete(pTHX_ HV *hv, char *key, I32 klen) PERL_ARGS_ASSERT_SAVE_DELETE; - SSCHECK(4); - SSPUSHINT(klen); - SSPUSHPTR(key); - SSPUSHPTR(SvREFCNT_inc_simple(hv)); - SSPUSHINT(SAVEt_DELETE); + save_pushptri32ptr(key, klen, SvREFCNT_inc_simple(hv), SAVEt_DELETE); +} + +void +Perl_save_hdelete(pTHX_ HV *hv, SV *keysv) +{ + STRLEN len; + I32 klen; + const char *key; + + PERL_ARGS_ASSERT_SAVE_HDELETE; + + key = SvPV_const(keysv, len); + klen = SvUTF8(keysv) ? -(I32)len : (I32)len; + SvREFCNT_inc_simple_void_NN(hv); + save_pushptri32ptr(savepvn(key, len), klen, hv, SAVEt_DELETE); +} + +void +Perl_save_adelete(pTHX_ AV *av, I32 key) +{ + dVAR; + + PERL_ARGS_ASSERT_SAVE_ADELETE; + + SvREFCNT_inc_void(av); + save_pushi32ptr(key, av, SAVEt_ADELETE); } void @@ -544,40 +577,49 @@ Perl_save_hints(pTHX) PL_compiling.cop_hints_hash->refcounted_he_refcnt++; HINTS_REFCNT_UNLOCK; } - SSCHECK(4); if (PL_hints & HINT_LOCALIZE_HH) { - SSPUSHPTR(GvHV(PL_hintgv)); + 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)); + } else { + save_pushi32ptr(PL_hints, PL_compiling.cop_hints_hash, SAVEt_HINTS); } - SSPUSHINT(PL_hints); - SSPUSHPTR(PL_compiling.cop_hints_hash); - SSPUSHINT(SAVEt_HINTS); +} + +static void +S_save_pushptri32ptr(pTHX_ void *const ptr1, const I32 i, void *const ptr2, + const int type) +{ + SSCHECK(4); + SSPUSHPTR(ptr1); + SSPUSHINT(i); + SSPUSHPTR(ptr2); + SSPUSHINT(type); } void -Perl_save_aelem(pTHX_ AV *av, I32 idx, SV **sptr) +Perl_save_aelem_flags(pTHX_ AV *av, I32 idx, SV **sptr, const U32 flags) { dVAR; SV *sv; - PERL_ARGS_ASSERT_SAVE_AELEM; + PERL_ARGS_ASSERT_SAVE_AELEM_FLAGS; SvGETMAGIC(*sptr); - SSCHECK(4); - SSPUSHPTR(SvREFCNT_inc_simple(av)); - SSPUSHINT(idx); - SSPUSHPTR(SvREFCNT_inc(*sptr)); - SSPUSHINT(SAVEt_AELEM); + save_pushptri32ptr(SvREFCNT_inc_simple(av), idx, SvREFCNT_inc(*sptr), + SAVEt_AELEM); /* if it gets reified later, the restore will have the wrong refcnt */ if (!AvREAL(av) && AvREIFY(av)) SvREFCNT_inc_void(*sptr); - save_scalar_at(sptr, SAVEf_SETMAGIC); /* XXX - FIXME - see #60360 */ + save_scalar_at(sptr, flags); /* XXX - FIXME - see #60360 */ + if (flags & SAVEf_KEEPOLDELEM) + return; sv = *sptr; /* If we're localizing a tied array element, this new sv * won't actually be stored in the array - so it won't get * reaped when the localize ends. Ensure it gets reaped by * mortifying it instead. DAPM */ - if (SvTIED_mg(sv, PERL_MAGIC_tiedelem)) + if (SvTIED_mg((const SV *)av, PERL_MAGIC_tied)) sv_2mortal(sv); } @@ -596,12 +638,14 @@ Perl_save_helem_flags(pTHX_ HV *hv, SV *key, SV **sptr, const U32 flags) SSPUSHPTR(SvREFCNT_inc(*sptr)); SSPUSHINT(SAVEt_HELEM); save_scalar_at(sptr, flags); + if (flags & SAVEf_KEEPOLDELEM) + return; sv = *sptr; /* If we're localizing a tied hash element, this new sv * won't actually be stored in the hash - so it won't get * reaped when the localize ends. Ensure it gets reaped by * mortifying it instead. DAPM */ - if (SvTIED_mg(sv, PERL_MAGIC_tiedelem)) + if (SvTIED_mg((const SV *)hv, PERL_MAGIC_tied)) sv_2mortal(sv); } @@ -645,9 +689,13 @@ Perl_leave_scope(pTHX_ I32 base) void* ptr; register char* str; I32 i; + /* Localise the effects of the TAINT_NOT inside the loop. */ + const bool was = PL_tainted; if (base < -1) Perl_croak(aTHX_ "panic: corrupt saved stack index"); + DEBUG_l(Perl_deb(aTHX_ "savestack: releasing items %ld -> %ld\n", + (long)PL_savestack_ix, (long)base)); while (PL_savestack_ix > base) { TAINT_NOT; @@ -707,9 +755,7 @@ Perl_leave_scope(pTHX_ I32 base) case SAVEt_AV: /* array reference */ av = MUTABLE_AV(SSPOPPTR); gv = MUTABLE_GV(SSPOPPTR); - if (GvAV(gv)) { - SvREFCNT_dec(GvAV(gv)); - } + SvREFCNT_dec(GvAV(gv)); GvAV(gv) = av; if (SvMAGICAL(av)) { PL_localizing = 2; @@ -720,9 +766,7 @@ Perl_leave_scope(pTHX_ I32 base) case SAVEt_HV: /* hash reference */ hv = MUTABLE_HV(SSPOPPTR); gv = MUTABLE_GV(SSPOPPTR); - if (GvHV(gv)) { - SvREFCNT_dec(GvHV(gv)); - } + SvREFCNT_dec(GvHV(gv)); GvHV(gv) = hv; if (SvMAGICAL(hv)) { PL_localizing = 2; @@ -736,7 +780,7 @@ Perl_leave_scope(pTHX_ I32 base) break; case SAVEt_BOOL: /* bool reference */ ptr = SSPOPPTR; - *(bool*)ptr = (bool)SSPOPBOOL; + *(bool*)ptr = cBOOL(SSPOPBOOL); break; case SAVEt_I32: /* I32 reference */ ptr = SSPOPPTR; @@ -853,11 +897,19 @@ Perl_leave_scope(pTHX_ I32 base) case SAVEt_DELETE: ptr = SSPOPPTR; hv = MUTABLE_HV(ptr); + i = SSPOPINT; ptr = SSPOPPTR; - (void)hv_delete(hv, (char*)ptr, (I32)SSPOPINT, G_DISCARD); + (void)hv_delete(hv, (char*)ptr, i, G_DISCARD); SvREFCNT_dec(hv); Safefree(ptr); break; + case SAVEt_ADELETE: + ptr = SSPOPPTR; + av = MUTABLE_AV(ptr); + i = SSPOPINT; + (void)av_delete(av, i, G_DISCARD); + SvREFCNT_dec(av); + break; case SAVEt_DESTRUCTOR_X: ptr = SSPOPPTR; (*SSPOPDXPTR)(aTHX_ ptr); @@ -898,19 +950,18 @@ Perl_leave_scope(pTHX_ I32 base) sv = MUTABLE_SV(SSPOPPTR); hv = MUTABLE_HV(SSPOPPTR); ptr = hv_fetch_ent(hv, sv, 1, 0); + SvREFCNT_dec(sv); if (ptr) { const SV * const oval = HeVAL((HE*)ptr); if (oval && oval != &PL_sv_undef) { ptr = &HeVAL((HE*)ptr); if (SvTIED_mg((const SV *)hv, PERL_MAGIC_tied)) SvREFCNT_inc_void(*(SV**)ptr); - SvREFCNT_dec(sv); av = MUTABLE_AV(hv); /* what to refcnt_dec */ goto restore_sv; } } SvREFCNT_dec(hv); - SvREFCNT_dec(sv); SvREFCNT_dec(value); break; case SAVEt_OP: @@ -1062,6 +1113,10 @@ Perl_leave_scope(pTHX_ I32 base) Perl_croak(aTHX_ "panic: leave_scope inconsistency"); } } + + PL_tainted = was; + + PERL_ASYNC_CHECK(); } void