This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perldelta for 23695c073f41
[perl5.git] / pp_hot.c
index 3d72d0d..223169b 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -284,8 +284,11 @@ PP(pp_concat)
     }
     else { /* $l .= $r   and   left == TARG */
        if (!SvOK(left)) {
-           if (left == right && ckWARN(WARN_UNINITIALIZED)) /* $l .= $l */
-               report_uninit(right);
+            if ((left == right                          /* $l .= $l */
+                 || (PL_op->op_private & OPpTARGET_MY)) /* $l = $l . $r */
+                && ckWARN(WARN_UNINITIALIZED)
+                )
+                report_uninit(left);
            sv_setpvs(left, "");
        }
         else {
@@ -963,7 +966,7 @@ PP(pp_print)
 PP(pp_rv2av)
 {
     dSP; dTOPss;
-    const I32 gimme = GIMME_V;
+    const U8 gimme = GIMME_V;
     static const char an_array[] = "an ARRAY";
     static const char a_hash[] = "a HASH";
     const bool is_pp_rv2av = PL_op->op_type == OP_RV2AV
@@ -1251,7 +1254,7 @@ PP(pp_aassign)
     SV *sv;
     AV *ary;
 
-    I32 gimme;
+    U8 gimme;
     HV *hash;
     SSize_t i;
     int magic;
@@ -1716,7 +1719,7 @@ PP(pp_match)
     const char *truebase;                      /* Start of string  */
     REGEXP *rx = PM_GETRE(pm);
     bool rxtainted;
-    const I32 gimme = GIMME_V;
+    const U8 gimme = GIMME_V;
     STRLEN len;
     const I32 oldsave = PL_savestack_ix;
     I32 had_zerolen = 0;
@@ -1908,7 +1911,7 @@ Perl_do_readline(pTHX)
     PerlIO *fp;
     IO * const io = GvIO(PL_last_in_gv);
     const I32 type = PL_op->op_type;
-    const I32 gimme = GIMME_V;
+    const U8 gimme = GIMME_V;
 
     if (io) {
        const MAGIC *const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar);
@@ -2630,8 +2633,14 @@ PP(pp_iter)
     SV **itersvp;
     SV *retsv;
 
+    SV *sv;
+    AV *av;
+    IV ix;
+    IV inc;
+
     cx = CX_CUR();
     itersvp = CxITERVAR(cx);
+    assert(itersvp);
 
     switch (CxTYPE(cx)) {
 
@@ -2714,12 +2723,6 @@ PP(pp_iter)
         break;
     }
 
-    {
-        SV *sv;
-        AV *av;
-        IV ix;
-        IV inc;
-
     case CXt_LOOP_LIST: /* for (1,2,3) */
 
         assert(OPpITER_REVERSED == 2); /* so inc becomes -1 or 1 */
@@ -2784,7 +2787,6 @@ PP(pp_iter)
         *itersvp = sv;
         SvREFCNT_dec(oldsv);
         break;
-    }
 
     default:
        DIE(aTHX_ "panic: pp_iter, type=%u", CxTYPE(cx));
@@ -2800,8 +2802,6 @@ PP(pp_iter)
     *++PL_stack_sp =retsv;
 
     return PL_op->op_next;
-
-
 }
 
 /*
@@ -2895,7 +2895,7 @@ PP(pp_subst)
     STRLEN slen;
     bool doutf8 = FALSE; /* whether replacement is in utf8 */
 #ifdef PERL_ANY_COW
-    bool is_cow;
+    bool was_cow;
 #endif
     SV *nsv = NULL;
     /* known replacement string? */
@@ -2914,24 +2914,25 @@ PP(pp_subst)
 
     SvGETMAGIC(TARG); /* must come before cow check */
 #ifdef PERL_ANY_COW
-    /* Awooga. Awooga. "bool" types that are actually char are dangerous,
-       because they make integers such as 256 "false".  */
-    is_cow = SvIsCOW(TARG) ? TRUE : FALSE;
-#else
-    if (SvIsCOW(TARG))
-       sv_force_normal_flags(TARG,0);
+    /* note that a string might get converted to COW during matching */
+    was_cow = cBOOL(SvIsCOW(TARG));
 #endif
-    if (!(rpm->op_pmflags & PMf_NONDESTRUCT)
-       && (SvREADONLY(TARG)
-           || ( ((SvTYPE(TARG) == SVt_PVGV && isGV_with_GP(TARG))
-                 || SvTYPE(TARG) > SVt_PVLV)
-                && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG)))))
-       Perl_croak_no_modify();
+    if (!(rpm->op_pmflags & PMf_NONDESTRUCT)) {
+#ifndef PERL_ANY_COW
+       if (SvIsCOW(TARG))
+           sv_force_normal_flags(TARG,0);
+#endif
+       if ((SvREADONLY(TARG)
+               || ( ((SvTYPE(TARG) == SVt_PVGV && isGV_with_GP(TARG))
+                     || SvTYPE(TARG) > SVt_PVLV)
+                    && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG)))))
+           Perl_croak_no_modify();
+    }
     PUTBACK;
 
     orig = SvPV_nomg(TARG, len);
     /* note we don't (yet) force the var into being a string; if we fail
-     * to match, we leave as-is; on successful match howeverm, we *will*
+     * to match, we leave as-is; on successful match however, we *will*
      * coerce into a string, then repeat the match */
     if (!SvPOKp(TARG) || SvTYPE(TARG) == SVt_PVGV || SvVOK(TARG))
        force_on_match = 1;
