This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Backport patch from CPANPLUS-0.9004 to cpanp-run-perl
[perl5.git] / sv.h
diff --git a/sv.h b/sv.h
index ec4e518..815f109 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -1,7 +1,7 @@
 /*    sv.h
  *
 /*    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
+ *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ *    2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -48,11 +48,12 @@ typedef enum {
        SVt_BIND,       /* 1 */
        SVt_IV,         /* 2 */
        SVt_NV,         /* 3 */
        SVt_BIND,       /* 1 */
        SVt_IV,         /* 2 */
        SVt_NV,         /* 3 */
-       SVt_RV,         /* 4 */
-       SVt_PV,         /* 5 */
-       SVt_PVIV,       /* 6 */
-       SVt_PVNV,       /* 7 */
-       SVt_PVMG,       /* 8 */
+       /* RV was here, before it was merged with IV.  */
+       SVt_PV,         /* 4 */
+       SVt_PVIV,       /* 5 */
+       SVt_PVNV,       /* 6 */
+       SVt_PVMG,       /* 7 */
+       SVt_REGEXP,     /* 8 */
        /* PVBM was here, before BIND replaced it.  */
        SVt_PVGV,       /* 9 */
        SVt_PVLV,       /* 10 */
        /* PVBM was here, before BIND replaced it.  */
        SVt_PVGV,       /* 9 */
        SVt_PVLV,       /* 10 */
