extra code in pp_concat, Take 2
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index 4157736..ba724ff 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1,7 +1,7 @@
 /*    pp_hot.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 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.
  *                     Fire, Foes!  Awake!
  */
 
+/* This file contains 'hot' pp ("push/pop") functions that
+ * execute the opcodes that make up a perl program. A typical pp function
+ * expects to find its arguments on the stack, and usually pushes its
+ * results onto the stack, hence the 'pp' terminology. Each OP structure
+ * contains a pointer to the relevant pp_foo() function.
+ *
+ * By 'hot', we mean common ops whose execution speed is critical.
+ * By gathering them together into a single file, we encourage
+ * CPU cache hits on hot code. Also it could be taken as a warning not to
+ * change any code in this file unless you're sure it won't affect
+ * performance.
+ */
+
 #include "EXTERN.h"
 #define PERL_IN_PP_HOT_C
 #include "perl.h"
@@ -132,12 +145,11 @@ PP(pp_concat)
   dSP; dATARGET; tryAMAGICbin(concat,opASSIGN);
   {
     dPOPTOPssrl;
-    STRLEN llen;
-    char* lpv;
     bool lbyte;
     STRLEN rlen;
-    char* rpv = SvPV(right, rlen);     /* mg_get(right) happens here */
-    bool rbyte = !DO_UTF8(right), rcopied = FALSE;
+    const char *rpv = SvPV(right, rlen);       /* mg_get(right) happens here */
+    const bool rbyte = !DO_UTF8(right);
+    bool rcopied = FALSE;
 
     if (TARG == right && right != left) {
        right = sv_2mortal(newSVpvn(rpv, rlen));
@@ -146,7 +158,8 @@ PP(pp_concat)
     }
 
     if (TARG != left) {
-       lpv = SvPV(left, llen);         /* mg_get(left) may happen here */
+        STRLEN llen;
+        const char* const lpv = SvPV(left, llen);      /* mg_get(left) may happen here */
        lbyte = !DO_UTF8(left);
        sv_setpvn(TARG, lpv, llen);
        if (!lbyte)
@@ -155,27 +168,17 @@ PP(pp_concat)
            SvUTF8_off(TARG);
     }
     else { /* TARG == left */
+        STRLEN llen;
        if (SvGMAGICAL(left))
            mg_get(left);               /* or mg_get(left) may happen here */
        if (!SvOK(TARG))
            sv_setpv(left, "");
-       lpv = SvPV_nomg(left, llen);
+       (void)SvPV_nomg(left, llen);    /* Needed to set UTF8 flag */
        lbyte = !DO_UTF8(left);
        if (IN_BYTES)
            SvUTF8_off(TARG);
     }
 
-#if defined(PERL_Y2KWARN)
-    if ((SvIOK(right) || SvNOK(right)) && ckWARN(WARN_Y2K) && SvOK(TARG)) {
-       if (llen >= 2 && lpv[llen - 2] == '1' && lpv[llen - 1] == '9'
-           && (llen == 2 || !isDIGIT(lpv[llen - 3])))
-       {
-           Perl_warner(aTHX_ packWARN(WARN_Y2K), "Possible Y2K bug: %s",
-                       "about to append an integer to '19'");
-       }
-    }
-#endif
-
     if (lbyte != rbyte) {
        if (lbyte)
            sv_utf8_upgrade_nomg(TARG);
@@ -302,7 +305,7 @@ PP(pp_preinc)
     if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
         && SvIVX(TOPs) != IV_MAX)
     {
-       ++SvIVX(TOPs);
+       SvIV_set(TOPs, SvIVX(TOPs) + 1);
        SvFLAGS(TOPs) &= ~(SVp_NOK|SVp_POK);
     }
     else /* Do all the PERL_PRESERVE_IVUV conditionals in sv_inc */
@@ -712,9 +715,6 @@ PP(pp_rv2av)
            GV *gv;
        
            if (SvTYPE(sv) != SVt_PVGV) {
-               char *sym;
-               STRLEN len;
-
                if (SvGMAGICAL(sv)) {
                    mg_get(sv);
                    if (SvROK(sv))
@@ -732,22 +732,21 @@ PP(pp_rv2av)
                    }
                    RETSETUNDEF;
                }
-               sym = SvPV(sv,len);
                if ((PL_op->op_flags & OPf_SPECIAL) &&
                    !(PL_op->op_flags & OPf_MOD))
                {
-                   gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PVAV);
+                   gv = (GV*)gv_fetchsv(sv, FALSE, SVt_PVAV);
                    if (!gv
-                       && (!is_gv_magical(sym,len,0)
-                           || !(gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVAV))))
+                       && (!is_gv_magical_sv(sv,0)
+                           || !(gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVAV))))
                    {
                        RETSETUNDEF;
                    }
                }
                else {
                    if (PL_op->op_private & HINT_STRICT_REFS)
-                       DIE(aTHX_ PL_no_symref, sym, "an ARRAY");
-                   gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVAV);
+                       DIE(aTHX_ PL_no_symref_sv, sv, "an ARRAY");
+                   gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVAV);
                }
            }
            else {
@@ -843,9 +842,6 @@ PP(pp_rv2hv)
            GV *gv;
        
            if (SvTYPE(sv) != SVt_PVGV) {
-               char *sym;
-               STRLEN len;
-
                if (SvGMAGICAL(sv)) {
                    mg_get(sv);
                    if (SvROK(sv))
@@ -863,22 +859,21 @@ PP(pp_rv2hv)
                    }
                    RETSETUNDEF;
                }
-               sym = SvPV(sv,len);
                if ((PL_op->op_flags & OPf_SPECIAL) &&
                    !(PL_op->op_flags & OPf_MOD))
                {
-                   gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PVHV);
+                   gv = (GV*)gv_fetchsv(sv, FALSE, SVt_PVHV);
                    if (!gv
-                       && (!is_gv_magical(sym,len,0)
-                           || !(gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVHV))))
+                       && (!is_gv_magical_sv(sv,0)
+                           || !(gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVHV))))
                    {
                        RETSETUNDEF;
                    }
                }
                else {
                    if (PL_op->op_private & HINT_STRICT_REFS)
-                       DIE(aTHX_ PL_no_symref, sym, "a HASH");
-                   gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PVHV);
+                       DIE(aTHX_ PL_no_symref_sv, sv, "a HASH");
+                   gv = (GV*)gv_fetchsv(sv, TRUE, SVt_PVHV);
                }
            }
            else {
@@ -1003,9 +998,8 @@ PP(pp_aassign)
            i = 0;
            while (relem <= lastrelem) {        /* gobble up all the rest */
                SV **didstore;
-               sv = NEWSV(28,0);
                assert(*relem);
-               sv_setsv(sv,*relem);
+               sv = newSVsv(*relem);
                *(relem++) = sv;
                didstore = av_store(ary,i++,sv);
                if (magic) {
@@ -1261,11 +1255,6 @@ PP(pp_match)
     if (SvSCREAM(TARG))
        r_flags |= REXEC_SCREAM;
 
-    if ((int)(pm->op_pmflags & PMf_MULTILINE) != PL_multiline) {
-       SAVEINT(PL_multiline);
-       PL_multiline = pm->op_pmflags & PMf_MULTILINE;
-    }
-
 play_it_again:
     if (global && rx->startp[0] != -1) {
        t = s = rx->endp[0] + truebase;
@@ -1524,7 +1513,7 @@ Perl_do_readline(pTHX)
            /* undef TARG, and push that undefined value */
            if (type != OP_RCATLINE) {
                SV_CHECK_THINKFIRST_COW_DROP(TARG);
-               (void)SvOK_off(TARG);
+               SvOK_off(TARG);
            }
            PUSHTARG;
        }
@@ -1590,7 +1579,7 @@ Perl_do_readline(pTHX)
            if (gimme == G_SCALAR) {
                if (type != OP_RCATLINE) {
                    SV_CHECK_THINKFIRST_COW_DROP(TARG);
-                   (void)SvOK_off(TARG);
+                   SvOK_off(TARG);
                }
                SPAGAIN;
                PUSHTARG;
@@ -1611,7 +1600,7 @@ Perl_do_readline(pTHX)
                tmps = SvEND(sv) - 1;
                if (*tmps == *SvPVX(PL_rs)) {
                    *tmps = '\0';
-                   SvCUR(sv)--;
+                   SvCUR_set(sv, SvCUR(sv) - 1);
                }
            }
            for (tmps = SvPVX(sv); *tmps; tmps++)
@@ -1623,9 +1612,9 @@ Perl_do_readline(pTHX)
                continue;
            }
        } else if (SvUTF8(sv)) { /* OP_READLINE, OP_RCATLINE */
-            U8 *s = (U8*)SvPVX(sv) + offset;
-            STRLEN len = SvCUR(sv) - offset;
-            U8 *f;
+            const U8 *s = (U8*)SvPVX(sv) + offset;
+            const STRLEN len = SvCUR(sv) - offset;
+            const U8 *f;
             
             if (ckWARN(WARN_UTF8) &&
                 !Perl_is_utf8_string_loc(aTHX_ s, len, &f))
@@ -1636,19 +1625,16 @@ Perl_do_readline(pTHX)
        }
        if (gimme == G_ARRAY) {
            if (SvLEN(sv) - SvCUR(sv) > 20) {
-               SvLEN_set(sv, SvCUR(sv)+1);
-               Renew(SvPVX(sv), SvLEN(sv), char);
+               SvPV_shrink_to_cur(sv);
            }
            sv = sv_2mortal(NEWSV(58, 80));
            continue;
        }
        else if (gimme == G_SCALAR && !tmplen && SvLEN(sv) - SvCUR(sv) > 80) {
            /* try to reclaim a bit of scalar space (only on 1st alloc) */
-           if (SvCUR(sv) < 60)
-               SvLEN_set(sv, 80);
-           else
-               SvLEN_set(sv, SvCUR(sv)+40);    /* allow some slop */
-           Renew(SvPVX(sv), SvLEN(sv), char);
+           const STRLEN new_len
+               = SvCUR(sv) < 60 ? 80 : SvCUR(sv)+40; /* allow some slop */
+           SvPV_renew(sv, new_len);
        }
        RETURN;
     }
