This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 249f173..403d1fe 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1,7 +1,7 @@
-/*    op.c
+ /*    op.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, 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.
@@ -128,7 +128,7 @@ Perl_Slab_Alloc(pTHX_ int m, size_t sz)
 void
 Perl_Slab_Free(pTHX_ void *op)
 {
-    I32 ** const ptr = (I32 **) op;
+    I32 * const * const ptr = (I32 **) op;
     I32 * const slab = ptr[-1];
     assert( ptr-1 > (I32 **) slab );
     assert( ptr < ( (I32 **) slab + PERL_SLAB_SIZE) );
@@ -162,7 +162,7 @@ STATIC const char*
 S_gv_ename(pTHX_ GV *gv)
 {
     SV* const tmpsv = sv_newmortal();
-    gv_efullname3(tmpsv, gv, Nullch);
+    gv_efullname3(tmpsv, gv, NULL);
     return SvPV_nolen_const(tmpsv);
 }
 
@@ -209,22 +209,29 @@ PADOFFSET
 Perl_allocmy(pTHX_ char *name)
 {
     PADOFFSET off;
+    const bool is_our = (PL_in_my == KEY_our);
 
     /* complain about "my $_" etc etc */
-    if (!(PL_in_my == KEY_our ||
+    if (*name &&
+       !(is_our ||
          isALPHA(name[1]) ||
          (USE_UTF8_IN_NAMES && UTF8_IS_START(name[1])) ||
-         (name[1] == '_' && (int)strlen(name) > 2)))
+         (name[1] == '_' && name[2])))
     {
+       /* name[2] is true if strlen(name) > 2  */
        if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) {
            /* 1999-02-27 mjd@plover.com */
            char *p;
            p = strchr(name, '\0');
            /* The next block assumes the buffer is at least 205 chars
               long.  At present, it's always at least 256 chars. */
-           if (p-name > 200) {
-               strcpy(name+200, "...");
-               p = name+199;
+           if (p - name > 200) {
+#ifdef HAS_STRLCPY
+               strlcpy(name + 200, "...", 4);
+#else
+               strcpy(name + 200, "...");
+#endif
+               p = name + 199;
            }
            else {
                p[1] = '\0';
@@ -238,24 +245,21 @@ Perl_allocmy(pTHX_ char *name)
        yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name));
     }
     /* check for duplicate declaration */
-    pad_check_dup(name,
-               (bool)(PL_in_my == KEY_our),
-               (PL_curstash ? PL_curstash : PL_defstash)
-    );
+    pad_check_dup(name, is_our, (PL_curstash ? PL_curstash : PL_defstash));
 
     if (PL_in_my_stash && *name != '$') {
        yyerror(Perl_form(aTHX_
                    "Can't declare class for non-scalar %s in \"%s\"",
-                    name, PL_in_my == KEY_our ? "our" : "my"));
+                    name, is_our ? "our" : "my"));
     }
 
     /* allocate a spare slot and store the name in that slot */
 
     off = pad_add_name(name,
                    PL_in_my_stash,
-                   (PL_in_my == KEY_our 
+                   (is_our
                        ? (PL_curstash ? PL_curstash : PL_defstash)
-                       : Nullhv
+                       : NULL
                    ),
                    0 /*  not fake */
     );
@@ -281,7 +285,7 @@ Perl_find_threadsv(pTHX_ const char *name)
     if (svp)
        MUTEX_UNLOCK(&thr->mutex);
     else {
-       SV *sv = NEWSV(0, 0);
+       SV *sv = newSV(0);
        av_store(thr->threadsv, key, sv);
        thr->threadsvp = AvARRAY(thr->threadsv);
        MUTEX_UNLOCK(&thr->mutex);
@@ -417,14 +421,14 @@ Perl_op_clear(pTHX_ OP *o)
            }
 #else
            SvREFCNT_dec(cSVOPo->op_sv);
-           cSVOPo->op_sv = Nullsv;
+           cSVOPo->op_sv = NULL;
 #endif
        }
        break;
     case OP_METHOD_NAMED:
     case OP_CONST:
        SvREFCNT_dec(cSVOPo->op_sv);
-       cSVOPo->op_sv = Nullsv;
+       cSVOPo->op_sv = NULL;
 #ifdef USE_ITHREADS
        /** Bug #15654
          Even if op_clear does a pad_free for the target of the op,
@@ -448,11 +452,11 @@ Perl_op_clear(pTHX_ OP *o)
     case OP_TRANS:
        if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) {
            SvREFCNT_dec(cSVOPo->op_sv);
-           cSVOPo->op_sv = Nullsv;
+           cSVOPo->op_sv = NULL;
        }
        else {
            Safefree(cPVOPo->op_pv);
-           cPVOPo->op_pv = Nullch;
+           cPVOPo->op_pv = NULL;
        }
        break;
     case OP_SUBST:
@@ -473,8 +477,8 @@ Perl_op_clear(pTHX_ OP *o)
     case OP_QR:
 clear_pmop:
        {
-           HV *pmstash = PmopSTASH(cPMOPo);
-           if (pmstash && SvREFCNT(pmstash)) {
+           HV * const pmstash = PmopSTASH(cPMOPo);
+           if (pmstash && !SvIS_FREED(pmstash)) {
                PMOP *pmop = HvPMROOT(pmstash);
                PMOP *lastpmop = NULL;
                while (pmop) {
@@ -536,6 +540,8 @@ S_cop_free(pTHX_ COP* cop)
        SvREFCNT_dec(cop->cop_io);
 #endif
     }
+    if (PL_curcop == cop)
+       PL_curcop = NULL;
 }
 
 void
@@ -568,19 +574,25 @@ Perl_op_refcnt_unlock(pTHX)
 OP *
 Perl_linklist(pTHX_ OP *o)
 {
+    OP *first;
 
     if (o->op_next)
        return o->op_next;
 
     /* establish postfix order */
-    if (cUNOPo->op_first) {
+    first = cUNOPo->op_first;
+    if (first) {
         register OP *kid;
-       o->op_next = LINKLIST(cUNOPo->op_first);
-       for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) {
-           if (kid->op_sibling)
+       o->op_next = LINKLIST(first);
+       kid = first;
+       for (;;) {
+           if (kid->op_sibling) {
                kid->op_next = LINKLIST(kid->op_sibling);
-           else
+               kid = kid->op_sibling;
+           } else {
                kid->op_next = o;
+               break;
+           }
        }
     }
     else
@@ -622,7 +634,7 @@ Perl_scalar(pTHX_ OP *o)
     OP *kid;
 
     /* assumes no premature commitment */
-    if (!o || (o->op_flags & OPf_WANT) || PL_error_count
+    if (!o || PL_error_count || (o->op_flags & OPf_WANT)
         || o->op_type == OP_RETURN)
     {
        return o;
@@ -690,7 +702,7 @@ OP *
 Perl_scalarvoid(pTHX_ OP *o)
 {
     OP *kid;
-    const char* useless = 0;
+    const char* useless = NULL;
     SV* sv;
     U8 want;
 
@@ -836,9 +848,10 @@ Perl_scalarvoid(pTHX_ OP *o)
                      built upon these three nroff macros being used in
                      void context. The pink camel has the details in
                      the script wrapman near page 319. */
-                   if (strnEQ(SvPVX_const(sv), "di", 2) ||
-                       strnEQ(SvPVX_const(sv), "ds", 2) ||
-                       strnEQ(SvPVX_const(sv), "ig", 2))
+                   const char * const maybe_macro = SvPVX_const(sv);
+                   if (strnEQ(maybe_macro, "di", 2) ||
+                       strnEQ(maybe_macro, "ds", 2) ||
+                       strnEQ(maybe_macro, "ig", 2))
                            useless = 0;
                }
            }
@@ -856,6 +869,16 @@ Perl_scalarvoid(pTHX_ OP *o)
        o->op_ppaddr = PL_ppaddr[OP_PREDEC];
        break;
 
+    case OP_I_POSTINC:
+       o->op_type = OP_I_PREINC;       /* pre-increment is faster */
+       o->op_ppaddr = PL_ppaddr[OP_I_PREINC];
+       break;
+
+    case OP_I_POSTDEC:
+       o->op_type = OP_I_PREDEC;       /* pre-decrement is faster */
+       o->op_ppaddr = PL_ppaddr[OP_I_PREDEC];
+       break;
+
     case OP_OR:
     case OP_AND:
     case OP_COND_EXPR:
@@ -1069,6 +1092,10 @@ Perl_mod(pTHX_ OP *o, I32 type)
        if ((type == OP_UNDEF || type == OP_REFGEN) &&
            !(o->op_flags & OPf_STACKED)) {
            o->op_type = OP_RV2CV;              /* entersub => rv2cv */
+           /* The default is to set op_private to the number of children,
+              which for a UNOP such as RV2CV is always 1. And w're using
+              the bit for a flag in RV2CV, so we need it clear.  */
+           o->op_private &= ~1;
            o->op_ppaddr = PL_ppaddr[OP_RV2CV];
            assert(cUNOPo->op_first->op_type == OP_NULL);
            op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */
@@ -1114,6 +1141,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
                         newop->op_next = (OP*)newop;
                        kid->op_sibling = (OP*)newop;
                        newop->op_private |= OPpLVAL_INTRO;
+                       newop->op_private &= ~1;
                        break;
                    }
 
@@ -1148,6 +1176,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
                    okid->op_targ = 0;
                    okid->op_ppaddr = PL_ppaddr[OP_RV2CV];
                    okid->op_private |= OPpLVAL_INTRO;
+                   okid->op_private &= ~1;
                    break;
                }
 
@@ -1437,7 +1466,7 @@ Perl_refkids(pTHX_ OP *o, I32 type)
 }
 
 OP *
-Perl_ref(pTHX_ OP *o, I32 type)
+Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref)
 {
     OP *kid;
 
@@ -1453,17 +1482,18 @@ Perl_ref(pTHX_ OP *o, I32 type)
            assert(cUNOPo->op_first->op_type == OP_NULL);
            op_null(((LISTOP*)cUNOPo->op_first)->op_first);     /* disable pushmark */
            o->op_flags |= OPf_SPECIAL;
+           o->op_private &= ~1;
        }
        break;
 
     case OP_COND_EXPR:
        for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling)
-           ref(kid, type);
+           doref(kid, type, set_op_ref);
        break;
     case OP_RV2SV:
        if (type == OP_DEFINED)
            o->op_flags |= OPf_SPECIAL;         /* don't create GV */
-       ref(cUNOPo->op_first, o->op_type);
+       doref(cUNOPo->op_first, o->op_type, set_op_ref);
        /* FALL THROUGH */
     case OP_PADSV:
        if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) {
@@ -1474,34 +1504,38 @@ Perl_ref(pTHX_ OP *o, I32 type)
        }
        break;
 
+#ifdef USE_5005THREADS
     case OP_THREADSV:
        o->op_flags |= OPf_MOD;         /* XXX ??? */
        break;
+#endif
 
     case OP_RV2AV:
     case OP_RV2HV:
-       o->op_flags |= OPf_REF;
+       if (set_op_ref)
+           o->op_flags |= OPf_REF;
        /* FALL THROUGH */
     case OP_RV2GV:
        if (type == OP_DEFINED)
            o->op_flags |= OPf_SPECIAL;         /* don't create GV */
-       ref(cUNOPo->op_first, o->op_type);
+       doref(cUNOPo->op_first, o->op_type, set_op_ref);
        break;
 
     case OP_PADAV:
     case OP_PADHV:
-       o->op_flags |= OPf_REF;
+       if (set_op_ref)
+           o->op_flags |= OPf_REF;
        break;
 
     case OP_SCALAR:
     case OP_NULL:
        if (!(o->op_flags & OPf_KIDS))
            break;
