This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
op_class_sv removed for threaded perls op_class_targ removed for non-threaded perls
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 07b9959..d44a7ea 100644 (file)
--- a/op.c
+++ b/op.c
@@ -862,6 +862,16 @@ Perl_op_clear(pTHX_ OP *o)
             o->op_targ = 0;
         }
 #endif
+    case OP_METHOD:
+#ifdef USE_ITHREADS
+       if (cMETHOPx(o)->op_class_targ) {
+           pad_swipe(cMETHOPx(o)->op_class_targ, 1);
+           cMETHOPx(o)->op_class_targ = 0;
+       }
+#else
+       SvREFCNT_dec(cMETHOPx(o)->op_class_sv);
+       cMETHOPx(o)->op_class_sv = NULL;
+#endif
         break;
     case OP_CONST:
     case OP_HINTSEVAL:
@@ -1547,7 +1557,10 @@ Perl_scalar(pTHX_ OP *o)
     do_kids:
        while (kid) {
            OP *sib = OP_SIBLING(kid);
-           if (sib && kid->op_type != OP_LEAVEWHEN)
+           if (sib && kid->op_type != OP_LEAVEWHEN
+            && (  OP_HAS_SIBLING(sib) || sib->op_type != OP_NULL
+               || (  sib->op_targ != OP_NEXTSTATE
+                  && sib->op_targ != OP_DBSTATE  )))
                scalarvoid(kid);
            else
                scalar(kid);
@@ -2422,6 +2435,22 @@ such as C<$$x = 5> which might have to vivify a reference in C<$x>.
 =cut
 */
 
+static void
+S_mark_padname_lvalue(pTHX_ PADNAME *pn)
+{
+    CV *cv = PL_compcv;
+    PadnameLVALUE_on(pn);
+    while (PadnameOUTER(pn) && PARENT_PAD_INDEX(pn)) {
+       cv = CvOUTSIDE(cv);
+       assert(cv);
+       assert(CvPADLIST(cv));
+       pn =
+          PadlistNAMESARRAY(CvPADLIST(cv))[PARENT_PAD_INDEX(pn)];
+       assert(PadnameLEN(pn));
+       PadnameLVALUE_on(pn);
+    }
+}
+
 static bool
 S_vivifies(const OPCODE type)
 {
@@ -2792,6 +2821,10 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
        if (!type) /* local() */
            Perl_croak(aTHX_ "Can't localize lexical variable %"SVf,
                 PAD_COMPNAME_SV(o->op_targ));
+       if (!(o->op_private & OPpLVAL_INTRO)
+        || (  type != OP_SASSIGN && type != OP_AASSIGN
+           && PadnameIsSTATE(PAD_COMPNAME_SV(o->op_targ))  ))
+           S_mark_padname_lvalue(aTHX_ PAD_COMPNAME_SV(o->op_targ));
        break;
 
     case OP_PUSHMARK:
@@ -3686,9 +3719,8 @@ Perl_block_start(pTHX_ int full)
 {
     const int retval = PL_savestack_ix;
 
-    PL_compiling.cop_seq = PL_cop_seqmax++;
-    if (PL_cop_seqmax == PERL_PADSEQ_INTRO) /* not a legal value */
-       PL_cop_seqmax++;
+    PL_compiling.cop_seq = PL_cop_seqmax;
+    COP_SEQMAX_INC;
     pad_block_start(full);
     SAVEHINTS();
     PL_hints &= ~HINT_BLOCK_SCOPE;
@@ -3720,6 +3752,14 @@ Perl_block_end(pTHX_ I32 floor, OP *seq)
     OP* retval = scalarseq(seq);
     OP *o;
 
+    /* XXX Is the null PL_parser check necessary here? */
+    assert(PL_parser); /* Let’s find out under debugging builds.  */
+    if (PL_parser && PL_parser->parsed_sub) {
+       o = newSTATEOP(0, NULL, NULL);
+       op_null(o);
+       retval = op_append_elem(OP_LINESEQ, retval, o);
+    }
+
     CALL_BLOCK_HOOKS(bhk_pre_end, &retval);
 
     LEAVE_SCOPE(floor);
@@ -4119,7 +4159,7 @@ S_fold_constants(pTHX_ OP *o)
     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. */
+       currently compiling COP, but that IN_PERL_RUNTIME is true. */
     assert(IN_PERL_RUNTIME);
     PL_warnhook = PERL_WARNHOOK_FATAL;
     PL_diehook  = NULL;
@@ -4638,6 +4678,11 @@ S_newMETHOP_internal(pTHX_ I32 type, I32 flags, OP* dynamic_meth, SV* const_meth
         methop->op_flags = (U8)(flags | OPf_KIDS);
         methop->op_u.op_first = dynamic_meth;
         methop->op_private = (U8)(1 | (flags >> 8));
+
+#ifdef PERL_OP_PARENT
+        if (!OP_HAS_SIBLING(dynamic_meth))
+            dynamic_meth->op_sibling = (OP*)methop;
+#endif
     }
     else {
         assert(const_meth);
@@ -4647,6 +4692,11 @@ S_newMETHOP_internal(pTHX_ I32 type, I32 flags, OP* dynamic_meth, SV* const_meth
         methop->op_next = (OP*)methop;
     }
 
+#ifdef USE_ITHREADS
+    methop->op_class_targ = 0;
+#else
+    methop->op_class_sv = NULL;
+#endif
     CHANGE_TYPE(methop, type);
     methop = (METHOP*) CHECKOP(type, methop);
 
@@ -5164,6 +5214,21 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags)
     return CHECKOP(type, pmop);
 }
 
+static void
+S_set_haseval(pTHX)
+{
+    PADOFFSET i = 1;
+    PL_cv_has_eval = 1;
+    /* Any pad names in scope are potentially lvalues.  */
+    for (; i < PadnamelistMAXNAMED(PL_comppad_name); i++) {
+       PADNAME *pn = PAD_COMPNAME_SV(i);
+       if (!pn || !PadnameLEN(pn))
+           continue;
+       if (PadnameOUTER(pn) || PadnameIN_SCOPE(pn, PL_cop_seqmax))
+           S_mark_padname_lvalue(aTHX_ pn);
+    }
+}
+
 /* Given some sort of match op o, and an expression expr containing a
  * pattern, either compile expr into a regex and attach it to o (if it's
  * constant), or convert expr into a runtime regcomp op sequence (if it's
@@ -5456,7 +5521,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor)
        rcop->op_targ = cv_targ;
 
        /* /$x/ may cause an eval, since $x might be qr/(?{..})/  */
-       if (PL_hints & HINT_RE_EVAL) PL_cv_has_eval = 1;
+       if (PL_hints & HINT_RE_EVAL)
+           S_set_haseval(aTHX);
 
        /* establish postfix order */
        if (expr->op_type == OP_REGCRESET || expr->op_type == OP_REGCMAYBE) {
@@ -5853,10 +5919,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
 
     PL_hints |= HINT_BLOCK_SCOPE;
     PL_parser->copline = NOLINE;
-    PL_cop_seqmax++; /* Purely for B::*'s benefit */
-    if (PL_cop_seqmax == PERL_PADSEQ_INTRO) /* not a legal value */
-       PL_cop_seqmax++;
-
+    COP_SEQMAX_INC; /* Purely for B::*'s benefit */
 }
 
 /*
@@ -6066,7 +6129,7 @@ S_assignment_type(pTHX_ const OP *o)
 }
 
 /*
-  Helper function for newASSIGNOP to detection commonality between the
+  Helper function for newASSIGNOP to detect commonality between the
   lhs and the rhs.  (It is actually called very indirectly.  newASSIGNOP
   flags the op and the peephole optimizer calls this helper function
   if the flag is set.)  Marks all variables with PL_generation.  If it
@@ -6442,6 +6505,8 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o)
     const U32 utf8 = flags & SVf_UTF8;
     COP *cop;
 
+    PL_parser->parsed_sub = 0;
+
     flags &= ~SVf_UTF8;
 
     NewOp(1101, cop, 1, COP);
@@ -7673,51 +7738,38 @@ Perl_cv_const_sv_or_av(const CV * const cv)
 }
 
 /* op_const_sv:  examine an optree to determine whether it's in-lineable.
- * Can be called in 3 ways:
+ * Can be called in 2 ways:
  *
- * !cv
+ * !allow_lex
  *     look for a single OP_CONST with attached value: return the value
  *
- * cv && CvCLONE(cv) && !CvCONST(cv)
+ * allow_lex && !CvCONST(cv);
  *
  *     examine the clone prototype, and if contains only a single
- *     OP_CONST referencing a pad const, or a single PADSV referencing
- *     an outer lexical, return a non-zero value to indicate the CV is
- *     a candidate for "constizing" at clone time
- *
- * cv && CvCONST(cv)
- *
- *     We have just cloned an anon prototype that was marked as a const
- *     candidate. Try to grab the current value, and in the case of
- *     PADSV, ignore it if it has multiple references. In this case we
- *     return a newly created *copy* of the value.
+ *     OP_CONST, return the value; or if it contains a single PADSV ref-
+ *     erencing an outer lexical, turn on CvCONST to indicate the CV is
+ *     a candidate for "constizing" at clone time, and return NULL.
  */
 
-SV *
-Perl_op_const_sv(pTHX_ const OP *o, CV *cv)
+static SV *
+S_op_const_sv(pTHX_ const OP *o, CV *cv, bool allow_lex)
 {
     SV *sv = NULL;
+    bool padsv = FALSE;
 
-    if (!o)
-       return NULL;
-
-    if (o->op_type == OP_LINESEQ && cLISTOPo->op_first)
-       o = OP_SIBLING(cLISTOPo->op_first);
+    assert(o);
+    assert(cv);
 
     for (; o; o = o->op_next) {
        const OPCODE type = o->op_type;
 
-       if (sv && o->op_next == o)
-           return sv;
-       if (o->op_next != o) {
-           if (type == OP_NEXTSTATE
-            || (type == OP_NULL && !(o->op_flags & OPf_KIDS))
+       if (type == OP_NEXTSTATE || type == OP_LINESEQ
+            || type == OP_NULL
             || type == OP_PUSHMARK)
                continue;
-           if (type == OP_DBSTATE)
+       if (type == OP_DBSTATE)
                continue;
-       }
-       if (type == OP_LEAVESUB || type == OP_RETURN)
+       if (type == OP_LEAVESUB)
            break;
        if (sv)
            return NULL;
@@ -7727,31 +7779,23 @@ Perl_op_const_sv(pTHX_ const OP *o, CV *cv)
            sv = newSV(0);
            SAVEFREESV(sv);
        }
-       else if (cv && type == OP_CONST) {
-           sv = PAD_BASE_SV(CvPADLIST(cv), o->op_targ);
-           if (!sv)
-               return NULL;
-       }
-       else if (cv && type == OP_PADSV) {
-           if (CvCONST(cv)) { /* newly cloned anon */
-               sv = PAD_BASE_SV(CvPADLIST(cv), o->op_targ);
-               /* the candidate should have 1 ref from this pad and 1 ref
-                * from the parent */
-               if (!sv || SvREFCNT(sv) != 2)
-                   return NULL;
-               sv = newSVsv(sv);
-               SvREADONLY_on(sv);
-               return sv;
-           }
-           else {
+       else if (allow_lex && type == OP_PADSV) {
                if (PAD_COMPNAME_FLAGS(o->op_targ) & SVf_FAKE)
+               {
                    sv = &PL_sv_undef; /* an arbitrary non-null value */
-           }
+                   padsv = TRUE;
+               }
+               else
+                   return NULL;
        }
        else {
            return NULL;
        }
     }
+    if (padsv) {
+       CvCONST_on(cv);
+       return NULL;
+    }
     return sv;
 }
 
@@ -7821,6 +7865,7 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
     CV *clonee = NULL;
     HEK *hek = NULL;
     bool reusable = FALSE;
+    OP *start;
 #ifdef PERL_DEBUG_READONLY_OPS
     OPSLAB *slab = NULL;
 #endif
@@ -7906,12 +7951,29 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        spot = (CV **)(svspot = &mg->mg_obj);
     }
 
+    if (block) {
+       /* This makes sub {}; work as expected.  */
+       if (block->op_type == OP_STUB) {
+           const line_t l = PL_parser->copline;
+           op_free(block);
+           block = newSTATEOP(0, NULL, 0);
+           PL_parser->copline = l;
+       }
+       block = CvLVALUE(compcv)
+            || (cv && CvLVALUE(cv) && !CvROOT(cv) && !CvXSUB(cv))
+                  ? newUNOP(OP_LEAVESUBLV, 0,
+                            op_lvalue(scalarseq(block), OP_LEAVESUBLV))
+                  : newUNOP(OP_LEAVESUB, 0, scalarseq(block));
+       start = LINKLIST(block);
+       block->op_next = 0;
+    }
+
     if (!block || !ps || *ps || attrs
-       || (CvFLAGS(compcv) & CVf_BUILTIN_ATTRS)
+       || CvLVALUE(compcv)
        )
        const_sv = NULL;
     else
-       const_sv = op_const_sv(block, NULL);
+       const_sv = S_op_const_sv(aTHX_ start, compcv, FALSE);
 
     if (cv) {
         const bool exists = CvROOT(cv) || CvXSUB(cv);
@@ -7957,6 +8019,7 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        CvCONST_on(cv);
        CvISXSUB_on(cv);
        PoisonPADLIST(cv);
+       CvFLAGS(cv) |= CvMETHOD(compcv);
        op_free(block);
        SvREFCNT_dec(compcv);
        PL_compcv = NULL;
@@ -8053,16 +8116,7 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
        exit.  */
        
     PL_breakable_sub_gen++;
-    /* This makes sub {}; work as expected.  */
-    if (block->op_type == OP_STUB) {
-           OP* const newblock = newSTATEOP(0, NULL, 0);
-           op_free(block);
-           block = newblock;
-    }
-    CvROOT(cv) = CvLVALUE(cv)
-                  ? newUNOP(OP_LEAVESUBLV, 0,
-                            op_lvalue(scalarseq(block), OP_LEAVESUBLV))
-                  : newUNOP(OP_LEAVESUB, 0, scalarseq(block));
+    CvROOT(cv) = block;
     CvROOT(cv)->op_private |= OPpREFCOUNTED;
     OpREFCNT_set(CvROOT(cv), 1);
     /* The cv no longer needs to hold a refcount on the slab, as CvROOT
@@ -8072,9 +8126,8 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 #ifdef PERL_DEBUG_READONLY_OPS
     slab = (OPSLAB *)CvSTART(cv);
 #endif
-    CvSTART(cv) = LINKLIST(CvROOT(cv));
-    CvROOT(cv)->op_next = 0;
-    CALL_PEEP(CvSTART(cv));
+    CvSTART(cv) = start;
+    CALL_PEEP(start);
     finalize_optree(CvROOT(cv));
     S_prune_chain_head(&CvSTART(cv));
 
@@ -8082,12 +8135,6 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
 
     pad_tidy(CvCLONE(cv) ? padtidy_SUBCLONE : padtidy_SUB);
 
-    if (CvCLONE(cv)) {
-       assert(!CvCONST(cv));
-       if (ps && !*ps && op_const_sv(block, cv))
-           CvCONST_on(cv);
-    }
-
   attrs:
     if (attrs) {
        /* Need to do a C<use attributes $stash_of_cv,\&cv,@attrs>. */
@@ -8186,6 +8233,7 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
         o ? SvPV_const(o_is_gv ? (SV *)o : cSVOPo->op_sv, namlen) : NULL;
     bool has_name;
     bool name_is_utf8 = o && !o_is_gv && SvUTF8(cSVOPo->op_sv);
+    OP *start;
 #ifdef PERL_DEBUG_READONLY_OPS
     OPSLAB *slab = NULL;
     bool special = FALSE;
@@ -8306,13 +8354,31 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
                ? (CV *)SvRV(gv)
                : NULL;
 
+    if (block) {
+       /* This makes sub {}; work as expected.  */
+       if (block->op_type == OP_STUB) {
+           const line_t l = PL_parser->copline;
+           op_free(block);
+           block = newSTATEOP(0, NULL, 0);
+           PL_parser->copline = l;
+       }
+       block = CvLVALUE(PL_compcv)
+            || (cv && CvLVALUE(cv) && !CvROOT(cv) && !CvXSUB(cv)
+                   && (!isGV(gv) || !GvASSUMECV(gv)))
+                  ? newUNOP(OP_LEAVESUBLV, 0,
+                            op_lvalue(scalarseq(block), OP_LEAVESUBLV))
+                  : newUNOP(OP_LEAVESUB, 0, scalarseq(block));
+       start = LINKLIST(block);
+       block->op_next = 0;
+    }
 
     if (!block || !ps || *ps || attrs
-       || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS)
+       || CvLVALUE(PL_compcv)
        )
        const_sv = NULL;
     else
-       const_sv = op_const_sv(block, NULL);
+       const_sv =
+           S_op_const_sv(aTHX_ start, PL_compcv, CvCLONE(PL_compcv));
 
     if (SvPOK(gv) || (SvROK(gv) && SvTYPE(SvRV(gv)) != SVt_PVCV)) {
        assert (block);
@@ -8379,14 +8445,17 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
            CvCONST_on(cv);
            CvISXSUB_on(cv);
            PoisonPADLIST(cv);
+           CvFLAGS(cv) |= CvMETHOD(PL_compcv);
        }
        else {
-           if (isGV(gv)) {
-               if (name) GvCV_set(gv, NULL);
+           if (isGV(gv) || CvMETHOD(PL_compcv)) {
+               if (name && isGV(gv))
+                   GvCV_set(gv, NULL);
                cv = newCONSTSUB_flags(
                    NULL, name, namlen, name_is_utf8 ? SVf_UTF8 : 0,
                    const_sv
                );
+               CvFLAGS(cv) |= CvMETHOD(PL_compcv);
            }
            else {
                if (!SvROK(gv)) {
@@ -8512,16 +8581,7 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
        exit.  */
        
     PL_breakable_sub_gen++;
-    /* This makes sub {}; work as expected.  */
-    if (block->op_type == OP_STUB) {
-           OP* const newblock = newSTATEOP(0, NULL, 0);
-           op_free(block);
-           block = newblock;
-    }
-    CvROOT(cv) = CvLVALUE(cv)
-                  ? newUNOP(OP_LEAVESUBLV, 0,
-                            op_lvalue(scalarseq(block), OP_LEAVESUBLV))
-                  : newUNOP(OP_LEAVESUB, 0, scalarseq(block));
+    CvROOT(cv) = block;
     CvROOT(cv)->op_private |= OPpREFCOUNTED;
     OpREFCNT_set(CvROOT(cv), 1);
     /* The cv no longer needs to hold a refcount on the slab, as CvROOT
@@ -8531,9 +8591,8 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
 #ifdef PERL_DEBUG_READONLY_OPS
     slab = (OPSLAB *)CvSTART(cv);
 #endif
-    CvSTART(cv) = LINKLIST(CvROOT(cv));
-    CvROOT(cv)->op_next = 0;
-    CALL_PEEP(CvSTART(cv));
+    CvSTART(cv) = start;
+    CALL_PEEP(start);
     finalize_optree(CvROOT(cv));
     S_prune_chain_head(&CvSTART(cv));
 
@@ -8541,12 +8600,6 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
 
     pad_tidy(CvCLONE(cv) ? padtidy_SUBCLONE : padtidy_SUB);
 
-    if (CvCLONE(cv)) {
-       assert(!CvCONST(cv));
-       if (ps && !*ps && op_const_sv(block, cv))
-           CvCONST_on(cv);
-    }
-
   attrs:
     if (attrs) {
        /* Need to do a C<use attributes $stash_of_cv,\&cv,@attrs>. */
@@ -9427,7 +9480,7 @@ Perl_ck_eval(pTHX_ OP *o)
        }
        else {
            scalar((OP*)kid);
-           PL_cv_has_eval = 1;
+           S_set_haseval(aTHX);
        }
     }
     else {
@@ -10629,6 +10682,9 @@ Perl_ck_sort(pTHX_ OP *o)
                    OP * const padop = newOP(OP_PADCV, 0);
                    padop->op_targ = off;
                    cUNOPx(firstkid)->op_first = padop;
+#ifdef PERL_OP_PARENT
+                    padop->op_sibling = firstkid;
+#endif
                    op_free(kid);
                }
            }
@@ -11112,8 +11168,11 @@ Perl_ck_entersub_args_proto(pTHX_ OP *entersubop, GV *namegv, SV *protosv)
            case '&':
                proto++;
                arg++;
-               if (o3->op_type != OP_REFGEN && o3->op_type != OP_SREFGEN
-                && o3->op_type != OP_UNDEF)
+               if (o3->op_type != OP_SREFGEN
+                || (  cUNOPx(cUNOPx(o3)->op_first)->op_first->op_type
+                       != OP_ANONCODE
+                   && cUNOPx(cUNOPx(o3)->op_first)->op_first->op_type
+                       != OP_RV2CV))
                    bad_type_gv(arg,
                            arg == 1 ? "block or sub {}" : "sub {}",
                            namegv, 0, o3);
@@ -11532,6 +11591,7 @@ Perl_ck_subr(pTHX_ OP *o)
     OP *aop, *cvop;
     CV *cv;
     GV *namegv;
+    SV *const_class = NULL;
 
     PERL_ARGS_ASSERT_CK_SUBR;
 
@@ -11548,17 +11608,41 @@ Perl_ck_subr(pTHX_ OP *o)
     o->op_private |= (PL_hints & HINT_STRICT_REFS);
     if (PERLDB_SUB && PL_curstash != PL_debstash)
        o->op_private |= OPpENTERSUB_DB;
-    if (cvop->op_type == OP_RV2CV) {
-       o->op_private |= (cvop->op_private & OPpENTERSUB_AMPER);
-       op_null(cvop);
-    } else if (cvop->op_type == OP_METHOD || cvop->op_type == OP_METHOD_NAMED) {
-       if (aop->op_type == OP_CONST)
-           aop->op_private &= ~OPpCONST_STRICT;
-       else if (aop->op_type == OP_LIST) {
-           OP * const sib = OP_SIBLING(((UNOP*)aop)->op_first);
-           if (sib && sib->op_type == OP_CONST)
-               sib->op_private &= ~OPpCONST_STRICT;
-       }
+    switch (cvop->op_type) {
+       case OP_RV2CV:
+           o->op_private |= (cvop->op_private & OPpENTERSUB_AMPER);
+           op_null(cvop);
+           break;
+       case OP_METHOD:
+       case OP_METHOD_NAMED:
+           if (aop->op_type == OP_CONST) {
+               aop->op_private &= ~OPpCONST_STRICT;
+               const_class = cSVOPx(aop)->op_sv;
+           }
+           else if (aop->op_type == OP_LIST) {
+               OP * const sib = OP_SIBLING(((UNOP*)aop)->op_first);
+               if (sib && sib->op_type == OP_CONST) {
+                   sib->op_private &= ~OPpCONST_STRICT;
+                   const_class = cSVOPx(sib)->op_sv;
+               }
+           }
+           /* cache const class' name to speedup class method calls */
+           if (const_class) {
+               STRLEN len;
+               SV* shared;
+               const char* str = SvPV(const_class, len);
+               if (len) {
+                   shared = newSVpvn_share(
+                       str, SvUTF8(const_class) ? -len : len, 0
+                   );
+#ifdef USE_ITHREADS
+                   op_relocate_sv(&shared, &cMETHOPx(cvop)->op_class_targ);
+#else
+                   cMETHOPx(cvop)->op_class_sv = shared;
+#endif
+               }
+           }
+           break;
     }
 
     if (!cv) {