This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [PATCH-revised] ext/Win32/t/Unicode.t failures on FAT32 under Cygwin
[perl5.git] / sv.h
diff --git a/sv.h b/sv.h
index e0b3be5..8ad522d 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -1,7 +1,7 @@
 /*    sv.h
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 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.
@@ -45,10 +45,10 @@ Type flag for code refs.  See C<svtype>.
 
 typedef enum {
        SVt_NULL,       /* 0 */
-       SVt_IV,         /* 1 */
-       SVt_NV,         /* 2 */
-       SVt_RV,         /* 3 */
-       SVt_BIND,       /* 4 */
+       SVt_BIND,       /* 1 */
+       SVt_IV,         /* 2 */
+       SVt_NV,         /* 3 */
+       SVt_RV,         /* 4 */
        SVt_PV,         /* 5 */
        SVt_PVIV,       /* 6 */
        SVt_PVNV,       /* 7 */
@@ -177,9 +177,8 @@ to return a meaningful value, or check for NULLness, so it's smaller
 and faster.
 
 =for apidoc Am|SV*|SvREFCNT_inc_simple|SV* sv
-Same as SvREFCNT_inc, but can only be used with simple variables, not
-expressions or pointer dereferences.  Since we don't have to store a
-temporary value, it's faster.
+Same as SvREFCNT_inc, but can only be used with expressions without side
+effects.  Since we don't have to store a temporary value, it's faster.
 
 =for apidoc Am|SV*|SvREFCNT_inc_simple_NN|SV* sv
 Same as SvREFCNT_inc_simple, but can only be used if you know I<sv>
@@ -274,7 +273,7 @@ perform the upgrade if necessary.  See C<svtype>.
 #endif
 
 #define SVTYPEMASK     0xff
-#define SvTYPE(sv)     (svtype)((sv)->sv_flags & SVTYPEMASK)
+#define SvTYPE(sv)     ((svtype)((sv)->sv_flags & SVTYPEMASK))
 
 /* Sadly there are some parts of the core that have pointers to already-freed
    SV heads, and rely on being able to tell that they are now free. So mark
@@ -331,7 +330,7 @@ perform the upgrade if necessary.  See C<svtype>.
                                       means that a hv_aux struct is present
                                       after the main array */
 #define SVf_BREAK      0x04000000  /* refcnt is artificially low - used by
-                                      SV's in final arena  cleanup */
+                                      SV's in final arena cleanup */
 #define SVf_READONLY   0x08000000  /* may not be modified */
 
 
@@ -389,24 +388,38 @@ struct xpv {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
 };
 
-#if 0
-typedef struct xpv xpv_allocated;
-#else
 typedef struct {
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
 } xpv_allocated;
-#endif
 
 struct xpviv {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -419,9 +432,6 @@ struct xpviv {
     }          xiv_u;
 };
 
-#if 0
-typedef struct xpviv xpviv_allocated;
-#else
 typedef struct {
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -433,7 +443,6 @@ typedef struct {
        HEK *   xivu_namehek;
     }          xiv_u;
 } xpviv_allocated;
-#endif
 
 #define xiv_iv xiv_u.xivu_iv
 
