merge changes from maintbranch (1354, and relevant part of 1356); all
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index b81ec56..dc8935b 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -250,9 +250,13 @@ PP(pp_aelemfast)
 {
     djSP;
     AV *av = GvAV((GV*)cSVOP->op_sv);
-    SV** svp = av_fetch(av, op->op_private, op->op_flags & OPf_MOD);
+    U32 lval = op->op_flags & OPf_MOD;
+    SV** svp = av_fetch(av, op->op_private, lval);
+    SV *sv = (svp ? *svp : &sv_undef);
     EXTEND(SP, 1);
-    PUSHs(svp ? *svp : &sv_undef);
+    if (!lval && SvGMAGICAL(sv))       /* see note in pp_helem() */
+       sv = sv_mortalcopy(sv);
+    PUSHs(sv);
     RETURN;
 }
 
@@ -540,7 +544,8 @@ PP(pp_rv2hv)
     }
     else {
        dTARGET;
-       /* This bit is OK even when hv is really an AV */
+       if (SvTYPE(hv) == SVt_PVAV)
+           hv = avhv_keys((AV*)hv);
        if (HvFILL(hv))
            sv_setpvf(TARG, "%ld/%ld",
                      (long)HvFILL(hv), (long)HvMAX(hv) + 1);
@@ -673,7 +678,7 @@ PP(pp_aassign)
        default:
            if (SvTHINKFIRST(sv)) {
                if (SvREADONLY(sv) && curcop != &compiling) {
-                   if (sv != &sv_undef && sv != &sv_yes && sv != &sv_no)
+                   if (!SvIMMORTAL(sv))
                        DIE(no_modify);
                    if (relem <= lastrelem)
                        relem++;
@@ -872,11 +877,11 @@ play_it_again:
            }
            else if (!(s = fbm_instr((unsigned char*)s + rx->check_offset_min,
                                     (unsigned char*)strend, 
-                                    rx->check_substr)))
+                                    rx->check_substr, 0)))
                goto nope;
            else if ((rx->reganch & ROPT_CHECK_ALL) && !sawampersand)
                goto yup;
-           if (s && rx->check_offset_max < t - s) {
+           if (s && rx->check_offset_max < s - t) {
                ++BmUSEFUL(rx->check_substr);
                s -= rx->check_offset_max;
            }
@@ -900,7 +905,7 @@ play_it_again:
            rx->float_substr = Nullsv;
        }
     }