@@ -3016,7 +3017,7 @@ PP(pp_subst)
     /* can do inplace substitution? */
     if (c
 #ifdef PERL_ANY_COW
-       && !is_cow
+       && !was_cow
 #endif
         && (I32)clen <= RX_MINLENRET(rx)
         && (  once
@@ -3029,6 +3030,7 @@ PP(pp_subst)
     {
 
 #ifdef PERL_ANY_COW
+        /* string might have got converted to COW since we set was_cow */
        if (SvIsCOW(TARG)) {
          if (!force_on_match)
            goto have_a_cow;
@@ -3268,7 +3270,7 @@ PP(pp_grepwhile)
     /* All done yet? */
     if (UNLIKELY(PL_stack_base + *PL_markstack_ptr > SP)) {
        I32 items;
-       const I32 gimme = GIMME_V;
+       const U8 gimme = GIMME_V;
 
        LEAVE_with_name("grep");                                        /* exit outer scope */
        (void)POPMARK;                          /* pop src */
@@ -3362,8 +3364,9 @@ PP(pp_grepwhile)
  */
 
 void
-Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, I32 gimme, int pass)
+Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, U8 gimme, int pass)
 {
+    dVAR;
     dSP;
     SSize_t tmps_base; /* lowest index into tmps stack that needs freeing now */
     SSize_t nargs;
@@ -3404,8 +3407,6 @@ Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, I32 gimme, int pass)
 
         EXTEND_MORTAL(nargs); /* one big extend for worst-case scenario */
         tmps_basep = PL_tmps_stack + tmps_base;
-        /* whether any SVs have have SvTEMP temporarily turned off,
-         * indicating that they need saving below the cut */
 
         /* process each return arg */
 
@@ -3432,7 +3433,7 @@ Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, I32 gimme, int pass)
              *  1) there is pp code similar to pp_substr that is
              *     returning a PADTMP instead of a mortal, and probably
              *     needs fixing, or
-             *  2) pp_leavesub is making unwarranted assumptions
+             *  2) pp_leavesublv is making unwarranted assumptions
              *     about always croaking on a PADTMP
              */
             if (SvPADTMP(sv) && SvSMAGICAL(sv)) {
@@ -3476,18 +3477,23 @@ Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, I32 gimme, int pass)
                      * merely by moving the cut boundary up one, rather
                      * than messing with SvTEMP.  If all args are 1:1 then
                      * we can avoid the sorting stage below completely.
+                     *
+                     * If there are no items above the cut on the tmps
+                     * stack, then the SvTEMP must comne from an item
+                     * below the cut, so there's nothing to do.
                      */
-                    if (sv == *tmps_basep)
-                        tmps_basep++;
-                    else
-                        SvTEMP_off(sv);
+                    if (tmps_basep <= &PL_tmps_stack[PL_tmps_ix]) {
+                        if (sv == *tmps_basep)
+                            tmps_basep++;
+                        else
+                            SvTEMP_off(sv);
+                    }
                 }
                 else if (!SvPADTMP(sv)) {
                     /* mortalise arg to avoid it being freed during save
                      * stack unwinding. Pad tmps don't need mortalising as
-                     * they're never freed */
-                    SvREFCNT_inc_simple_void_NN(sv);
-                    /* equivalent of sv_2mortal(), except that:
+                     * they're never freed. This is the equivalent of
+                     * sv_2mortal(SvREFCNT_inc(sv)), except that:
                      *  * it assumes that the temps stack has already been
                      *    extended;
                      *  * it puts the new item at the cut rather than at
@@ -3495,7 +3501,14 @@ Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, I32 gimme, int pass)
                      *    instead.
                      */
                     if (!SvIMMORTAL(sv)) {
+                        SvREFCNT_inc_simple_void_NN(sv);
                         SvTEMP_on(sv);
+                        /* Note that if there's nothing above the cut,
+                         * this copies the garbage one slot above
+                         * PL_tmps_ix onto itself. This is harmless (the
+                         * stack's already been extended), but might in
+                         * theory trigger warnings from tools like ASan
+                         */
                         PL_tmps_stack[++PL_tmps_ix] = *tmps_basep;
                         *tmps_basep++ = sv;
                     }
@@ -3613,9 +3626,11 @@ Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, I32 gimme, int pass)
 }
 
 