@@ -1841,7 +1827,7 @@ PP(pp_iter)
            /* string increment */
            register SV* cur = cx->blk_loop.iterlval;
            STRLEN maxlen = 0;
-           char *max = SvOK((SV*)av) ? SvPV((SV*)av, maxlen) : "";
+           const char *max = SvOK((SV*)av) ? SvPV((SV*)av, maxlen) : "";
            if (!SvNIOK(cur) && SvCUR(cur) <= maxlen) {
                if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) {
                    /* safe to reuse old SV */
@@ -1888,7 +1874,7 @@ PP(pp_iter)
     /* iterate array */
     if (PL_op->op_private & OPpITER_REVERSED) {
        /* In reverse, use itermax as the min :-)  */
-       if (cx->blk_loop.iterix <= 0)
+       if (cx->blk_loop.iterix <= cx->blk_loop.itermax)
            RETPUSHNO;
 
        if (SvMAGICAL(av) || AvREIFY(av)) {
@@ -2043,10 +2029,7 @@ PP(pp_subst)
               ? REXEC_COPY_STR : 0;
     if (SvSCREAM(TARG))
        r_flags |= REXEC_SCREAM;
-    if ((int)(pm->op_pmflags & PMf_MULTILINE) != PL_multiline) {
-       SAVEINT(PL_multiline);
-       PL_multiline = pm->op_pmflags & PMf_MULTILINE;
-    }
+
     orig = m = s;
     if (rx->reganch & RE_USE_INTUIT) {
        PL_bostr = orig;
@@ -2217,8 +2200,7 @@ PP(pp_subst)
       have_a_cow:
 #endif
        rxtainted |= RX_MATCH_TAINTED(rx);
-       dstr = NEWSV(25, len);
-       sv_setpvn(dstr, m, s-m);
+       dstr = newSVpvn(m, s-m);
        if (DO_UTF8(TARG))
            SvUTF8_on(dstr);
        PL_curpm = pm;
@@ -2269,15 +2251,15 @@ PP(pp_subst)
        } else
 #endif
        {
-           (void)SvOOK_off(TARG);
+           SvOOK_off(TARG);
            if (SvLEN(TARG))
                Safefree(SvPVX(TARG));
        }
-       SvPVX(TARG) = SvPVX(dstr);
+       SvPV_set(TARG, SvPVX(dstr));
        SvCUR_set(TARG, SvCUR(dstr));
        SvLEN_set(TARG, SvLEN(dstr));
        doutf8 |= DO_UTF8(dstr);
-       SvPVX(dstr) = 0;
+       SvPV_set(dstr, (char*)0);
        sv_free(dstr);
 
        TAINT_IF(rxtainted & 1);
@@ -2409,7 +2391,7 @@ PP(pp_leavesub)
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVESUB(sv);
-    return pop_return();
+    return cx->blk_sub.retop;
 }
 
 /* This duplicates the above code because the above code must not
@@ -2567,7 +2549,7 @@ PP(pp_leavesublv)
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVESUB(sv);
-    return pop_return();
+    return cx->blk_sub.retop;
 }
 
 
@@ -2576,10 +2558,10 @@ S_get_db_sub(pTHX_ SV **svp, CV *cv)
 {
     SV *dbsv = GvSV(PL_DBsub);
 
+    save_item(dbsv);
     if (!PERLDB_SUB_NN) {
        GV *gv = CvGV(cv);
 
-       save_item(dbsv);
        if ( (CvFLAGS(cv) & (CVf_ANON | CVf_CLONED))
             || strEQ(GvNAME(gv), "END")
             || ((GvCV(gv) != cv) && /* Could be imported, and old sub redefined. */
@@ -2596,10 +2578,11 @@ S_get_db_sub(pTHX_ SV **svp, CV *cv)
        }
     }
     else {
-       (void)SvUPGRADE(dbsv, SVt_PVIV);
+       const int type = SvTYPE(dbsv);
+       if (type < SVt_PVIV && type != SVt_IV)
+           sv_upgrade(dbsv, SVt_PVIV);
        (void)SvIOK_on(dbsv);
-       SAVEIV(SvIVX(dbsv));
-       SvIVX(dbsv) = PTR2IV(cv);       /* Do it the quickest way  */
+       SvIV_set(dbsv, PTR2IV(cv));     /* Do it the quickest way  */
     }
 
     if (CvXSUB(cv))