-       ref(cBINOPo->op_first, type);
+       doref(cBINOPo->op_first, type, set_op_ref);
        break;
     case OP_AELEM:
     case OP_HELEM:
-       ref(cBINOPo->op_first, o->op_type);
+       doref(cBINOPo->op_first, o->op_type, set_op_ref);
        if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) {
            o->op_private |= (type == OP_RV2AV ? OPpDEREF_AV
                              : type == OP_RV2HV ? OPpDEREF_HV
@@ -1512,11 +1546,13 @@ Perl_ref(pTHX_ OP *o, I32 type)
 
     case OP_SCOPE:
     case OP_LEAVE:
+       set_op_ref = FALSE;
+       /* FALL THROUGH */
     case OP_ENTER:
     case OP_LIST:
        if (!(o->op_flags & OPf_KIDS))
            break;
-       ref(cLISTOPo->op_last, type);
+       doref(cLISTOPo->op_last, type, set_op_ref);
        break;
     default:
        break;
@@ -1528,21 +1564,22 @@ Perl_ref(pTHX_ OP *o, I32 type)
 STATIC OP *
 S_dup_attrlist(pTHX_ OP *o)
 {
-    OP *rop = Nullop;
+    OP *rop;
 
     /* An attrlist is either a simple OP_CONST or an OP_LIST with kids,
      * where the first kid is OP_PUSHMARK and the remaining ones
      * are OP_CONST.  We need to push the OP_CONST values.
      */
     if (o->op_type == OP_CONST)
-       rop = newSVOP(OP_CONST, o->op_flags, SvREFCNT_inc(cSVOPo->op_sv));
+       rop = newSVOP(OP_CONST, o->op_flags, SvREFCNT_inc_NN(cSVOPo->op_sv));
     else {
        assert((o->op_type == OP_LIST) && (o->op_flags & OPf_KIDS));
+       rop = Nullop;
        for (o = cLISTOPo->op_first; o; o=o->op_sibling) {
            if (o->op_type == OP_CONST)
                rop = append_elem(OP_LIST, rop,
                                  newSVOP(OP_CONST, o->op_flags,
-                                         SvREFCNT_inc(cSVOPo->op_sv)));
+                                         SvREFCNT_inc_NN(cSVOPo->op_sv)));
        }
     }
     return rop;
@@ -1566,19 +1603,17 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
 
     if (for_my) {
        /* Don't force the C<use> if we don't need it. */
-       SV **svp = hv_fetch(GvHVn(PL_incgv), ATTRSMODULE_PM,
-                      sizeof(ATTRSMODULE_PM)-1, 0);
+       SV * const * const svp = hv_fetchs(GvHVn(PL_incgv), ATTRSMODULE_PM, FALSE);
        if (svp && *svp != &PL_sv_undef)
            ;           /* already in %INC */
        else
            Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
-                            newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
-                            Nullsv);
+                            newSVpvs(ATTRSMODULE), NULL);
     }
     else {
        Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
-                        newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
-                        Nullsv,
+                        newSVpvs(ATTRSMODULE),
+                        NULL,
                         prepend_elem(OP_LIST,
                                      newSVOP(OP_CONST, 0, stashsv),
                                      prepend_elem(OP_LIST,
@@ -1606,7 +1641,7 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp)
     apply_attrs(stash, PAD_SV(target->op_targ), attrs, TRUE);
 
     /* Need package name for method call. */
-    pack = newSVOP(OP_CONST, 0, newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1));
+    pack = newSVOP(OP_CONST, 0, newSVpvs(ATTRSMODULE));
 
     /* Build up the real arg-list. */
     if (stash)
@@ -1623,14 +1658,7 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp)
                                    dup_attrlist(attrs)));
 
     /* Fake up a method call to import */
-    meth = newSVpvn("import", 6);
-    (void)SvUPGRADE(meth, SVt_PVIV);
-    (void)SvIOK_on(meth);
-    {
-       U32 hash;
-       PERL_HASH(hash, SvPVX_const(meth), SvCUR(meth));
-       SvUV_set(meth, hash);
-    }
+    meth = newSVpvs("import");
     imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL|OPf_WANT_VOID,
                   append_elem(OP_LIST,
                               prepend_elem(OP_LIST, pack, list(arg)),
@@ -1680,8 +1708,8 @@ Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv,
     }
 
     Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