-    if (regexec_flags(rx, s, strend, truebase, minmatch,
+    if (CALLREGEXEC(rx, s, strend, truebase, minmatch,
                      screamer, NULL, safebase))
     {
        curpm = pm;
@@ -913,7 +918,9 @@ play_it_again:
     /*NOTREACHED*/
 
   gotcha:
-    RX_MATCH_TAINTED_SET(rx, rxtainted);
+    if (rxtainted)
+       RX_MATCH_TAINTED_on(rx);
+    TAINT_IF(RX_MATCH_TAINTED(rx));
     if (gimme == G_ARRAY) {
        I32 iters, i, len;
 
@@ -966,7 +973,9 @@ play_it_again:
     }
 
 yup:                                   /* Confirmed by check_substr */
-    RX_MATCH_TAINTED_SET(rx, rxtainted);
+    if (rxtainted)
+       RX_MATCH_TAINTED_on(rx);
+    TAINT_IF(RX_MATCH_TAINTED(rx));
     ++BmUSEFUL(rx->check_substr);
     curpm = pm;
     if (pm->op_pmflags & PMf_ONCE)
@@ -1311,6 +1320,7 @@ PP(pp_helem)
     HV *hv = (HV*)POPs;
     U32 lval = op->op_flags & OPf_MOD;
     U32 defer = op->op_private & OPpLVAL_DEFER;
+    SV *sv;
 
     if (SvTYPE(hv) == SVt_PVHV) {
        he = hv_fetch_ent(hv, keysv, lval && !defer, 0);
@@ -1347,7 +1357,16 @@ PP(pp_helem)
        else if (op->op_private & OPpDEREF)
            vivify_ref(*svp, op->op_private & OPpDEREF);
     }
-    PUSHs(svp ? *svp : &sv_undef);
+    sv = (svp ? *svp : &sv_undef);
+    /* This makes C<local $tied{foo} = $tied{foo}> possible.
+     * Pushing the magical RHS on to the stack is useless, since
+     * that magic is soon destined to be misled by the local(),
+     * and thus the later pp_sassign() will fail to mg_get() the
+     * old value.  This should also cure problems with delayed
+     * mg_get()s.  GSAR 98-07-03 */
+    if (!lval && SvGMAGICAL(sv))
+       sv = sv_mortalcopy(sv);
+    PUSHs(sv);
     RETURN;
 }
 
@@ -1440,7 +1459,14 @@ PP(pp_iter)
        /* integer increment */
        if (cx->blk_loop.iterix > cx->blk_loop.itermax)
            RETPUSHNO;
-       sv_setiv(*cx->blk_loop.itervar, cx->blk_loop.iterix++);
+
+       /* we know that the loop index SV is IV capable, so we can save
+        * some time by doing the essential work of sv_setiv() ourself.
+        */
+       sv = *cx->blk_loop.itervar;
+       (void)SvIOK_only(sv);
+       SvIVX(sv) = cx->blk_loop.iterix++;
+
        RETPUSHYES;
     }
 
@@ -1562,7 +1588,7 @@ PP(pp_subst)
            }
            else if (!(s = fbm_instr((unsigned char*)s + rx->check_offset_min, 
                                     (unsigned char*)strend,
-                                    rx->check_substr)))
+                                    rx->check_substr, 0)))
                goto nope;
            if (s && rx->check_offset_max < s - m) {
                ++BmUSEFUL(rx->check_substr);
@@ -1598,7 +1624,7 @@ PP(pp_subst)
     /* can do inplace substitution? */
     if (c && clen <= rx->minlen && (once || !(safebase & REXEC_COPY_STR))
        && !(rx->reganch & ROPT_LOOKBEHIND_SEEN)) {
-       if (!regexec_flags(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
+       if (!CALLREGEXEC(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
            SPAGAIN;
            PUSHs(&sv_no);
            LEAVE_SCOPE(oldsave);
@@ -1675,7 +1701,7 @@ PP(pp_subst)
                    d += clen;
                }
                s = rx->endp[0];
-           } while (regexec_flags(rx, s, strend, orig, s == m,
+           } while (CALLREGEXEC(rx, s, strend, orig, s == m,
                              Nullsv, NULL, 0)); /* don't match same null twice */
            if (s != d) {
                i = strend - s;
@@ -1698,7 +1724,7 @@ PP(pp_subst)
        RETURN;
     }
 
-    if (regexec_flags(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
+    if (CALLREGEXEC(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
        if (force_on_match) {
            force_on_match = 0;
            s = SvPV_force(TARG, len);
@@ -1732,7 +1758,7 @@ PP(pp_subst)
                sv_catpvn(dstr, c, clen);
            if (once)
                break;
-       } while (regexec_flags(rx, s, strend, orig, s == m, Nullsv, NULL, safebase));
+       } while (CALLREGEXEC(rx, s, strend, orig, s == m, Nullsv, NULL, safebase));
        sv_catpvn(dstr, s, strend - s);
 
        (void)SvOOK_off(TARG);
@@ -2320,6 +2346,7 @@ PP(pp_aelem)
     AV* av = (AV*)POPs;
     U32 lval = op->op_flags & OPf_MOD;
     U32 defer = (op->op_private & OPpLVAL_DEFER) && (elem > AvFILL(av));
+    SV *sv;
 
     if (elem > 0)
        elem -= curcop->cop_arybase;
@@ -2346,7 +2373,10 @@ PP(pp_aelem)
        else if (op->op_private & OPpDEREF)
            vivify_ref(*svp, op->op_private & OPpDEREF);
     }
-    PUSHs(svp ? *svp : &sv_undef);
+    sv = (svp ? *svp : &sv_undef);
+    if (!lval && SvGMAGICAL(sv))       /* see note in pp_helem() */
+       sv = sv_mortalcopy(sv);
+    PUSHs(sv);
     RETURN;
 }
 
@@ -2417,7 +2447,9 @@ PP(pp_method)
            !(ob=(SV*)GvIO(iogv)))
        {
            if (!packname || !isIDFIRST(*packname))
-  DIE("Can't call method \"%s\" without a package or object reference", name);
+               DIE("Can't call method \"%s\" %s", name,
+                   SvOK(sv)? "without a package or object reference"
+                           : "on an undefined value");
            stash = gv_stashpvn(packname, packlen, TRUE);
            goto fetch;
        }