@@ -69,16 +70,15 @@ typedef enum {
    purposes eternal code wanting to consider PVBM probably needs to think of
    PVMG instead.  */
 #  define SVt_PVBM     SVt_PVMG
    purposes eternal code wanting to consider PVBM probably needs to think of
    PVMG instead.  */
 #  define SVt_PVBM     SVt_PVMG
+/* Anything wanting to create a reference from clean should ensure that it has
+   a scalar of type SVt_IV now:  */
+#  define SVt_RV       SVt_IV
 #endif
 
 /* There is collusion here with sv_clear - sv_clear exits early for SVt_NULL
 #endif
 
 /* There is collusion here with sv_clear - sv_clear exits early for SVt_NULL
-   and SVt_IV, so never reaches the clause at the end that uses
-   sv_type_details->body_size to determine whether to call safefree(). Hence
-   body_size can be set no-zero to record the size of PTEs and HEs, without
-   fear of bogus frees.  */
-#ifdef PERL_IN_SV_C
-#define PTE_SVSLOT     SVt_IV
-#endif
+   so never reaches the clause at the end that uses sv_type_details->body_size
+   to determine whether to call safefree(). Hence body_size can be set
+   non-zero to record the size of HEs, without fear of bogus frees.  */
 #if defined(PERL_IN_HV_C) || defined(PERL_IN_XS_APITEST)
 #define HE_SVSLOT      SVt_NULL
 #endif
 #if defined(PERL_IN_HV_C) || defined(PERL_IN_XS_APITEST)
 #define HE_SVSLOT      SVt_NULL
 #endif
@@ -99,10 +99,10 @@ typedef struct hek HEK;
 
 #define _SV_HEAD_UNION \
     union {                            \
 
 #define _SV_HEAD_UNION \
     union {                            \
+       char*   svu_pv;         /* pointer to malloced string */        \
        IV      svu_iv;                 \
        UV      svu_uv;                 \
        SV*     svu_rv;         /* pointer to another SV */             \
        IV      svu_iv;                 \
        UV      svu_uv;                 \
        SV*     svu_rv;         /* pointer to another SV */             \
-       char*   svu_pv;         /* pointer to malloced string */        \
        SV**    svu_array;              \
        HE**    svu_hash;               \
        GP*     svu_gp;                 \
        SV**    svu_array;              \
        HE**    svu_hash;               \
        GP*     svu_gp;                 \
@@ -113,10 +113,11 @@ struct STRUCT_SV {                /* struct sv { */
     _SV_HEAD(void*);
     _SV_HEAD_UNION;
 #ifdef DEBUG_LEAKING_SCALARS
     _SV_HEAD(void*);
     _SV_HEAD_UNION;
 #ifdef DEBUG_LEAKING_SCALARS
-    unsigned   sv_debug_optype:9;      /* the type of OP that allocated us */
-    unsigned   sv_debug_inpad:1;       /* was allocated in a pad for an OP */
-    unsigned   sv_debug_cloned:1;      /* was cloned for an ithread */
-    unsigned   sv_debug_line:16;       /* the line where we were allocated */
+    PERL_BITFIELD32 sv_debug_optype:9; /* the type of OP that allocated us */
+    PERL_BITFIELD32 sv_debug_inpad:1;  /* was allocated in a pad for an OP */
+    PERL_BITFIELD32 sv_debug_cloned:1; /* was cloned for an ithread */
+    PERL_BITFIELD32 sv_debug_line:16;  /* the line where we were allocated */
+    U32                    sv_debug_serial;    /* serial number of sv allocation   */
     char *     sv_debug_file;          /* the file where we were allocated */
 #endif
 };
     char *     sv_debug_file;          /* the file where we were allocated */
 #endif
 };
@@ -146,6 +147,11 @@ struct io {
     _SV_HEAD_UNION;
 };
 
     _SV_HEAD_UNION;
 };
 
+struct p5rx {
+    _SV_HEAD(struct regexp*);  /* pointer to regexp body */
+    _SV_HEAD_UNION;
+};
+
 #undef _SV_HEAD
 #undef _SV_HEAD_UNION          /* ensure no pollution */
 
 #undef _SV_HEAD
 #undef _SV_HEAD_UNION          /* ensure no pollution */
 
@@ -177,9 +183,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
 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>
 
 =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>
@@ -213,10 +218,10 @@ perform the upgrade if necessary.  See C<svtype>.
 #define SvFLAGS(sv)    (sv)->sv_flags
 #define SvREFCNT(sv)   (sv)->sv_refcnt
 
 #define SvFLAGS(sv)    (sv)->sv_flags
 #define SvREFCNT(sv)   (sv)->sv_refcnt
 
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && !defined(PERL_GCC_PEDANTIC)
+#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvREFCNT_inc(sv)             \
     ({                                 \
 #  define SvREFCNT_inc(sv)             \
     ({                                 \
-       SV * const _sv = (SV*)(sv);     \
+       SV * const _sv = MUTABLE_SV(sv);        \
        if (_sv)                        \
             (SvREFCNT(_sv))++;         \
        _sv;                            \
        if (_sv)                        \
             (SvREFCNT(_sv))++;         \
        _sv;                            \
@@ -225,41 +230,41 @@ perform the upgrade if necessary.  See C<svtype>.
     ({                                 \
        if (sv)                         \
             (SvREFCNT(sv))++;          \
     ({                                 \
        if (sv)                         \
             (SvREFCNT(sv))++;          \
-       (SV *)(sv);                             \
+       MUTABLE_SV(sv);                         \
     })
 #  define SvREFCNT_inc_NN(sv)          \
     ({                                 \
     })
 #  define SvREFCNT_inc_NN(sv)          \
     ({                                 \
-       SV * const _sv = (SV*)(sv);     \
+       SV * const _sv = MUTABLE_SV(sv);        \
        SvREFCNT(_sv)++;                \
        _sv;                            \
     })
 #  define SvREFCNT_inc_void(sv)                \
     ({                                 \
        SvREFCNT(_sv)++;                \
        _sv;                            \
     })
 #  define SvREFCNT_inc_void(sv)                \
     ({                                 \
-       SV * const _sv = (SV*)(sv);     \
+       SV * const _sv = MUTABLE_SV(sv);        \
        if (_sv)                        \
            (void)(SvREFCNT(_sv)++);    \
     })
 #else
 #  define SvREFCNT_inc(sv)     \
        if (_sv)                        \
            (void)(SvREFCNT(_sv)++);    \
     })
 #else
 #  define SvREFCNT_inc(sv)     \
-       ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
+       ((PL_Sv=MUTABLE_SV(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
 #  define SvREFCNT_inc_simple(sv) \
 #  define SvREFCNT_inc_simple(sv) \
-       ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL)
+       ((sv) ? (SvREFCNT(sv)++,MUTABLE_SV(sv)) : NULL)
 #  define SvREFCNT_inc_NN(sv) \
 #  define SvREFCNT_inc_NN(sv) \
-       (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv)
+       (PL_Sv=MUTABLE_SV(sv),++(SvREFCNT(PL_Sv)),PL_Sv)
 #  define SvREFCNT_inc_void(sv) \
 #  define SvREFCNT_inc_void(sv) \
-       (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0)
+       (void)((PL_Sv=MUTABLE_SV(sv)) ? ++(SvREFCNT(PL_Sv)) : 0)
 #endif
 
 /* These guys don't need the curly blocks */
 #define SvREFCNT_inc_simple_void(sv)   STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END
 #endif
 
 /* These guys don't need the curly blocks */
 #define SvREFCNT_inc_simple_void(sv)   STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END
-#define SvREFCNT_inc_simple_NN(sv)     (++(SvREFCNT(sv)),(SV*)(sv))
-#define SvREFCNT_inc_void_NN(sv)       (void)(++SvREFCNT((SV*)(sv)))
-#define SvREFCNT_inc_simple_void_NN(sv)        (void)(++SvREFCNT((SV*)(sv)))
+#define SvREFCNT_inc_simple_NN(sv)     (++(SvREFCNT(sv)),MUTABLE_SV(sv))
+#define SvREFCNT_inc_void_NN(sv)       (void)(++SvREFCNT(MUTABLE_SV(sv)))
+#define SvREFCNT_inc_simple_void_NN(sv)        (void)(++SvREFCNT(MUTABLE_SV(sv)))
 
 
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && !defined(PERL_GCC_PEDANTIC)
+#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvREFCNT_dec(sv)             \
     ({                                 \
 #  define SvREFCNT_dec(sv)             \
     ({                                 \
-       SV * const _sv = (SV*)(sv);     \
+       SV * const _sv = MUTABLE_SV(sv);        \
        if (_sv) {                      \
            if (SvREFCNT(_sv)) {        \
                if (--(SvREFCNT(_sv)) == 0) \
        if (_sv) {                      \
            if (SvREFCNT(_sv)) {        \
                if (--(SvREFCNT(_sv)) == 0) \
@@ -270,11 +275,11 @@ perform the upgrade if necessary.  See C<svtype>.
        }                               \
     })
 #else
        }                               \
     })
 #else
-#define SvREFCNT_dec(sv)       sv_free((SV*)(sv))
+#define SvREFCNT_dec(sv)       sv_free(MUTABLE_SV(sv))
 #endif
 
 #define SVTYPEMASK     0xff
 #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
 
 /* 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
@@ -320,18 +325,18 @@ perform the upgrade if necessary.  See C<svtype>.
                                       3: For PVCV, whether CvUNIQUE(cv)
                                          refers to an eval or once only
                                          [CvEVAL(cv), CvSPECIAL(cv)]
                                       3: For PVCV, whether CvUNIQUE(cv)
                                          refers to an eval or once only
                                          [CvEVAL(cv), CvSPECIAL(cv)]
-                                      4: Whether the regexp pointer is in
-                                         fact an offset [SvREPADTMP(sv)]
-                                      5: On a pad name SV, that slot in the
+                                      4: On a pad name SV, that slot in the
                                          frame AV is a REFCNT'ed reference
                                          to a lexical from "outside". */
                                          frame AV is a REFCNT'ed reference
                                          to a lexical from "outside". */
-#define SVphv_REHASH   SVf_FAKE    /* 6: On a PVHV, hash values are being
+#define SVphv_REHASH   SVf_FAKE    /* 5: On a PVHV, hash values are being
                                          recalculated */
 #define SVf_OOK                0x02000000  /* has valid offset value. For a PVHV this
                                       means that a hv_aux struct is present
                                       after the main array */
 #define SVf_BREAK      0x04000000  /* refcnt is artificially low - used by
                                          recalculated */
 #define SVf_OOK                0x02000000  /* has valid offset value. For a PVHV this
                                       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 */
+                                      SVs in final arena cleanup.
+                                      Set in S_regtry on PL_reg_curpm, so that
+                                      perl_destruct will skip it. */
 #define SVf_READONLY   0x08000000  /* may not be modified */
 
 
 #define SVf_READONLY   0x08000000  /* may not be modified */
 
 
@@ -345,15 +350,20 @@ perform the upgrade if necessary.  See C<svtype>.
 #define PRIVSHIFT 4    /* (SVp_?OK >> PRIVSHIFT) == SVf_?OK */
 
 #define SVf_AMAGIC     0x10000000  /* has magical overloaded methods */
 #define PRIVSHIFT 4    /* (SVp_?OK >> PRIVSHIFT) == SVf_?OK */
 
 #define SVf_AMAGIC     0x10000000  /* has magical overloaded methods */
+
+/* Ensure this value does not clash with the GV_ADD* flags in gv.h: */
 #define SVf_UTF8        0x20000000  /* SvPV is UTF-8 encoded
                                       This is also set on RVs whose overloaded
                                       stringification is UTF-8. This might
                                       only happen as a side effect of SvPV() */
                                           
 #define SVf_UTF8        0x20000000  /* SvPV is UTF-8 encoded
                                       This is also set on RVs whose overloaded
                                       stringification is UTF-8. This might
                                       only happen as a side effect of SvPV() */
                                           
-/* Ensure this value does not clash with the GV_ADD* flags in gv.h */
 
 /* Some private flags. */
 
 
 /* Some private flags. */
 
+/* PVAV could probably use 0x2000000 without conflict. I assume that PVFM can
+   be UTF-8 encoded, and PVCVs could well have UTF-8 prototypes. PVIOs haven't
+   been restructured, so sometimes get used as string buffers.  */
+
 /* PVHV */
 #define SVphv_SHAREKEYS 0x20000000  /* PVHV keys live on shared string table */
 /* PVNV, PVMG, presumably only inside pads */
 /* PVHV */
 #define SVphv_SHAREKEYS 0x20000000  /* PVHV keys live on shared string table */
 /* PVNV, PVMG, presumably only inside pads */
@@ -384,179 +394,77 @@ perform the upgrade if necessary.  See C<svtype>.
 /* RV upwards. However, SVf_ROK and SVp_IOK are exclusive  */
 #define SVprv_WEAKREF   0x80000000  /* Weak reference */
 
 /* RV upwards. However, SVf_ROK and SVp_IOK are exclusive  */
 #define SVprv_WEAKREF   0x80000000  /* Weak reference */
 
+#define _XPV_HEAD      \
+    union _xnvu xnv_u; \
+    STRLEN     xpv_cur;        /* length of svu_pv as a C string */    \
+    STRLEN     xpv_len         /* allocated size */
+
+union _xnvu {
+    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 */
+};
 
 
-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 */
+union _xivu {
+    IV     xivu_iv;            /* integer value */
+                               /* xpvfm: lines */
+    UV     xivu_uv;
+    void *  xivu_p1;
+    I32            xivu_i32;
+    HEK *   xivu_namehek;      /* xpvlv, xpvgv: GvNAME */
+    HV *    xivu_hv;           /* regexp: paren_names */
 };
 
 };
 
-typedef struct {
-    STRLEN     xpv_cur;        /* length of svu_pv as a C string */
-    STRLEN     xpv_len;        /* allocated size */
-} xpv_allocated;
+union _xmgu {
+    MAGIC*  xmg_magic;         /* linked list of magicalness */
+    HV*            xmg_ourstash;       /* Stash for our (when SvPAD_OUR is true) */
+};
 
 
-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 */
-    union {
-       IV      xivu_iv;        /* integer value or pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
+struct xpv {
+    _XPV_HEAD;
 };
 
 };
 
-typedef struct {
-    STRLEN     xpv_cur;        /* length of svu_pv as a C string */
-    STRLEN     xpv_len;        /* allocated size */
-    union {
-       IV      xivu_iv;        /* integer value or pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
-} xpviv_allocated;
+struct xpviv {
+    _XPV_HEAD;
+    union _xivu xiv_u;
+};
 
 #define xiv_iv xiv_u.xivu_iv
 
 struct xpvuv {
 
 #define xiv_iv xiv_u.xivu_iv
 
 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 */
-    union {
-       IV      xuvu_iv;
-       UV      xuvu_uv;        /* unsigned value or pv offset */
-       void *  xuvu_p1;
-       HEK *   xivu_namehek;
-    }          xuv_u;
+    _XPV_HEAD;
+    union _xivu xuv_u;
 };
 
 };
 
-#define xuv_uv xuv_u.xuvu_uv
+#define xuv_uv xuv_u.xivu_uv
 
 struct xpvnv {
 
 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 */
-    union {
-       IV      xivu_iv;        /* integer value or pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
+    _XPV_HEAD;
+    union _xivu xiv_u;
 };
 
 };
 
-/* These structure must match the beginning of struct xpvhv in hv.h. */
+#define _XPVMG_HEAD                                \
+    union _xivu xiv_u;                             \
+    union _xmgu        xmg_u;                              \
+    HV*                xmg_stash       /* class package */
+
+/* This structure must match the beginning of struct xpvhv in hv.h. */
 struct xpvmg {
 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 */
-    union {
-       IV      xivu_iv;        /* integer value or pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
-    union {
-       MAGIC*  xmg_magic;      /* linked list of magicalness */
-       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
-    } xmg_u;
-    HV*                xmg_stash;      /* class package */
+    _XPV_HEAD;
+    _XPVMG_HEAD;
 };
 
 struct xpvlv {
 };
 
 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 */
-    union {
-       IV      xivu_iv;        /* integer value or pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;   /* GvNAME */
-    }          xiv_u;
-    union {
-       MAGIC*  xmg_magic;      /* linked list of magicalness */
-       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
-    } xmg_u;
-    HV*                xmg_stash;      /* class package */
+    _XPV_HEAD;
+    _XPVMG_HEAD;
 
     STRLEN     xlv_targoff;
     STRLEN     xlv_targlen;
 
     STRLEN     xlv_targoff;
     STRLEN     xlv_targlen;
@@ -568,183 +476,75 @@ struct xpvlv {
 /* This structure works in 3 ways - regular scalar, GV with GP, or fast
    Boyer-Moore.  */
 struct xpvgv {
 /* This structure works in 3 ways - regular scalar, GV with GP, or fast
    Boyer-Moore.  */
 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 */
-    union {
-       IV      xivu_iv;
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;       /* is this constant pattern being useful? */
-       HEK *   xivu_namehek;   /* GvNAME */
-    }          xiv_u;
-    union {
-       MAGIC*  xmg_magic;      /* linked list of magicalness */
-       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
-    } xmg_u;
-    HV*                xmg_stash;      /* class package */
-
+    _XPV_HEAD;
+    _XPVMG_HEAD;
 };
 
 /* This structure must match XPVCV in cv.h */
 
 typedef U16 cv_flags_t;
 
 };
 
 /* This structure must match XPVCV in cv.h */
 
 typedef U16 cv_flags_t;
 
+#define _XPVCV_COMMON                                                          \
+    HV *       xcv_stash;                                                      \
+    union {                                                                    \
+       OP *    xcv_start;                                                      \
+       ANY     xcv_xsubany;                                                    \
+    }          xcv_start_u;                                                    \
+    union {                                                                    \
+       OP *    xcv_root;                                                       \
+       void    (*xcv_xsub) (pTHX_ CV*);                                        \
+    }          xcv_root_u;                                                     \
+    GV *       xcv_gv;                                                         \
+    char *     xcv_file;                                                       \
+    AV *       xcv_padlist;                                                    \
+    CV *       xcv_outside;                                                    \
+    U32                xcv_outside_seq; /* the COP sequence (at the point of our       \
+                                 * compilation) in the lexically enclosing     \
+                                 * sub */                                      \
+    cv_flags_t xcv_flags
+
 struct xpvfm {
 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 */
-    union {
-       IV      xivu_iv;        /* PVFMs use the pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
-    union {
-       MAGIC*  xmg_magic;      /* linked list of magicalness */
-       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
-    } xmg_u;
-    HV*                xmg_stash;      /* class package */
-
-    HV *       xcv_stash;
-    union {
-       OP *    xcv_start;
-       ANY     xcv_xsubany;
-    }          xcv_start_u;
-    union {
-       OP *    xcv_root;
-       void    (*xcv_xsub) (pTHX_ CV*);
-    }          xcv_root_u;
-    GV *       xcv_gv;
-    char *     xcv_file;
-    AV *       xcv_padlist;
-    CV *       xcv_outside;
-    U32                xcv_outside_seq; /* the COP sequence (at the point of our
-                                 * compilation) in the lexically enclosing
-                                 * sub */
-    cv_flags_t xcv_flags;
-    IV         xfm_lines;
+    _XPV_HEAD;
+    _XPVMG_HEAD;
+    _XPVCV_COMMON;
 };
 
 };
 
-typedef struct {
-    STRLEN     xpv_cur;        /* length of svu_pv as a C string */
-    STRLEN     xpv_len;        /* allocated size */
-    union {
-       IV      xivu_iv;        /* PVFMs use the pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
-    union {
-       MAGIC*  xmg_magic;      /* linked list of magicalness */
-       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
-    } xmg_u;
-    HV*                xmg_stash;      /* class package */
-
-    HV *       xcv_stash;
-    union {
-       OP *    xcv_start;
-       ANY     xcv_xsubany;
-    }          xcv_start_u;
-    union {
-       OP *    xcv_root;
-       void    (*xcv_xsub) (pTHX_ CV*);
-    }          xcv_root_u;
-    GV *       xcv_gv;
-    char *     xcv_file;
-    AV *       xcv_padlist;
-    CV *       xcv_outside;
-    U32                xcv_outside_seq; /* the COP sequence (at the point of our
-                                 * compilation) in the lexically enclosing
-                                 * sub */
-    cv_flags_t xcv_flags;
-    IV         xfm_lines;
-} xpvfm_allocated;
+#define _XPVIO_TAIL                                                    \
+    PerlIO *   xio_ifp;        /* ifp and ofp are normally the same */ \
+    PerlIO *   xio_ofp;        /* but sockets need separate streams */ \
+    /* Cray addresses everything by word boundaries (64 bits) and      \
+     * code and data pointers cannot be mixed (which is exactly what   \
+     * Perl_filter_add() tries to do with the dirp), hence the         \
+     *  following union trick (as suggested by Gurusamy Sarathy).      \
+     * For further information see Geir Johansen's problem report      \
+     * titled [ID 20000612.002] Perl problem on Cray system            \
+     * The any pointer (known as IoANY()) will also be a good place    \
+     * to hang any IO disciplines to.                                  \
+     */                                                                        \
+    union {                                                            \
+       DIR *   xiou_dirp;      /* for opendir, readdir, etc */         \
+       void *  xiou_any;       /* for alignment */                     \
+    } xio_dirpu;                                                       \
+    /* IV xio_lines is now in IVX  $. */                               \
+    IV         xio_page;       /* $% */                                \
+    IV         xio_page_len;   /* $= */                                \
+    IV         xio_lines_left; /* $- */                                \
+    char *     xio_top_name;   /* $^ */                                \
+    GV *       xio_top_gv;     /* $^ */                                \
+    char *     xio_fmt_name;   /* $~ */                                \
+    GV *       xio_fmt_gv;     /* $~ */                                \
+    char *     xio_bottom_name;/* $^B */                               \
+    GV *       xio_bottom_gv;  /* $^B */                               \
+    char       xio_type;                                               \
+    U8         xio_flags
+
 
 struct xpvio {
 
 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 */
-    union {
-       IV      xivu_iv;        /* integer value or pv offset */
-       UV      xivu_uv;
-       void *  xivu_p1;
-       I32     xivu_i32;
-       HEK *   xivu_namehek;
-    }          xiv_u;
-    union {
-       MAGIC*  xmg_magic;      /* linked list of magicalness */
-       HV*     xmg_ourstash;   /* Stash for our (when SvPAD_OUR is true) */
-    } xmg_u;
-    HV*                xmg_stash;      /* class package */
-
-    PerlIO *   xio_ifp;        /* ifp and ofp are normally the same */
-    PerlIO *   xio_ofp;        /* but sockets need separate streams */
-    /* Cray addresses everything by word boundaries (64 bits) and
-     * code and data pointers cannot be mixed (which is exactly what
-     * Perl_filter_add() tries to do with the dirp), hence the following
-     * union trick (as suggested by Gurusamy Sarathy).
-     * For further information see Geir Johansen's problem report titled
-       [ID 20000612.002] Perl problem on Cray system
-     * The any pointer (known as IoANY()) will also be a good place
-     * to hang any IO disciplines to.
-     */
-    union {
-       DIR *   xiou_dirp;      /* for opendir, readdir, etc */
-       void *  xiou_any;       /* for alignment */
-    } xio_dirpu;
-    IV         xio_lines;      /* $. */
-    IV         xio_page;       /* $% */
-    IV         xio_page_len;   /* $= */
-    IV         xio_lines_left; /* $- */
-    char *     xio_top_name;   /* $^ */
-    GV *       xio_top_gv;     /* $^ */
-    char *     xio_fmt_name;   /* $~ */
-    GV *       xio_fmt_gv;     /* $~ */
-    char *     xio_bottom_name;/* $^B */
-    GV *       xio_bottom_gv;  /* $^B */
-    short      xio_subprocess; /* -| or |- */
-    char       xio_type;
-    char       xio_flags;
+    _XPV_HEAD;
+    _XPVMG_HEAD;
+    _XPVIO_TAIL;
 };
 };
+
 #define xio_dirp       xio_dirpu.xiou_dirp
 #define xio_any                xio_dirpu.xiou_any
 
 #define xio_dirp       xio_dirpu.xiou_dirp
 #define xio_any                xio_dirpu.xiou_any
 
@@ -759,35 +559,35 @@ struct xpvio {
 /* The following macros define implementation-independent predicates on SVs. */
 
 /*
 /* 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.
 
 double.
 
-=for apidoc Am|bool|SvNIOKp|SV* sv
-Returns a boolean indicating whether the SV contains a number, integer or
-double.  Checks the B<private> setting.  Use C<SvNIOK>.
+=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> instead.
 
 =for apidoc Am|void|SvNIOK_off|SV* sv
 Unsets the NV/IV status of an SV.
 
 
 =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
-whether the value is defined or not.
+=for apidoc Am|U32|SvOK|SV* sv
+Returns a U32 value indicating whether the value is defined. This is
+only meaningful for scalars.
 
 
-=for apidoc Am|bool|SvIOKp|SV* sv
-Returns a boolean indicating whether the SV contains an integer.  Checks
-the B<private> setting.  Use C<SvIOK>.
+=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> instead.
 
 
-=for apidoc Am|bool|SvNOKp|SV* sv
-Returns a boolean indicating whether the SV contains a double.  Checks the
-B<private> setting.  Use C<SvNOK>.
+=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> instead.
 
 
-=for apidoc Am|bool|SvPOKp|SV* sv
-Returns a boolean indicating whether the SV contains a character string.
-Checks the B<private> setting.  Use C<SvPOK>.
+=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> instead.
 
 
-=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.
 
 =for apidoc Am|void|SvIOK_on|SV* sv
 Tells an SV that it is an integer.
@@ -804,14 +604,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|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.
 
 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.
 
 =for apidoc Am|void|SvNOK_on|SV* sv
 Tells an SV that it is a double.
@@ -822,8 +622,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|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
 string.
 
 =for apidoc Am|void|SvPOK_on|SV* sv
@@ -839,13 +639,15 @@ 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|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
-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|U32|SvOOK|SV* sv
+Returns a U32 indicating whether the pointer to the string buffer is offset.
+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 actually C<SvOOK_offset()> bytes before SvPVX.
+This offset used to be stored in SvIVX, but is now stored within the spare
+part of the buffer.
 
 
-=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
 Tests if the SV is an RV.
 
 =for apidoc Am|void|SvROK_on|SV* sv
@@ -948,7 +750,7 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
 
 #define SvOKp(sv)              (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK))
 #define SvIOKp(sv)             (SvFLAGS(sv) & SVp_IOK)
 
 #define SvOKp(sv)              (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK))
 #define SvIOKp(sv)             (SvFLAGS(sv) & SVp_IOK)
-#define SvIOKp_on(sv)          (assert_not_glob(sv) SvRELEASE_IVX(sv), \
+#define SvIOKp_on(sv)          (assert_not_glob(sv) SvRELEASE_IVX_(sv) \
                                    SvFLAGS(sv) |= SVp_IOK)
 #define SvNOKp(sv)             (SvFLAGS(sv) & SVp_NOK)
 #define SvNOKp_on(sv)          (assert_not_glob(sv) SvFLAGS(sv) |= SVp_NOK)
                                    SvFLAGS(sv) |= SVp_IOK)
 #define SvNOKp(sv)             (SvFLAGS(sv) & SVp_NOK)
 #define SvNOKp_on(sv)          (assert_not_glob(sv) SvFLAGS(sv) |= SVp_NOK)
@@ -957,7 +759,7 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
                                 SvFLAGS(sv) |= SVp_POK)
 
 #define SvIOK(sv)              (SvFLAGS(sv) & SVf_IOK)
                                 SvFLAGS(sv) |= SVp_POK)
 
 #define SvIOK(sv)              (SvFLAGS(sv) & SVf_IOK)
-#define SvIOK_on(sv)           (assert_not_glob(sv) SvRELEASE_IVX(sv), \
+#define SvIOK_on(sv)           (assert_not_glob(sv) SvRELEASE_IVX_(sv) \
                                    SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
 #define SvIOK_off(sv)          (SvFLAGS(sv) &= ~(SVf_IOK|SVp_IOK|SVf_IVisUV))
 #define SvIOK_only(sv)         (SvOK_off(sv), \
                                    SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
 #define SvIOK_off(sv)          (SvFLAGS(sv) &= ~(SVf_IOK|SVp_IOK|SVf_IVisUV))
 #define SvIOK_only(sv)         (SvOK_off(sv), \
@@ -983,8 +785,8 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
                                    SvFLAGS(sv) |= (SVf_NOK|SVp_NOK))
 
 /*
                                    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.
 
 Call this after SvPV() in case any call to string overloading updates the
 internal flag.
 
@@ -1072,7 +874,7 @@ in gv.h: */
 #endif
 
 /*
 #endif
 
 /*
-=for apidoc Am|char*|SvGAMAGIC|SV* sv
+=for apidoc Am|U32|SvGAMAGIC|SV* sv
 
 Returns true if the SV has get magic or overloading. If either is true then
 the scalar is active data, and has the potential to return a new value every
 
 Returns true if the SV has get magic or overloading. If either is true then
 the scalar is active data, and has the potential to return a new value every
@@ -1085,7 +887,7 @@ the scalar's value cannot change unless written to.
 
 #define SvGAMAGIC(sv)           (SvGMAGICAL(sv) || SvAMAGIC(sv))
 
 
 #define SvGAMAGIC(sv)           (SvGMAGICAL(sv) || SvAMAGIC(sv))
 
-#define Gv_AMG(stash)           (PL_amagic_generation && Gv_AMupdate(stash))
+#define Gv_AMG(stash)           (PL_amagic_generation && Gv_AMupdate(stash, FALSE))
 
 #define SvWEAKREF(sv)          ((SvFLAGS(sv) & (SVf_ROK|SVprv_WEAKREF)) \
                                  == (SVf_ROK|SVprv_WEAKREF))
 
 #define SvWEAKREF(sv)          ((SvFLAGS(sv) & (SVf_ROK|SVprv_WEAKREF)) \
                                  == (SVf_ROK|SVprv_WEAKREF))
@@ -1135,23 +937,23 @@ the scalar's value cannot change unless written to.
 #define SvEVALED_off(sv)       (SvFLAGS(sv) &= ~SVrepl_EVAL)
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #define SvEVALED_off(sv)       (SvFLAGS(sv) &= ~SVrepl_EVAL)
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
-#  define SvVALID(sv)          ({ SV *const thwacke = (SV *) (sv);     \
-                                  if (SvFLAGS(thwacke) & SVpbm_VALID)  \
-                                      assert(!isGV_with_GP(thwacke));  \
-                                  (SvFLAGS(thwacke) & SVpbm_VALID);    \
+#  define SvVALID(sv)          ({ const SV *const _svvalid = (const SV*)(sv); \
+                                  if (SvFLAGS(_svvalid) & SVpbm_VALID) \
+                                      assert(!isGV_with_GP(_svvalid)); \
+                                  (SvFLAGS(_svvalid) & SVpbm_VALID);   \
                                })
                                })
-#  define SvVALID_on(sv)       ({ SV *const thwacke = (SV *) (sv);     \
-                                  assert(!isGV_with_GP(thwacke));      \
-                                  (SvFLAGS(thwacke) |= SVpbm_VALID);   \
+#  define SvVALID_on(sv)       ({ SV *const _svvalid = MUTABLE_SV(sv); \
+                                  assert(!isGV_with_GP(_svvalid));     \
+                                  (SvFLAGS(_svvalid) |= SVpbm_VALID);  \
                                })
                                })
-#  define SvVALID_off(sv)      ({ SV *const thwacke = (SV *) (sv);     \
-                                  assert(!isGV_with_GP(thwacke));      \
-                                  (SvFLAGS(thwacke) &= ~SVpbm_VALID);  \
+#  define SvVALID_off(sv)      ({ SV *const _svvalid = MUTABLE_SV(sv); \
+                                  assert(!isGV_with_GP(_svvalid));     \
+                                  (SvFLAGS(_svvalid) &= ~SVpbm_VALID); \
                                })
 
                                })
 
-#  define SvTAIL(sv)   ({ SV *const _svi = (SV *) (sv);                \
-                           assert(SvTYPE(_svi) != SVt_PVAV);           \
-                           assert(SvTYPE(_svi) != SVt_PVHV);           \
+#  define SvTAIL(sv)   ({ const SV *const _svtail = (const SV *)(sv);  \
+                           assert(SvTYPE(_svtail) != SVt_PVAV);                \
+                           assert(SvTYPE(_svtail) != SVt_PVHV);                \
                            (SvFLAGS(sv) & (SVpbm_TAIL|SVpbm_VALID))    \
                                == (SVpbm_TAIL|SVpbm_VALID);            \
                        })
                            (SvFLAGS(sv) & (SVpbm_TAIL|SVpbm_VALID))    \
                                == (SVpbm_TAIL|SVpbm_VALID);            \
                        })
@@ -1167,14 +969,6 @@ the scalar's value cannot change unless written to.
 #define SvTAIL_off(sv)         (SvFLAGS(sv) &= ~SVpbm_TAIL)
 
 
 #define SvTAIL_off(sv)         (SvFLAGS(sv) &= ~SVpbm_TAIL)
 
 
-#ifdef USE_ITHREADS
-/* The following uses the FAKE flag to show that a regex pointer is infact
-   its own offset in the regexpad for ithreads */
-#define SvREPADTMP(sv)         (SvFLAGS(sv) & SVf_FAKE)
-#define SvREPADTMP_on(sv)      (SvFLAGS(sv) |= SVf_FAKE)
-#define SvREPADTMP_off(sv)     (SvFLAGS(sv) &= ~SVf_FAKE)
-#endif
-
 #define SvPAD_TYPED(sv) \
        ((SvFLAGS(sv) & (SVpad_NAME|SVpad_TYPED)) == (SVpad_NAME|SVpad_TYPED))
 
 #define SvPAD_TYPED(sv) \
        ((SvFLAGS(sv) & (SVpad_NAME|SVpad_TYPED)) == (SVpad_NAME|SVpad_TYPED))
 
@@ -1186,19 +980,19 @@ the scalar's value cannot change unless written to.
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvPAD_TYPED_on(sv)   ({                                      \
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvPAD_TYPED_on(sv)   ({                                      \
-           SV *const whap = (SV *) (sv);                               \
-           assert(SvTYPE(whap) == SVt_PVMG);                           \
-           (SvFLAGS(whap) |= SVpad_NAME|SVpad_TYPED);                  \
+           SV *const _svpad = MUTABLE_SV(sv);                          \
+           assert(SvTYPE(_svpad) == SVt_PVMG);                         \
+           (SvFLAGS(_svpad) |= SVpad_NAME|SVpad_TYPED);                \
        })
 #define SvPAD_OUR_on(sv)       ({                                      \
        })
 #define SvPAD_OUR_on(sv)       ({                                      \
-           SV *const whap = (SV *) (sv);                               \
-           assert(SvTYPE(whap) == SVt_PVMG);                           \
-           (SvFLAGS(whap) |= SVpad_NAME|SVpad_OUR);                    \
+           SV *const _svpad = MUTABLE_SV(sv);                          \
+           assert(SvTYPE(_svpad) == SVt_PVMG);                         \
+           (SvFLAGS(_svpad) |= SVpad_NAME|SVpad_OUR);                  \
        })
 #define SvPAD_STATE_on(sv)     ({                                      \
        })
 #define SvPAD_STATE_on(sv)     ({                                      \
-           SV *const whap = (SV *) (sv);                               \
-           assert(SvTYPE(whap) == SVt_PVNV || SvTYPE(whap) == SVt_PVMG); \
-           (SvFLAGS(whap) |= SVpad_NAME|SVpad_STATE);                  \
+           SV *const _svpad = MUTABLE_SV(sv);                          \
+           assert(SvTYPE(_svpad) == SVt_PVNV || SvTYPE(_svpad) == SVt_PVMG); \
+           (SvFLAGS(_svpad) |= SVpad_NAME|SVpad_STATE);                \
        })
 #else
 #  define SvPAD_TYPED_on(sv)   (SvFLAGS(sv) |= SVpad_NAME|SVpad_TYPED)
        })
 #else
 #  define SvPAD_TYPED_on(sv)   (SvFLAGS(sv) |= SVpad_NAME|SVpad_TYPED)
@@ -1206,18 +1000,16 @@ the scalar's value cannot change unless written to.
 #  define SvPAD_STATE_on(sv)   (SvFLAGS(sv) |= SVpad_NAME|SVpad_STATE)
 #endif
 
 #  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)
        (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;      \
        } STMT_END
 
 #ifdef PERL_DEBUG_COW
         STMT_START {                                           \
            assert(SvTYPE(sv) == SVt_PVMG);                     \
            ((XPVMG*) SvANY(sv))->xmg_u.xmg_ourstash = st;      \
        } STMT_END
 
 #ifdef PERL_DEBUG_COW
-#define SvRV(sv) (0 + (sv)->sv_u.svu_rv)
 #else
 #else
-#define SvRV(sv) ((sv)->sv_u.svu_rv)
 #endif
 #define SvRVx(sv) SvRV(sv)
 
 #endif
 #define SvRVx(sv) SvRV(sv)
 
@@ -1227,6 +1019,8 @@ the scalar's value cannot change unless written to.
 #  define SvIVX(sv) (0 + ((XPVIV*) SvANY(sv))->xiv_iv)
 #  define SvUVX(sv) (0 + ((XPVUV*) SvANY(sv))->xuv_uv)
 #  define SvNVX(sv) (-0.0 + ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv)
 #  define SvIVX(sv) (0 + ((XPVIV*) SvANY(sv))->xiv_iv)
 #  define SvUVX(sv) (0 + ((XPVUV*) SvANY(sv))->xuv_uv)
 #  define SvNVX(sv) (-0.0 + ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv)
+#  define SvRV(sv) (0 + (sv)->sv_u.svu_rv)
+#  define SvRV_const(sv) (0 + (sv)->sv_u.svu_rv)
 /* Don't test the core XS code yet.  */
 #  if defined (PERL_CORE) && PERL_DEBUG_COW > 1
 #    define SvPVX(sv) (0 + (assert(!SvREADONLY(sv)), (sv)->sv_u.svu_pv))
 /* Don't test the core XS code yet.  */
 #  if defined (PERL_CORE) && PERL_DEBUG_COW > 1
 #    define SvPVX(sv) (0 + (assert(!SvREADONLY(sv)), (sv)->sv_u.svu_pv))
@@ -1251,60 +1045,85 @@ the scalar's value cannot change unless written to.
 #  if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 /* These get expanded inside other macros that already use a variable _sv  */
 #    define SvPVX(sv)                                                  \
 #  if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 /* These get expanded inside other macros that already use a variable _sv  */
 #    define SvPVX(sv)                                                  \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) >= SVt_PV);                             \
-           assert(SvTYPE(_svi) != SVt_PVAV);                           \
-           assert(SvTYPE(_svi) != SVt_PVHV);                           \
-           assert(!isGV_with_GP(_svi));                                \
-           &((_svi)->sv_u.svu_pv);                                     \
+       (*({ SV *const _svpvx = MUTABLE_SV(sv);                         \
+           assert(SvTYPE(_svpvx) >= SVt_PV);                           \
+           assert(SvTYPE(_svpvx) != SVt_PVAV);                         \
+           assert(SvTYPE(_svpvx) != SVt_PVHV);                         \
+           assert(!isGV_with_GP(_svpvx));                              \
+           &((_svpvx)->sv_u.svu_pv);                                   \
         }))
 #    define SvCUR(sv)                                                  \
         }))
 #    define SvCUR(sv)                                                  \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) >= SVt_PV);                             \