-                     newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
-                     Nullsv, prepend_elem(OP_LIST,
+                    newSVpvs(ATTRSMODULE),
+                     NULL, prepend_elem(OP_LIST,
                                  newSVOP(OP_CONST, 0, newSVpv(stashpv,0)),
                                  prepend_elem(OP_LIST,
                                               newSVOP(OP_CONST, 0,
@@ -1711,9 +1739,9 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
            yyerror(Perl_form(aTHX_ "Can't declare %s in %s",
                        OP_DESC(o), PL_in_my == KEY_our ? "our" : "my"));
        } else if (attrs) {
-           GV *gv = cGVOPx_gv(cUNOPo->op_first);
+           GV * const gv = cGVOPx_gv(cUNOPo->op_first);
            PL_in_my = FALSE;
-           PL_in_my_stash = Nullhv;
+           PL_in_my_stash = NULL;
            apply_attrs(GvSTASH(gv),
                        (type == OP_RV2SV ? GvSV(gv) :
                         type == OP_RV2AV ? (SV*)GvAV(gv) :
@@ -1737,7 +1765,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
        HV *stash;
 
        PL_in_my = FALSE;
-       PL_in_my_stash = Nullhv;
+       PL_in_my_stash = NULL;
 
        /* check for C<my Dog $spot> when deciding package */
        stash = PAD_COMPNAME_TYPE(o->op_targ);
@@ -1753,7 +1781,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
 OP *
 Perl_my_attrs(pTHX_ OP *o, OP *attrs)
 {
-    OP *rops = Nullop;
+    OP *rops;
     int maybe_scalar = 0;
 
 /* [perl #17376]: this appears to be premature, and results in code such as
@@ -1768,6 +1796,7 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs)
 #endif
     if (attrs)
        SAVEFREEOP(attrs);
+    rops = Nullop;
     o = my_kid(o, attrs, &rops);
     if (rops) {
        if (maybe_scalar && o->op_type == OP_PADSV) {
@@ -1778,7 +1807,7 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs)
            o = append_list(OP_LIST, (LISTOP*)o, (LISTOP*)rops);
     }
     PL_in_my = FALSE;
-    PL_in_my_stash = Nullhv;
+    PL_in_my_stash = NULL;
     return o;
 }
 
@@ -1801,15 +1830,16 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
 {
     OP *o;
 
-    if (ckWARN(WARN_MISC) &&
-      (left->op_type == OP_RV2AV ||
+    if ( (left->op_type == OP_RV2AV ||
        left->op_type == OP_RV2HV ||
        left->op_type == OP_PADAV ||
-       left->op_type == OP_PADHV)) {
-      const char *desc = PL_op_desc[(right->op_type == OP_SUBST ||
+       left->op_type == OP_PADHV)
+       && ckWARN(WARN_MISC))
+    {
+      const char * const desc = PL_op_desc[(right->op_type == OP_SUBST ||
                             right->op_type == OP_TRANS)
                            ? right->op_type : OP_MATCH];
-      const char *sample = ((left->op_type == OP_RV2AV ||
+      const char * const sample = ((left->op_type == OP_RV2AV ||
                             left->op_type == OP_PADAV)
                            ? "@array" : "%hash");
       Perl_warner(aTHX_ packWARN(WARN_MISC),
@@ -1869,8 +1899,15 @@ Perl_scope(pTHX_ OP *o)
            o->op_type = OP_SCOPE;
            o->op_ppaddr = PL_ppaddr[OP_SCOPE];
            kid = ((LISTOP*)o)->op_first;
-           if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE)
+           if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
                op_null(kid);
+
+               /* The following deals with things like 'do {1 for 1}' */
+               kid = kid->op_sibling;
+               if (kid &&
+                   (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE))
+                   op_null(kid);
+           }
        }
        else
            o = newLISTOP(OP_SCOPE, 0, o, Nullop);
@@ -1878,13 +1915,6 @@ Perl_scope(pTHX_ OP *o)
     return o;
 }
 
-/* XXX kept for BINCOMPAT only */
-void
-Perl_save_hints(pTHX)
-{
-    Perl_croak(aTHX_ "internal error: obsolete function save_hints() called");
-}
-
 int
 Perl_block_start(pTHX_ int full)
 {
@@ -1912,7 +1942,7 @@ OP*
 Perl_block_end(pTHX_ I32 floor, OP *seq)
 {
     const int needblockscope = PL_hints & HINT_BLOCK_SCOPE;
-    OP* retval = scalarseq(seq);
+    OP* const retval = scalarseq(seq);
     /* If there were syntax errors, don't try to close a block */
     if (PL_yynerrs) return retval;
     LEAVE_SCOPE(floor);
@@ -1927,7 +1957,7 @@ STATIC OP *
 S_newDEFSVOP(pTHX)
 {
 #ifdef USE_5005THREADS
-    OP *o = newOP(OP_THREADSV, 0);
+    OP *const o = newOP(OP_THREADSV, 0);
     o->op_targ = find_threadsv("_");
     return o;
 #else
@@ -1968,7 +1998,7 @@ Perl_newPROG(pTHX_ OP *o)
 
        /* Register with debugger */
        if (PERLDB_INTER) {
-           CV *cv = get_cv("DB::postponed", FALSE);
+           CV * const cv = get_cv("DB::postponed", FALSE);
            if (cv) {
                dSP;
                PUSHMARK(SP);
@@ -1992,8 +2022,8 @@ Perl_localize(pTHX_ OP *o, I32 lex)
        ;
 #endif
     else {
-       if (ckWARN(WARN_PARENTHESIS)
-           && PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',')
+       if ( PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ','
+           && ckWARN(WARN_PARENTHESIS))
        {
            char *s = PL_bufptr;
            bool sigil = FALSE;
@@ -2028,7 +2058,7 @@ Perl_localize(pTHX_ OP *o, I32 lex)
     else
        o = mod(o, OP_NULL);            /* a bit kludgey */
     PL_in_my = FALSE;
-    PL_in_my_stash = Nullhv;
+    PL_in_my_stash = NULL;
     return o;
 }
 
@@ -2036,24 +2066,38 @@ OP *
 Perl_jmaybe(pTHX_ OP *o)
 {
     if (o->op_type == OP_LIST) {
-       OP *o2;
 #ifdef USE_5005THREADS
-       o2 = newOP(OP_THREADSV, 0);
+       OP * const o2 = newOP(OP_THREADSV, 0);
        o2->op_targ = find_threadsv(";");
 #else
-       o2 = newSVREF(newGVOP(OP_GV, 0, gv_fetchpv(";", TRUE, SVt_PV))),
+       OP * const o2
+           = newSVREF(newGVOP(OP_GV, 0, gv_fetchpvs(";", GV_ADD|GV_NOTQUAL,
+                                                    SVt_PV)));
 #endif /* USE_5005THREADS */
        o = convert(OP_JOIN, 0, prepend_elem(OP_LIST, o2, o));
     }
     return o;
 }
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+STATIC void *
+S_vcall_runops(pTHX_ va_list args)
+{
+    CALLRUNOPS(aTHX);
+    return NULL;
+}
+#endif
+
 OP *
 Perl_fold_constants(pTHX_ register OP *o)
 {
     register OP *curop;
     I32 type = o->op_type;
     SV *sv;
+    int ret = 0;
+    I32 oldscope;
+    OP *old_next;
+    dJMPENV;
 
     if (PL_opargs[type] & OA_RETSCALAR)
        scalar(o);
@@ -2077,7 +2121,6 @@ Perl_fold_constants(pTHX_ register OP *o)
        /* XXX might want a ck_negate() for this */
        cUNOPo->op_first->op_private &= ~OPpCONST_STRICT;
        break;
-    case OP_SPRINTF:
     case OP_UCFIRST:
     case OP_LCFIRST:
     case OP_UC:
@@ -2108,22 +2151,84 @@ Perl_fold_constants(pTHX_ register OP *o)
     }
 
     curop = LINKLIST(o);
+    old_next = o->op_next;
     o->op_next = 0;
     PL_op = curop;
-    CALLRUNOPS(aTHX);
-    sv = *(PL_stack_sp--);
-    if (o->op_targ && sv == PAD_SV(o->op_targ))        /* grab pad temp? */
-       pad_swipe(o->op_targ,  FALSE);
-    else if (SvTEMP(sv)) {                     /* grab mortal temp? */
-       (void)SvREFCNT_inc(sv);
-       SvTEMP_off(sv);
+
+    oldscope = PL_scopestack_ix;
+
+       /* we're trying to emulate pp_entertry() here */
+       {
+           register PERL_CONTEXT *cx;
+           const I32 gimme = GIMME_V;
+       
+           ENTER;
+           SAVETMPS;
+       
+           PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), PL_stack_sp);
+           PUSHEVAL(cx, 0, 0);
+           PL_eval_root = PL_op;             /* Only needed so that goto works right. */
+       
+           PL_in_eval = EVAL_INEVAL;
+           sv_setpvn(ERRSV,"",0);
+       }
+
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vcall_runops));
+#else
+    JMPENV_PUSH(ret);
+#endif
+    switch (ret) {
+    case 0:
+#ifndef PERL_FLEXIBLE_EXCEPTIONS
+       CALLRUNOPS(aTHX);
+#endif
+       sv = *(PL_stack_sp--);
+       if (o->op_targ && sv == PAD_SV(o->op_targ))     /* grab pad temp? */
+           pad_swipe(o->op_targ,  FALSE);
+       else if (SvTEMP(sv)) {                  /* grab mortal temp? */
+           SvREFCNT_inc_simple_void(sv);
+           SvTEMP_off(sv);
+       }
+       break;
+    case 3:
+       /* Something tried to die.  Abandon constant folding.  */
+       /* Pretend the error never happened.  */
+       sv_setpvn(ERRSV,"",0);
+       o->op_next = old_next;
+       break;
+    default:
+       JMPENV_POP;
+       /* Don't expect 1 (setjmp failed) or 2 (something called my_exit)  */
+       Perl_croak(aTHX_ "panic: fold_constants JMPENV_PUSH returned %d", ret);
+    }
+
+    JMPENV_POP;
+    if (PL_scopestack_ix > oldscope) {
+       SV **newsp;
+       PMOP *newpm;
+       I32 gimme;
+       register PERL_CONTEXT *cx;
+       I32 optype;
+       
+       POPBLOCK(cx,newpm);
+           POPEVAL(cx);
+           PL_curpm = newpm;
+           LEAVE;
+           PERL_UNUSED_VAR(newsp);
+           PERL_UNUSED_VAR(gimme);
+           PERL_UNUSED_VAR(optype);
     }
+
+    if (ret)
+       goto nope;
+
     op_free(o);
     if (type == OP_RV2GV)
        return newGVOP(OP_GV, 0, (GV*)sv);
     return newSVOP(OP_CONST, 0, sv);
 
 nope:
+ nope:
     return o;
 }
 
@@ -2143,6 +2248,8 @@ Perl_gen_constant_list(pTHX_ register OP *o)
     pp_pushmark();
     CALLRUNOPS(aTHX);
     PL_op = curop;
+    assert (!(curop->op_flags & OPf_SPECIAL));
+    assert(curop->op_type == OP_RANGE);
     pp_anonlist();
     PL_tmps_floor = oldtmps_floor;
 
@@ -2152,7 +2259,7 @@ Perl_gen_constant_list(pTHX_ register OP *o)
     o->op_flags |= OPf_PARENS; /* and flatten \(1..2,3) */
     o->op_seq = 0;             /* needs to be revisited in peep() */
     curop = ((UNOP*)o)->op_first;
-    ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, SvREFCNT_inc(*PL_stack_sp--));
+    ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, SvREFCNT_inc_NN(*PL_stack_sp--));
     op_free(curop);
     linklist(o);
     return list(o);
@@ -2301,8 +2408,7 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last)
     listop->op_first = first;
     listop->op_last = last;
     if (type == OP_LIST) {
-       OP* pushop;
-       pushop = newOP(OP_PUSHMARK, 0);
+       OP* const pushop = newOP(OP_PUSHMARK, 0);
        pushop->op_sibling = first;
        listop->op_first = pushop;
        listop->op_flags |= OPf_KIDS;
@@ -2345,7 +2451,7 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first)
     unop->op_type = (OPCODE)type;
     unop->op_ppaddr = PL_ppaddr[type];
     unop->op_first = first;
-    unop->op_flags = flags | OPf_KIDS;
+    unop->op_flags = (U8)(flags | OPf_KIDS);
     unop->op_private = (U8)(1 | (flags >> 8));
     unop = (UNOP*) CHECKOP(type, unop);
     if (unop->op_next)
@@ -2366,7 +2472,7 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last)
     binop->op_type = (OPCODE)type;
     binop->op_ppaddr = PL_ppaddr[type];
     binop->op_first = first;
-    binop->op_flags = flags | OPf_KIDS;
+    binop->op_flags = (U8)(flags | OPf_KIDS);
     if (!last) {
        last = first;
        binop->op_private = (U8)(1 | (flags >> 8));
@@ -2410,16 +2516,13 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
     const U8 *r = (U8*)SvPV_const(rstr, rlen);
     register I32 i;
     register I32 j;
-    I32 del;
-    I32 complement;
-    I32 squash;
     I32 grows = 0;
     register short *tbl;
 
+    const I32 complement = o->op_private & OPpTRANS_COMPLEMENT;
+    const I32 squash     = o->op_private & OPpTRANS_SQUASH;
+    I32 del              = o->op_private & OPpTRANS_DELETE;
     PL_hints |= HINT_BLOCK_SCOPE;
-    complement = o->op_private & OPpTRANS_COMPLEMENT;
-    del                = o->op_private & OPpTRANS_DELETE;
-    squash     = o->op_private & OPpTRANS_SQUASH;
 
     if (SvUTF8(tstr))
         o->op_private |= OPpTRANS_FROM_UTF;
@@ -2428,8 +2531,8 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
         o->op_private |= OPpTRANS_TO_UTF;
 
     if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) {
-       SV* listsv = newSVpvn("# comment\n",10);
-       SV* transv = 0;
+       SV* const listsv = newSVpvs("# comment\n");
+       SV* transv = NULL;
        const U8* tend = t + tlen;
        const U8* rend = r + rlen;
        STRLEN ulen;
@@ -2445,8 +2548,8 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        I32 bits;
        I32 havefinal = 0;
        U32 final = 0;
-       I32 from_utf    = o->op_private & OPpTRANS_FROM_UTF;
-       I32 to_utf      = o->op_private & OPpTRANS_TO_UTF;
+       const I32 from_utf  = o->op_private & OPpTRANS_FROM_UTF;
+       const I32 to_utf    = o->op_private & OPpTRANS_TO_UTF;
        U8* tsave = NULL;
        U8* rsave = NULL;
 
@@ -2473,7 +2576,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            UV nextmin = 0;
            Newx(cp, 2*tlen, UV);
            i = 0;
-           transv = newSVpvn("",0);
+           transv = newSVpvs("");
            while (t < tend) {
                cp[2*i] = utf8n_to_uvuni((U8 *)t, tend-t, &ulen, 0);
                t += ulen;
@@ -2615,8 +2718,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        Safefree(cPVOPo->op_pv);
        cSVOPo->op_sv = (SV*)swash_init("utf8", "", listsv, bits, none);
        SvREFCNT_dec(listsv);
-       if (transv)
-           SvREFCNT_dec(transv);
+       SvREFCNT_dec(transv);
 
        if (!del && havefinal && rlen)
            (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
@@ -2625,10 +2727,8 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        if (grows)
            o->op_private |= OPpTRANS_GROWS;
 
-       if (tsave)
-           Safefree(tsave);
-       if (rsave)
-           Safefree(rsave);
+       Safefree(tsave);
+       Safefree(rsave);
 
        op_free(expr);
        op_free(repl);
@@ -2667,7 +2767,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
                j = rlen - 1;
            else
                cPVOPo->op_pv = (char*)Renew(tbl, 0x101+rlen-j, short);
-           tbl[0x100] = rlen - j;
+           tbl[0x100] = (short)(rlen - j);
            for (i=0; i < (I32)rlen - j; i++)
                tbl[0x101+i] = r[j+i];
        }
@@ -2725,19 +2825,16 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags)
     pmop->op_pmflags = pmop->op_pmpermflags;
 
 #ifdef USE_ITHREADS
-    {
-        SV* repointer;
-        if(av_len((AV*) PL_regex_pad[0]) > -1) {
-           repointer = av_pop((AV*)PL_regex_pad[0]);
-            pmop->op_pmoffset = SvIV(repointer);
-           SvREPADTMP_off(repointer);
-           sv_setiv(repointer,0);
-        } else {
-            repointer = newSViv(0);
-            av_push(PL_regex_padav,SvREFCNT_inc(repointer));
-            pmop->op_pmoffset = av_len(PL_regex_padav);
-            PL_regex_pad = AvARRAY(PL_regex_padav);
-        }
+    if (av_len((AV*) PL_regex_pad[0]) > -1) {
+       SV * const repointer = av_pop((AV*)PL_regex_pad[0]);
+       pmop->op_pmoffset = SvIV(repointer);
+       SvREPADTMP_off(repointer);
+       sv_setiv(repointer,0);
+    } else {
+       SV * const repointer = newSViv(0);
+       av_push(PL_regex_padav, SvREFCNT_inc_simple_NN(repointer));
+       pmop->op_pmoffset = av_len(PL_regex_padav);
+       PL_regex_pad = AvARRAY(PL_regex_padav);
     }
 #endif
 
@@ -2766,7 +2863,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
 
     if (expr->op_type == OP_CONST) {
        STRLEN plen;
-       SV *pat = ((SVOP*)expr)->op_sv;
+       SV * const pat = ((SVOP*)expr)->op_sv;
        const char *p = SvPV_const(pat, plen);
        if ((o->op_flags & OPf_SPECIAL) && (*p == ' ' && p[1] == '\0')) {
            U32 was_readonly = SvREADONLY(pat);
@@ -2829,7 +2926,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
     if (repl) {
        OP *curop;
        if (pm->op_pmflags & PMf_EVAL) {
-           curop = 0;
+           curop = NULL;
            if (CopLINE(PL_curcop) < (line_t)PL_multi_end)
                CopLINE_set(PL_curcop, (line_t)PL_multi_end);
        }
@@ -2844,7 +2941,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
        else if (repl->op_type == OP_CONST)
            curop = repl;
        else {
-           OP *lastop = 0;
+           OP *lastop = NULL;
            for (curop = LINKLIST(repl); curop!=repl; curop = LINKLIST(curop)) {
                if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
 #ifdef USE_5005THREADS
@@ -2855,7 +2952,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
                    }
 #else
                    if (curop->op_type == OP_GV) {
-                       GV *gv = cGVOPx_gv(curop);
+                       GV * const gv = cGVOPx_gv(curop);
                        repl_has_vars = 1;
                        if (strchr("&`'123456789+-\016\022", *GvENAME(gv)))
                            break;
@@ -2962,9 +3059,9 @@ Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv)
 #ifdef USE_ITHREADS
     if (gv)
        GvIN_PAD_on(gv);
-    return newPADOP(type, flags, SvREFCNT_inc(gv));
+    return newPADOP(type, flags, SvREFCNT_inc_simple(gv));
 #else
-    return newSVOP(type, flags, SvREFCNT_inc(gv));
+    return newSVOP(type, flags, SvREFCNT_inc_simple(gv));
 #endif
 }
 
@@ -3024,7 +3121,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
     veop = Nullop;
 
     if (version) {
-       SV *vesv = ((SVOP*)version)->op_sv;
+       SV * const vesv = ((SVOP*)version)->op_sv;
 
        if (!arg && !SvNIOKp(vesv)) {
            arg = version;
@@ -3040,7 +3137,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
            pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv));
 
            /* Fake up a method call to VERSION */
-           meth = newSVpvn("VERSION",7);
+           meth = newSVpvs("VERSION");
            sv_upgrade(meth, SVt_PVIV);
            (void)SvIOK_on(meth);
            {
@@ -3060,6 +3157,8 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
        imop = arg;             /* no import on explicit () */
     else if (SvNIOKp(((SVOP*)idop)->op_sv)) {
        imop = Nullop;          /* use 5.0; */
+       if (!aver)
+           idop->op_private |= OPpCONST_NOVER;
     }
     else {
        SV *meth;
@@ -3068,7 +3167,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
        pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv));
 
        /* Fake up a method call to import/unimport */
-       meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8);
+       meth = aver ? newSVpvs("import") : newSVpvs("unimport");
        (void)SvUPGRADE(meth, SVt_PVIV);
        (void)SvIOK_on(meth);
        {
@@ -3084,14 +3183,14 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
 
     /* Fake up the BEGIN {}, which does its thing immediately. */
     newATTRSUB(floor,
-       newSVOP(OP_CONST, 0, newSVpvn("BEGIN", 5)),
+       newSVOP(OP_CONST, 0, newSVpvs("BEGIN")),
        Nullop,
        Nullop,
        append_elem(OP_LINESEQ,
            append_elem(OP_LINESEQ,
-               newSTATEOP(0, Nullch, newUNOP(OP_REQUIRE, 0, idop)),
-               newSTATEOP(0, Nullch, veop)),
-           newSTATEOP(0, Nullch, imop) ));
+               newSTATEOP(0, NULL, newUNOP(OP_REQUIRE, 0, idop)),
+               newSTATEOP(0, NULL, veop)),
+           newSTATEOP(0, NULL, imop) ));
 
     /* The "did you use incorrect case?" warning used to be here.
      * The problem is that on case-insensitive filesystems one
@@ -3156,9 +3255,9 @@ Perl_load_module_nocontext(U32 flags, SV *name, SV *ver, ...)
 void
 Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
 {
-    OP *modname, *veop, *imop;
+    OP *veop, *imop;
 
-    modname = newSVOP(OP_CONST, 0, name);
+    OP * const modname = newSVOP(OP_CONST, 0, name);
     modname->op_private |= OPpCONST_BARE;
     if (ver) {
        veop = newSVOP(OP_CONST, 0, ver);
@@ -3196,12 +3295,22 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
 OP *
 Perl_dofile(pTHX_ OP *term)
 {
+    return dofile2(term, 0);
+}
+
+OP *
+Perl_dofile2(pTHX_ OP *term, I32 force_builtin)
+{
     OP *doop;
-    GV *gv;
+    GV *gv = Nullgv;
 
-    gv = gv_fetchpv("do", FALSE, SVt_PVCV);
-    if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv)))
-       gv = gv_fetchpv("CORE::GLOBAL::do", FALSE, SVt_PVCV);
+    if (!force_builtin) {
+       gv = gv_fetchpvs("do", GV_NOTQUAL, SVt_PVCV);
+       if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) {
+           GV * const * const gvp = (GV**)hv_fetchs(PL_globalstash, "do", FALSE);
+           gv = gvp ? *gvp : Nullgv;
+       }
+    }
 
     if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) {
        doop = ck_subr(newUNOP(OP_ENTERSUB, OPf_STACKED,
@@ -3284,23 +3393,15 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
        OP *curop;
 
        PL_modcount = 0;
-       PL_eval_start = right;  /* Grandfathering $[ assignment here.  Bletch.*/
+       /* Grandfathering $[ assignment here.  Bletch.*/
+       /* Only simple assignments like C<< ($[) = 1 >> are allowed */
+       PL_eval_start = (left->op_type == OP_CONST) ? right : 0;
        left = mod(left, OP_AASSIGN);
        if (PL_eval_start)
            PL_eval_start = 0;
-       else {
-           op_free(left);
-           op_free(right);
-           return Nullop;
-       }
-       /* optimise C<my @x = ()> to C<my @x>, and likewise for hashes */
-       if ((left->op_type == OP_PADAV || left->op_type == OP_PADHV)
-               && right->op_type == OP_STUB
-               && (left->op_private & OPpLVAL_INTRO))
-       {
-           op_free(right);
-           left->op_flags &= ~(OPf_REF|OPf_SPECIAL);
-           return left;
+       else if (left->op_type == OP_CONST) {
+           /* Result of assignment is always 1 (or we'd be dead already) */
+           return newSVOP(OP_CONST, 0, newSViv(1));
        }
        curop = list(force_list(left));
        o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop);
@@ -3386,7 +3487,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
            if ((tmpop = ((LISTOP*)right)->op_first) &&
                tmpop->op_type == OP_PUSHRE)
            {
-               PMOP *pm = (PMOP*)tmpop;
+               PMOP * const pm = (PMOP*)tmpop;
                if (left->op_type == OP_RV2AV &&
                    !(left->op_private & OPpLVAL_INTRO) &&
                    !(o->op_private & OPpASSIGN_COMMON) )
@@ -3398,7 +3499,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                        cPADOPx(tmpop)->op_padix = 0;   /* steal it */
 #else
                        pm->op_pmreplroot = (OP*)cSVOPx(tmpop)->op_sv;
-                       cSVOPx(tmpop)->op_sv = Nullsv;  /* steal it */
+                       cSVOPx(tmpop)->op_sv = NULL;    /* steal it */
 #endif
                        pm->op_pmflags |= PMf_ONCE;
                        tmpop = cUNOPo->op_first;       /* to list (nulled) */
@@ -3437,8 +3538,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
        if (PL_eval_start)
            PL_eval_start = 0;
        else {
-           op_free(o);
-           return Nullop;
+           o = newSVOP(OP_CONST, 0, newSViv(PL_compiling.cop_arybase));
        }
     }
     return o;
@@ -3497,7 +3597,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     CopSTASH_set(cop, PL_curstash);
 
     if (PERLDB_LINE && PL_curstash != PL_debstash) {
-       SV ** const svp = av_fetch(CopFILEAV(PL_curcop), (I32)CopLINE(cop), FALSE);
+       SV * const * const svp = av_fetch(CopFILEAVx(PL_curcop), (I32)CopLINE(cop), FALSE);
        if (svp && *svp != &PL_sv_undef ) {
            (void)SvIOK_on(*svp);
            SvIV_set(*svp, PTR2IV(cop));
@@ -3544,7 +3644,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
     if (first->op_type == OP_CONST) {
        if (first->op_private & OPpCONST_STRICT)
            no_bareword_allowed(first);
-       else if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE))
+       else if ((first->op_private & OPpCONST_BARE) && ckWARN(WARN_BAREWORD))
                Perl_warner(aTHX_ packWARN(WARN_BAREWORD), "Bareword found in conditional");
        if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
            op_free(first);
@@ -3561,7 +3661,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
            return first;
        }
     }
-    else if (ckWARN(WARN_MISC) && (first->op_flags & OPf_KIDS)) {
+    else if ((first->op_flags & OPf_KIDS) && ckWARN(WARN_MISC)) {
        const OP * const k1 = ((UNOP*)first)->op_first;
        const OP * const k2 = k1->op_sibling;
        OPCODE warnop = 0;
@@ -3610,7 +3710,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
     logop->op_type = (OPCODE)type;
     logop->op_ppaddr = PL_ppaddr[type];
     logop->op_first = first;
-    logop->op_flags = flags | OPf_KIDS;
+    logop->op_flags = (U8)(flags | OPf_KIDS);
     logop->op_other = LINKLIST(other);
     logop->op_private = (U8)(1 | (flags >> 8));
 
@@ -3660,7 +3760,7 @@ Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop)
     logop->op_type = OP_COND_EXPR;
     logop->op_ppaddr = PL_ppaddr[OP_COND_EXPR];
     logop->op_first = first;
-    logop->op_flags = flags | OPf_KIDS;
+    logop->op_flags = (U8)(flags | OPf_KIDS);
     logop->op_private = (U8)(1 | (flags >> 8));
     logop->op_other = LINKLIST(trueop);
     logop->op_next = LINKLIST(falseop);
@@ -3789,11 +3889,21 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block)
     return o;
 }
 
+
+OP *
+Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop,
+               I32 whileline, OP *expr, OP *block, OP *cont)
+{
+    return newWHILEOP8(flags, debuggable, loop, whileline, expr, block, cont,
+                      0);
+}
+
 OP *
-Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *block, OP *cont)
+Perl_newWHILEOP8(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32
+whileline, OP *expr, OP *block, OP *cont, I32 has_my)
 {
     OP *redo;
-    OP *next = 0;
+    OP *next = NULL;
     OP *listop;
     OP *o;
     U8 loopflags = 0;
@@ -3829,7 +3939,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
 
     if (!block)
        block = newOP(OP_NULL, 0);
-    else if (cont) {
+    else if (cont || has_my) {
        block = scope(block);
     }
 
@@ -3837,7 +3947,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
        next = LINKLIST(cont);
     }
     if (expr) {
-       OP *unstack = newOP(OP_UNSTACK, 0);
+       OP * const unstack = newOP(OP_UNSTACK, 0);
        if (!next)
            next = unstack;
        cont = append_elem(OP_LINESEQ, cont, unstack);
@@ -3908,6 +4018,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
            op_free(sv);
            sv = Nullop;
        }
+#ifdef USE_5005THREADS
        else if (sv->op_type == OP_THREADSV) { /* per-thread variable */
            padoff = sv->op_targ;
            sv->op_targ = 0;
@@ -3915,6 +4026,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
            op_free(sv);
            sv = Nullop;
        }
+#endif
        else
            Perl_croak(aTHX_ "Can't use %s for loop variable", PL_op_desc[sv->op_type]);
     }
