Add get_cvn_flags(), which is like get_cv() but takes a length. This
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index f5e24fc..9e565fe 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1,7 +1,7 @@
 /*    op.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -89,10 +89,10 @@ recursive, but it's recursive on basic blocks, not on tree nodes.
    To cause actions on %^H to write out the serialisation records, it has
    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> with a store
+   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>
-   saves the current C<PL_compiling.cop_hints> on the save stack, so that it
-   will be correctly restored when any inner compiling scope is exited.
+   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.
 */
 
 #include "EXTERN.h"
@@ -224,7 +224,7 @@ S_no_bareword_allowed(pTHX_ const OP *o)
        return;         /* various ok barewords are hidden in extra OP_NULL */
     qerror(Perl_mess(aTHX_
                     "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use",
-                    (void*)cSVOPo_sv));
+                    SVfARG(cSVOPo_sv)));
 }
 
 /* "register" allocation */
@@ -277,6 +277,20 @@ Perl_allocmy(pTHX_ const char *const name)
     return off;
 }
 
+/* free the body of an op without examining its contents.
+ * Always use this rather than FreeOp directly */
+
+void
+S_op_destroy(pTHX_ OP *o)
+{
+    if (o->op_latefree) {
+       o->op_latefreed = 1;
+       return;
+    }
+    FreeOp(o);
+}
+
+
 /* Destructor */
 
 void
@@ -287,6 +301,11 @@ Perl_op_free(pTHX_ OP *o)
 
     if (!o || o->op_static)
        return;
+    if (o->op_latefreed) {
+       if (o->op_latefree)
+           return;
+       goto do_free;
+    }
 
     type = o->op_type;
     if (o->op_private & OPpREFCOUNTED) {
@@ -327,6 +346,11 @@ Perl_op_free(pTHX_ OP *o)
        cop_free((COP*)o);
 
     op_clear(o);
+    if (o->op_latefree) {
+       o->op_latefreed = 1;
+       return;
+    }
+  do_free:
     FreeOp(o);
 #ifdef DEBUG_LEAKING_SCALARS
     if (PL_op == o)
@@ -414,11 +438,18 @@ Perl_op_clear(pTHX_ OP *o)
        /* FALL THROUGH */
     case OP_TRANS:
        if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) {
+#ifdef USE_ITHREADS
+           if (cPADOPo->op_padix > 0) {
+               pad_swipe(cPADOPo->op_padix, TRUE);
+               cPADOPo->op_padix = 0;
+           }
+#else
            SvREFCNT_dec(cSVOPo->op_sv);
            cSVOPo->op_sv = NULL;
+#endif
        }
        else {
-           Safefree(cPVOPo->op_pv);
+           PerlMemShared_free(cPVOPo->op_pv);
            cPVOPo->op_pv = NULL;
        }
        break;
@@ -490,19 +521,12 @@ clear_pmop:
 STATIC void
 S_cop_free(pTHX_ COP* cop)
 {
-    Safefree(cop->cop_label);   /* FIXME: treaddead ??? */
+    CopLABEL_free(cop);
     CopFILE_free(cop);
     CopSTASH_free(cop);
     if (! specialWARN(cop->cop_warnings))
        PerlMemShared_free(cop->cop_warnings);
-    if (! specialCopIO(cop->cop_io)) {
-#ifdef USE_ITHREADS
-       NOOP;
-#else
-       SvREFCNT_dec(cop->cop_io);
-#endif
-    }
-    Perl_refcounted_he_free(aTHX_ cop->cop_hints);
+    Perl_refcounted_he_free(aTHX_ cop->cop_hints_hash);
 }
 
 void
@@ -647,7 +671,7 @@ Perl_scalar(pTHX_ OP *o)
            else
                scalar(kid);
        }
-       WITH_THR(PL_curcop = &PL_compiling);
+       PL_curcop = &PL_compiling;
        break;
     case OP_SCOPE:
     case OP_LINESEQ:
@@ -658,7 +682,7 @@ Perl_scalar(pTHX_ OP *o)
            else
                scalar(kid);
        }
