This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Eliminate SVt_RV, and use SVt_IV to store plain references.
[perl5.git] / pp_hot.c
index 71bbb5c..276010c 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -127,15 +127,6 @@ PP(pp_sassign)
        SV * const temp = left;
        left = right; right = temp;
     }
-    else if (PL_op->op_private & OPpASSIGN_STATE) {
-       if (SvPADSTALE(right))
-           SvPADSTALE_off(right);
-       else {
-           (void)POPs;
-           PUSHs(right);
-           RETURN; /* ignore assignment */
-       }
-    }
     if (PL_tainting && PL_tainted && !SvTAINTED(left))
        TAINT_NOT;
     if (PL_op->op_private & OPpASSIGN_CV_TO_GV) {
@@ -159,7 +150,7 @@ PP(pp_sassign)
                   The gv becomes a(nother) reference to the constant.  */
                SV *const value = SvRV(cv);
 
-               SvUPGRADE((SV *)gv, SVt_RV);
+               SvUPGRADE((SV *)gv, SVt_IV);
                SvPCS_IMPORTED_on(gv);
                SvRV_set(gv, value);
                SvREFCNT_inc_simple_void(value);
@@ -177,23 +168,44 @@ PP(pp_sassign)
        if (!got_coderef) {
            /* We've been returned a constant rather than a full subroutine,
               but they expect a subroutine reference to apply.  */
-           ENTER;
-           SvREFCNT_inc_void(SvRV(cv));
-           /* newCONSTSUB takes a reference count on the passed in SV
-              from us.  We set the name to NULL, otherwise we get into
-              all sorts of fun as the reference to our new sub is
-              donated to the GV that we're about to assign to.
-           */
-           SvRV_set(left, (SV *)newCONSTSUB(GvSTASH(right), NULL,
+           if (SvROK(cv)) {
+               ENTER;
+               SvREFCNT_inc_void(SvRV(cv));
+               /* newCONSTSUB takes a reference count on the passed in SV
+                  from us.  We set the name to NULL, otherwise we get into
+                  all sorts of fun as the reference to our new sub is
+                  donated to the GV that we're about to assign to.
+               */
+               SvRV_set(left, (SV *)newCONSTSUB(GvSTASH(right), NULL,
                                                 SvRV(cv)));
-           SvREFCNT_dec(cv);
-           LEAVE;
-       }
+               SvREFCNT_dec(cv);
+               LEAVE;
+           } else {
+               /* What can happen for the corner case *{"BONK"} = \&{"BONK"};
+                  is that
+                  First:   ops for \&{"BONK"}; return us the constant in the
+                           symbol table
+                  Second:  ops for *{"BONK"} cause that symbol table entry
+                           (and our reference to it) to be upgraded from RV
+                           to typeblob)
+                  Thirdly: We get here. cv is actually PVGV now, and its
+                           GvCV() is actually the subroutine we're looking for
 
-       if (strEQ(GvNAME(right),"isa")) {
-           GvCVGEN(right) = 0;
-           ++PL_sub_generation; /* I don't get this at all --blblack */
+                  So change the reference so that it points to the subroutine
+                  of that typeglob, as that's what they were after all along.
+               */
+               GV *const upgraded = (GV *) cv;
+               CV *const source = GvCV(upgraded);
+
+               assert(source);
+               assert(CvFLAGS(source) & CVf_CONST);
+
+               SvREFCNT_inc_void(source);
+               SvREFCNT_dec(upgraded);
+               SvRV_set(left, (SV *)source);
+           }
        }
+
     }
     SvSetMagicSV(right, left);
     SETs(right);
@@ -440,12 +452,13 @@ PP(pp_defined)
                --SP;
             RETURNOP(cLOGOP->op_other);
         }
