This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
RT-23180 - If we skip matching in pp_match for any reason, pos() must still be updated.
[perl5.git] / pp_hot.c
index e02558c..8b4bc94 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -85,9 +85,12 @@ PP(pp_pushmark)
 PP(pp_stringify)
 {
     dVAR; dSP; dTARGET;
-    sv_copypv(TARG,TOPs);
-    SETTARG;
-    RETURN;
+    SV * const sv = TOPs;
+    SETs(TARG);
+    sv_copypv(TARG, sv);
+    SvSETMAGIC(TARG);
+    /* no PUTBACK, SETs doesn't inc/dec SP */
+    return NORMAL;
 }
 
 PP(pp_gv)
@@ -99,14 +102,22 @@ PP(pp_gv)
 
 PP(pp_and)
 {
-    dVAR; dSP;
+    dVAR;
     PERL_ASYNC_CHECK();
-    if (!SvTRUE(TOPs))
-       RETURN;
-    else {
-        if (PL_op->op_type == OP_AND)
-           --SP;
-       RETURNOP(cLOGOP->op_other);
+    {
+       /* SP is not used to remove a variable that is saved across the
+         sv_2bool_flags call in SvTRUE_NN, if a RISC/CISC or low/high machine
+         register or load/store vs direct mem ops macro is introduced, this
+         should be a define block between direct PL_stack_sp and dSP operations,
+         presently, using PL_stack_sp is bias towards CISC cpus */
+       SV * const sv = *PL_stack_sp;
+       if (!SvTRUE_NN(sv))
+           return NORMAL;
+       else {
+           if (PL_op->op_type == OP_AND)
+               --PL_stack_sp;
+           return cLOGOP->op_other;
+       }
     }
 }
 
@@ -377,19 +388,32 @@ PP(pp_padrange)
 
 PP(pp_padsv)
 {
-    dVAR; dSP; dTARGET;
-    XPUSHs(TARG);
-    if (PL_op->op_flags & OPf_MOD) {
-       if (PL_op->op_private & OPpLVAL_INTRO)
-           if (!(PL_op->op_private & OPpPAD_STATE))
-               SAVECLEARSV(PAD_SVl(PL_op->op_targ));
-        if (PL_op->op_private & OPpDEREF) {
-           PUTBACK;
-           TOPs = vivify_ref(TOPs, PL_op->op_private & OPpDEREF);
-           SPAGAIN;
+    dVAR; dSP;
+    EXTEND(SP, 1);
+    {
+       OP * const op = PL_op;
+       /* access PL_curpad once */
+       SV ** const padentry = &(PAD_SVl(op->op_targ));
+       {
+           dTARG;
+           TARG = *padentry;
+           PUSHs(TARG);
+           PUTBACK; /* no pop/push after this, TOPs ok */
+       }
+       if (op->op_flags & OPf_MOD) {
+           if (op->op_private & OPpLVAL_INTRO)
+               if (!(op->op_private & OPpPAD_STATE))
+                   save_clearsv(padentry);
+           if (op->op_private & OPpDEREF) {
+               /* TOPs is equivalent to TARG here.  Using TOPs (SP) rather
+                  than TARG reduces the scope of TARG, so it does not
+                  span the call to save_clearsv, resulting in smaller
+                  machine code. */
+               TOPs = vivify_ref(TOPs, op->op_private & OPpDEREF);
+           }
        }
+       return op->op_next;
     }
-    RETURN;
 }
 
 PP(pp_readline)
@@ -1326,6 +1350,9 @@ PP(pp_match)
 
     RX_MATCH_UTF8_set(rx, DO_UTF8(TARG));
 
+    /* We need to know this incase we fail out early - pos() must be reset */
+    global = dynpm->op_pmflags & PMf_GLOBAL;
+
     /* PMdf_USED is set after a ?? matches once */
     if (
 #ifdef USE_ITHREADS
@@ -1335,11 +1362,7 @@ PP(pp_match)
 #endif
     ) {
         DEBUG_r(PerlIO_printf(Perl_debug_log, "?? already matched once"));
-      failure:
-
-       if (gimme == G_ARRAY)
-           RETURN;
-       RETPUSHNO;
+       goto nope;
     }
 
 
@@ -1354,13 +1377,13 @@ PP(pp_match)
 
     if (RX_MINLEN(rx) > (I32)len) {
         DEBUG_r(PerlIO_printf(Perl_debug_log, "String shorter than min possible regex match\n"));
-       goto failure;
+       goto nope;
     }
 
     truebase = t = s;
 
     /* XXXX What part of this is needed with true \G-support? */
-    if ((global = dynpm->op_pmflags & PMf_GLOBAL)) {
+    if (global) {
        RX_OFFS(rx)[0].start = -1;
        if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
            MAGIC* const mg = mg_find(TARG, PERL_MAGIC_regex_global);
@@ -1905,121 +1928,115 @@ PP(pp_iter)
     itersvp = CxITERVAR(cx);
 
     switch (CxTYPE(cx)) {
-    case CXt_LOOP_LAZYSV:
-        {
-           /* string increment */
-           SV* cur = cx->blk_loop.state_u.lazysv.cur;
-           SV *end = cx->blk_loop.state_u.lazysv.end;
-           /* If the maximum is !SvOK(), pp_enteriter substitutes PL_sv_no.
-              It has SvPVX of "" and SvCUR of 0, which is what we want.  */
-           STRLEN maxlen = 0;
-           const char *max = SvPV_const(end, maxlen);
-           if (SvNIOK(cur) || SvCUR(cur) > maxlen)
-                RETPUSHNO;
 
-            if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) {
-                /* safe to reuse old SV */
-                sv_setsv(*itersvp, cur);
-            }
-            else
-            {
-                /* we need a fresh SV every time so that loop body sees a
-                 * completely new SV for closures/references to work as
-                 * they used to */
-                oldsv = *itersvp;
-                *itersvp = newSVsv(cur);
-                SvREFCNT_dec(oldsv);
-            }
-            if (strEQ(SvPVX_const(cur), max))
-                sv_setiv(cur, 0); /* terminate next time */
-            else
-                sv_inc(cur);
-            break;
+    case CXt_LOOP_LAZYSV: /* string increment */
+    {
+        SV* cur = cx->blk_loop.state_u.lazysv.cur;
+        SV *end = cx->blk_loop.state_u.lazysv.end;
+        /* If the maximum is !SvOK(), pp_enteriter substitutes PL_sv_no.
+           It has SvPVX of "" and SvCUR of 0, which is what we want.  */
+        STRLEN maxlen = 0;
+        const char *max = SvPV_const(end, maxlen);
+        if (SvNIOK(cur) || SvCUR(cur) > maxlen)
+            RETPUSHNO;
+
+        oldsv = *itersvp;
+        if (SvREFCNT(oldsv) == 1 && !SvMAGICAL(oldsv)) {
+            /* safe to reuse old SV */
+            sv_setsv(oldsv, cur);
         }
+        else
+        {
+            /* we need a fresh SV every time so that loop body sees a
+             * completely new SV for closures/references to work as
+             * they used to */
+            *itersvp = newSVsv(cur);
+            SvREFCNT_dec(oldsv);
+        }
+        if (strEQ(SvPVX_const(cur), max))
+            sv_setiv(cur, 0); /* terminate next time */
+        else
+            sv_inc(cur);
+        break;
+    }
 
-    case CXt_LOOP_LAZYIV:
-       /* integer increment */
-       if (cx->blk_loop.state_u.lazyiv.cur > cx->blk_loop.state_u.lazyiv.end)
+    case CXt_LOOP_LAZYIV: /* integer increment */
+    {
+        IV cur = cx->blk_loop.state_u.lazyiv.cur;
+       if (cur > cx->blk_loop.state_u.lazyiv.end)
            RETPUSHNO;
 
+        oldsv = *itersvp;
        /* don't risk potential race */
-       if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) {
+       if (SvREFCNT(oldsv) == 1 && !SvMAGICAL(oldsv)) {
            /* safe to reuse old SV */
-           sv_setiv(*itersvp, cx->blk_loop.state_u.lazyiv.cur);
+           sv_setiv(oldsv, cur);
        }
        else
        {
            /* we need a fresh SV every time so that loop body sees a
             * completely new SV for closures/references to work as they
             * used to */
-           oldsv = *itersvp;
-           *itersvp = newSViv(cx->blk_loop.state_u.lazyiv.cur);
+           *itersvp = newSViv(cur);
            SvREFCNT_dec(oldsv);
        }
 
-       if (cx->blk_loop.state_u.lazyiv.cur == IV_MAX) {
+       if (cur == IV_MAX) {
            /* Handle end of range at IV_MAX */
            cx->blk_loop.state_u.lazyiv.end = IV_MIN;
        } else
            ++cx->blk_loop.state_u.lazyiv.cur;
         break;
+    }
 
-    case CXt_LOOP_FOR:
+    case CXt_LOOP_FOR: /* iterate array */
     {
 
-        /* iterate array */
         AV *av = cx->blk_loop.state_u.ary.ary;
         SV *sv;
         bool av_is_stack = FALSE;
+        IV ix;
 
         if (!av) {
             av_is_stack = TRUE;
             av = PL_curstack;
         }
         if (PL_op->op_private & OPpITER_REVERSED) {
-            if (cx->blk_loop.state_u.ary.ix <= (av_is_stack
-                                        ? cx->blk_loop.resetsp + 1 : 0))
+            ix = --cx->blk_loop.state_u.ary.ix;
+            if (ix <= (av_is_stack ? cx->blk_loop.resetsp : -1))
                 RETPUSHNO;
-
-            if (SvMAGICAL(av) || AvREIFY(av)) {
-                SV * const * const svp = av_fetch(av, --cx->blk_loop.state_u.ary.ix, FALSE);
-                sv = svp ? *svp : NULL;
-            }
-            else {
-                sv = AvARRAY(av)[--cx->blk_loop.state_u.ary.ix];
-            }
         }
         else {
-            if (cx->blk_loop.state_u.ary.ix >= (av_is_stack ? cx->blk_oldsp :
-                                        AvFILL(av)))
+            ix = ++cx->blk_loop.state_u.ary.ix;
+            if (ix > (av_is_stack ? cx->blk_oldsp : AvFILL(av)))
                 RETPUSHNO;
-
-            if (SvMAGICAL(av) || AvREIFY(av)) {
-                SV * const * const svp = av_fetch(av, ++cx->blk_loop.state_u.ary.ix, FALSE);
-                sv = svp ? *svp : NULL;
-            }
-            else {
-                sv = AvARRAY(av)[++cx->blk_loop.state_u.ary.ix];
-            }
         }
 
-        if (sv && SvIS_FREED(sv)) {
-            *itersvp = NULL;
-            Perl_croak(aTHX_ "Use of freed value in iteration");
+        if (SvMAGICAL(av) || AvREIFY(av)) {
+            SV * const * const svp = av_fetch(av, ix, FALSE);
+            sv = svp ? *svp : NULL;
+        }
+        else {
+            sv = AvARRAY(av)[ix];
         }
 
         if (sv) {
+            if (SvIS_FREED(sv)) {
+                *itersvp = NULL;
+                Perl_croak(aTHX_ "Use of freed value in iteration");
+            }
             SvTEMP_off(sv);
             SvREFCNT_inc_simple_void_NN(sv);
         }
         else
             sv = &PL_sv_undef;
+
         if (!av_is_stack && sv == &PL_sv_undef) {
             SV *lv = newSV_type(SVt_PVLV);
             LvTYPE(lv) = 'y';
             sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0);
             LvTARG(lv) = SvREFCNT_inc_simple(av);
-            LvTARGOFF(lv) = cx->blk_loop.state_u.ary.ix;
+            LvTARGOFF(lv) = ix;
             LvTARGLEN(lv) = (STRLEN)UV_MAX;
             sv = lv;
         }
@@ -2033,7 +2050,7 @@ PP(pp_iter)
     default:
        DIE(aTHX_ "panic: pp_iter, type=%u", CxTYPE(cx));
     }
-        RETPUSHYES;
+    RETPUSHYES;
 }
 
 /*