-       WITH_THR(PL_curcop = &PL_compiling);
+       PL_curcop = &PL_compiling;
        break;
     case OP_SORT:
        if (ckWARN(WARN_VOID))
@@ -995,7 +1019,7 @@ Perl_list(pTHX_ OP *o)
            else
                list(kid);
        }
-       WITH_THR(PL_curcop = &PL_compiling);
+       PL_curcop = &PL_compiling;
        break;
     case OP_SCOPE:
     case OP_LINESEQ:
@@ -1005,7 +1029,7 @@ Perl_list(pTHX_ OP *o)
            else
                list(kid);
        }
-       WITH_THR(PL_curcop = &PL_compiling);
+       PL_curcop = &PL_compiling;
        break;
     case OP_REQUIRE:
        /* all requires must return a boolean value */
@@ -1534,10 +1558,6 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref)
        }
        break;
 
-    case OP_THREADSV:
-       o->op_flags |= OPf_MOD;         /* XXX ??? */
-       break;
-
     case OP_RV2AV:
     case OP_RV2HV:
        if (set_op_ref)
@@ -1776,7 +1796,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
               type == OP_RV2AV ||
               type == OP_RV2HV) { /* XXX does this let anything illegal in? */
        if (cUNOPo->op_first->op_type != OP_GV) { /* MJD 20011224 */
-           yyerror(Perl_form(aTHX_ "Can't declare %s in %s",
+           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"));
        } else if (attrs) {
@@ -1883,7 +1903,7 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
     {
       const char * const desc
          = PL_op_desc[(rtype == OP_SUBST || rtype == OP_TRANS)
-            ? rtype : OP_MATCH];
+                      ? (int)rtype : OP_MATCH];
       const char * const sample = ((ltype == OP_RV2AV || ltype == OP_PADAV)
             ? "@array" : "%hash");
       Perl_warner(aTHX_ packWARN(WARN_MISC),
@@ -1977,11 +1997,6 @@ Perl_block_start(pTHX_ int full)
     PL_hints &= ~HINT_BLOCK_SCOPE;
     SAVECOMPILEWARNINGS();
     PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings);
-    SAVESPTR(PL_compiling.cop_io);
-    if (! specialCopIO(PL_compiling.cop_io)) {
-        PL_compiling.cop_io = newSVsv(PL_compiling.cop_io) ;
-        SAVEFREESV(PL_compiling.cop_io) ;
-    }
     return retval;
 }
 
@@ -2034,7 +2049,7 @@ Perl_newPROG(pTHX_ OP *o)
        if (o->op_type == OP_STUB) {
            PL_comppad_name = 0;
            PL_compcv = 0;
-           FreeOp(o);
+           S_op_destroy(aTHX_ o);
            return;
        }
        PL_main_root = scope(sawparens(scalarvoid(o)));
@@ -2048,7 +2063,8 @@ Perl_newPROG(pTHX_ OP *o)
 
        /* Register with debugger */
        if (PERLDB_INTER) {
-           CV * const cv = get_cv("DB::postponed", FALSE);
+           CV * const cv
+               = Perl_get_cvn_flags(aTHX_ STR_WITH_LEN("DB::postponed"), 0);
            if (cv) {
                dSP;
                PUSHMARK(SP);
@@ -2130,8 +2146,8 @@ Perl_fold_constants(pTHX_ register OP *o)
     dVAR;
     register OP *curop;
     OP *newop;
-    I32 type = o->op_type;
-    SV *sv = NULL;
+    VOL I32 type = o->op_type;
+    SV * VOL sv = NULL;
     int ret = 0;
     I32 oldscope;
     OP *old_next;
@@ -2245,7 +2261,7 @@ Perl_fold_constants(pTHX_ register OP *o)
     if (type == OP_RV2GV)
        newop = newGVOP(OP_GV, 0, (GV*)sv);
     else
-       newop = newSVOP(OP_CONST, 0, sv);
+       newop = newSVOP(OP_CONST, 0, (SV*)sv);
     op_getmad(o,newop,'f');
     return newop;
 
@@ -2270,6 +2286,8 @@ Perl_gen_constant_list(pTHX_ register OP *o)
     pp_pushmark();
     CALLRUNOPS(aTHX);
     PL_op = curop;
+    assert (!(curop->op_flags & OPf_SPECIAL));
+    assert(curop->op_type == OP_RANGE);
     pp_anonlist();
     PL_tmps_floor = oldtmps_floor;
 
@@ -2374,7 +2392,7 @@ Perl_append_list(pTHX_ I32 type, LISTOP *first, LISTOP *last)
     last->op_madprop = 0;
 #endif
 
-    FreeOp(last);
+    S_op_destroy(aTHX_ (OP*)last);
 
     return (OP*)first;
 }
@@ -2710,6 +2728,9 @@ Perl_newOP(pTHX_ I32 type, I32 flags)
     o->op_type = (OPCODE)type;
     o->op_ppaddr = PL_ppaddr[type];
     o->op_flags = (U8)flags;
+    o->op_latefree = 0;
+    o->op_latefreed = 0;
+    o->op_attached = 0;
 
     o->op_next = o;
     o->op_private = (U8)(0 | (flags >> 8));
@@ -2798,7 +2819,12 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
 {
     dVAR;
     SV * const tstr = ((SVOP*)expr)->op_sv;
-    SV * const rstr = ((SVOP*)repl)->op_sv;
+    SV * const rstr =
+#ifdef PERL_MAD
+                       (repl->op_type == OP_NULL)
+                           ? ((SVOP*)((LISTOP*)repl)->op_first)->op_sv :
+#endif
+                             ((SVOP*)repl)->op_sv;
     STRLEN tlen;
     STRLEN rlen;
     const U8 *t = (U8*)SvPV_const(tstr, tlen);
@@ -2811,6 +2837,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
     const I32 complement = o->op_private & OPpTRANS_COMPLEMENT;
     const I32 squash     = o->op_private & OPpTRANS_SQUASH;
     I32 del              = o->op_private & OPpTRANS_DELETE;
+    SV* swash;
     PL_hints |= HINT_BLOCK_SCOPE;
 
     if (SvUTF8(tstr))
@@ -3004,13 +3031,23 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        else
            bits = 8;
 
-       Safefree(cPVOPo->op_pv);
-       cSVOPo->op_sv = (SV*)swash_init("utf8", "", listsv, bits, none);
+       PerlMemShared_free(cPVOPo->op_pv);
+       cPVOPo->op_pv = NULL;
+
+       swash = (SV*)swash_init("utf8", "", listsv, bits, none);
+#ifdef USE_ITHREADS
+       cPADOPo->op_padix = pad_alloc(OP_TRANS, SVs_PADTMP);
+       SvREFCNT_dec(PAD_SVl(cPADOPo->op_padix));
+       PAD_SETSV(cPADOPo->op_padix, swash);
+       SvPADTMP_on(swash);
+#else
+       cSVOPo->op_sv = swash;
+#endif
        SvREFCNT_dec(listsv);
        SvREFCNT_dec(transv);
 
        if (!del && havefinal && rlen)
-           (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
+           (void)hv_store((HV*)SvRV(swash), "FINAL", 5,
                           newSVuv((UV)final), 0);
 
        if (grows)
@@ -3059,8 +3096,13 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
            }
            else if (j >= (I32)rlen)
                j = rlen - 1;
-           else
-               cPVOPo->op_pv = (char*)Renew(tbl, 0x101+rlen-j, short);
+           else {
+               tbl = 
+                   (short *)
+                   PerlMemShared_realloc(tbl,
+                                         (0x101+rlen-j) * sizeof(short));
+               cPVOPo->op_pv = (char*)tbl;
+           }
            tbl[0x100] = (short)(rlen - j);
            for (i=0; i < (I32)rlen - j; i++)
                tbl[0x101+i] = r[j+i];
@@ -3235,9 +3277,11 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
         if (DO_UTF8(pat))
            pm->op_pmdynflags |= PMdf_UTF8;
        /* FIXME - can we make this function take const char * args?  */
-       PM_SETRE(pm, CALLREGCOMP(aTHX_ (char*)p, (char*)p + plen, pm));
-       if (strEQ("\\s+", PM_GETRE(pm)->precomp))
+       PM_SETRE(pm, CALLREGCOMP((char*)p, (char*)p + plen, pm));
+       if (PM_GETRE(pm)->extflags & RXf_WHITE)
            pm->op_pmflags |= PMf_WHITE;
+       else
+           pm->op_pmflags &= ~PMf_WHITE;
 #ifdef PERL_MAD
        op_getmad(expr,(OP*)pm,'e');
 #else
@@ -3291,7 +3335,9 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
        else {
            OP *lastop = NULL;
            for (curop = LINKLIST(repl); curop!=repl; curop = LINKLIST(curop)) {
-               if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
+               if (curop->op_type == OP_SCOPE
+                       || curop->op_type == OP_LEAVE
+                       || (PL_opargs[curop->op_type] & OA_DANGEROUS)) {
                    if (curop->op_type == OP_GV) {
                        GV * const gv = cGVOPx_gv(curop);
                        repl_has_vars = 1;
@@ -3310,7 +3356,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
                    else if (curop->op_type == OP_PADSV ||
                             curop->op_type == OP_PADAV ||
                             curop->op_type == OP_PADHV ||
-                            curop->op_type == OP_PADANY) {
+                            curop->op_type == OP_PADANY)
+                   {
                        repl_has_vars = 1;
                    }
                    else if (curop->op_type == OP_PUSHRE)
@@ -3324,7 +3371,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
        if (curop == repl
            && !(repl_has_vars
                 && (!PM_GETRE(pm)
-                    || PM_GETRE(pm)->reganch & ROPT_EVAL_SEEN))) {
+                    || PM_GETRE(pm)->extflags & RXf_EVAL_SEEN)))
+       {
            pm->op_pmflags |= PMf_CONST;        /* const for long enough */
            pm->op_pmpermflags |= PMf_CONST;    /* const for long enough */
            prepend_elem(o->op_type, scalar(repl), o);
@@ -3792,10 +3840,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
         * that value, we know we've got commonality.  We could use a
         * single bit marker, but then we'd have to make 2 passes, first
         * to clear the flag, then to test and set it.  To find somewhere
-        * to store these values, evil chicanery is done with SvCUR().
+        * to store these values, evil chicanery is done with SvUVX().
         */
 
-       if (!(left->op_private & OPpLVAL_INTRO)) {
+       {
            OP *lastop = o;
            PL_generation++;
            for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
@@ -3850,6 +3898,34 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
            if (curop != o)
                o->op_private |= OPpASSIGN_COMMON;
        }
+
+       if ( ((left->op_private & OPpLVAL_INTRO) || ckWARN(WARN_MISC))
+               && (left->op_type == OP_LIST
+                   || (left->op_type == OP_NULL && left->op_targ == OP_LIST)))
+       {
+           OP* lop = ((LISTOP*)left)->op_first;
+           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 & OPpPAD_STATE) {
+                       if (left->op_private & OPpLVAL_INTRO) {
+                           o->op_private |= OPpASSIGN_STATE;
+                           /* hijacking PADSTALE for uninitialized state variables */
+                           SvPADSTALE_on(PAD_SVl(lop->op_targ));
+                       }
+                       else { /* we already checked for WARN_MISC before */
+                           Perl_warner(aTHX_ packWARN(WARN_MISC), "State variable %s will be reinitialized",
+                                   PAD_COMPNAME_PV(lop->op_targ));
+                       }
+                   }
+               }
+               lop = lop->op_sibling;
+           }
+       }
+
        if (right && right->op_type == OP_SPLIT) {
            OP* tmpop = ((LISTOP*)right)->op_first;
            if (tmpop && (tmpop->op_type == OP_PUSHRE)) {
@@ -3942,20 +4018,18 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     cop->op_next = (OP*)cop;
 
     if (label) {
-       cop->cop_label = label;
+       CopLABEL_set(cop, label);
        PL_hints |= HINT_BLOCK_SCOPE;
     }
     cop->cop_seq = seq;
-    CopARYBASE_set(cop, CopARYBASE_get(PL_curcop));
+    /* 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.
+    */
     cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
-    if (specialCopIO(PL_curcop->cop_io))
-        cop->cop_io = PL_curcop->cop_io;
-    else
-        cop->cop_io = newSVsv(PL_curcop->cop_io) ;
-    cop->cop_hints = PL_curcop->cop_hints;
-    if (cop->cop_hints) {
+    cop->cop_hints_hash = PL_curcop->cop_hints_hash;
+    if (cop->cop_hints_hash) {
        HINTS_REFCNT_LOCK;
-       cop->cop_hints->refcounted_he_refcnt++;
+       cop->cop_hints_hash->refcounted_he_refcnt++;
        HINTS_REFCNT_UNLOCK;
     }
 
@@ -3973,10 +4047,13 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     CopSTASH_set(cop, PL_curstash);
 
     if (PERLDB_LINE && PL_curstash != PL_debstash) {
-       SV * const * const svp = av_fetch(CopFILEAVx(PL_curcop), (I32)CopLINE(cop), FALSE);
-       if (svp && *svp != &PL_sv_undef ) {
-           (void)SvIOK_on(*svp);
-           SvIV_set(*svp, PTR2IV(cop));
+       AV *av = CopFILEAVx(PL_curcop);
+       if (av) {
+           SV * const * const svp = av_fetch(av, (I32)CopLINE(cop), FALSE);
+           if (svp && *svp != &PL_sv_undef ) {
+               (void)SvIOK_on(*svp);
+               SvIV_set(*svp, PTR2IV(cop));
+           }
        }
     }
 
@@ -4458,21 +4535,16 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
            }
            sv = NULL;
        }
-       else if (sv->op_type == OP_THREADSV) { /* per-thread variable */
-           padoff = sv->op_targ;
-           if (PL_madskills)
-               madsv = sv;
-           else {
-               sv->op_targ = 0;
-               iterflags |= OPf_SPECIAL;
-               op_free(sv);
-           }
-           sv = NULL;
-       }
        else
            Perl_croak(aTHX_ "Can't use %s for loop variable", PL_op_desc[sv->op_type]);
-       if (padoff && strEQ(PAD_COMPNAME_PV(padoff), "$_"))
-           iterpflags |= OPpITER_DEF;
+       if (padoff) {
+           SV *const namesv = PAD_COMPNAME_SV(padoff);
+           STRLEN len;
+           const char *const name = SvPV_const(namesv, len);
+
+           if (len == 2 && name[0] == '$' && name[1] == '_')
+               iterpflags |= OPpITER_DEF;
+       }
     }
     else {
         const PADOFFSET offset = pad_findmy("$_");
@@ -4535,11 +4607,11 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
        LOOP *tmp;
        NewOp(1234,tmp,1,LOOP);
        Copy(loop,tmp,1,LISTOP);
-       FreeOp(loop);
+       S_op_destroy(aTHX_ (OP*)loop);
        loop = tmp;
     }
 #else
-    loop = PerlMemShared_realloc(loop, sizeof(LOOP));
+    loop = (LOOP*)PerlMemShared_realloc(loop, sizeof(LOOP));
 #endif
     loop->op_targ = padoff;
     wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont, 0);
@@ -4560,7 +4632,7 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label)
        if (label->op_type == OP_STUB && (label->op_flags & OPf_PARENS))
            o = newOP(type, OPf_SPECIAL);
        else {
-           o = newPVOP(type, 0, savepv(label->op_type == OP_CONST
+           o = newPVOP(type, 0, savesharedpv(label->op_type == OP_CONST
                                        ? SvPVx_nolen_const(((SVOP*)label)->op_sv)
                                        : ""));
        }
@@ -4775,7 +4847,7 @@ Perl_cv_undef(pTHX_ CV *cv)
        /* for XSUBs CvFILE point directly to static memory; __FILE__ */
        Safefree(CvFILE(cv));
     }
-    CvFILE(cv) = 0;
+    CvFILE(cv) = NULL;
 #endif
 
     if (!CvISXSUB(cv) && CvROOT(cv)) {
@@ -4829,9 +4901,9 @@ Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p,
            gv_efullname3(name = sv_newmortal(), gv, NULL);
        sv_setpv(msg, "Prototype mismatch:");
        if (name)
-           Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, (void*)name);
+           Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, SVfARG(name));
        if (SvPOK(cv))
-           Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (void*)cv);
+           Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", SVfARG(cv));
        else
            sv_catpvs(msg, ": none");
        sv_catpvs(msg, " vs ");
@@ -4839,7 +4911,7 @@ Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p,
            Perl_sv_catpvf(aTHX_ msg, "(%.*s)", (int) len, p);
        else
            sv_catpvs(msg, "none");
-       Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, (void*)msg);
+       Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, SVfARG(msg));
     }
 }
 
@@ -5250,7 +5322,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                else {
                    /* force display of errors found but not reported */
                    sv_catpv(ERRSV, not_safe);
-                   Perl_croak(aTHX_ "%"SVf, (void*)ERRSV);
+                   Perl_croak(aTHX_ "%"SVf, SVfARG(ERRSV));
                }
            }
        }
@@ -5262,6 +5334,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     if (CvLVALUE(cv)) {
        CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0,
                             mod(scalarseq(block), OP_LEAVESUBLV));
+       block->op_attached = 1;
     }
     else {
        /* This makes sub {}; work as expected.  */
@@ -5274,6 +5347,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 #endif
            block = newblock;
        }
+       else
+           block->op_attached = 1;
        CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block));
     }
     CvROOT(cv)->op_private |= OPpREFCOUNTED;
@@ -5326,7 +5401,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        else
            s = tname;
 
-       if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I')
+       if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I' && *s != 'U')
            goto done;
 
        if (strEQ(s, "BEGIN") && !PL_error_count) {
@@ -5354,6 +5429,15 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            av_store(PL_endav, 0, (SV*)cv);
            GvCV(gv) = 0;               /* cv has been hijacked */
        }
+       else if (strEQ(s, "UNITCHECK") && !PL_error_count) {
+           /* It's never too late to run a unitcheck block */
+           if (!PL_unitcheckav)
+               PL_unitcheckav = newAV();
+           DEBUG_x( dump_sub(gv) );
+           av_unshift(PL_unitcheckav, 1);
+           av_store(PL_unitcheckav, 0, (SV*)cv);
+           GvCV(gv) = 0;               /* cv has been hijacked */
+       }
        else if (strEQ(s, "CHECK") && !PL_error_count) {
            if (!PL_checkav)
                PL_checkav = newAV();
@@ -5428,6 +5512,7 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
     cv = newXS_flags(name, const_sv_xsub, file, "", XS_DYNAMIC_FILENAME);
     CvXSUBANY(cv).any_ptr = sv;
     CvCONST_on(cv);
+    Safefree(file);
 
 #ifdef USE_ITHREADS
     if (stash)
@@ -5633,7 +5718,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
                CopLINE_set(PL_curcop, PL_copline);
            Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
                        o ? "Format %"SVf" redefined"
-                       : "Format STDOUT redefined", (void*)cSVOPo->op_sv);
+                       : "Format STDOUT redefined", SVfARG(cSVOPo->op_sv));
            CopLINE_set(PL_curcop, oldline);
        }
        SvREFCNT_dec(cv);
@@ -5667,15 +5752,13 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
 OP *
 Perl_newANONLIST(pTHX_ OP *o)
 {
-    return newUNOP(OP_REFGEN, 0,
-       mod(list(convert(OP_ANONLIST, 0, o)), OP_REFGEN));
+    return convert(OP_ANONLIST, OPf_SPECIAL, o);
 }
 
 OP *
 Perl_newANONHASH(pTHX_ OP *o)
 {
-    return newUNOP(OP_REFGEN, 0,
-       mod(list(convert(OP_ANONHASH, 0, o)), OP_REFGEN));
+    return convert(OP_ANONHASH, OPf_SPECIAL, o);
 }
 
 OP *
@@ -5799,10 +5882,6 @@ Perl_newSVREF(pTHX_ OP *o)
        o->op_ppaddr = PL_ppaddr[OP_PADSV];
        return o;
     }
-    else if (o->op_type == OP_THREADSV && !(o->op_flags & OPpDONE_SVREF)) {
-       o->op_flags |= OPpDONE_SVREF;
-       return o;
-    }
     return newUNOP(OP_RV2SV, 0, scalar(o));
 }
 
@@ -5830,7 +5909,7 @@ Perl_ck_bitop(pTHX_ OP *o)
         (op) == OP_EQ   || (op) == OP_I_EQ || \
         (op) == OP_NE   || (op) == OP_I_NE || \
         (op) == OP_NCMP || (op) == OP_I_NCMP)
-    o->op_private = (U8)(PL_hints & HINT_PRIVATE_MASK);
+    o->op_private = (U8)(PL_hints & HINT_INTEGER);
     if (!(o->op_flags & OPf_STACKED) /* Not an assignment */
            && (o->op_type == OP_BIT_OR
             || o->op_type == OP_BIT_AND
@@ -6085,24 +6164,24 @@ Perl_ck_rvconst(pTHX_ register OP *o)
        /* Is it a constant from cv_const_sv()? */
        if (SvROK(kidsv) && SvREADONLY(kidsv)) {
            SV * const rsv = SvRV(kidsv);
-           const int svtype = SvTYPE(rsv);
+           const svtype type = SvTYPE(rsv);
             const char *badtype = NULL;
 
            switch (o->op_type) {
            case OP_RV2SV:
-               if (svtype > SVt_PVMG)
+               if (type > SVt_PVMG)
                    badtype = "a SCALAR";
                break;
            case OP_RV2AV:
-               if (svtype != SVt_PVAV)
+               if (type != SVt_PVAV)
                    badtype = "an ARRAY";
                break;
            case OP_RV2HV:
-               if (svtype != SVt_PVHV)
+               if (type != SVt_PVHV)
                    badtype = "a HASH";
                break;
            case OP_RV2CV:
-               if (svtype != SVt_PVCV)
+               if (type != SVt_PVCV)
                    badtype = "a CODE";
                break;
            }
@@ -6140,7 +6219,7 @@ Perl_ck_rvconst(pTHX_ register OP *o)
            if (badthing)
                Perl_croak(aTHX_
                           "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use",
-                          (void*)kidsv, badthing);
+                          SVfARG(kidsv), badthing);
        }
        /*
         * This is a little tricky.  We only want to add the symbol if we
@@ -6298,7 +6377,7 @@ Perl_ck_fun(pTHX_ OP *o)
                    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
                        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
                            "Array @%"SVf" missing the @ in argument %"IVdf" of %s()",
-                           (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
+                           SVfARG(((SVOP*)kid)->op_sv), (IV)numargs, PL_op_desc[type]);
 #ifdef PERL_MAD
                    op_getmad(kid,newop,'K');
 #else
@@ -6321,7 +6400,7 @@ Perl_ck_fun(pTHX_ OP *o)
                    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
                        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
                            "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()",
-                           (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
+                           SVfARG(((SVOP*)kid)->op_sv), (IV)numargs, PL_op_desc[type]);
 #ifdef PERL_MAD
                    op_getmad(kid,newop,'K');
 #else
@@ -6384,13 +6463,9 @@ Perl_ck_fun(pTHX_ OP *o)
                             */
                            priv = OPpDEREF;
                            if (kid->op_type == OP_PADSV) {
-                               name = PAD_COMPNAME_PV(kid->op_targ);
-                               /* SvCUR of a pad namesv can't be trusted
-                                * (see PL_generation), so calc its length
-                                * manually */
-                               if (name)
-                                   len = strlen(name);
-
+                               SV *const namesv
+                                   = PAD_COMPNAME_SV(kid->op_targ);
+                               name = SvPV_const(namesv, len);
                            }
                            else if (kid->op_type == OP_RV2SV
                                     && kUNOP->op_first->op_type == OP_GV)
@@ -6730,16 +6805,6 @@ Perl_ck_listiob(pTHX_ OP *o)
 }
 
 OP *
-Perl_ck_say(pTHX_ OP *o)
-{
-    o = ck_listiob(o);
-    o->op_type = OP_PRINT;
-    cLISTOPo->op_last = cLISTOPo->op_last->op_sibling
-       = newSVOP(OP_CONST, 0, newSVpvs("\n"));
-    return o;
-}
-
-OP *
 Perl_ck_smartmatch(pTHX_ OP *o)
 {
     dVAR;
@@ -7289,7 +7354,7 @@ Perl_ck_subr(pTHX_ OP *o)
     int optional = 0;
     I32 arg = 0;
     I32 contextclass = 0;
-    char *e = NULL;
+    const char *e = NULL;
     bool delete_op = 0;
 
     o->op_private |= OPpENTERSUB_HASTARG;
@@ -7312,13 +7377,20 @@ Perl_ck_subr(pTHX_ OP *o)
                    proto_end = proto + len;
                }
                if (CvASSERTION(cv)) {
-                   if (PL_hints & HINT_ASSERTING) {
+                   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 (!(PL_hints & HINT_ASSERTIONSSEEN) && ckWARN(WARN_ASSERTIONS)) {
+                       if (!(asserthints & HINT_ASSERTIONSSEEN) && ckWARN(WARN_ASSERTIONS)) {
                            Perl_warner(aTHX_ packWARN(WARN_ASSERTIONS),
                                        "Impossible to activate assertion call");
                        }
@@ -7354,6 +7426,10 @@ Perl_ck_subr(pTHX_ OP *o)
                optional = 1;
                proto++;
                continue;
+           case '_':
+               /* _ must be at the end */
+               if (proto[1] && proto[1] != ';')
+                   goto oops;
            case '$':
                proto++;
                arg++;
@@ -7459,8 +7535,7 @@ Perl_ck_subr(pTHX_ OP *o)
                    if (o3->op_type == OP_RV2SV ||
                        o3->op_type == OP_PADSV ||
                        o3->op_type == OP_HELEM ||
-                       o3->op_type == OP_AELEM ||
-                       o3->op_type == OP_THREADSV)
+                       o3->op_type == OP_AELEM)
                         goto wrapref;
                    if (!contextclass)
                        bad_type(arg, "scalar", gv_ename(namegv), o3);
@@ -7504,7 +7579,7 @@ Perl_ck_subr(pTHX_ OP *o)
            default:
              oops:
                Perl_croak(aTHX_ "Malformed prototype for %s: %"SVf,
-                          gv_ename(namegv), (void*)cv);
+                          gv_ename(namegv), SVfARG(cv));
            }
        }
        else
@@ -7513,8 +7588,14 @@ Perl_ck_subr(pTHX_ OP *o)
        prev = o2;
        o2 = o2->op_sibling;
     } /* while */
+    if (o2 == cvop && proto && *proto == '_') {
+       /* generate an access to $_ */
+       o2 = newDEFSVOP();
+       o2->op_sibling = prev->op_sibling;
+       prev->op_sibling = o2; /* instead of cvop */
+    }
     if (proto && !optional && proto_end > proto &&
-       (*proto != '@' && *proto != '%' && *proto != ';'))
+       (*proto != '@' && *proto != '%' && *proto != ';' && *proto != '_'))
        return too_few_arguments(o, gv_ename(namegv));
     if(delete_op) {
 #ifdef PERL_MAD
@@ -7775,7 +7856,7 @@ Perl_peep(pTHX_ register OP *o)
                    gv_efullname3(sv, gv, NULL);
                    Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
                                "%"SVf"() called too early to check prototype",
-                               (void*)sv);
+                               SVfARG(sv));
                }
            }
            else if (o->op_next->op_type == OP_READLINE