This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Lexical use open ... support:
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 35fa3f5..07d147d 100644 (file)
--- a/op.c
+++ b/op.c
@@ -22,7 +22,7 @@
 
 /* #define PL_OP_SLAB_ALLOC */
 
-#ifdef PL_OP_SLAB_ALLOC 
+#ifdef PL_OP_SLAB_ALLOC
 #define SLAB_SIZE 8192
 static char    *PL_OpPtr  = NULL;
 static int     PL_OpSpace = 0;
@@ -32,15 +32,15 @@ static int     PL_OpSpace = 0;
                               var = (type *) Slab_Alloc(m,c*sizeof(type));    \
                            } while (0)
 
-STATIC void *           
+STATIC void *
 S_Slab_Alloc(pTHX_ int m, size_t sz)
-{ 
+{
  Newz(m,PL_OpPtr,SLAB_SIZE,char);
  PL_OpSpace = SLAB_SIZE - sz;
  return PL_OpPtr += PL_OpSpace;
 }
 
-#else 
+#else
 #define NewOp(m, var, c, type) Newz(m, var, c, type)
 #endif
 /*
@@ -150,7 +150,7 @@ Perl_pad_allocmy(pTHX_ char *name)
                && strEQ(name, SvPVX(sv)))
            {
                Perl_warner(aTHX_ WARN_MISC,
-                   "\"%s\" variable %s masks earlier declaration in same %s", 
+                   "\"%s\" variable %s masks earlier declaration in same %s",
                    (PL_in_my == KEY_our ? "our" : "my"),
                    name,
                    (SvIVX(sv) == PAD_MAX ? "scope" : "statement"));
@@ -162,13 +162,14 @@ Perl_pad_allocmy(pTHX_ char *name)
            do {
                if ((sv = svp[off])
                    && sv != &PL_sv_undef
+                   && (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0)
                    && ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash)
                    && strEQ(name, SvPVX(sv)))
                {
                    Perl_warner(aTHX_ WARN_MISC,
                        "\"our\" variable %s redeclared", name);
                    Perl_warner(aTHX_ WARN_MISC,
-                       "(Did you mean \"local\" instead of \"our\"?)\n");
+                       "\t(Did you mean \"local\" instead of \"our\"?)\n");
                    break;
                }
            } while ( off-- > 0 );
@@ -321,9 +322,12 @@ S_pad_findlex(pTHX_ char *name, PADOFFSET newoff, U32 seq, CV* startcv,
                        }
                    }
                    else if (!CvUNIQUE(PL_compcv)) {
-                       if (ckWARN(WARN_CLOSURE) && !SvFAKE(sv) && !CvUNIQUE(cv))
+                       if (ckWARN(WARN_CLOSURE) && !SvFAKE(sv) && !CvUNIQUE(cv)
+                           && !(SvFLAGS(sv) & SVpad_OUR))
+                       {
                            Perl_warner(aTHX_ WARN_CLOSURE,
                                "Variable \"%s\" will not stay shared", name);
+                       }
                    }
                }
                av_store(PL_comppad, newoff, SvREFCNT_inc(oldsv));
@@ -491,7 +495,8 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype)
                   (sv = names[PL_padix]) && sv != &PL_sv_undef)
                continue;
            sv = *av_fetch(PL_comppad, PL_padix, TRUE);
-           if (!(SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY)) && !IS_PADGV(sv))
+           if (!(SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY)) &&
+               !IS_PADGV(sv) && !IS_PADCONST(sv))
                break;
        }
        retval = PL_padix;
@@ -647,7 +652,7 @@ Perl_find_threadsv(pTHX_ const char *name)
            break;
        case ';':
            sv_setpv(sv, "\034");
-           sv_magic(sv, 0, 0, name, 1); 
+           sv_magic(sv, 0, 0, name, 1);
            break;
        case '&':
        case '`':
@@ -671,7 +676,7 @@ Perl_find_threadsv(pTHX_ const char *name)
        /* case '!': */
 
        default:
-           sv_magic(sv, 0, 0, name, 1); 
+           sv_magic(sv, 0, 0, name, 1);
        }
        DEBUG_S(PerlIO_printf(Perl_error_log,
                              "find_threadsv: new SV %p for $%s%c\n",
@@ -780,6 +785,7 @@ S_op_clear(pTHX_ OP *o)
        cSVOPo->op_sv = Nullsv;
 #endif
        break;
+    case OP_METHOD_NAMED:
     case OP_CONST:
        SvREFCNT_dec(cSVOPo->op_sv);
        cSVOPo->op_sv = Nullsv;
@@ -839,14 +845,16 @@ S_cop_free(pTHX_ COP* cop)
 {
     Safefree(cop->cop_label);
 #ifdef USE_ITHREADS
-    Safefree(CopFILE(cop));            /* XXXXX share in a pvtable? */
-    Safefree(CopSTASHPV(cop));         /* XXXXX share in a pvtable? */
+    Safefree(CopFILE(cop));            /* XXX share in a pvtable? */
+    Safefree(CopSTASHPV(cop));         /* XXX share in a pvtable? */
 #else
     /* NOTE: COP.cop_stash is not refcounted */
     SvREFCNT_dec(CopFILEGV(cop));
 #endif
     if (! specialWARN(cop->cop_warnings))
        SvREFCNT_dec(cop->cop_warnings);
+    if (! specialCopIO(cop->cop_io))
+       SvREFCNT_dec(cop->cop_io);
 }
 
 STATIC void
@@ -1017,7 +1025,7 @@ Perl_scalarvoid(pTHX_ OP *o)
     {
        return scalar(o);                       /* As if inside SASSIGN */
     }
-    
+
     o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_VOID;
 
     switch (o->op_type) {
@@ -1160,7 +1168,6 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_DBSTATE:
     case OP_ENTERTRY:
     case OP_ENTER:
-    case OP_SCALAR:
        if (!(o->op_flags & OPf_KIDS))
            break;
        /* FALL THROUGH */
@@ -1179,6 +1186,8 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_REQUIRE:
        /* all requires must return a boolean value */
        o->op_flags &= ~OPf_WANT;
+       /* FALL THROUGH */
+    case OP_SCALAR:
        return scalar(o);
     case OP_SPLIT:
        if ((kid = cLISTOPo->op_first) && kid->op_type == OP_PUSHRE) {
@@ -1223,7 +1232,7 @@ Perl_list(pTHX_ OP *o)
     {
        return o;                               /* As if inside SASSIGN */
     }
-    
+
     o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_LIST;
 
     switch (o->op_type) {
@@ -1335,7 +1344,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
     {
        return o;
     }
-    
+
     switch (o->op_type) {
     case OP_UNDEF:
        PL_modcount++;
@@ -1413,7 +1422,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
                        newop->op_private |= OPpLVAL_INTRO;
                        break;
                    }
-                   
+               
                    if (kid->op_type != OP_RV2CV)
                        Perl_croak(aTHX_
                                   "panic: unexpected lvalue entersub "
@@ -1449,7 +1458,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
                }
                
                cv = GvCV(kGVOP_gv);
-               if (!cv) 
+               if (!cv)
                    goto restore_2cv;
                if (CvLVALUE(cv))
                    break;
@@ -1743,7 +1752,7 @@ Perl_ref(pTHX_ OP *o, I32 type)
            o->op_flags |= OPf_MOD;
        }
        break;
-      
+
     case OP_THREADSV:
        o->op_flags |= OPf_MOD;         /* XXX ??? */
        break;
@@ -1845,6 +1854,37 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs)
     LEAVE;
 }
 
+void
+Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv,
+                        char *attrstr, STRLEN len)
+{
+    OP *attrs = Nullop;
+
+    if (!len) {
+        len = strlen(attrstr);
+    }
+
+    while (len) {
+        for (; isSPACE(*attrstr) && len; --len, ++attrstr) ;
+        if (len) {
+            char *sstr = attrstr;
+            for (; !isSPACE(*attrstr) && len; --len, ++attrstr) ;
+            attrs = append_elem(OP_LIST, attrs,
+                                newSVOP(OP_CONST, 0,
+                                        newSVpvn(sstr, attrstr-sstr)));
+        }
+    }
+
+    Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
+                     newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
+                     Nullsv, prepend_elem(OP_LIST,
+                                 newSVOP(OP_CONST, 0, newSVpv(stashpv,0)),
+                                 prepend_elem(OP_LIST,
+                                              newSVOP(OP_CONST, 0,
+                                                      newRV((SV*)cv)),
+                                               attrs)));
+}
+
 STATIC OP *
 S_my_kid(pTHX_ OP *o, OP *attrs)
 {
@@ -1942,15 +1982,18 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
                             left->op_type == OP_PADAV)
                            ? "@array" : "%hash");
       Perl_warner(aTHX_ WARN_MISC,
-             "Applying %s to %s will act on scalar(%s)", 
+             "Applying %s to %s will act on scalar(%s)",
              desc, sample, sample);
     }
 