-    } else if (op_type == OP_DEFINED) {
+    }
+    else {
+       /* OP_DEFINED */
         sv = POPs;
         if (!sv || !SvANY(sv))
             RETPUSHNO;
-    } else
-        DIE(aTHX_ "panic:  Invalid op (%s) in pp_defined()", OP_NAME(PL_op));
+    }
 
     defined = FALSE;
     switch (SvTYPE(sv)) {
@@ -483,8 +496,11 @@ PP(pp_defined)
 
 PP(pp_add)
 {
-    dVAR; dSP; dATARGET; bool useleft; tryAMAGICbin(add,opASSIGN);
-    useleft = USE_LEFT(TOPm1s);
+    dVAR; dSP; dATARGET; bool useleft; SV *svl, *svr;
+    tryAMAGICbin(add,opASSIGN);
+    svl = sv_2num(TOPm1s);
+    svr = sv_2num(TOPs);
+    useleft = USE_LEFT(svl);
 #ifdef PERL_PRESERVE_IVUV
     /* We must see if we can perform the addition with integers if possible,
        as the integer code detects overflow while the NV code doesn't.
@@ -532,8 +548,8 @@ PP(pp_add)
        unsigned code below is actually shorter than the old code. :-)
     */
 
-    SvIV_please(TOPs);
-    if (SvIOK(TOPs)) {
+    SvIV_please(svr);
+    if (SvIOK(svr)) {
        /* Unless the left argument is integer in range we are going to have to
           use NV maths. Hence only attempt to coerce the right argument if
           we know the left is integer.  */
@@ -549,12 +565,12 @@ PP(pp_add)
               lots of code to speed up what is probably a rarish case.  */
        } else {
            /* Left operand is defined, so is it IV? */
-           SvIV_please(TOPm1s);
-           if (SvIOK(TOPm1s)) {
-               if ((auvok = SvUOK(TOPm1s)))
-                   auv = SvUVX(TOPm1s);
+           SvIV_please(svl);
+           if (SvIOK(svl)) {
+               if ((auvok = SvUOK(svl)))
+                   auv = SvUVX(svl);
                else {
-                   register const IV aiv = SvIVX(TOPm1s);
+                   register const IV aiv = SvIVX(svl);
                    if (aiv >= 0) {
                        auv = aiv;
                        auvok = 1;      /* Now acting as a sign flag.  */
@@ -569,12 +585,12 @@ PP(pp_add)
            bool result_good = 0;
            UV result;
            register UV buv;
-           bool buvok = SvUOK(TOPs);
+           bool buvok = SvUOK(svr);
        
            if (buvok)
-               buv = SvUVX(TOPs);
+               buv = SvUVX(svr);
            else {
-               register const IV biv = SvIVX(TOPs);
+               register const IV biv = SvIVX(svr);
                if (biv >= 0) {
                    buv = biv;
                    buvok = 1;
@@ -632,13 +648,14 @@ PP(pp_add)
     }
 #endif
     {
-       dPOPnv;
+       NV value = SvNV(svr);
+       (void)POPs;
        if (!useleft) {
            /* left operand is undef, treat as zero. + 0.0 is identity. */
            SETn(value);
            RETURN;
        }
-       SETn( value + TOPn );
+       SETn( value + SvNV(svl) );
        RETURN;
     }
 }
@@ -972,13 +989,6 @@ PP(pp_aassign)
     int duplicates = 0;
     SV **firsthashrelem = NULL;        /* "= 0" keeps gcc 2.95 quiet  */
 
-    if (PL_op->op_private & OPpASSIGN_STATE) {
-       if (SvPADSTALE(*firstlelem))
-           SvPADSTALE_off(*firstlelem);
-       else
-           RETURN; /* ignore assignment */
-    }
-
     PL_delaymagic = DM_DELAY;          /* catch simultaneous items */
     gimme = GIMME_V;
 
@@ -1025,6 +1035,8 @@ PP(pp_aassign)
                }
                TAINT_NOT;
            }
+           if (PL_delaymagic & DM_ARRAY)
+               SvSETMAGIC((SV*)ary);
            break;
        case SVt_PVHV: {                                /* normal hash */
                SV *tmpstr;
@@ -1171,6 +1183,7 @@ PP(pp_aassign)
        while (relem <= SP)
            *relem++ = (lelem <= lastlelem) ? *lelem++ : &PL_sv_undef;
     }
+
     RETURN;
 }
 
@@ -1179,7 +1192,7 @@ PP(pp_qr)
     dVAR; dSP;
     register PMOP * const pm = cPMOP;
     REGEXP * rx = PM_GETRE(pm);
-    SV * const pkg = CALLREG_QRPKG(rx);
+    SV * const pkg = CALLREG_PACKAGE(rx);
     SV * const rv = sv_newmortal();
     SV * const sv = newSVrv(rv, SvPV_nolen(pkg));
     if (rx->extflags & RXf_TAINTED)
@@ -1277,9 +1290,12 @@ PP(pp_match)
            }
        }
     }
-    /* remove comment to get faster /g but possibly unsafe $1 vars after a
-       match. Test for the unsafe vars will fail as well*/
-    if (( /* !global &&  */ rx->nparens) 
+    /* XXX: comment out !global get safe $1 vars after a
+       match, BUT be aware that this leads to dramatic slowdowns on
+       /g matches against large strings.  So far a solution to this problem
+       appears to be quite tricky.
+       Test for the unsafe vars are TODO for now. */
+    if ((  !global &&  rx->nparens) 
            || SvTEMP(TARG) || PL_sawampersand ||
            (rx->extflags & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY)))
        r_flags |= REXEC_COPY_STR;
@@ -1311,7 +1327,8 @@ play_it_again:
             && !SvROK(TARG))   /* Cannot trust since INTUIT cannot guess ^ */
            goto yup;
     }