-           assert(SvTYPE(_svi) != SVt_PVAV);                           \
-           assert(SvTYPE(_svi) != SVt_PVHV);                           \
-           assert(!isGV_with_GP(_svi));                                \
-           &(((XPV*) SvANY(_svi))->xpv_cur);                           \
+       (*({ const SV *const _svcur = (const SV *)(sv);                 \
+           assert(SvTYPE(_svcur) >= SVt_PV);                           \
+           assert(SvTYPE(_svcur) != SVt_PVAV);                         \
+           assert(SvTYPE(_svcur) != SVt_PVHV);                         \
+           assert(!isGV_with_GP(_svcur));                              \
+           &(((XPV*) MUTABLE_PTR(SvANY(_svcur)))->xpv_cur);            \
         }))
 #    define SvIVX(sv)                                                  \
         }))
 #    define SvIVX(sv)                                                  \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) == SVt_IV || SvTYPE(_svi) >= SVt_PVIV); \
-           assert(SvTYPE(_svi) != SVt_PVAV);                           \
-           assert(SvTYPE(_svi) != SVt_PVHV);                           \
-           assert(SvTYPE(_svi) != SVt_PVCV);                           \
-           assert(!isGV_with_GP(_svi));                                \
-           &(((XPVIV*) SvANY(_svi))->xiv_iv);                          \
+       (*({ const SV *const _svivx = (const SV *)(sv);                 \
+           assert(SvTYPE(_svivx) == SVt_IV || SvTYPE(_svivx) >= SVt_PVIV); \
+           assert(SvTYPE(_svivx) != SVt_PVAV);                         \
+           assert(SvTYPE(_svivx) != SVt_PVHV);                         \
+           assert(SvTYPE(_svivx) != SVt_PVCV);                         \
+           assert(SvTYPE(_svivx) != SVt_PVFM);                         \
+           assert(SvTYPE(_svivx) != SVt_PVIO);                         \
+           assert(!isGV_with_GP(_svivx));                              \
+           &(((XPVIV*) MUTABLE_PTR(SvANY(_svivx)))->xiv_iv);           \
         }))
 #    define SvUVX(sv)                                                  \
         }))
 #    define SvUVX(sv)                                                  \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) == SVt_IV || SvTYPE(_svi) >= SVt_PVIV); \