@@ -2616,7 +2599,7 @@ PP(pp_entersub)
     register CV *cv;
     register PERL_CONTEXT *cx;
     I32 gimme;
-    bool hasargs = (PL_op->op_flags & OPf_STACKED) != 0;
+    const bool hasargs = (PL_op->op_flags & OPf_STACKED) != 0;
 
     if (!sv)
        DIE(aTHX_ "Not a CODE reference");
@@ -2633,9 +2616,7 @@ PP(pp_entersub)
        break;
     default:
        if (!SvROK(sv)) {
-           char *sym;
-           STRLEN n_a;
-
+           const char *sym;
            if (sv == &PL_sv_yes) {             /* unfound import, ignore */
                if (hasargs)
                    SP = PL_stack_base + POPMARK;
@@ -2647,8 +2628,10 @@ PP(pp_entersub)
                    goto got_rv;
                sym = SvPOKp(sv) ? SvPVX(sv) : Nullch;
            }
-           else
+           else {
+                STRLEN n_a;
                sym = SvPV(sv, n_a);
+            }
            if (!sym)
                DIE(aTHX_ PL_no_usym, "a subroutine");
            if (PL_op->op_private & HINT_STRICT_REFS)
@@ -2688,8 +2671,8 @@ PP(pp_entersub)
            sv_setiv(PL_DBassertion, 1);
        
        cv = get_db_sub(&sv, cv);
-       if (!cv)
-           DIE(aTHX_ "No DBsub routine");
+       if (!cv || (!CvXSUB(cv) && !CvSTART(cv)))
+           DIE(aTHX_ "No DB::sub routine defined");
     }
 
     if (!(CvXSUB(cv))) {
@@ -2697,9 +2680,9 @@ PP(pp_entersub)
        dMARK;
        register I32 items = SP - MARK;
        AV* padlist = CvPADLIST(cv);
-       push_return(PL_op->op_next);
        PUSHBLOCK(cx, CXt_SUB, MARK);
        PUSHSUB(cx);
+       cx->blk_sub.retop = PL_op->op_next;
        CvDEPTH(cv)++;
        /* XXX This would be a natural place to set C<PL_compcv = cv> so
         * that eval'' ops within this sub know the correct lexical space.
@@ -2708,7 +2691,7 @@ PP(pp_entersub)
         */
        if (CvDEPTH(cv) >= 2) {
            PERL_STACK_OVERFLOW_CHECK();
-           pad_push(padlist, CvDEPTH(cv), 1);
+           pad_push(padlist, CvDEPTH(cv));
        }
        PAD_SET_CUR(padlist, CvDEPTH(cv));
        if (hasargs)
@@ -2738,13 +2721,13 @@ PP(pp_entersub)
                ary = AvALLOC(av);
                if (AvARRAY(av) != ary) {
                    AvMAX(av) += AvARRAY(av) - AvALLOC(av);
-                   SvPVX(av) = (char*)ary;
+                   SvPV_set(av, (char*)ary);
                }
                if (items > AvMAX(av) + 1) {
                    AvMAX(av) = items - 1;
                    Renew(ary,items,SV*);
                    AvALLOC(av) = ary;
-                   SvPVX(av) = (char*)ary;
+                   SvPV_set(av, (char*)ary);
                }
            }
            Copy(MARK,AvARRAY(av),items,SV*);