@@ -3938,8 +4050,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
         * set the STACKED flag to indicate that these values are to be
         * treated as min/max values by 'pp_iterinit'.
         */
-       UNOP* flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first;
-       LOGOP* range = (LOGOP*) flip->op_first;
+       UNOP* const flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first;
+       LOGOP* const range = (LOGOP*) flip->op_first;
        OP* const left  = range->op_first;
        OP* const right = left->op_sibling;
        LISTOP* listop;
@@ -3980,7 +4092,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
     Renew(loop, 1, LOOP);
 #endif
     loop->op_targ = padoff;
-    wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont);
+    wop = newWHILEOP8(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont,
+                     0);
     PL_copline = forline;
     return newSTATEOP(0, label, wop);
 }
@@ -4060,7 +4173,7 @@ Perl_cv_undef(pTHX_ CV *cv)
        LEAVE;
     }
     SvPOK_off((SV*)cv);                /* forget prototype */
-    CvGV(cv) = Nullgv;
+    CvGV(cv) = NULL;
 
     pad_undef(cv);
 
@@ -4086,22 +4199,22 @@ Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p)
 {
     if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX_const(cv)))) && ckWARN_d(WARN_PROTOTYPE)) {
        SV* const msg = sv_newmortal();
-       SV* name = Nullsv;
+       SV* name = NULL;
 
        if (gv)
-           gv_efullname3(name = sv_newmortal(), gv, Nullch);
+           gv_efullname3(name = sv_newmortal(), gv, NULL);
        sv_setpv(msg, "Prototype mismatch:");
        if (name)
            Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name);
        if (SvPOK(cv))
            Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (const SV *)cv);
        else
