Re: [PATCH for _66] Makefile.SH problem on dos/djgpp
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index 702e447..dd5ef14 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -251,6 +251,7 @@ PP(pp_aelemfast)
     djSP;
     AV *av = GvAV((GV*)cSVOP->op_sv);
     SV** svp = av_fetch(av, op->op_private, op->op_flags & OPf_MOD);
+    EXTEND(SP, 1);
     PUSHs(svp ? *svp : &sv_undef);
     RETURN;
 }
@@ -644,8 +645,15 @@ PP(pp_aassign)
                    }
                    TAINT_NOT;
                }
-               if (relem == lastrelem && dowarn)
-                   warn("Odd number of elements in hash list");
+               if (relem == lastrelem && dowarn) {
+                   if (relem == firstrelem &&
+                       SvROK(*relem) &&
+                       ( SvTYPE(SvRV(*relem)) == SVt_PVAV ||
+                         SvTYPE(SvRV(*relem)) == SVt_PVHV ) )
+                       warn("Reference found where even-sized list expected");
+                   else
+                       warn("Odd number of elements in hash assignment");
+               }
            }
            break;
        default:
@@ -763,7 +771,7 @@ PP(pp_match)
     I32 global;
     I32 safebase;
     char *truebase;
-    register REGEXP *prx = pm->op_pmregexp;
+    register REGEXP *rx = pm->op_pmregexp;
     I32 gimme = GIMME;
     STRLEN len;
     I32 minmatch = 0;
@@ -784,38 +792,38 @@ PP(pp_match)
        DIE("panic: do_match");
     TAINT_NOT;
 
-    if (pm->op_pmflags & PMf_USED) {
+    if (pm->op_pmdynflags & PMdf_USED) {
       failure:
        if (gimme == G_ARRAY)
            RETURN;
        RETPUSHNO;
     }
 
-    if (!prx->prelen && curpm) {
+    if (!rx->prelen && curpm) {
        pm = curpm;
-       prx = pm->op_pmregexp;
+       rx = pm->op_pmregexp;
     }
-    if (prx->minlen > len) goto failure;
+    if (rx->minlen > len) goto failure;
 
-    screamer = ( (SvSCREAM(TARG) && prx->check_substr
-                 && SvTYPE(prx->check_substr) == SVt_PVBM
-                 && SvVALID(prx->check_substr)) 
+    screamer = ( (SvSCREAM(TARG) && rx->check_substr
+                 && SvTYPE(rx->check_substr) == SVt_PVBM
+                 && SvVALID(rx->check_substr)) 
                ? TARG : Nullsv);
     truebase = t = s;
     if (global = pm->op_pmflags & PMf_GLOBAL) {
-       prx->startp[0] = 0;
+       rx->startp[0] = 0;
        if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
            MAGIC* mg = mg_find(TARG, 'g');
            if (mg && mg->mg_len >= 0) {
-               prx->endp[0] = prx->startp[0] = s + mg->mg_len; 
+               rx->endp[0] = rx->startp[0] = s + mg->mg_len; 
                minmatch = (mg->mg_flags & MGf_MINMATCH);
                update_minmatch = 0;
            }
        }
     }
-    if (!prx->nparens && !global)
+    if (!rx->nparens && !global)
        gimme = G_SCALAR;                       /* accidental array context? */
-    safebase = (((gimme == G_ARRAY) || global || !prx->nparens)
+    safebase = (((gimme == G_ARRAY) || global || !rx->nparens)
                && !sawampersand);
     safebase = safebase ? 0  : REXEC_COPY_STR ;
     if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
@@ -824,36 +832,36 @@ PP(pp_match)
     }
 
 play_it_again:
-    if (global && prx->startp[0]) {
-       t = s = prx->endp[0];
-       if ((s + prx->minlen) > strend)
+    if (global && rx->startp[0]) {
+       t = s = rx->endp[0];
+       if ((s + rx->minlen) > strend)
            goto nope;
        if (update_minmatch++)
-           minmatch = (s == prx->startp[0]);
+           minmatch = (s == rx->startp[0]);
     }
-    if (prx->check_substr) {
-       if (!(prx->reganch & ROPT_NOSCAN)) { /* Floating checkstring. */
+    if (rx->check_substr) {
+       if (!(rx->reganch & ROPT_NOSCAN)) { /* Floating checkstring. */
            if ( screamer ) {
                I32 p = -1;
                
-               if (screamfirst[BmRARE(prx->check_substr)] < 0)
+               if (screamfirst[BmRARE(rx->check_substr)] < 0)
                    goto nope;
-               else if (!(s = screaminstr(TARG, prx->check_substr, 
-                                          prx->check_offset_min, 0, &p, 0)))
+               else if (!(s = screaminstr(TARG, rx->check_substr, 
+                                          rx->check_offset_min, 0, &p, 0)))
                    goto nope;
-               else if ((prx->reganch & ROPT_CHECK_ALL)
-                        && !sawampersand && !SvTAIL(prx->check_substr))
+               else if ((rx->reganch & ROPT_CHECK_ALL)
+                        && !sawampersand && !SvTAIL(rx->check_substr))
                    goto yup;
            }
-           else if (!(s = fbm_instr((unsigned char*)s + prx->check_offset_min,
+           else if (!(s = fbm_instr((unsigned char*)s + rx->check_offset_min,
                                     (unsigned char*)strend, 
-                                    prx->check_substr)))
+                                    rx->check_substr)))
                goto nope;
-           else if ((prx->reganch & ROPT_CHECK_ALL) && !sawampersand)
+           else if ((rx->reganch & ROPT_CHECK_ALL) && !sawampersand)
                goto yup;
-           if (s && prx->check_offset_max < t - s) {
-               ++BmUSEFUL(prx->check_substr);
-               s -= prx->check_offset_max;
+           if (s && rx->check_offset_max < t - s) {
+               ++BmUSEFUL(rx->check_substr);
+               s -= rx->check_offset_max;
            }
            else
                s = t;
@@ -862,25 +870,25 @@ play_it_again:
           beginning of match, and the match is anchored at s. */
        else if (!multiline) {  /* Anchored near beginning of string. */
            I32 slen;
-           if (*SvPVX(prx->check_substr) != s[prx->check_offset_min]
-               || ((slen = SvCUR(prx->check_substr)) > 1
-                   && memNE(SvPVX(prx->check_substr), 
-                            s + prx->check_offset_min, slen)))
+           if (*SvPVX(rx->check_substr) != s[rx->check_offset_min]
+               || ((slen = SvCUR(rx->check_substr)) > 1
+                   && memNE(SvPVX(rx->check_substr), 
+                            s + rx->check_offset_min, slen)))
                goto nope;
        }
-       if (!prx->naughty && --BmUSEFUL(prx->check_substr) < 0
-           && prx->check_substr == prx->float_substr) {
-           SvREFCNT_dec(prx->check_substr);
-           prx->check_substr = Nullsv; /* opt is being useless */
-           prx->float_substr = Nullsv;
+       if (!rx->naughty && --BmUSEFUL(rx->check_substr) < 0
+           && rx->check_substr == rx->float_substr) {
+           SvREFCNT_dec(rx->check_substr);
+           rx->check_substr = Nullsv;  /* opt is being useless */
+           rx->float_substr = Nullsv;
        }
     }
-    if (regexec_flags(prx, s, strend, truebase, minmatch,
+    if (regexec_flags(rx, s, strend, truebase, minmatch,
                      screamer, NULL, safebase))
     {
        curpm = pm;
        if (pm->op_pmflags & PMf_ONCE)
-           pm->op_pmflags |= PMf_USED;
+           pm->op_pmdynflags |= PMdf_USED;
        goto gotcha;
     }
     else
@@ -888,11 +896,11 @@ play_it_again:
     /*NOTREACHED*/
 
   gotcha:
-    TAINT_IF(RX_MATCH_TAINTED(prx));
+    TAINT_IF(RX_MATCH_TAINTED(rx));
     if (gimme == G_ARRAY) {
        I32 iters, i, len;
 
-       iters = prx->nparens;
+       iters = rx->nparens;
        if (global && !iters)
            i = 1;
        else
@@ -903,16 +911,16 @@ play_it_again:
        for (i = !i; i <= iters; i++) {
            PUSHs(sv_newmortal());
            /*SUPPRESS 560*/
-           if ((s = prx->startp[i]) && prx->endp[i] ) {
-               len = prx->endp[i] - s;
+           if ((s = rx->startp[i]) && rx->endp[i] ) {
+               len = rx->endp[i] - s;
                sv_setpvn(*SP, s, len);
            }
        }
        if (global) {
-           truebase = prx->subbeg;
-           strend = prx->subend;
-           if (prx->startp[0] && prx->startp[0] == prx->endp[0])
-               ++prx->endp[0];
+           truebase = rx->subbeg;
+           strend = rx->subend;
+           if (rx->startp[0] && rx->startp[0] == rx->endp[0])
+               ++rx->endp[0];
            PUTBACK;                    /* EVAL blocks may use stack */
            goto play_it_again;
        }
@@ -928,9 +936,9 @@ play_it_again:
                sv_magic(TARG, (SV*)0, 'g', Nullch, 0);
                mg = mg_find(TARG, 'g');
            }
-           if (prx->startp[0]) {
-               mg->mg_len = prx->endp[0] - prx->subbeg;
-               if (prx->startp[0] == prx->endp[0])
+           if (rx->startp[0]) {
+               mg->mg_len = rx->endp[0] - rx->subbeg;
+               if (rx->startp[0] == rx->endp[0])
                    mg->mg_flags |= MGf_MINMATCH;
                else
                    mg->mg_flags &= ~MGf_MINMATCH;
@@ -941,35 +949,35 @@ play_it_again:
     }
 
 yup:                                   /* Confirmed by check_substr */
-    TAINT_IF(RX_MATCH_TAINTED(prx));
-    ++BmUSEFUL(prx->check_substr);
+    TAINT_IF(RX_MATCH_TAINTED(rx));
+    ++BmUSEFUL(rx->check_substr);
     curpm = pm;
     if (pm->op_pmflags & PMf_ONCE)
-       pm->op_pmflags |= PMf_USED;
-    Safefree(prx->subbase);
-    prx->subbase = Nullch;
+       pm->op_pmdynflags |= PMdf_USED;
+    Safefree(rx->subbase);
+    rx->subbase = Nullch;
     if (global) {
-       prx->subbeg = truebase;
-       prx->subend = strend;
-       prx->startp[0] = s;
-       prx->endp[0] = s + SvCUR(prx->check_substr);
+       rx->subbeg = truebase;
+       rx->subend = strend;
+       rx->startp[0] = s;
+       rx->endp[0] = s + SvCUR(rx->check_substr);
        goto gotcha;
     }
     if (sawampersand) {
        char *tmps;
 
-       tmps = prx->subbase = savepvn(t, strend-t);
-       prx->subbeg = tmps;
-       prx->subend = tmps + (strend-t);
-       tmps = prx->startp[0] = tmps + (s - t);
-       prx->endp[0] = tmps + SvCUR(prx->check_substr);
+       tmps = rx->subbase = savepvn(t, strend-t);
+       rx->subbeg = tmps;
+       rx->subend = tmps + (strend-t);
+       tmps = rx->startp[0] = tmps + (s - t);
+       rx->endp[0] = tmps + SvCUR(rx->check_substr);
     }
     LEAVE_SCOPE(oldsave);
     RETPUSHYES;
 
 nope:
-    if (prx->check_substr)
-       ++BmUSEFUL(prx->check_substr);
+    if (rx->check_substr)
+       ++BmUSEFUL(rx->check_substr);
 
 ret_no:
     if (global && !(pm->op_pmflags & PMf_CONTINUE)) {
@@ -1019,8 +1027,11 @@ do_readline(void)
                    IoFLAGS(io) &= ~IOf_START;
                    IoLINES(io) = 0;
                    if (av_len(GvAVn(last_in_gv)) < 0) {
-                       SV *tmpstr = newSVpv("-", 1); /* assume stdin */
-                       av_push(GvAVn(last_in_gv), tmpstr);
+                       do_open(last_in_gv,"-",1,FALSE,0,0,Nullfp);
+                       sv_setpvn(GvSV(last_in_gv), "-", 1);
+                       SvSETMAGIC(GvSV(last_in_gv));
+                       fp = IoIFP(io);
+                       goto have_fp;
                    }
                }
                fp = nextargv(last_in_gv);
@@ -1077,7 +1088,10 @@ do_readline(void)
                       }
                    }
                    if ((tmpfp = PerlIO_open(tmpfnam,"w+","fop=dlt")) != NULL) {
-                       ok = ((wilddsc.dsc$a_pointer = tovmsspec(SvPVX(tmpglob),vmsspec)) != NULL);
+                       Stat_t st;
+                       if (!PerlLIO_stat(SvPVX(tmpglob),&st) && S_ISDIR(st.st_mode))
+                         ok = ((wilddsc.dsc$a_pointer = tovmspath(SvPVX(tmpglob),vmsspec)) != NULL);
+                       else ok = ((wilddsc.dsc$a_pointer = tovmsspec(SvPVX(tmpglob),vmsspec)) != NULL);
                        if (ok) wilddsc.dsc$w_length = (unsigned short int) strlen(wilddsc.dsc$a_pointer);
                        while (ok && ((sts = lib$find_file(&wilddsc,&rsdsc,&cxt,
                                                    &dfltdsc,NULL,NULL,NULL))&1)) {
@@ -1165,6 +1179,7 @@ do_readline(void)
        }
        RETURN;
     }
+  have_fp:
     if (gimme == G_SCALAR) {
        sv = TARG;
        if (SvROK(sv))
@@ -1442,7 +1457,7 @@ PP(pp_subst)
     bool rxtainted;
     char *orig;
     I32 safebase;
-    register REGEXP *prx = pm->op_pmregexp;
+    register REGEXP *rx = pm->op_pmregexp;
     STRLEN len;
     int force_on_match = 0;
     I32 oldsave = savestack_ix;
@@ -1466,6 +1481,7 @@ PP(pp_subst)
     s = SvPV(TARG, len);
     if (!SvPOKp(TARG) || SvTYPE(TARG) == SVt_PVGV)
        force_on_match = 1;
+    rxtainted = tainted << 1;
     TAINT_NOT;
 
   force_it:
@@ -1475,37 +1491,37 @@ PP(pp_subst)
     strend = s + len;
     maxiters = (strend - s) + 10;
 
-    if (!prx->prelen && curpm) {
+    if (!rx->prelen && curpm) {
        pm = curpm;
-       prx = pm->op_pmregexp;
+       rx = pm->op_pmregexp;
     }
-    screamer = ( (SvSCREAM(TARG) && prx->check_substr
-                 && SvTYPE(prx->check_substr) == SVt_PVBM
-                 && SvVALID(prx->check_substr)) 
+    screamer = ( (SvSCREAM(TARG) && rx->check_substr
+                 && SvTYPE(rx->check_substr) == SVt_PVBM
+                 && SvVALID(rx->check_substr)) 
                ? TARG : Nullsv);
-    safebase = (!prx->nparens && !sawampersand) ? 0 : REXEC_COPY_STR;
+    safebase = (!rx->nparens && !sawampersand) ? 0 : REXEC_COPY_STR;
     if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
        SAVEINT(multiline);
        multiline = pm->op_pmflags & PMf_MULTILINE;
     }
     orig = m = s;
-    if (prx->check_substr) {
-       if (!(prx->reganch & ROPT_NOSCAN)) { /* It floats. */
+    if (rx->check_substr) {
+       if (!(rx->reganch & ROPT_NOSCAN)) { /* It floats. */
            if (screamer) {
                I32 p = -1;
                
-               if (screamfirst[BmRARE(prx->check_substr)] < 0)
+               if (screamfirst[BmRARE(rx->check_substr)] < 0)
                    goto nope;
-               else if (!(s = screaminstr(TARG, prx->check_substr, prx->check_offset_min, 0, &p, 0)))
+               else if (!(s = screaminstr(TARG, rx->check_substr, rx->check_offset_min, 0, &p, 0)))
                    goto nope;
            }
-           else if (!(s = fbm_instr((unsigned char*)s + prx->check_offset_min, 
+           else if (!(s = fbm_instr((unsigned char*)s + rx->check_offset_min, 
                                     (unsigned char*)strend,
-                                    prx->check_substr)))
+                                    rx->check_substr)))
                goto nope;
-           if (s && prx->check_offset_max < s - m) {
-               ++BmUSEFUL(prx->check_substr);
-               s -= prx->check_offset_max;
+           if (s && rx->check_offset_max < s - m) {
+               ++BmUSEFUL(rx->check_substr);
+               s -= rx->check_offset_max;
            }
            else
                s = m;
@@ -1514,17 +1530,17 @@ PP(pp_subst)
           beginning of match, and the match is anchored at s. */
        else if (!multiline) { /* Anchored at beginning of string. */
            I32 slen;
-           if (*SvPVX(prx->check_substr) != s[prx->check_offset_min]
-               || ((slen = SvCUR(prx->check_substr)) > 1
-                   && memNE(SvPVX(prx->check_substr), 
-                            s + prx->check_offset_min, slen)))
+           if (*SvPVX(rx->check_substr) != s[rx->check_offset_min]
+               || ((slen = SvCUR(rx->check_substr)) > 1
+                   && memNE(SvPVX(rx->check_substr), 
+                            s + rx->check_offset_min, slen)))
                goto nope;
        }
-       if (!prx->naughty && --BmUSEFUL(prx->check_substr) < 0
-           && prx->check_substr == prx->float_substr) {
-           SvREFCNT_dec(prx->check_substr);
-           prx->check_substr = Nullsv; /* opt is being useless */
-           prx->float_substr = Nullsv;
+       if (!rx->naughty && --BmUSEFUL(rx->check_substr) < 0
+           && rx->check_substr == rx->float_substr) {
+           SvREFCNT_dec(rx->check_substr);
+           rx->check_substr = Nullsv;  /* opt is being useless */
+           rx->float_substr = Nullsv;
        }
     }
 
@@ -1535,9 +1551,9 @@ PP(pp_subst)
     c = dstr ? SvPV(dstr, clen) : Nullch;
 
     /* can do inplace substitution? */
-    if (c && clen <= prx->minlen && (once || !(safebase & REXEC_COPY_STR))
-       && !(prx->reganch & ROPT_LOOKBEHIND_SEEN)) {
-       if (!regexec_flags(prx, s, strend, orig, 0, screamer, NULL, safebase)) {
+    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)) {
            SPAGAIN;
            PUSHs(&sv_no);
            LEAVE_SCOPE(oldsave);
@@ -1552,13 +1568,13 @@ PP(pp_subst)
        curpm = pm;
        SvSCREAM_off(TARG);     /* disable possible screamer */
        if (once) {
-           rxtainted = RX_MATCH_TAINTED(prx);
-           if (prx->subbase) {
-               m = orig + (prx->startp[0] - prx->subbase);
-               d = orig + (prx->endp[0] - prx->subbase);
+           rxtainted |= RX_MATCH_TAINTED(rx);
+           if (rx->subbase) {
+               m = orig + (rx->startp[0] - rx->subbase);
+               d = orig + (rx->endp[0] - rx->subbase);
            } else {
-               m = prx->startp[0];
-               d = prx->endp[0];
+               m = rx->startp[0];
+               d = rx->endp[0];
            }
            s = orig;
            if (m - s > strend - d) {  /* faster to shorten from end */
@@ -1593,17 +1609,16 @@ PP(pp_subst)
            else {
                sv_chop(TARG, d);
            }
-           TAINT_IF(rxtainted);
+           TAINT_IF(rxtainted & 1);
            SPAGAIN;
            PUSHs(&sv_yes);
        }
        else {
-           rxtainted = 0;
            do {
                if (iters++ > maxiters)
                    DIE("Substitution loop");
-               rxtainted |= RX_MATCH_TAINTED(prx);
-               m = prx->startp[0];
+               rxtainted |= RX_MATCH_TAINTED(rx);
+               m = rx->startp[0];
                /*SUPPRESS 560*/
                if (i = m - s) {
                    if (s != d)
@@ -1614,19 +1629,20 @@ PP(pp_subst)
                    Copy(c, d, clen, char);
                    d += clen;
                }
-               s = prx->endp[0];
-           } while (regexec_flags(prx, s, strend, orig, s == m,
+               s = rx->endp[0];
+           } while (regexec_flags(rx, s, strend, orig, s == m,
                              Nullsv, NULL, 0)); /* don't match same null twice */
            if (s != d) {
                i = strend - s;
                SvCUR_set(TARG, d - SvPVX(TARG) + i);
                Move(s, d, i+1, char);          /* include the NUL */
            }
-           TAINT_IF(rxtainted);
+           TAINT_IF(rxtainted & 1);
            SPAGAIN;
            PUSHs(sv_2mortal(newSViv((I32)iters)));
        }
        (void)SvPOK_only(TARG);
+       TAINT_IF(rxtainted);
        if (SvSMAGICAL(TARG)) {
            PUTBACK;
            mg_set(TARG);
@@ -1637,13 +1653,13 @@ PP(pp_subst)
        RETURN;
     }
 
-    if (regexec_flags(prx, s, strend, orig, 0, screamer, NULL, safebase)) {
+    if (regexec_flags(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
        if (force_on_match) {
            force_on_match = 0;
            s = SvPV_force(TARG, len);
            goto force_it;
        }
-       rxtainted = RX_MATCH_TAINTED(prx);
+       rxtainted |= RX_MATCH_TAINTED(rx);
        dstr = NEWSV(25, len);
        sv_setpvn(dstr, m, s-m);
        curpm = pm;
@@ -1656,26 +1672,24 @@ PP(pp_subst)
        do {
            if (iters++ > maxiters)
                DIE("Substitution loop");
-           rxtainted |= RX_MATCH_TAINTED(prx);
-           if (prx->subbase && prx->subbase != orig) {
+           rxtainted |= RX_MATCH_TAINTED(rx);
+           if (rx->subbase && rx->subbase != orig) {
                m = s;
                s = orig;
-               orig = prx->subbase;
+               orig = rx->subbase;
                s = orig + (m - s);
                strend = s + (strend - m);
            }
-           m = prx->startp[0];
+           m = rx->startp[0];
            sv_catpvn(dstr, s, m-s);
-           s = prx->endp[0];
+           s = rx->endp[0];
            if (clen)
                sv_catpvn(dstr, c, clen);
            if (once)
                break;
-       } while (regexec_flags(prx, s, strend, orig, s == m, Nullsv, NULL, safebase));
+       } while (regexec_flags(rx, s, strend, orig, s == m, Nullsv, NULL, safebase));
        sv_catpvn(dstr, s, strend - s);
 
-       TAINT_IF(rxtainted);
-
        (void)SvOOK_off(TARG);
        Safefree(SvPVX(TARG));
        SvPVX(TARG) = SvPVX(dstr);
@@ -1684,18 +1698,21 @@ PP(pp_subst)
        SvPVX(dstr) = 0;
        sv_free(dstr);
 
+       TAINT_IF(rxtainted & 1);
+       SPAGAIN;
+       PUSHs(sv_2mortal(newSViv((I32)iters)));
+
        (void)SvPOK_only(TARG);
+       TAINT_IF(rxtainted);
        SvSETMAGIC(TARG);
        SvTAINT(TARG);
-       SPAGAIN;
-       PUSHs(sv_2mortal(newSViv((I32)iters)));
        LEAVE_SCOPE(oldsave);
        RETURN;
     }
     goto ret_no;
 
 nope:
-    ++BmUSEFUL(prx->check_substr);
+    ++BmUSEFUL(rx->check_substr);
 
 ret_no:         
     SPAGAIN;
@@ -1761,9 +1778,19 @@ PP(pp_leavesub)
     TAINT_NOT;
     if (gimme == G_SCALAR) {
        MARK = newsp + 1;
-       if (MARK <= SP)
-           *MARK = SvTEMP(TOPs) ? TOPs : sv_mortalcopy(TOPs);
-       else {
+       if (MARK <= SP) {
+           if (cxsub.cv && CvDEPTH(cxsub.cv) > 1) {
+               if (SvTEMP(TOPs)) {
+                   *MARK = SvREFCNT_inc(TOPs);
+                   FREETMPS;
+                   sv_2mortal(*MARK);
+               } else {
+                   FREETMPS;
+                   *MARK = sv_mortalcopy(TOPs);
+               }
+           } else
+               *MARK = SvTEMP(TOPs) ? TOPs : sv_mortalcopy(TOPs);
+       } else {
            MEXTEND(MARK, 0);
            *MARK = &sv_undef;
        }
@@ -1790,27 +1817,35 @@ STATIC CV *
 get_db_sub(SV **svp, CV *cv)
 {
     dTHR;
-    SV *oldsv = *svp;
-    GV *gv;
+    SV *dbsv = GvSV(DBsub);
+
+    if (!PERLDB_SUB_NN) {
+       GV *gv = CvGV(cv);
 
-    *svp = GvSV(DBsub);
-    save_item(*svp);
-    gv = CvGV(cv);
-    if ( (CvFLAGS(cv) & (CVf_ANON | CVf_CLONED))
-        || strEQ(GvNAME(gv), "END") 
-        || ((GvCV(gv) != cv) && /* Could be imported, and old sub redefined. */
-            !( (SvTYPE(oldsv) == SVt_PVGV) && (GvCV((GV*)oldsv) == cv)
-               && (gv = (GV*)oldsv) ))) {
-       /* Use GV from the stack as a fallback. */
-       /* GV is potentially non-unique, or contain different CV. */
-       sv_setsv(*svp, newRV((SV*)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. */
+                !( (SvTYPE(*svp) == SVt_PVGV) && (GvCV((GV*)*svp) == cv)
+                   && (gv = (GV*)*svp) ))) {
+           /* Use GV from the stack as a fallback. */
+           /* GV is potentially non-unique, or contain different CV. */
+           sv_setsv(dbsv, newRV((SV*)cv));
+       }
+       else {
+           gv_efullname3(dbsv, gv, Nullch);
+       }
     }
     else {
-       gv_efullname3(*svp, gv, Nullch);
+       SvUPGRADE(dbsv, SVt_PVIV);
+       SvIOK_on(dbsv);
+       SAVEIV(SvIVX(dbsv));
+       SvIVX(dbsv) = (IV)cv;           /* Do it the quickest way  */
     }
-    cv = GvCV(DBsub);
+
     if (CvXSUB(cv))
        curcopdb = curcop;
+    cv = GvCV(DBsub);
     return cv;
 }
 
@@ -1979,8 +2014,9 @@ PP(pp_entersub)
         * (3) instead of (2) so we'd have to clone. Would the fact
         * that we released the mutex more quickly make up for this?
         */
-       svp = hv_fetch(thr->cvcache, (char *)cv, sizeof(cv), FALSE);
-       if (svp) {
+       if (threadnum &&
+           (svp = hv_fetch(thr->cvcache, (char *)cv, sizeof(cv), FALSE)))
+       {
            /* We already have a clone to use */
            MUTEX_UNLOCK(CvMUTEXP(cv));
            cv = *(CV**)svp;
@@ -2083,7 +2119,7 @@ PP(pp_entersub)
                curcopdb = NULL;
            }
            /* Do we need to open block here? XXXX */
-           (void)(*CvXSUB(cv))(THIS_ cv);
+           (void)(*CvXSUB(cv))(cv _PERL_OBJECT_THIS);
 
            /* Enforce some sanity in scalar context. */
            if (gimme == G_SCALAR && ++markix != stack_sp - stack_base ) {