@@ -2890,8 +2873,8 @@ PP(pp_aelem)
     SV* elemsv = POPs;
     IV elem = SvIV(elemsv);
     AV* av = (AV*)POPs;
-    U32 lval = PL_op->op_flags & OPf_MOD || LVRET;
-    U32 defer = (PL_op->op_private & OPpLVAL_DEFER) && (elem > AvFILL(av));
+    const U32 lval = PL_op->op_flags & OPf_MOD || LVRET;
+    const U32 defer = (PL_op->op_private & OPpLVAL_DEFER) && (elem > av_len(av));
     SV *sv;
 
     if (SvROK(elemsv) && !SvGAMAGIC(elemsv) && ckWARN(WARN_MISC))
@@ -2906,7 +2889,7 @@ PP(pp_aelem)
         static const char oom_array_extend[] =
              "Out of memory during array extend"; /* Duplicated in av.c */
         if (SvUOK(elemsv)) {
-             UV uv = SvUV(elemsv);
+             const UV uv = SvUV(elemsv);
              elem = uv > IV_MAX ? IV_MAX : uv;
         }
         else if (SvNOK(elemsv))
@@ -2951,19 +2934,20 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
        if (SvTYPE(sv) < SVt_RV)
            sv_upgrade(sv, SVt_RV);
        else if (SvTYPE(sv) >= SVt_PV) {
-           (void)SvOOK_off(sv);
+           SvOOK_off(sv);
            Safefree(SvPVX(sv));
-           SvLEN(sv) = SvCUR(sv) = 0;
+            SvLEN_set(sv, 0);
+           SvCUR_set(sv, 0);
        }
        switch (to_what) {
        case OPpDEREF_SV:
-           SvRV(sv) = NEWSV(355,0);
+           SvRV_set(sv, NEWSV(355,0));
            break;
        case OPpDEREF_AV:
-           SvRV(sv) = (SV*)newAV();
+           SvRV_set(sv, (SV*)newAV());
            break;
        case OPpDEREF_HV:
-           SvRV(sv) = (SV*)newHV();
+           SvRV_set(sv, (SV*)newHV());
            break;
        }
        SvROK_on(sv);
