This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regen header after last patches
[perl5.git] / pp_hot.c
index d812e95..aa038d3 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
  * 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
@@ -50,6 +52,7 @@ PP(pp_nextstate)
     TAINT_NOT;         /* Each statement is presumed innocent */
     PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
     FREETMPS;
+    PERL_ASYNC_CHECK();
     return NORMAL;
 }
 
@@ -89,13 +92,14 @@ PP(pp_stringify)
 PP(pp_gv)
 {
     dVAR; dSP;
-    XPUSHs((SV*)cGVOP_gv);
+    XPUSHs(MUTABLE_SV(cGVOP_gv));
     RETURN;
 }
 
 PP(pp_and)
 {
     dVAR; dSP;
+    PERL_ASYNC_CHECK();
     if (!SvTRUE(TOPs))
        RETURN;
     else {
@@ -136,7 +140,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);
@@ -148,24 +152,24 @@ 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) {
            /* We've been returned a constant rather than a full subroutine,
               but they expect a subroutine reference to apply.  */
            if (SvROK(cv)) {
-               ENTER;
+               ENTER_with_name("sassign_coderef");
                SvREFCNT_inc_void(SvRV(cv));
                /* newCONSTSUB takes a reference count on the passed in SV
                   from us.  We set the name to NULL, otherwise we get into
                   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;
+               LEAVE_with_name("sassign_coderef");
            } else {
                /* What can happen for the corner case *{"BONK"} = \&{"BONK"};
                   is that
@@ -180,7 +184,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);
@@ -188,7 +192,7 @@ PP(pp_sassign)
 
                SvREFCNT_inc_void(source);
                SvREFCNT_dec(upgraded);
-               SvRV_set(left, (SV *)source);
+               SvRV_set(left, MUTABLE_SV(source));
            }
        }
 
@@ -201,6 +205,7 @@ PP(pp_sassign)
 PP(pp_cond_expr)
 {
     dVAR; dSP;
+    PERL_ASYNC_CHECK();
     if (SvTRUEx(POPs))
        RETURNOP(cLOGOP->op_other);
     else
@@ -211,6 +216,7 @@ PP(pp_unstack)
 {
     dVAR;
     I32 oldsave;
+    PERL_ASYNC_CHECK();
     TAINT_NOT;         /* Each statement is presumed innocent */
     PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
     FREETMPS;
@@ -255,7 +261,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);
@@ -306,16 +312,16 @@ PP(pp_readline)
 {
     dVAR;
     tryAMAGICunTARGET(iter, 0);
-    PL_last_in_gv = (GV*)(*PL_stack_sp--);
+    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 = (GV*)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();
@@ -398,7 +404,7 @@ PP(pp_preinc)
 {
     dVAR; dSP;
     if (SvTYPE(TOPs) >= SVt_PVAV || isGV_with_GP(TOPs))
-       DIE(aTHX_ PL_no_modify);
+       DIE(aTHX_ "%s", PL_no_modify);
     if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
         && SvIVX(TOPs) != IV_MAX)
     {
@@ -414,6 +420,7 @@ PP(pp_preinc)
 PP(pp_or)
 {
     dVAR; dSP;
+    PERL_ASYNC_CHECK();
     if (SvTRUE(TOPs))
        RETURN;
     else {
@@ -432,6 +439,7 @@ PP(pp_defined)
     const bool is_dor = (op_type == OP_DOR || op_type == OP_DORASSIGN);
 
     if (is_dor) {
+       PERL_ASYNC_CHECK();
         sv = TOPs;
         if (!sv || !SvANY(sv)) {
            if (op_type == OP_DOR)
@@ -649,14 +657,14 @@ 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);
     EXTEND(SP, 1);
-    if (!lval && SvGMAGICAL(sv))       /* see note in pp_helem() */
-       sv = sv_mortalcopy(sv);
+    if (!lval && SvRMAGICAL(av) && SvGMAGICAL(sv)) /* see note in pp_helem() */
+       mg_get(sv);
     PUSHs(sv);
     RETURN;
 }
@@ -685,7 +693,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;
 }
@@ -698,10 +706,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) {
@@ -714,16 +723,16 @@ PP(pp_print)
            ++SP;
        }
        PUSHMARK(MARK - 1);
-       *MARK = SvTIED_obj((SV*)io, mg);
+       *MARK = SvTIED_obj(MUTABLE_SV(io), mg);
        PUTBACK;
-       ENTER;
+       ENTER_with_name("call_PRINT");
        if( PL_op->op_type == OP_SAY ) {
                /* local $\ = "\n" */
                SAVEGENERICSV(PL_ors_sv);
                PL_ors_sv = newSVpvs("\n");
        }
        call_method("PRINT", G_SCALAR);
-       LEAVE;
+       LEAVE_with_name("call_PRINT");
        SPAGAIN;
        MARK = ORIGMARK + 1;
        *MARK = *SP;
@@ -731,8 +740,8 @@ PP(pp_print)
        RETURN;
     }
     if (!(io = GvIO(gv))) {
-        if ((GvEGV(gv)) && (io = GvIO(GvEGV(gv)))
-           && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
+        if ((GvEGVx(gv)) && (io = GvIO(GvEGV(gv)))
+           && (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);
@@ -750,14 +759,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;
                    }
@@ -825,7 +836,7 @@ PP(pp_rv2av)
        }
        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) {
@@ -855,11 +866,11 @@ 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;
@@ -874,7 +885,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.  */
@@ -888,7 +899,7 @@ PP(pp_rv2av)
                SV ** const svp = av_fetch(av, i, FALSE);
                /* See note in pp_helem, and bug id #27839 */
                SP[i+1] = svp
-                   ? SvGMAGICAL(*svp) ? sv_mortalcopy(*svp) : *svp
+                   ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp
                    : &PL_sv_undef;
            }
        }
@@ -945,7 +956,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);
@@ -1008,7 +1019,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);
@@ -1034,7 +1045,7 @@ PP(pp_aassign)
                TAINT_NOT;
            }
            if (PL_delaymagic & DM_ARRAY)
