This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove select’s prototype
[perl5.git] / op.c
diff --git a/op.c b/op.c
index fbf3d71..1f6743d 100644 (file)
--- a/op.c
+++ b/op.c
@@ -365,7 +365,7 @@ S_bad_type(pTHX_ I32 n, const char *t, const char *name, const OP *kid)
 }
 
 STATIC void
-S_no_bareword_allowed(pTHX_ const OP *o)
+S_no_bareword_allowed(pTHX_ OP *o)
 {
     PERL_ARGS_ASSERT_NO_BAREWORD_ALLOWED;
 
@@ -374,6 +374,7 @@ S_no_bareword_allowed(pTHX_ const OP *o)
     qerror(Perl_mess(aTHX_
                     "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use",
                     SVfARG(cSVOPo_sv)));
+    o->op_private &= ~OPpCONST_STRICT; /* prevent warning twice about the same OP */
 }
 
 /* "register" allocation */
@@ -387,7 +388,7 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags)
 
     PERL_ARGS_ASSERT_ALLOCMY;
 
-    if (flags)
+    if (flags & ~SVf_UTF8)
        Perl_croak(aTHX_ "panic: allocmy illegal flag bits 0x%" UVxf,
                   (UV)flags);
 
@@ -399,7 +400,7 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags)
     if (len &&
        !(is_our ||
          isALPHA(name[1]) ||
-         (USE_UTF8_IN_NAMES && UTF8_IS_START(name[1])) ||
+         ((flags & SVf_UTF8) && UTF8_IS_START(name[1])) ||
          (name[1] == '_' && (*name == '$' || len > 2))))
     {
        /* name[2] is true if strlen(name) > 2  */
@@ -415,9 +416,10 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags)
 
     /* allocate a spare slot and store the name in that slot */
 
-    off = pad_add_name(name, len,
-                      is_our ? padadd_OUR :
-                      PL_parser->in_my == KEY_state ? padadd_STATE : 0,
+    off = pad_add_name_pvn(name, len,
+                      (is_our ? padadd_OUR :
+                       PL_parser->in_my == KEY_state ? padadd_STATE : 0)
+                            | ( flags & SVf_UTF8 ? SVf_UTF8 : 0 ),
                    PL_parser->in_my_stash,
                    (is_our
                        /* $_ is always in main::, even with our */
@@ -547,18 +549,8 @@ Perl_op_clear(pTHX_ OP *o)
     PERL_ARGS_ASSERT_OP_CLEAR;
 
 #ifdef PERL_MAD
-    /* if (o->op_madprop && o->op_madprop->mad_next)
-       abort(); */
-    /* FIXME for MAD - if I uncomment these two lines t/op/pack.t fails with
-       "modification of a read only value" for a reason I can't fathom why.
-       It's the "" stringification of $_, where $_ was set to '' in a foreach
-       loop, but it defies simplification into a small test case.
-       However, commenting them out has caused ext/List/Util/t/weak.t to fail
-       the last test.  */
-    /*
-      mad_free(o->op_madprop);
-      o->op_madprop = 0;
-    */
+    mad_free(o->op_madprop);
+    o->op_madprop = 0;
 #endif    
 
  retry:
@@ -581,8 +573,7 @@ Perl_op_clear(pTHX_ OP *o)
     case OP_GVSV:
     case OP_GV:
     case OP_AELEMFAST:
-       if (! (o->op_type == OP_AELEMFAST && o->op_flags & OPf_SPECIAL)) {
-           /* not an OP_PADAV replacement */
+       {
            GV *gv = (o->op_type == OP_GV || o->op_type == OP_GVSV)
 #ifdef USE_ITHREADS
                        && PL_curpad
@@ -970,14 +961,9 @@ Perl_scalar(pTHX_ OP *o)
     do_kids:
        while (kid) {
            OP *sib = kid->op_sibling;
-           if (sib && kid->op_type != OP_LEAVEWHEN) {
-               if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) {
-                   scalar(kid);
-                   scalarvoid(sib);
-                   break;
-               } else
-                   scalarvoid(kid);
-           } else
+           if (sib && kid->op_type != OP_LEAVEWHEN)
+               scalarvoid(kid);
+           else
                scalar(kid);
            kid = sib;
        }
@@ -1079,6 +1065,7 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_SPRINTF:
     case OP_AELEM:
     case OP_AELEMFAST:
+    case OP_AELEMFAST_LEX:
     case OP_ASLICE:
     case OP_HELEM:
     case OP_HSLICE:
@@ -1355,14 +1342,9 @@ Perl_list(pTHX_ OP *o)
     do_kids:
        while (kid) {
            OP *sib = kid->op_sibling;
-           if (sib && kid->op_type != OP_LEAVEWHEN) {
-               if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) {
-                   list(kid);
-                   scalarvoid(sib);
-                   break;
-               } else
-                   scalarvoid(kid);
-           } else
+           if (sib && kid->op_type != OP_LEAVEWHEN)
+               scalarvoid(kid);
+           else
                list(kid);
            kid = sib;
        }
@@ -1415,6 +1397,251 @@ S_modkids(pTHX_ OP *o, I32 type)
 }
 
 /*
+=for apidoc finalize_optree
+
+This function finalizes the optree. Should be called directly after
+the complete optree is built. It does some additional
+checking which can't be done in the normal ck_xxx functions and makes
+the tree thread-safe.
+
+=cut
+*/
+void
+Perl_finalize_optree(pTHX_ OP* o)
+{
+    PERL_ARGS_ASSERT_FINALIZE_OPTREE;
+
+    ENTER;
+    SAVEVPTR(PL_curcop);
+
+    finalize_op(o);
+
+    LEAVE;
+}
+
+void
+S_finalize_op(pTHX_ OP* o)
+{
+    PERL_ARGS_ASSERT_FINALIZE_OP;
+
+#if defined(PERL_MAD) && defined(USE_ITHREADS)
+    {
+       /* Make sure mad ops are also thread-safe */
+       MADPROP *mp = o->op_madprop;
+       while (mp) {
+           if (mp->mad_type == MAD_OP && mp->mad_vlen) {
+               OP *prop_op = (OP *) mp->mad_val;
+               /* We only need "Relocate sv to the pad for thread safety.", but this
+                  easiest way to make sure it traverses everything */
+               finalize_op(prop_op);
+           }
+           mp = mp->mad_next;
+       }
+    }
+#endif
+
+    switch (o->op_type) {
+    case OP_NEXTSTATE:
+    case OP_DBSTATE:
+       PL_curcop = ((COP*)o);          /* for warnings */
+       break;
+    case OP_EXEC:
+       if ( o->op_sibling
+           && (o->op_sibling->op_type == OP_NEXTSTATE || o->op_sibling->op_type == OP_DBSTATE)
+           && ckWARN(WARN_SYNTAX))
+           {
+               if (o->op_sibling->op_sibling) {
+                   const OPCODE type = o->op_sibling->op_sibling->op_type;
+                   if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) {
+                       const line_t oldline = CopLINE(PL_curcop);
+                       CopLINE_set(PL_curcop, CopLINE((COP*)o->op_sibling));
+                       Perl_warner(aTHX_ packWARN(WARN_EXEC),
+                           "Statement unlikely to be reached");
+                       Perl_warner(aTHX_ packWARN(WARN_EXEC),
+                           "\t(Maybe you meant system() when you said exec()?)\n");
+                       CopLINE_set(PL_curcop, oldline);
+                   }
+               }
+           }
+       break;
+
+    case OP_GV:
+       if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
+           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 * const sv = sv_newmortal();
+               gv_efullname3(sv, gv, NULL);
+               Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
+                   "%"SVf"() called too early to check prototype",
+                   SVfARG(sv));
+           }
+       }
+       break;
+
+    case OP_CONST:
+       if (cSVOPo->op_private & OPpCONST_STRICT)
+           no_bareword_allowed(o);
+       /* FALLTHROUGH */
+#ifdef USE_ITHREADS
+    case OP_HINTSEVAL:
+    case OP_METHOD_NAMED:
+       /* Relocate sv to the pad for thread safety.
+        * Despite being a "constant", the SV is written to,
+        * for reference counts, sv_upgrade() etc. */
+       if (cSVOPo->op_sv) {
+           const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
+           if (o->op_type != OP_METHOD_NAMED &&
+               (SvPADTMP(cSVOPo->op_sv) || SvPADMY(cSVOPo->op_sv)))
+           {
+               /* If op_sv is already a PADTMP/MY then it is being used by
+                * some pad, so make a copy. */
+               sv_setsv(PAD_SVl(ix),cSVOPo->op_sv);
+               SvREADONLY_on(PAD_SVl(ix));
+               SvREFCNT_dec(cSVOPo->op_sv);
+           }
+           else if (o->op_type != OP_METHOD_NAMED
+               && 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);
+               PAD_SETSV(ix, cSVOPo->op_sv);
+               /* XXX I don't know how this isn't readonly already. */
+               SvREADONLY_on(PAD_SVl(ix));
+           }
+           cSVOPo->op_sv = NULL;
+           o->op_targ = ix;
+       }
+#endif
+       break;
+
+    case OP_HELEM: {
+       UNOP *rop;
+       SV *lexname;
+       GV **fields;
+       SV **svp, *sv;
+       const char *key = NULL;
+       STRLEN keylen;
+
+       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))
+           && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) {
+           key = SvPV_const(sv, keylen);
+           lexname = newSVpvn_share(key,
+               SvUTF8(sv) ? -(I32)keylen : (I32)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;
+       lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
+       if (!SvPAD_TYPED(lexname))
+           break;
+       fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
+       if (!fields || !GvHV(*fields))
+           break;
+       key = SvPV_const(*svp, keylen);
+       if (!hv_fetch(GvHV(*fields), key,
+               SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) {
+           Perl_croak(aTHX_ "No such class field \"%s\" "
+               "in variable %s of type %s",
+               key, SvPV_nolen_const(lexname), HvNAME_get(SvSTASH(lexname)));
+       }
+       break;
+    }
+
+    case OP_HSLICE: {
+       UNOP *rop;
+       SV *lexname;
+       GV **fields;
+       SV **svp;
+       const char *key;
+       STRLEN keylen;
+       SVOP *first_key_op, *key_op;
+
+       if ((o->op_private & (OPpLVAL_INTRO))
+           /* I bet there's always a pushmark... */
+           || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
+           /* hmmm, no optimization if list contains only one key. */
+           break;
+       rop = (UNOP*)((LISTOP*)o)->op_last;
+       if (rop->op_type != OP_RV2HV)
+           break;
+       if (rop->op_first->op_type == OP_PADSV)
+           /* @$hash{qw(keys here)} */
+           rop = (UNOP*)rop->op_first;
+       else {
+           /* @{$hash}{qw(keys here)} */
+           if (rop->op_first->op_type == OP_SCOPE
+               && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV)
+               {
+                   rop = (UNOP*)cLISTOPx(rop->op_first)->op_last;
+               }
+           else
+               break;
+       }
+
+       lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE);
+       if (!SvPAD_TYPED(lexname))
+           break;
+       fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
+       if (!fields || !GvHV(*fields))
+           break;
+       /* Again guessing that the pushmark can be jumped over.... */
+       first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
+           ->op_first->op_sibling;
+       for (key_op = first_key_op; key_op;
+            key_op = (SVOP*)key_op->op_sibling) {
+           if (key_op->op_type != OP_CONST)
+               continue;
+           svp = cSVOPx_svp(key_op);
+           key = SvPV_const(*svp, keylen);
+           if (!hv_fetch(GvHV(*fields), key,
+                   SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) {
+               Perl_croak(aTHX_ "No such class field \"%s\" "
+                   "in variable %s of type %s",
+                   key, SvPV_nolen(lexname), HvNAME_get(SvSTASH(lexname)));
+           }
+       }
+       break;
+    }
+    case OP_SUBST: {
+       if (cPMOPo->op_pmreplrootu.op_pmreplroot)
+           finalize_op(cPMOPo->op_pmreplrootu.op_pmreplroot);
+       break;
+    }
+    default:
+       break;
+    }
+
+    if (o->op_flags & OPf_KIDS) {
+       OP *kid;
+       for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling)
+           finalize_op(kid);
+    }
+}
+
+/*
 =for apidoc Amx|OP *|op_lvalue|OP *o|I32 type
 
 Propagate lvalue ("modifiable") context to an op and its children.
@@ -1434,7 +1661,7 @@ such as C<$$x = 5> which might have to vivify a reference in C<$x>.
 */
 
 OP *