-           Perl_sv_catpv(aTHX_ msg, ": none");
-       sv_catpv(msg, " vs ");
+           sv_catpvs(msg, ": none");
+       sv_catpvs(msg, " vs ");
        if (p)
            Perl_sv_catpvf(aTHX_ msg, "(%s)", p);
        else
-           sv_catpv(msg, "none");
+           sv_catpvs(msg, "none");
        Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, msg);
     }
 }
@@ -4125,18 +4238,20 @@ L<perlsub/"Constant Functions">.
 SV *
 Perl_cv_const_sv(pTHX_ CV *cv)
 {
-    if (!cv || !CvCONST(cv))
-       return Nullsv;
-    return (SV*)CvXSUBANY(cv).any_ptr;
+    if (!cv)
+       return NULL;
+    if (!(SvTYPE(cv) == SVt_PVCV || SvTYPE(cv) == SVt_PVFM))
+       return NULL;
+    return CvCONST(cv) ? (SV*)CvXSUBANY(cv).any_ptr : NULL;
 }
 
 SV *
 Perl_op_const_sv(pTHX_ OP *o, CV *cv)
 {
-    SV *sv = Nullsv;
+    SV *sv = NULL;
 
     if (!o)
-       return Nullsv;
+       return NULL;
 
     if (o->op_type == OP_LINESEQ && cLISTOPo->op_first)
        o = cLISTOPo->op_first->op_sibling;
@@ -4155,13 +4270,13 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv)
        if (type == OP_LEAVESUB || type == OP_RETURN)
            break;
        if (sv)
-           return Nullsv;
+           return NULL;
        if (type == OP_CONST && cSVOPo->op_sv)
            sv = cSVOPo->op_sv;
        else if ((type == OP_PADSV || type == OP_CONST) && cv) {
            sv = PAD_BASE_SV(CvPADLIST(cv), o->op_targ);
            if (!sv)
-               return Nullsv;
+               return NULL;
            if (CvCONST(cv)) {
                /* We get here only from cv_clone2() while creating a closure.
                   Copy the const value here instead of in cv_clone2 so that
@@ -4174,7 +4289,7 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv)
                return Nullsv;
        }
        else
-           return Nullsv;
+           return NULL;
     }
     if (sv)
        SvREADONLY_on(sv);
@@ -4210,17 +4325,24 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     GV *gv;
     const char *ps;
     STRLEN ps_len;
-    register CV *cv=0;
+    register CV *cv = NULL;
     SV *const_sv;
-
-    const char * const name = o ? SvPVx_nolen_const(cSVOPo->op_sv) : Nullch;
+    /* If the subroutine has no body, no attributes, and no builtin attributes
+       then it's just a sub declaration, and we may be able to get away with
+       storing with a placeholder scalar in the symbol table, rather than a
+       full GV and CV.  If anything is present then it will take a full CV to
+       store it.  */
+    const I32 gv_fetch_flags
+       = (block || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS))
+       ? GV_ADDMULTI : GV_ADDMULTI | GV_NOINIT;
+    const char * const name = o ? SvPVx_nolen_const(cSVOPo->op_sv) : NULL;
 
     if (proto) {
        assert(proto->op_type == OP_CONST);
        ps = SvPVx_const(((SVOP*)proto)->op_sv, ps_len);
     }
     else
-       ps = Nullch;
+       ps = NULL;
 
     if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) {
        SV * const sv = sv_newmortal();
@@ -4230,11 +4352,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        aname = SvPVX_const(sv);
     }
     else
-       aname = Nullch;
-    gv = gv_fetchpv(name ? name : (aname ? aname : 
-                   (PL_curstash ? "__ANON__" : "__ANON__::__ANON__")),
-                   GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT),
-                   SVt_PVCV);
+       aname = NULL;
+
+    /* There may be future conflict here as change 23766 is not yet merged.  */
+    gv = name ? gv_fetchsv(cSVOPo->op_sv, gv_fetch_flags, SVt_PVCV)
+       : gv_fetchpv(aname ? aname
+                    : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"),
+                    gv_fetch_flags, SVt_PVCV);
 
     if (o)
        SAVEFREEOP(o);
@@ -4271,8 +4395,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     }
 #endif
 
-    if (!block || !ps || *ps || attrs)
-       const_sv = Nullsv;
+    if (!block || !ps || *ps || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS))
+       const_sv = NULL;
     else
        const_sv = op_const_sv(block, Nullcv);
 
@@ -4302,9 +4426,6 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                SAVEFREESV(PL_compcv);
                goto done;
            }
-           /* ahem, death to those who redefine active sort subs */
-           if (PL_curstackinfo->si_type == PERLSI_SORT && PL_sortcop == CvSTART(cv))
-               Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name);
            if (block) {
                if (ckWARN(WARN_REDEFINE)
                    || (CvCONST(cv)
@@ -4324,7 +4445,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        }
     }
     if (const_sv) {
-       (void)SvREFCNT_inc(const_sv);
+       SvREFCNT_inc_simple_void_NN(const_sv);
        if (cv) {
            assert(!CvROOT(cv) && !CvCONST(cv));
            sv_setpvn((SV*)cv, "", 0);  /* prototype is "" */
@@ -4445,7 +4566,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        /* This makes sub {}; work as expected.  */
        if (block->op_type == OP_STUB) {
            op_free(block);
-           block = newSTATEOP(0, Nullch, 0);
+           block = newSTATEOP(0, NULL, 0);
        }
        CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block));
     }
@@ -4467,29 +4588,30 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 
     if (name || aname) {
        const char *s;
-       const char *tname = (name ? name : aname);
+       const char * const tname = (name ? name : aname);
 
        if (PERLDB_SUBLINE && PL_curstash != PL_debstash) {
-           SV *sv = NEWSV(0,0);
-           SV *tmpstr = sv_newmortal();
-           GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV);
-           CV *pcv;
+           SV * const sv = newSV(0);
+           SV * const tmpstr = sv_newmortal();
+           GV * const db_postponed = gv_fetchpvs("DB::postponed",
+                                                 GV_ADDMULTI, SVt_PVHV);
            HV *hv;
 
            Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld",
                           CopFILE(PL_curcop),
                           (long)PL_subline, (long)CopLINE(PL_curcop));
-           gv_efullname3(tmpstr, gv, Nullch);
+           gv_efullname3(tmpstr, gv, NULL);
            hv_store(GvHV(PL_DBsub), SvPVX_const(tmpstr), SvCUR(tmpstr), sv, 0);
            hv = GvHVn(db_postponed);
-           if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX_const(tmpstr), SvCUR(tmpstr))
-               && (pcv = GvCV(db_postponed)))
-           {
-               dSP;
-               PUSHMARK(SP);
-               XPUSHs(tmpstr);
-               PUTBACK;
-               call_sv((SV*)pcv, G_DISCARD);
+           if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX_const(tmpstr), SvCUR(tmpstr))) {
+               CV * const pcv = GvCV(db_postponed);
+               if (pcv) {
+                   dSP;
+                   PUSHMARK(SP);
+                   XPUSHs(tmpstr);
+                   PUTBACK;
+                   call_sv((SV*)pcv, G_DISCARD);
+               }
            }
        }
 
@@ -4588,9 +4710,10 @@ Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
     CvCONST_on(cv);
     sv_setpvn((SV*)cv, "", 0);  /* prototype is "" */
 
+#ifdef USE_ITHREADS
     if (stash)
        CopSTASH_free(PL_curcop);
-
+#endif
     LEAVE;
 
     return cv;
@@ -4648,7 +4771,7 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
     if (cv)                            /* must reuse cv if autoloaded */
        cv_undef(cv);
     else {
-       cv = (CV*)NEWSV(1105,0);
+       cv = (CV*)newSV(0);
        sv_upgrade((SV *)cv, SVt_PVCV);
        if (name) {
            GvCV(gv) = cv;
@@ -4719,15 +4842,11 @@ void
 Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
 {
     register CV *cv;
-    char *name;
-    GV *gv;
-    STRLEN n_a;
 
-    if (o)
-       name = SvPVx(cSVOPo->op_sv, n_a);
-    else
-       name = "STDOUT";
-    gv = gv_fetchpv(name,TRUE, SVt_PVFM);
+    GV * const gv = o
+       ? gv_fetchsv(cSVOPo->op_sv, TRUE, SVt_PVFM)
+       : gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVFM);
+
 #ifdef GV_UNIQUE_CHECK
     if (GvUNIQUE(gv)) {
         Perl_croak(aTHX_ "Bad symbol for form (GV is unique)");
@@ -4739,7 +4858,9 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
            const line_t oldline = CopLINE(PL_curcop);
            if (PL_copline != NOLINE)
                CopLINE_set(PL_curcop, PL_copline);
-           Perl_warner(aTHX_ packWARN(WARN_REDEFINE), "Format %s redefined",name);
+           Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
+                       o ? "Format %"SVf" redefined"
+                       : "Format STDOUT redefined" ,cSVOPo->op_sv);
            CopLINE_set(PL_curcop, oldline);
        }
        SvREFCNT_dec(cv);
@@ -4765,15 +4886,13 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
 OP *
 Perl_newANONLIST(pTHX_ OP *o)
 {
-    return newUNOP(OP_REFGEN, 0,
-       mod(list(convert(OP_ANONLIST, 0, o)), OP_REFGEN));
+    return convert(OP_ANONLIST, OPf_SPECIAL, o);
 }
 
 OP *
 Perl_newANONHASH(pTHX_ OP *o)
 {
-    return newUNOP(OP_REFGEN, 0,
-       mod(list(convert(OP_ANONHASH, 0, o)), OP_REFGEN));
+    return convert(OP_ANONHASH, OPf_SPECIAL, o);
 }
 
 OP *
@@ -4879,15 +4998,6 @@ Perl_newHVREF(pTHX_ OP *o)
 }
 
 OP *
-Perl_oopsCV(pTHX_ OP *o)
-{
-    Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__);
-    /* STUB */
-    PERL_UNUSED_ARG(o);
-    NORETURN_FUNCTION_END;
-}
-
-OP *
 Perl_newCVREF(pTHX_ I32 flags, OP *o)
 {
     return newUNOP(OP_RV2CV, flags, scalar(o));
@@ -4901,10 +5011,12 @@ Perl_newSVREF(pTHX_ OP *o)
        o->op_ppaddr = PL_ppaddr[OP_PADSV];
        return o;
     }
+#ifdef USE_5005THREADS
     else if (o->op_type == OP_THREADSV && !(o->op_flags & OPpDONE_SVREF)) {
        o->op_flags |= OPpDONE_SVREF;
        return o;
     }
+#endif
     return newUNOP(OP_RV2SV, 0, scalar(o));
 }
 
@@ -4915,7 +5027,7 @@ OP *
 Perl_ck_anoncode(pTHX_ OP *o)
 {
     cSVOPo->op_targ = pad_add_anon(cSVOPo->op_sv, o->op_type);
-    cSVOPo->op_sv = Nullsv;
+    cSVOPo->op_sv = NULL;
     return o;
 }
 
