X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_hot.c;h=16992d47b747c90953b69cd4d9183feb20c979e0;hb=a4df5da1fe962395b9ad9ab6a0922d022fdb809c;hp=ad9e0ea5fc00860f6ee8ea39a9835398cc97acff;hpb=a2309040b8fe324ae09c064137c624b4292d93c1;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_hot.c b/pp_hot.c index ad9e0ea..16992d4 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -1,7 +1,7 @@ /* pp_hot.c * - * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -12,8 +12,10 @@ * Then he heard Merry change the note, and up went the Horn-cry of Buckland, * shaking the air. * - * Awake! Awake! Fear, Fire, Foes! Awake! - * Fire, Foes! Awake! + * Awake! Awake! Fear, Fire, Foes! Awake! + * Fire, Foes! Awake! + * + * [p.1007 of _The Lord of the Rings_, VI/viii: "The Scouring of the Shire"] */ /* This file contains 'hot' pp ("push/pop") functions that @@ -39,14 +41,7 @@ PP(pp_const) { dVAR; dSP; - if ( PL_op->op_flags & OPf_SPECIAL ) - /* This is a const op added to hold the hints hash for - pp_entereval. The hash can be modified by the code - being eval'ed, so we return a copy instead. */ - mXPUSHs((SV*)Perl_hv_copy_hints_hv(aTHX_ (HV*)cSVOP_sv)); - else - /* Normal const. */ - XPUSHs(cSVOP_sv); + XPUSHs(cSVOP_sv); RETURN; } @@ -78,13 +73,6 @@ PP(pp_null) return NORMAL; } -PP(pp_setstate) -{ - dVAR; - PL_curcop = (COP*)PL_op; - return NORMAL; -} - PP(pp_pushmark) { dVAR; @@ -103,7 +91,7 @@ PP(pp_stringify) PP(pp_gv) { dVAR; dSP; - XPUSHs((SV*)cGVOP_gv); + XPUSHs(MUTABLE_SV(cGVOP_gv)); RETURN; } @@ -150,7 +138,7 @@ PP(pp_sassign) The gv becomes a(nother) reference to the constant. */ SV *const value = SvRV(cv); - SvUPGRADE((SV *)gv, SVt_IV); + SvUPGRADE(MUTABLE_SV(gv), SVt_IV); SvPCS_IMPORTED_on(gv); SvRV_set(gv, value); SvREFCNT_inc_simple_void(value); @@ -162,7 +150,7 @@ PP(pp_sassign) /* Need to fix things up. */ if (gv_type != SVt_PVGV) { /* Need to fix GV. */ - right = (SV*)gv_fetchsv(right, GV_ADD, SVt_PVGV); + right = MUTABLE_SV(gv_fetchsv(right, GV_ADD, SVt_PVGV)); } if (!got_coderef) { @@ -176,8 +164,8 @@ PP(pp_sassign) all sorts of fun as the reference to our new sub is donated to the GV that we're about to assign to. */ - SvRV_set(left, (SV *)newCONSTSUB(GvSTASH(right), NULL, - SvRV(cv))); + SvRV_set(left, MUTABLE_SV(newCONSTSUB(GvSTASH(right), NULL, + SvRV(cv)))); SvREFCNT_dec(cv); LEAVE; } else { @@ -194,7 +182,7 @@ PP(pp_sassign) So change the reference so that it points to the subroutine of that typeglob, as that's what they were after all along. */ - GV *const upgraded = (GV *) cv; + GV *const upgraded = MUTABLE_GV(cv); CV *const source = GvCV(upgraded); assert(source); @@ -202,7 +190,7 @@ PP(pp_sassign) SvREFCNT_inc_void(source); SvREFCNT_dec(upgraded); - SvRV_set(left, (SV *)source); + SvRV_set(left, MUTABLE_SV(source)); } } @@ -269,7 +257,7 @@ PP(pp_concat) if (!SvOK(TARG)) { if (left == right && ckWARN(WARN_UNINITIALIZED)) report_uninit(right); - sv_setpvn(left, "", 0); + sv_setpvs(left, ""); } (void)SvPV_nomg_const(left, llen); /* Needed to set UTF8 flag */ lbyte = !DO_UTF8(left); @@ -320,16 +308,16 @@ PP(pp_readline) { dVAR; tryAMAGICunTARGET(iter, 0); - PL_last_in_gv = (GV*)(*PL_stack_sp--); - if (SvTYPE(PL_last_in_gv) != SVt_PVGV) { - if (SvROK(PL_last_in_gv) && SvTYPE(SvRV(PL_last_in_gv)) == SVt_PVGV) - PL_last_in_gv = (GV*)SvRV(PL_last_in_gv); + PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--); + if (!isGV_with_GP(PL_last_in_gv)) { + if (SvROK(PL_last_in_gv) && isGV_with_GP(SvRV(PL_last_in_gv))) + PL_last_in_gv = MUTABLE_GV(SvRV(PL_last_in_gv)); else { dSP; - XPUSHs((SV*)PL_last_in_gv); + XPUSHs(MUTABLE_SV(PL_last_in_gv)); PUTBACK; pp_rv2gv(); - PL_last_in_gv = (GV*)(*PL_stack_sp--); + PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--); } } return do_readline(); @@ -411,8 +399,8 @@ PP(pp_eq) PP(pp_preinc) { dVAR; dSP; - if (SvTYPE(TOPs) >= SVt_PVGV && SvTYPE(TOPs) != SVt_PVLV) - DIE(aTHX_ PL_no_modify); + if (SvTYPE(TOPs) >= SVt_PVAV || isGV_with_GP(TOPs)) + DIE(aTHX_ "%s", PL_no_modify); if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && SvIVX(TOPs) != IV_MAX) { @@ -663,8 +651,8 @@ PP(pp_add) PP(pp_aelemfast) { dVAR; dSP; - AV * const av = PL_op->op_flags & OPf_SPECIAL ? - (AV*)PAD_SV(PL_op->op_targ) : GvAV(cGVOP_gv); + AV * const av = PL_op->op_flags & OPf_SPECIAL + ? MUTABLE_AV(PAD_SV(PL_op->op_targ)) : GvAV(cGVOP_gv); const U32 lval = PL_op->op_flags & OPf_MOD; SV** const svp = av_fetch(av, PL_op->op_private, lval); SV *sv = (svp ? *svp : &PL_sv_undef); @@ -699,7 +687,7 @@ PP(pp_pushre) Copy(&PL_op, &LvTARGOFF(sv), 1, OP*); XPUSHs(sv); #else - XPUSHs((SV*)PL_op); + XPUSHs(MUTABLE_SV(PL_op)); #endif RETURN; } @@ -712,10 +700,11 @@ PP(pp_print) IO *io; register PerlIO *fp; MAGIC *mg; - GV * const gv = (PL_op->op_flags & OPf_STACKED) ? (GV*)*++MARK : PL_defoutgv; + GV * const gv + = (PL_op->op_flags & OPf_STACKED) ? MUTABLE_GV(*++MARK) : PL_defoutgv; if (gv && (io = GvIO(gv)) - && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) + && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) { had_magic: if (MARK == ORIGMARK) { @@ -728,7 +717,7 @@ PP(pp_print) ++SP; } PUSHMARK(MARK - 1); - *MARK = SvTIED_obj((SV*)io, mg); + *MARK = SvTIED_obj(MUTABLE_SV(io), mg); PUTBACK; ENTER; if( PL_op->op_type == OP_SAY ) { @@ -746,7 +735,7 @@ PP(pp_print) } if (!(io = GvIO(gv))) { if ((GvEGV(gv)) && (io = GvIO(GvEGV(gv))) - && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) + && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) goto had_magic; if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) report_evil_fh(gv, io, PL_op->op_type); @@ -764,14 +753,16 @@ PP(pp_print) goto just_say_no; } else { + SV * const ofs = GvSV(PL_ofsgv); /* $, */ MARK++; - if (PL_ofs_sv && SvOK(PL_ofs_sv)) { + if (ofs && (SvGMAGICAL(ofs) || SvOK(ofs))) { while (MARK <= SP) { if (!do_print(*MARK, fp)) break; MARK++; if (MARK <= SP) { - if (!do_print(PL_ofs_sv, fp)) { /* $, */ + /* don't use 'ofs' here - it may be invalidated by magic callbacks */ + if (!do_print(GvSV(PL_ofsgv), fp)) { MARK--; break; } @@ -815,8 +806,6 @@ PP(pp_rv2av) { dVAR; dSP; dTOPss; const I32 gimme = GIMME_V; - static const char return_array_to_lvalue_scalar[] = "Can't return array to lvalue scalar context"; - static const char return_hash_to_lvalue_scalar[] = "Can't return hash to lvalue scalar context"; static const char an_array[] = "an ARRAY"; static const char a_hash[] = "a HASH"; const bool is_pp_rv2av = PL_op->op_type == OP_RV2AV; @@ -835,14 +824,13 @@ PP(pp_rv2av) } else if (LVRET) { if (gimme != G_ARRAY) - Perl_croak(aTHX_ is_pp_rv2av ? return_array_to_lvalue_scalar - : return_hash_to_lvalue_scalar); + goto croak_cant_return; SETs(sv); RETURN; } else if (PL_op->op_flags & OPf_MOD && PL_op->op_private & OPpLVAL_INTRO) - Perl_croak(aTHX_ PL_no_localize_ref); + Perl_croak(aTHX_ "%s", PL_no_localize_ref); } else { if (SvTYPE(sv) == type) { @@ -852,9 +840,7 @@ PP(pp_rv2av) } else if (LVRET) { if (gimme != G_ARRAY) - Perl_croak(aTHX_ - is_pp_rv2av ? return_array_to_lvalue_scalar - : return_hash_to_lvalue_scalar); + goto croak_cant_return; SETs(sv); RETURN; } @@ -862,7 +848,7 @@ PP(pp_rv2av) else { GV *gv; - if (SvTYPE(sv) != SVt_PVGV) { + if (!isGV_with_GP(sv)) { if (SvGMAGICAL(sv)) { mg_get(sv); if (SvROK(sv)) @@ -874,20 +860,18 @@ PP(pp_rv2av) RETURN; } else { - gv = (GV*)sv; + gv = MUTABLE_GV(sv); } - sv = is_pp_rv2av ? (SV*)GvAVn(gv) : (SV*)GvHVn(gv); + sv = is_pp_rv2av ? MUTABLE_SV(GvAVn(gv)) : MUTABLE_SV(GvHVn(gv)); if (PL_op->op_private & OPpLVAL_INTRO) - sv = is_pp_rv2av ? (SV*)save_ary(gv) : (SV*)save_hash(gv); + sv = is_pp_rv2av ? MUTABLE_SV(save_ary(gv)) : MUTABLE_SV(save_hash(gv)); if (PL_op->op_flags & OPf_REF) { SETs(sv); RETURN; } else if (LVRET) { if (gimme != G_ARRAY) - Perl_croak(aTHX_ - is_pp_rv2av ? return_array_to_lvalue_scalar - : return_hash_to_lvalue_scalar); + goto croak_cant_return; SETs(sv); RETURN; } @@ -895,7 +879,7 @@ PP(pp_rv2av) } if (is_pp_rv2av) { - AV *const av = (AV*)sv; + AV *const av = MUTABLE_AV(sv); /* The guts of pp_rv2av, with no intenting change to preserve history (until such time as we get tools that can do blame annotation across whitespace changes. */ @@ -931,18 +915,26 @@ PP(pp_rv2av) } else if (gimme == G_SCALAR) { dTARGET; - TARG = Perl_hv_scalar(aTHX_ (HV*)sv); + TARG = Perl_hv_scalar(aTHX_ MUTABLE_HV(sv)); SPAGAIN; SETTARG; } } RETURN; + + croak_cant_return: + Perl_croak(aTHX_ "Can't return %s to lvalue scalar context", + is_pp_rv2av ? "array" : "hash"); + RETURN; } STATIC void S_do_oddball(pTHX_ HV *hash, SV **relem, SV **firstrelem) { dVAR; + + PERL_ARGS_ASSERT_DO_ODDBALL; + if (*relem) { SV *tmpstr; const HE *didstore; @@ -958,7 +950,7 @@ S_do_oddball(pTHX_ HV *hash, SV **relem, SV **firstrelem) } else err = "Odd number of elements in hash assignment"; - Perl_warner(aTHX_ packWARN(WARN_MISC), err); + Perl_warner(aTHX_ packWARN(WARN_MISC), "%s", err); } tmpstr = newSV(0); @@ -1021,7 +1013,7 @@ PP(pp_aassign) sv = *lelem++; switch (SvTYPE(sv)) { case SVt_PVAV: - ary = (AV*)sv; + ary = MUTABLE_AV(sv); magic = SvMAGICAL(ary) != 0; av_clear(ary); av_extend(ary, lastrelem - relem); @@ -1033,20 +1025,26 @@ PP(pp_aassign) *(relem++) = sv; didstore = av_store(ary,i++,sv); if (magic) { - if (SvSMAGICAL(sv)) + if (SvSMAGICAL(sv)) { + /* More magic can happen in the mg_set callback, so we + * backup the delaymagic for now. */ + U16 dmbak = PL_delaymagic; + PL_delaymagic = 0; mg_set(sv); + PL_delaymagic = dmbak; + } if (!didstore) sv_2mortal(sv); } TAINT_NOT; } if (PL_delaymagic & DM_ARRAY) - SvSETMAGIC((SV*)ary); + SvSETMAGIC(MUTABLE_SV(ary)); break; case SVt_PVHV: { /* normal hash */ SV *tmpstr; - hash = (HV*)sv; + hash = MUTABLE_HV(sv); magic = SvMAGICAL(hash) != 0; hv_clear(hash); firsthashrelem = relem; @@ -1064,8 +1062,12 @@ PP(pp_aassign) duplicates += 2; didstore = hv_store_ent(hash,sv,tmpstr,0); if (magic) { - if (SvSMAGICAL(tmpstr)) + if (SvSMAGICAL(tmpstr)) { + U16 dmbak = PL_delaymagic; + PL_delaymagic = 0; mg_set(tmpstr); + PL_delaymagic = dmbak; + } if (!didstore) sv_2mortal(tmpstr); } @@ -1089,7 +1091,13 @@ PP(pp_aassign) } else sv_setsv(sv, &PL_sv_undef); - SvSETMAGIC(sv); + + if (SvSMAGICAL(sv)) { + U16 dmbak = PL_delaymagic; + PL_delaymagic = 0; + mg_set(sv); + PL_delaymagic = dmbak; + } break; } } @@ -1204,11 +1212,12 @@ PP(pp_qr) /* This RV is about to own a reference to the regexp. (In addition to the reference already owned by the PMOP. */ ReREFCNT_inc(rx); - SvRV_set(rv, (SV*) rx); + SvRV_set(rv, MUTABLE_SV(rx)); SvROK_on(rv); if (pkg) { HV* const stash = gv_stashpv(SvPV_nolen(pkg), GV_ADD); + SvREFCNT_dec(pkg); (void)sv_bless(rv, stash); } @@ -1227,7 +1236,7 @@ PP(pp_match) register const char *s; const char *strend; I32 global; - I32 r_flags = REXEC_CHECKED; + U8 r_flags = REXEC_CHECKED; const char *truebase; /* Start of string */ register REGEXP *rx = PM_GETRE(pm); bool rxtainted; @@ -1540,10 +1549,10 @@ Perl_do_readline(pTHX) const I32 gimme = GIMME_V; if (io) { - MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar); + MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); if (mg) { PUSHMARK(SP); - XPUSHs(SvTIED_obj((SV*)io, mg)); + XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg)); PUTBACK; ENTER; call_method("READLINE", gimme); @@ -1567,7 +1576,7 @@ Perl_do_readline(pTHX) if (av_len(GvAVn(PL_last_in_gv)) < 0) { IoFLAGS(io) &= ~IOf_START; do_open(PL_last_in_gv,"-",1,FALSE,O_RDONLY,0,NULL); - sv_setpvn(GvSVn(PL_last_in_gv), "-", 1); + sv_setpvs(GvSVn(PL_last_in_gv), "-"); SvSETMAGIC(GvSV(PL_last_in_gv)); fp = IoIFP(io); goto have_fp; @@ -1666,11 +1675,11 @@ Perl_do_readline(pTHX) (void)do_close(PL_last_in_gv, FALSE); } else if (type == OP_GLOB) { - if (!do_close(PL_last_in_gv, FALSE) && ckWARN(WARN_GLOB)) { - Perl_warner(aTHX_ packWARN(WARN_GLOB), - "glob failed (child exited with status %d%s)", - (int)(STATUS_CURRENT >> 8), - (STATUS_CURRENT & 0x80) ? ", core dumped" : ""); + if (!do_close(PL_last_in_gv, FALSE)) { + Perl_ck_warner(aTHX_ packWARN(WARN_GLOB), + "glob failed (child exited with status %d%s)", + (int)(STATUS_CURRENT >> 8), + (STATUS_CURRENT & 0x80) ? ", core dumped" : ""); } } if (gimme == G_SCALAR) { @@ -1745,9 +1754,13 @@ PP(pp_enter) I32 gimme = OP_GIMME(PL_op, -1); if (gimme == -1) { - if (cxstack_ix >= 0) - gimme = cxstack[cxstack_ix].blk_gimme; - else + if (cxstack_ix >= 0) { + /* If this flag is set, we're just inside a return, so we should + * store the caller's context */ + gimme = (PL_op->op_flags & OPf_SPECIAL) + ? block_gimme() + : cxstack[cxstack_ix].blk_gimme; + } else gimme = G_SCALAR; } @@ -1765,33 +1778,29 @@ PP(pp_helem) HE* he; SV **svp; SV * const keysv = POPs; - HV * const hv = (HV*)POPs; + HV * const hv = MUTABLE_HV(POPs); const U32 lval = PL_op->op_flags & OPf_MOD || LVRET; const U32 defer = PL_op->op_private & OPpLVAL_DEFER; SV *sv; const U32 hash = (SvIsCOW_shared_hash(keysv)) ? SvSHARED_HASH(keysv) : 0; - I32 preeminent = 0; + const bool localizing = PL_op->op_private & OPpLVAL_INTRO; + bool preeminent = TRUE; if (SvTYPE(hv) != SVt_PVHV) RETPUSHUNDEF; - if (PL_op->op_private & OPpLVAL_INTRO) { + if (localizing) { MAGIC *mg; HV *stash; - /* does the element we're localizing already exist? */ - preeminent = /* can we determine whether it exists? */ - ( !SvRMAGICAL(hv) - || mg_find((SV*)hv, PERL_MAGIC_env) - || ( (mg = mg_find((SV*)hv, PERL_MAGIC_tied)) - /* Try to preserve the existenceness of a tied hash - * element by using EXISTS and DELETE if possible. - * Fallback to FETCH and STORE otherwise */ - && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg)))) - && gv_fetchmethod_autoload(stash, "EXISTS", TRUE) - && gv_fetchmethod_autoload(stash, "DELETE", TRUE) - ) - ) ? hv_exists_ent(hv, keysv, 0) : 1; + + /* If we can determine whether the element exist, + * Try to preserve the existenceness of a tied hash + * element by using EXISTS and DELETE if possible. + * Fallback to FETCH and STORE otherwise. */ + if (SvCANEXISTDELETE(hv) || mg_find((const SV *)hv, PERL_MAGIC_env)) + preeminent = hv_exists_ent(hv, keysv, 0); } + he = hv_fetch_ent(hv, keysv, lval && !defer, hash); svp = he ? &HeVAL(he) : NULL; if (lval) { @@ -1811,18 +1820,14 @@ PP(pp_helem) PUSHs(lv); RETURN; } - if (PL_op->op_private & OPpLVAL_INTRO) { + if (localizing) { if (HvNAME_get(hv) && isGV(*svp)) - save_gp((GV*)*svp, !(PL_op->op_flags & OPf_SPECIAL)); - else { - if (!preeminent) { - STRLEN keylen; - const char * const key = SvPV_const(keysv, keylen); - SAVEDELETE(hv, savepvn(key,keylen), - SvUTF8(keysv) ? -(I32)keylen : (I32)keylen); - } else - save_helem(hv, keysv, svp); - } + save_gp(MUTABLE_GV(*svp), !(PL_op->op_flags & OPf_SPECIAL)); + else if (preeminent) + save_helem_flags(hv, keysv, svp, + (PL_op->op_flags & OPf_SPECIAL) ? 0 : SAVEf_SETMAGIC); + else + SAVEHDELETE(hv, keysv); } else if (PL_op->op_private & OPpDEREF) vivify_ref(*svp, PL_op->op_private & OPpDEREF); @@ -1855,13 +1860,7 @@ PP(pp_leave) POPBLOCK(cx,newpm); - gimme = OP_GIMME(PL_op, -1); - if (gimme == -1) { - if (cxstack_ix >= 0) - gimme = cxstack[cxstack_ix].blk_gimme; - else - gimme = G_SCALAR; - } + gimme = OP_GIMME(PL_op, (cxstack_ix >= 0) ? gimme : G_SCALAR); TAINT_NOT; if (gimme == G_VOID) @@ -1902,25 +1901,24 @@ PP(pp_iter) dVAR; dSP; register PERL_CONTEXT *cx; SV *sv, *oldsv; - AV* av; SV **itersvp; + AV *av = NULL; /* used for LOOP_FOR on arrays and the stack */ + bool av_is_stack = FALSE; EXTEND(SP, 1); cx = &cxstack[cxstack_ix]; - if (CxTYPE(cx) != CXt_LOOP) + if (!CxTYPE_is_LOOP(cx)) DIE(aTHX_ "panic: pp_iter"); itersvp = CxITERVAR(cx); - av = cx->blk_loop.iterary; - if (SvTYPE(av) != SVt_PVAV) { - /* iterate ($min .. $max) */ - if (cx->blk_loop.iterlval) { + if (CxTYPE(cx) == CXt_LOOP_LAZYSV) { /* string increment */ - register SV* cur = cx->blk_loop.iterlval; + SV* cur = cx->blk_loop.state_u.lazysv.cur; + SV *end = cx->blk_loop.state_u.lazysv.end; + /* If the maximum is !SvOK(), pp_enteriter substitutes PL_sv_no. + It has SvPVX of "" and SvCUR of 0, which is what we want. */ STRLEN maxlen = 0; - const char *max = - SvOK((SV*)av) ? - SvPV_const((SV*)av, maxlen) : (const char *)""; + const char *max = SvPV_const(end, maxlen); if (!SvNIOK(cur) && SvCUR(cur) <= maxlen) { if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) { /* safe to reuse old SV */ @@ -1942,15 +1940,16 @@ PP(pp_iter) RETPUSHYES; } RETPUSHNO; - } + } + else if (CxTYPE(cx) == CXt_LOOP_LAZYIV) { /* integer increment */ - if (cx->blk_loop.iterix > cx->blk_loop.itermax) + if (cx->blk_loop.state_u.lazyiv.cur > cx->blk_loop.state_u.lazyiv.end) RETPUSHNO; /* don't risk potential race */ if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) { /* safe to reuse old SV */ - sv_setiv(*itersvp, cx->blk_loop.iterix++); + sv_setiv(*itersvp, cx->blk_loop.state_u.lazyiv.cur++); } else { @@ -1958,46 +1957,52 @@ PP(pp_iter) * completely new SV for closures/references to work as they * used to */ oldsv = *itersvp; - *itersvp = newSViv(cx->blk_loop.iterix++); + *itersvp = newSViv(cx->blk_loop.state_u.lazyiv.cur++); SvREFCNT_dec(oldsv); } /* Handle end of range at IV_MAX */ - if ((cx->blk_loop.iterix == IV_MIN) && - (cx->blk_loop.itermax == IV_MAX)) + if ((cx->blk_loop.state_u.lazyiv.cur == IV_MIN) && + (cx->blk_loop.state_u.lazyiv.end == IV_MAX)) { - cx->blk_loop.iterix++; - cx->blk_loop.itermax++; + cx->blk_loop.state_u.lazyiv.cur++; + cx->blk_loop.state_u.lazyiv.end++; } RETPUSHYES; } /* iterate array */ + assert(CxTYPE(cx) == CXt_LOOP_FOR); + av = cx->blk_loop.state_u.ary.ary; + if (!av) { + av_is_stack = TRUE; + av = PL_curstack; + } if (PL_op->op_private & OPpITER_REVERSED) { - /* In reverse, use itermax as the min :-) */ - if (cx->blk_loop.iterix <= cx->blk_loop.itermax) + if (cx->blk_loop.state_u.ary.ix <= (av_is_stack + ? cx->blk_loop.resetsp + 1 : 0)) RETPUSHNO; if (SvMAGICAL(av) || AvREIFY(av)) { - SV * const * const svp = av_fetch(av, --cx->blk_loop.iterix, FALSE); + SV * const * const svp = av_fetch(av, --cx->blk_loop.state_u.ary.ix, FALSE); sv = svp ? *svp : NULL; } else { - sv = AvARRAY(av)[--cx->blk_loop.iterix]; + sv = AvARRAY(av)[--cx->blk_loop.state_u.ary.ix]; } } else { - if (cx->blk_loop.iterix >= (av == PL_curstack ? cx->blk_oldsp : + if (cx->blk_loop.state_u.ary.ix >= (av_is_stack ? cx->blk_oldsp : AvFILL(av))) RETPUSHNO; if (SvMAGICAL(av) || AvREIFY(av)) { - SV * const * const svp = av_fetch(av, ++cx->blk_loop.iterix, FALSE); + SV * const * const svp = av_fetch(av, ++cx->blk_loop.state_u.ary.ix, FALSE); sv = svp ? *svp : NULL; } else { - sv = AvARRAY(av)[++cx->blk_loop.iterix]; + sv = AvARRAY(av)[++cx->blk_loop.state_u.ary.ix]; } } @@ -2006,31 +2011,24 @@ PP(pp_iter) Perl_croak(aTHX_ "Use of freed value in iteration"); } - if (sv) + if (sv) { SvTEMP_off(sv); + SvREFCNT_inc_simple_void_NN(sv); + } else sv = &PL_sv_undef; - if (av != PL_curstack && sv == &PL_sv_undef) { - SV *lv = cx->blk_loop.iterlval; - if (lv && SvREFCNT(lv) > 1) { - SvREFCNT_dec(lv); - lv = NULL; - } - if (lv) - SvREFCNT_dec(LvTARG(lv)); - else { - lv = cx->blk_loop.iterlval = newSV_type(SVt_PVLV); - LvTYPE(lv) = 'y'; - sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0); - } + if (!av_is_stack && sv == &PL_sv_undef) { + SV *lv = newSV_type(SVt_PVLV); + LvTYPE(lv) = 'y'; + sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0); LvTARG(lv) = SvREFCNT_inc_simple(av); - LvTARGOFF(lv) = cx->blk_loop.iterix; + LvTARGOFF(lv) = cx->blk_loop.state_u.ary.ix; LvTARGLEN(lv) = (STRLEN)UV_MAX; - sv = (SV*)lv; + sv = lv; } oldsv = *itersvp; - *itersvp = SvREFCNT_inc_simple_NN(sv); + *itersvp = sv; SvREFCNT_dec(oldsv); RETPUSHYES; @@ -2051,9 +2049,9 @@ PP(pp_subst) I32 maxiters; register I32 i; bool once; - bool rxtainted; + U8 rxtainted; char *orig; - I32 r_flags; + U8 r_flags; register REGEXP *rx = PM_GETRE(pm); STRLEN len; int force_on_match = 0; @@ -2093,7 +2091,7 @@ PP(pp_subst) || ( ((SvTYPE(TARG) == SVt_PVGV && isGV_with_GP(TARG)) || SvTYPE(TARG) > SVt_PVLV) && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG))))) - DIE(aTHX_ PL_no_modify); + DIE(aTHX_ "%s", PL_no_modify); PUTBACK; s = SvPV_mutable(TARG, len); @@ -2418,7 +2416,7 @@ PP(pp_grepwhile) if (PL_op->op_private & OPpGREP_LEX) PAD_SVl(PL_op->op_targ) = src; else - DEFSV = src; + DEFSV_set(src); RETURNOP(cLOGOP->op_other); } @@ -2505,7 +2503,7 @@ PP(pp_leavesublv) TAINT_NOT; - if (cx->blk_sub.lval & OPpENTERSUB_INARGS) { + if (CxLVAL(cx) & OPpENTERSUB_INARGS) { /* We are an argument to a function or grep(). * This kind of lvalueness was legal before lvalue * subroutines too, so be backward compatible: @@ -2532,7 +2530,7 @@ PP(pp_leavesublv) } } } - else if (cx->blk_sub.lval) { /* Leave it as it is if we can. */ + else if (CxLVAL(cx)) { /* Leave it as it is if we can. */ /* Here we go for robustness, not for speed, so we change all * the refcounts so the caller gets a live guy. Cannot set * TEMP, so sv_2mortal is out of question. */ @@ -2663,7 +2661,9 @@ PP(pp_entersub) switch (SvTYPE(sv)) { /* This is overwhelming the most common case: */ case SVt_PVGV: - if (!(cv = GvCVu((GV*)sv))) { + if (!isGV_with_GP(sv)) + DIE(aTHX_ "Not a CODE reference"); + if (!(cv = GvCVu((const GV *)sv))) { HV *stash; cv = sv_2cv(sv, &stash, &gv, 0); } @@ -2709,7 +2709,7 @@ PP(pp_entersub) SV * const * sp = &sv; /* Used in tryAMAGICunDEREF macro. */ tryAMAGICunDEREF(to_cv); } - cv = (CV*)SvRV(sv); + cv = MUTABLE_CV(SvRV(sv)); if (SvTYPE(cv) == SVt_PVCV) break; /* FALL THROUGH */ @@ -2718,7 +2718,7 @@ PP(pp_entersub) DIE(aTHX_ "Not a CODE reference"); /* This is the second most common case: */ case SVt_PVCV: - cv = (CV*)sv; + cv = MUTABLE_CV(sv); break; } @@ -2763,7 +2763,14 @@ try_autoload: Perl_get_db_sub(aTHX_ &sv, cv); if (CvISXSUB(cv)) PL_curcopdb = PL_curcop; - cv = GvCV(PL_DBsub); + if (CvLVALUE(cv)) { + /* check for lsub that handles lvalue subroutines */ + cv = GvCV(gv_HVadd(gv_fetchpvs("DB::lsub", GV_ADDMULTI, SVt_PVHV))); + /* if lsub not found then fall back to DB::sub */ + if (!cv) cv = GvCV(PL_DBsub); + } else { + cv = GvCV(PL_DBsub); + } if (!cv || (!CvXSUB(cv) && !CvSTART(cv))) DIE(aTHX_ "No DB::sub routine defined"); @@ -2790,7 +2797,7 @@ try_autoload: SAVECOMPPAD(); PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); if (hasargs) { - AV* const av = (AV*)PAD_SVl(0); + AV *const av = MUTABLE_AV(PAD_SVl(0)); if (AvREAL(av)) { /* @_ is normally not REAL--this should only ever * happen when DB::sub() calls things that modify @_ */ @@ -2799,7 +2806,7 @@ try_autoload: AvREIFY_on(av); } cx->blk_sub.savearray = GvAV(PL_defgv); - GvAV(PL_defgv) = (AV*)SvREFCNT_inc_simple(av); + GvAV(PL_defgv) = MUTABLE_AV(SvREFCNT_inc_simple(av)); CX_CURPAD_SAVE(cx->blk_sub); cx->blk_sub.argarray = av; ++MARK; @@ -2833,10 +2840,6 @@ try_autoload: if (CvDEPTH(cv) == PERL_SUB_DEPTH_WARN && ckWARN(WARN_RECURSION) && !(PERLDB_SUB && cv == GvCV(PL_DBsub))) sub_crush_depth(cv); -#if 0 - DEBUG_S(PerlIO_printf(Perl_debug_log, - "%p entersub returning %p\n", (void*)thr, (void*)CvSTART(cv))); -#endif RETURNOP(CvSTART(cv)); } else { @@ -2866,8 +2869,10 @@ try_autoload: PL_curcopdb = NULL; } /* Do we need to open block here? XXXX */ - if (CvXSUB(cv)) /* XXX this is supposed to be true */ - (void)(*CvXSUB(cv))(aTHX_ cv); + + /* CvXSUB(cv) must not be NULL because newXS() refuses NULL xsub address */ + assert(CvXSUB(cv)); + CALL_FPTR(CvXSUB(cv))(aTHX_ cv); /* Enforce some sanity in scalar context. */ if (gimme == G_SCALAR && ++markix != PL_stack_sp - PL_stack_base ) { @@ -2885,6 +2890,8 @@ try_autoload: void Perl_sub_crush_depth(pTHX_ CV *cv) { + PERL_ARGS_ASSERT_SUB_CRUSH_DEPTH; + if (CvANON(cv)) Perl_warner(aTHX_ packWARN(WARN_RECURSION), "Deep recursion on anonymous subroutine"); else { @@ -2901,9 +2908,11 @@ PP(pp_aelem) SV** svp; SV* const elemsv = POPs; IV elem = SvIV(elemsv); - AV* const av = (AV*)POPs; + AV *const av = MUTABLE_AV(POPs); const U32 lval = PL_op->op_flags & OPf_MOD || LVRET; const U32 defer = (PL_op->op_private & OPpLVAL_DEFER) && (elem > av_len(av)); + const bool localizing = PL_op->op_private & OPpLVAL_INTRO; + bool preeminent = TRUE; SV *sv; if (SvROK(elemsv) && !SvGAMAGIC(elemsv) && ckWARN(WARN_MISC)) @@ -2914,6 +2923,19 @@ PP(pp_aelem) elem -= CopARYBASE_get(PL_curcop); if (SvTYPE(av) != SVt_PVAV) RETPUSHUNDEF; + + if (localizing) { + MAGIC *mg; + HV *stash; + + /* If we can determine whether the element exist, + * Try to preserve the existenceness of a tied array + * element by using EXISTS and DELETE if possible. + * Fallback to FETCH and STORE otherwise. */ + if (SvCANEXISTDELETE(av)) + preeminent = av_exists(av, elem); + } + svp = av_fetch(av, elem, lval && !defer); if (lval) { #ifdef PERL_MALLOC_WRAP @@ -2943,8 +2965,12 @@ PP(pp_aelem) PUSHs(lv); RETURN; } - if (PL_op->op_private & OPpLVAL_INTRO) - save_aelem(av, elem, svp); + if (localizing) { + if (preeminent) + save_aelem(av, elem, svp); + else + SAVEADELETE(av, elem); + } else if (PL_op->op_private & OPpDEREF) vivify_ref(*svp, PL_op->op_private & OPpDEREF); } @@ -2958,20 +2984,22 @@ PP(pp_aelem) void Perl_vivify_ref(pTHX_ SV *sv, U32 to_what) { + PERL_ARGS_ASSERT_VIVIFY_REF; + SvGETMAGIC(sv); if (!SvOK(sv)) { if (SvREADONLY(sv)) - Perl_croak(aTHX_ PL_no_modify); + Perl_croak(aTHX_ "%s", PL_no_modify); prepare_SV_for_RV(sv); switch (to_what) { case OPpDEREF_SV: SvRV_set(sv, newSV(0)); break; case OPpDEREF_AV: - SvRV_set(sv, (SV*)newAV()); + SvRV_set(sv, MUTABLE_SV(newAV())); break; case OPpDEREF_HV: - SvRV_set(sv, (SV*)newHV()); + SvRV_set(sv, MUTABLE_SV(newHV())); break; } SvROK_on(sv); @@ -3013,19 +3041,20 @@ S_method_common(pTHX_ SV* meth, U32* hashp) SV* ob; GV* gv; HV* stash; - STRLEN namelen; const char* packname = NULL; SV *packsv = NULL; STRLEN packlen; - const char * const name = SvPV_const(meth, namelen); SV * const sv = *(PL_stack_base + TOPMARK + 1); + PERL_ARGS_ASSERT_METHOD_COMMON; + if (!sv) - Perl_croak(aTHX_ "Can't call method \"%s\" on an undefined value", name); + Perl_croak(aTHX_ "Can't call method \"%"SVf"\" on an undefined value", + SVfARG(meth)); SvGETMAGIC(sv); if (SvROK(sv)) - ob = (SV*)SvRV(sv); + ob = MUTABLE_SV(SvRV(sv)); else { GV* iogv; @@ -3041,7 +3070,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp) if (!SvOK(sv) || !(packname) || !(iogv = gv_fetchsv(sv, 0, SVt_PVIO)) || - !(ob=(SV*)GvIO(iogv))) + !(ob=MUTABLE_SV(GvIO(iogv)))) { /* this isn't the name of a filehandle either */ if (!packname || @@ -3050,7 +3079,8 @@ S_method_common(pTHX_ SV* meth, U32* hashp) : !isIDFIRST(*packname) )) { - Perl_croak(aTHX_ "Can't call method \"%s\" %s", name, + Perl_croak(aTHX_ "Can't call method \"%"SVf"\" %s", + SVfARG(meth), SvOK(sv) ? "without a package or object reference" : "on an undefined value"); } @@ -3065,14 +3095,17 @@ S_method_common(pTHX_ SV* meth, U32* hashp) goto fetch; } /* it _is_ a filehandle name -- replace with a reference */ - *(PL_stack_base + TOPMARK + 1) = sv_2mortal(newRV((SV*)iogv)); + *(PL_stack_base + TOPMARK + 1) = sv_2mortal(newRV(MUTABLE_SV(iogv))); } /* if we got here, ob should be a reference or a glob */ if (!ob || !(SvOBJECT(ob) - || (SvTYPE(ob) == SVt_PVGV && (ob = (SV*)GvIO((GV*)ob)) + || (SvTYPE(ob) == SVt_PVGV + && isGV_with_GP(ob) + && (ob = MUTABLE_SV(GvIO((const GV *)ob))) && SvOBJECT(ob)))) { + const char * const name = SvPV_nolen_const(meth); Perl_croak(aTHX_ "Can't call method \"%s\" on unblessed reference", (SvSCREAM(meth) && strEQ(name,"isa")) ? "DOES" : name); @@ -3088,90 +3121,21 @@ S_method_common(pTHX_ SV* meth, U32* hashp) if (hashp) { const HE* const he = hv_fetch_ent(stash, meth, 0, *hashp); if (he) { - gv = (GV*)HeVAL(he); + gv = MUTABLE_GV(HeVAL(he)); if (isGV(gv) && GvCV(gv) && (!GvCVGEN(gv) || GvCVGEN(gv) == (PL_sub_generation + HvMROMETA(stash)->cache_gen))) - return (SV*)GvCV(gv); - } - } - - gv = gv_fetchmethod(stash ? stash : (HV*)packsv, name); - - if (!gv) { - /* This code tries to figure out just what went wrong with - gv_fetchmethod. It therefore needs to duplicate a lot of - the internals of that function. We can't move it inside - Perl_gv_fetchmethod_autoload(), however, since that would - cause UNIVERSAL->can("NoSuchPackage::foo") to croak, and we - don't want that. - */ - const char* leaf = name; - const char* sep = NULL; - const char* p; - - for (p = name; *p; p++) { - if (*p == '\'') - sep = p, leaf = p + 1; - else if (*p == ':' && *(p + 1) == ':') - sep = p, leaf = p + 2; - } - if (!sep || ((sep - name) == 5 && strnEQ(name, "SUPER", 5))) { - /* the method name is unqualified or starts with SUPER:: */ -#ifndef USE_ITHREADS - if (sep) - stash = CopSTASH(PL_curcop); -#else - bool need_strlen = 1; - if (sep) { - packname = CopSTASHPV(PL_curcop); - } - else -#endif - if (stash) { - HEK * const packhek = HvNAME_HEK(stash); - if (packhek) { - packname = HEK_KEY(packhek); - packlen = HEK_LEN(packhek); -#ifdef USE_ITHREADS - need_strlen = 0; -#endif - } else { - goto croak; - } - } - - if (!packname) { - croak: - Perl_croak(aTHX_ - "Can't use anonymous symbol table for method lookup"); - } -#ifdef USE_ITHREADS - if (need_strlen) - packlen = strlen(packname); -#endif - - } - else { - /* the method name is qualified */ - packname = name; - packlen = sep - name; - } - - /* we're relying on gv_fetchmethod not autovivifying the stash */ - if (gv_stashpvn(packname, packlen, 0)) { - Perl_croak(aTHX_ - "Can't locate object method \"%s\" via package \"%.*s\"", - leaf, (int)packlen, packname); - } - else { - Perl_croak(aTHX_ - "Can't locate object method \"%s\" via package \"%.*s\"" - " (perhaps you forgot to load \"%.*s\"?)", - leaf, (int)packlen, packname, (int)packlen, packname); + return MUTABLE_SV(GvCV(gv)); } } - return isGV(gv) ? (SV*)GvCV(gv) : (SV*)gv; + + gv = gv_fetchmethod_flags(stash ? stash : MUTABLE_HV(packsv), + SvPV_nolen_const(meth), + GV_AUTOLOAD | GV_CROAK); + + assert(gv); + + return isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv); } /*