Resync with mainline
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index e3969be..eb05228 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1,6 +1,6 @@
 /*    pp.c
  *
- *    Copyright (c) 1991-1999, Larry Wall
+ *    Copyright (c) 1991-2000, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -47,7 +47,7 @@ typedef unsigned UBW;
  * have an integral type (except char) small enough to be represented
  * in a double without loss; that is, it has no 32-bit type.
  */
-#if LONGSIZE > 4  && defined(_CRAY) && !defined(_CRAYMPP)
+#if LONGSIZE > 4  && defined(_CRAY)
 #  define BW_BITS  32
 #  define BW_MASK  ((1 << BW_BITS) - 1)
 #  define BW_SIGN  (1 << (BW_BITS - 1))
@@ -86,7 +86,7 @@ typedef unsigned UBW;
 #   define PERL_NATINT_PACK
 #endif
 
-#if BYTEORDER > 0xFFFF && defined(_CRAY) && !defined(_CRAYMPP)
+#if LONGSIZE > 4 && defined(_CRAY)
 #  if BYTEORDER == 0x12345678
 #    define OFF16(p)   (char*)(p)
 #    define OFF32(p)   (char*)(p)
@@ -241,25 +241,30 @@ PP(pp_rv2gv)
                 * NI-S 1999/05/07
                 */ 
                if (PL_op->op_private & OPpDEREF) {
-                   GV *gv = (GV *) newSV(0);
-                   STRLEN len = 0;
-                   char *name = "";
-                   if (cUNOP->op_first->op_type == OP_PADSV) {
-                       SV *padname = *av_fetch(PL_comppad_name, cUNOP->op_first->op_targ, 4);
-                       name = SvPV(padname,len);                                                    
+                   char *name;
+                   GV *gv;
+                   if (cUNOP->op_targ) {
+                       STRLEN len;
+                       SV *namesv = PL_curpad[cUNOP->op_targ];
+                       name = SvPV(namesv, len);
+                       gv = (GV*)NEWSV(0,0);
+                       gv_init(gv, CopSTASH(PL_curcop), name, len, 0);
+                   }
+                   else {
+                       name = CopSTASHPV(PL_curcop);
+                       gv = newGVgen(name);
                    }
-                   gv_init(gv, PL_curcop->cop_stash, name, len, 0);
                    sv_upgrade(sv, SVt_RV);
-                   SvRV(sv) = (SV *) gv;
+                   SvRV(sv) = (SV*)gv;
                    SvROK_on(sv);
                    SvSETMAGIC(sv);
                    goto wasref;
-               }  
+               }
                if (PL_op->op_flags & OPf_REF ||
                    PL_op->op_private & HINT_STRICT_REFS)
                    DIE(aTHX_ PL_no_usym, "a symbol");
                if (ckWARN(WARN_UNINITIALIZED))
-                   Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit);
+                   report_uninit();
                RETSETUNDEF;
            }
            sym = SvPV(sv, n_a);
@@ -315,7 +320,7 @@ PP(pp_rv2sv)
                    PL_op->op_private & HINT_STRICT_REFS)
                    DIE(aTHX_ PL_no_usym, "a SCALAR");
                if (ckWARN(WARN_UNINITIALIZED))
-                   Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit);
+                   report_uninit();
                RETSETUNDEF;
            }
            sym = SvPV(sv, n_a);
@@ -384,7 +389,7 @@ PP(pp_pos)
            mg = mg_find(sv, 'g');
            if (mg && mg->mg_len >= 0) {
                I32 i = mg->mg_len;
-               if (IN_UTF8)
+               if (DO_UTF8(sv))
                    sv_pos_b2u(sv, &i);
                PUSHi(i + PL_curcop->cop_arybase);
                RETURN;
@@ -406,6 +411,8 @@ PP(pp_rv2cv)
     if (cv) {
        if (CvCLONE(cv))
            cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
+       if ((PL_op->op_private & OPpLVAL_INTRO) && !CvLVALUE(cv))
+           DIE(aTHX_ "Can't modify non-lvalue subroutine call");
     }
     else
        cv = (CV*)&PL_sv_undef;
@@ -467,7 +474,7 @@ PP(pp_prototype)
                goto set;
            else {                      /* None such */
              nonesuch:
-               Perl_croak(aTHX_ "Can't find an opnumber for \"%s\"", s+6);
+               DIE(aTHX_ "Can't find an opnumber for \"%s\"", s+6);
            }
        }
     }
@@ -528,6 +535,12 @@ S_refto(pTHX_ SV *sv)
        else
            (void)SvREFCNT_inc(sv);
     }