-    if (right->op_type == OP_MATCH ||
+    if (!(right->op_flags & OPf_STACKED) &&
+       (right->op_type == OP_MATCH ||
        right->op_type == OP_SUBST ||
-       right->op_type == OP_TRANS) {
+       right->op_type == OP_TRANS)) {
        right->op_flags |= OPf_STACKED;
-       if (right->op_type != OP_MATCH)
+       if (right->op_type != OP_MATCH &&
+            ! (right->op_type == OP_TRANS &&
+               right->op_private & OPpTRANS_IDENTICAL))
            left = mod(left, right->op_type);
        if (right->op_type == OP_TRANS)
            o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right);
@@ -2029,11 +2072,16 @@ Perl_block_start(pTHX_ int full)
     PL_pad_reset_pending = FALSE;
     SAVEHINTS();
     PL_hints &= ~HINT_BLOCK_SCOPE;
-    SAVESPTR(PL_compiling.cop_warnings); 
+    SAVESPTR(PL_compiling.cop_warnings);
     if (! specialWARN(PL_compiling.cop_warnings)) {
         PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ;
         SAVEFREESV(PL_compiling.cop_warnings) ;
     }
+    SAVESPTR(PL_compiling.cop_io);
+    if (! specialCopIO(PL_compiling.cop_io)) {
+        PL_compiling.cop_io = newSVsv(PL_compiling.cop_io) ;
+        SAVEFREESV(PL_compiling.cop_io) ;
+    }
     return retval;
 }
 
@@ -2375,10 +2423,10 @@ Perl_append_list(pTHX_ I32 type, LISTOP *first, LISTOP *last)
     first->op_children += last->op_children;
     if (first->op_children)
        first->op_flags |= OPf_KIDS;
-    
+
 #ifdef PL_OP_SLAB_ALLOC
 #else
-    Safefree(last);     
+    Safefree(last);
 #endif
     return (OP*)first;
 }
@@ -2569,12 +2617,18 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
     del                = o->op_private & OPpTRANS_DELETE;
     squash     = o->op_private & OPpTRANS_SQUASH;
 
+    if (SvUTF8(tstr))
+        o->op_private |= OPpTRANS_FROM_UTF;
+
+    if (SvUTF8(rstr))
+        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;
        U8* tend = t + tlen;
        U8* rend = r + rlen;
-       I32 ulen;
+       STRLEN ulen;
        U32 tfirst = 1;
        U32 tlast = 0;
        I32 tdiff;
@@ -2594,6 +2648,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        if (complement) {
            U8 tmpbuf[UTF8_MAXLEN];
            U8** cp;
+           I32* cl;
            UV nextmin = 0;
            New(1109, cp, tlen, U8*);
            i = 0;
@@ -2609,7 +2664,8 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            qsort(cp, i, sizeof(U8*), utf8compare);
            for (j = 0; j < i; j++) {
                U8 *s = cp[j];
-               UV val = utf8_to_uv(s, &ulen);
+               I32 cur = j < i ? cp[j+1] - s : tend - s;
+               UV  val = utf8_to_uv(s, cur, &ulen, 0);
                s += ulen;
                diff = val - nextmin;
                if (diff > 0) {
@@ -2622,7 +2678,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
                    }
                }
                if (*s == 0xff)
-                   val = utf8_to_uv(s+1, &ulen);
+                   val = utf8_to_uv(s+1, cur - 1, &ulen, 0);
                if (val >= nextmin)
                    nextmin = val + 1;
            }