-    if (CALLREGEXEC(rx, (char*)s, (char *)strend, (char*)truebase, minmatch, TARG, INT2PTR(void*, gpos), r_flags))
+    if (CALLREGEXEC(rx, (char*)s, (char *)strend, (char*)truebase,
+                    minmatch, TARG, NUM2PTR(void*, gpos), r_flags))
     {
        PL_curpm = pm;
        if (dynpm->op_pmflags & PMf_ONCE) {
@@ -2721,9 +2738,6 @@ try_autoload:
 
     gimme = GIMME_V;
     if ((PL_op->op_private & OPpENTERSUB_DB) && GvCV(PL_DBsub) && !CvNODEBUG(cv)) {
-        if (CvASSERTION(cv) && PL_DBassertion)
-           sv_setiv(PL_DBassertion, 1);
-       
         Perl_get_db_sub(aTHX_ &sv, cv);
         if (CvISXSUB(cv))
             PL_curcopdb = PL_curcop;
@@ -2926,8 +2940,8 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
     if (!SvOK(sv)) {
        if (SvREADONLY(sv))
            Perl_croak(aTHX_ PL_no_modify);
-       if (SvTYPE(sv) < SVt_RV)
-           sv_upgrade(sv, SVt_RV);
+       if (SvTYPE(sv) < SVt_PV && SvTYPE(sv) != SVt_IV)
+           sv_upgrade(sv, SVt_IV);
        else if (SvTYPE(sv) >= SVt_PV) {
            SvPV_free(sv);
             SvLEN_set(sv, 0);
@@ -3030,7 +3044,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
                packsv = sv;
             else {
                SV* const ref = newSViv(PTR2IV(stash));
-               hv_store(PL_stashcache, packname, packlen, ref, 0);
+               (void)hv_store(PL_stashcache, packname, packlen, ref, 0);
            }
            goto fetch;
        }
@@ -3061,7 +3075,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
            gv = (GV*)HeVAL(he);
            if (isGV(gv) && GvCV(gv) &&
                (!GvCVGEN(gv) || GvCVGEN(gv)
-                  == (PL_sub_generation + HvMROMETA(stash)->sub_generation)))
+                  == (PL_sub_generation + HvMROMETA(stash)->cache_gen)))
                return (SV*)GvCV(gv);
        }
     }
@@ -3088,16 +3102,24 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
        }
        if (!sep || ((sep - name) == 5 && strnEQ(name, "SUPER", 5))) {
            /* the method name is unqualified or starts with SUPER:: */
+#ifndef USE_ITHREADS
+           if (sep)
+               stash = CopSTASH(PL_curcop);
+#else
            bool need_strlen = 1;
            if (sep) {
                packname = CopSTASHPV(PL_curcop);
            }
-           else if (stash) {
+           else
+#endif
+           if (stash) {
                HEK * const packhek = HvNAME_HEK(stash);
                if (packhek) {
                    packname = HEK_KEY(packhek);
                    packlen = HEK_LEN(packhek);
+#ifdef USE_ITHREADS
                    need_strlen = 0;
+#endif
                } else {
                    goto croak;
                }
@@ -3108,8 +3130,10 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
                Perl_croak(aTHX_
                           "Can't use anonymous symbol table for method lookup");
            }
-           else if (need_strlen)
+#ifdef USE_ITHREADS
+           if (need_strlen)
                packlen = strlen(packname);
+#endif
 
        }
        else {