-               SvSETMAGIC((SV*)ary);
+               SvSETMAGIC(MUTABLE_SV(ary));
            break;
        case SVt_PVHV: {                                /* normal hash */
                SV *tmpstr;
@@ -1204,10 +1215,13 @@ PP(pp_qr)
     SV * const rv = sv_newmortal();
 
     SvUPGRADE(rv, SVt_IV);
-    /* 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);
+    /* For a subroutine describing itself as "This is a hacky workaround" I'm
+       loathe to use it here, but it seems to be the right fix. Or close.
+       The key part appears to be that it's essential for pp_qr to return a new
+       object (SV), which implies that there needs to be an effective way to
+       generate a new SV from the existing SV that is pre-compiled in the
+       optree.  */
+    SvRV_set(rv, MUTABLE_SV(reg_temp_copy(NULL, rx)));
     SvROK_on(rv);
 
     if (pkg) {
@@ -1253,7 +1267,11 @@ PP(pp_match)
     }
 
     PUTBACK;                           /* EVAL blocks need stack_sp. */
-    s = SvPV_const(TARG, len);
+    /* Skip get-magic if this is a qr// clone, because regcomp has
+       already done it. */
+    s = ((struct regexp *)SvANY(rx))->mother_re
+        ? SvPV_nomg_const(TARG, len)
+        : SvPV_const(TARG, len);
     if (!s)
        DIE(aTHX_ "panic: pp_match");
     strend = s + len;
@@ -1544,14 +1562,14 @@ 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;
+           ENTER_with_name("call_READLINE");
            call_method("READLINE", gimme);
-           LEAVE;
+           LEAVE_with_name("call_READLINE");
            SPAGAIN;
            if (gimme == G_SCALAR) {
                SV* const result = POPs;
@@ -1571,7 +1589,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;
@@ -1670,11 +1688,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) {
@@ -1749,13 +1767,17 @@ 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;
     }
 
-    ENTER;
+    ENTER_with_name("block");
 
     SAVETMPS;
     PUSHBLOCK(cx, CXt_BLOCK, SP);
@@ -1774,28 +1796,24 @@ PP(pp_helem)
     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) {
@@ -1815,31 +1833,33 @@ 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);
     }
     sv = (svp ? *svp : &PL_sv_undef);
-    /* This makes C<local $tied{foo} = $tied{foo}> possible.
-     * Pushing the magical RHS on to the stack is useless, since
-     * that magic is soon destined to be misled by the local(),
-     * and thus the later pp_sassign() will fail to mg_get() the
-     * old value.  This should also cure problems with delayed
-     * mg_get()s.  GSAR 98-07-03 */
-    if (!lval && SvGMAGICAL(sv))
-       sv = sv_mortalcopy(sv);
+    /* Originally this did a conditional C<sv = sv_mortalcopy(sv)>; this
+     * was to make C<local $tied{foo} = $tied{foo}> possible.
+     * However, it seems no longer to be needed for that purpose, and
+     * introduced a new bug: stuff like C<while ($hash{taintedval} =~ /.../g>
+     * would loop endlessly since the pos magic is getting set on the
+     * mortal copy and lost. However, the copy has the effect of
+     * triggering the get magic, and losing it altogether made things like
+     * c<$tied{foo};> in void context no longer do get magic, which some
+     * code relied on. Also, delayed triggering of magic on @+ and friends
+     * meant the original regex may be out of scope by now. So as a
+     * compromise, do the get magic here. (The MGf_GSKIP flag will stop it
+     * being called too many times). */
+    if (!lval && SvRMAGICAL(hv) && SvGMAGICAL(sv))
+       mg_get(sv);
     PUSHs(sv);
     RETURN;
 }