@@ -4955,7 +5067,7 @@ Perl_ck_bitop(pTHX_ OP *o)
 OP *
 Perl_ck_concat(pTHX_ OP *o)
 {
-    const OP *kid = cUNOPo->op_first;
+    const OP * const kid = cUNOPo->op_first;
     if (kid->op_type == OP_CONCAT && !(kid->op_private & OPpTARGET_MY) &&
            !(kUNOP->op_first->op_flags & OPf_MOD))
         o->op_flags |= OPf_STACKED;
@@ -4993,7 +5105,7 @@ Perl_ck_delete(pTHX_ OP *o)
     o = ck_fun(o);
     o->op_private = 0;
     if (o->op_flags & OPf_KIDS) {
-       OP *kid = cUNOPo->op_first;
+       OP * const kid = cUNOPo->op_first;
        switch (kid->op_type) {
        case OP_ASLICE:
            o->op_flags |= OPf_SPECIAL;
@@ -5085,9 +5197,9 @@ OP *
 Perl_ck_exit(pTHX_ OP *o)
 {
 #ifdef VMS
-    HV *table = GvHV(PL_hintgv);
+    HV * const table = GvHV(PL_hintgv);
     if (table) {
-       SV **svp = hv_fetch(table, "vmsish_exit", 11, FALSE);
+       SV * const * const svp = hv_fetchs(table, "vmsish_exit", FALSE);
        if (svp && *svp && SvTRUE(*svp))
            o->op_private |= OPpEXIT_VMSISH;
     }
@@ -5137,21 +5249,22 @@ Perl_ck_exists(pTHX_ OP *o)
 OP *
 Perl_ck_rvconst(pTHX_ register OP *o)
 {
-    SVOP *kid = (SVOP*)cUNOPo->op_first;
+    SVOP * const kid = (SVOP*)cUNOPo->op_first;
 
     o->op_private |= (PL_hints & HINT_STRICT_REFS);
+    if (o->op_type == OP_RV2CV)
+       o->op_private &= ~1;
+
     if (kid->op_type == OP_CONST) {
-       char *name;
        int iscv;
        GV *gv;
        SV * const kidsv = kid->op_sv;
-       STRLEN n_a;
 
        /* Is it a constant from cv_const_sv()? */
        if (SvROK(kidsv) && SvREADONLY(kidsv)) {
-           SV *rsv = SvRV(kidsv);
+           SV * const rsv = SvRV(kidsv);
            const int svtype = SvTYPE(rsv);
-            const char *badtype = Nullch;
+            const char *badtype = NULL;
 
            switch (o->op_type) {
            case OP_RV2SV:
@@ -5184,9 +5297,8 @@ Perl_ck_rvconst(pTHX_ register OP *o)
                Perl_croak(aTHX_ "Constant is not %s reference", badtype);
            return o;
        }
-       name = SvPV(kidsv, n_a);
        if ((PL_hints & HINT_STRICT_REFS) && (kid->op_private & OPpCONST_BARE)) {
-            const char *badthing = Nullch;
+            const char *badthing = NULL;
            switch (o->op_type) {
            case OP_RV2SV:
                badthing = "a SCALAR";
@@ -5200,8 +5312,8 @@ Perl_ck_rvconst(pTHX_ register OP *o)
            }
            if (badthing)
                Perl_croak(aTHX_
-         "Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use",
-                     name, badthing);
+         "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use",
+                     kidsv, badthing);
        }
        /*
         * This is a little tricky.  We only want to add the symbol if we
@@ -5213,7 +5325,7 @@ Perl_ck_rvconst(pTHX_ register OP *o)
         */
        iscv = (o->op_type == OP_RV2CV) * 2;
        do {
-           gv = gv_fetchpv(name,
+           gv = gv_fetchsv(kidsv,
                iscv | !(kid->op_private & OPpCONST_ENTERED),
                iscv
                    ? SVt_PVCV
@@ -5233,9 +5345,9 @@ Perl_ck_rvconst(pTHX_ register OP *o)
            kPADOP->op_padix = pad_alloc(OP_GV, SVs_PADTMP);
            SvREFCNT_dec(PAD_SVl(kPADOP->op_padix));
            GvIN_PAD_on(gv);
-           PAD_SETSV(kPADOP->op_padix, (SV*) SvREFCNT_inc(gv));
+           PAD_SETSV(kPADOP->op_padix, (SV*) SvREFCNT_inc_simple_NN(gv));
 #else
-           kid->op_sv = SvREFCNT_inc(gv);
+           kid->op_sv = SvREFCNT_inc_simple_NN(gv);
 #endif
            kid->op_private = 0;
            kid->op_ppaddr = PL_ppaddr[OP_GV];
@@ -5253,12 +5365,11 @@ Perl_ck_ftst(pTHX_ OP *o)
        /* nothing */
     }
     else if (o->op_flags & OPf_KIDS && cUNOPo->op_first->op_type != OP_STUB) {
-       SVOP *kid = (SVOP*)cUNOPo->op_first;
+       SVOP * const kid = (SVOP*)cUNOPo->op_first;
 
        if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) {
-           STRLEN n_a;
-           OP *newop = newGVOP(type, OPf_REF,
-               gv_fetchpv(SvPVx(kid->op_sv, n_a), TRUE, SVt_PVIO));
+           OP * const newop = newGVOP(type, OPf_REF,
+               gv_fetchsv(kid->op_sv, GV_ADD, SVt_PVIO));
            op_free(o);
            o = newop;
        }
@@ -5292,7 +5403,6 @@ Perl_ck_fun(pTHX_ OP *o)
     }
 
     if (o->op_flags & OPf_KIDS) {
-       STRLEN n_a;
         OP **tokid = &cLISTOPo->op_first;
         register OP *kid = cLISTOPo->op_first;
         OP *sibl;
@@ -5338,13 +5448,12 @@ Perl_ck_fun(pTHX_ OP *o)
                if (kid->op_type == OP_CONST &&
                    (kid->op_private & OPpCONST_BARE))
                {
-                   char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
-                   OP *newop = newAVREF(newGVOP(OP_GV, 0,
-                       gv_fetchpv(name, TRUE, SVt_PVAV) ));
+                   OP * const newop = newAVREF(newGVOP(OP_GV, 0,
+                       gv_fetchsv(((SVOP*)kid)->op_sv, GV_ADD, SVt_PVAV) ));
                    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
                        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
-                           "Array @%s missing the @ in argument %"IVdf" of %s()",
-                           name, (IV)numargs, PL_op_desc[type]);
+                           "Array @%"SVf" missing the @ in argument %"IVdf" of %s()",
+                           ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
                    op_free(kid);
                    kid = newop;
                    kid->op_sibling = sibl;
@@ -5358,13 +5467,12 @@ Perl_ck_fun(pTHX_ OP *o)
                if (kid->op_type == OP_CONST &&
                    (kid->op_private & OPpCONST_BARE))
                {
-                   char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
-                   OP *newop = newHVREF(newGVOP(OP_GV, 0,
-                       gv_fetchpv(name, TRUE, SVt_PVHV) ));
+                   OP * const newop = newHVREF(newGVOP(OP_GV, 0,
+                       gv_fetchsv(((SVOP*)kid)->op_sv, GV_ADD, SVt_PVHV) ));
                    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
                        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
-                           "Hash %%%s missing the %% in argument %"IVdf" of %s()",
-                           name, (IV)numargs, PL_op_desc[type]);
+                           "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()",
+                           ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
                    op_free(kid);
                    kid = newop;
                    kid->op_sibling = sibl;
@@ -5376,7 +5484,7 @@ Perl_ck_fun(pTHX_ OP *o)
                break;
            case OA_CVREF:
                {
-                   OP *newop = newUNOP(OP_NULL, 0, kid);
+                   OP * const newop = newUNOP(OP_NULL, 0, kid);
                    kid->op_sibling = 0;
                    linklist(kid);
                    newop->op_next = newop;
@@ -5390,9 +5498,8 @@ Perl_ck_fun(pTHX_ OP *o)
                    if (kid->op_type == OP_CONST &&
                        (kid->op_private & OPpCONST_BARE))
                    {
-                       OP *newop = newGVOP(OP_GV, 0,
-                           gv_fetchpv(SvPVx(((SVOP*)kid)->op_sv, n_a), TRUE,
-                                       SVt_PVIO) );
+                       OP * const newop = newGVOP(OP_GV, 0,
+                           gv_fetchsv(((SVOP*)kid)->op_sv, GV_ADD, SVt_PVIO));
                        if (!(o->op_private & 1) && /* if not unop */
                            kid == cLISTOPo->op_last)
                            cLISTOPo->op_last = newop;
@@ -5410,7 +5517,7 @@ Perl_ck_fun(pTHX_ OP *o)
 
                        /* is this op a FH constructor? */
                        if (is_handle_constructor(o,numargs)) {
-                            const char *name = Nullch;
+                            const char *name = NULL;
                            STRLEN len = 0;
 
                            flags = 0;
@@ -5435,19 +5542,18 @@ Perl_ck_fun(pTHX_ OP *o)
                            else if (kid->op_type == OP_RV2SV
                                     && kUNOP->op_first->op_type == OP_GV)
                            {
-                               GV *gv = cGVOPx_gv(kUNOP->op_first);
+                               GV * const gv = cGVOPx_gv(kUNOP->op_first);
                                name = GvNAME(gv);
                                len = GvNAMELEN(gv);
                            }
                            else if (kid->op_type == OP_AELEM
                                     || kid->op_type == OP_HELEM)
                            {
-                                OP *op;
-
-                                name = 0;
-                                if ((op = ((BINOP*)kid)->op_first)) {
-                                     SV *tmpstr = Nullsv;
-                                     const char *a =
+                                OP *op = ((BINOP*)kid)->op_first;
+                                name = NULL;
+                                if (op) {
+                                     SV *tmpstr = NULL;
+                                     const char * const a =
                                           kid->op_type == OP_AELEM ?
                                           "[]" : "{}";
                                      if (((op->op_type == OP_RV2AV) ||
@@ -5455,7 +5561,7 @@ Perl_ck_fun(pTHX_ OP *o)
                                          (op = ((UNOP*)op)->op_first) &&
                                          (op->op_type == OP_GV)) {
                                           /* packagevar $a[] or $h{} */
-                                          GV *gv = cGVOPx_gv(op);
+                                          GV * const gv = cGVOPx_gv(op);
                                           if (gv)
                                                tmpstr =
                                                     Perl_newSVpvf(aTHX_
@@ -5466,7 +5572,7 @@ Perl_ck_fun(pTHX_ OP *o)
                                      else if (op->op_type == OP_PADAV
                                               || op->op_type == OP_PADHV) {
                                           /* lexicalvar $a[] or $h{} */
-                                          const char *padname =
+                                          const char * const padname =
                                                PAD_COMPNAME_PV(op->op_targ);
                                           if (padname)
                                                tmpstr =
@@ -5474,7 +5580,6 @@ Perl_ck_fun(pTHX_ OP *o)
                                                                   "%s%c...%c",
                                                                   padname + 1,
                                                                   a[0], a[1]);
-                                          
                                      }
                                      if (tmpstr) {
                                           name = SvPV_const(tmpstr, len);
@@ -5543,10 +5648,10 @@ Perl_ck_glob(pTHX_ OP *o)
     if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling)
        append_elem(OP_GLOB, o, newDEFSVOP());
 
-    if (!((gv = gv_fetchpv("glob", FALSE, SVt_PVCV))
+    if (!((gv = gv_fetchpvs("glob", GV_NOTQUAL, SVt_PVCV))
          && GvCVu(gv) && GvIMPORTED_CV(gv)))
     {
-       gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
+       gv = gv_fetchpvs("CORE::GLOBAL::glob", 0, SVt_PVCV);
     }
 
 #if !defined(PERL_EXTERNAL_GLOB)
@@ -5555,11 +5660,11 @@ Perl_ck_glob(pTHX_ OP *o)
        GV *glob_gv;
        ENTER;
        Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
-               newSVpvn("File::Glob", 10), Nullsv, Nullsv, Nullsv);
-       gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV);
-       glob_gv = gv_fetchpv("File::Glob::csh_glob", FALSE, SVt_PVCV);
+               newSVpvs("File::Glob"), NULL, NULL, NULL);
+       gv = gv_fetchpvs("CORE::GLOBAL::glob", 0, SVt_PVCV);
+       glob_gv = gv_fetchpvs("File::Glob::csh_glob", 0, SVt_PVCV);
        GvCV(gv) = GvCV(glob_gv);
-       (void)SvREFCNT_inc((SV*)GvCV(gv));
+       SvREFCNT_inc_void((SV*)GvCV(gv));
        GvIMPORTED_CV_on(gv);
        LEAVE;
     }
@@ -5753,7 +5858,7 @@ Perl_ck_sassign(pTHX_ OP *o)
        /* Cannot steal the second time! */
        && !(kid->op_private & OPpTARGET_MY))
     {
-       OP *kkid = kid->op_sibling;
+       OP * const kkid = kid->op_sibling;
 
        /* Can just relocate the target. */
        if (kkid && kkid->op_type == OP_PADSV
@@ -5770,19 +5875,6 @@ Perl_ck_sassign(pTHX_ OP *o)
            return kid;
        }
     }
-    /* optimise C<my $x = undef> to C<my $x> */
-    if (kid->op_type == OP_UNDEF) {
-       OP *kkid = kid->op_sibling;
-       if (kkid && kkid->op_type == OP_PADSV
-               && (kkid->op_private & OPpLVAL_INTRO))
-       {
-           cLISTOPo->op_first = NULL;
-           kid->op_sibling = NULL;
-           op_free(o);
-           op_free(kid);
-           return kkid;
-       }
-    }
     return o;
 }
 
@@ -5796,16 +5888,17 @@ Perl_ck_match(pTHX_ OP *o)
 OP *
 Perl_ck_method(pTHX_ OP *o)
 {
-    OP *kid = cUNOPo->op_first;
+    OP * const kid = cUNOPo->op_first;
     if (kid->op_type == OP_CONST) {
        SV* sv = kSVOP->op_sv;
-       if (!(strchr(SvPVX_const(sv), ':') || strchr(SvPVX_const(sv), '\''))) {
+       const char * const method = SvPVX_const(sv);
+       if (!(strchr(method, ':') || strchr(method, '\''))) {
            OP *cmop;
            if (!SvREADONLY(sv) || !SvFAKE(sv)) {
-               sv = newSVpvn_share(SvPVX_const(sv), SvCUR(sv), 0);
+               sv = newSVpvn_share(method, SvCUR(sv), 0);
            }
            else {
-               kSVOP->op_sv = Nullsv;
+               kSVOP->op_sv = NULL;
            }
            cmop = newSVOP(OP_METHOD_NAMED, 0, sv);
            op_free(o);
@@ -5824,22 +5917,20 @@ Perl_ck_null(pTHX_ OP *o)
 OP *
 Perl_ck_open(pTHX_ OP *o)
 {
-    HV *table = GvHV(PL_hintgv);
+    HV * const table = GvHV(PL_hintgv);
     if (table) {
-       SV **svp;
-       I32 mode;
-       svp = hv_fetch(table, "open_IN", 7, FALSE);
+       SV **svp = hv_fetchs(table, "open_IN", FALSE);
        if (svp && *svp) {
-           mode = mode_from_discipline(*svp);
+           const I32 mode = mode_from_discipline(*svp);
            if (mode & O_BINARY)
                o->op_private |= OPpOPEN_IN_RAW;
            else if (mode & O_TEXT)
                o->op_private |= OPpOPEN_IN_CRLF;
        }
 
-       svp = hv_fetch(table, "open_OUT", 8, FALSE);
+       svp = hv_fetchs(table, "open_OUT", FALSE);
        if (svp && *svp) {
-           mode = mode_from_discipline(*svp);
+           const I32 mode = mode_from_discipline(*svp);
            if (mode & O_BINARY)
                o->op_private |= OPpOPEN_OUT_RAW;
            else if (mode & O_TEXT)
@@ -5851,8 +5942,8 @@ Perl_ck_open(pTHX_ OP *o)
     {
         /* In case of three-arg dup open remove strictness
          * from the last arg if it is a bareword. */
-        OP *first = cLISTOPx(o)->op_first; /* The pushmark. */
-        OP *last  = cLISTOPx(o)->op_last;  /* The bareword. */
+        OP * const first = cLISTOPx(o)->op_first; /* The pushmark. */
+        OP * const last  = cLISTOPx(o)->op_last;  /* The bareword. */
         OP *oa;
         const char *mode;
 
@@ -5861,6 +5952,7 @@ Perl_ck_open(pTHX_ OP *o)
             (last->op_private & OPpCONST_STRICT) &&
             (oa = first->op_sibling) &&                /* The fh. */
             (oa = oa->op_sibling) &&                   /* The mode. */
+            (oa->op_type == OP_CONST) &&
             SvPOK(((SVOP*)oa)->op_sv) &&
             (mode = SvPVX_const(((SVOP*)oa)->op_sv)) &&
             mode[0] == '>' && mode[1] == '&' &&        /* A dup open. */
@@ -5885,13 +5977,13 @@ Perl_ck_repeat(pTHX_ OP *o)
 OP *
 Perl_ck_require(pTHX_ OP *o)
 {
-    GV* gv;
+    GV* gv = Nullgv;
 
     if (o->op_flags & OPf_KIDS) {      /* Shall we supply missing .pm? */
-       SVOP *kid = (SVOP*)cUNOPo->op_first;
+       SVOP * const kid = (SVOP*)cUNOPo->op_first;
 
        if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) {
-           SV *sv = kid->op_sv;
+           SV * const sv = kid->op_sv;
            U32 was_readonly = SvREADONLY(sv);
            char *s;
 
@@ -5907,23 +5999,28 @@ Perl_ck_require(pTHX_ OP *o)
 
            for (s = SvPVX(sv); *s; s++) {
                if (*s == ':' && s[1] == ':') {
+                   const STRLEN len = strlen(s+2)+1;
                    *s = '/';
-                   Move(s+2, s+1, strlen(s+2)+1, char);
+                   Move(s+2, s+1, len, char);
                    SvCUR_set(sv, SvCUR(sv) - 1);
                }
            }
-           sv_catpvn(sv, ".pm", 3);
+           sv_catpvs(sv, ".pm");
            SvFLAGS(sv) |= was_readonly;
        }
     }
 
-    /* handle override, if any */
-    gv = gv_fetchpv("require", FALSE, SVt_PVCV);
-    if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv)))
-       gv = gv_fetchpv("CORE::GLOBAL::require", FALSE, SVt_PVCV);
+    if (!(o->op_flags & OPf_SPECIAL)) { /* Wasn't written as CORE::require */
+       /* handle override, if any */
+       gv = gv_fetchpvs("require", GV_NOTQUAL, SVt_PVCV);
+       if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) {
+           GV * const * const gvp = (GV**)hv_fetchs(PL_globalstash, "require", FALSE);
+           gv = gvp ? *gvp : Nullgv;
+       }
+    }
 
     if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) {
-       OP *kid = cUNOPo->op_first;
+       OP * const kid = cUNOPo->op_first;
        cUNOPo->op_first = 0;
        op_free(o);
        return ck_subr(newUNOP(OP_ENTERSUB, OPf_STACKED,
@@ -5947,16 +6044,6 @@ Perl_ck_return(pTHX_ OP *o)
     return o;
 }
 
-#if 0
-OP *
-Perl_ck_retarget(pTHX_ OP *o)
-{
-    Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__);
-    /* STUB */
-    return o;
-}
-#endif
-
 OP *
 Perl_ck_select(pTHX_ OP *o)
 {
@@ -6078,8 +6165,8 @@ S_simplify_sort(pTHX_ OP *o)
     const char *gvname;
     if (!(o->op_flags & OPf_STACKED))
        return;
-    GvMULTI_on(gv_fetchpv("a", TRUE, SVt_PV));
-    GvMULTI_on(gv_fetchpv("b", TRUE, SVt_PV));
+    GvMULTI_on(gv_fetchpvs("a", GV_ADD|GV_NOTQUAL, SVt_PV));
+    GvMULTI_on(gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV));
     kid = kUNOP->op_first;                             /* get past null */
     if (kid->op_type != OP_SCOPE)
        return;
@@ -6152,12 +6239,12 @@ Perl_ck_split(pTHX_ OP *o)
     op_free(cLISTOPo->op_first);
     cLISTOPo->op_first = kid;
     if (!kid) {
-       cLISTOPo->op_first = kid = newSVOP(OP_CONST, 0, newSVpvn(" ", 1));
+       cLISTOPo->op_first = kid = newSVOP(OP_CONST, 0, newSVpvs(" "));
        cLISTOPo->op_last = kid; /* There was only one element previously */
     }
 
     if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) {
-       OP *sibl = kid->op_sibling;
+       OP * const sibl = kid->op_sibling;
        kid->op_sibling = 0;
        kid = pmruntime( newPMOP(OP_MATCH, OPf_SPECIAL), kid, Nullop);
        if (cLISTOPo->op_first == cLISTOPo->op_last)
@@ -6169,7 +6256,7 @@ Perl_ck_split(pTHX_ OP *o)
     kid->op_type = OP_PUSHRE;
     kid->op_ppaddr = PL_ppaddr[OP_PUSHRE];
     scalar(kid);
-    if (ckWARN(WARN_REGEXP) && ((PMOP *)kid)->op_pmflags & PMf_GLOBAL) {
+    if (((PMOP *)kid)->op_pmflags & PMf_GLOBAL && ckWARN(WARN_REGEXP)) {
       Perl_warner(aTHX_ packWARN(WARN_REGEXP),
                   "Use of /g modifier is meaningless in split");
     }
@@ -6195,9 +6282,9 @@ Perl_ck_split(pTHX_ OP *o)
 OP *
 Perl_ck_join(pTHX_ OP *o)
 {
-    if (ckWARN(WARN_SYNTAX)) {
-       const OP *kid = cLISTOPo->op_first->op_sibling;
-       if (kid && kid->op_type == OP_MATCH) {
+    const OP * const kid = cLISTOPo->op_first->op_sibling;
+    if (kid && kid->op_type == OP_MATCH) {
+       if (ckWARN(WARN_SYNTAX)) {
             const REGEXP *re = PM_GETRE(kPMOP);
            const char *pmstr = re ? re->precomp : "STRING";
            Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
@@ -6215,13 +6302,13 @@ Perl_ck_subr(pTHX_ OP *o)
             ? cUNOPo : ((UNOP*)cUNOPo->op_first))->op_first;
     OP *o2 = prev->op_sibling;
     OP *cvop;
-    char *proto = 0;
-    CV *cv = 0;
-    GV *namegv = 0;
+    char *proto = NULL;
+    CV *cv = NULL;
+    GV *namegv = NULL;
     int optional = 0;
     I32 arg = 0;
     I32 contextclass = 0;
-    char *e = 0;
+    char *e = NULL;
 
     o->op_private |= OPpENTERSUB_HASTARG;
     for (cvop = o2; cvop->op_sibling; cvop = cvop->op_sibling) ;
@@ -6245,7 +6332,7 @@ Perl_ck_subr(pTHX_ OP *o)
        if (o2->op_type == OP_CONST)
            o2->op_private &= ~OPpCONST_STRICT;
        else if (o2->op_type == OP_LIST) {
-           OP *o = ((UNOP*)o2)->op_first->op_sibling;
+           OP * const o = ((UNOP*)o2)->op_first->op_sibling;
            if (o && o->op_type == OP_CONST)
                o->op_private &= ~OPpCONST_STRICT;
        }
@@ -6301,9 +6388,9 @@ Perl_ck_subr(pTHX_ OP *o)
                                (gvop = ((UNOP*)gvop)->op_first) &&
                                gvop->op_type == OP_GV)
                            {
-                               GV *gv = cGVOPx_gv(gvop);
-                               OP *sibling = o2->op_sibling;
-                               SV *n = newSVpvn("",0);
+                               GV * const gv = cGVOPx_gv(gvop);
+                               OP * const sibling = o2->op_sibling;
+                               SV * const n = newSVpvs("");
                                op_free(o2);
                                gv_fullname4(n, gv, "", FALSE);
                                o2 = newSVOP(OP_CONST, 0, n);
@@ -6335,6 +6422,7 @@ Perl_ck_subr(pTHX_ OP *o)
                     break;
                case ']':
                     if (contextclass) {
+                        /* XXX We shouldn't be modifying proto, so we can const proto */
                         char *p = proto;
                         const char s = *p;
                         contextclass = 0;
@@ -6362,8 +6450,11 @@ Perl_ck_subr(pTHX_ OP *o)
                    if (o2->op_type == OP_RV2SV ||
                        o2->op_type == OP_PADSV ||
                        o2->op_type == OP_HELEM ||
-                       o2->op_type == OP_AELEM ||
-                       o2->op_type == OP_THREADSV)
+                       o2->op_type == OP_AELEM
+#ifdef USE_5005THREADS
+                       || o2->op_type == OP_THREADSV
+#endif
+                       )
                         goto wrapref;
                    if (!contextclass)
                        bad_type(arg, "scalar", gv_ename(namegv), o2);
@@ -6384,8 +6475,8 @@ Perl_ck_subr(pTHX_ OP *o)
                    break;
                wrapref:
                    {
-                       OP* kid = o2;
-                       OP* sib = kid->op_sibling;
+                       OP* const kid = o2;
+                       OP* const sib = kid->op_sibling;
                        kid->op_sibling = 0;
                        o2 = newUNOP(OP_REFGEN, 0, kid);
                        o2->op_sibling = sib;
@@ -6415,7 +6506,7 @@ Perl_ck_subr(pTHX_ OP *o)
        mod(o2, OP_ENTERSUB);
        prev = o2;
        o2 = o2->op_sibling;
-    }
+    } /* while */
     if (proto && !optional &&
          (*proto && *proto != '@' && *proto != '%' && *proto != ';'))
        return too_few_arguments(o, gv_ename(namegv));
@@ -6470,7 +6561,7 @@ Perl_ck_substr(pTHX_ OP *o)
 void
 Perl_peep(pTHX_ register OP *o)
 {
-    register OP* oldop = 0;
+    register OP* oldop = NULL;
     STRLEN n_a;
 
     if (!o || o->op_seq)
@@ -6511,6 +6602,18 @@ Perl_peep(pTHX_ register OP *o)
                    SvREADONLY_on(PAD_SVl(ix));
                    SvREFCNT_dec(cSVOPo->op_sv);
                }
+               else if (o->op_type == OP_CONST
+                        && cSVOPo->op_sv == &PL_sv_undef) {
+                   /* PL_sv_undef is hack - it's unsafe to store it in the
+                      AV that is the pad, because av_fetch treats values of
+                      PL_sv_undef as a "free" AV entry and will merrily
+                      replace them with a new SV, causing pad_alloc to think
+                      that this pad slot is free. (When, clearly, it is not)
+                   */
+                   SvOK_off(PAD_SVl(ix));
+                   SvPADTMP_on(PAD_SVl(ix));
+                   SvREADONLY_on(PAD_SVl(ix));
+               }
                else {
                    SvREFCNT_dec(PAD_SVl(ix));
                    SvPADTMP_on(cSVOPo->op_sv);
@@ -6518,7 +6621,7 @@ Perl_peep(pTHX_ register OP *o)
                    /* XXX I don't know how this isn't readonly already. */
                    SvREADONLY_on(PAD_SVl(ix));
                }
-               cSVOPo->op_sv = Nullsv;
+               cSVOPo->op_sv = NULL;
                o->op_targ = ix;
            }
 #endif
@@ -6578,7 +6681,7 @@ Perl_peep(pTHX_ register OP *o)
        case OP_PADAV:
        case OP_GV:
            if (o->op_type == OP_PADAV || o->op_next->op_type == OP_RV2AV) {
-               OP* pop = (o->op_type == OP_PADAV) ?
+               OP* const pop = (o->op_type == OP_PADAV) ?
                            o->op_next : o->op_next->op_next;
                IV i;
                if (pop && pop->op_type == OP_CONST &&
@@ -6624,11 +6727,11 @@ Perl_peep(pTHX_ register OP *o)
                }
            }
            else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
-               GV *gv = cGVOPo_gv;
+               GV * const gv = cGVOPo_gv;
                if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX_const(GvCV(gv))) {
                    /* XXX could check prototype here instead of just carping */
-                   SV *sv = sv_newmortal();
-                   gv_efullname3(sv, gv, Nullch);
+                   SV * const sv = sv_newmortal();
+                   gv_efullname3(sv, gv, NULL);
                    Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
                                "%"SVf"() called too early to check prototype",
                                sv);
@@ -6689,8 +6792,9 @@ Perl_peep(pTHX_ register OP *o)
 
        case OP_EXEC:
            o->op_seq = PL_op_seqmax++;
-           if (ckWARN(WARN_SYNTAX) && o->op_next
-               && o->op_next->op_type == OP_NEXTSTATE) {
+           if (o->op_next && o->op_next->op_type == OP_NEXTSTATE
+               && ckWARN(WARN_SYNTAX))
+           {
                if (o->op_next->op_sibling &&
                        o->op_next->op_sibling->op_type != OP_EXIT &&
                        o->op_next->op_sibling->op_type != OP_WARN &&
@@ -6741,7 +6845,7 @@ Perl_peep(pTHX_ register OP *o)
            lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
            if (!(SvFLAGS(lexname) & SVpad_TYPED))
                break;
-           fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
+           fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
            if (!fields || !GvHV(*fields))
                break;
            key = SvPV_const(*svp, keylen);
@@ -6792,7 +6896,7 @@ Perl_peep(pTHX_ register OP *o)
            lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
            if (!(SvFLAGS(lexname) & SVpad_TYPED))
                break;
-           fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
+           fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
            if (!fields || !GvHV(*fields))
                break;
            /* Again guessing that the pushmark can be jumped over.... */
@@ -6836,22 +6940,22 @@ Perl_peep(pTHX_ register OP *o)
 
        case OP_SORT: {
            /* will point to RV2AV or PADAV op on LHS/RHS of assign */
-           OP *oleft, *oright;
+           OP *oleft;
            OP *o2;
 
            /* check that RHS of sort is a single plain array */
-           oright = cUNOPo->op_first;
+           OP *oright = cUNOPo->op_first;
            if (!oright || oright->op_type != OP_PUSHMARK)
                break;
 
            /* reverse sort ... can be optimised.  */
            if (!cUNOPo->op_sibling) {
                /* Nothing follows us on the list. */
-               OP *reverse = o->op_next;
+               OP * const reverse = o->op_next;
 
                if (reverse->op_type == OP_REVERSE &&
                    (reverse->op_flags & OPf_WANT) == OPf_WANT_LIST) {
-                   OP *pushmark = cUNOPx(reverse)->op_first;
+                   OP * const pushmark = cUNOPx(reverse)->op_first;
                    if (pushmark && (pushmark->op_type == OP_PUSHMARK)
                        && (cUNOPx(pushmark)->op_sibling == o)) {
                        /* reverse -> pushmark -> sort */
@@ -7042,6 +7146,59 @@ Perl_peep(pTHX_ register OP *o)
            
            break;
        }
+
+       case OP_SASSIGN: {
+           OP *rv2gv;
+           UNOP *refgen, *rv2cv;
+           LISTOP *exlist;
+
+           /* I do not understand this, but if o->op_opt isn't set to 1,
+              various tests in ext/B/t/bytecode.t fail with no readily
+              apparent cause.  */
+           /* Converted from op_opt to op_seq for 5.8.x.  */
+
+           o->op_seq = PL_op_seqmax++;
+
+
+           if ((o->op_flags && OPf_WANT) != OPf_WANT_VOID)
+               break;
+
+           if ((o->op_private & ~OPpASSIGN_BACKWARDS) != 2)
+               break;
+
+           rv2gv = ((BINOP *)o)->op_last;
+           if (!rv2gv || rv2gv->op_type != OP_RV2GV)
+               break;
+
+           refgen = (UNOP *)((BINOP *)o)->op_first;
+
+           if (!refgen || refgen->op_type != OP_REFGEN)
+               break;
+
+           exlist = (LISTOP *)refgen->op_first;
+           if (!exlist || exlist->op_type != OP_NULL
+               || exlist->op_targ != OP_LIST)
+               break;
+
+           if (exlist->op_first->op_type != OP_PUSHMARK)
+               break;
+
+           rv2cv = (UNOP*)exlist->op_last;
+
+           if (rv2cv->op_type != OP_RV2CV)
+               break;
+
+           assert ((rv2gv->op_private & OPpDONT_INIT_GV) == 0);
+           assert ((o->op_private & OPpASSIGN_CV_TO_GV) == 0);
+           assert ((rv2cv->op_private & OPpMAY_RETURN_CONSTANT) == 0);
+
+           o->op_private |= OPpASSIGN_CV_TO_GV;
+           rv2gv->op_private |= OPpDONT_INIT_GV;
+           rv2cv->op_private |= OPpMAY_RETURN_CONSTANT;
+
+           break;
+       }
+
        
        default:
            o->op_seq = PL_op_seqmax++;
@@ -7060,13 +7217,13 @@ Perl_custom_op_name(pTHX_ OP* o)
     HE* he;
 
     if (!PL_custom_op_names) /* This probably shouldn't happen */
-        return PL_op_name[OP_CUSTOM];
+        return (char *)PL_op_name[OP_CUSTOM];
 
     keysv = sv_2mortal(newSViv(index));
 
     he = hv_fetch_ent(PL_custom_op_names, keysv, 0, 0);
     if (!he)
-        return PL_op_name[OP_CUSTOM]; /* Don't know who you are */
+        return (char *)PL_op_name[OP_CUSTOM]; /* Don't know who you are */
 
     return SvPV_nolen(HeVAL(he));
 }
@@ -7079,13 +7236,13 @@ Perl_custom_op_desc(pTHX_ OP* o)
     HE* he;
 
     if (!PL_custom_op_descs)
-        return PL_op_desc[OP_CUSTOM];
+        return (char *)PL_op_desc[OP_CUSTOM];
 
     keysv = sv_2mortal(newSViv(index));
 
     he = hv_fetch_ent(PL_custom_op_descs, keysv, 0, 0);
     if (!he)
-        return PL_op_desc[OP_CUSTOM];
+        return (char *)PL_op_desc[OP_CUSTOM];
 
     return SvPV_nolen(HeVAL(he));
 }