+    else if (SvTYPE(sv) == SVt_PVAV) {
+       if (!AvREAL((AV*)sv) && AvREIFY((AV*)sv))
+           av_reify((AV*)sv);
+       SvTEMP_off(sv);
+       (void)SvREFCNT_inc(sv);
+    }
     else if (SvPADTMP(sv))
        sv = newSVsv(sv);
     else {
@@ -567,7 +580,7 @@ PP(pp_bless)
     HV *stash;
 
     if (MAXARG == 1)
-       stash = PL_curcop->cop_stash;
+       stash = CopSTASH(PL_curcop);
     else {
        SV *ssv = POPs;
        STRLEN len;
@@ -840,7 +853,7 @@ PP(pp_undef)
            Newz(602, gp, 1, GP);
            GvGP(sv) = gp_ref(gp);
            GvSV(sv) = NEWSV(72,0);
-           GvLINE(sv) = PL_curcop->cop_line;
+           GvLINE(sv) = CopLINE(PL_curcop);
            GvEGV(sv) = (GV*)sv;
            GvMULTI_on(sv);
        }
@@ -863,7 +876,7 @@ PP(pp_predec)
 {
     djSP;
     if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
-       Perl_croak(aTHX_ PL_no_modify);
+       DIE(aTHX_ PL_no_modify);
     if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
        SvIVX(TOPs) != IV_MIN)
     {
@@ -880,7 +893,7 @@ PP(pp_postinc)
 {
     djSP; dTARGET;
     if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
-       Perl_croak(aTHX_ PL_no_modify);
+       DIE(aTHX_ PL_no_modify);
     sv_setsv(TARG, TOPs);
     if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
        SvIVX(TOPs) != IV_MAX)
@@ -901,7 +914,7 @@ PP(pp_postdec)
 {
     djSP; dTARGET;
     if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
-       Perl_croak(aTHX_ PL_no_modify);
+       DIE(aTHX_ PL_no_modify);
     sv_setsv(TARG, TOPs);
     if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
        SvIVX(TOPs) != IV_MIN)
@@ -1413,7 +1426,7 @@ PP(pp_negate)
                sv_setsv(TARG, sv);
                *SvPV_force(TARG, len) = *s == '-' ? '+' : '-';
            }
-           else if (IN_UTF8 && *(U8*)s >= 0xc0 && isIDFIRST_utf8((U8*)s)) {
+           else if (DO_UTF8(sv) && *(U8*)s >= 0xc0 && isIDFIRST_utf8((U8*)s)) {
                sv_setpvn(TARG, "-", 1);
                sv_catsv(TARG, sv);
            }
@@ -1775,10 +1788,10 @@ S_seed(pTHX)
     u = (U32)SEED_C1 * when;
 #  endif
 #endif
-    u += SEED_C3 * (U32)getpid();
-    u += SEED_C4 * (U32)(UV)PL_stack_sp;
+    u += SEED_C3 * (U32)PerlProc_getpid();
+    u += SEED_C4 * (U32)PTR2UV(PL_stack_sp);
 #ifndef PLAN9           /* XXX Plan9 assembler chokes on this; fix needed  */
-    u += SEED_C5 * (U32)(UV)&when;
+    u += SEED_C5 * (U32)PTR2UV(&when);
 #endif
     return u;
 }
@@ -1917,13 +1930,12 @@ PP(pp_oct)
 PP(pp_length)
 {
     djSP; dTARGET;
+    SV *sv = TOPs;
 
-    if (IN_UTF8) {
-       SETi( sv_len_utf8(TOPs) );
-       RETURN;
-    }
-
-    SETi( sv_len(TOPs) );
+    if (DO_UTF8(sv))
+       SETi(sv_len_utf8(sv));
+    else
+       SETi(sv_len(sv));
     RETURN;
 }
 
@@ -1944,6 +1956,7 @@ PP(pp_substr)
     STRLEN repl_len;
 
     SvTAINTED_off(TARG);                       /* decontaminate */
+    SvUTF8_off(TARG);                          /* decontaminate */
     if (MAXARG > 2) {
        if (MAXARG > 3) {
            sv = POPs;
@@ -1955,7 +1968,7 @@ PP(pp_substr)
     sv = POPs;
     PUTBACK;
     tmps = SvPV(sv, curlen);
-    if (IN_UTF8) {
+    if (DO_UTF8(sv)) {
         utfcurlen = sv_len_utf8(sv);
        if (utfcurlen == curlen)
            utfcurlen = 0;
@@ -2004,11 +2017,15 @@ PP(pp_substr)
        RETPUSHUNDEF;
     }
     else {
-        if (utfcurlen)
+        if (utfcurlen) {
            sv_pos_u2b(sv, &pos, &rem);
+           SvUTF8_on(TARG);
+       }
        tmps += pos;
        sv_setpvn(TARG, tmps, rem);
-       if (lvalue) {                   /* it's an lvalue! */
+       if (repl)
+           sv_insert(sv, pos, rem, repl, repl_len);
+       else if (lvalue) {              /* it's an lvalue! */
            if (!SvGMAGICAL(sv)) {
                if (SvROK(sv)) {
                    STRLEN n_a;
@@ -2037,8 +2054,6 @@ PP(pp_substr)
            LvTARGOFF(TARG) = pos;
            LvTARGLEN(TARG) = rem;
        }
-       else if (repl)
-           sv_insert(sv, pos, rem, repl, repl_len);
     }
     SPAGAIN;
     PUSHs(TARG);               /* avoid SvSETMAGIC here */
@@ -2052,74 +2067,24 @@ PP(pp_vec)
     register I32 offset = POPi;
     register SV *src = POPs;
     I32 lvalue = PL_op->op_flags & OPf_MOD;
-    STRLEN srclen;
-    unsigned char *s = (unsigned char*)SvPV(src, srclen);
-    unsigned long retnum;
-    I32 len;
-
-    SvTAINTED_off(TARG);                       /* decontaminate */
-    offset *= size;            /* turn into bit offset */
-    len = (offset + size + 7) / 8;
-    if (offset < 0 || size < 1)
-       retnum = 0;
-    else {
-       if (lvalue) {                      /* it's an lvalue! */
-           if (SvTYPE(TARG) < SVt_PVLV) {
-               sv_upgrade(TARG, SVt_PVLV);
-               sv_magic(TARG, Nullsv, 'v', Nullch, 0);
-           }
 
-           LvTYPE(TARG) = 'v';
-           if (LvTARG(TARG) != src) {
-               if (LvTARG(TARG))
-                   SvREFCNT_dec(LvTARG(TARG));
-               LvTARG(TARG) = SvREFCNT_inc(src);
-           }
-           LvTARGOFF(TARG) = offset;
-           LvTARGLEN(TARG) = size;
-       }
-       if (len > srclen) {
-           if (size <= 8)
-               retnum = 0;
-           else {
-               offset >>= 3;
-               if (size == 16) {
-                   if (offset >= srclen)
-                       retnum = 0;
-                   else
-                       retnum = (unsigned long) s[offset] << 8;
-               }
-               else if (size == 32) {
-                   if (offset >= srclen)
-                       retnum = 0;
-                   else if (offset + 1 >= srclen)
-                       retnum = (unsigned long) s[offset] << 24;
-                   else if (offset + 2 >= srclen)
-                       retnum = ((unsigned long) s[offset] << 24) +
-                           ((unsigned long) s[offset + 1] << 16);
-                   else
-                       retnum = ((unsigned long) s[offset] << 24) +
-                           ((unsigned long) s[offset + 1] << 16) +
-                           (s[offset + 2] << 8);
-               }
-           }
+    SvTAINTED_off(TARG);               /* decontaminate */
+    if (lvalue) {                      /* it's an lvalue! */
+       if (SvTYPE(TARG) < SVt_PVLV) {
+           sv_upgrade(TARG, SVt_PVLV);
+           sv_magic(TARG, Nullsv, 'v', Nullch, 0);
        }
-       else if (size < 8)
-           retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
-       else {
-           offset >>= 3;
-           if (size == 8)
-               retnum = s[offset];
-           else if (size == 16)
-               retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
-           else if (size == 32)
-               retnum = ((unsigned long) s[offset] << 24) +
-                       ((unsigned long) s[offset + 1] << 16) +
-                       (s[offset + 2] << 8) + s[offset+3];
+       LvTYPE(TARG) = 'v';
+       if (LvTARG(TARG) != src) {
+           if (LvTARG(TARG))
+               SvREFCNT_dec(LvTARG(TARG));
+           LvTARG(TARG) = SvREFCNT_inc(src);
        }
+       LvTARGOFF(TARG) = offset;
+       LvTARGLEN(TARG) = size;
     }
 
-    sv_setuv(TARG, (UV)retnum);
+    sv_setuv(TARG, do_vecget(src, offset, size));
     PUSHs(TARG);
     RETURN;
 }
@@ -2143,7 +2108,7 @@ PP(pp_index)
     little = POPs;
     big = POPs;
     tmps = SvPV(big, biglen);
-    if (IN_UTF8 && offset > 0)
+    if (offset > 0 && DO_UTF8(big))
        sv_pos_u2b(big, &offset, 0);
     if (offset < 0)
        offset = 0;
@@ -2154,7 +2119,7 @@ PP(pp_index)
        retval = -1;
     else
        retval = tmps2 - tmps;
-    if (IN_UTF8 && retval > 0)
+    if (retval > 0 && DO_UTF8(big))
        sv_pos_b2u(big, &retval);
     PUSHi(retval + arybase);
     RETURN;
@@ -2182,7 +2147,7 @@ PP(pp_rindex)
     if (MAXARG < 3)
        offset = blen;
     else {
-       if (IN_UTF8 && offset > 0)
+       if (offset > 0 && DO_UTF8(big))
            sv_pos_u2b(big, &offset, 0);
        offset = offset - arybase + llen;
     }
@@ -2195,7 +2160,7 @@ PP(pp_rindex)
        retval = -1;
     else
        retval = tmps2 - tmps;
-    if (IN_UTF8 && retval > 0)
+    if (retval > 0 && DO_UTF8(big))
        sv_pos_b2u(big, &retval);
     PUSHi(retval + arybase);
     RETURN;
@@ -2216,10 +2181,11 @@ PP(pp_ord)
     djSP; dTARGET;
     UV value;
     STRLEN n_a;
-    U8 *tmps = (U8*)POPpx;
+    SV *tmpsv = POPs;
+    U8 *tmps = (U8*)SvPVx(tmpsv,n_a);
     I32 retlen;
 
-    if (IN_UTF8 && (*tmps & 0x80))
+    if ((*tmps & 0x80) && DO_UTF8(tmpsv))
        value = utf8_to_uv(tmps, &retlen);
     else
        value = (UV)(*tmps & 255);
@@ -2235,12 +2201,13 @@ PP(pp_chr)
 
     (void)SvUPGRADE(TARG,SVt_PV);
 
-    if (IN_UTF8 && value >= 128) {
+    if (value > 255 && !IN_BYTE) {
        SvGROW(TARG,8);
        tmps = SvPVX(TARG);
        tmps = (char*)uv_to_utf8((U8*)tmps, (UV)value);
        SvCUR_set(TARG, tmps - SvPVX(TARG));
        *tmps = '\0';
+       SvUTF8_on(TARG);
        (void)SvPOK_only(TARG);
        XPUSHs(TARG);
        RETURN;
@@ -2251,6 +2218,7 @@ PP(pp_chr)
     tmps = SvPVX(TARG);
     *tmps++ = value;
     *tmps = '\0';
+    SvUTF8_off(TARG);                          /* decontaminate */
     (void)SvPOK_only(TARG);
     XPUSHs(TARG);
     RETURN;
@@ -2282,7 +2250,7 @@ PP(pp_ucfirst)
     register U8 *s;
     STRLEN slen;
 
-    if (IN_UTF8 && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
+    if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
        I32 ulen;
        U8 tmpbuf[10];
        U8 *tend;
@@ -2298,10 +2266,11 @@ PP(pp_ucfirst)
        
        tend = uv_to_utf8(tmpbuf, uv);
 
-       if (!SvPADTMP(sv) || tend - tmpbuf != ulen) {
+       if (!SvPADTMP(sv) || tend - tmpbuf != ulen || SvREADONLY(sv)) {
            dTARGET;
            sv_setpvn(TARG, (char*)tmpbuf, tend - tmpbuf);
            sv_catpvn(TARG, (char*)(s + ulen), slen - ulen);
+           SvUTF8_on(TARG);
            SETs(TARG);
        }
        else {
@@ -2310,8 +2279,9 @@ PP(pp_ucfirst)
        }
     }
     else {
-       if (!SvPADTMP(sv)) {
+       if (!SvPADTMP(sv) || SvREADONLY(sv)) {
            dTARGET;
+           SvUTF8_off(TARG);                           /* decontaminate */
            sv_setsv(TARG, sv);
            sv = TARG;
            SETs(sv);
@@ -2339,7 +2309,7 @@ PP(pp_lcfirst)
     register U8 *s;
     STRLEN slen;
 
-    if (IN_UTF8 && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
+    if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
        I32 ulen;
        U8 tmpbuf[10];
        U8 *tend;
@@ -2355,10 +2325,11 @@ PP(pp_lcfirst)
        
        tend = uv_to_utf8(tmpbuf, uv);
 
-       if (!SvPADTMP(sv) || tend - tmpbuf != ulen) {
+       if (!SvPADTMP(sv) || tend - tmpbuf != ulen || SvREADONLY(sv)) {
            dTARGET;
            sv_setpvn(TARG, (char*)tmpbuf, tend - tmpbuf);
            sv_catpvn(TARG, (char*)(s + ulen), slen - ulen);
+           SvUTF8_on(TARG);
            SETs(TARG);
        }
        else {
@@ -2367,8 +2338,9 @@ PP(pp_lcfirst)
        }
     }
     else {
-       if (!SvPADTMP(sv)) {
+       if (!SvPADTMP(sv) || SvREADONLY(sv)) {
            dTARGET;
+           SvUTF8_off(TARG);                           /* decontaminate */
            sv_setsv(TARG, sv);
            sv = TARG;
            SETs(sv);
@@ -2383,7 +2355,6 @@ PP(pp_lcfirst)
            else
                *s = toLOWER(*s);
        }
-       SETs(sv);
     }
     if (SvSMAGICAL(sv))
        mg_set(sv);
@@ -2397,7 +2368,7 @@ PP(pp_uc)
     register U8 *s;
     STRLEN len;
 
-    if (IN_UTF8) {
+    if (DO_UTF8(sv)) {
        dTARGET;
        I32 ulen;
        register U8 *d;
@@ -2405,6 +2376,7 @@ PP(pp_uc)
 
        s = (U8*)SvPV(sv,len);
        if (!len) {
+           SvUTF8_off(TARG);                           /* decontaminate */
            sv_setpvn(TARG, "", 0);
            SETs(TARG);
        }
@@ -2429,13 +2401,15 @@ PP(pp_uc)
                }
            }
            *d = '\0';
+           SvUTF8_on(TARG);
            SvCUR_set(TARG, d - (U8*)SvPVX(TARG));
            SETs(TARG);
        }
     }
     else {
-       if (!SvPADTMP(sv)) {
+       if (!SvPADTMP(sv) || SvREADONLY(sv)) {
            dTARGET;
+           SvUTF8_off(TARG);                           /* decontaminate */
            sv_setsv(TARG, sv);
            sv = TARG;
            SETs(sv);
@@ -2468,7 +2442,7 @@ PP(pp_lc)
     register U8 *s;
     STRLEN len;
 
-    if (IN_UTF8) {
+    if (DO_UTF8(sv)) {
        dTARGET;
        I32 ulen;
        register U8 *d;
@@ -2476,6 +2450,7 @@ PP(pp_lc)
 
        s = (U8*)SvPV(sv,len);
        if (!len) {
+           SvUTF8_off(TARG);                           /* decontaminate */
            sv_setpvn(TARG, "", 0);
            SETs(TARG);
        }
@@ -2500,13 +2475,15 @@ PP(pp_lc)
                }
            }
            *d = '\0';
+           SvUTF8_on(TARG);
            SvCUR_set(TARG, d - (U8*)SvPVX(TARG));
            SETs(TARG);
        }
     }
     else {
-       if (!SvPADTMP(sv)) {
+       if (!SvPADTMP(sv) || SvREADONLY(sv)) {
            dTARGET;
+           SvUTF8_off(TARG);                           /* decontaminate */
            sv_setsv(TARG, sv);
            sv = TARG;
            SETs(sv);
@@ -2541,11 +2518,12 @@ PP(pp_quotemeta)
     register char *s = SvPV(sv,len);
     register char *d;
 
+    SvUTF8_off(TARG);                          /* decontaminate */
     if (len) {
        (void)SvUPGRADE(TARG, SVt_PV);
        SvGROW(TARG, (len * 2) + 1);
        d = SvPVX(TARG);
-       if (IN_UTF8) {
+       if (DO_UTF8(sv)) {
            while (len) {
                if (*s & 0x80) {
                    STRLEN ulen = UTF8SKIP(s);
@@ -2562,6 +2540,7 @@ PP(pp_quotemeta)
                    len--;
                }
            }
+           SvUTF8_on(TARG);
        }
        else {
            while (len--) {
@@ -2684,13 +2663,28 @@ PP(pp_delete)
        U32 hvtype;
        hv = (HV*)POPs;
        hvtype = SvTYPE(hv);
-       while (++MARK <= SP) {
-           if (hvtype == SVt_PVHV)
+       if (hvtype == SVt_PVHV) {                       /* hash element */
+           while (++MARK <= SP) {
                sv = hv_delete_ent(hv, *MARK, discard, 0);
-           else
-               DIE(aTHX_ "Not a HASH reference");
-           *MARK = sv ? sv : &PL_sv_undef;
+               *MARK = sv ? sv : &PL_sv_undef;
+           }
+       }
+       else if (hvtype == SVt_PVAV) {
+           if (PL_op->op_flags & OPf_SPECIAL) {        /* array element */
+               while (++MARK <= SP) {
+                   sv = av_delete((AV*)hv, SvIV(*MARK), discard);
+                   *MARK = sv ? sv : &PL_sv_undef;
+               }
+           }
+           else {                                      /* pseudo-hash element */
+               while (++MARK <= SP) {
+                   sv = avhv_delete_ent((AV*)hv, *MARK, discard, 0);
+                   *MARK = sv ? sv : &PL_sv_undef;
+               }
+           }
        }
+       else
+           DIE(aTHX_ "Not a HASH reference");
        if (discard)
            SP = ORIGMARK;
        else if (gimme == G_SCALAR) {
@@ -2704,6 +2698,12 @@ PP(pp_delete)
        hv = (HV*)POPs;
        if (SvTYPE(hv) == SVt_PVHV)
            sv = hv_delete_ent(hv, keysv, discard, 0);
+       else if (SvTYPE(hv) == SVt_PVAV) {
+           if (PL_op->op_flags & OPf_SPECIAL)
+               sv = av_delete((AV*)hv, SvIV(keysv), discard);
+           else
+               sv = avhv_delete_ent((AV*)hv, keysv, discard, 0);
+       }
        else
            DIE(aTHX_ "Not a HASH reference");
        if (!sv)
@@ -2717,14 +2717,32 @@ PP(pp_delete)
 PP(pp_exists)
 {
     djSP;
-    SV *tmpsv = POPs;
-    HV *hv = (HV*)POPs;
+    SV *tmpsv;
+    HV *hv;
+
+    if (PL_op->op_private & OPpEXISTS_SUB) {
+       GV *gv;
+       CV *cv;
+       SV *sv = POPs;
+       cv = sv_2cv(sv, &hv, &gv, FALSE);
+       if (cv)
+           RETPUSHYES;
+       if (gv && isGV(gv) && GvCV(gv) && !GvCVGEN(gv))
+           RETPUSHYES;
+       RETPUSHNO;
+    }
+    tmpsv = POPs;
+    hv = (HV*)POPs;
     if (SvTYPE(hv) == SVt_PVHV) {
        if (hv_exists_ent(hv, tmpsv, 0))
            RETPUSHYES;
     }
     else if (SvTYPE(hv) == SVt_PVAV) {
-       if (avhv_exists_ent((AV*)hv, tmpsv, 0))
+       if (PL_op->op_flags & OPf_SPECIAL) {            /* array element */
+           if (av_exists((AV*)hv, SvIV(tmpsv)))
+               RETPUSHYES;
+       }
+       else if (avhv_exists_ent((AV*)hv, tmpsv, 0))    /* pseudo-hash element */
            RETPUSHYES;
     }
     else {
@@ -3172,6 +3190,7 @@ PP(pp_reverse)
            *MARK++ = *SP;
            *SP-- = tmp;
        }
+       /* safe as long as stack cannot get extended in the above */
        SP = oldsp;
     }
     else {
@@ -3181,13 +3200,14 @@ PP(pp_reverse)
        dTARGET;
        STRLEN len;
 
+       SvUTF8_off(TARG);                               /* decontaminate */
        if (SP - MARK > 1)
            do_join(TARG, &PL_sv_no, MARK, SP);
        else
            sv_setsv(TARG, (SP > MARK) ? *SP : DEFSV);
        up = SvPV_force(TARG, len);
        if (len > 1) {
-           if (IN_UTF8) {      /* first reverse each character */
+           if (DO_UTF8(TARG)) {        /* first reverse each character */
                U8* s = (U8*)SvPVX(TARG);
                U8* send = (U8*)(s + len);
                while (s < send) {
@@ -3272,7 +3292,7 @@ PP(pp_unpack)
 {
     djSP;
     dPOPPOPssrl;
-    SV **oldsp = SP;
+    I32 start_sp_offset = SP - PL_stack_base;
     I32 gimme = GIMME_V;
     SV *sv;
     STRLEN llen;
@@ -3285,6 +3305,7 @@ PP(pp_unpack)
     I32 datumtype;
     register I32 len;
     register I32 bits;
+    register char *str;
 
     /* These must not be in registers: */
     I16 ashort;
@@ -3306,6 +3327,7 @@ PP(pp_unpack)
     register U32 culong;
     NV cdouble;
     int commas = 0;
+    int star;
 #ifdef PERL_NATINT_PACK
     int natint;                /* native integer */
     int unatint;       /* unsigned native integer */
@@ -3330,6 +3352,11 @@ PP(pp_unpack)
 #endif
        if (isSPACE(datumtype))
            continue;
+       if (datumtype == '#') {
+           while (pat < patend && *pat != '\n')
+               pat++;
+           continue;
+       }
        if (*pat == '!') {
            char *natstr = "sSiIlL";
 
@@ -3340,27 +3367,34 @@ PP(pp_unpack)
                pat++;
            }
            else
-               Perl_croak(aTHX_ "'!' allowed only after types %s", natstr);
+               DIE(aTHX_ "'!' allowed only after types %s", natstr);
        }
+       star = 0;
        if (pat >= patend)
            len = 1;
        else if (*pat == '*') {
            len = strend - strbeg;      /* long enough */
            pat++;
+           star = 1;
        }
        else if (isDIGIT(*pat)) {
            len = *pat++ - '0';
-           while (isDIGIT(*pat))
+           while (isDIGIT(*pat)) {
                len = (len * 10) + (*pat++ - '0');
+               if (len < 0)
+                   DIE(aTHX_ "Repeat count in unpack overflows");
+           }
        }
        else
            len = (datumtype != '@');
+      redo_switch:
        switch(datumtype) {
        default:
-           Perl_croak(aTHX_ "Invalid type in unpack: '%c'", (int)datumtype);
+           DIE(aTHX_ "Invalid type in unpack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
            if (commas++ == 0 && ckWARN(WARN_UNSAFE))
-               Perl_warner(aTHX_ WARN_UNSAFE, "Invalid type in unpack: '%c'", (int)datumtype);
+               Perl_warner(aTHX_ WARN_UNSAFE,
+                           "Invalid type in unpack: '%c'", (int)datumtype);
            break;
        case '%':
            if (len == 1 && pat[-1] != '1')
@@ -3386,18 +3420,17 @@ PP(pp_unpack)
                DIE(aTHX_ "x outside of string");
            s += len;
            break;
-       case '#':
-           if (oldsp >= SP)
-               DIE(aTHX_ "# must follow a numeric type");
-           if (*pat != 'a' && *pat != 'A' && *pat != 'Z')
-               DIE(aTHX_ "# must be followed by a, A or Z");
+       case '/':
+           if (start_sp_offset >= SP - PL_stack_base)
+               DIE(aTHX_ "/ must follow a numeric type");
            datumtype = *pat++;
            if (*pat == '*')
                pat++;          /* ignore '*' for compatibility with pack */
            if (isDIGIT(*pat))
-               DIE(aTHX_ "# cannot take a count" );
+               DIE(aTHX_ "/ cannot take a count" );
            len = POPi;
-           /* drop through */
+           star = 0;
+           goto redo_switch;
        case 'A':
        case 'Z':
        case 'a':
@@ -3428,7 +3461,7 @@ PP(pp_unpack)
            break;
        case 'B':
        case 'b':
-           if (pat[-1] == '*' || len > (strend - s) * 8)
+           if (star || len > (strend - s) * 8)
                len = (strend - s) * 8;
            if (checksum) {
                if (!PL_bitcount) {
@@ -3468,8 +3501,7 @@ PP(pp_unpack)
            sv = NEWSV(35, len + 1);
            SvCUR_set(sv, len);
            SvPOK_on(sv);
-           aptr = pat;                 /* borrow register */
-           pat = SvPVX(sv);
+           str = SvPVX(sv);
            if (datumtype == 'b') {
                aint = len;
                for (len = 0; len < aint; len++) {
@@ -3477,7 +3509,7 @@ PP(pp_unpack)
                        bits >>= 1;
                    else
                        bits = *s++;
-                   *pat++ = '0' + (bits & 1);
+                   *str++ = '0' + (bits & 1);
                }
            }
            else {
@@ -3487,22 +3519,20 @@ PP(pp_unpack)
                        bits <<= 1;
                    else
                        bits = *s++;
-                   *pat++ = '0' + ((bits & 128) != 0);
+                   *str++ = '0' + ((bits & 128) != 0);
                }
            }
-           *pat = '\0';
-           pat = aptr;                 /* unborrow register */
+           *str = '\0';
            XPUSHs(sv_2mortal(sv));
            break;
        case 'H':
        case 'h':
-           if (pat[-1] == '*' || len > (strend - s) * 2)
+           if (star || len > (strend - s) * 2)
                len = (strend - s) * 2;
            sv = NEWSV(35, len + 1);
            SvCUR_set(sv, len);
            SvPOK_on(sv);
-           aptr = pat;                 /* borrow register */
-           pat = SvPVX(sv);
+           str = SvPVX(sv);
            if (datumtype == 'h') {
                aint = len;
                for (len = 0; len < aint; len++) {
@@ -3510,7 +3540,7 @@ PP(pp_unpack)
                        bits >>= 4;
                    else
                        bits = *s++;
-                   *pat++ = PL_hexdigit[bits & 15];
+                   *str++ = PL_hexdigit[bits & 15];
                }
            }
            else {
@@ -3520,11 +3550,10 @@ PP(pp_unpack)
                        bits <<= 4;
                    else
                        bits = *s++;
-                   *pat++ = PL_hexdigit[(bits >> 4) & 15];
+                   *str++ = PL_hexdigit[(bits >> 4) & 15];
                }
            }
-           *pat = '\0';
-           pat = aptr;                 /* unborrow register */
+           *str = '\0';
            XPUSHs(sv_2mortal(sv));
            break;
        case 'c':
@@ -3608,6 +3637,7 @@ PP(pp_unpack)
            if (checksum) {
 #if SHORTSIZE != SIZE16
                if (natint) {
+                   short ashort;
                    while (len-- > 0) {
                        COPYNN(s, &ashort, sizeof(short));
                        s += sizeof(short);
@@ -3634,6 +3664,7 @@ PP(pp_unpack)
                EXTEND_MORTAL(len);
 #if SHORTSIZE != SIZE16
                if (natint) {
+                   short ashort;
                    while (len-- > 0) {
                        COPYNN(s, &ashort, sizeof(short));
                        s += sizeof(short);
@@ -3673,6 +3704,7 @@ PP(pp_unpack)
            if (checksum) {
 #if SHORTSIZE != SIZE16
                if (unatint) {
+                   unsigned short aushort;
                    while (len-- > 0) {
                        COPYNN(s, &aushort, sizeof(unsigned short));
                        s += sizeof(unsigned short);
@@ -3702,6 +3734,7 @@ PP(pp_unpack)
                EXTEND_MORTAL(len);
 #if SHORTSIZE != SIZE16
                if (unatint) {
+                   unsigned short aushort;
                    while (len-- > 0) {
                        COPYNN(s, &aushort, sizeof(unsigned short));
                        s += sizeof(unsigned short);
@@ -3826,6 +3859,7 @@ PP(pp_unpack)
            if (checksum) {
 #if LONGSIZE != SIZE32
                if (natint) {
+                   long along;
                    while (len-- > 0) {
                        COPYNN(s, &along, sizeof(long));
                        s += sizeof(long);
@@ -3857,6 +3891,7 @@ PP(pp_unpack)
                EXTEND_MORTAL(len);
 #if LONGSIZE != SIZE32
                if (natint) {
+                   long along;
                    while (len-- > 0) {
                        COPYNN(s, &along, sizeof(long));
                        s += sizeof(long);
@@ -3896,6 +3931,7 @@ PP(pp_unpack)
            if (checksum) {
 #if LONGSIZE != SIZE32
                if (unatint) {
+                   unsigned long aulong;
                    while (len-- > 0) {
                        COPYNN(s, &aulong, sizeof(unsigned long));
                        s += sizeof(unsigned long);
@@ -3931,6 +3967,7 @@ PP(pp_unpack)
                EXTEND_MORTAL(len);
 #if LONGSIZE != SIZE32
                if (unatint) {
+                   unsigned long aulong;
                    while (len-- > 0) {
                        COPYNN(s, &aulong, sizeof(unsigned long));
                        s += sizeof(unsigned long);
@@ -4018,7 +4055,7 @@ PP(pp_unpack)
                    }
                }
                if ((s >= strend) && bytes)
-                   Perl_croak(aTHX_ "Unterminated compressed integer");
+                   DIE(aTHX_ "Unterminated compressed integer");
            }
            break;
        case 'P':
@@ -4220,7 +4257,7 @@ PP(pp_unpack)
            checksum = 0;
        }
     }
-    if (SP == oldsp && gimme == G_SCALAR)
+    if (SP - PL_stack_base == start_sp_offset && gimme == G_SCALAR)
        PUSHs(&PL_sv_undef);
     RETURN;
 }
@@ -4376,6 +4413,11 @@ PP(pp_pack)
 #endif
        if (isSPACE(datumtype))
            continue;
+       if (datumtype == '#') {
+           while (pat < patend && *pat != '\n')
+               pat++;
+           continue;
+       }
         if (*pat == '!') {
            char *natstr = "sSiIlL";
 
@@ -4386,7 +4428,7 @@ PP(pp_pack)
                pat++;
            }
            else
-               Perl_croak(aTHX_ "'!' allowed only after types %s", natstr);
+               DIE(aTHX_ "'!' allowed only after types %s", natstr);
        }
        if (*pat == '*') {
            len = strchr("@Xxu", datumtype) ? 0 : items;
@@ -4394,21 +4436,24 @@ PP(pp_pack)
        }
        else if (isDIGIT(*pat)) {
            len = *pat++ - '0';
-           while (isDIGIT(*pat))
+           while (isDIGIT(*pat)) {
                len = (len * 10) + (*pat++ - '0');
+               if (len < 0)
+                   DIE(aTHX_ "Repeat count in pack overflows");
+           }
        }
        else
            len = 1;
-       if (*pat == '#') {
+       if (*pat == '/') {
            ++pat;
            if (*pat != 'a' && *pat != 'A' && *pat != 'Z' || pat[1] != '*')
-               DIE(aTHX_ "# must be followed by a*, A* or Z*");
+               DIE(aTHX_ "/ must be followed by a*, A* or Z*");
            lengthcode = sv_2mortal(newSViv(sv_len(items > 0
                                                   ? *MARK : &PL_sv_no)));
        }
        switch(datumtype) {
        default:
-           Perl_croak(aTHX_ "Invalid type in pack: '%c'", (int)datumtype);
+           DIE(aTHX_ "Invalid type in pack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
            if (commas++ == 0 && ckWARN(WARN_UNSAFE))
                Perl_warner(aTHX_ WARN_UNSAFE,
@@ -4444,10 +4489,16 @@ PP(pp_pack)
        case 'a':
            fromstr = NEXTFROM;
            aptr = SvPV(fromstr, fromlen);
-           if (pat[-1] == '*')
+           if (pat[-1] == '*') {
                len = fromlen;
-           if (fromlen > len)
+               if (datumtype == 'Z')
+                   ++len;
+           }
+           if (fromlen >= len) {
                sv_catpvn(cat, aptr, len);
+               if (datumtype == 'Z')
+                   *(SvEND(cat)-1) = '\0';
+           }
            else {
                sv_catpvn(cat, aptr, fromlen);
                len -= fromlen;
@@ -4470,15 +4521,14 @@ PP(pp_pack)
        case 'B':
        case 'b':
            {
-               char *savepat = pat;
+               register char *str;
                I32 saveitems;
 
                fromstr = NEXTFROM;
                saveitems = items;
-               aptr = SvPV(fromstr, fromlen);
+               str = SvPV(fromstr, fromlen);
                if (pat[-1] == '*')
                    len = fromlen;
-               pat = aptr;
                aint = SvCUR(cat);
                SvCUR(cat) += (len+7)/8;
                SvGROW(cat, SvCUR(cat) + 1);
@@ -4489,7 +4539,7 @@ PP(pp_pack)
                items = 0;
                if (datumtype == 'B') {
                    for (len = 0; len++ < aint;) {
-                       items |= *pat++ & 1;
+                       items |= *str++ & 1;
                        if (len & 7)
                            items <<= 1;
                        else {
@@ -4500,7 +4550,7 @@ PP(pp_pack)
                }
                else {
                    for (len = 0; len++ < aint;) {
-                       if (*pat++ & 1)
+                       if (*str++ & 1)
                            items |= 128;
                        if (len & 7)
                            items >>= 1;
@@ -4517,26 +4567,24 @@ PP(pp_pack)
                        items >>= 7 - (aint & 7);
                    *aptr++ = items & 0xff;
                }
-               pat = SvPVX(cat) + SvCUR(cat);
-               while (aptr <= pat)
+               str = SvPVX(cat) + SvCUR(cat);
+               while (aptr <= str)
                    *aptr++ = '\0';
 
-               pat = savepat;
                items = saveitems;
            }
            break;
        case 'H':
        case 'h':
            {
-               char *savepat = pat;
+               register char *str;
                I32 saveitems;
 
                fromstr = NEXTFROM;
                saveitems = items;
-               aptr = SvPV(fromstr, fromlen);
+               str = SvPV(fromstr, fromlen);
                if (pat[-1] == '*')
                    len = fromlen;
-               pat = aptr;
                aint = SvCUR(cat);
                SvCUR(cat) += (len+1)/2;
                SvGROW(cat, SvCUR(cat) + 1);
@@ -4547,10 +4595,10 @@ PP(pp_pack)
                items = 0;
                if (datumtype == 'H') {
                    for (len = 0; len++ < aint;) {
-                       if (isALPHA(*pat))
-                           items |= ((*pat++ & 15) + 9) & 15;
+                       if (isALPHA(*str))
+                           items |= ((*str++ & 15) + 9) & 15;
                        else
-                           items |= *pat++ & 15;
+                           items |= *str++ & 15;
                        if (len & 1)
                            items <<= 4;
                        else {
@@ -4561,10 +4609,10 @@ PP(pp_pack)
                }
                else {
                    for (len = 0; len++ < aint;) {
-                       if (isALPHA(*pat))
-                           items |= (((*pat++ & 15) + 9) & 15) << 4;
+                       if (isALPHA(*str))
+                           items |= (((*str++ & 15) + 9) & 15) << 4;
                        else
-                           items |= (*pat++ & 15) << 4;
+                           items |= (*str++ & 15) << 4;
                        if (len & 1)
                            items >>= 4;
                        else {
@@ -4575,11 +4623,10 @@ PP(pp_pack)
                }
                if (aint & 1)
                    *aptr++ = items & 0xff;
-               pat = SvPVX(cat) + SvCUR(cat);
-               while (aptr <= pat)
+               str = SvPVX(cat) + SvCUR(cat);
+               while (aptr <= str)
                    *aptr++ = '\0';
 
-               pat = savepat;
                items = saveitems;
            }
            break;
@@ -4666,6 +4713,8 @@ PP(pp_pack)
        case 's':
 #if SHORTSIZE != SIZE16
            if (natint) {
+               short ashort;
+
                while (len-- > 0) {
                    fromstr = NEXTFROM;
                    ashort = SvIV(fromstr);
@@ -4695,7 +4744,7 @@ PP(pp_pack)
                adouble = Perl_floor(SvNV(fromstr));
 
                if (adouble < 0)
-                   Perl_croak(aTHX_ "Cannot compress negative numbers");
+                   DIE(aTHX_ "Cannot compress negative numbers");
 
                if (
 #ifdef BW_BITS
@@ -4729,7 +4778,7 @@ PP(pp_pack)
                    /* Copy string and check for compliance */
                    from = SvPV(fromstr, len);
                    if ((norm = is_an_int(from, len)) == NULL)
-                       Perl_croak(aTHX_ "can compress only unsigned integer");
+                       DIE(aTHX_ "can compress only unsigned integer");
 
                    New('w', result, len, char);
                    in = result + len;
@@ -4749,14 +4798,14 @@ PP(pp_pack)
                        double next = floor(adouble / 128);
                        *--in = (unsigned char)(adouble - (next * 128)) | 0x80;
                        if (--in < buf)  /* this cannot happen ;-) */
-                           Perl_croak(aTHX_ "Cannot compress integer");
+                           DIE(aTHX_ "Cannot compress integer");
                        adouble = next;
                    } while (adouble > 0);
                    buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
                    sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
                }
                else
-                   Perl_croak(aTHX_ "Cannot compress non integer");
+                   DIE(aTHX_ "Cannot compress non integer");
            }
             break;
        case 'i':
@@ -4789,6 +4838,8 @@ PP(pp_pack)
        case 'L':
 #if LONGSIZE != SIZE32
            if (natint) {
+               unsigned long aulong;
+
                while (len-- > 0) {
                    fromstr = NEXTFROM;
                    aulong = SvUV(fromstr);
@@ -4808,6 +4859,8 @@ PP(pp_pack)
        case 'l':
 #if LONGSIZE != SIZE32
            if (natint) {
+               long along;
+
                while (len-- > 0) {
                    fromstr = NEXTFROM;
                    along = SvIV(fromstr);
@@ -4828,7 +4881,7 @@ PP(pp_pack)
        case 'Q':
            while (len-- > 0) {
                fromstr = NEXTFROM;
-               auquad = (Uquad_t)SvIV(fromstr);
+               auquad = (Uquad_t)SvUV(fromstr);
                sv_catpvn(cat, (char*)&auquad, sizeof(Uquad_t));
            }
            break;
@@ -4839,7 +4892,7 @@ PP(pp_pack)
                sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
            }
            break;
-#endif /* HAS_QUAD */
+#endif
        case 'P':
            len = 1;            /* assume SV is correct length */
            /* FALL THROUGH */
@@ -4855,9 +4908,13 @@ PP(pp_pack)
                     * of pack() (and all copies of the result) are
                     * gone.
                     */
-                   if (ckWARN(WARN_UNSAFE) && (SvTEMP(fromstr) || SvPADTMP(fromstr)))
+                   if (ckWARN(WARN_UNSAFE) && (SvTEMP(fromstr)
+                                               || (SvPADTMP(fromstr)
+                                                   && !SvREADONLY(fromstr))))
+                   {
                        Perl_warner(aTHX_ WARN_UNSAFE,
                                "Attempt to pack pointer to temporary value");
+                   }
                    if (SvPOK(fromstr) || SvNIOK(fromstr))
                        aptr = SvPV(fromstr,n_a);
                    else
@@ -4934,8 +4991,13 @@ PP(pp_split)
     TAINT_IF((pm->op_pmflags & PMf_LOCALE) &&
             (pm->op_pmflags & (PMf_WHITE | PMf_SKIPWHITE)));
 
-    if (pm->op_pmreplroot)
+    if (pm->op_pmreplroot) {
+#ifdef USE_ITHREADS
+       ary = GvAVn((GV*)PL_curpad[(PADOFFSET)pm->op_pmreplroot]);
+#else
        ary = GvAVn((GV*)pm->op_pmreplroot);
+#endif
+    }
     else if (gimme != G_ARRAY)
 #ifdef USE_THREADS
        ary = (AV*)PL_curpad[0];
@@ -4957,6 +5019,7 @@ PP(pp_split)
        else {
            if (!AvREAL(ary)) {
                AvREAL_on(ary);
+               AvREIFY_off(ary);
                for (i = AvFILLp(ary); i >= 0; i--)
                    AvARRAY(ary)[i] = &PL_sv_undef;     /* don't free mere refs */
            }
@@ -5007,13 +5070,7 @@ PP(pp_split)
                ++s;
        }
     }
-    else if (rx->prelen == 1 && *rx->precomp == '^') {
-       if (!(pm->op_pmflags & PMf_MULTILINE)
-           && !(pm->op_pmregexp->reganch & ROPT_WARNED)) {
-           if (ckWARN(WARN_DEPRECATED))
-               warn("split /^/ better written as split /^/m");
-           pm->op_pmregexp->reganch |= ROPT_WARNED;
-       }       
+    else if (strEQ("^", rx->precomp)) {
        while (--limit) {
            /*SUPPRESS 530*/
            for (m = s; m < strend && *m != '\n'; m++) ;
@@ -5186,8 +5243,8 @@ Perl_unlock_condpair(pTHX_ void *svv)
        Perl_croak(aTHX_ "panic: unlock_condpair unlocking mutex that we don't own");
     MgOWNER(mg) = 0;
     COND_SIGNAL(MgOWNERCONDP(mg));
-    DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: unlock 0x%lx\n",
-                         (unsigned long)thr, (unsigned long)svv);)
+    DEBUG_S(PerlIO_printf(Perl_debug_log, "0x%"UVxf": unlock 0x%"UVxf"\n",
+                         PTR2UV(thr), PTR2UV(svv));)
     MUTEX_UNLOCK(MgMUTEXP(mg));
 }
 #endif /* USE_THREADS */
@@ -5211,10 +5268,10 @@ PP(pp_lock)
        while (MgOWNER(mg))
            COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg));
        MgOWNER(mg) = thr;
-       DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: pp_lock lock 0x%lx\n",
-                             (unsigned long)thr, (unsigned long)sv);)
+       DEBUG_S(PerlIO_printf(Perl_debug_log, "0x%"UVxf": pp_lock lock 0x%"UVxf"\n",
+                             PTR2UV(thr), PTR2UV(sv));)
        MUTEX_UNLOCK(MgMUTEXP(mg));
-       SAVEDESTRUCTOR(Perl_unlock_condpair, sv);
+       SAVEDESTRUCTOR_X(Perl_unlock_condpair, sv);
     }
 #endif /* USE_THREADS */
     if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV