Given that @optype and @specialsv_name are hard coded tables, it seems
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index 524777d..40b415d 100644 (file)
--- a/op.c
+++ b/op.c
@@ -186,7 +186,6 @@ Perl_pending_Slabs_to_ro(pTHX) {
        read only. Also, do it ahead of the loop in case the warn triggers,
        and a warn handler has an eval */
 
-    free(PL_slabs);
     PL_slabs = NULL;
     PL_slab_count = 0;
 
@@ -194,13 +193,15 @@ Perl_pending_Slabs_to_ro(pTHX) {
     PL_OpSpace = 0;
 
     while (count--) {
-       const void *start = slabs[count];
+       void *const start = slabs[count];
        const size_t size = PERL_SLAB_SIZE* sizeof(I32*);
        if(mprotect(start, size, PROT_READ)) {
            Perl_warn(aTHX_ "mprotect for %p %lu failed with %d",
                      start, (unsigned long) size, errno);
        }
     }
+
+    free(slabs);
 }
 
 STATIC void
@@ -216,6 +217,24 @@ S_Slab_to_rw(pTHX_ void *op)
                  slab, (unsigned long) PERL_SLAB_SIZE*sizeof(I32*), errno);
     }
 }
+
+OP *
+Perl_op_refcnt_inc(pTHX_ OP *o)
+{
+    if(o) {
+       Slab_to_rw(o);
+       ++o->op_targ;
+    }
+    return o;
+
+}
+
+PADOFFSET
+Perl_op_refcnt_dec(pTHX_ OP *o)
+{
+    Slab_to_rw(o);
+    return --o->op_targ;
+}
 #else
 #  define Slab_to_rw(op)
 #endif
@@ -249,17 +268,12 @@ Perl_Slab_Free(pTHX_ void *op)
                    PL_slabs[count] = PL_slabs[--PL_slab_count];
                    /* Could realloc smaller at this point, but probably not
                       worth it.  */
-                   goto gotcha;
+                   if(munmap(slab, PERL_SLAB_SIZE*sizeof(I32*))) {
+                       perror("munmap failed");
+                       abort();
+                   }
+                   break;
                }
-               
-           }
-           Perl_croak(aTHX_
-                      "panic: Couldn't find slab at %p (%lu allocated)",
-                      slab, (unsigned long) PL_slabs);
-       gotcha:
-           if(munmap(slab, PERL_SLAB_SIZE*sizeof(I32*))) {
-               perror("munmap failed");
-               abort();
            }
        }
 #else
@@ -394,6 +408,11 @@ S_op_destroy(pTHX_ OP *o)
     FreeOp(o);
 }
 
+#ifdef USE_ITHREADS
+#  define forget_pmop(a,b)     S_forget_pmop(aTHX_ a,b)
+#else
+#  define forget_pmop(a,b)     S_forget_pmop(aTHX_ a)
+#endif
 
 /* Destructor */
 
@@ -422,9 +441,6 @@ Perl_op_free(pTHX_ OP *o)
        case OP_LEAVEWRITE:
            {
            PADOFFSET refcnt;
-#ifdef PERL_DEBUG_READONLY_OPS
-           Slab_to_rw(o);
-#endif
            OP_REFCNT_LOCK;
            refcnt = OpREFCNT_dec(o);
            OP_REFCNT_UNLOCK;
@@ -451,12 +467,13 @@ Perl_op_free(pTHX_ OP *o)
     if (type == OP_NULL)
        type = (OPCODE)o->op_targ;
 
+#ifdef PERL_DEBUG_READONLY_OPS
+    Slab_to_rw(o);
+#endif
+
     /* 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) {
-#ifdef PERL_DEBUG_READONLY_OPS
-       Slab_to_rw(o);
-#endif
        cop_free((COP*)o);
     }
 
@@ -569,24 +586,24 @@ Perl_op_clear(pTHX_ OP *o)
        }
        break;
     case OP_SUBST:
-       op_free(cPMOPo->op_pmreplroot);
+       op_free(cPMOPo->op_pmreplrootu.op_pmreplroot);
        goto clear_pmop;
     case OP_PUSHRE:
 #ifdef USE_ITHREADS
-        if (INT2PTR(PADOFFSET, cPMOPo->op_pmreplroot)) {
+        if (cPMOPo->op_pmreplrootu.op_pmtargetoff) {
            /* No GvIN_PAD_off here, because other references may still
             * exist on the pad */
-           pad_swipe(INT2PTR(PADOFFSET, cPMOPo->op_pmreplroot), TRUE);
+           pad_swipe(cPMOPo->op_pmreplrootu.op_pmtargetoff, TRUE);
        }
 #else
-       SvREFCNT_dec((SV*)cPMOPo->op_pmreplroot);
+       SvREFCNT_dec((SV*)cPMOPo->op_pmreplrootu.op_pmtargetgv);
 #endif
        /* FALL THROUGH */
     case OP_MATCH:
     case OP_QR:
 clear_pmop:
        forget_pmop(cPMOPo, 1);
-       cPMOPo->op_pmreplroot = NULL;
+       cPMOPo->op_pmreplrootu.op_pmreplroot = NULL;
         /* we use the "SAFE" version of the PM_ macros here
          * since sv_clean_all might release some PMOPs
          * after PL_regex_padav has been cleared
@@ -625,7 +642,11 @@ S_cop_free(pTHX_ COP* cop)
 }
 
 STATIC void
-S_forget_pmop(pTHX_ PMOP *const o, U32 flags)
+S_forget_pmop(pTHX_ PMOP *const o
+#ifdef USE_ITHREADS
+             , U32 flags
+#endif
+             )
 {
     HV * const pmstash = PmopSTASH(o);
     if (pmstash && !SvIS_FREED(pmstash)) {
@@ -652,8 +673,12 @@ S_forget_pmop(pTHX_ PMOP *const o, U32 flags)
            }
        }
     }
+    if (PL_curpm == o) 
+       PL_curpm = NULL;
+#ifdef USE_ITHREADS
     if (flags)
        PmopSTASH_free(o);
+#endif
 }
 
 STATIC void
@@ -757,8 +782,8 @@ S_scalarboolean(pTHX_ OP *o)
        if (ckWARN(WARN_SYNTAX)) {
            const line_t oldline = CopLINE(PL_curcop);
 
-           if (PL_copline != NOLINE)
-               CopLINE_set(PL_curcop, PL_copline);
+           if (PL_parser && PL_parser->copline != NOLINE)
+               CopLINE_set(PL_curcop, PL_parser->copline);
            Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Found = in conditional, should be ==");
            CopLINE_set(PL_curcop, oldline);
        }
@@ -793,7 +818,7 @@ Perl_scalar(pTHX_ OP *o)
        break;
     case OP_SPLIT:
        if ((kid = cLISTOPo->op_first) && kid->op_type == OP_PUSHRE) {
-           if (!kPMOP->op_pmreplroot)
+           if (!kPMOP->op_pmreplrootu.op_pmreplroot)
                deprecate_old("implicit split to @_");
        }
        /* FALL THROUGH */
@@ -1088,7 +1113,7 @@ Perl_scalarvoid(pTHX_ OP *o)
        return scalar(o);
     case OP_SPLIT:
        if ((kid = cLISTOPo->op_first) && kid->op_type == OP_PUSHRE) {
-           if (!kPMOP->op_pmreplroot)
+           if (!kPMOP->op_pmreplrootu.op_pmreplroot)
                deprecate_old("implicit split to @_");
        }
        break;
@@ -1275,7 +1300,7 @@ Perl_mod(pTHX_ OP *o, I32 type)
            Perl_croak(aTHX_ "That use of $[ is unsupported");
        break;
     case OP_STUB:
-       if (o->op_flags & OPf_PARENS || PL_madskills)
+       if ((o->op_flags & OPf_PARENS) || PL_madskills)
            break;
        goto nomod;
     case OP_ENTERSUB:
@@ -1624,6 +1649,7 @@ S_scalar_mod_type(const OP *o, I32 type)
     case OP_RECV:
     case OP_ANDASSIGN:
     case OP_ORASSIGN:
+    case OP_DORASSIGN:
        return TRUE;
     default:
        return FALSE;
@@ -1792,7 +1818,6 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
 
     /* fake up C<use attributes $pkg,$rv,@attrs> */
     ENTER;             /* need to protect against side-effects of 'use' */
-    SAVEINT(PL_expect);
     stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no;
 
 #define ATTRSMODULE "attributes"
@@ -2235,10 +2260,11 @@ Perl_localize(pTHX_ OP *o, I32 lex)
        NOOP;
 #endif
     else {
-       if ( PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ','
+       if ( PL_parser->bufptr > PL_parser->oldbufptr
+           && PL_parser->bufptr[-1] == ','
            && ckWARN(WARN_PARENTHESIS))
        {
-           char *s = PL_bufptr;
+           char *s = PL_parser->bufptr;
            bool sigil = FALSE;
 
            /* some heuristics to detect a potential error */
@@ -2792,7 +2818,7 @@ Perl_mad_free(pTHX_ MADPROP* mp)
        return;
     if (mp->mad_next)
        mad_free(mp->mad_next);
-/*    if (PL_lex_state != LEX_NOTPARSING && mp->mad_vlen)
+/*    if (PL_parser && PL_parser->lex_state != LEX_NOTPARSING && mp->mad_vlen)
        PerlIO_printf(PerlIO_stderr(), "DESTROYING '%c'=<%s>\n", mp->mad_key & 255, mp->mad_val); */
     switch (mp->mad_type) {
     case MAD_NULL:
@@ -3411,8 +3437,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
        }
         if (DO_UTF8(pat))
            pm_flags |= RXf_UTF8;
-       /* FIXME - can we make this function take const char * args?  */
-       PM_SETRE(pm, CALLREGCOMP((char*)p, (char*)p + plen, pm_flags));
+       PM_SETRE(pm, CALLREGCOMP(pat, pm_flags));
 
 #ifdef PERL_MAD
        op_getmad(expr,(OP*)pm,'e');
@@ -3524,7 +3549,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
            rcop->op_next = LINKLIST(repl);
            repl->op_next = (OP*)rcop;
 
-           pm->op_pmreplroot = scalar((OP*)rcop);
+           pm->op_pmreplrootu.op_pmreplroot = scalar((OP*)rcop);
            assert(!(pm->op_pmflags & PMf_ONCE));
            pm->op_pmstashstartu.op_pmreplstart = LINKLIST(rcop);
            rcop->op_next = 0;
@@ -3624,11 +3649,12 @@ Perl_package(pTHX_ OP *o)
     save_item(PL_curstname);
 
     PL_curstash = gv_stashsv(sv, GV_ADD);
+
     sv_setsv(PL_curstname, sv);
 
     PL_hints |= HINT_BLOCK_SCOPE;
-    PL_copline = NOLINE;
-    PL_expect = XSTATE;
+    PL_parser->copline = NOLINE;
+    PL_parser->expect = XSTATE;
 
 #ifndef PERL_MAD
     op_free(o);
@@ -3752,8 +3778,8 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
      */
 
     PL_hints |= HINT_BLOCK_SCOPE;
-    PL_copline = NOLINE;
-    PL_expect = XSTATE;
+    PL_parser->copline = NOLINE;
+    PL_parser->expect = XSTATE;
     PL_cop_seqmax++; /* Purely for B::*'s benefit */
 
 #ifdef PERL_MAD
@@ -3831,17 +3857,19 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args)
            sv = va_arg(*args, SV*);
        }
     }
-    {
-       const line_t ocopline = PL_copline;
-       COP * const ocurcop = PL_curcop;
-       const int oexpect = PL_expect;
 
-       utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
-               veop, modname, imop);
-       PL_expect = oexpect;
-       PL_copline = ocopline;
-       PL_curcop = ocurcop;
-    }
+    /* utilize() fakes up a BEGIN { require ..; import ... }, so make sure
+     * that it has a PL_parser to play with while doing that, and also
+     * that it doesn't mess with any existing parser, by creating a tmp
+     * new parser with lex_start(). This won't actually be used for much,
+     * since pp_require() will create another parser for the real work. */
+
+    ENTER;
+    SAVEVPTR(PL_curcop);
+    lex_start(NULL);
+    utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
+           veop, modname, imop);
+    LEAVE;
 }
 
 OP *
@@ -4007,19 +4035,24 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                            break;
                    }
                    else if (curop->op_type == OP_PUSHRE) {
-                       if (((PMOP*)curop)->op_pmreplroot) {
 #ifdef USE_ITHREADS
-                           GV *gv = (GV*)PAD_SVl(INT2PTR(PADOFFSET,
-                                       ((PMOP*)curop)->op_pmreplroot));
-#else
-                           GV *gv = (GV*)((PMOP*)curop)->op_pmreplroot;
-#endif
+                       if (((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff) {
+                           GV *const gv = (GV*)PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff);
                            if (gv == PL_defgv
                                || (int)GvASSIGN_GENERATION(gv) == PL_generation)
                                break;
                            GvASSIGN_GENERATION_set(gv, PL_generation);
+                       }
+#else
+                       GV *const gv
+                           = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv;
+                       if (gv) {
+                           if (gv == PL_defgv
+                               || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+                               break;
                            GvASSIGN_GENERATION_set(gv, PL_generation);
                        }
+#endif
                    }
                    else
                        break;
@@ -4030,44 +4063,6 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                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;
-           }
-       }
-       else if (((left->op_private & (OPpLVAL_INTRO | OPpPAD_STATE))
-                   == (OPpLVAL_INTRO | OPpPAD_STATE))
-               && (   left->op_type == OP_PADSV
-                   || left->op_type == OP_PADAV
-                   || left->op_type == OP_PADHV
-                   || left->op_type == OP_PADANY))
-       {
-           o->op_private |= OPpASSIGN_STATE;
-           /* hijacking PADSTALE for uninitialized state variables */
-           SvPADSTALE_on(PAD_SVl(left->op_targ));
-       }
-
        if (right && right->op_type == OP_SPLIT) {
            OP* tmpop = ((LISTOP*)right)->op_first;
            if (tmpop && (tmpop->op_type == OP_PUSHRE)) {
@@ -4077,12 +4072,20 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                    !(o->op_private & OPpASSIGN_COMMON) )
                {
                    tmpop = ((UNOP*)left)->op_first;
-                   if (tmpop->op_type == OP_GV && !pm->op_pmreplroot) {
+                   if (tmpop->op_type == OP_GV
+#ifdef USE_ITHREADS
+                       && !pm->op_pmreplrootu.op_pmtargetoff
+#else
+                       && !pm->op_pmreplrootu.op_pmtargetgv
+#endif
+                       ) {
 #ifdef USE_ITHREADS
-                       pm->op_pmreplroot = INT2PTR(OP*, cPADOPx(tmpop)->op_padix);
+                       pm->op_pmreplrootu.op_pmtargetoff
+                           = cPADOPx(tmpop)->op_padix;
                        cPADOPx(tmpop)->op_padix = 0;   /* steal it */
 #else
-                       pm->op_pmreplroot = (OP*)cSVOPx(tmpop)->op_sv;
+                       pm->op_pmreplrootu.op_pmtargetgv
+                           = (GV*)cSVOPx(tmpop)->op_sv;
                        cSVOPx(tmpop)->op_sv = NULL;    /* steal it */
 #endif
                        pm->op_pmflags |= PMf_ONCE;
@@ -4175,11 +4178,12 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
        HINTS_REFCNT_UNLOCK;
     }
 
-    if (PL_copline == NOLINE)
+    if (PL_parser && PL_parser->copline == NOLINE)
         CopLINE_set(cop, CopLINE(PL_curcop));
     else {
-       CopLINE_set(cop, PL_copline);
-        PL_copline = NOLINE;
+       CopLINE_set(cop, PL_parser->copline);
+       if (PL_parser)
+           PL_parser->copline = NOLINE;
     }
 #ifdef USE_ITHREADS
     CopFILE_set(cop, CopFILE(PL_curcop));      /* XXX share in a pvtable? */
@@ -4325,7 +4329,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
        }
        if (warnop) {
            const line_t oldline = CopLINE(PL_curcop);
-           CopLINE_set(PL_curcop, PL_copline);
+           CopLINE_set(PL_curcop, PL_parser->copline);
            Perl_warner(aTHX_ packWARN(WARN_MISC),
                 "Value of %s%s can be \"0\"; test with defined()",
                 PL_op_desc[warnop],
@@ -4594,7 +4598,7 @@ whileline, OP *expr, OP *block, OP *cont, I32 has_my)
     redo = LINKLIST(listop);
 
     if (expr) {
-       PL_copline = (line_t)whileline;
+       PL_parser->copline = (line_t)whileline;
        scalar(listop);
        o = new_logop(OP_AND, 0, &expr, &listop);
        if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) {
@@ -4753,7 +4757,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
     wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont, 0);
     if (madsv)
        op_getmad(madsv, (OP*)loop, 'v');
-    PL_copline = forline;
+    PL_parser->copline = forline;
     return newSTATEOP(0, label, wop);
 }
 
@@ -4769,7 +4773,7 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label)
            o = newOP(type, OPf_SPECIAL);
        else {
            o = newPVOP(type, 0, savesharedpv(label->op_type == OP_CONST
-                                       ? SvPVx_nolen_const(((SVOP*)label)->op_sv)
+                                       ? SvPV_nolen_const(((SVOP*)label)->op_sv)
                                        : ""));
        }
 #ifdef PERL_MAD
@@ -5206,11 +5210,11 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        = (block || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS)
           || PL_madskills)
        ? GV_ADDMULTI : GV_ADDMULTI | GV_NOINIT;
-    const char * const name = o ? SvPVx_nolen_const(cSVOPo->op_sv) : NULL;
+    const char * const name = o ? SvPV_nolen_const(cSVOPo->op_sv) : NULL;
 
     if (proto) {
        assert(proto->op_type == OP_CONST);
-       ps = SvPVx_const(((SVOP*)proto)->op_sv, ps_len);
+       ps = SvPV_const(((SVOP*)proto)->op_sv, ps_len);
     }
     else
        ps = NULL;
@@ -5253,9 +5257,9 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            sv_setpvn((SV*)gv, ps, ps_len);
        else
            sv_setiv((SV*)gv, -1);
+
        SvREFCNT_dec(PL_compcv);
        cv = PL_compcv = NULL;
-       PL_sub_generation++;
        goto done;
     }
 
@@ -5317,8 +5321,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                        && (!const_sv || sv_cmp(cv_const_sv(cv), const_sv))))
                {
                    const line_t oldline = CopLINE(PL_curcop);
-                   if (PL_copline != NOLINE)
-                       CopLINE_set(PL_curcop, PL_copline);
+                   if (PL_parser && PL_parser->copline != NOLINE)
+                       CopLINE_set(PL_curcop, PL_parser->copline);
                    Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
                        CvCONST(cv) ? "Constant subroutine %s redefined"
                                    : "Subroutine %s redefined", name);
@@ -5349,7 +5353,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            GvCV(gv) = NULL;
            cv = newCONSTSUB(NULL, name, const_sv);
        }
-       PL_sub_generation++;
+        mro_method_changed_in( /* sub Foo::Bar () { 123 } */
+            (CvGV(cv) && GvSTASH(CvGV(cv)))
+                ? GvSTASH(CvGV(cv))
+                : CvSTASH(cv)
+                    ? CvSTASH(cv)
+                    : PL_curstash
+        );
        if (PL_madskills)
            goto install_block;
        op_free(block);
@@ -5432,7 +5442,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                }
            }
            GvCVGEN(gv) = 0;
-           PL_sub_generation++;
+            mro_method_changed_in(GvSTASH(gv)); /* sub Foo::bar { (shift)+1 } */
        }
     }
     CvGV(cv) = gv;
@@ -5532,7 +5542,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     }
 
   done:
-    PL_copline = NOLINE;
+    if (PL_parser)
+       PL_parser->copline = NOLINE;
     LEAVE_SCOPE(floor);
     return cv;
 }
@@ -5628,7 +5639,7 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
     ENTER;
 
     SAVECOPLINE(PL_curcop);
-    CopLINE_set(PL_curcop, PL_copline);
+    CopLINE_set(PL_curcop, PL_parser ? PL_parser->copline : NOLINE);
 
     SAVEHINTS();
     PL_hints &= ~HINT_BLOCK_SCOPE;
@@ -5741,8 +5752,8 @@ Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename)
                        const char *redefined_name = HvNAME_get(stash);
                        if ( strEQ(redefined_name,"autouse") ) {
                            const line_t oldline = CopLINE(PL_curcop);
-                           if (PL_copline != NOLINE)
-                               CopLINE_set(PL_curcop, PL_copline);
+                           if (PL_parser && PL_parser->copline != NOLINE)
+                               CopLINE_set(PL_curcop, PL_parser->copline);
                            Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
                                        CvCONST(cv) ? "Constant subroutine %s redefined"
                                                    : "Subroutine %s redefined"
@@ -5764,7 +5775,7 @@ Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename)
        if (name) {
            GvCV(gv) = cv;
            GvCVGEN(gv) = 0;
-           PL_sub_generation++;
+            mro_method_changed_in(GvSTASH(gv)); /* newXS */
        }
     }
     CvGV(cv) = gv;
@@ -5808,8 +5819,8 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
     if ((cv = GvFORM(gv))) {
        if (ckWARN(WARN_REDEFINE)) {
            const line_t oldline = CopLINE(PL_curcop);
-           if (PL_copline != NOLINE)
-               CopLINE_set(PL_curcop, PL_copline);
+           if (PL_parser && PL_parser->copline != NOLINE)
+               CopLINE_set(PL_curcop, PL_parser->copline);
            Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
                        o ? "Format %"SVf" redefined"
                        : "Format STDOUT redefined", SVfARG(cSVOPo->op_sv));
@@ -5836,7 +5847,8 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
 #else
     op_free(o);
 #endif
-    PL_copline = NOLINE;
+    if (PL_parser)
+       PL_parser->copline = NOLINE;
     LEAVE_SCOPE(floor);
 #ifdef PERL_MAD
     return pegop;
@@ -6977,16 +6989,6 @@ Perl_ck_sassign(pTHX_ OP *o)
            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))) {
-           o->op_private |= OPpASSIGN_STATE;
-           /* hijacking PADSTALE for uninitialized state variables */
-           SvPADSTALE_on(PAD_SVl(kkid->op_targ));
-       }
-    }
     return o;
 }
 
@@ -7882,7 +7884,7 @@ Perl_peep(pTHX_ register OP *o)
            if (o->op_next && o->op_next->op_type == OP_STRINGIFY) {
                if (o->op_next->op_private & OPpTARGET_MY) {
                    if (o->op_flags & OPf_STACKED) /* chained concats */
-                       goto ignore_optimization;
+                       break; /* ignore_optimization */
                    else {
                        /* assert(PL_opargs[o->op_type] & OA_TARGLEX); */
                        o->op_targ = o->op_next->op_targ;
@@ -7892,7 +7894,6 @@ Perl_peep(pTHX_ register OP *o)
                }
                op_null(o->op_next);
            }
-         ignore_optimization:
            break;
        case OP_STUB:
            if ((o->op_flags & OPf_WANT) != OPf_WANT_LIST) {