@@ -2639,24 +2695,21 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            r = t; rlen = tlen; rend = tend;
        }
        if (!squash) {
-           if (to_utf && from_utf) {   /* only counting characters */
-               if (t == r || (tlen == rlen && memEQ(t, r, tlen)))
-                   o->op_private |= OPpTRANS_IDENTICAL;
-           }
-           else {      /* straight latin-1 translation */
-               if (tlen == 4 && memEQ(t, "\0\377\303\277", 4) &&
-                   rlen == 4 && memEQ(r, "\0\377\303\277", 4))
+               if (t == r ||
+                   (tlen == rlen && memEQ((char *)t, (char *)r, tlen)))
+               {
                    o->op_private |= OPpTRANS_IDENTICAL;
-           }
+               }
        }
 
        while (t < tend || tfirst <= tlast) {
            /* see if we need more "t" chars */
            if (tfirst > tlast) {
-               tfirst = (I32)utf8_to_uv(t, &ulen);
+               tfirst = (I32)utf8_to_uv(t, tend - t, &ulen, 0);
                t += ulen;
                if (t < tend && *t == 0xff) {   /* illegal utf8 val indicates range */
-                   tlast = (I32)utf8_to_uv(++t, &ulen);
+                   t++;
+                   tlast = (I32)utf8_to_uv(t, tend - t, &ulen, 0);
                    t += ulen;
                }
                else
@@ -2666,10 +2719,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            /* now see if we need more "r" chars */
            if (rfirst > rlast) {
                if (r < rend) {
-                   rfirst = (I32)utf8_to_uv(r, &ulen);
+                   rfirst = (I32)utf8_to_uv(r, rend - r, &ulen, 0);
                    r += ulen;
                    if (r < rend && *r == 0xff) {       /* illegal utf8 val indicates range */
-                       rlast = (I32)utf8_to_uv(++r, &ulen);
+                       r++;
+                       rlast = (I32)utf8_to_uv(r, rend - r, &ulen, 0);
                        r += ulen;
                    }
                    else
@@ -2746,7 +2800,8 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            SvREFCNT_dec(transv);
 
        if (!del && havefinal)
-           (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5, newSViv((IV)final), 0);
+           (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
+                          newSVuv((UV)final), 0);
 
        if (grows && to_utf)
            o->op_private |= OPpTRANS_GROWS;
@@ -2864,7 +2919,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
        if (PL_hints & HINT_UTF8)
            pm->op_pmdynflags |= PMdf_UTF8;
        if (pm->op_pmflags & PMf_KEEP || !(PL_hints & HINT_RE_EVAL))
-           expr = newUNOP((!(PL_hints & HINT_RE_EVAL) 
+           expr = newUNOP((!(PL_hints & HINT_RE_EVAL)
                            ? OP_REGCRESET
                            : OP_REGCMAYBE),0,expr);
 
@@ -2872,7 +2927,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
        rcop->op_type = OP_REGCOMP;
        rcop->op_ppaddr = PL_ppaddr[OP_REGCOMP];
        rcop->op_first = scalar(expr);
-       rcop->op_flags |= ((PL_hints & HINT_RE_EVAL) 
+       rcop->op_flags |= ((PL_hints & HINT_RE_EVAL)
                           ? (OPf_SPECIAL | OPf_KIDS)
                           : OPf_KIDS);
        rcop->op_private = 1;
@@ -2951,8 +3006,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl)
            }
        }
        if (curop == repl
-           && !(repl_has_vars 
-                && (!pm->op_pmregexp 
+           && !(repl_has_vars
+                && (!pm->op_pmregexp
                     || pm->op_pmregexp->reganch & ROPT_EVAL_SEEN))) {
            pm->op_pmflags |= PMf_CONST;        /* const for long enough */
            pm->op_pmpermflags |= PMf_CONST;    /* const for long enough */
@@ -3221,8 +3276,15 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
            sv = va_arg(*args, SV*);
        }
     }
-    utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
-           veop, modname, imop);
+    {
+       line_t ocopline = PL_copline;
+       int oexpect = PL_expect;
+
+       utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
+               veop, modname, imop);
+       PL_expect = oexpect;
+       PL_copline = ocopline;
+    }
 }
 
 OP *
@@ -3365,7 +3427,11 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                    }
                    else if (curop->op_type == OP_PUSHRE) {
                        if (((PMOP*)curop)->op_pmreplroot) {
+#ifdef USE_ITHREADS
+                           GV *gv = (GV*)PL_curpad[(PADOFFSET)((PMOP*)curop)->op_pmreplroot];
+#else
                            GV *gv = (GV*)((PMOP*)curop)->op_pmreplroot;
+#endif
                            if (gv == PL_defgv || SvCUR(gv) == PL_generation)
                                break;
                            SvCUR(gv) = PL_generation;
@@ -3474,8 +3540,12 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     cop->cop_arybase = PL_curcop->cop_arybase;
     if (specialWARN(PL_curcop->cop_warnings))
         cop->cop_warnings = PL_curcop->cop_warnings ;
-    else 
+    else
         cop->cop_warnings = newSVsv(PL_curcop->cop_warnings) ;
+    if (specialCopIO(PL_curcop->cop_io))
+        cop->cop_io = PL_curcop->cop_io;
+    else
+        cop->cop_io = newSVsv(PL_curcop->cop_io) ;
 
 
     if (PL_copline == NOLINE)
@@ -3485,9 +3555,9 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
         PL_copline = NOLINE;
     }
 #ifdef USE_ITHREADS
-    CopFILE_set(cop, CopFILE(PL_curcop));      /* XXXXX share in a pvtable? */
+    CopFILE_set(cop, CopFILE(PL_curcop));      /* XXX share in a pvtable? */
 #else
-    CopFILEGV_set(cop, (GV*)SvREFCNT_inc(CopFILEGV(PL_curcop)));
+    CopFILEGV_set(cop, CopFILEGV(PL_curcop));
 #endif
     CopSTASH_set(cop, PL_curstash);
 
@@ -3561,7 +3631,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
     }
     if (first->op_type == OP_CONST) {
        if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE))
-           Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional"); 
+           Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional");
        if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
            op_free(first);
            *firstp = Nullop;
@@ -3588,7 +3658,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
        case OP_NULL:
            if (k2 && k2->op_type == OP_READLINE
                  && (k2->op_flags & OPf_STACKED)
-                 && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) 
+                 && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
            {
                warnop = k2->op_type;
            }
@@ -3764,12 +3834,12 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block)
            OP *k1 = ((UNOP*)expr)->op_first;
            OP *k2 = (k1) ? k1->op_sibling : NULL;
            switch (expr->op_type) {
-             case OP_NULL: 
+             case OP_NULL:
                if (k2 && k2->op_type == OP_READLINE
                      && (k2->op_flags & OPf_STACKED)
-                     && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) 
+                     && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
                    expr = newUNOP(OP_DEFINED, 0, expr);
-               break;                                
+               break;
 
              case OP_SASSIGN:
                if (k1->op_type == OP_READDIR
@@ -3819,12 +3889,12 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
        OP *k1 = ((UNOP*)expr)->op_first;
        OP *k2 = (k1) ? k1->op_sibling : NULL;
        switch (expr->op_type) {
-         case OP_NULL: 
+         case OP_NULL:
            if (k2 && k2->op_type == OP_READLINE
                  && (k2->op_flags & OPf_STACKED)
-                 && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) 
+                 && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR))
                expr = newUNOP(OP_DEFINED, 0, expr);
-           break;                                
+           break;
 
          case OP_SASSIGN:
            if (k1->op_type == OP_READDIR
@@ -3847,7 +3917,10 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
        loopflags |= OPpLOOP_CONTINUE;
     }
     if (expr) {
-       cont = append_elem(OP_LINESEQ, cont, newOP(OP_UNSTACK, 0));
+       OP *unstack = newOP(OP_UNSTACK, 0);
+       if (!next)
+           next = unstack;
+       cont = append_elem(OP_LINESEQ, cont, unstack);
        if ((line_t)whileline != NOLINE) {
            PL_copline = whileline;
            cont = append_elem(OP_LINESEQ, cont,
@@ -3870,8 +3943,6 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
        if (listop)
            ((LISTOP*)listop)->op_last->op_next = condop =
                (o == listop ? redo : LINKLIST(o));
-       if (!next)
-           next = condop;
     }
     else
        o = listop;
@@ -3986,7 +4057,7 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo
     }
 #else
     Renew(loop, 1, LOOP);
-#endif 
+#endif
     loop->op_targ = padoff;
     wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont);
     PL_copline = forline;
@@ -4056,6 +4127,10 @@ Perl_cv_undef(pTHX_ CV *cv)
     CvGV(cv) = Nullgv;
     SvREFCNT_dec(CvOUTSIDE(cv));
     CvOUTSIDE(cv) = Nullcv;
+    if (CvCONST(cv)) {
+       SvREFCNT_dec((SV*)CvXSUBANY(cv).any_ptr);
+       CvCONST_off(cv);
+    }
     if (CvPADLIST(cv)) {
        /* may be during global destruction */
        if (SvREFCNT(CvPADLIST(cv))) {
@@ -4256,6 +4331,15 @@ S_cv_clone2(pTHX_ CV *proto, CV *outside)
 #endif
 
     LEAVE;
+
+    if (CvCONST(cv)) {
+       SV* const_sv = op_const_sv(CvSTART(cv), cv);
+       assert(const_sv);
+       /* constant sub () { $x } closing over $x - see lib/constant.pm */
+       SvREFCNT_dec(cv);
+       cv = newCONSTSUB(CvSTASH(proto), 0, const_sv);
+    }
+
     return cv;
 }
 
@@ -4294,12 +4378,25 @@ Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p)
     }
 }
 
+static void const_sv_xsub(pTHXo_ CV* cv);
+
+/*
+=for apidoc cv_const_sv
+
+If C<cv> is a constant sub eligible for inlining. returns the constant
+value returned by the sub.  Otherwise, returns NULL.
+
+Constant subs can be created with C<newCONSTSUB> or as described in
+L<perlsub/"Constant Functions">.
+
+=cut
+*/
 SV *
 Perl_cv_const_sv(pTHX_ CV *cv)
 {
-    if (!cv || !SvPOK(cv) || SvCUR(cv))
+    if (!cv || !CvCONST(cv))
        return Nullsv;
-    return op_const_sv(CvSTART(cv), cv);
+    return (SV*)CvXSUBANY(cv).any_ptr;
 }
 
 SV *
@@ -4309,17 +4406,21 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv)
 
     if (!o)
        return Nullsv;
-    if (o->op_type == OP_LINESEQ && cLISTOPo->op_first) 
+
+    if (o->op_type == OP_LINESEQ && cLISTOPo->op_first)
        o = cLISTOPo->op_first->op_sibling;
 
     for (; o; o = o->op_next) {
        OPCODE type = o->op_type;
 
-       if (sv && o->op_next == o) 
+       if (sv && o->op_next == o)
            return sv;
-       if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK)
-           continue;
+       if (o->op_next != o) {
+           if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK)
+               continue;
+           if (type == OP_DBSTATE)
+               continue;
+       }
        if (type == OP_LEAVESUB || type == OP_RETURN)
            break;
        if (sv)