-Perl_op_lvalue(pTHX_ OP *o, I32 type)
+Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
 {
     dVAR;
     OP *kid;
@@ -1481,9 +1708,8 @@ Perl_op_lvalue(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.  */
+           /* Both ENTERSUB and RV2CV use this bit, but for different pur-
+              poses, so we need it clear.  */
            o->op_private &= ~1;
            o->op_ppaddr = PL_ppaddr[OP_RV2CV];
            assert(cUNOPo->op_first->op_type == OP_NULL);
@@ -1493,7 +1719,8 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
        else if (o->op_private & OPpENTERSUB_NOMOD)
            return o;
        else {                          /* lvalue subroutine call */
-           o->op_private |= OPpLVAL_INTRO;
+           o->op_private |= OPpLVAL_INTRO
+                          |(OPpENTERSUB_INARGS * (type == OP_LEAVESUBLV));
            PL_modcount = RETURN_UNLIMITED_NUMBER;
            if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN) {
                /* Backward compatibility mode: */
@@ -1578,8 +1805,10 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
        /* FALL THROUGH */
     default:
       nomod:
+       if (flags & OP_LVALUE_NO_CROAK) return NULL;
        /* grep, foreach, subcalls, refgen */
-       if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN)
+       if (type == OP_GREPSTART || type == OP_ENTERSUB
+        || type == OP_REFGEN    || type == OP_LEAVESUBLV)
            break;
        yyerror(Perl_form(aTHX_ "Can't modify %s in %s",
                     (o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL)
@@ -1664,6 +1893,7 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
        break;
 
     case OP_AELEMFAST:
+    case OP_AELEMFAST_LEX:
        localize = -1;
        PL_modcount++;
        break;
@@ -1681,8 +1911,8 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
     case OP_PADSV:
        PL_modcount++;
        if (!type) /* local() */
-           Perl_croak(aTHX_ "Can't localize lexical variable %s",
-                PAD_COMPNAME_PV(o->op_targ));
+           Perl_croak(aTHX_ "Can't localize lexical variable %"SVf,
+                PAD_COMPNAME_SV(o->op_targ));
        break;
 
     case OP_PUSHMARK:
@@ -1690,7 +1920,8 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
        break;
 
     case OP_KEYS:
-       if (type != OP_SASSIGN)
+    case OP_RKEYS:
+       if (type != OP_SASSIGN && type != OP_LEAVESUBLV)
            goto nomod;
        goto lvalue_func;
     case OP_SUBSTR:
@@ -1699,9 +1930,9 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
        /* FALL THROUGH */
     case OP_POS:
     case OP_VEC:
+      lvalue_func:
        if (type == OP_LEAVESUBLV)
            o->op_private |= OPpMAYBE_LVSUB;
-      lvalue_func:
        pad_free(o->op_targ);
        o->op_targ = pad_alloc(o->op_type, SVs_PADMY);
        assert(SvTYPE(PAD_SV(o->op_targ)) == SVt_NULL);
@@ -1785,18 +2016,10 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
     return o;
 }
 
-/* Do not use this. It will be removed after 5.14. */
-OP *
-Perl_mod(pTHX_ OP *o, I32 type)
-{
-    return op_lvalue(o,type);
-}
-
-
 STATIC bool
 S_scalar_mod_type(const OP *o, I32 type)
 {
-    PERL_ARGS_ASSERT_SCALAR_MOD_TYPE;
+    assert(o || type != OP_SASSIGN);
 
     switch (type) {
     case OP_SASSIGN:
@@ -1893,7 +2116,7 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref)
 
     switch (o->op_type) {
     case OP_ENTERSUB:
-       if ((type == OP_EXISTS || type == OP_DEFINED || type == OP_LOCK) &&
+       if ((type == OP_EXISTS || type == OP_DEFINED) &&
            !(o->op_flags & OPf_STACKED)) {
            o->op_type = OP_RV2CV;             /* entersub => rv2cv */
            o->op_ppaddr = PL_ppaddr[OP_RV2CV];
@@ -1902,6 +2125,11 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref)
            o->op_flags |= OPf_SPECIAL;
            o->op_private &= ~1;
        }
+       else if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV){
+           o->op_private |= OPpENTERSUB_DEREF;
+           o->op_flags |= OPf_MOD;
+       }
+
        break;
 
     case OP_COND_EXPR:
@@ -2247,8 +2475,19 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs)
            o = scalar(op_append_list(OP_LIST, rops, o));
            o->op_private |= OPpLVAL_INTRO;
        }
-       else
+       else {
+           /* The listop in rops might have a pushmark at the beginning,
+              which will mess up list assignment. */
+           LISTOP * const lrops = (LISTOP *)rops; /* for brevity */
+           if (rops->op_type == OP_LIST && 
+               lrops->op_first && lrops->op_first->op_type == OP_PUSHMARK)
+           {
+               OP * const pushmark = lrops->op_first;
+               lrops->op_first = pushmark->op_sibling;
+               op_free(pushmark);
+           }
            o = op_append_list(OP_LIST, o, rops);
+       }
     }
     PL_parser->in_my = FALSE;
     PL_parser->in_my_stash = NULL;
@@ -2450,7 +2689,7 @@ STATIC OP *
 S_newDEFSVOP(pTHX)
 {
     dVAR;
-    const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0);
+    const PADOFFSET offset = pad_findmy_pvs("$_", 0);
     if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) {
        return newSVREF(newGVOP(OP_GV, 0, PL_defgv));
     }
@@ -2469,11 +2708,23 @@ Perl_newPROG(pTHX_ OP *o)
     PERL_ARGS_ASSERT_NEWPROG;
 
     if (PL_in_eval) {
+       PERL_CONTEXT *cx;
        if (PL_eval_root)
                return;
        PL_eval_root = newUNOP(OP_LEAVEEVAL,
                               ((PL_in_eval & EVAL_KEEPERR)
                                ? OPf_SPECIAL : 0), o);
+
+       cx = &cxstack[cxstack_ix];
+       assert(CxTYPE(cx) == CXt_EVAL);
+
+       if ((cx->blk_gimme & G_WANT) == G_VOID)
+           scalarvoid(PL_eval_root);
+       else if ((cx->blk_gimme & G_WANT) == G_ARRAY)
+           list(PL_eval_root);
+       else
+           scalar(PL_eval_root);
+
        /* don't use LINKLIST, since PL_eval_root might indirect through
         * a rather expensive function call and LINKLIST evaluates its
         * argument more than once */
@@ -2482,6 +2733,8 @@ Perl_newPROG(pTHX_ OP *o)
        OpREFCNT_set(PL_eval_root, 1);
        PL_eval_root->op_next = 0;
        CALL_PEEP(PL_eval_start);
+       finalize_optree(PL_eval_root);
+
     }
     else {
        if (o->op_type == OP_STUB) {
@@ -2497,6 +2750,7 @@ Perl_newPROG(pTHX_ OP *o)
        OpREFCNT_set(PL_main_root, 1);
        PL_main_root->op_next = 0;
        CALL_PEEP(PL_main_start);
+       finalize_optree(PL_main_root);
        PL_compcv = 0;
 
        /* Register with debugger */
@@ -2682,8 +2936,16 @@ S_fold_constants(pTHX_ register OP *o)
     case 0:
        CALLRUNOPS(aTHX);
        sv = *(PL_stack_sp--);
-       if (o->op_targ && sv == PAD_SV(o->op_targ))     /* grab pad temp? */
+       if (o->op_targ && sv == PAD_SV(o->op_targ)) {   /* grab pad temp? */
+#ifdef PERL_MAD
+           /* Can't simply swipe the SV from the pad, because that relies on
+              the op being freed "real soon now". Under MAD, this doesn't
+              happen (see the #ifdef below).  */
+           sv = newSVsv(sv);
+#else
            pad_swipe(o->op_targ,  FALSE);
+#endif
+       }
        else if (SvTEMP(sv)) {                  /* grab mortal temp? */
            SvREFCNT_inc_simple_void(sv);
            SvTEMP_off(sv);
@@ -3138,8 +3400,7 @@ Perl_newMADsv(pTHX_ char key, SV* sv)
 MADPROP *
 Perl_newMADPROP(pTHX_ char key, char type, void* val, I32 vlen)
 {
-    MADPROP *mp;
-    Newxz(mp, 1, MADPROP);
+    MADPROP *const mp = (MADPROP *) PerlMemShared_malloc(sizeof(MADPROP));
     mp->mad_next = 0;
     mp->mad_key = key;
     mp->mad_vlen = vlen;
@@ -3176,7 +3437,7 @@ Perl_mad_free(pTHX_ MADPROP* mp)
        PerlIO_printf(PerlIO_stderr(), "Unrecognized mad\n");
        break;
     }
-    Safefree(mp);
+    PerlMemShared_free(mp);
 }
 
 #endif
@@ -3792,7 +4053,7 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags)
          PL_compiling.cop_hints_hash, STR_WITH_LEN("reflags_charset"), 0, 0
         );
         if (reflags && SvOK(reflags)) {
-            set_regex_charset(&(pmop->op_pmflags), SvIV(reflags));
+            set_regex_charset(&(pmop->op_pmflags), (regex_charset)SvIV(reflags));
         }
     }
 
@@ -3885,7 +4146,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
 
     if (expr->op_type == OP_CONST) {
        SV *pat = ((SVOP*)expr)->op_sv;
-       U32 pm_flags = pm->op_pmflags & PMf_COMPILETIME;
+       U32 pm_flags = pm->op_pmflags & RXf_PMf_COMPILETIME;
 
        if (o->op_flags & OPf_SPECIAL)
            pm_flags |= RXf_SPLIT;
@@ -4356,6 +4617,8 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
     PL_parser->copline = NOLINE;
     PL_parser->expect = XSTATE;
     PL_cop_seqmax++; /* Purely for B::*'s benefit */
+    if (PL_cop_seqmax == PERL_PADSEQ_INTRO) /* not a legal value */
+       PL_cop_seqmax++;
 
 #ifdef PERL_MAD
     if (!PL_madskills) {
@@ -4451,7 +4714,7 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
 
     ENTER;
     SAVEVPTR(PL_curcop);
-    lex_start(NULL, NULL, 0);
+    lex_start(NULL, NULL, LEX_START_SAME_FILTER);
     utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
            veop, modname, imop);
     LEAVE;
@@ -4555,6 +4818,76 @@ S_is_list_assignment(pTHX_ register const OP *o)
 }
 
 /*
+  Helper function for newASSIGNOP to detection commonality between the
+  lhs and the rhs.  Marks all variables with PL_generation.  If it
+  returns TRUE the assignment must be able to handle common variables.
+*/
+PERL_STATIC_INLINE bool
+S_aassign_common_vars(pTHX_ OP* o)
+{
+    OP *curop;
+    for (curop = cUNOPo->op_first; curop; curop=curop->op_sibling) {
+       if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
+           if (curop->op_type == OP_GV) {
+               GV *gv = cGVOPx_gv(curop);
+               if (gv == PL_defgv
+                   || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+                   return TRUE;
+               GvASSIGN_GENERATION_set(gv, PL_generation);
+           }
+           else if (curop->op_type == OP_PADSV ||
+               curop->op_type == OP_PADAV ||
+               curop->op_type == OP_PADHV ||
+               curop->op_type == OP_PADANY)
+               {
+                   if (PAD_COMPNAME_GEN(curop->op_targ)
+                       == (STRLEN)PL_generation)
+                       return TRUE;
+                   PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation);
+
+               }
+           else if (curop->op_type == OP_RV2CV)
+               return TRUE;
+           else if (curop->op_type == OP_RV2SV ||
+               curop->op_type == OP_RV2AV ||
+               curop->op_type == OP_RV2HV ||
+               curop->op_type == OP_RV2GV) {
+               if (cUNOPx(curop)->op_first->op_type != OP_GV)  /* funny deref? */
+                   return TRUE;
+           }
+           else if (curop->op_type == OP_PUSHRE) {
+#ifdef USE_ITHREADS
+               if (((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff) {
+                   GV *const gv = MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff));
+                   if (gv == PL_defgv
+                       || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+                       return TRUE;
+                   GvASSIGN_GENERATION_set(gv, PL_generation);
+               }
+#else
+               GV *const gv
+                   = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv;
+               if (gv) {
+                   if (gv == PL_defgv
+                       || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+                       return TRUE;
+                   GvASSIGN_GENERATION_set(gv, PL_generation);
+               }
+#endif
+           }
+           else
+               return TRUE;
+       }
+
+       if (curop->op_flags & OPf_KIDS) {
+           if (aassign_common_vars(curop))
+               return TRUE;
+       }
+    }
+    return FALSE;
+}
+
+/*
 =for apidoc Am|OP *|newASSIGNOP|I32 flags|OP *left|I32 optype|OP *right
 
 Constructs, checks, and returns an assignment op.  I<left> and I<right>
@@ -4692,64 +5025,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
         */
 
        if (maybe_common_vars) {
-           OP *lastop = o;
            PL_generation++;
-           for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
-               if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
-                   if (curop->op_type == OP_GV) {
-                       GV *gv = cGVOPx_gv(curop);
-                       if (gv == PL_defgv
-                           || (int)GvASSIGN_GENERATION(gv) == PL_generation)
-                           break;
-                       GvASSIGN_GENERATION_set(gv, PL_generation);
-                   }
-                   else if (curop->op_type == OP_PADSV ||
-                            curop->op_type == OP_PADAV ||
-                            curop->op_type == OP_PADHV ||
-                            curop->op_type == OP_PADANY)
-                   {
-                       if (PAD_COMPNAME_GEN(curop->op_targ)
-                                                   == (STRLEN)PL_generation)
-                           break;
-                       PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation);
-
-                   }
-                   else if (curop->op_type == OP_RV2CV)
-                       break;
-                   else if (curop->op_type == OP_RV2SV ||
-                            curop->op_type == OP_RV2AV ||
-                            curop->op_type == OP_RV2HV ||
-                            curop->op_type == OP_RV2GV) {
-                       if (lastop->op_type != OP_GV)   /* funny deref? */
-                           break;
-                   }
-                   else if (curop->op_type == OP_PUSHRE) {
-#ifdef USE_ITHREADS
-                       if (((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff) {
-                           GV *const gv = MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff));
-                           if (gv == PL_defgv
-                               || (int)GvASSIGN_GENERATION(gv) == PL_generation)
-                               break;
-                           GvASSIGN_GENERATION_set(gv, PL_generation);
-                       }
-#else
-                       GV *const gv
-                           = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv;
-                       if (gv) {
-                           if (gv == PL_defgv
-                               || (int)GvASSIGN_GENERATION(gv) == PL_generation)
-                               break;
-                           GvASSIGN_GENERATION_set(gv, PL_generation);
-                       }
-#endif
-                   }
-                   else
-                       break;
-               }
-               lastop = curop;
-           }
-           if (curop != o)
+           if (aassign_common_vars(o))
                o->op_private |= OPpASSIGN_COMMON;
+           LINKLIST(o);
        }
 
        if (right && right->op_type == OP_SPLIT && !PL_madskills) {
@@ -4875,7 +5154,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
     CopHINTHASH_set(cop, cophh_copy(CopHINTHASH_get(PL_curcop)));
     if (label) {
-       Perl_store_cop_label(aTHX_ cop, label, strlen(label), 0);
+       Perl_cop_store_label(aTHX_ cop, label, strlen(label), 0);
                                                     
        PL_hints |= HINT_BLOCK_SCOPE;
        /* It seems that we need to defer freeing this pointer, as other parts
@@ -5103,7 +5382,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
            if (k1->op_type == OP_READDIR
                  || k1->op_type == OP_GLOB
                  || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB)
-                 || k1->op_type == OP_EACH)
+                 || k1->op_type == OP_EACH
+                 || k1->op_type == OP_AEACH)
            {
                warnop = ((k1->op_type == OP_NULL)
                          ? (OPCODE)k1->op_targ : k1->op_type);
@@ -5289,6 +5569,12 @@ Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right)
     flip->op_private =  left->op_type == OP_CONST ? OPpFLIP_LINENUM : 0;
     flop->op_private = right->op_type == OP_CONST ? OPpFLIP_LINENUM : 0;
 
+    /* check barewords before they might be optimized aways */
+    if (flip->op_private && cSVOPx(left)->op_private & OPpCONST_STRICT)
+       no_bareword_allowed(left);
+    if (flop->op_private && cSVOPx(right)->op_private & OPpCONST_STRICT)
+       no_bareword_allowed(right);
+
     flip->op_next = o;
     if (!flip->op_private || !flop->op_private)
        LINKLIST(o);            /* blow off optimizer unless constant */
@@ -5347,7 +5633,8 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block)
                if (k1 && (k1->op_type == OP_READDIR
                      || k1->op_type == OP_GLOB
                      || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB)
-                     || k1->op_type == OP_EACH))
+                     || k1->op_type == OP_EACH
+                     || k1->op_type == OP_AEACH))
                    expr = newUNOP(OP_DEFINED, 0, expr);
                break;
            }
@@ -5435,7 +5722,8 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop,
                if (k1 && (k1->op_type == OP_READDIR
                      || k1->op_type == OP_GLOB
                      || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB)
-                     || k1->op_type == OP_EACH))
+                     || k1->op_type == OP_EACH
+                     || k1->op_type == OP_AEACH))
                    expr = newUNOP(OP_DEFINED, 0, expr);
                break;
            }
@@ -5577,7 +5865,7 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont)
        }
     }
     else {
-        const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0);
+        const PADOFFSET offset = pad_findmy_pvs("$_", 0);
        if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) {
            sv = newGVOP(OP_GV, 0, PL_defgv);
        }
@@ -5916,10 +6204,7 @@ Perl_newWHENOP(pTHX_ OP *cond, OP *block)
                scalar(ref_array_or_hash(cond)));
     }
     
-    return newGIVWHENOP(
-       cond_op,
-       op_append_elem(block->op_type, block, newOP(OP_BREAK, OPf_SPECIAL)),
-       OP_ENTERWHEN, OP_LEAVEWHEN, 0);
+    return newGIVWHENOP(cond_op, block, OP_ENTERWHEN, OP_LEAVEWHEN, 0);
 }
 
 void
@@ -6194,13 +6479,18 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 #ifdef PERL_MAD
                 || block->op_type == OP_NULL
 #endif
-                )&& !attrs) {
+                )) {
                if (CvFLAGS(PL_compcv)) {
                    /* might have had built-in attrs applied */
-                   if (CvLVALUE(PL_compcv) && ! CvLVALUE(cv) && ckWARN(WARN_MISC))
+                   const bool pureperl = !CvISXSUB(cv) && CvROOT(cv);
+                   if (CvLVALUE(PL_compcv) && ! CvLVALUE(cv) && pureperl
+                    && ckWARN(WARN_MISC))
                        Perl_warner(aTHX_ packWARN(WARN_MISC), "lvalue attribute ignored after the subroutine has been defined");
-                   CvFLAGS(cv) |= (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS & ~CVf_LVALUE);
+                   CvFLAGS(cv) |=
+                       (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS
+                         & ~(CVf_LVALUE * pureperl));
                }
+               if (attrs) goto attrs;
                /* just a "sub foo;" when &foo is already defined */
                SAVEFREESV(PL_compcv);
                goto done;
@@ -6244,7 +6534,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            CvISXSUB_on(cv);
        }
        else {
-           GvCV(gv) = NULL;
+           GvCV_set(gv, NULL);
            cv = newCONSTSUB(NULL, name, const_sv);
        }
         mro_method_changed_in( /* sub Foo::Bar () { 123 } */
@@ -6309,7 +6599,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     else {
        cv = PL_compcv;
        if (name) {
-           GvCV(gv) = cv;
+           GvCV_set(gv, cv);
            if (PL_madskills) {
                if (strEQ(name, "import")) {
                    PL_formfeed = MUTABLE_SV(cv);
@@ -6326,6 +6616,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        CvFILE_set_from_cop(cv, PL_curcop);
        CvSTASH_set(cv, PL_curstash);
     }
+  attrs:
     if (attrs) {
        /* Need to do a C<use attributes $stash_of_cv,\&cv,@attrs>. */
        HV *stash = name && GvSTASH(CvGV(cv)) ? GvSTASH(CvGV(cv)) : PL_curstash;
@@ -6364,14 +6655,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        exit.  */
        
     PL_breakable_sub_gen++;
-    if (CvLVALUE(cv)) {
-       CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0,
-                            op_lvalue(scalarseq(block), OP_LEAVESUBLV));
-       block->op_attached = 1;
-    }
-    else {
-       /* This makes sub {}; work as expected.  */
-       if (block->op_type == OP_STUB) {
+    /* This makes sub {}; work as expected.  */
+    if (block->op_type == OP_STUB) {
            OP* const newblock = newSTATEOP(0, NULL, 0);
 #ifdef PERL_MAD
            op_getmad(block,newblock,'B');
@@ -6379,16 +6664,18 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            op_free(block);
 #endif
            block = newblock;
-       }
-       else
-           block->op_attached = 1;
-       CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block));
     }
+    else block->op_attached = 1;
+    CvROOT(cv) = CvLVALUE(cv)
+                  ? newUNOP(OP_LEAVESUBLV, 0,
+                            op_lvalue(scalarseq(block), OP_LEAVESUBLV))
+                  : newUNOP(OP_LEAVESUB, 0, scalarseq(block));
     CvROOT(cv)->op_private |= OPpREFCOUNTED;
     OpREFCNT_set(CvROOT(cv), 1);
     CvSTART(cv) = LINKLIST(CvROOT(cv));
     CvROOT(cv)->op_next = 0;
     CALL_PEEP(CvSTART(cv));
+    finalize_optree(CvROOT(cv));
 
     /* now that optimizer has done its work, adjust pad values */
 
@@ -6455,7 +6742,7 @@ S_process_special_blocks(pTHX_ const char *const fullname, GV *const gv,
 
            DEBUG_x( dump_sub(gv) );
            Perl_av_create_and_push(aTHX_ &PL_beginav, MUTABLE_SV(cv));
-           GvCV(gv) = 0;               /* cv has been hijacked */
+           GvCV_set(gv,0);             /* cv has been hijacked */
            call_list(oldscope, PL_beginav);
 
            PL_curcop = &PL_compiling;
@@ -6499,7 +6786,7 @@ S_process_special_blocks(pTHX_ const char *const fullname, GV *const gv,
        } else
            return;
        DEBUG_x( dump_sub(gv) );
-       GvCV(gv) = 0;           /* cv has been hijacked */
+       GvCV_set(gv,0);         /* cv has been hijacked */
     }
 }
 
@@ -6677,7 +6964,7 @@ Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename)
     else {
        cv = MUTABLE_CV(newSV_type(SVt_PVCV));
        if (name) {
-           GvCV(gv) = cv;
+           GvCV_set(gv,cv);
            GvCVGEN(gv) = 0;
             mro_method_changed_in(GvSTASH(gv)); /* newXS */
        }
@@ -6744,6 +7031,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
     CvSTART(cv) = LINKLIST(CvROOT(cv));
     CvROOT(cv)->op_next = 0;
     CALL_PEEP(CvSTART(cv));
+    finalize_optree(CvROOT(cv));
 #ifdef PERL_MAD
     op_getmad(o,pegop,'n');
     op_getmad_weak(block, pegop, 'b');
@@ -6913,7 +7201,7 @@ Perl_ck_anoncode(pTHX_ OP *o)
 {
     PERL_ARGS_ASSERT_CK_ANONCODE;
 
-    cSVOPo->op_targ = pad_add_anon(cSVOPo->op_sv, o->op_type);
+    cSVOPo->op_targ = pad_add_anon((CV*)cSVOPo->op_sv, o->op_type);
     if (!PL_madskills)
        cSVOPo->op_sv = NULL;
     return o;
@@ -7332,8 +7620,10 @@ Perl_ck_ftst(pTHX_ OP *o)
        if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o->op_type))
            o->op_private |= OPpFT_ACCESS;
        if (PL_check[kidtype] == Perl_ck_ftst
-               && kidtype != OP_STAT && kidtype != OP_LSTAT)
+               && kidtype != OP_STAT && kidtype != OP_LSTAT) {
            o->op_private |= OPpFT_STACKED;
+           kid->op_private |= OPpFT_STACKING;
+       }
     }
     else {
 #ifdef PERL_MAD
@@ -7432,9 +7722,15 @@ Perl_ck_fun(pTHX_ OP *o)
                    kid->op_sibling = sibl;
                    *tokid = kid;
                }
-               else if (kid->op_type != OP_RV2AV && kid->op_type != OP_PADAV)
+               else if (kid->op_type == OP_CONST
+                     && (  !SvROK(cSVOPx_sv(kid)) 
+                        || SvTYPE(SvRV(cSVOPx_sv(kid))) != SVt_PVAV  )
+                       )
                    bad_type(numargs, "array", PL_op_desc[type], kid);
-               op_lvalue(kid, type);
+               /* Defer checks to run-time if we have a scalar arg */
+               if (kid->op_type == OP_RV2AV || kid->op_type == OP_PADAV)
+                   op_lvalue(kid, type);
+               else scalar(kid);
                break;
            case OA_HVREF:
                if (kid->op_type == OP_CONST &&
@@ -7645,7 +7941,6 @@ Perl_ck_glob(pTHX_ OP *o)
     }
 
 #if !defined(PERL_EXTERNAL_GLOB)
-    /* XXX this can be tightened up and made more failsafe. */
     if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) {
        GV *glob_gv;
        ENTER;
@@ -7653,7 +7948,7 @@ Perl_ck_glob(pTHX_ OP *o)
                newSVpvs("File::Glob"), NULL, NULL, NULL);
        if((glob_gv = gv_fetchpvs("File::Glob::csh_glob", 0, SVt_PVCV))) {
            gv = gv_fetchpvs("CORE::GLOBAL::glob", 0, SVt_PVCV);
-           GvCV(gv) = GvCV(glob_gv);
+           GvCV_set(gv, GvCV(glob_gv));
            SvREFCNT_inc_void(MUTABLE_SV(GvCV(gv)));
            GvIMPORTED_CV_on(gv);
        }
@@ -7743,7 +8038,7 @@ Perl_ck_grep(pTHX_ OP *o)
     gwop->op_flags |= OPf_KIDS;
     gwop->op_other = LINKLIST(kid);
     kid->op_next = (OP*)gwop;
-    offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0);
+    offset = pad_findmy_pvs("$_", 0);
     if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) {
        o->op_private = gwop->op_private = 0;
        gwop->op_targ = pad_alloc(type, SVs_PADTMP);
@@ -7771,8 +8066,11 @@ Perl_ck_index(pTHX_ OP *o)
        OP *kid = cLISTOPo->op_first->op_sibling;       /* get past pushmark */
        if (kid)
            kid = kid->op_sibling;                      /* get past "big" */
-       if (kid && kid->op_type == OP_CONST)
+       if (kid && kid->op_type == OP_CONST) {
+           const bool save_taint = PL_tainted;
            fbm_compile(((SVOP*)kid)->op_sv, 0);
+           PL_tainted = save_taint;
+       }
     }
     return ck_fun(o);
 }
@@ -7990,7 +8288,7 @@ Perl_ck_match(pTHX_ OP *o)
     PERL_ARGS_ASSERT_CK_MATCH;
 
     if (o->op_type != OP_QR && PL_compcv) {
-       const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0);
+       const PADOFFSET offset = pad_findmy_pvs("$_", 0);
        if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS_isOUR(offset))) {
            o->op_targ = offset;
            o->op_private |= OPpTARGET_MY;
@@ -8204,19 +8502,6 @@ Perl_ck_return(pTHX_ OP *o)
     if (CvLVALUE(PL_compcv)) {
        for (; kid; kid = kid->op_sibling)
            op_lvalue(kid, OP_LEAVESUBLV);
-    } else {
-       for (; kid; kid = kid->op_sibling)
-           if ((kid->op_type == OP_NULL)
-               && ((kid->op_flags & (OPf_SPECIAL|OPf_KIDS)) == (OPf_SPECIAL|OPf_KIDS))) {
-               /* This is a do block */
-               OP *op = kUNOP->op_first;
-               if (op->op_type == OP_LEAVE && op->op_flags & OPf_KIDS) {
-                   op = cUNOPx(op)->op_first;
-                   assert(op->op_type == OP_ENTER && !(op->op_flags & OPf_SPECIAL));
-                   /* Force the use of the caller's context */
-                   op->op_flags |= OPf_SPECIAL;
-               }
-           }
     }
 
     return o;
@@ -8275,7 +8560,7 @@ Perl_ck_shift(pTHX_ OP *o)
        return newUNOP(type, 0, scalar(argop));
 #endif
     }
-    return scalar(modkids(ck_push(o), type));
+    return scalar(ck_fun(o));
 }
 
 OP *
@@ -8451,8 +8736,9 @@ Perl_ck_split(pTHX_ OP *o)
        Perl_croak(aTHX_ "panic: ck_split");
     kid = kid->op_sibling;
     op_free(cLISTOPo->op_first);
-    cLISTOPo->op_first = kid;
-    if (!kid) {
+    if (kid)
+       cLISTOPo->op_first = kid;
+    else {
        cLISTOPo->op_first = kid = newSVOP(OP_CONST, 0, newSVpvs(" "));
        cLISTOPo->op_last = kid; /* There was only one element previously */
     }
@@ -8796,7 +9082,14 @@ Perl_ck_entersub_args_proto(pTHX_ OP *entersubop, GV *namegv, SV *protosv)
                            const char *p = proto;
                            const char *const end = proto;
                            contextclass = 0;
-                           while (*--p != '[') {}
+                           while (*--p != '[')
+                               /* \[$] accepts any scalar lvalue */
+                               if (*p == '$'
+                                && Perl_op_lvalue_flags(aTHX_
+                                    scalar(o3),
+                                    OP_READ, /* not entersub */
+                                    OP_LVALUE_NO_CROAK
+                                   )) goto wrapref;
                            bad_type(arg, Perl_form(aTHX_ "one of %.*s",
                                        (int)(end - p), p),
                                    gv_ename(namegv), o3);
@@ -8822,8 +9115,15 @@ Perl_ck_entersub_args_proto(pTHX_ OP *entersubop, GV *namegv, SV *protosv)
                                o3->op_type == OP_HELEM ||
                                o3->op_type == OP_AELEM)
                            goto wrapref;
-                       if (!contextclass)
+                       if (!contextclass) {
+                           /* \$ accepts any scalar lvalue */
+                           if (Perl_op_lvalue_flags(aTHX_
+                                   scalar(o3),
+                                   OP_READ,  /* not entersub */
+                                   OP_LVALUE_NO_CROAK
+                              )) goto wrapref;
                            bad_type(arg, "scalar", gv_ename(namegv), o3);
+                       }
                        break;
                    case '@':
                        if (o3->op_type == OP_RV2AV ||
@@ -9034,6 +9334,7 @@ Perl_ck_subr(pTHX_ OP *o)
     cv = rv2cv_op_cv(cvop, RV2CVOPCV_MARK_EARLY);
     namegv = cv ? (GV*)rv2cv_op_cv(cvop, RV2CVOPCV_RETURN_NAME_GV) : NULL;
 
+    o->op_private &= ~1;
     o->op_private |= OPpENTERSUB_HASTARG;
     o->op_private |= (PL_hints & HINT_STRICT_REFS);
     if (PERLDB_SUB && PL_curstash != PL_debstash)
@@ -9141,48 +9442,6 @@ Perl_ck_substr(pTHX_ OP *o)
 }
 
 OP *
-Perl_ck_push(pTHX_ OP *o)
-{
-    dVAR;
-    OP *kid = o->op_flags & OPf_KIDS ? cLISTOPo->op_first : NULL;
-    OP *cursor = NULL;
-    OP *proxy = NULL;
-
-    PERL_ARGS_ASSERT_CK_PUSH;
-
-    /* If 1st kid is pushmark (e.g. push, unshift, splice), we need 2nd kid */
-    if (kid) {
-       cursor = kid->op_type == OP_PUSHMARK ? kid->op_sibling : kid;
-    }
-
-    /* If not array or array deref, wrap it with an array deref.
-     * For OP_CONST, we only wrap arrayrefs */
-    if (cursor) {
-       if ( (    cursor->op_type != OP_PADAV
-              && cursor->op_type != OP_RV2AV
-              && cursor->op_type != OP_CONST
-            )
-            ||
-            (    cursor->op_type == OP_CONST
-              && SvROK(cSVOPx_sv(cursor))
-              && SvTYPE(SvRV(cSVOPx_sv(cursor))) == SVt_PVAV
-            )
-       ) {
-           proxy = newAVREF(cursor);
-           if ( cursor == kid ) {
-               cLISTOPx(o)->op_first = proxy;
-           }
-           else {
-               cLISTOPx(kid)->op_sibling = proxy;
-           }
-           cLISTOPx(proxy)->op_sibling = cLISTOPx(cursor)->op_sibling;
-           cLISTOPx(cursor)->op_sibling = NULL;
-       }
-    }
-    return ck_fun(o);
-}
-
-OP *
 Perl_ck_each(pTHX_ OP *o)
 {
     dVAR;
@@ -9205,11 +9464,16 @@ Perl_ck_each(pTHX_ OP *o)
                CHANGE_TYPE(o, array_type);
                break;
            case OP_CONST:
-               if (kid->op_private == OPpCONST_BARE)
-                   /* we let ck_fun treat as hash */
+               if (kid->op_private == OPpCONST_BARE
+                || !SvROK(cSVOPx_sv(kid))
+                || (  SvTYPE(SvRV(cSVOPx_sv(kid))) != SVt_PVAV
+                   && SvTYPE(SvRV(cSVOPx_sv(kid))) != SVt_PVHV  )
+                  )
+                   /* we let ck_fun handle it */
                    break;
            default:
                CHANGE_TYPE(o, ref_type);
+               scalar(kid);
        }
     }
     /* if treating as a reference, defer additional checks to runtime */