-           assert(SvTYPE(_svi) != SVt_PVAV);                           \
-           assert(SvTYPE(_svi) != SVt_PVHV);                           \
-           assert(SvTYPE(_svi) != SVt_PVCV);                           \
-           assert(!isGV_with_GP(_svi));                                \
-           &(((XPVUV*) SvANY(_svi))->xuv_uv);                          \
+       (*({ const SV *const _svuvx = (const SV *)(sv);                 \
+           assert(SvTYPE(_svuvx) == SVt_IV || SvTYPE(_svuvx) >= SVt_PVIV); \
+           assert(SvTYPE(_svuvx) != SVt_PVAV);                         \
+           assert(SvTYPE(_svuvx) != SVt_PVHV);                         \
+           assert(SvTYPE(_svuvx) != SVt_PVCV);                         \
+           assert(SvTYPE(_svuvx) != SVt_PVFM);                         \
+           assert(SvTYPE(_svuvx) != SVt_PVIO);                         \
+           assert(!isGV_with_GP(_svuvx));                              \
+           &(((XPVUV*) MUTABLE_PTR(SvANY(_svuvx)))->xuv_uv);           \
         }))
 #    define SvNVX(sv)                                                  \
         }))
 #    define SvNVX(sv)                                                  \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) == SVt_NV || SvTYPE(_svi) >= SVt_PVNV); \