@@ -1859,13 +1879,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)
@@ -1896,7 +1910,7 @@ PP(pp_leave)
     }
     PL_curpm = newpm;  /* Don't pop $1 et al till now */
 
-    LEAVE;
+    LEAVE_with_name("block");
 
     RETURN;
 }
@@ -2068,9 +2082,11 @@ PP(pp_subst)
     bool is_cow;
 #endif
     SV *nsv = NULL;
-
     /* known replacement string? */
     register SV *dstr = (pm->op_pmflags & PMf_CONST) ? POPs : NULL;
+
+    PERL_ASYNC_CHECK();
+
     if (PL_op->op_flags & OPf_STACKED)
        TARG = POPs;
     else if (PL_op->op_private & OPpTARGET_MY)
@@ -2096,7 +2112,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);
@@ -2383,14 +2399,14 @@ PP(pp_grepwhile)
     if (SvTRUEx(POPs))
        PL_stack_base[PL_markstack_ptr[-1]++] = PL_stack_base[*PL_markstack_ptr];
     ++*PL_markstack_ptr;
-    LEAVE;                                     /* exit inner scope */
+    LEAVE_with_name("grep_item");                                      /* exit inner scope */
 
     /* All done yet? */
     if (PL_stack_base + *PL_markstack_ptr > SP) {
        I32 items;
        const I32 gimme = GIMME_V;
 
-       LEAVE;                                  /* exit outer scope */
+       LEAVE_with_name("grep");                                        /* exit outer scope */
        (void)POPMARK;                          /* pop src */
        items = --*PL_markstack_ptr - PL_markstack_ptr[-1];
        (void)POPMARK;                          /* pop dst */
@@ -2413,7 +2429,7 @@ PP(pp_grepwhile)
     else {
        SV *src;
 
-       ENTER;                                  /* enter inner scope */
+       ENTER_with_name("grep_item");                                   /* enter inner scope */
        SAVEVPTR(PL_curpm);
 
        src = PL_stack_base[*PL_markstack_ptr];
@@ -2421,7 +2437,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);
     }
@@ -2668,7 +2684,7 @@ PP(pp_entersub)
     case SVt_PVGV:
        if (!isGV_with_GP(sv))
            DIE(aTHX_ "Not a CODE reference");
-       if (!(cv = GvCVu((GV*)sv))) {
+       if (!(cv = GvCVu((const GV *)sv))) {
            HV *stash;
            cv = sv_2cv(sv, &stash, &gv, 0);
        }
@@ -2705,7 +2721,7 @@ PP(pp_entersub)
            if (!sym)
                DIE(aTHX_ PL_no_usym, "a subroutine");
            if (PL_op->op_private & HINT_STRICT_REFS)
-               DIE(aTHX_ PL_no_symref, sym, "a subroutine");
+               DIE(aTHX_ "Can't use string (\"%.32s\"%s) as a subroutine ref while \"strict refs\" in use", sym, len>32 ? "..." : "");
            cv = get_cvn_flags(sym, len, GV_ADD|SvUTF8(sv));
            break;
        }
@@ -2768,7 +2784,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");
@@ -2795,7 +2818,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 @_ */
@@ -2804,7 +2827,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;
@@ -2867,8 +2890,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 ) {
@@ -2904,9 +2929,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))
@@ -2917,6 +2944,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
@@ -2946,14 +2986,18 @@ 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);
     }
     sv = (svp ? *svp : &PL_sv_undef);
-    if (!lval && SvGMAGICAL(sv))       /* see note in pp_helem() */
-       sv = sv_mortalcopy(sv);
+    if (!lval && SvRMAGICAL(av) && SvGMAGICAL(sv)) /* see note in pp_helem() */
+       mg_get(sv);
     PUSHs(sv);
     RETURN;
 }
@@ -2966,17 +3010,17 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
     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);
@@ -3018,21 +3062,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;
 
@@ -3048,7 +3091,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 ||
@@ -3057,7 +3100,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");
            }
@@ -3072,16 +3116,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 
                     && isGV_with_GP(ob)
-                    && (ob = (SV*)GvIO((GV*)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);
@@ -3097,20 +3142,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);
+               return MUTABLE_SV(GvCV(gv));
        }
     }
 
-    gv = gv_fetchmethod_flags(stash ? stash : MUTABLE_HV(packsv), name,
+    gv = gv_fetchmethod_flags(stash ? stash : MUTABLE_HV(packsv),
+                             SvPV_nolen_const(meth),
                              GV_AUTOLOAD | GV_CROAK);
 
     assert(gv);
 
-    return isGV(gv) ? (SV*)GvCV(gv) : (SV*)gv;
+    return isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv);
 }
 
 /*