@@ -441,6 +450,15 @@ struct xpvuv {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -458,6 +476,15 @@ struct xpvnv {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -475,6 +502,15 @@ struct xpvmg {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -496,6 +532,15 @@ struct xpvlv {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -525,6 +570,15 @@ struct xpvgv {
     union {
        NV      xnv_nv;
        HV *    xgv_stash;      /* The stash of this GV */
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* xgv_flags */
     STRLEN     xpv_len;        /* 0 */
@@ -551,6 +605,15 @@ struct xpvfm {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -627,6 +690,15 @@ struct xpvio {
     union {
        NV      xnv_nv;         /* numeric value, if any */
        HV *    xgv_stash;
+       struct {
+           U32 xlow;
+           U32 xhigh;
+       }       xpad_cop_seq;   /* used by pad.c for cop_sequence */
+       struct {
+           U32 xbm_previous;   /* how many characters in string before rare? */
+           U8  xbm_flags;
+           U8  xbm_rare;       /* rarest character in string */
+       }       xbm_s;          /* fields from PVBM */
     }          xnv_u;
     STRLEN     xpv_cur;        /* length of svu_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
@@ -686,35 +758,35 @@ struct xpvio {
 /* The following macros define implementation-independent predicates on SVs. */
 
 /*
-=for apidoc Am|bool|SvNIOK|SV* sv
-Returns a boolean indicating whether the SV contains a number, integer or
+=for apidoc Am|U32|SvNIOK|SV* sv
+Returns a U32 value indicating whether the SV contains a number, integer or
 double.
 
-=for apidoc Am|bool|SvNIOKp|SV* sv
-Returns a boolean indicating whether the SV contains a number, integer or
+=for apidoc Am|U32|SvNIOKp|SV* sv
+Returns a U32 value indicating whether the SV contains a number, integer or
 double.  Checks the B<private> setting.  Use C<SvNIOK>.
 
 =for apidoc Am|void|SvNIOK_off|SV* sv
 Unsets the NV/IV status of an SV.
 
-=for apidoc Am|bool|SvOK|SV* sv
-Returns a boolean indicating whether the value is an SV. It also tells
+=for apidoc Am|U32|SvOK|SV* sv
+Returns a U32 value indicating whether the value is an SV. It also tells
 whether the value is defined or not.
 
-=for apidoc Am|bool|SvIOKp|SV* sv
-Returns a boolean indicating whether the SV contains an integer.  Checks
+=for apidoc Am|U32|SvIOKp|SV* sv
+Returns a U32 value indicating whether the SV contains an integer.  Checks
 the B<private> setting.  Use C<SvIOK>.
 
-=for apidoc Am|bool|SvNOKp|SV* sv
-Returns a boolean indicating whether the SV contains a double.  Checks the
+=for apidoc Am|U32|SvNOKp|SV* sv
+Returns a U32 value indicating whether the SV contains a double.  Checks the
 B<private> setting.  Use C<SvNOK>.
 
-=for apidoc Am|bool|SvPOKp|SV* sv
-Returns a boolean indicating whether the SV contains a character string.
+=for apidoc Am|U32|SvPOKp|SV* sv
+Returns a U32 value indicating whether the SV contains a character string.
 Checks the B<private> setting.  Use C<SvPOK>.
 
-=for apidoc Am|bool|SvIOK|SV* sv
-Returns a boolean indicating whether the SV contains an integer.
+=for apidoc Am|U32|SvIOK|SV* sv
+Returns a U32 value indicating whether the SV contains an integer.
 
 =for apidoc Am|void|SvIOK_on|SV* sv
 Tells an SV that it is an integer.
@@ -731,14 +803,14 @@ Tells and SV that it is an unsigned integer and disables all other OK bits.
 =for apidoc Am|bool|SvIOK_UV|SV* sv
 Returns a boolean indicating whether the SV contains an unsigned integer.
 
-=for apidoc Am|void|SvUOK|SV* sv
+=for apidoc Am|bool|SvUOK|SV* sv
 Returns a boolean indicating whether the SV contains an unsigned integer.
 
 =for apidoc Am|bool|SvIOK_notUV|SV* sv
 Returns a boolean indicating whether the SV contains a signed integer.
 
-=for apidoc Am|bool|SvNOK|SV* sv
-Returns a boolean indicating whether the SV contains a double.
+=for apidoc Am|U32|SvNOK|SV* sv
+Returns a U32 value indicating whether the SV contains a double.
 
 =for apidoc Am|void|SvNOK_on|SV* sv
 Tells an SV that it is a double.
@@ -749,8 +821,8 @@ Unsets the NV status of an SV.
 =for apidoc Am|void|SvNOK_only|SV* sv
 Tells an SV that it is a double and disables all other OK bits.
 
-=for apidoc Am|bool|SvPOK|SV* sv
-Returns a boolean indicating whether the SV contains a character
+=for apidoc Am|U32|SvPOK|SV* sv
+Returns a U32 value indicating whether the SV contains a character
 string.
 
 =for apidoc Am|void|SvPOK_on|SV* sv
@@ -766,13 +838,13 @@ Will also turn off the UTF-8 status.
 =for apidoc Am|bool|SvVOK|SV* sv
 Returns a boolean indicating whether the SV contains a v-string.
 
-=for apidoc Am|bool|SvOOK|SV* sv
-Returns a boolean indicating whether the SvIVX is a valid offset value for
+=for apidoc Am|U32|SvOOK|SV* sv
+Returns a U32 indicating whether the SvIVX is a valid offset value for
 the SvPVX.  This hack is used internally to speed up removal of characters
 from the beginning of a SvPV.  When SvOOK is true, then the start of the
 allocated string buffer is really (SvPVX - SvIVX).
 
-=for apidoc Am|bool|SvROK|SV* sv
+=for apidoc Am|U32|SvROK|SV* sv
 Tests if the SV is an RV.
 
 =for apidoc Am|void|SvROK_on|SV* sv
@@ -861,7 +933,9 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
 #define assert_not_glob(sv)    
 #endif
 
-#define SvOK(sv)               (SvFLAGS(sv) & SVf_OK)
+#define SvOK(sv)               ((SvTYPE(sv) == SVt_BIND)               \
+                                ? (SvFLAGS(SvRV(sv)) & SVf_OK)         \
+                                : (SvFLAGS(sv) & SVf_OK))
 #define SvOK_off(sv)           (assert_not_ROK(sv) assert_not_glob(sv) \
                                 SvFLAGS(sv) &= ~(SVf_OK|               \
                                                  SVf_IVisUV|SVf_UTF8), \
@@ -908,8 +982,8 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
                                    SvFLAGS(sv) |= (SVf_NOK|SVp_NOK))
 
 /*
-=for apidoc Am|bool|SvUTF8|SV* sv
-Returns a boolean indicating whether the SV contains UTF-8 encoded data.
+=for apidoc Am|U32|SvUTF8|SV* sv
+Returns a U32 value indicating whether the SV contains UTF-8 encoded data.
 Call this after SvPV() in case any call to string overloading updates the
 internal flag.
 
@@ -1131,9 +1205,9 @@ the scalar's value cannot change unless written to.
 #  define SvPAD_STATE_on(sv)   (SvFLAGS(sv) |= SVpad_NAME|SVpad_STATE)
 #endif
 
-#define OURSTASH(sv)   \
+#define SvOURSTASH(sv) \
        (SvPAD_OUR(sv) ? ((XPVMG*) SvANY(sv))->xmg_u.xmg_ourstash : NULL)
-#define OURSTASH_set(sv, st)                                   \
+#define SvOURSTASH_set(sv, st)                                 \
         STMT_START {                                           \
            assert(SvTYPE(sv) == SVt_PVMG);                     \
            ((XPVMG*) SvANY(sv))->xmg_u.xmg_ourstash = st;      \
@@ -1345,32 +1419,23 @@ the scalar's value cannot change unless written to.
                 } STMT_END
 
 
-#define PERL_FBM_TABLE_OFFSET 5        /* Number of bytes between EOS and table */
-#define PERL_FBM_FLAGS_OFFSET_FROM_TABLE -1
-/* how many characters in string before rare? */
-#if (BYTEORDER == 0x4321) || (BYTEORDER == 0x87654321)
-#  define PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE -2
-#  define PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE -3
-#else
-#  define PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE -2
-#  define PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE -3
-#endif
-/* rarest character in string */
-#define PERL_FBM_RARE_OFFSET_FROM_TABLE -4
+#define PERL_FBM_TABLE_OFFSET 1        /* Number of bytes between EOS and table */
 
 /* SvPOKp not SvPOK in the assertion because the string can be tainted! eg
    perl -T -e '/$^X/'
 */
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+#  define BmFLAGS(sv)                                                  \
+       (*({ SV *const uggh = (SV *) (sv);                              \
+               assert(SvTYPE(uggh) == SVt_PVGV);                       \
+               assert(SvVALID(uggh));                                  \
+           &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_flags);           \
+        }))
 #  define BmRARE(sv)                                                   \
        (*({ SV *const uggh = (SV *) (sv);                              \
                assert(SvTYPE(uggh) == SVt_PVGV);                       \
                assert(SvVALID(uggh));                                  \
-               assert(SvCUR(uggh) + PERL_FBM_TABLE_OFFSET              \
-                      + PERL_FBM_RARE_OFFSET_FROM_TABLE <= SvLEN(uggh)); \
-           assert(SvPOKp(uggh));                                       \
-           (U8*)(SvEND(uggh)                                           \
-                 + PERL_FBM_TABLE_OFFSET + PERL_FBM_RARE_OFFSET_FROM_TABLE); \
+           &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_rare);            \
         }))
 #  define BmUSEFUL(sv)                                                 \
        (*({ SV *const uggh = (SV *) (sv);                              \
@@ -1380,39 +1445,18 @@ the scalar's value cannot change unless written to.
            &(((XPVGV*) SvANY(uggh))->xiv_u.xivu_i32);                  \
         }))
 #  define BmPREVIOUS(sv)                                               \
-       ({ SV *const uggh = (SV *) (sv);                                \
-          assert(SvTYPE(uggh) == SVt_PVGV);                            \
-          assert(SvVALID(uggh));                                       \
-          assert(SvPOKp(uggh));                                        \
-          assert(SvCUR(uggh) + PERL_FBM_TABLE_OFFSET <= SvLEN(uggh));  \
-          (*(U8*)(SvEND(uggh) + PERL_FBM_TABLE_OFFSET                  \
-                 + PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE) << 8)        \
-              | (*(U8*)(SvEND(uggh) + PERL_FBM_TABLE_OFFSET            \
-                       + PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE));      \
-       })
+       (*({ SV *const uggh = (SV *) (sv);                              \
+               assert(SvTYPE(uggh) == SVt_PVGV);                       \
+               assert(SvVALID(uggh));                                  \
+           &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_previous);        \
+        }))
 #else
-#  define BmRARE(sv)                                                   \
-    (*(U8*)(SvEND(sv)                                                  \
-           + PERL_FBM_TABLE_OFFSET + PERL_FBM_RARE_OFFSET_FROM_TABLE))
-
-#  define BmUSEFUL(sv) ((XPVGV*)  SvANY(sv))->xiv_u.xivu_i32
-#  define BmPREVIOUS(sv)                                               \
-    ((*(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET                         \
-          + PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE) << 8)               \
-       | (*(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET                     \
-          + PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE)))                   \
+#  define BmFLAGS(sv)          ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_flags
+#  define BmRARE(sv)           ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_rare
+#  define BmUSEFUL(sv)         ((XPVGV*) SvANY(sv))->xiv_u.xivu_i32
+#  define BmPREVIOUS(sv)       ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_previous
 
 #endif
-#define BmPREVIOUS_set(sv, val)                                                \
-    STMT_START { assert(SvTYPE(sv) == SVt_PVGV);                       \
-       assert(SvVALID(sv));                                            \
-       assert(SvPOKp(sv));                                             \
-       assert(SvCUR(sv) + PERL_FBM_TABLE_OFFSET <= SvLEN(sv));         \
-       *(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET                        \
-              + PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE) = (U8)((U32)(val)>>8); \
-       *(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET                        \
-              + PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE) = (U8)(val);    \
-    } STMT_END
 
 #define FmLINES(sv)    ((XPVFM*)  SvANY(sv))->xfm_lines
 
@@ -1505,7 +1549,9 @@ stringified version becoming C<SvPOK>.  Handles 'get' magic. See also
 C<SvPVx> for a version which guarantees to evaluate sv only once.
 
 =for apidoc Am|char*|SvPVx|SV* sv|STRLEN len
-A version of C<SvPV> which guarantees to evaluate sv only once.
+A version of C<SvPV> which guarantees to evaluate C<sv> only once.
+Only use this if C<sv> is an expression with side effects, otherwise use the
+more efficient C<SvPVX>.
 
 =for apidoc Am|char*|SvPV_nomg|SV* sv|STRLEN len
 Like C<SvPV> but doesn't process magic.
@@ -1516,7 +1562,7 @@ the SV if the SV does not contain a string.  The SV may cache the
 stringified form becoming C<SvPOK>.  Handles 'get' magic.
 
 =for apidoc Am|IV|SvIV|SV* sv
-Coerces the given SV to an integer and returns it. See  C<SvIVx> for a
+Coerces the given SV to an integer and returns it. See C<SvIVx> for a
 version which guarantees to evaluate sv only once.
 
 =for apidoc Am|IV|SvIV_nomg|SV* sv
@@ -1524,15 +1570,17 @@ Like C<SvIV> but doesn't process magic.
 
 =for apidoc Am|IV|SvIVx|SV* sv
 Coerces the given SV to an integer and returns it. Guarantees to evaluate
-sv only once. Use the more efficient C<SvIV> otherwise.
+C<sv> only once. Only use this if C<sv> is an expression with side effects,
+otherwise use the more efficient C<SvIV>.
 
 =for apidoc Am|NV|SvNV|SV* sv
-Coerce the given SV to a double and return it. See  C<SvNVx> for a version
+Coerce the given SV to a double and return it. See C<SvNVx> for a version
 which guarantees to evaluate sv only once.
 
 =for apidoc Am|NV|SvNVx|SV* sv
 Coerces the given SV to a double and returns it. Guarantees to evaluate
-sv only once. Use the more efficient C<SvNV> otherwise.
+C<sv> only once. Only use this if C<sv> is an expression with side effects,
+otherwise use the more efficient C<SvNV>.
 
 =for apidoc Am|UV|SvUV|SV* sv
 Coerces the given SV to an unsigned integer and returns it.  See C<SvUVx>
@@ -1543,7 +1591,8 @@ Like C<SvUV> but doesn't process magic.
 
 =for apidoc Am|UV|SvUVx|SV* sv
 Coerces the given SV to an unsigned integer and returns it. Guarantees to
-evaluate sv only once. Use the more efficient C<SvUV> otherwise.
+C<sv> only once. Only use this if C<sv> is an expression with side effects,
+otherwise use the more efficient C<SvUV>.
 
 =for apidoc Am|bool|SvTRUE|SV* sv
 Returns a boolean indicating whether Perl would evaluate the SV as true or
@@ -1790,13 +1839,15 @@ Like C<sv_catsv> but doesn't process magic.
 #define SV_SMAGIC              128
 #define SV_HAS_TRAILING_NUL    256
 #define SV_COW_SHARED_HASH_KEYS        512
+/* This one is only enabled for PERL_OLD_COPY_ON_WRITE */
+#define SV_COW_OTHER_PVS       1024
 
 /* The core is safe for this COW optimisation. XS code on CPAN may not be.
    So only default to doing the COW setup if we're in the core.
  */
 #ifdef PERL_CORE
 #  ifndef SV_DO_COW_SVSETSV
-#    define SV_DO_COW_SVSETSV  SV_COW_SHARED_HASH_KEYS
+#    define SV_DO_COW_SVSETSV  SV_COW_SHARED_HASH_KEYS|SV_COW_OTHER_PVS
 #  endif
 #endif
 
@@ -1820,8 +1871,8 @@ Like C<sv_catsv> but doesn't process magic.
                                    sv_force_normal_flags(sv, SV_COW_DROP_PV)
 
 #ifdef PERL_OLD_COPY_ON_WRITE
-#  define SvRELEASE_IVX(sv)   ((void)((SvFLAGS(sv) & (SVf_OOK|SVf_READONLY|SVf_FAKE)) \
-                               && Perl_sv_release_IVX(aTHX_ sv)))
+#define SvRELEASE_IVX(sv)   \
+    ((SvIsCOW(sv) ? sv_force_normal_flags(sv, 0) : (void) 0), SvOOK_off(sv))
 #  define SvIsCOW_normal(sv)   (SvIsCOW(sv) && SvLEN(sv))
 #else
 #  define SvRELEASE_IVX(sv)   SvOOK_off(sv)