@@ -9316,6 +9580,16 @@ S_is_inplace_av(pTHX_ OP *o, OP *oright) {
     return oleft;
 }
 
+#define MAX_DEFERRED 4
+
+#define DEFER(o) \
+    if (defer_ix == (MAX_DEFERRED-1)) { \
+       CALL_RPEEP(defer_queue[defer_base]); \
+       defer_base = (defer_base + 1) % MAX_DEFERRED; \
+       defer_ix--; \
+    } \
+    defer_queue[(defer_base + ++defer_ix) % MAX_DEFERRED] = o;
+
 /* A peephole optimizer.  We visit the ops in the order they're to execute.
  * See the comments at the top of this file for more details about when
  * peep() is called */
@@ -9325,15 +9599,24 @@ Perl_rpeep(pTHX_ register OP *o)
 {
     dVAR;
     register OP* oldop = NULL;
+    OP* defer_queue[MAX_DEFERRED]; /* small queue of deferred branches */
+    int defer_base = 0;
+    int defer_ix = -1;
 
     if (!o || o->op_opt)
        return;
     ENTER;
     SAVEOP();
     SAVEVPTR(PL_curcop);
-    for (; o; o = o->op_next) {
-       if (o->op_opt)
+    for (;; o = o->op_next) {
+       if (o && o->op_opt)
+           o = NULL;
+       if (!o) {
+           while (defer_ix >= 0)
+               CALL_RPEEP(defer_queue[(defer_base + defer_ix--) % MAX_DEFERRED]);
            break;
+       }
+
        /* By default, this op has now been optimised. A couple of cases below
           clear this again.  */
        o->op_opt = 1;
@@ -9396,49 +9679,6 @@ Perl_rpeep(pTHX_ register OP *o)
            }
            break;
 
-       case OP_CONST:
-           if (cSVOPo->op_private & OPpCONST_STRICT)
-               no_bareword_allowed(o);
-#ifdef USE_ITHREADS
-       case OP_HINTSEVAL:
-       case OP_METHOD_NAMED:
-           /* Relocate sv to the pad for thread safety.
-            * Despite being a "constant", the SV is written to,
-            * for reference counts, sv_upgrade() etc. */
-           if (cSVOP->op_sv) {
-               const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
-               if (o->op_type != OP_METHOD_NAMED && 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(PAD_SVl(ix),cSVOPo->op_sv);
-                   SvREADONLY_on(PAD_SVl(ix));
-                   SvREFCNT_dec(cSVOPo->op_sv);
-               }
-               else if (o->op_type != OP_METHOD_NAMED
-                        && 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);
-                   PAD_SETSV(ix, cSVOPo->op_sv);
-                   /* XXX I don't know how this isn't readonly already. */
-                   SvREADONLY_on(PAD_SVl(ix));
-               }
-               cSVOPo->op_sv = NULL;
-               o->op_targ = ix;
-           }
-#endif
-           break;
-
        case OP_CONCAT:
            if (o->op_next && o->op_next->op_type == OP_STRINGIFY) {
                if (o->op_next->op_private & OPpTARGET_MY) {
@@ -9512,10 +9752,10 @@ Perl_rpeep(pTHX_ register OP *o)
                    if (o->op_type == OP_GV) {
                        gv = cGVOPo_gv;
                        GvAVn(gv);
+                       o->op_type = OP_AELEMFAST;
                    }
                    else
-                       o->op_flags |= OPf_SPECIAL;
-                   o->op_type = OP_AELEMFAST;
+                       o->op_type = OP_AELEMFAST_LEX;
                }
                break;
            }
@@ -9530,17 +9770,6 @@ Perl_rpeep(pTHX_ register OP *o)
                    o->op_ppaddr = PL_ppaddr[OP_GVSV];
                }
            }
-           else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
-               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 * const sv = sv_newmortal();
-                   gv_efullname3(sv, gv, NULL);
-                   Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
-                               "%"SVf"() called too early to check prototype",
-                               SVfARG(sv));
-               }
-           }
            else if (o->op_next->op_type == OP_READLINE
                    && o->op_next->op_next->op_type == OP_CONCAT
                    && (o->op_next->op_next->op_flags & OPf_STACKED))
@@ -9572,7 +9801,10 @@ Perl_rpeep(pTHX_ register OP *o)
             sop = fop->op_sibling;
            while (cLOGOP->op_other->op_type == OP_NULL)
                cLOGOP->op_other = cLOGOP->op_other->op_next;
-           CALL_RPEEP(cLOGOP->op_other);
+           while (o->op_next && (   o->op_type == o->op_next->op_type
+                                 || o->op_next->op_type == OP_NULL))
+               o->op_next = o->op_next->op_next;
+           DEFER(cLOGOP->op_other);
           
           stitch_keys:     
            o->op_opt = 1;
@@ -9623,20 +9855,21 @@ Perl_rpeep(pTHX_ register OP *o)
        case OP_ONCE:
            while (cLOGOP->op_other->op_type == OP_NULL)
                cLOGOP->op_other = cLOGOP->op_other->op_next;
-           CALL_RPEEP(cLOGOP->op_other);
+           DEFER(cLOGOP->op_other);
            break;
 
        case OP_ENTERLOOP:
        case OP_ENTERITER:
            while (cLOOP->op_redoop->op_type == OP_NULL)
                cLOOP->op_redoop = cLOOP->op_redoop->op_next;
-           CALL_RPEEP(cLOOP->op_redoop);
            while (cLOOP->op_nextop->op_type == OP_NULL)
                cLOOP->op_nextop = cLOOP->op_nextop->op_next;
-           CALL_RPEEP(cLOOP->op_nextop);
            while (cLOOP->op_lastop->op_type == OP_NULL)
                cLOOP->op_lastop = cLOOP->op_lastop->op_next;
-           CALL_RPEEP(cLOOP->op_lastop);
+           /* a while(1) loop doesn't have an op_next that escapes the
+            * loop, so we have to explicitly follow the op_lastop to
+            * process the rest of the code */
+           DEFER(cLOOP->op_lastop);
            break;
 
        case OP_SUBST:
@@ -9645,142 +9878,26 @@ Perl_rpeep(pTHX_ register OP *o)
                   cPMOP->op_pmstashstartu.op_pmreplstart->op_type == OP_NULL)
                cPMOP->op_pmstashstartu.op_pmreplstart
                    = cPMOP->op_pmstashstartu.op_pmreplstart->op_next;
-           CALL_RPEEP(cPMOP->op_pmstashstartu.op_pmreplstart);
-           break;
-
-       case OP_EXEC:
-           if (o->op_next && o->op_next->op_type == OP_NEXTSTATE
-               && ckWARN(WARN_SYNTAX))
-           {
-               if (o->op_next->op_sibling) {
-                   const OPCODE type = o->op_next->op_sibling->op_type;
-                   if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) {
-                       const line_t oldline = CopLINE(PL_curcop);
-                       CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next));
-                       Perl_warner(aTHX_ packWARN(WARN_EXEC),
-                                   "Statement unlikely to be reached");
-                       Perl_warner(aTHX_ packWARN(WARN_EXEC),
-                                   "\t(Maybe you meant system() when you said exec()?)\n");
-                       CopLINE_set(PL_curcop, oldline);
-                   }
-               }
-           }
+           DEFER(cPMOP->op_pmstashstartu.op_pmreplstart);
            break;
 