-           assert(SvTYPE(_svi) != SVt_PVAV);                           \
-           assert(SvTYPE(_svi) != SVt_PVHV);                           \
-           assert(SvTYPE(_svi) != SVt_PVCV);                           \
-           assert(SvTYPE(_svi) != SVt_PVFM);                           \
-           assert(!isGV_with_GP(_svi));                                \
-          &(((XPVNV*) SvANY(_svi))->xnv_u.xnv_nv);                     \
+       (*({ const SV *const _svnvx = (const SV *)(sv);                 \
+           assert(SvTYPE(_svnvx) == SVt_NV || SvTYPE(_svnvx) >= SVt_PVNV); \
+           assert(SvTYPE(_svnvx) != SVt_PVAV);                         \
+           assert(SvTYPE(_svnvx) != SVt_PVHV);                         \
+           assert(SvTYPE(_svnvx) != SVt_PVCV);                         \
+           assert(SvTYPE(_svnvx) != SVt_PVFM);                         \
+           assert(SvTYPE(_svnvx) != SVt_PVIO);                         \
+           assert(!isGV_with_GP(_svnvx));                              \
+           &(((XPVNV*) MUTABLE_PTR(SvANY(_svnvx)))->xnv_u.xnv_nv);     \
+        }))
+#    define SvRV(sv)                                                   \
+       (*({ SV *const _svrv = MUTABLE_SV(sv);                          \
+           assert(SvTYPE(_svrv) >= SVt_PV || SvTYPE(_svrv) == SVt_IV); \
+           assert(SvTYPE(_svrv) != SVt_PVAV);                          \
+           assert(SvTYPE(_svrv) != SVt_PVHV);                          \
+           assert(SvTYPE(_svrv) != SVt_PVCV);                          \
+           assert(SvTYPE(_svrv) != SVt_PVFM);                          \
+           assert(!isGV_with_GP(_svrv));                               \
+           &((_svrv)->sv_u.svu_rv);                                    \
         }))
         }))
