This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Call cop_free on nullified cops too
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 7015695..ba9e2a5 100644 (file)
--- a/op.c
+++ b/op.c
@@ -90,7 +90,7 @@ recursive, but it's recursive on basic blocks, not on tree nodes.
    magic type 'H'. This magic (itself) does nothing, but its presence causes
    the values to gain magic type 'h', which has entries for set and clear.
    C<Perl_magic_sethint> updates C<PL_compiling.cop_hints_hash> with a store
-   record, with deletes written by C<Perl_magic_clearhint>. C<SAVE_HINTS>
+   record, with deletes written by C<Perl_magic_clearhint>. C<SAVEHINTS>
    saves the current C<PL_compiling.cop_hints_hash> on the save stack, so that
    it will be correctly restored when any inner compiling scope is exited.
 */
@@ -116,6 +116,7 @@ recursive, but it's recursive on basic blocks, not on tree nodes.
 void *
 Perl_Slab_Alloc(pTHX_ size_t sz)
 {
+    dVAR;
     /*
      * To make incrementing use count easy PL_OpSlab is an I32 *
      * To make inserting the link to slab PL_OpPtr is I32 **
@@ -127,7 +128,7 @@ Perl_Slab_Alloc(pTHX_ size_t sz)
 #ifdef PERL_DEBUG_READONLY_OPS
        /* We need to allocate chunk by chunk so that we can control the VM
           mapping */
-       PL_OpPtr = mmap(0, PERL_SLAB_SIZE*sizeof(I32*), PROT_READ|PROT_WRITE,
+       PL_OpPtr = (I32**) mmap(0, PERL_SLAB_SIZE*sizeof(I32*), PROT_READ|PROT_WRITE,
                        MAP_ANON|MAP_PRIVATE, -1, 0);
 
        DEBUG_m(PerlIO_printf(Perl_debug_log, "mapped %lu at %p\n",
@@ -159,7 +160,7 @@ Perl_Slab_Alloc(pTHX_ size_t sz)
 #ifdef PERL_DEBUG_READONLY_OPS
        /* We remember this slab.  */
        /* This implementation isn't efficient, but it is simple. */
-       PL_slabs = realloc(PL_slabs, sizeof(I32**) * (PL_slab_count + 1));
+       PL_slabs = (I32**) realloc(PL_slabs, sizeof(I32**) * (PL_slab_count + 1));
        PL_slabs[PL_slab_count++] = PL_OpSlab;
        DEBUG_m(PerlIO_printf(Perl_debug_log, "Allocate %p\n", PL_OpSlab));
 #endif
@@ -209,6 +210,9 @@ S_Slab_to_rw(pTHX_ void *op)
 {
     I32 * const * const ptr = (I32 **) op;
     I32 * const slab = ptr[-1];
+
+    PERL_ARGS_ASSERT_SLAB_TO_RW;
+
     assert( ptr-1 > (I32 **) slab );
     assert( ptr < ( (I32 **) slab + PERL_SLAB_SIZE) );
     assert( *slab > 0 );
@@ -232,6 +236,7 @@ Perl_op_refcnt_inc(pTHX_ OP *o)
 PADOFFSET
 Perl_op_refcnt_dec(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_OP_REFCNT_DEC;
     Slab_to_rw(o);
     return --o->op_targ;
 }
@@ -244,6 +249,7 @@ Perl_Slab_Free(pTHX_ void *op)
 {
     I32 * const * const ptr = (I32 **) op;
     I32 * const slab = ptr[-1];
+    PERL_ARGS_ASSERT_SLAB_FREE;
     assert( ptr-1 > (I32 **) slab );
     assert( ptr < ( (I32 **) slab + PERL_SLAB_SIZE) );
     assert( *slab > 0 );
@@ -259,6 +265,7 @@ Perl_Slab_Free(pTHX_ void *op)
        if (count) {
            while (count--) {
                if (PL_slabs[count] == slab) {
+                   dVAR;
                    /* Found it. Move the entry at the end to overwrite it.  */
                    DEBUG_m(PerlIO_printf(Perl_debug_log,
                                          "Deallocate %p by moving %p from %lu to %lu\n",
@@ -302,6 +309,9 @@ STATIC const char*
 S_gv_ename(pTHX_ GV *gv)
 {
     SV* const tmpsv = sv_newmortal();
+
+    PERL_ARGS_ASSERT_GV_ENAME;
+
     gv_efullname3(tmpsv, gv, NULL);
     return SvPV_nolen_const(tmpsv);
 }
@@ -309,6 +319,8 @@ S_gv_ename(pTHX_ GV *gv)
 STATIC OP *
 S_no_fh_allowed(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_NO_FH_ALLOWED;
+
     yyerror(Perl_form(aTHX_ "Missing comma after first argument to %s function",
                 OP_DESC(o)));
     return o;
@@ -317,6 +329,8 @@ S_no_fh_allowed(pTHX_ OP *o)
 STATIC OP *
 S_too_few_arguments(pTHX_ OP *o, const char *name)
 {
+    PERL_ARGS_ASSERT_TOO_FEW_ARGUMENTS;
+
     yyerror(Perl_form(aTHX_ "Not enough arguments for %s", name));
     return o;
 }
@@ -324,6 +338,8 @@ S_too_few_arguments(pTHX_ OP *o, const char *name)
 STATIC OP *
 S_too_many_arguments(pTHX_ OP *o, const char *name)
 {
+    PERL_ARGS_ASSERT_TOO_MANY_ARGUMENTS;
+
     yyerror(Perl_form(aTHX_ "Too many arguments for %s", name));
     return o;
 }
@@ -331,6 +347,8 @@ S_too_many_arguments(pTHX_ OP *o, const char *name)
 STATIC void
 S_bad_type(pTHX_ I32 n, const char *t, const char *name, const OP *kid)
 {
+    PERL_ARGS_ASSERT_BAD_TYPE;
+
     yyerror(Perl_form(aTHX_ "Type of arg %d to %s must be %s (not %s)",
                 (int)n, name, t, OP_DESC(kid)));
 }
@@ -338,6 +356,8 @@ 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)
 {
+    PERL_ARGS_ASSERT_NO_BAREWORD_ALLOWED;
+
     if (PL_madskills)
        return;         /* various ok barewords are hidden in extra OP_NULL */
     qerror(Perl_mess(aTHX_
@@ -352,7 +372,9 @@ Perl_allocmy(pTHX_ const char *const name)
 {
     dVAR;
     PADOFFSET off;
-    const bool is_our = (PL_in_my == KEY_our);
+    const bool is_our = (PL_parser->in_my == KEY_our);
+
+    PERL_ARGS_ASSERT_ALLOCMY;
 
     /* complain about "my $<special_var>" etc etc */
     if (*name &&
@@ -363,35 +385,44 @@ Perl_allocmy(pTHX_ const char *const name)
     {
        /* name[2] is true if strlen(name) > 2  */
        if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) {
-           yyerror(Perl_form(aTHX_ "Can't use global %c^%c%s in \"my\"",
-                             name[0], toCTRL(name[1]), name + 2));
+           yyerror(Perl_form(aTHX_ "Can't use global %c^%c%s in \"%s\"",
+                             name[0], toCTRL(name[1]), name + 2,
+                             PL_parser->in_my == KEY_state ? "state" : "my"));
        } else {
-           yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name));
+           yyerror(Perl_form(aTHX_ "Can't use global %s in \"%s\"",name,
+                             PL_parser->in_my == KEY_state ? "state" : "my"));
        }
     }
 
     /* check for duplicate declaration */
     pad_check_dup(name, is_our, (PL_curstash ? PL_curstash : PL_defstash));
 
-    if (PL_in_my_stash && *name != '$') {
+    if (PL_parser->in_my_stash && *name != '$') {
        yyerror(Perl_form(aTHX_
                    "Can't declare class for non-scalar %s in \"%s\"",
                     name,
-                    is_our ? "our" : PL_in_my == KEY_state ? "state" : "my"));
+                    is_our ? "our"
+                           : PL_parser->in_my == KEY_state ? "state" : "my"));
     }
 
     /* allocate a spare slot and store the name in that slot */
 
     off = pad_add_name(name,
-                   PL_in_my_stash,
+                   PL_parser->in_my_stash,
                    (is_our
                        /* $_ is always in main::, even with our */
                        ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash)
                        : NULL
                    ),
                    0, /*  not fake */
-                   PL_in_my == KEY_state
+                   PL_parser->in_my == KEY_state
     );
+    /* anon sub prototypes contains state vars should always be cloned,
+     * otherwise the state var would be shared between anon subs */
+
+    if (PL_parser->in_my == KEY_state && CvANON(PL_compcv))
+       CvCLONE_on(PL_compcv);
+
     return off;
 }
 
@@ -422,7 +453,7 @@ Perl_op_free(pTHX_ OP *o)
     dVAR;
     OPCODE type;
 
-    if (!o || o->op_static)
+    if (!o)
        return;
     if (o->op_latefreed) {
        if (o->op_latefree)
@@ -464,8 +495,6 @@ Perl_op_free(pTHX_ OP *o)
            op_free(kid);
        }
     }
-    if (type == OP_NULL)
-       type = (OPCODE)o->op_targ;
 
 #ifdef PERL_DEBUG_READONLY_OPS
     Slab_to_rw(o);
@@ -473,10 +502,16 @@ Perl_op_free(pTHX_ OP *o)
 
     /* COP* is not cleared by op_clear() so that we may track line
      * numbers etc even after null() */
-    if (type == OP_NEXTSTATE || type == OP_SETSTATE || type == OP_DBSTATE) {
+    if (type == OP_NEXTSTATE || type == OP_DBSTATE
+           || (type == OP_NULL /* the COP might have been null'ed */
+               && ((OPCODE)o->op_targ == OP_NEXTSTATE
+                   || (OPCODE)o->op_targ == OP_DBSTATE))) {
        cop_free((COP*)o);
     }
 
+    if (type == OP_NULL)
+       type = (OPCODE)o->op_targ;
+
     op_clear(o);
     if (o->op_latefree) {
        o->op_latefreed = 1;
@@ -495,6 +530,9 @@ Perl_op_clear(pTHX_ OP *o)
 {
 
     dVAR;
+
+    PERL_ARGS_ASSERT_OP_CLEAR;
+
 #ifdef PERL_MAD
     /* if (o->op_madprop && o->op_madprop->mad_next)
        abort(); */
@@ -514,7 +552,7 @@ Perl_op_clear(pTHX_ OP *o)
     switch (o->op_type) {
     case OP_NULL:      /* Was holding old type, if any. */
        if (PL_madskills && o->op_targ != OP_NULL) {
-           o->op_type = o->op_targ;
+           o->op_type = (Optype)o->op_targ;
            o->op_targ = 0;
            goto retry;
        }
@@ -546,6 +584,7 @@ Perl_op_clear(pTHX_ OP *o)
        break;
     case OP_METHOD_NAMED:
     case OP_CONST:
+    case OP_HINTSEVAL:
        SvREFCNT_dec(cSVOPo->op_sv);
        cSVOPo->op_sv = NULL;
 #ifdef USE_ITHREADS
@@ -604,21 +643,23 @@ Perl_op_clear(pTHX_ OP *o)
 clear_pmop:
        forget_pmop(cPMOPo, 1);
        cPMOPo->op_pmreplrootu.op_pmreplroot = NULL;
-        /* we use the "SAFE" version of the PM_ macros here
-         * since sv_clean_all might release some PMOPs
+        /* we use the same protection as the "SAFE" version of the PM_ macros
+         * here since sv_clean_all might release some PMOPs
          * after PL_regex_padav has been cleared
          * and the clearing of PL_regex_padav needs to
          * happen before sv_clean_all
          */
-       ReREFCNT_dec(PM_GETRE_SAFE(cPMOPo));
-       PM_SETRE_SAFE(cPMOPo, NULL);
 #ifdef USE_ITHREADS
        if(PL_regex_pad) {        /* We could be in destruction */
-            av_push((AV*) PL_regex_pad[0],(SV*) PL_regex_pad[(cPMOPo)->op_pmoffset]);
-            SvREADONLY_off(PL_regex_pad[(cPMOPo)->op_pmoffset]);
-           SvREPADTMP_on(PL_regex_pad[(cPMOPo)->op_pmoffset]);
-            PM_SETRE(cPMOPo, (cPMOPo)->op_pmoffset);
+           const IV offset = (cPMOPo)->op_pmoffset;
+           ReREFCNT_dec(PM_GETRE(cPMOPo));
+           PL_regex_pad[offset] = &PL_sv_undef;
+            sv_catpvn_nomg(PL_regex_pad[0], (const char *)&offset,
+                          sizeof(offset));
         }
+#else
+       ReREFCNT_dec(PM_GETRE(cPMOPo));
+       PM_SETRE(cPMOPo, NULL);
 #endif
 
        break;
@@ -633,7 +674,8 @@ clear_pmop:
 STATIC void
 S_cop_free(pTHX_ COP* cop)
 {
-    CopLABEL_free(cop);
+    PERL_ARGS_ASSERT_COP_FREE;
+
     CopFILE_free(cop);
     CopSTASH_free(cop);
     if (! specialWARN(cop->cop_warnings))
@@ -649,6 +691,9 @@ S_forget_pmop(pTHX_ PMOP *const o
              )
 {
     HV * const pmstash = PmopSTASH(o);
+
+    PERL_ARGS_ASSERT_FORGET_PMOP;
+
     if (pmstash && !SvIS_FREED(pmstash)) {
        MAGIC * const mg = mg_find((SV*)pmstash, PERL_MAGIC_symtab);
        if (mg) {
@@ -684,6 +729,8 @@ S_forget_pmop(pTHX_ PMOP *const o
 STATIC void
 S_find_and_forget_pmops(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_FIND_AND_FORGET_PMOPS;
+
     if (o->op_flags & OPf_KIDS) {
         OP *kid = cUNOPo->op_first;
        while (kid) {
@@ -704,6 +751,9 @@ void
 Perl_op_null(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_OP_NULL;
+
     if (o->op_type == OP_NULL)
        return;
     if (!PL_madskills)
@@ -738,6 +788,8 @@ Perl_linklist(pTHX_ OP *o)
 {
     OP *first;
 
+    PERL_ARGS_ASSERT_LINKLIST;
+
     if (o->op_next)
        return o->op_next;
 
@@ -778,6 +830,9 @@ STATIC OP *
 S_scalarboolean(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_SCALARBOOLEAN;
+
     if (o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST) {
        if (ckWARN(WARN_SYNTAX)) {
            const line_t oldline = CopLINE(PL_curcop);
@@ -798,7 +853,8 @@ Perl_scalar(pTHX_ OP *o)
     OP *kid;
 
     /* assumes no premature commitment */
-    if (!o || PL_error_count || (o->op_flags & OPf_WANT)
+    if (!o || (PL_parser && PL_parser->error_count)
+        || (o->op_flags & OPf_WANT)
         || o->op_type == OP_RETURN)
     {
        return o;
@@ -858,6 +914,7 @@ Perl_scalar(pTHX_ OP *o)
     case OP_SORT:
        if (ckWARN(WARN_VOID))
            Perl_warner(aTHX_ packWARN(WARN_VOID), "Useless use of sort in scalar context");
+       break;
     }
     return o;
 }
@@ -871,6 +928,8 @@ Perl_scalarvoid(pTHX_ OP *o)
     SV* sv;
     U8 want;
 
+    PERL_ARGS_ASSERT_SCALARVOID;
+
     /* trailing mad null ops don't count as "there" for void processing */
     if (PL_madskills &&
        o->op_type != OP_NULL &&
@@ -887,16 +946,15 @@ Perl_scalarvoid(pTHX_ OP *o)
     }
 
     if (o->op_type == OP_NEXTSTATE
-       || o->op_type == OP_SETSTATE
        || o->op_type == OP_DBSTATE
        || (o->op_type == OP_NULL && (o->op_targ == OP_NEXTSTATE
-                                     || o->op_targ == OP_SETSTATE
                                      || o->op_targ == OP_DBSTATE)))
        PL_curcop = (COP*)o;            /* for warning below */
 
     /* assumes no premature commitment */
     want = o->op_flags & OPf_WANT;
-    if ((want && want != OPf_WANT_SCALAR) || PL_error_count
+    if ((want && want != OPf_WANT_SCALAR)
+        || (PL_parser && PL_parser->error_count)
         || o->op_type == OP_RETURN)
     {
        return o;
@@ -926,6 +984,7 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_GVSV:
     case OP_WANTARRAY:
     case OP_GV:
+    case OP_SMARTMATCH:
     case OP_PADSV:
     case OP_PADAV:
     case OP_PADHV:
@@ -993,6 +1052,7 @@ Perl_scalarvoid(pTHX_ OP *o)
     case OP_PROTOTYPE:
       func_ops:
        if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)))
+           /* Otherwise it's "Useless use of grep iterator" */
            useless = OP_DESC(o);
        break;
 
@@ -1020,7 +1080,13 @@ Perl_scalarvoid(pTHX_ OP *o)
            no_bareword_allowed(o);
        else {
            if (ckWARN(WARN_VOID)) {
-               useless = "a constant";
+               if (SvOK(sv)) {
+                   SV* msv = sv_2mortal(Perl_newSVpvf(aTHX_
+                               "a constant (%"SVf")", sv));
+                   useless = SvPV_nolen(msv);
+               }
+               else
+                   useless = "a constant (undef)";
                if (o->op_private & OPpCONST_ARYBASE)
                    useless = NULL;
                /* don't warn on optimised away booleans, eg 
@@ -1141,7 +1207,8 @@ Perl_list(pTHX_ OP *o)
     OP *kid;
 
     /* assumes no premature commitment */
-    if (!o || (o->op_flags & OPf_WANT) || PL_error_count
+    if (!o || (o->op_flags & OPf_WANT)
+        || (PL_parser && PL_parser->error_count)
         || o->op_type == OP_RETURN)
     {
        return o;
@@ -1267,7 +1334,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
     /* -1 = error on localize, 0 = ignore localize, 1 = ok to localize */
     int localize = -1;
 
-    if (!o || PL_error_count)
+    if (!o || (PL_parser && PL_parser->error_count))
        return o;
 
     if ((o->op_private & OPpTARGET_MY)
@@ -1611,6 +1678,8 @@ Perl_mod(pTHX_ OP *o, I32 type)
 STATIC bool
 S_scalar_mod_type(const OP *o, I32 type)
 {
+    PERL_ARGS_ASSERT_SCALAR_MOD_TYPE;
+
     switch (type) {
     case OP_SASSIGN:
        if (o->op_type == OP_RV2GV)
@@ -1659,6 +1728,8 @@ S_scalar_mod_type(const OP *o, I32 type)
 STATIC bool
 S_is_handle_constructor(const OP *o, I32 numargs)
 {
+    PERL_ARGS_ASSERT_IS_HANDLE_CONSTRUCTOR;
+
     switch (o->op_type) {
     case OP_PIPE_OP:
     case OP_SOCKPAIR:
@@ -1696,7 +1767,9 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref)
     dVAR;
     OP *kid;
 
-    if (!o || PL_error_count)
+    PERL_ARGS_ASSERT_DOREF;
+
+    if (!o || (PL_parser && PL_parser->error_count))
        return o;
 
     switch (o->op_type) {
@@ -1787,6 +1860,8 @@ S_dup_attrlist(pTHX_ OP *o)
     dVAR;
     OP *rop;
 
+    PERL_ARGS_ASSERT_DUP_ATTRLIST;
+
     /* An attrlist is either a simple OP_CONST or an OP_LIST with kids,
      * where the first kid is OP_PUSHMARK and the remaining ones
      * are OP_CONST.  We need to push the OP_CONST values.
@@ -1816,6 +1891,8 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
     dVAR;
     SV *stashsv;
 
+    PERL_ARGS_ASSERT_APPLY_ATTRS;
+
     /* fake up C<use attributes $pkg,$rv,@attrs> */
     ENTER;             /* need to protect against side-effects of 'use' */
     stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no;
@@ -1853,6 +1930,8 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp)
     OP *pack, *imop, *arg;
     SV *meth, *stashsv;
 
+    PERL_ARGS_ASSERT_APPLY_ATTRS_MY;
+
     if (!attrs)
        return;
 
@@ -1913,6 +1992,8 @@ Perl_apply_attrs_string(pTHX_ const char *stashpv, CV *cv,
 {
     OP *attrs = NULL;
 
+    PERL_ARGS_ASSERT_APPLY_ATTRS_STRING;
+
     if (!len) {
         len = strlen(attrstr);
     }
@@ -1944,7 +2025,9 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
     dVAR;
     I32 type;
 
-    if (!o || PL_error_count)
+    PERL_ARGS_ASSERT_MY_KID;
+
+    if (!o || (PL_parser && PL_parser->error_count))
        return o;
 
     type = o->op_type;
@@ -1969,11 +2052,13 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
        if (cUNOPo->op_first->op_type != OP_GV) { /* MJD 20011224 */
            yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"",
                        OP_DESC(o),
-                       PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my"));
+                       PL_parser->in_my == KEY_our
+                           ? "our"
+                           : PL_parser->in_my == KEY_state ? "state" : "my"));
        } else if (attrs) {
            GV * const gv = cGVOPx_gv(cUNOPo->op_first);
-           PL_in_my = FALSE;
-           PL_in_my_stash = NULL;
+           PL_parser->in_my = FALSE;
+           PL_parser->in_my_stash = NULL;
            apply_attrs(GvSTASH(gv),
                        (type == OP_RV2SV ? GvSV(gv) :
                         type == OP_RV2AV ? (SV*)GvAV(gv) :
@@ -1990,14 +2075,16 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
     {
        yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"",
                          OP_DESC(o),
-                         PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my"));
+                         PL_parser->in_my == KEY_our
+                           ? "our"
+                           : PL_parser->in_my == KEY_state ? "state" : "my"));
        return o;
     }
     else if (attrs && type != OP_PUSHMARK) {
        HV *stash;
 
-       PL_in_my = FALSE;
-       PL_in_my_stash = NULL;
+       PL_parser->in_my = FALSE;
+       PL_parser->in_my_stash = NULL;
 
        /* check for C<my Dog $spot> when deciding package */
        stash = PAD_COMPNAME_TYPE(o->op_targ);
@@ -2007,7 +2094,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
     }
     o->op_flags |= OPf_MOD;
     o->op_private |= OPpLVAL_INTRO;
-    if (PL_in_my == KEY_state)
+    if (PL_parser->in_my == KEY_state)
        o->op_private |= OPpPAD_STATE;
     return o;
 }
@@ -2019,6 +2106,8 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs)
     OP *rops;
     int maybe_scalar = 0;
 
+    PERL_ARGS_ASSERT_MY_ATTRS;
+
 /* [perl #17376]: this appears to be premature, and results in code such as
    C< our(%x); > executing in list mode rather than void mode */
 #if 0
@@ -2041,14 +2130,16 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs)
        else
            o = append_list(OP_LIST, (LISTOP*)o, (LISTOP*)rops);
     }
-    PL_in_my = FALSE;
-    PL_in_my_stash = NULL;
+    PL_parser->in_my = FALSE;
+    PL_parser->in_my_stash = NULL;
     return o;
 }
 
 OP *
 Perl_my(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_MY;
+
     return my_attrs(o, NULL);
 }
 
@@ -2069,6 +2160,8 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
     const OPCODE ltype = left->op_type;
     const OPCODE rtype = right->op_type;
 
+    PERL_ARGS_ASSERT_BIND_MATCH;
+
     if ( (ltype == OP_RV2AV || ltype == OP_RV2HV || ltype == OP_PADAV
          || ltype == OP_PADHV) && ckWARN(WARN_MISC))
     {
@@ -2204,6 +2297,9 @@ void
 Perl_newPROG(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_NEWPROG;
+
     if (PL_in_eval) {
        if (PL_eval_root)
                return;
@@ -2251,6 +2347,9 @@ OP *
 Perl_localize(pTHX_ OP *o, I32 lex)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_LOCALIZE;
+
     if (o->op_flags & OPf_PARENS)
 /* [perl #17376]: this appears to be premature, and results in code such as
    C< our(%x); > executing in list mode rather than void mode */
@@ -2287,8 +2386,13 @@ Perl_localize(pTHX_ OP *o, I32 lex)
            if (sigil && (*s == ';' || *s == '=')) {
                Perl_warner(aTHX_ packWARN(WARN_PARENTHESIS),
                                "Parentheses missing around \"%s\" list",
-                               lex ? (PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my")
-                               : "local");
+                               lex
+                                   ? (PL_parser->in_my == KEY_our
+                                       ? "our"
+                                       : PL_parser->in_my == KEY_state
+                                           ? "state"
+                                           : "my")
+                                   : "local");
            }
        }
     }
@@ -2296,14 +2400,16 @@ Perl_localize(pTHX_ OP *o, I32 lex)
        o = my(o);
     else
        o = mod(o, OP_NULL);            /* a bit kludgey */
-    PL_in_my = FALSE;
-    PL_in_my_stash = NULL;
+    PL_parser->in_my = FALSE;
+    PL_parser->in_my_stash = NULL;
     return o;
 }
 
 OP *
 Perl_jmaybe(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_JMAYBE;
+
     if (o->op_type == OP_LIST) {
        OP * const o2
            = newSVREF(newGVOP(OP_GV, 0, gv_fetchpvs(";", GV_ADD|GV_NOTQUAL, SVt_PV)));
@@ -2316,7 +2422,7 @@ OP *
 Perl_fold_constants(pTHX_ register OP *o)
 {
     dVAR;
-    register OP *curop;
+    register OP * VOL curop;
     OP *newop;
     VOL I32 type = o->op_type;
     SV * VOL sv = NULL;
@@ -2325,8 +2431,11 @@ Perl_fold_constants(pTHX_ register OP *o)
     OP *old_next;
     SV * const oldwarnhook = PL_warnhook;
     SV * const olddiehook  = PL_diehook;
+    COP not_compiling;
     dJMPENV;
 
+    PERL_ARGS_ASSERT_FOLD_CONSTANTS;
+
     if (PL_opargs[type] & OA_RETSCALAR)
        scalar(o);
     if (PL_opargs[type] & OA_TARGET && !o->op_targ)
@@ -2361,9 +2470,10 @@ Perl_fold_constants(pTHX_ register OP *o)
        /* XXX what about the numeric ops? */
        if (PL_hints & HINT_LOCALE)
            goto nope;
+       break;
     }
 
-    if (PL_error_count)
+    if (PL_parser && PL_parser->error_count)
        goto nope;              /* Don't try to run w/ errors */
 
     for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
@@ -2386,6 +2496,13 @@ Perl_fold_constants(pTHX_ register OP *o)
     oldscope = PL_scopestack_ix;
     create_eval_scope(G_FAKINGEVAL);
 
+    /* Verify that we don't need to save it:  */
+    assert(PL_curcop == &PL_compiling);
+    StructCopy(&PL_compiling, &not_compiling, COP);
+    PL_curcop = &not_compiling;
+    /* The above ensures that we run with all the correct hints of the
+       currently compiling COP, but that IN_PERL_RUNTIME is not true. */
+    assert(IN_PERL_RUNTIME);
     PL_warnhook = PERL_WARNHOOK_FATAL;
     PL_diehook  = NULL;
     JMPENV_PUSH(ret);
@@ -2419,6 +2536,7 @@ Perl_fold_constants(pTHX_ register OP *o)
     JMPENV_POP;
     PL_warnhook = oldwarnhook;
     PL_diehook  = olddiehook;
+    PL_curcop = &PL_compiling;
 
     if (PL_scopestack_ix > oldscope)
        delete_eval_scope();
@@ -2449,7 +2567,7 @@ Perl_gen_constant_list(pTHX_ register OP *o)
     const I32 oldtmps_floor = PL_tmps_floor;
 
     list(o);
-    if (PL_error_count)
+    if (PL_parser && PL_parser->error_count)
        return o;               /* Don't attempt to run with errors */
 
     PL_op = curop = LINKLIST(o);
@@ -2619,6 +2737,8 @@ Perl_newTOKEN(pTHX_ I32 optype, YYSTYPE lval, MADPROP* madprop)
 void
 Perl_token_free(pTHX_ TOKEN* tk)
 {
+    PERL_ARGS_ASSERT_TOKEN_FREE;
+
     if (tk->tk_type != 12345)
        return;
     mad_free(tk->tk_mad);
@@ -2630,6 +2750,9 @@ Perl_token_getmad(pTHX_ TOKEN* tk, OP* o, char slot)
 {
     MADPROP* mp;
     MADPROP* tm;
+
+    PERL_ARGS_ASSERT_TOKEN_GETMAD;
+
     if (tk->tk_type != 12345) {
        Perl_warner(aTHX_ packWARN(WARN_MISC),
             "Invalid TOKEN object ignored");
@@ -2793,11 +2916,13 @@ Perl_addmad(pTHX_ MADPROP* tm, MADPROP** root, char slot)
 MADPROP *
 Perl_newMADsv(pTHX_ char key, SV* sv)
 {
+    PERL_ARGS_ASSERT_NEWMADSV;
+
     return newMADPROP(key, MAD_SV, sv, 0);
 }
 
 MADPROP *
-Perl_newMADPROP(pTHX_ char key, char type, void* val, I32 vlen)
+Perl_newMADPROP(pTHX_ char key, char type, const void* val, I32 vlen)
 {
     MADPROP *mp;
     Newxz(mp, 1, MADPROP);
@@ -3010,6 +3135,9 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
     const I32 squash     = o->op_private & OPpTRANS_SQUASH;
     I32 del              = o->op_private & OPpTRANS_DELETE;
     SV* swash;
+
+    PERL_ARGS_ASSERT_PMTRANS;
+
     PL_hints |= HINT_BLOCK_SCOPE;
 
     if (SvUTF8(tstr))
@@ -3339,14 +3467,23 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags)
 
 
 #ifdef USE_ITHREADS
-    if (av_len((AV*) PL_regex_pad[0]) > -1) {
-       SV * const repointer = av_pop((AV*)PL_regex_pad[0]);
-       pmop->op_pmoffset = SvIV(repointer);
-       SvREPADTMP_off(repointer);
-       sv_setiv(repointer,0);
+    assert(SvPOK(PL_regex_pad[0]));
+    if (SvCUR(PL_regex_pad[0])) {
+       /* Pop off the "packed" IV from the end.  */
+       SV *const repointer_list = PL_regex_pad[0];
+       const char *p = SvEND(repointer_list) - sizeof(IV);
+       const IV offset = *((IV*)p);
+
+       assert(SvCUR(repointer_list) % sizeof(IV) == 0);
+
+       SvEND_set(repointer_list, p);
+
+       pmop->op_pmoffset = offset;
+       /* This slot should be free, so assert this:  */
+       assert(PL_regex_pad[offset] == &PL_sv_undef);
     } else {
-       SV * const repointer = newSViv(0);
-       av_push(PL_regex_padav, SvREFCNT_inc_simple_NN(repointer));
+       SV * const repointer = &PL_sv_undef;
+       av_push(PL_regex_padav, repointer);
        pmop->op_pmoffset = av_len(PL_regex_padav);
        PL_regex_pad = AvARRAY(PL_regex_padav);
     }
@@ -3377,6 +3514,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
     OP* repl = NULL;
     bool reglist;
 
+    PERL_ARGS_ASSERT_PMRUNTIME;
+
     if (o->op_type == OP_SUBST || o->op_type == OP_TRANS) {
        /* last element in list is the replacement; pop it */
        OP* kid;
@@ -3411,32 +3550,24 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
     pm = (PMOP*)o;
 
     if (expr->op_type == OP_CONST) {
-       STRLEN plen;
-       SV * const pat = ((SVOP*)expr)->op_sv;
-       const char *p = SvPV_const(pat, plen);
+       SV *pat = ((SVOP*)expr)->op_sv;
        U32 pm_flags = pm->op_pmflags & PMf_COMPILETIME;
-       if ((o->op_flags & OPf_SPECIAL) && (plen == 1 && *p == ' ')) {
-           U32 was_readonly = SvREADONLY(pat);
 
-           if (was_readonly) {
-               if (SvFAKE(pat)) {
-                   sv_force_normal_flags(pat, 0);
-                   assert(!SvREADONLY(pat));
-                   was_readonly = 0;
-               } else {
-                   SvREADONLY_off(pat);
-               }
-           }   
-
-           sv_setpvn(pat, "\\s+", 3);
+       if (o->op_flags & OPf_SPECIAL)
+           pm_flags |= RXf_SPLIT;
 
-           SvFLAGS(pat) |= was_readonly;
-
-           p = SvPV_const(pat, plen);
-           pm_flags |= RXf_SKIPWHITE;
+       if (DO_UTF8(pat)) {
+           assert (SvUTF8(pat));
+       } else if (SvUTF8(pat)) {
+           /* Not doing UTF-8, despite what the SV says. Is this only if we're
+              trapped in use 'bytes'?  */
+           /* Make a copy of the octet sequence, but without the flag on, as
+              the compiler now honours the SvUTF8 flag on pat.  */
+           STRLEN len;
+           const char *const p = SvPV(pat, len);
+           pat = newSVpvn_flags(p, len, SVs_TEMP);
        }
-        if (DO_UTF8(pat))
-           pm_flags |= RXf_UTF8;
+
        PM_SETRE(pm, CALLREGCOMP(pat, pm_flags));
 
 #ifdef PERL_MAD
@@ -3484,8 +3615,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
        OP *curop;
        if (pm->op_pmflags & PMf_EVAL) {
            curop = NULL;
-           if (CopLINE(PL_curcop) < (line_t)PL_multi_end)
-               CopLINE_set(PL_curcop, (line_t)PL_multi_end);
+           if (CopLINE(PL_curcop) < (line_t)PL_parser->multi_end)
+               CopLINE_set(PL_curcop, (line_t)PL_parser->multi_end);
        }
        else if (repl->op_type == OP_CONST)
            curop = repl;
@@ -3528,7 +3659,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
        if (curop == repl
            && !(repl_has_vars
                 && (!PM_GETRE(pm)
-                    || PM_GETRE(pm)->extflags & RXf_EVAL_SEEN)))
+                    || RX_EXTFLAGS(PM_GETRE(pm)) & RXf_EVAL_SEEN)))
        {
            pm->op_pmflags |= PMf_CONST;        /* const for long enough */
            prepend_elem(o->op_type, scalar(repl), o);
@@ -3564,6 +3695,9 @@ Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv)
 {
     dVAR;
     SVOP *svop;
+
+    PERL_ARGS_ASSERT_NEWSVOP;
+
     NewOp(1101, svop, 1, SVOP);
     svop->op_type = (OPCODE)type;
     svop->op_ppaddr = PL_ppaddr[type];
@@ -3583,6 +3717,9 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv)
 {
     dVAR;
     PADOP *padop;
+
+    PERL_ARGS_ASSERT_NEWPADOP;
+
     NewOp(1101, padop, 1, PADOP);
     padop->op_type = (OPCODE)type;
     padop->op_ppaddr = PL_ppaddr[type];
@@ -3605,7 +3742,9 @@ OP *
 Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv)
 {
     dVAR;
-    assert(gv);
+
+    PERL_ARGS_ASSERT_NEWGVOP;
+
 #ifdef USE_ITHREADS
     GvIN_PAD_on(gv);
     return newPADOP(type, flags, SvREFCNT_inc_simple_NN(gv));
@@ -3645,6 +3784,8 @@ Perl_package(pTHX_ OP *o)
     OP *pegop;
 #endif
 
+    PERL_ARGS_ASSERT_PACKAGE;
+
     save_hptr(&PL_curstash);
     save_item(PL_curstname);
 
@@ -3685,6 +3826,8 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
     OP *pegop = newOP(OP_NULL,0);
 #endif
 
+    PERL_ARGS_ASSERT_UTILIZE;
+
     if (idop->op_type != OP_CONST)
        Perl_croak(aTHX_ "Module name must be constant");
 
@@ -3812,6 +3955,9 @@ void
 Perl_load_module(pTHX_ U32 flags, SV *name, SV *ver, ...)
 {
     va_list args;
+
+    PERL_ARGS_ASSERT_LOAD_MODULE;
+
     va_start(args, ver);
     vload_module(flags, name, ver, &args);
     va_end(args);
@@ -3823,6 +3969,7 @@ Perl_load_module_nocontext(U32 flags, SV *name, SV *ver, ...)
 {
     dTHX;
     va_list args;
+    PERL_ARGS_ASSERT_LOAD_MODULE_NOCONTEXT;
     va_start(args, ver);
     vload_module(flags, name, ver, &args);
     va_end(args);
@@ -3834,8 +3981,10 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
 {
     dVAR;
     OP *veop, *imop;
-
     OP * const modname = newSVOP(OP_CONST, 0, name);
+
+    PERL_ARGS_ASSERT_VLOAD_MODULE;
+
     modname->op_private |= OPpCONST_BARE;
     if (ver) {
        veop = newSVOP(OP_CONST, 0, ver);
@@ -3866,7 +4015,7 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
 
     ENTER;
     SAVEVPTR(PL_curcop);
-    lex_start(NULL, NULL);
+    lex_start(NULL, NULL, FALSE);
     utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
            veop, modname, imop);
     LEAVE;
@@ -3879,6 +4028,8 @@ Perl_dofile(pTHX_ OP *term, I32 force_builtin)
     OP *doop;
     GV *gv = NULL;
 
+    PERL_ARGS_ASSERT_DOFILE;
+
     if (!force_builtin) {
        gv = gv_fetchpvs("do", GV_NOTQUAL, SVt_PVCV);
        if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) {
@@ -3970,12 +4121,15 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
     }
 
     if (is_list_assignment(left)) {
+       static const char no_list_state[] = "Initialization of state variables"
+           " in list context currently forbidden";
        OP *curop;
+       bool maybe_common_vars = TRUE;
 
        PL_modcount = 0;
        /* Grandfathering $[ assignment here.  Bletch.*/
        /* Only simple assignments like C<< ($[) = 1 >> are allowed */
-       PL_eval_start = (left->op_type == OP_CONST) ? right : 0;
+       PL_eval_start = (left->op_type == OP_CONST) ? right : NULL;
        left = mod(left, OP_AASSIGN);
        if (PL_eval_start)
            PL_eval_start = 0;
@@ -3988,6 +4142,65 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
        o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop);
        o->op_private = (U8)(0 | (flags >> 8));
 
+       if ((left->op_type == OP_LIST
+            || (left->op_type == OP_NULL && left->op_targ == OP_LIST)))
+       {
+           OP* lop = ((LISTOP*)left)->op_first;
+           maybe_common_vars = FALSE;
+           while (lop) {
+               if (lop->op_type == OP_PADSV ||
+                   lop->op_type == OP_PADAV ||
+                   lop->op_type == OP_PADHV ||
+                   lop->op_type == OP_PADANY) {
+                   if (!(lop->op_private & OPpLVAL_INTRO))
+                       maybe_common_vars = TRUE;
+
+                   if (lop->op_private & OPpPAD_STATE) {
+                       if (left->op_private & OPpLVAL_INTRO) {
+                           /* Each variable in state($a, $b, $c) = ... */
+                       }
+                       else {
+                           /* Each state variable in
+                              (state $a, my $b, our $c, $d, undef) = ... */
+                       }
+                       yyerror(no_list_state);
+                   } else {
+                       /* Each my variable in
+                          (state $a, my $b, our $c, $d, undef) = ... */
+                   }
+               } else if (lop->op_type == OP_UNDEF ||
+                          lop->op_type == OP_PUSHMARK) {
+                   /* undef may be interesting in
+                      (state $a, undef, state $c) */
+               } else {
+                   /* Other ops in the list. */
+                   maybe_common_vars = TRUE;
+               }
+               lop = lop->op_sibling;
+           }
+       }
+       else if ((left->op_private & OPpLVAL_INTRO)
+               && (   left->op_type == OP_PADSV
+                   || left->op_type == OP_PADAV
+                   || left->op_type == OP_PADHV
+                   || left->op_type == OP_PADANY))
+       {
+           maybe_common_vars = FALSE;
+           if (left->op_private & OPpPAD_STATE) {
+               /* All single variable list context state assignments, hence
+                  state ($a) = ...
+                  (state $a) = ...
+                  state @a = ...
+                  state (@a) = ...
+                  (state @a) = ...
+                  state %a = ...
+                  state (%a) = ...
+                  (state %a) = ...
+               */
+               yyerror(no_list_state);
+           }
+       }
+
        /* PL_generation sorcery:
         * an assignment like ($a,$b) = ($c,$d) is easier than
         * ($a,$b) = ($c,$a), since there is no need for temporary vars.
@@ -4002,7 +4215,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
         * to store these values, evil chicanery is done with SvUVX().
         */
 
-       {
+       if (maybe_common_vars) {
            OP *lastop = o;
            PL_generation++;
            for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
@@ -4063,7 +4276,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                o->op_private |= OPpASSIGN_COMMON;
        }
 
-       if (right && right->op_type == OP_SPLIT) {
+       if (right && right->op_type == OP_SPLIT && !PL_madskills) {
            OP* tmpop = ((LISTOP*)right)->op_first;
            if (tmpop && (tmpop->op_type == OP_PUSHRE)) {
                PMOP * const pm = (PMOP*)tmpop;
@@ -4093,11 +4306,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                        tmpop = ((UNOP*)tmpop)->op_first; /* to pushmark */
                        tmpop->op_sibling = NULL;       /* don't free split */
                        right->op_next = tmpop->op_next;  /* fix starting loc */
-#ifdef PERL_MAD
-                       op_getmad(o,right,'R');         /* blow off assign */
-#else
                        op_free(o);                     /* blow off assign */
-#endif
                        right->op_flags &= ~OPf_WANT;
                                /* "I don't know and I don't care." */
                        return right;
@@ -4129,10 +4338,11 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
        if (PL_eval_start)
            PL_eval_start = 0;
        else {
-           /* FIXME for MAD */
-           op_free(o);
-           o = newSVOP(OP_CONST, 0, newSViv(CopARYBASE_get(&PL_compiling)));
-           o->op_private |= OPpCONST_ARYBASE;
+           if (!PL_madskills) { /* assignment to $[ is ignored when making a mad dump */
+               op_free(o);
+               o = newSVOP(OP_CONST, 0, newSViv(CopARYBASE_get(&PL_compiling)));
+               o->op_private |= OPpCONST_ARYBASE;
+           }
        }
     }
     return o;
@@ -4162,10 +4372,6 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     CopHINTS_set(&PL_compiling, CopHINTS_get(cop));
     cop->op_next = (OP*)cop;
 
-    if (label) {
-       CopLABEL_set(cop, label);
-       PL_hints |= HINT_BLOCK_SCOPE;
-    }
     cop->cop_seq = seq;
     /* CopARYBASE is now "virtual", in that it's stored as a flag bit in
        CopHINTS and a possible value in cop_hints_hash, so no need to copy it.
@@ -4177,6 +4383,16 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
        cop->cop_hints_hash->refcounted_he_refcnt++;
        HINTS_REFCNT_UNLOCK;
     }
+    if (label) {
+       cop->cop_hints_hash
+           = Perl_store_cop_label(aTHX_ cop->cop_hints_hash, label);
+                                                    
+       PL_hints |= HINT_BLOCK_SCOPE;
+       /* It seems that we need to defer freeing this pointer, as other parts
+          of the grammar end up wanting to copy it after this op has been
+          created. */
+       SAVEFREEPV(label);
+    }
 
     if (PL_parser && PL_parser->copline == NOLINE)
         CopLINE_set(cop, CopLINE(PL_curcop));
@@ -4211,6 +4427,9 @@ OP *
 Perl_newLOGOP(pTHX_ I32 type, I32 flags, OP *first, OP *other)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_NEWLOGOP;
+
     return new_logop(type, flags, &first, &other);
 }
 
@@ -4223,6 +4442,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
     OP *first = *firstp;
     OP * const other = *otherp;
 
+    PERL_ARGS_ASSERT_NEW_LOGOP;
+
     if (type == OP_XOR)                /* Not short circuit, but here by precedence. */
        return newBINOP(type, flags, scalar(first), scalar(other));
 
@@ -4230,7 +4451,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
     /* optimize "!a && b" to "a || b", and "!a || b" to "a && b" */
     if (first->op_type == OP_NOT
        && (first->op_flags & OPf_SPECIAL)
-       && (first->op_flags & OPf_KIDS)) {
+       && (first->op_flags & OPf_KIDS)
+       && !PL_madskills) {
        if (type == OP_AND || type == OP_OR) {
            if (type == OP_AND)
                type = OP_OR;
@@ -4241,11 +4463,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
            if (o->op_next)
                first->op_next = o->op_next;
            cUNOPo->op_first = NULL;
-#ifdef PERL_MAD
-           op_getmad(o,first,'O');
-#else
            op_free(o);
-#endif
        }
     }
     if (first->op_type == OP_CONST) {
@@ -4280,6 +4498,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
            if ((o2->op_type == OP_PADSV || o2->op_type == OP_PADAV
                        || o2->op_type == OP_PADHV)
                && o2->op_private & OPpLVAL_INTRO
+               && !(o2->op_private & OPpPAD_STATE)
                && ckWARN(WARN_DEPRECATED))
            {
                Perl_warner(aTHX_ packWARN(WARN_DEPRECATED),
@@ -4375,6 +4594,8 @@ Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop)
     OP *start;
     OP *o;
 
+    PERL_ARGS_ASSERT_NEWCONDOP;
+
     if (!falseop)
        return newLOGOP(OP_AND, 0, first, trueop);
     if (!trueop)
@@ -4437,6 +4658,8 @@ Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right)
     OP *leftstart;
     OP *o;
 
+    PERL_ARGS_ASSERT_NEWRANGE;
+
     NewOp(1101, range, 1, LOGOP);
 
     range->op_type = OP_RANGE;
@@ -4648,6 +4871,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
     I32 iterpflags = 0;
     OP *madsv = NULL;
 
+    PERL_ARGS_ASSERT_NEWFOROP;
+
     if (sv) {
        if (sv->op_type == OP_RV2SV) {  /* symbol table variable */
            iterpflags = sv->op_private & OPpOUR_INTRO; /* for our $x () */
@@ -4767,6 +4992,8 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label)
     dVAR;
     OP *o;
 
+    PERL_ARGS_ASSERT_NEWLOOPEX;
+
     if (type != OP_GOTO || label->op_type == OP_CONST) {
        /* "last()" means "last" */
        if (label->op_type == OP_STUB && (label->op_flags & OPf_PARENS))
@@ -4831,8 +5058,10 @@ S_newGIVWHENOP(pTHX_ OP *cond, OP *block,
     LOGOP *enterop;
     OP *o;
 
+    PERL_ARGS_ASSERT_NEWGIVWHENOP;
+
     NewOp(1101, enterop, 1, LOGOP);
-    enterop->op_type = enter_opcode;
+    enterop->op_type = (Optype)enter_opcode;
     enterop->op_ppaddr = PL_ppaddr[enter_opcode];
     enterop->op_flags =  (U8) OPf_KIDS;
     enterop->op_targ = ((entertarg == NOT_IN_PAD) ? 0 : entertarg);
@@ -4880,6 +5109,9 @@ STATIC bool
 S_looks_like_bool(pTHX_ const OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_LOOKS_LIKE_BOOL;
+
     switch(o->op_type) {
        case OP_OR:
            return looks_like_bool(cLOGOPo->op_first);
@@ -4889,6 +5121,11 @@ S_looks_like_bool(pTHX_ const OP *o)
                looks_like_bool(cLOGOPo->op_first)
             && looks_like_bool(cLOGOPo->op_first->op_sibling));
 
+       case OP_NULL:
+           return (
+               o->op_flags & OPf_KIDS
+           && looks_like_bool(cUNOPo->op_first));
+
        case OP_ENTERSUB:
 
        case OP_NOT:    case OP_XOR:
@@ -4936,7 +5173,7 @@ OP *
 Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off)
 {
     dVAR;
-    assert( cond );
+    PERL_ARGS_ASSERT_NEWGIVENOP;
     return newGIVWHENOP(
        ref_array_or_hash(cond),
        block,
@@ -4951,6 +5188,8 @@ Perl_newWHENOP(pTHX_ OP *cond, OP *block)
     const bool cond_llb = (!cond || looks_like_bool(cond));
     OP *cond_op;
 
+    PERL_ARGS_ASSERT_NEWWHENOP;
+
     if (cond_llb)
        cond_op = cond;
     else {
@@ -4980,6 +5219,14 @@ void
 Perl_cv_undef(pTHX_ CV *cv)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CV_UNDEF;
+
+    DEBUG_X(PerlIO_printf(Perl_debug_log,
+         "CV undef: cv=0x%"UVxf" comppad=0x%"UVxf"\n",
+           PTR2UV(cv), PTR2UV(PL_comppad))
+    );
+
 #ifdef USE_ITHREADS
     if (CvFILE(cv) && !CvISXSUB(cv)) {
        /* for XSUBs CvFILE point directly to static memory; __FILE__ */
@@ -5026,6 +5273,8 @@ void
 Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p,
                    const STRLEN len)
 {
+    PERL_ARGS_ASSERT_CV_CKPROTO_LEN;
+
     /* Can't just use a strcmp on the prototype, as CONSTSUBs "cheat" by
        relying on SvCUR, and doubling up the buffer to hold CvFILE().  */
     if (((!p != !SvPOK(cv)) /* One has prototype, one has not.  */
@@ -5106,6 +5355,9 @@ Perl_op_const_sv(pTHX_ const OP *o, CV *cv)
     dVAR;
     SV *sv = NULL;
 
+    if (PL_madskills)
+       return NULL;
+
     if (!o)
        return NULL;
 
@@ -5452,7 +5704,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     if (ps)
        sv_setpvn((SV*)cv, ps, ps_len);
 
-    if (PL_error_count) {
+    if (PL_parser && PL_parser->error_count) {
        op_free(block);
        block = NULL;
        if (name) {
@@ -5523,7 +5775,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                           CopFILE(PL_curcop),
                           (long)PL_subline, (long)CopLINE(PL_curcop));
            gv_efullname3(tmpstr, gv, NULL);
-           hv_store(GvHV(PL_DBsub), SvPVX_const(tmpstr), SvCUR(tmpstr), sv, 0);
+           (void)hv_store(GvHV(PL_DBsub), SvPVX_const(tmpstr),
+                   SvCUR(tmpstr), sv, 0);
            hv = GvHVn(db_postponed);
            if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX_const(tmpstr), SvCUR(tmpstr))) {
                CV * const pcv = GvCV(db_postponed);
@@ -5537,7 +5790,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            }
        }
 
-       if (name && !PL_error_count)
+       if (name && ! (PL_parser && PL_parser->error_count))
            process_special_blocks(name, gv, cv);
     }
 
@@ -5555,6 +5808,8 @@ S_process_special_blocks(pTHX_ const char *const fullname, GV *const gv,
     const char *const colon = strrchr(fullname,':');
     const char *const name = colon ? colon + 1 : fullname;
 
+    PERL_ARGS_ASSERT_PROCESS_SPECIAL_BLOCKS;
+
     if (*name == 'B') {
        if (strEQ(name, "BEGIN")) {
            const I32 oldscope = PL_scopestack_ix;
@@ -5638,6 +5893,13 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
 
     ENTER;
 
+    if (IN_PERL_RUNTIME) {
+       /* at runtime, it's not safe to manipulate PL_curcop: it may be
+        * an op shared between threads. Use a non-shared COP for our
+        * dirty work */
+        SAVEVPTR(PL_curcop);
+        PL_curcop = &PL_compiling;
+    }
     SAVECOPLINE(PL_curcop);
     CopLINE_set(PL_curcop, PL_parser ? PL_parser->copline : NOLINE);
 
@@ -5676,6 +5938,8 @@ Perl_newXS_flags(pTHX_ const char *name, XSUBADDR_t subaddr,
 {
     CV *cv = newXS(name, subaddr, filename);
 
+    PERL_ARGS_ASSERT_NEWXS_FLAGS;
+
     if (flags & XS_DYNAMIC_FILENAME) {
        /* We need to "make arrangements" (ie cheat) to ensure that the
           filename lasts as long as the PVCV we just created, but also doesn't
@@ -5732,6 +5996,8 @@ Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename)
                        GV_ADDMULTI, SVt_PVCV);
     register CV *cv;
 
+    PERL_ARGS_ASSERT_NEWXS;
+
     if (!subaddr)
        Perl_croak(aTHX_ "panic: no address for '%s' in '%s'", name, filename);
 
@@ -5885,6 +6151,9 @@ OP *
 Perl_oopsAV(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_OOPSAV;
+
     switch (o->op_type) {
     case OP_PADSV:
        o->op_type = OP_PADAV;
@@ -5909,6 +6178,9 @@ OP *
 Perl_oopsHV(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_OOPSHV;
+
     switch (o->op_type) {
     case OP_PADSV:
     case OP_PADAV:
@@ -5935,6 +6207,9 @@ OP *
 Perl_newAVREF(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_NEWAVREF;
+
     if (o->op_type == OP_PADANY) {
        o->op_type = OP_PADAV;
        o->op_ppaddr = PL_ppaddr[OP_PADAV];
@@ -5960,6 +6235,9 @@ OP *
 Perl_newHVREF(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_NEWHVREF;
+
     if (o->op_type == OP_PADANY) {
        o->op_type = OP_PADHV;
        o->op_ppaddr = PL_ppaddr[OP_PADHV];
@@ -5983,6 +6261,9 @@ OP *
 Perl_newSVREF(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_NEWSVREF;
+
     if (o->op_type == OP_PADANY) {
        o->op_type = OP_PADSV;
        o->op_ppaddr = PL_ppaddr[OP_PADSV];
@@ -5997,6 +6278,8 @@ Perl_newSVREF(pTHX_ OP *o)
 OP *
 Perl_ck_anoncode(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_ANONCODE;
+
     cSVOPo->op_targ = pad_add_anon(cSVOPo->op_sv, o->op_type);
     if (!PL_madskills)
        cSVOPo->op_sv = NULL;
@@ -6007,6 +6290,9 @@ OP *
 Perl_ck_bitop(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CK_BITOP;
+
 #define OP_IS_NUMCOMPARE(op) \
        ((op) == OP_LT   || (op) == OP_I_LT || \
         (op) == OP_GT   || (op) == OP_I_GT || \
@@ -6041,7 +6327,10 @@ OP *
 Perl_ck_concat(pTHX_ OP *o)
 {
     const OP * const kid = cUNOPo->op_first;
+
+    PERL_ARGS_ASSERT_CK_CONCAT;
     PERL_UNUSED_CONTEXT;
+
     if (kid->op_type == OP_CONCAT && !(kid->op_private & OPpTARGET_MY) &&
            !(kUNOP->op_first->op_flags & OPf_MOD))
         o->op_flags |= OPf_STACKED;
@@ -6052,6 +6341,9 @@ OP *
 Perl_ck_spair(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CK_SPAIR;
+
     if (o->op_flags & OPf_KIDS) {
        OP* newop;
        OP* kid;
@@ -6080,6 +6372,8 @@ Perl_ck_spair(pTHX_ OP *o)
 OP *
 Perl_ck_delete(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_DELETE;
+
     o = ck_fun(o);
     o->op_private = 0;
     if (o->op_flags & OPf_KIDS) {
@@ -6108,6 +6402,8 @@ Perl_ck_delete(pTHX_ OP *o)
 OP *
 Perl_ck_die(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_DIE;
+
 #ifdef VMS
     if (VMSISH_HUSHED) o->op_private |= OPpHUSH_VMSISH;
 #endif
@@ -6119,6 +6415,8 @@ Perl_ck_eof(pTHX_ OP *o)
 {
     dVAR;
 
+    PERL_ARGS_ASSERT_CK_EOF;
+
     if (o->op_flags & OPf_KIDS) {
        if (cLISTOPo->op_first->op_type == OP_STUB) {
            OP * const newop
@@ -6139,6 +6437,9 @@ OP *
 Perl_ck_eval(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CK_EVAL;
+
     PL_hints |= HINT_BLOCK_SCOPE;
     if (o->op_flags & OPf_KIDS) {
        SVOP * const kid = (SVOP*)cUNOPo->op_first;
@@ -6189,11 +6490,8 @@ Perl_ck_eval(pTHX_ OP *o)
     }
     o->op_targ = (PADOFFSET)PL_hints;
     if ((PL_hints & HINT_LOCALIZE_HH) != 0 && GvHV(PL_hintgv)) {
-       /* Store a copy of %^H that pp_entereval can pick up.
-          OPf_SPECIAL flags the opcode as being for this purpose,
-          so that it in turn will return a copy at every
-          eval.*/
-       OP *hhop = newSVOP(OP_CONST, OPf_SPECIAL,
+       /* Store a copy of %^H that pp_entereval can pick up. */
+       OP *hhop = newSVOP(OP_HINTSEVAL, 0,
                           (SV*)Perl_hv_copy_hints_hv(aTHX_ GvHV(PL_hintgv)));
        cUNOPo->op_first->op_sibling = hhop;
        o->op_private |= OPpEVAL_HAS_HH;
@@ -6204,6 +6502,8 @@ Perl_ck_eval(pTHX_ OP *o)
 OP *
 Perl_ck_exit(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_EXIT;
+
 #ifdef VMS
     HV * const table = GvHV(PL_hintgv);
     if (table) {
@@ -6219,6 +6519,8 @@ Perl_ck_exit(pTHX_ OP *o)
 OP *
 Perl_ck_exec(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_EXEC;
+
     if (o->op_flags & OPf_STACKED) {
         OP *kid;
        o = ck_fun(o);
@@ -6235,12 +6537,16 @@ OP *
 Perl_ck_exists(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CK_EXISTS;
+
     o = ck_fun(o);
     if (o->op_flags & OPf_KIDS) {
        OP * const kid = cUNOPo->op_first;
        if (kid->op_type == OP_ENTERSUB) {
            (void) ref(kid, o->op_type);
-           if (kid->op_type != OP_RV2CV && !PL_error_count)
+           if (kid->op_type != OP_RV2CV
+                       && !(PL_parser && PL_parser->error_count))
                Perl_croak(aTHX_ "%s argument is not a subroutine name",
                            OP_DESC(o));
            o->op_private |= OPpEXISTS_SUB;
@@ -6261,6 +6567,8 @@ Perl_ck_rvconst(pTHX_ register OP *o)
     dVAR;
     SVOP * const kid = (SVOP*)cUNOPo->op_first;
 
+    PERL_ARGS_ASSERT_CK_RVCONST;
+
     o->op_private |= (PL_hints & HINT_STRICT_REFS);
     if (o->op_type == OP_RV2CV)
        o->op_private &= ~1;
@@ -6377,6 +6685,8 @@ Perl_ck_ftst(pTHX_ OP *o)
     dVAR;
     const I32 type = o->op_type;
 
+    PERL_ARGS_ASSERT_CK_FTST;
+
     if (o->op_flags & OPf_REF) {
        NOOP;
     }
@@ -6394,7 +6704,7 @@ Perl_ck_ftst(pTHX_ OP *o)
 #endif
            return newop;
        }
-       if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o))
+       if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o->op_type))
            o->op_private |= OPpFT_ACCESS;
        if (PL_check[kidtype] == MEMBER_TO_FPTR(Perl_ck_ftst)
                && kidtype != OP_STAT && kidtype != OP_LSTAT)
@@ -6422,6 +6732,8 @@ Perl_ck_fun(pTHX_ OP *o)
     const int type = o->op_type;
     register I32 oa = PL_opargs[type] >> OASHIFT;
 
+    PERL_ARGS_ASSERT_CK_FUN;
+
     if (o->op_flags & OPf_STACKED) {
        if ((oa & OA_OPTIONAL) && (oa >> 4) && !((oa >> 4) & OA_OPTIONAL))
            oa &= ~OA_OPTIONAL;
@@ -6697,6 +7009,8 @@ Perl_ck_glob(pTHX_ OP *o)
     dVAR;
     GV *gv;
 
+    PERL_ARGS_ASSERT_CK_GLOB;
+
     o = ck_fun(o);
     if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling)
        append_elem(OP_GLOB, o, newDEFSVOP());
@@ -6755,8 +7069,10 @@ Perl_ck_grep(pTHX_ OP *o)
     const OPCODE type = o->op_type == OP_GREPSTART ? OP_GREPWHILE : OP_MAPWHILE;
     PADOFFSET offset;
 
+    PERL_ARGS_ASSERT_CK_GREP;
+
     o->op_ppaddr = PL_ppaddr[OP_GREPSTART];
-    /* don't allocate gwop here, as we may leak it if PL_error_count > 0 */
+    /* don't allocate gwop here, as we may leak it if PL_parser->error_count > 0 */
 
     if (o->op_flags & OPf_STACKED) {
        OP* k;
@@ -6777,7 +7093,7 @@ Perl_ck_grep(pTHX_ OP *o)
     else
        scalar(kid);
     o = ck_fun(o);
-    if (PL_error_count)
+    if (PL_parser && PL_parser->error_count)
        return o;
     kid = cLISTOPo->op_first->op_sibling;
     if (kid->op_type != OP_NULL)
@@ -6814,6 +7130,8 @@ Perl_ck_grep(pTHX_ OP *o)
 OP *
 Perl_ck_index(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_INDEX;
+
     if (o->op_flags & OPf_KIDS) {
        OP *kid = cLISTOPo->op_first->op_sibling;       /* get past pushmark */
        if (kid)
@@ -6825,22 +7143,20 @@ Perl_ck_index(pTHX_ OP *o)
 }
 
 OP *
-Perl_ck_lengthconst(pTHX_ OP *o)
-{
-    /* XXX length optimization goes here */
-    return ck_fun(o);
-}
-
-OP *
 Perl_ck_lfun(pTHX_ OP *o)
 {
     const OPCODE type = o->op_type;
+
+    PERL_ARGS_ASSERT_CK_LFUN;
+
     return modkids(ck_fun(o), type);
 }
 
 OP *
 Perl_ck_defined(pTHX_ OP *o)           /* 19990527 MJD */
 {
+    PERL_ARGS_ASSERT_CK_DEFINED;
+
     if ((o->op_flags & OPf_KIDS) && ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) {
        switch (cUNOPo->op_first->op_type) {
        case OP_RV2AV:
@@ -6879,6 +7195,8 @@ Perl_ck_defined(pTHX_ OP *o)              /* 19990527 MJD */
 OP *
 Perl_ck_readline(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_READLINE;
+
     if (!(o->op_flags & OPf_KIDS)) {
        OP * const newop
            = newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, PL_argvgv));
@@ -6896,6 +7214,9 @@ OP *
 Perl_ck_rfun(pTHX_ OP *o)
 {
     const OPCODE type = o->op_type;
+
+    PERL_ARGS_ASSERT_CK_RFUN;
+
     return refkids(ck_fun(o), type);
 }
 
@@ -6904,6 +7225,8 @@ Perl_ck_listiob(pTHX_ OP *o)
 {
     register OP *kid;
 
+    PERL_ARGS_ASSERT_CK_LISTIOB;
+
     kid = cLISTOPo->op_first;
     if (!kid) {
        o = force_list(o);
@@ -6960,12 +7283,19 @@ Perl_ck_smartmatch(pTHX_ OP *o)
 OP *
 Perl_ck_sassign(pTHX_ OP *o)
 {
+    dVAR;
     OP * const kid = cLISTOPo->op_first;
+
+    PERL_ARGS_ASSERT_CK_SASSIGN;
+
     /* has a disposable target? */
     if ((PL_opargs[kid->op_type] & OA_TARGLEX)
        && !(kid->op_flags & OPf_STACKED)
        /* Cannot steal the second time! */
-       && !(kid->op_private & OPpTARGET_MY))
+       && !(kid->op_private & OPpTARGET_MY)
+       /* Keep the full thing for madskills */
+       && !PL_madskills
+       )
     {
        OP * const kkid = kid->op_sibling;
 
@@ -6978,17 +7308,40 @@ Perl_ck_sassign(pTHX_ OP *o)
            /* Now we do not need PADSV and SASSIGN. */
            kid->op_sibling = o->op_sibling;    /* NULL */
            cLISTOPo->op_first = NULL;
-#ifdef PERL_MAD
-           op_getmad(o,kid,'O');
-           op_getmad(kkid,kid,'M');
-#else
            op_free(o);
            op_free(kkid);
-#endif
            kid->op_private |= OPpTARGET_MY;    /* Used for context settings */
            return kid;
        }
     }
+    if (kid->op_sibling) {
+       OP *kkid = kid->op_sibling;
+       if (kkid->op_type == OP_PADSV
+               && (kkid->op_private & OPpLVAL_INTRO)
+               && SvPAD_STATE(*av_fetch(PL_comppad_name, kkid->op_targ, FALSE))) {
+           const PADOFFSET target = kkid->op_targ;
+           OP *const other = newOP(OP_PADSV,
+                                   kkid->op_flags
+                                   | ((kkid->op_private & ~OPpLVAL_INTRO) << 8));
+           OP *const first = newOP(OP_NULL, 0);
+           OP *const nullop = newCONDOP(0, first, o, other);
+           OP *const condop = first->op_next;
+           /* hijacking PADSTALE for uninitialized state variables */
+           SvPADSTALE_on(PAD_SVl(target));
+
+           condop->op_type = OP_ONCE;
+           condop->op_ppaddr = PL_ppaddr[OP_ONCE];
+           condop->op_targ = target;
+           other->op_targ = target;
+
+           /* Because we change the type of the op here, we will skip the
+              assinment binop->op_last = binop->op_first->op_sibling; at the
+              end of Perl_newBINOP(). So need to do it here. */
+           cBINOPo->op_last = cBINOPo->op_first->op_sibling;
+
+           return nullop;
+       }
+    }
     return o;
 }
 
@@ -6996,6 +7349,9 @@ OP *
 Perl_ck_match(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CK_MATCH;
+
     if (o->op_type != OP_QR && PL_compcv) {
        const PADOFFSET offset = pad_findmy("$_");
        if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS_isOUR(offset))) {
@@ -7012,6 +7368,9 @@ OP *
 Perl_ck_method(pTHX_ OP *o)
 {
     OP * const kid = cUNOPo->op_first;
+
+    PERL_ARGS_ASSERT_CK_METHOD;
+
     if (kid->op_type == OP_CONST) {
        SV* sv = kSVOP->op_sv;
        const char * const method = SvPVX_const(sv);
@@ -7038,6 +7397,7 @@ Perl_ck_method(pTHX_ OP *o)
 OP *
 Perl_ck_null(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_NULL;
     PERL_UNUSED_CONTEXT;
     return o;
 }
@@ -7047,6 +7407,9 @@ Perl_ck_open(pTHX_ OP *o)
 {
     dVAR;
     HV * const table = GvHV(PL_hintgv);
+
+    PERL_ARGS_ASSERT_CK_OPEN;
+
     if (table) {
        SV **svp = hv_fetchs(table, "open_IN", FALSE);
        if (svp && *svp) {
@@ -7104,6 +7467,8 @@ Perl_ck_open(pTHX_ OP *o)
 OP *
 Perl_ck_repeat(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_REPEAT;
+
     if (cBINOPo->op_first->op_flags & OPf_PARENS) {
        o->op_private |= OPpREPEAT_DOLIST;
        cBINOPo->op_first = force_list(cBINOPo->op_first);
@@ -7119,6 +7484,8 @@ Perl_ck_require(pTHX_ OP *o)
     dVAR;
     GV* gv = NULL;
 
+    PERL_ARGS_ASSERT_CK_REQUIRE;
+
     if (o->op_flags & OPf_KIDS) {      /* Shall we supply missing .pm? */
        SVOP * const kid = (SVOP*)cUNOPo->op_first;
 
@@ -7126,6 +7493,8 @@ Perl_ck_require(pTHX_ OP *o)
            SV * const sv = kid->op_sv;
            U32 was_readonly = SvREADONLY(sv);
            char *s;
+           STRLEN len;
+           const char *end;
 
            if (was_readonly) {
                if (SvFAKE(sv)) {
@@ -7137,14 +7506,17 @@ Perl_ck_require(pTHX_ OP *o)
                }
            }   
 
-           for (s = SvPVX(sv); *s; s++) {
+           s = SvPVX(sv);
+           len = SvCUR(sv);
+           end = s + len;
+           for (; s < end; s++) {
                if (*s == ':' && s[1] == ':') {
-                   const STRLEN len = strlen(s+2)+1;
                    *s = '/';
-                   Move(s+2, s+1, len, char);
-                   SvCUR_set(sv, SvCUR(sv) - 1);
+                   Move(s+2, s+1, end - s - 1, char);
+                   --end;
                }
            }
+           SvEND_set(sv, end);
            sv_catpvs(sv, ".pm");
            SvFLAGS(sv) |= was_readonly;
        }
@@ -7183,6 +7555,9 @@ OP *
 Perl_ck_return(pTHX_ OP *o)
 {
     dVAR;
+
+    PERL_ARGS_ASSERT_CK_RETURN;
+
     if (CvLVALUE(PL_compcv)) {
         OP *kid;
        for (kid = cLISTOPo->op_first->op_sibling; kid; kid = kid->op_sibling)
@@ -7196,6 +7571,9 @@ Perl_ck_select(pTHX_ OP *o)
 {
     dVAR;
     OP* kid;
+
+    PERL_ARGS_ASSERT_CK_SELECT;
+
     if (o->op_flags & OPf_KIDS) {
        kid = cLISTOPo->op_first->op_sibling;   /* get past pushmark */
        if (kid && kid->op_sibling) {
@@ -7218,6 +7596,8 @@ Perl_ck_shift(pTHX_ OP *o)
     dVAR;
     const I32 type = o->op_type;
 
+    PERL_ARGS_ASSERT_CK_SHIFT;
+
     if (!(o->op_flags & OPf_KIDS)) {
        OP *argop;
        /* FIXME - this can be refactored to reduce code in #ifdefs  */
@@ -7245,6 +7625,8 @@ Perl_ck_sort(pTHX_ OP *o)
     dVAR;
     OP *firstkid;
 
+    PERL_ARGS_ASSERT_CK_SORT;
+
     if (o->op_type == OP_SORT && (PL_hints & HINT_LOCALIZE_HH) != 0) {
        HV * const hinthv = GvHV(PL_hintgv);
        if (hinthv) {
@@ -7326,6 +7708,9 @@ S_simplify_sort(pTHX_ OP *o)
     int descending;
     GV *gv;
     const char *gvname;
+
+    PERL_ARGS_ASSERT_SIMPLIFY_SORT;
+
     if (!(o->op_flags & OPf_STACKED))
        return;
     GvMULTI_on(gv_fetchpvs("a", GV_ADD|GV_NOTQUAL, SVt_PV));
@@ -7397,6 +7782,8 @@ Perl_ck_split(pTHX_ OP *o)
     dVAR;
     register OP *kid;
 
+    PERL_ARGS_ASSERT_CK_SPLIT;
+
     if (o->op_flags & OPf_STACKED)
        return no_fh_allowed(o);
 
@@ -7452,11 +7839,14 @@ OP *
 Perl_ck_join(pTHX_ OP *o)
 {
     const OP * const kid = cLISTOPo->op_first->op_sibling;
+
+    PERL_ARGS_ASSERT_CK_JOIN;
+
     if (kid && kid->op_type == OP_MATCH) {
        if (ckWARN(WARN_SYNTAX)) {
             const REGEXP *re = PM_GETRE(kPMOP);
-           const char *pmstr = re ? re->precomp : "STRING";
-           const STRLEN len = re ? re->prelen : 6;
+           const char *pmstr = re ? RX_PRECOMP(re) : "STRING";
+           const STRLEN len = re ? RX_PRELEN(re) : 6;
            Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                        "/%.*s/ should probably be written as \"%.*s\"",
                        (int)len, pmstr, (int)len, pmstr);
@@ -7483,6 +7873,8 @@ Perl_ck_subr(pTHX_ OP *o)
     const char *e = NULL;
     bool delete_op = 0;
 
+    PERL_ARGS_ASSERT_CK_SUBR;
+
     o->op_private |= OPpENTERSUB_HASTARG;
     for (cvop = o2; cvop->op_sibling; cvop = cvop->op_sibling) ;
     if (cvop->op_type == OP_RV2CV) {
@@ -7502,26 +7894,6 @@ Perl_ck_subr(pTHX_ OP *o)
                    proto = SvPV((SV*)cv, len);
                    proto_end = proto + len;
                }
-               if (CvASSERTION(cv)) {
-                   U32 asserthints = 0;
-                   HV *const hinthv = GvHV(PL_hintgv);
-                   if (hinthv) {
-                       SV **svp = hv_fetchs(hinthv, "assertions", FALSE);
-                       if (svp && *svp)
-                           asserthints = SvUV(*svp);
-                   }
-                   if (asserthints & HINT_ASSERTING) {
-                       if (PERLDB_ASSERTION && PL_curstash != PL_debstash)
-                           o->op_private |= OPpENTERSUB_DB;
-                   }
-                   else {
-                       delete_op = 1;
-                       if (!(asserthints & HINT_ASSERTIONSSEEN) && ckWARN(WARN_ASSERTIONS)) {
-                           Perl_warner(aTHX_ packWARN(WARN_ASSERTIONS),
-                                       "Impossible to activate assertion call");
-                       }
-                   }
-               }
            }
        }
     }
@@ -7742,6 +8114,7 @@ Perl_ck_subr(pTHX_ OP *o)
 OP *
 Perl_ck_svconst(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_SVCONST;
     PERL_UNUSED_CONTEXT;
     SvREADONLY_on(cSVOPo->op_sv);
     return o;
@@ -7766,6 +8139,8 @@ Perl_ck_chdir(pTHX_ OP *o)
 OP *
 Perl_ck_trunc(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_TRUNC;
+
     if (o->op_flags & OPf_KIDS) {
        SVOP *kid = (SVOP*)cUNOPo->op_first;
 
@@ -7785,6 +8160,9 @@ OP *
 Perl_ck_unpack(pTHX_ OP *o)
 {
     OP *kid = cLISTOPo->op_first;
+
+    PERL_ARGS_ASSERT_CK_UNPACK;
+
     if (kid->op_sibling) {
        kid = kid->op_sibling;
        if (!kid->op_sibling)
@@ -7796,6 +8174,8 @@ Perl_ck_unpack(pTHX_ OP *o)
 OP *
 Perl_ck_substr(pTHX_ OP *o)
 {
+    PERL_ARGS_ASSERT_CK_SUBSTR;
+
     o = ck_fun(o);
     if ((o->op_flags & OPf_KIDS) && (o->op_private == 4)) {
        OP *kid = cLISTOPo->op_first;
@@ -7809,6 +8189,29 @@ Perl_ck_substr(pTHX_ OP *o)
     return o;
 }
 
+OP *
+Perl_ck_each(pTHX_ OP *o)
+{
+    dVAR;
+    OP *kid = cLISTOPo->op_first;
+
+    PERL_ARGS_ASSERT_CK_EACH;
+
+    if (kid->op_type == OP_PADAV || kid->op_type == OP_RV2AV) {
+       const unsigned new_type = o->op_type == OP_EACH ? OP_AEACH
+           : o->op_type == OP_KEYS ? OP_AKEYS : OP_AVALUES;
+       o->op_type = new_type;
+       o->op_ppaddr = PL_ppaddr[new_type];
+    }
+    else if (!(kid->op_type == OP_PADHV || kid->op_type == OP_RV2HV
+              || (kid->op_type == OP_CONST && kid->op_private & OPpCONST_BARE)
+              )) {
+       bad_type(1, "hash or array", PL_op_desc[o->op_type], kid);
+       return o;
+    }
+    return ck_fun(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 */
@@ -7832,7 +8235,6 @@ Perl_peep(pTHX_ register OP *o)
        o->op_opt = 1;
        PL_op = o;
        switch (o->op_type) {
-       case OP_SETSTATE:
        case OP_NEXTSTATE:
        case OP_DBSTATE:
            PL_curcop = ((COP*)o);              /* for warnings */
@@ -7842,20 +8244,21 @@ Perl_peep(pTHX_ register OP *o)
            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_CONST && SvPADTMP(cSVOPo->op_sv)) {
+               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_CONST
+               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
@@ -7902,8 +8305,7 @@ Perl_peep(pTHX_ register OP *o)
            goto nothin;
        case OP_NULL:
            if (o->op_targ == OP_NEXTSTATE
-               || o->op_targ == OP_DBSTATE
-               || o->op_targ == OP_SETSTATE)
+               || o->op_targ == OP_DBSTATE)
            {
                PL_curcop = ((COP*)o);
            }
@@ -8007,6 +8409,7 @@ Perl_peep(pTHX_ register OP *o)
        case OP_DORASSIGN:
        case OP_COND_EXPR:
        case OP_RANGE:
+       case OP_ONCE:
            while (cLOGOP->op_other->op_type == OP_NULL)
                cLOGOP->op_other = cLOGOP->op_other->op_next;
            peep(cLOGOP->op_other); /* Recursive calls are not replaced by fptr calls */
@@ -8367,7 +8770,7 @@ Perl_peep(pTHX_ register OP *o)
            UNOP *refgen, *rv2cv;
            LISTOP *exlist;
 
-           if ((o->op_flags && OPf_WANT) != OPf_WANT_VOID)
+           if ((o->op_flags & OPf_WANT) != OPf_WANT_VOID)
                break;
 
            if ((o->op_private & ~OPpASSIGN_BACKWARDS) != 2)
@@ -8419,7 +8822,7 @@ Perl_peep(pTHX_ register OP *o)
     LEAVE;
 }
 
-char*
+const char*
 Perl_custom_op_name(pTHX_ const OP* o)
 {
     dVAR;
@@ -8427,6 +8830,8 @@ Perl_custom_op_name(pTHX_ const OP* o)
     SV* keysv;
     HE* he;
 
+    PERL_ARGS_ASSERT_CUSTOM_OP_NAME;
+
     if (!PL_custom_op_names) /* This probably shouldn't happen */
         return (char *)PL_op_name[OP_CUSTOM];
 
@@ -8439,7 +8844,7 @@ Perl_custom_op_name(pTHX_ const OP* o)
     return SvPV_nolen(HeVAL(he));
 }
 
-char*
+const char*
 Perl_custom_op_desc(pTHX_ const OP* o)
 {
     dVAR;
@@ -8447,6 +8852,8 @@ Perl_custom_op_desc(pTHX_ const OP* o)
     SV* keysv;
     HE* he;
 
+    PERL_ARGS_ASSERT_CUSTOM_OP_DESC;
+
     if (!PL_custom_op_descs)
         return (char *)PL_op_desc[OP_CUSTOM];