X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/e0fa7e2be05466f132eb653ebe7b2f9664ffcb3b..fa01018c102d8360898153b9f4b062716ad06702:/scope.c diff --git a/scope.c b/scope.c index b2c2ee0..cc207c0 100644 --- a/scope.c +++ b/scope.c @@ -77,7 +77,7 @@ Perl_cxinc(pTHX) dVAR; const IV old_max = cxstack_max; cxstack_max = GROW(cxstack_max); - Renew(cxstack, cxstack_max + 1, PERL_CONTEXT); /* XXX should fix CXINC macro */ + Renew(cxstack, cxstack_max + 1, PERL_CONTEXT); /* Without any kind of initialising deep enough recursion * will end up reading uninitialised PERL_CONTEXTs. */ PoisonNew(cxstack + old_max + 1, cxstack_max - old_max, PERL_CONTEXT); @@ -181,15 +181,13 @@ S_save_scalar_at(pTHX_ SV **sptr, const U32 flags) 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; @@ -281,15 +279,7 @@ Perl_save_gp(pTHX_ GV *gv, I32 empty) 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); @@ -308,7 +298,7 @@ Perl_save_gp(pTHX_ GV *gv, I32 empty) gp->gp_sv = newSV(0); } #endif - GvGP(gv) = gp; + GvGP_set(gv,gp); } else { gp_ref(GvGP(gv)); @@ -327,7 +317,7 @@ Perl_save_ary(pTHX_ GV *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); @@ -344,7 +334,9 @@ Perl_save_hash(pTHX_ GV *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); @@ -373,10 +365,9 @@ Perl_save_bool(pTHX_ bool *boolp) PERL_ARGS_ASSERT_SAVE_BOOL; - SSCHECK(3); - SSPUSHBOOL(*boolp); + SSCHECK(2); SSPUSHPTR(boolp); - SSPUSHUV(SAVEt_BOOL); + SSPUSHUV(SAVEt_BOOL | (*boolp << 8)); } void @@ -393,10 +384,16 @@ void Perl_save_int(pTHX_ int *intp) { dVAR; + const UV shifted = (UV)*intp << SAVE_TIGHT_SHIFT; PERL_ARGS_ASSERT_SAVE_INT; - save_pushi32ptr(*intp, intp, SAVEt_INT); + if ((int)(shifted >> SAVE_TIGHT_SHIFT) == *intp) { + SSCHECK(2); + SSPUSHPTR(intp); + SSPUSHUV(SAVEt_INT_SMALL | shifted); + } else + save_pushi32ptr(*intp, intp, SAVEt_INT); } void @@ -406,7 +403,9 @@ Perl_save_I8(pTHX_ I8 *bytep) PERL_ARGS_ASSERT_SAVE_I8; - save_pushi32ptr(*bytep, bytep, SAVEt_I8); + SSCHECK(2); + SSPUSHPTR(bytep); + SSPUSHUV(SAVEt_I8 | ((UV)*bytep << 8)); } void @@ -416,17 +415,25 @@ Perl_save_I16(pTHX_ I16 *intp) PERL_ARGS_ASSERT_SAVE_I16; - save_pushi32ptr(*intp, intp, SAVEt_I16); + SSCHECK(2); + SSPUSHPTR(intp); + SSPUSHUV(SAVEt_I16 | ((UV)*intp << 8)); } void Perl_save_I32(pTHX_ I32 *intp) { dVAR; + const UV shifted = (UV)*intp << SAVE_TIGHT_SHIFT; PERL_ARGS_ASSERT_SAVE_I32; - save_pushi32ptr(*intp, intp, SAVEt_I32); + if ((I32)(shifted >> SAVE_TIGHT_SHIFT) == *intp) { + SSCHECK(2); + SSPUSHPTR(intp); + SSPUSHUV(SAVEt_I32_SMALL | shifted); + } else + save_pushi32ptr(*intp, intp, SAVEt_I32); } /* Cannot use save_sptr() to store a char* since the SV** cast will @@ -585,17 +592,14 @@ 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); } } @@ -680,13 +684,17 @@ Perl_save_alloc(pTHX_ I32 size, I32 pad) dVAR; register const I32 start = pad + ((char*)&PL_savestack[PL_savestack_ix] - (char*)PL_savestack); - register const I32 elems = 1 + ((size + pad - 1) / sizeof(*PL_savestack)); + const UV elems = 1 + ((size + pad - 1) / sizeof(*PL_savestack)); + const UV elems_shifted = elems << SAVE_TIGHT_SHIFT; - SSGROW(elems + 2); + if ((elems_shifted >> SAVE_TIGHT_SHIFT) != elems) + Perl_croak(aTHX_ "panic: save_alloc elems %"UVuf" out of range (%ld-%ld)", + elems, size, pad); + + SSGROW(elems + 1); PL_savestack_ix += elems; - SSPUSHINT(elems); - SSPUSHUV(SAVEt_ALLOC); + SSPUSHUV(SAVEt_ALLOC | elems_shifted); return start; } @@ -703,10 +711,10 @@ Perl_leave_scope(pTHX_ I32 base) 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) { @@ -736,8 +744,7 @@ Perl_leave_scope(pTHX_ I32 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; @@ -759,9 +766,15 @@ Perl_leave_scope(pTHX_ I32 base) *(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); @@ -777,6 +790,7 @@ Perl_leave_scope(pTHX_ I32 base) SvSETMAGIC(MUTABLE_SV(av)); PL_localizing = 0; } + SvREFCNT_dec(gv); break; case SAVEt_HV: /* hash reference */ hv = MUTABLE_HV(SSPOPPTR); @@ -788,6 +802,11 @@ Perl_leave_scope(pTHX_ I32 base) SvSETMAGIC(MUTABLE_SV(hv)); PL_localizing = 0; } + SvREFCNT_dec(gv); + break; + case SAVEt_INT_SMALL: + ptr = SSPOPPTR; + *(int*)ptr = (int)(uv >> SAVE_TIGHT_SHIFT); break; case SAVEt_INT: /* int reference */ ptr = SSPOPPTR; @@ -795,7 +814,20 @@ Perl_leave_scope(pTHX_ I32 base) break; case SAVEt_BOOL: /* bool reference */ ptr = SSPOPPTR; - *(bool*)ptr = cBOOL(SSPOPBOOL); + *(bool*)ptr = cBOOL(uv >> 8); + + if (ptr == &PL_tainted) { + /* If we don't update , 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; + *(I32*)ptr = (I32)(uv >> SAVE_TIGHT_SHIFT); break; case SAVEt_I32: /* I32 reference */ ptr = SSPOPPTR; @@ -827,13 +859,12 @@ Perl_leave_scope(pTHX_ I32 base) *(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; @@ -841,6 +872,10 @@ Perl_leave_scope(pTHX_ I32 base) 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)); @@ -877,7 +912,10 @@ Perl_leave_scope(pTHX_ I32 base) 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)) { @@ -898,7 +936,8 @@ Perl_leave_scope(pTHX_ I32 base) 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; @@ -907,7 +946,7 @@ Perl_leave_scope(pTHX_ I32 base) 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: @@ -932,11 +971,8 @@ Perl_leave_scope(pTHX_ I32 base) break; case SAVEt_REGCONTEXT: /* regexp must have croaked */ - PL_savestack_ix -= uv >> SAVE_TIGHT_SHIFT; - break; case SAVEt_ALLOC: - i = SSPOPINT; - PL_savestack_ix -= i; /* regexp must have croaked */ + PL_savestack_ix -= uv >> SAVE_TIGHT_SHIFT; break; case SAVEt_STACK_POS: /* Position on Perl stack */ i = SSPOPINT; @@ -991,8 +1027,8 @@ Perl_leave_scope(pTHX_ I32 base) SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv))); GvHV(PL_hintgv) = NULL; } - 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))); @@ -1084,21 +1120,16 @@ Perl_leave_scope(pTHX_ I32 base) case SAVEt_I16: /* I16 reference */ ptr = SSPOPPTR; - *(I16*)ptr = (I16)SSPOPINT; + *(I16*)ptr = (I16)(uv >> 8); break; case SAVEt_I8: /* I8 reference */ ptr = SSPOPPTR; - *(I8*)ptr = (I8)SSPOPINT; + *(I8*)ptr = (I8)(uv >> 8); break; case SAVEt_DESTRUCTOR: 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; @@ -1129,7 +1160,7 @@ Perl_leave_scope(pTHX_ I32 base) parser_free((yy_parser *) ptr); break; default: - Perl_croak(aTHX_ "panic: leave_scope inconsistency"); + Perl_croak(aTHX_ "panic: leave_scope inconsistency %u", type); } } @@ -1208,8 +1239,6 @@ Perl_cx_dump(pTHX_ PERL_CONTEXT *cx) (long)cx->blk_loop.resetsp); PerlIO_printf(Perl_debug_log, "BLK_LOOP.MY_OP = 0x%"UVxf"\n", PTR2UV(cx->blk_loop.my_op)); - PerlIO_printf(Perl_debug_log, "BLK_LOOP.NEXT_OP = 0x%"UVxf"\n", - PTR2UV(CX_LOOP_NEXTOP_GET(cx))); /* XXX: not accurate for LAZYSV/IV */ PerlIO_printf(Perl_debug_log, "BLK_LOOP.ITERARY = 0x%"UVxf"\n", PTR2UV(cx->blk_loop.state_u.ary.ary));