-       case OP_HELEM: {
-           UNOP *rop;
-            SV *lexname;
-           GV **fields;
-           SV **svp, *sv;
-           const char *key = NULL;
-           STRLEN keylen;
-
-           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))
-            && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) {
-               key = SvPV_const(sv, keylen);
-               lexname = newSVpvn_share(key,
-                                        SvUTF8(sv) ? -(I32)keylen : (I32)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;
-           lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
-           if (!SvPAD_TYPED(lexname))
-               break;
-           fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
-           if (!fields || !GvHV(*fields))
-               break;
-           key = SvPV_const(*svp, keylen);
-           if (!hv_fetch(GvHV(*fields), key,
-                       SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE))
-           {
-               Perl_croak(aTHX_ "No such class field \"%s\" " 
-                          "in variable %s of type %s", 
-                     key, SvPV_nolen_const(lexname), HvNAME_get(SvSTASH(lexname)));
-           }
-
-            break;
-        }
-
-       case OP_HSLICE: {
-           UNOP *rop;
-           SV *lexname;
-           GV **fields;
-           SV **svp;
-           const char *key;
-           STRLEN keylen;
-           SVOP *first_key_op, *key_op;
-
-           if ((o->op_private & (OPpLVAL_INTRO))
-               /* I bet there's always a pushmark... */
-               || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
-               /* hmmm, no optimization if list contains only one key. */
-               break;
-           rop = (UNOP*)((LISTOP*)o)->op_last;
-           if (rop->op_type != OP_RV2HV)
-               break;
-           if (rop->op_first->op_type == OP_PADSV)
-               /* @$hash{qw(keys here)} */
-               rop = (UNOP*)rop->op_first;
-           else {
-               /* @{$hash}{qw(keys here)} */
-               if (rop->op_first->op_type == OP_SCOPE 
-                   && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV)
-               {
-                   rop = (UNOP*)cLISTOPx(rop->op_first)->op_last;
-               }
-               else
-                   break;
-           }
-                   
-           lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE);
-           if (!SvPAD_TYPED(lexname))
-               break;
-           fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
-           if (!fields || !GvHV(*fields))
-               break;
-           /* Again guessing that the pushmark can be jumped over.... */
-           first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
-               ->op_first->op_sibling;
-           for (key_op = first_key_op; key_op;
-                key_op = (SVOP*)key_op->op_sibling) {
-               if (key_op->op_type != OP_CONST)
-                   continue;
-               svp = cSVOPx_svp(key_op);
-               key = SvPV_const(*svp, keylen);
-               if (!hv_fetch(GvHV(*fields), key, 
-                           SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE))
-               {
-                   Perl_croak(aTHX_ "No such class field \"%s\" "
-                              "in variable %s of type %s",
-                         key, SvPV_nolen(lexname), HvNAME_get(SvSTASH(lexname)));
-               }
-           }
-           break;
-       }
        case OP_RV2SV:
        case OP_RV2AV:
        case OP_RV2HV:
-           if (oldop
-                && (  oldop->op_type == OP_AELEM
+           if (oldop &&
+               (
+                (
+                   (  oldop->op_type == OP_AELEM
                    || oldop->op_type == OP_PADSV
                    || oldop->op_type == OP_RV2SV
                    || oldop->op_type == OP_RV2GV
                    || oldop->op_type == OP_HELEM
                    )
                 && (oldop->op_private & OPpDEREF)
+                )
+                || (   oldop->op_type == OP_ENTERSUB
+                    && oldop->op_private & OPpENTERSUB_DEREF )
+               )
            ) {
                o->op_private |= OPpDEREFed;
            }
@@ -10121,6 +10238,114 @@ Perl_custom_op_register(pTHX_ Perl_ppaddr_t ppaddr, const XOP *xop)
        Perl_croak(aTHX_ "panic: can't register custom OP %s", xop->xop_name);
 }
 
+/*
+=head1 Functions in file op.c
+
+=for apidoc core_prototype
+This function assigns the prototype of the named core function to C<sv>, or
+to a new mortal SV if C<sv> is NULL.  It returns the modified C<sv>, or
+NULL if the core function has no prototype.
+
+If the C<name> is not a Perl keyword, it croaks if C<croak> is true, or
+returns NULL if C<croak> is false.
+
+=cut
+*/
+
+SV *
+Perl_core_prototype(pTHX_ SV *sv, const char *name, const STRLEN len,
+                          const bool croak)
+{
+    const int code = keyword(name, len, 1);
+    int i = 0, n = 0, seen_question = 0, defgv = 0;
+    I32 oa;
+#define MAX_ARGS_OP ((sizeof(I32) - 1) * 2)
+    char str[ MAX_ARGS_OP * 2 + 2 ]; /* One ';', one '\0' */
+
+    PERL_ARGS_ASSERT_CORE_PROTOTYPE;
+
+    if (!code || code == -KEY_CORE) {
+       if (croak)
+           return (SV *)Perl_die(aTHX_
+               "Can't find an opnumber for \"%s\"", name
+           );
+       return NULL;
+    }
+
+    if (code > 0) return NULL; /* Not overridable */
+
+    if (!sv) sv = sv_newmortal();
+
+#define retsetpvs(x) sv_setpvs(sv, x); return sv
+
+    switch (-code) {
+    case KEY_and   : case KEY_chop: case KEY_chomp:
+    case KEY_cmp   : case KEY_exec: case KEY_eq   :
+    case KEY_ge    : case KEY_gt  : case KEY_le   :
+    case KEY_lt    : case KEY_ne  : case KEY_or   :
+    case KEY_select: case KEY_system: case KEY_x  : case KEY_xor:
+       return NULL;
+    case KEY_keys: case KEY_values: case KEY_each:
+       retsetpvs("+");
+    case KEY_push: case KEY_unshift:
+       retsetpvs("+@");
+    case KEY_pop: case KEY_shift:
+       retsetpvs(";+");
+    case KEY_splice:
+       retsetpvs("+;$$@");
+    case KEY___FILE__: case KEY___LINE__: case KEY___PACKAGE__:
+       retsetpvs("");
+    case KEY_readpipe:
+       name = "backtick";
+    }
+
+#undef retsetpvs
+
+    while (i < MAXO) { /* The slow way. */
+       if (strEQ(name, PL_op_name[i])
+           || strEQ(name, PL_op_desc[i]))
+       {
+           goto found;
+       }
+       i++;
+    }
+    assert(0); return NULL;    /* Should not happen... */
+  found:
+    defgv = PL_opargs[i] & OA_DEFGV;
+    oa = PL_opargs[i] >> OASHIFT;
+    while (oa) {
+       if (oa & OA_OPTIONAL && !seen_question && (
+             !defgv || n || (oa & (OA_OPTIONAL - 1)) == OA_FILEREF
+       )) {
+           seen_question = 1;
+           str[n++] = ';';
+       }
+       if ((oa & (OA_OPTIONAL - 1)) >= OA_AVREF
+           && (oa & (OA_OPTIONAL - 1)) <= OA_SCALARREF
+           /* But globs are already references (kinda) */
+           && (oa & (OA_OPTIONAL - 1)) != OA_FILEREF
+       ) {
+           str[n++] = '\\';
+       }
+       if ((oa & (OA_OPTIONAL - 1)) == OA_SCALARREF
+        && !scalar_mod_type(NULL, i)) {
+           str[n++] = '[';
+           str[n++] = '$';
+           str[n++] = '@';
+           str[n++] = '%';
+           str[n++] = '*';
+           str[n++] = ']';
+       }
+       else str[n++] = ("?$@@%&*$")[oa & (OA_OPTIONAL - 1)];
+       oa = oa >> 4;
+    }
+    if (defgv && str[0] == '$')
+       str[0] = '_';
+    str[n++] = '\0';
+    sv_setpvn(sv, str, n - 1);
+    return sv;
+}
+
 #include "XSUB.h"
 
 /* Efficient sub that returns a constant scalar value. */