@@ -4329,7 +4430,17 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv)
        else if ((type == OP_PADSV || type == OP_CONST) && cv) {
            AV* padav = (AV*)(AvARRAY(CvPADLIST(cv))[1]);
            sv = padav ? AvARRAY(padav)[o->op_targ] : Nullsv;
-           if (!sv || (!SvREADONLY(sv) && SvREFCNT(sv) > 1))
+           if (!sv)
+               return Nullsv;
+           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
+                  SvREADONLY_on doesn't lead to problems when leaving
+                  scope.
+               */
+               sv = newSVsv(sv);
+           }
+           if (!SvREADONLY(sv) && SvREFCNT(sv) > 1)
                return Nullsv;
        }
        else
@@ -4371,6 +4482,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch;
     register CV *cv=0;
     I32 ix;
+    SV *const_sv;
 
     name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch;
     if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) {
@@ -4409,17 +4521,26 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        SvREFCNT_dec(PL_compcv);
        cv = PL_compcv = NULL;
        PL_sub_generation++;
-       goto noblock;
+       goto done;
     }
 
-    if (!name || GvCVGEN(gv))
-       cv = Nullcv;
-    else if ((cv = GvCV(gv))) {
-       cv_ckproto(cv, gv, ps);
+    cv = (!name || GvCVGEN(gv)) ? Nullcv : GvCV(gv);
+
+    if (!block || !ps || *ps || attrs)
+       const_sv = Nullsv;
+    else
+       const_sv = op_const_sv(block, Nullcv);
+
+    if (cv) {
+        bool exists = CvROOT(cv) || CvXSUB(cv);
+        /* if the subroutine doesn't exist and wasn't pre-declared
+         * with a prototype, assume it will be AUTOLOADed,
+         * skipping the prototype check
+         */
+        if (exists || SvPOK(cv))
+           cv_ckproto(cv, gv, ps);
        /* already defined (or promised)? */
-       if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
-           SV* const_sv;
-           bool const_changed = TRUE;
+       if (exists || GvASSUMECV(gv)) {
            if (!block && !attrs) {
                /* just a "sub foo;" when &foo is already defined */
                SAVEFREESV(PL_compcv);
@@ -4428,24 +4549,48 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            /* 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)
-               goto withattrs;
-           if ((const_sv = cv_const_sv(cv)))
-               const_changed = sv_cmp(const_sv, op_const_sv(block, Nullcv));
-           if ((const_sv || const_changed) && ckWARN(WARN_REDEFINE))
-           {
-               line_t oldline = CopLINE(PL_curcop);
-               CopLINE_set(PL_curcop, PL_copline);
-               Perl_warner(aTHX_ WARN_REDEFINE,
-                       const_sv ? "Constant subroutine %s redefined"
-                                : "Subroutine %s redefined", name);
-               CopLINE_set(PL_curcop, oldline);
+           if (block) {
+               if (ckWARN(WARN_REDEFINE)
+                   || (CvCONST(cv)
+                       && (!const_sv || sv_cmp(cv_const_sv(cv), const_sv))))
+               {
+                   line_t oldline = CopLINE(PL_curcop);
+                   CopLINE_set(PL_curcop, PL_copline);
+                   Perl_warner(aTHX_ WARN_REDEFINE,
+                       CvCONST(cv) ? "Constant subroutine %s redefined"
+                                   : "Subroutine %s redefined", name);
+                   CopLINE_set(PL_curcop, oldline);
+               }
+               SvREFCNT_dec(cv);
+               cv = Nullcv;
            }
-           SvREFCNT_dec(cv);
-           cv = Nullcv;
        }
     }
-  withattrs:
+    if (const_sv) {
+       SvREFCNT_inc(const_sv);
+       if (cv) {
+           cv_undef(cv);
+#ifdef USE_THREADS
+           New(666, CvMUTEXP(cv), 1, perl_mutex);
+           MUTEX_INIT(CvMUTEXP(cv));
+           CvOWNER(cv) = 0;
+#endif /* USE_THREADS */
+           sv_setpv((SV*)cv, "");  /* prototype is "" */
+           CvXSUBANY(cv).any_ptr = const_sv;
+           CvXSUB(cv) = const_sv_xsub;
+           CvCONST_on(cv);
+           /* XXX Does anybody care that CvFILE(cv) is blank? */
+       }
+       else {
+           GvCV(gv) = Nullcv;
+           cv = newCONSTSUB(NULL, name, const_sv);
+       }
+       op_free(block);
+       SvREFCNT_dec(PL_compcv);
+       PL_compcv = NULL;
+       PL_sub_generation++;
+       goto done;
+    }
     if (attrs) {
        HV *stash;
        SV *rcv;
@@ -4529,12 +4674,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            }
        }
     }
-    if (!block) {
-      noblock:
-       PL_copline = NOLINE;
-       LEAVE_SCOPE(floor);
-       return cv;
-    }
+    if (!block)
+       goto done;
 
     if (AvFILLp(PL_comppad_name) < AvFILLp(PL_comppad))
        av_store(PL_comppad_name, AvFILLp(PL_comppad), Nullsv);
@@ -4573,6 +4714,9 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                PL_curpad[ix] = Nullsv;
            }
        }
+       assert(!CvCONST(cv));
+       if (ps && !*ps && op_const_sv(block, cv))
+           CvCONST_on(cv);
     }
     else {
        AV *av = newAV();                       /* Will be @_ */
@@ -4635,8 +4779,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            if (!PL_beginav)
                PL_beginav = newAV();
            DEBUG_x( dump_sub(gv) );
-           av_push(PL_beginav, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           av_push(PL_beginav, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
            call_list(oldscope, PL_beginav);
 
            PL_curcop = &PL_compiling;
@@ -4648,23 +4792,27 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                PL_endav = newAV();
            DEBUG_x( dump_sub(gv) );
            av_unshift(PL_endav, 1);
-           av_store(PL_endav, 0, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           av_store(PL_endav, 0, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
        else if (strEQ(s, "CHECK") && !PL_error_count) {
            if (!PL_checkav)
                PL_checkav = newAV();
            DEBUG_x( dump_sub(gv) );
+           if (PL_main_start && ckWARN(WARN_VOID))
+               Perl_warner(aTHX_ WARN_VOID, "Too late to run CHECK block");
            av_unshift(PL_checkav, 1);
-           av_store(PL_checkav, 0, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           av_store(PL_checkav, 0, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
        else if (strEQ(s, "INIT") && !PL_error_count) {
            if (!PL_initav)
                PL_initav = newAV();
            DEBUG_x( dump_sub(gv) );
-           av_push(PL_initav, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           if (PL_main_start && ckWARN(WARN_VOID))
+               Perl_warner(aTHX_ WARN_VOID, "Too late to run INIT block");
+           av_push(PL_initav, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
     }
 
@@ -4684,16 +4832,18 @@ eligible for inlining at compile-time.
 =cut
 */
 
-void
+CV *
 Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
 {
     dTHR;
+    CV* cv;
 
     ENTER;
-    SAVECOPLINE(PL_curcop);
-    SAVEHINTS();
 
+    SAVECOPLINE(PL_curcop);
     CopLINE_set(PL_curcop, PL_copline);
+
+    SAVEHINTS();
     PL_hints &= ~HINT_BLOCK_SCOPE;
 
     if (stash) {
@@ -4707,15 +4857,14 @@ Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv)
 #endif
     }
 
-    newATTRSUB(
-       start_subparse(FALSE, 0),
-       newSVOP(OP_CONST, 0, newSVpv(name,0)),
-       newSVOP(OP_CONST, 0, &PL_sv_no),        /* SvPV(&PL_sv_no) == "" -- GMB */
-       Nullop,
-       newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
-    );
+    cv = newXS(name, const_sv_xsub, __FILE__);
+    CvXSUBANY(cv).any_ptr = sv;
+    CvCONST_on(cv);
+    sv_setpv((SV*)cv, "");  /* prototype is "" */
 
     LEAVE;
+
+    return cv;
 }
 
 /*
@@ -4747,7 +4896,10 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
                line_t oldline = CopLINE(PL_curcop);
                if (PL_copline != NOLINE)
                    CopLINE_set(PL_curcop, PL_copline);
-               Perl_warner(aTHX_ WARN_REDEFINE, "Subroutine %s redefined",name);
+               Perl_warner(aTHX_ WARN_REDEFINE,
+                           CvCONST(cv) ? "Constant subroutine %s redefined"
+                                       : "Subroutine %s redefined"
+                           ,name);
                CopLINE_set(PL_curcop, oldline);
            }
            SvREFCNT_dec(cv);
@@ -4790,28 +4942,32 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
        if (strEQ(s, "BEGIN")) {
            if (!PL_beginav)
                PL_beginav = newAV();
-           av_push(PL_beginav, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           av_push(PL_beginav, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
        else if (strEQ(s, "END")) {
            if (!PL_endav)
                PL_endav = newAV();
            av_unshift(PL_endav, 1);
-           av_store(PL_endav, 0, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           av_store(PL_endav, 0, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
        else if (strEQ(s, "CHECK")) {
            if (!PL_checkav)
                PL_checkav = newAV();
+           if (PL_main_start && ckWARN(WARN_VOID))
+               Perl_warner(aTHX_ WARN_VOID, "Too late to run CHECK block");
            av_unshift(PL_checkav, 1);
-           av_store(PL_checkav, 0, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           av_store(PL_checkav, 0, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
        else if (strEQ(s, "INIT")) {
            if (!PL_initav)
                PL_initav = newAV();
-           av_push(PL_initav, SvREFCNT_inc(cv));
-           GvCV(gv) = 0;
+           if (PL_main_start && ckWARN(WARN_VOID))
+               Perl_warner(aTHX_ WARN_VOID, "Too late to run INIT block");
+           av_push(PL_initav, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
        }
     }
     else
@@ -4923,7 +5079,7 @@ OP *
 Perl_oopsHV(pTHX_ OP *o)
 {
     dTHR;
-    
+
     switch (o->op_type) {
     case OP_PADSV:
     case OP_PADAV:
@@ -5155,6 +5311,20 @@ Perl_ck_eval(pTHX_ OP *o)
 }
 
 OP *
+Perl_ck_exit(pTHX_ OP *o)
+{
+#ifdef VMS
+    HV *table = GvHV(PL_hintgv);
+    if (table) {
+       SV **svp = hv_fetch(table, "vmsish_exit", 11, FALSE);
+       if (svp && *svp && SvTRUE(*svp))
+           o->op_private |= OPpEXIT_VMSISH;
+    }
+#endif
+    return ck_fun(o);
+}
+
+OP *
 Perl_ck_exec(pTHX_ OP *o)
 {
     OP *kid;
@@ -5269,7 +5439,7 @@ Perl_ck_rvconst(pTHX_ register OP *o)
                break;
            }
            if (badthing)
-               Perl_croak(aTHX_ 
+               Perl_croak(aTHX_
          "Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use",
                      name, badthing);
        }
@@ -5301,6 +5471,7 @@ Perl_ck_rvconst(pTHX_ register OP *o)
 #ifdef USE_ITHREADS
            /* XXX hack: dependence on sizeof(PADOP) <= sizeof(SVOP) */
            kPADOP->op_padix = pad_alloc(OP_GV, SVs_PADTMP);
+           SvREFCNT_dec(PL_curpad[kPADOP->op_padix]);
            GvIN_PAD_on(gv);
            PL_curpad[kPADOP->op_padix] = SvREFCNT_inc(gv);
 #else
@@ -5497,6 +5668,13 @@ Perl_ck_fun(pTHX_ OP *o)
                                name = GvNAME(gv);
                                len = GvNAMELEN(gv);
                            }
+                           else if (kid->op_type == OP_AELEM
+                                    || kid->op_type == OP_HELEM)
+                           {
+                               name = "__ANONIO__";
+                               len = 10;
+                               mod(kid,type);
+                           }
                            if (name) {
                                SV *namesv;
                                targ = pad_alloc(OP_RV2GV, SVs_PADTMP);
@@ -5675,21 +5853,29 @@ Perl_ck_defined(pTHX_ OP *o)            /* 19990527 MJD */
     if ((o->op_flags & OPf_KIDS) && ckWARN(WARN_DEPRECATED)) {
        switch (cUNOPo->op_first->op_type) {
        case OP_RV2AV:
-           break;                      /* Globals via GV can be undef */ 
+           /* This is needed for
+              if (defined %stash::)
+              to work.   Do not break Tk.
+              */
+           break;                      /* Globals via GV can be undef */
        case OP_PADAV:
        case OP_AASSIGN:                /* Is this a good idea? */
            Perl_warner(aTHX_ WARN_DEPRECATED,
                        "defined(@array) is deprecated");
            Perl_warner(aTHX_ WARN_DEPRECATED,
-                       "(Maybe you should just omit the defined()?)\n");
+                       "\t(Maybe you should just omit the defined()?)\n");
        break;
        case OP_RV2HV:
-           break;                      /* Globals via GV can be undef */ 
+           /* This is needed for
+              if (defined %stash::)
+              to work.   Do not break Tk.
+              */
+           break;                      /* Globals via GV can be undef */
        case OP_PADHV:
            Perl_warner(aTHX_ WARN_DEPRECATED,
                        "defined(%%hash) is deprecated");
            Perl_warner(aTHX_ WARN_DEPRECATED,
-                       "(Maybe you should just omit the defined()?)\n");
+                       "\t(Maybe you should just omit the defined()?)\n");
            break;
        default:
            /* no warning */
@@ -5815,11 +6001,13 @@ Perl_ck_method(pTHX_ OP *o)
        SV* sv = kSVOP->op_sv;
        if (!(strchr(SvPVX(sv), ':') || strchr(SvPVX(sv), '\''))) {
            OP *cmop;
-           (void)SvUPGRADE(sv, SVt_PVIV);
-           (void)SvIOK_on(sv);
-           PERL_HASH(SvUVX(sv), SvPVX(sv), SvCUR(sv));
+           if (!SvREADONLY(sv) || !SvFAKE(sv)) {
+               sv = newSVpvn_share(SvPVX(sv), SvCUR(sv), 0);
+           }
+           else {
+               kSVOP->op_sv = Nullsv;
+           }
            cmop = newSVOP(OP_METHOD_NAMED, 0, sv);
-           kSVOP->op_sv = Nullsv;
            op_free(o);
            return cmop;
        }
@@ -5964,6 +6152,7 @@ Perl_ck_shift(pTHX_ OP *o)
 OP *
 Perl_ck_sort(pTHX_ OP *o)
 {
+    OP *firstkid;
     o->op_private = 0;
 #ifdef USE_LOCALE
     if (PL_hints & HINT_LOCALE)
@@ -5972,10 +6161,10 @@ Perl_ck_sort(pTHX_ OP *o)
 
     if (o->op_type == OP_SORT && o->op_flags & OPf_STACKED)
        simplify_sort(o);
-    if (o->op_flags & OPf_STACKED) {                /* may have been cleared */
-       OP *kid = cLISTOPo->op_first->op_sibling;       /* get past pushmark */
+    firstkid = cLISTOPo->op_first->op_sibling;         /* get past pushmark */
+    if (o->op_flags & OPf_STACKED) {                   /* may have been cleared */
        OP *k;
-       kid = kUNOP->op_first;                          /* get past null */
+       OP *kid = cUNOPx(firstkid)->op_first;           /* get past null */
 
        if (kid->op_type == OP_SCOPE || kid->op_type == OP_LEAVE) {
            linklist(kid);
@@ -5991,6 +6180,12 @@ Perl_ck_sort(pTHX_ OP *o)
                    for (k = kLISTOP->op_first->op_next; k; k = k->op_next) {
                        if (k->op_next == kid)
                            k->op_next = 0;
+                       /* don't descend into loops */
+                       else if (k->op_type == OP_ENTERLOOP
+                                || k->op_type == OP_ENTERITER)
+                       {
+                           k = cLOOPx(k)->op_lastop;
+                       }
                    }
                }
                else
@@ -5999,17 +6194,26 @@ Perl_ck_sort(pTHX_ OP *o)
            }
            peep(k);
 
-           kid = cLISTOPo->op_first->op_sibling;       /* get past pushmark */
-           if (o->op_type == OP_SORT)
+           kid = firstkid;
+           if (o->op_type == OP_SORT) {
+               /* provide scalar context for comparison function/block */
+               kid = scalar(kid);
                kid->op_next = kid;
+           }
            else
                kid->op_next = k;
            o->op_flags |= OPf_SPECIAL;
        }
        else if (kid->op_type == OP_RV2SV || kid->op_type == OP_PADSV)
-           null(cLISTOPo->op_first->op_sibling);
+           null(firstkid);
+
+       firstkid = firstkid->op_sibling;
     }
 
+    /* provide list context for arguments */
+    if (o->op_type == OP_SORT)
+       list(firstkid);
+
     return o;
 }
 
@@ -6023,8 +6227,8 @@ S_simplify_sort(pTHX_ OP *o)
     GV *gv;
     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_fetchpv("a", TRUE, SVt_PV));
+    GvMULTI_on(gv_fetchpv("b", TRUE, SVt_PV));
     kid = kUNOP->op_first;                             /* get past null */
     if (kid->op_type != OP_SCOPE)
        return;
@@ -6098,7 +6302,7 @@ Perl_ck_split(pTHX_ OP *o)
        cLISTOPo->op_last = kid; /* There was only one element previously */
     }
 
-    if (kid->op_type != OP_MATCH) {
+    if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) {
        OP *sibl = kid->op_sibling;
        kid->op_sibling = 0;
        kid = pmruntime( newPMOP(OP_MATCH, OPf_SPECIAL), kid, Nullop);
@@ -6131,7 +6335,7 @@ Perl_ck_split(pTHX_ OP *o)
 }
 
 OP *
-Perl_ck_join(pTHX_ OP *o) 
+Perl_ck_join(pTHX_ OP *o)
 {
     if (ckWARN(WARN_SYNTAX)) {
        OP *kid = cLISTOPo->op_first->op_sibling;
@@ -6215,7 +6419,9 @@ Perl_ck_subr(pTHX_ OP *o)
                proto++;
                arg++;
                if (o2->op_type != OP_REFGEN && o2->op_type != OP_UNDEF)
-                   bad_type(arg, "block", gv_ename(namegv), o2);
+                   bad_type(arg,
+                       arg == 1 ? "block or sub {}" : "sub {}",
+                       gv_ename(namegv), o2);
                break;
            case '*':
                /* '*' allows any scalar type, including bareword */
@@ -6263,8 +6469,8 @@ Perl_ck_subr(pTHX_ OP *o)
                        bad_type(arg, "symbol", gv_ename(namegv), o2);
                    goto wrapref;
                case '&':
-                   if (o2->op_type != OP_RV2CV)
-                       bad_type(arg, "sub", gv_ename(namegv), o2);
+                   if (o2->op_type != OP_ENTERSUB)
+                       bad_type(arg, "subroutine entry", gv_ename(namegv), o2);
                    goto wrapref;
                case '$':
                    if (o2->op_type != OP_RV2SV
@@ -6342,6 +6548,22 @@ Perl_ck_trunc(pTHX_ OP *o)
     return ck_fun(o);
 }
 
+OP *
+Perl_ck_substr(pTHX_ OP *o)
+{
+    o = ck_fun(o);
+    if ((o->op_flags & OPf_KIDS) && o->op_private == 4) {
+       OP *kid = cLISTOPo->op_first;
+
+       if (kid->op_type == OP_NULL)
+           kid = kid->op_sibling;
+       if (kid)
+           kid->op_flags |= OPf_MOD;
+
+    }
+    return o;
+}
+
 /* A peephole optimizer.  We visit the ops in the order they're to execute. */
 
 void
@@ -6381,9 +6603,20 @@ Perl_peep(pTHX_ register OP *o)
             * for reference counts, sv_upgrade() etc. */
            if (cSVOP->op_sv) {
                PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
-               SvREFCNT_dec(PL_curpad[ix]);
-               SvPADTMP_on(cSVOPo->op_sv);
-               PL_curpad[ix] = cSVOPo->op_sv;
+               if (SvPADTMP(cSVOPo->op_sv)) {
+                   /* If op_sv is already a PADTMP then it is being used by
+                    * some pad, so make a copy. */
+                   sv_setsv(PL_curpad[ix],cSVOPo->op_sv);
+                   SvREADONLY_on(PL_curpad[ix]);
+                   SvREFCNT_dec(cSVOPo->op_sv);
+               }
+               else {
+                   SvREFCNT_dec(PL_curpad[ix]);
+                   SvPADTMP_on(cSVOPo->op_sv);
+                   PL_curpad[ix] = cSVOPo->op_sv;
+                   /* XXX I don't know how this isn't readonly already. */
+                   SvREADONLY_on(PL_curpad[ix]);
+               }
                cSVOPo->op_sv = Nullsv;
                o->op_targ = ix;
            }
@@ -6514,7 +6747,7 @@ Perl_peep(pTHX_ register OP *o)
 
        case OP_EXEC:
            o->op_seq = PL_op_seqmax++;
-           if (ckWARN(WARN_SYNTAX) && o->op_next 
+           if (ckWARN(WARN_SYNTAX) && o->op_next
                && o->op_next->op_type == OP_NEXTSTATE) {
                if (o->op_next->op_sibling &&
                        o->op_next->op_sibling->op_type != OP_EXIT &&
@@ -6526,7 +6759,7 @@ Perl_peep(pTHX_ register OP *o)
                    Perl_warner(aTHX_ WARN_EXEC,
                                "Statement unlikely to be reached");
                    Perl_warner(aTHX_ WARN_EXEC,
-                               "(Maybe you meant system() when you said exec()?)\n");
+                               "\t(Maybe you meant system() when you said exec()?)\n");
                    CopLINE_set(PL_curcop, oldline);
                }
            }
@@ -6538,13 +6771,26 @@ Perl_peep(pTHX_ register OP *o)
            GV **fields;
            SV **svp, **indsvp, *sv;
            I32 ind;
-           char *key;
+           char *key = NULL;
            STRLEN keylen;
        
            o->op_seq = PL_op_seqmax++;
-           if ((o->op_private & (OPpLVAL_INTRO))
-               || ((BINOP*)o)->op_last->op_type != OP_CONST)
+
+           if (((BINOP*)o)->op_last->op_type != OP_CONST)
                break;
+
+           /* Make the CONST have a shared SV */
+           svp = cSVOPx_svp(((BINOP*)o)->op_last);
+           if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) && !IS_PADCONST(sv)) {
+               key = SvPV(sv, keylen);
+               lexname = newSVpvn_share(key, keylen, 0);
+               SvREFCNT_dec(sv);
+               *svp = lexname;
+           }
+
+           if ((o->op_private & (OPpLVAL_INTRO)))
+               break;
+
            rop = (UNOP*)((BINOP*)o)->op_first;
            if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
                break;
@@ -6554,7 +6800,6 @@ Perl_peep(pTHX_ register OP *o)
            fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE);
            if (!fields || !GvHV(*fields))
                break;
-           svp = cSVOPx_svp(((BINOP*)o)->op_last);
            key = SvPV(*svp, keylen);
            indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE);
            if (!indsvp) {
@@ -6664,7 +6909,7 @@ Perl_peep(pTHX_ register OP *o)
 
                while (r->op_sibling)
                   r = r->op_sibling;
-               if (r->op_next == o 
+               if (r->op_next == o
                    || (r->op_next->op_type == OP_LIST
                        && r->op_next->op_next == o))
                {
@@ -6685,3 +6930,15 @@ Perl_peep(pTHX_ register OP *o)
     }
     LEAVE;
 }
+
+#include "XSUB.h"
+
+/* Efficient sub that returns a constant scalar value. */
+static void
+const_sv_xsub(pTHXo_ CV* cv)
+{
+    dXSARGS;
+    EXTEND(sp, 1);
+    ST(0) = sv_2mortal(SvREFCNT_inc((SV*)XSANY.any_ptr));
+    XSRETURN(1);
+}