+#    define SvRV_const(sv)                                             \
+       ({ const SV *const _svrv = (const SV *)(sv);                    \
+           assert(SvTYPE(_svrv) >= SVt_PV || SvTYPE(_svrv) == SVt_IV); \
+           assert(SvTYPE(_svrv) != SVt_PVAV);                          \
+           assert(SvTYPE(_svrv) != SVt_PVHV);                          \
+           assert(SvTYPE(_svrv) != SVt_PVCV);                          \
+           assert(SvTYPE(_svrv) != SVt_PVFM);                          \
+           assert(!isGV_with_GP(_svrv));                               \
+           (_svrv)->sv_u.svu_rv;                                       \
+        })
 #    define SvMAGIC(sv)                                                        \
 #    define SvMAGIC(sv)                                                        \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) >= SVt_PVMG);                           \
-           if(SvTYPE(_svi) == SVt_PVMG)                                \
-               assert(!SvPAD_OUR(_svi));                               \
-           &(((XPVMG*) SvANY(_svi))->xmg_u.xmg_magic);                 \
+       (*({ const SV *const _svmagic = (const SV *)(sv);               \
+           assert(SvTYPE(_svmagic) >= SVt_PVMG);                       \
+           if(SvTYPE(_svmagic) == SVt_PVMG)                            \
+               assert(!SvPAD_OUR(_svmagic));                           \
+           &(((XPVMG*) MUTABLE_PTR(SvANY(_svmagic)))->xmg_u.xmg_magic); \
          }))
 #    define SvSTASH(sv)                                                        \
          }))
 #    define SvSTASH(sv)                                                        \
-       (*({ SV *const _svi = (SV *) (sv);                              \
-           assert(SvTYPE(_svi) >= SVt_PVMG);                           \
-           &(((XPVMG*) SvANY(_svi))->xmg_stash);                       \
+       (*({ const SV *const _svstash = (const SV *)(sv);               \
+           assert(SvTYPE(_svstash) >= SVt_PVMG);                       \
+           &(((XPVMG*) MUTABLE_PTR(SvANY(_svstash)))->xmg_stash);      \
          }))
 #  else
 #    define SvPVX(sv) ((sv)->sv_u.svu_pv)
          }))
 #  else
 #    define SvPVX(sv) ((sv)->sv_u.svu_pv)
@@ -1312,6 +1131,8 @@ the scalar's value cannot change unless written to.
 #    define SvIVX(sv) ((XPVIV*) SvANY(sv))->xiv_iv
 #    define SvUVX(sv) ((XPVUV*) SvANY(sv))->xuv_uv
 #    define SvNVX(sv) ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv
 #    define SvIVX(sv) ((XPVIV*) SvANY(sv))->xiv_iv
 #    define SvUVX(sv) ((XPVUV*) SvANY(sv))->xuv_uv
 #    define SvNVX(sv) ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv
+#    define SvRV(sv) ((sv)->sv_u.svu_rv)
+#    define SvRV_const(sv) (0 + (sv)->sv_u.svu_rv)
 #    define SvMAGIC(sv)        ((XPVMG*)  SvANY(sv))->xmg_u.xmg_magic
 #    define SvSTASH(sv)        ((XPVMG*)  SvANY(sv))->xmg_stash
 #  endif
 #    define SvMAGIC(sv)        ((XPVMG*)  SvANY(sv))->xmg_u.xmg_magic
 #    define SvSTASH(sv)        ((XPVMG*)  SvANY(sv))->xmg_stash
 #  endif
@@ -1354,6 +1175,7 @@ the scalar's value cannot change unless written to.
        STMT_START { assert(SvTYPE(sv) == SVt_NV || SvTYPE(sv) >= SVt_PVNV); \
            assert(SvTYPE(sv) != SVt_PVAV); assert(SvTYPE(sv) != SVt_PVHV); \
            assert(SvTYPE(sv) != SVt_PVCV); assert(SvTYPE(sv) != SVt_PVFM); \
        STMT_START { assert(SvTYPE(sv) == SVt_NV || SvTYPE(sv) >= SVt_PVNV); \
            assert(SvTYPE(sv) != SVt_PVAV); assert(SvTYPE(sv) != SVt_PVHV); \
            assert(SvTYPE(sv) != SVt_PVCV); assert(SvTYPE(sv) != SVt_PVFM); \
+               assert(SvTYPE(sv) != SVt_PVIO);         \
                assert(!isGV_with_GP(sv));              \
                (((XPVNV*)SvANY(sv))->xnv_u.xnv_nv = (val)); } STMT_END
 #define SvPV_set(sv, val) \
                assert(!isGV_with_GP(sv));              \
                (((XPVNV*)SvANY(sv))->xnv_u.xnv_nv = (val)); } STMT_END
 #define SvPV_set(sv, val) \
@@ -1370,7 +1192,11 @@ the scalar's value cannot change unless written to.
                assert(!isGV_with_GP(sv));              \
                (((XPVUV*)SvANY(sv))->xuv_uv = (val)); } STMT_END
 #define SvRV_set(sv, val) \
                assert(!isGV_with_GP(sv));              \
                (((XPVUV*)SvANY(sv))->xuv_uv = (val)); } STMT_END
 #define SvRV_set(sv, val) \
-        STMT_START { assert(SvTYPE(sv) >=  SVt_RV); \
+        STMT_START { assert(SvTYPE(sv) >=  SVt_PV || SvTYPE(sv) ==  SVt_IV); \
+               assert(SvTYPE(sv) != SVt_PVAV);         \
+               assert(SvTYPE(sv) != SVt_PVHV);         \
+               assert(SvTYPE(sv) != SVt_PVCV);         \
+               assert(SvTYPE(sv) != SVt_PVFM);         \
                assert(!isGV_with_GP(sv));              \
                 ((sv)->sv_u.svu_rv = (val)); } STMT_END
 #define SvMAGIC_set(sv, val) \
                assert(!isGV_with_GP(sv));              \
                 ((sv)->sv_u.svu_rv = (val)); } STMT_END
 #define SvMAGIC_set(sv, val) \
@@ -1393,7 +1219,7 @@ the scalar's value cannot change unless written to.
                (((XPV*)  SvANY(sv))->xpv_len = (val)); } STMT_END
 #define SvEND_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
                (((XPV*)  SvANY(sv))->xpv_len = (val)); } STMT_END
 #define SvEND_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
-               (SvCUR(sv) = (val) - SvPVX(sv)); } STMT_END
+               SvCUR_set(sv, (val) - SvPVX(sv)); } STMT_END
 
 #define SvPV_renew(sv,n) \
        STMT_START { SvLEN_set(sv, n); \
 
 #define SvPV_renew(sv,n) \
        STMT_START { SvLEN_set(sv, n); \
@@ -1411,14 +1237,31 @@ the scalar's value cannot change unless written to.
     STMT_START {                                                       \
                     assert(SvTYPE(sv) >= SVt_PV);                      \
                     if (SvLEN(sv)) {                                   \
     STMT_START {                                                       \
                     assert(SvTYPE(sv) >= SVt_PV);                      \
                     if (SvLEN(sv)) {                                   \
+                        assert(!SvROK(sv));                            \
                         if(SvOOK(sv)) {                                \
                         if(SvOOK(sv)) {                                \
-                            SvPV_set(sv, SvPVX_mutable(sv) - SvIVX(sv)); \
+                            STRLEN zok;                                \
+                            SvOOK_offset(sv, zok);                     \
+                            SvPV_set(sv, SvPVX_mutable(sv) - zok);     \
                             SvFLAGS(sv) &= ~SVf_OOK;                   \
                         }                                              \
                         Safefree(SvPVX(sv));                           \
                     }                                                  \
                 } STMT_END
 
                             SvFLAGS(sv) &= ~SVf_OOK;                   \
                         }                                              \
                         Safefree(SvPVX(sv));                           \
                     }                                                  \
                 } STMT_END
 
+#ifdef PERL_CORE
+/* Code that crops up in three places to take a scalar and ready it to hold
+   a reference */
+#  define prepare_SV_for_RV(sv)                                                \
+    STMT_START {                                                       \
+                   if (SvTYPE(sv) < SVt_PV && SvTYPE(sv) != SVt_IV)    \
+                       sv_upgrade(sv, SVt_IV);                         \
+                   else if (SvTYPE(sv) >= SVt_PV) {                    \
+                       SvPV_free(sv);                                  \
+                       SvLEN_set(sv, 0);                               \
+                        SvCUR_set(sv, 0);                              \
+                   }                                                   \
+                } STMT_END
+#endif
 
 #define PERL_FBM_TABLE_OFFSET 1        /* Number of bytes between EOS and table */
 
 
 #define PERL_FBM_TABLE_OFFSET 1        /* Number of bytes between EOS and table */
 
@@ -1427,29 +1270,29 @@ the scalar's value cannot change unless written to.
 */
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define BmFLAGS(sv)                                                  \
 */
 #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);           \
+       (*({ SV *const _bmflags = MUTABLE_SV(sv);                       \
+               assert(SvTYPE(_bmflags) == SVt_PVGV);                   \
+               assert(SvVALID(_bmflags));                              \
+           &(((XPVGV*) SvANY(_bmflags))->xnv_u.xbm_s.xbm_flags);       \
         }))
 #  define BmRARE(sv)                                                   \
         }))
 #  define BmRARE(sv)                                                   \
-       (*({ SV *const uggh = (SV *) (sv);                              \
-               assert(SvTYPE(uggh) == SVt_PVGV);                       \
-               assert(SvVALID(uggh));                                  \
-           &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_rare);            \
+       (*({ SV *const _bmrare = MUTABLE_SV(sv);                        \
+               assert(SvTYPE(_bmrare) == SVt_PVGV);                    \
+               assert(SvVALID(_bmrare));                               \
+           &(((XPVGV*) SvANY(_bmrare))->xnv_u.xbm_s.xbm_rare);         \
         }))
 #  define BmUSEFUL(sv)                                                 \
         }))
 #  define BmUSEFUL(sv)                                                 \
-       (*({ SV *const uggh = (SV *) (sv);                              \
-           assert(SvTYPE(uggh) == SVt_PVGV);                           \
-           assert(SvVALID(uggh));                                      \
-           assert(!SvIOK(uggh));                                       \
-           &(((XPVGV*) SvANY(uggh))->xiv_u.xivu_i32);                  \
+       (*({ SV *const _bmuseful = MUTABLE_SV(sv);                      \
+           assert(SvTYPE(_bmuseful) == SVt_PVGV);                      \
+           assert(SvVALID(_bmuseful));                                 \
+           assert(!SvIOK(_bmuseful));                                  \
+           &(((XPVGV*) SvANY(_bmuseful))->xiv_u.xivu_i32);             \
         }))
 #  define BmPREVIOUS(sv)                                               \
         }))
 #  define BmPREVIOUS(sv)                                               \
-       (*({ SV *const uggh = (SV *) (sv);                              \
-               assert(SvTYPE(uggh) == SVt_PVGV);                       \
-               assert(SvVALID(uggh));                                  \
-           &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_previous);        \
+    (*({ SV *const _bmprevious = MUTABLE_SV(sv);                       \
+               assert(SvTYPE(_bmprevious) == SVt_PVGV);                \
+               assert(SvVALID(_bmprevious));                           \
+           &(((XPVGV*) SvANY(_bmprevious))->xnv_u.xbm_s.xbm_previous); \
         }))
 #else
 #  define BmFLAGS(sv)          ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_flags
         }))
 #else
 #  define BmFLAGS(sv)          ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_flags
@@ -1459,7 +1302,7 @@ the scalar's value cannot change unless written to.
 
 #endif
 
 
 #endif
 
-#define FmLINES(sv)    ((XPVFM*)  SvANY(sv))->xfm_lines
+#define FmLINES(sv)    ((XPVFM*)  SvANY(sv))->xiv_u.xivu_iv
 
 #define LvTYPE(sv)     ((XPVLV*)  SvANY(sv))->xlv_type
 #define LvTARG(sv)     ((XPVLV*)  SvANY(sv))->xlv_targ
 
 #define LvTYPE(sv)     ((XPVLV*)  SvANY(sv))->xlv_type
 #define LvTARG(sv)     ((XPVLV*)  SvANY(sv))->xlv_targ
@@ -1470,7 +1313,7 @@ the scalar's value cannot change unless written to.
 #define IoOFP(sv)      ((XPVIO*)  SvANY(sv))->xio_ofp
 #define IoDIRP(sv)     ((XPVIO*)  SvANY(sv))->xio_dirp
 #define IoANY(sv)      ((XPVIO*)  SvANY(sv))->xio_any
 #define IoOFP(sv)      ((XPVIO*)  SvANY(sv))->xio_ofp
 #define IoDIRP(sv)     ((XPVIO*)  SvANY(sv))->xio_dirp
 #define IoANY(sv)      ((XPVIO*)  SvANY(sv))->xio_any
-#define IoLINES(sv)    ((XPVIO*)  SvANY(sv))->xio_lines
+#define IoLINES(sv)    ((XPVIO*)  SvANY(sv))->xiv_u.xivu_iv
 #define IoPAGE(sv)     ((XPVIO*)  SvANY(sv))->xio_page
 #define IoPAGE_LEN(sv) ((XPVIO*)  SvANY(sv))->xio_page_len
 #define IoLINES_LEFT(sv)((XPVIO*)  SvANY(sv))->xio_lines_left
 #define IoPAGE(sv)     ((XPVIO*)  SvANY(sv))->xio_page
 #define IoPAGE_LEN(sv) ((XPVIO*)  SvANY(sv))->xio_page_len
 #define IoLINES_LEFT(sv)((XPVIO*)  SvANY(sv))->xio_lines_left
@@ -1480,7 +1323,6 @@ the scalar's value cannot change unless written to.
 #define IoFMT_GV(sv)   ((XPVIO*)  SvANY(sv))->xio_fmt_gv
 #define IoBOTTOM_NAME(sv)((XPVIO*) SvANY(sv))->xio_bottom_name
 #define IoBOTTOM_GV(sv)        ((XPVIO*)  SvANY(sv))->xio_bottom_gv
 #define IoFMT_GV(sv)   ((XPVIO*)  SvANY(sv))->xio_fmt_gv
 #define IoBOTTOM_NAME(sv)((XPVIO*) SvANY(sv))->xio_bottom_name
 #define IoBOTTOM_GV(sv)        ((XPVIO*)  SvANY(sv))->xio_bottom_gv
-#define IoSUBPROCESS(sv)((XPVIO*)  SvANY(sv))->xio_subprocess
 #define IoTYPE(sv)     ((XPVIO*)  SvANY(sv))->xio_type
 #define IoFLAGS(sv)    ((XPVIO*)  SvANY(sv))->xio_flags
 
 #define IoTYPE(sv)     ((XPVIO*)  SvANY(sv))->xio_type
 #define IoFLAGS(sv)    ((XPVIO*)  SvANY(sv))->xio_flags
 
@@ -1550,7 +1392,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
 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.
 
 =for apidoc Am|char*|SvPV_nomg|SV* sv|STRLEN len
 Like C<SvPV> but doesn't process magic.
@@ -1561,7 +1405,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
 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
 version which guarantees to evaluate sv only once.
 
 =for apidoc Am|IV|SvIV_nomg|SV* sv
@@ -1569,15 +1413,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
 
 =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
 
 =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
 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>
 
 =for apidoc Am|UV|SvUV|SV* sv
 Coerces the given SV to an unsigned integer and returns it.  See C<SvUVx>
@@ -1588,11 +1434,12 @@ 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
 
 =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
 
 =for apidoc Am|bool|SvTRUE|SV* sv
 Returns a boolean indicating whether Perl would evaluate the SV as true or
-false, defined or undefined.  Does not handle 'get' magic.
+false.  See SvOK() for a defined/undefined test.  Does not handle 'get' magic.
 
 =for apidoc Am|char*|SvPVutf8_force|SV* sv|STRLEN len
 Like C<SvPV_force>, but converts sv to utf8 first if necessary.
 
 =for apidoc Am|char*|SvPVutf8_force|SV* sv|STRLEN len
 Like C<SvPV_force>, but converts sv to utf8 first if necessary.
@@ -1650,6 +1497,10 @@ Like C<sv_setsv> but doesn't process magic.
 =for apidoc Am|void|sv_catsv_nomg|SV* dsv|SV* ssv
 Like C<sv_catsv> but doesn't process magic.
 
 =for apidoc Am|void|sv_catsv_nomg|SV* dsv|SV* ssv
 Like C<sv_catsv> but doesn't process magic.
 
+=for apidoc Amdb|STRLEN|sv_utf8_upgrade_nomg|NN SV *sv
+
+Like sv_utf8_upgrade, but doesn't do magic on C<sv>
+
 =cut
 */
 
 =cut
 */
 
@@ -1720,7 +1571,7 @@ Like C<sv_catsv> but doesn't process magic.
      ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvutf8(sv, &lp))
 
 #define SvPVutf8_force(sv, lp) \
      ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvutf8(sv, &lp))
 
 #define SvPVutf8_force(sv, lp) \
-    ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == (SVf_POK|SVf_UTF8) \
+    ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8|SVf_THINKFIRST)) == (SVf_POK|SVf_UTF8) \
      ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvutf8n_force(sv, &lp))
 
 
      ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvutf8n_force(sv, &lp))
 
 
@@ -1755,9 +1606,9 @@ Like C<sv_catsv> but doesn't process magic.
 
 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 
 
 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 
-#  define SvIVx(sv) ({SV *_sv = (SV*)(sv); SvIV(_sv); })
-#  define SvUVx(sv) ({SV *_sv = (SV*)(sv); SvUV(_sv); })
-#  define SvNVx(sv) ({SV *_sv = (SV*)(sv); SvNV(_sv); })
+#  define SvIVx(sv) ({SV *_sv = MUTABLE_SV(sv); SvIV(_sv); })
+#  define SvUVx(sv) ({SV *_sv = MUTABLE_SV(sv); SvUV(_sv); })
+#  define SvNVx(sv) ({SV *_sv = MUTABLE_SV(sv); SvNV(_sv); })
 #  define SvPVx(sv, lp) ({SV *_sv = (sv); SvPV(_sv, lp); })
 #  define SvPVx_const(sv, lp) ({SV *_sv = (sv); SvPV_const(_sv, lp); })
 #  define SvPVx_nolen(sv) ({SV *_sv = (sv); SvPV_nolen(_sv); })
 #  define SvPVx(sv, lp) ({SV *_sv = (sv); SvPV(_sv, lp); })
 #  define SvPVx_const(sv, lp) ({SV *_sv = (sv); SvPV_const(_sv, lp); })
 #  define SvPVx_nolen(sv) ({SV *_sv = (sv); SvPV_nolen(_sv); })
@@ -1835,13 +1686,21 @@ 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
 #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
+/* Make sv_2pv_flags return NULL if something is undefined.  */
+#define SV_UNDEF_RETURNS_NULL  2048
+/* Tell sv_utf8_upgrade() to not check to see if an upgrade is really needed.
+ * This is used when the caller has already determined it is, and avoids
+ * redundant work */
+#define SV_FORCE_UTF8_UPGRADE  4096
 
 /* 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
 
 /* 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
 
 #  endif
 #endif
 
@@ -1865,11 +1724,17 @@ Like C<sv_catsv> but doesn't process magic.
                                    sv_force_normal_flags(sv, SV_COW_DROP_PV)
 
 #ifdef PERL_OLD_COPY_ON_WRITE
                                    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), 0)
 #  define SvIsCOW_normal(sv)   (SvIsCOW(sv) && SvLEN(sv))
 #  define SvIsCOW_normal(sv)   (SvIsCOW(sv) && SvLEN(sv))
+#  define SvRELEASE_IVX_(sv)   SvRELEASE_IVX(sv),
 #else
 #else
-#  define SvRELEASE_IVX(sv)   SvOOK_off(sv)
+#  define SvRELEASE_IVX(sv)   0
+/* This little game brought to you by the need to shut this warning up:
+mg.c: In function `Perl_magic_get':
+mg.c:1024: warning: left-hand operand of comma expression has no effect
+*/
+#  define SvRELEASE_IVX_(sv)  /**/
 #endif /* PERL_OLD_COPY_ON_WRITE */
 
 #define CAN_COW_MASK   (SVs_OBJECT|SVs_GMG|SVs_SMG|SVs_RMG|SVf_IOK|SVf_NOK| \
 #endif /* PERL_OLD_COPY_ON_WRITE */
 
 #define CAN_COW_MASK   (SVs_OBJECT|SVs_GMG|SVs_SMG|SVs_RMG|SVf_IOK|SVf_NOK| \
@@ -1888,6 +1753,7 @@ Like C<sv_catsv> but doesn't process magic.
 #define sv_pvbyte(sv) SvPVbyte_nolen(sv)
 
 #define sv_pvn_force_nomg(sv, lp) sv_pvn_force_flags(sv, lp, 0)
 #define sv_pvbyte(sv) SvPVbyte_nolen(sv)
 
 #define sv_pvn_force_nomg(sv, lp) sv_pvn_force_flags(sv, lp, 0)
+#define sv_utf8_upgrade_flags(sv, flags) sv_utf8_upgrade_flags_grow(sv, flags, 0)
 #define sv_utf8_upgrade_nomg(sv) sv_utf8_upgrade_flags(sv, 0)
 #define sv_catpvn_nomg(dsv, sstr, slen) sv_catpvn_flags(dsv, sstr, slen, 0)
 #define sv_setsv(dsv, ssv) \
 #define sv_utf8_upgrade_nomg(sv) sv_utf8_upgrade_flags(sv, 0)
 #define sv_catpvn_nomg(dsv, sstr, slen) sv_catpvn_flags(dsv, sstr, slen, 0)
 #define sv_setsv(dsv, ssv) \
@@ -1908,12 +1774,15 @@ Like C<sv_catsv> but doesn't process magic.
 #define sv_utf8_upgrade(sv) sv_utf8_upgrade_flags(sv, SV_GMAGIC)
 #define sv_2iv(sv) sv_2iv_flags(sv, SV_GMAGIC)
 #define sv_2uv(sv) sv_2uv_flags(sv, SV_GMAGIC)
 #define sv_utf8_upgrade(sv) sv_utf8_upgrade_flags(sv, SV_GMAGIC)
 #define sv_2iv(sv) sv_2iv_flags(sv, SV_GMAGIC)
 #define sv_2uv(sv) sv_2uv_flags(sv, SV_GMAGIC)
+#define sv_insert(bigstr, offset, len, little, littlelen)              \
+       Perl_sv_insert_flags(aTHX_ (bigstr),(offset), (len), (little),  \
+                            (littlelen), SV_GMAGIC)
 
 /* Should be named SvCatPVN_utf8_upgrade? */
 #define sv_catpvn_utf8_upgrade(dsv, sstr, slen, nsv)   \
        STMT_START {                                    \
            if (!(nsv))                                 \
 
 /* Should be named SvCatPVN_utf8_upgrade? */
 #define sv_catpvn_utf8_upgrade(dsv, sstr, slen, nsv)   \
        STMT_START {                                    \
            if (!(nsv))                                 \
-               nsv = sv_2mortal(newSVpvn(sstr, slen)); \
+               nsv = newSVpvn_flags(sstr, slen, SVs_TEMP);     \
            else                                        \
                sv_setpvn(nsv, sstr, slen);             \
            SvUTF8_off(nsv);                            \
            else                                        \
                sv_setpvn(nsv, sstr, slen);             \
            SvUTF8_off(nsv);                            \
@@ -1985,6 +1854,7 @@ Returns a pointer to the character buffer.
 #define SvSHARE(sv) CALL_FPTR(PL_sharehook)(aTHX_ sv)
 #define SvLOCK(sv) CALL_FPTR(PL_lockhook)(aTHX_ sv)
 #define SvUNLOCK(sv) CALL_FPTR(PL_unlockhook)(aTHX_ sv)
 #define SvSHARE(sv) CALL_FPTR(PL_sharehook)(aTHX_ sv)
 #define SvLOCK(sv) CALL_FPTR(PL_lockhook)(aTHX_ sv)
 #define SvUNLOCK(sv) CALL_FPTR(PL_unlockhook)(aTHX_ sv)
+#define SvDESTROYABLE(sv) CALL_FPTR(PL_destroyhook)(aTHX_ sv)
 
 #define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
 #define SvSETMAGIC(x) STMT_START { if (SvSMAGICAL(x)) mg_set(x); } STMT_END
 
 #define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
 #define SvSETMAGIC(x) STMT_START { if (SvSMAGICAL(x)) mg_set(x); } STMT_END
@@ -2062,6 +1932,74 @@ struct clone_params {
 };
 
 /*
 };
 
 /*
+=for apidoc Am|SV*|newSVpvn_utf8|NULLOK const char* s|STRLEN len|U32 utf8
+
+Creates a new SV and copies a string into it.  If utf8 is true, calls
+C<SvUTF8_on> on the new SV.  Implemented as a wrapper around C<newSVpvn_flags>.
+
+=cut
+*/
+
+#define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0)
+
+/*
+=for apidoc Am|void|SvOOK_offset|NN SV*sv|STRLEN len
+
+Reads into I<len> the offset from SvPVX back to the true start of the
+allocated buffer, which will be non-zero if C<sv_chop> has been used to
+efficiently remove characters from start of the buffer. Implemented as a
+macro, which takes the address of I<len>, which must be of type C<STRLEN>.
+Evaluates I<sv> more than once. Sets I<len> to 0 if C<SvOOK(sv)> is false.
+
+=cut
+*/
+
+#ifdef DEBUGGING
+/* Does the bot know something I don't?
+10:28 <@Nicholas> metabatman
+10:28 <+meta> Nicholas: crash
+*/
+#  define SvOOK_offset(sv, offset) STMT_START {                                \
+       assert(sizeof(offset) == sizeof(STRLEN));                       \
+       if (SvOOK(sv)) {                                                \
+           const U8 *crash = (U8*)SvPVX_const(sv);                     \
+           offset = *--crash;                                          \
+           if (!offset) {                                              \
+               crash -= sizeof(STRLEN);                                \
+               Copy(crash, (U8 *)&offset, sizeof(STRLEN), U8);         \
+           }                                                           \
+           {                                                           \
+               /* Validate the preceding buffer's sentinels to         \
+                  verify that no-one is using it.  */                  \
+               const U8 *const bonk = (U8 *) SvPVX_const(sv) - offset; \
+               while (crash > bonk) {                                  \
+                   --crash;                                            \
+                   assert (*crash == (U8)PTR2UV(crash));               \
+               }                                                       \
+           }                                                           \
+       } else {                                                        \
+           offset = 0;                                                 \
+       }                                                               \
+    } STMT_END
+#else
+    /* This is the same code, but avoids using any temporary variables:  */
+#  define SvOOK_offset(sv, offset) STMT_START {                                \
+       assert(sizeof(offset) == sizeof(STRLEN));                       \
+       if (SvOOK(sv)) {                                                \
+           offset = ((U8*)SvPVX_const(sv))[-1];                        \
+           if (!offset) {                                              \
+               Copy(SvPVX_const(sv) - 1 - sizeof(STRLEN),              \
+                    (U8 *)&offset, sizeof(STRLEN), U8);                \
+           }                                                           \
+       } else {                                                        \
+           offset = 0;                                                 \
+       }                                                               \
+    } STMT_END
+#endif
+
+#define newIO()        MUTABLE_IO(newSV_type(SVt_PVIO))
+
+/*
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4