+/* also tail-called by pp_return */
+
 PP(pp_leavesub)
 {
-    I32 gimme;
+    U8 gimme;
     PERL_CONTEXT *cx;
     SV **oldsp;
     OP *retop;
@@ -3639,8 +3654,8 @@ PP(pp_leavesub)
         leave_adjust_stacks(oldsp, oldsp, gimme, 0);
 
     CX_LEAVE_SCOPE(cx);
-    CX_POPSUB(cx);     /* Stack values are safe: release CV and @_ ... */
-    CX_POPBLOCK(cx);
+    cx_popsub(cx);     /* Stack values are safe: release CV and @_ ... */
+    cx_popblock(cx);
     retop = cx->blk_sub.retop;
     CX_POP(cx);
 
@@ -3763,15 +3778,16 @@ PP(pp_entersub)
     }
 
     /* At this point we want to save PL_savestack_ix, either by doing a
-     * CX_PUSHSUB, or for XS, doing an ENTER. But we don't yet know the final
+     * cx_pushsub(), or for XS, doing an ENTER. But we don't yet know the final
      * CV we will be using (so we don't know whether its XS, so we can't
-     * CX_PUSHSUB or ENTER yet), and determining cv may itself push stuff on
+     * cx_pushsub() or ENTER yet), and determining cv may itself push stuff on
      * the save stack. So remember where we are currently on the save
      * stack, and later update the CX or scopestack entry accordingly. */
     old_savestack_ix = PL_savestack_ix;
 
     /* these two fields are in a union. If they ever become separate,
      * we have to test for both of them being null below */
+    assert(cv);
     assert((void*)&CvROOT(cv) == (void*)&CvXSUB(cv));
     while (UNLIKELY(!CvROOT(cv))) {
        GV* autogv;
@@ -3832,7 +3848,7 @@ PP(pp_entersub)
        PADLIST *padlist;
         I32 depth;
         bool hasargs;
-        I32 gimme;
+        U8 gimme;
 
         /* keep PADTMP args alive throughout the call (we need to do this
          * because @_ isn't refcounted). Note that we create the mortals
@@ -3852,9 +3868,9 @@ PP(pp_entersub)
         }
 
         gimme = GIMME_V;
-       CX_PUSHBLOCK(cx, CXt_SUB, gimme, MARK, old_savestack_ix);
+       cx = cx_pushblock(CXt_SUB, gimme, MARK, old_savestack_ix);
         hasargs = cBOOL(PL_op->op_flags & OPf_STACKED);
-       CX_PUSHSUB(cx, cv, PL_op->op_next, hasargs);
+       cx_pushsub(cx, cv, PL_op->op_next, hasargs);
 
        padlist = CvPADLIST(cv);
        if (UNLIKELY((depth = ++CvDEPTH(cv)) >= 2))
@@ -3871,7 +3887,7 @@ PP(pp_entersub)
 
             /* it's the responsibility of whoever leaves a sub to ensure
              * that a clean, empty AV is left in pad[0]. This is normally
-             * done by CX_POPSUB() */
+             * done by cx_popsub() */
             assert(!AvREAL(av) && AvFILLp(av) == -1);
 
             items = SP - MARK;
@@ -3902,6 +3918,7 @@ PP(pp_entersub)
     }
     else {
        SSize_t markix = TOPMARK;
+        bool is_scalar;
 
         ENTER;
         /* pretend we did the ENTER earlier */
@@ -3964,12 +3981,16 @@ PP(pp_entersub)
        }
        /* Do we need to open block here? XXXX */
 
+        /* calculate gimme here as PL_op might get changed and then not
+         * restored until the LEAVE further down */
+        is_scalar = (GIMME_V == G_SCALAR);
+
        /* CvXSUB(cv) must not be NULL because newXS() refuses NULL xsub address */
        assert(CvXSUB(cv));
        CvXSUB(cv)(aTHX_ cv);
 
        /* Enforce some sanity in scalar context. */
-       if (GIMME_V == G_SCALAR) {
+       if (is_scalar) {
             SV **svp = PL_stack_base + markix + 1;
             if (svp != PL_stack_sp) {
                 *svp = svp > PL_stack_sp ? &PL_sv_undef : *PL_stack_sp;