@@ -3005,13 +2989,12 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
     SV* ob;
     GV* gv;
     HV* stash;
-    char* name;
     STRLEN namelen;
-    char* packname = 0;
+    const char* packname = 0;
     SV *packsv = Nullsv;
     STRLEN packlen;
+    const char *name = SvPV(meth, namelen);
 
-    name = SvPV(meth, namelen);
     sv = *(PL_stack_base + TOPMARK + 1);
 
     if (!sv)
@@ -3038,7 +3021,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
 
        if (!SvOK(sv) ||
            !(packname) ||
-           !(iogv = gv_fetchpv(packname, FALSE, SVt_PVIO)) ||
+           !(iogv = gv_fetchsv(sv, FALSE, SVt_PVIO)) ||
            !(ob=(SV*)GvIO(iogv)))
        {
            /* this isn't the name of a filehandle either */
@@ -3102,9 +3085,9 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
           cause UNIVERSAL->can("NoSuchPackage::foo") to croak, and we
           don't want that.
        */
-       char* leaf = name;
-       char* sep = Nullch;
-       char* p;
+       const char* leaf = name;
+       const char* sep = Nullch;
+       const char* p;
 
        for (p = name; *p; p++) {
            if (*p == '\'')
@@ -3143,3 +3126,13 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
     }
     return isGV(gv) ? (SV*)GvCV(gv) : (SV*)gv;
 }
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vim: shiftwidth=4:
+*/