This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Refactor porting/diag.t and improve output format
[perl5.git] / sv.h
diff --git a/sv.h b/sv.h
index e0b3be5..a49954d 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.
@@ -45,14 +45,15 @@ Type flag for code refs.  See C<svtype>.
 
 typedef enum {
        SVt_NULL,       /* 0 */
 
 typedef enum {
        SVt_NULL,       /* 0 */
-       SVt_IV,         /* 1 */
-       SVt_NV,         /* 2 */
-       SVt_RV,         /* 3 */
-       SVt_BIND,       /* 4 */
-       SVt_PV,         /* 5 */
-       SVt_PVIV,       /* 6 */
-       SVt_PVNV,       /* 7 */
-       SVt_PVMG,       /* 8 */
+       SVt_BIND,       /* 1 */
+       SVt_IV,         /* 2 */
+       SVt_NV,         /* 3 */
+       /* 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,13 +99,14 @@ 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;                 \
+       PerlIO *svu_fp;                 \
     }  sv_u
 
 
     }  sv_u
 
 
@@ -113,11 +114,12 @@ 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 */
-    char *     sv_debug_file;          /* the file 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_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 */
+    SV *           sv_debug_parent;    /* what we were cloned from (ithreads)*/
 #endif
 };
 
 #endif
 };
 
@@ -146,6 +148,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 +184,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 +219,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 +231,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 +276,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 +326,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 +351,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,134 +395,73 @@ 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                                                      \
+    HV*                xmg_stash;      /* class package */                     \
+    union _xmgu        xmg_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;
-    }          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 */
+    UV     xivu_uv;
+    I32            xivu_i32;           /* BmUSEFUL */
+    HEK *   xivu_namehek;      /* xpvlv, xpvgv: GvNAME */
 };
 
 };
 
-#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
+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;
-    }          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;
 };
 
 };
 
-#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 */
-    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;
-#endif
+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;
-    }          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;
-    }          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;
+    union _xnvu xnv_u;
 };
 
 };
 
-/* These structure must match the beginning of struct xpvhv in hv.h. */
+/* 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;
-    }          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;
+    union _xivu xiv_u;
+    union _xnvu xnv_u;
 };
 
 struct xpvlv {
 };
 
 struct xpvlv {
-    union {
-       NV      xnv_nv;         /* numeric value, if any */
-       HV *    xgv_stash;
-    }          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;
+    union _xivu xiv_u;
+    union _xnvu xnv_u;
     STRLEN     xlv_targoff;
     STRLEN     xlv_targlen;
     SV*                xlv_targ;
     STRLEN     xlv_targoff;
     STRLEN     xlv_targlen;
     SV*                xlv_targ;
@@ -522,135 +472,52 @@ 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 */
-    }          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;
+    union _xivu xiv_u;
+    union _xnvu xnv_u;
 };
 
 /* 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;
 
-struct xpvfm {
-    union {
-       NV      xnv_nv;         /* numeric value, if any */
-       HV *    xgv_stash;
-    }          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 */
+#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
 
 
-    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 {
+    _XPV_HEAD;
+    _XPVCV_COMMON;
     IV         xfm_lines;
 };
 
     IV         xfm_lines;
 };
 
-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;
 
 struct xpvio {
 
 struct xpvio {
-    union {
-       NV      xnv_nv;         /* numeric value, if any */
-       HV *    xgv_stash;
-    }          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 */
+    _XPV_HEAD;
+    union _xivu xiv_u;
+    /* ifp and ofp are normally the same, but sockets need separate streams */
+    PerlIO *   xio_ofp;
     /* Cray addresses everything by word boundaries (64 bits) and
      * code and data pointers cannot be mixed (which is exactly what
     /* 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
+     * 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.
      */
      * The any pointer (known as IoANY()) will also be a good place
      * to hang any IO disciplines to.
      */
@@ -658,7 +525,7 @@ struct xpvio {
        DIR *   xiou_dirp;      /* for opendir, readdir, etc */
        void *  xiou_any;       /* for alignment */
     } xio_dirpu;
        DIR *   xiou_dirp;      /* for opendir, readdir, etc */
        void *  xiou_any;       /* for alignment */
     } xio_dirpu;
-    IV         xio_lines;      /* $. */
+    /* IV xio_lines is now in IVX  $. */
     IV         xio_page;       /* $% */
     IV         xio_page_len;   /* $= */
     IV         xio_lines_left; /* $- */
     IV         xio_page;       /* $% */
     IV         xio_page_len;   /* $= */
     IV         xio_lines_left; /* $- */
@@ -668,10 +535,10 @@ struct xpvio {
     GV *       xio_fmt_gv;     /* $~ */
     char *     xio_bottom_name;/* $^B */
     GV *       xio_bottom_gv;  /* $^B */
     GV *       xio_fmt_gv;     /* $~ */
     char *     xio_bottom_name;/* $^B */
     GV *       xio_bottom_gv;  /* $^B */
-    short      xio_subprocess; /* -| or |- */
     char       xio_type;
     char       xio_type;
-    char       xio_flags;
+    U8         xio_flags;
 };
 };
+
 #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
 
@@ -681,40 +548,41 @@ struct xpvio {
 #define IOf_DIDTOP     8       /* just did top of form */
 #define IOf_UNTAINT    16      /* consider this fp (and its data) "safe" */
 #define IOf_NOLINE     32      /* slurped a pseudo-line from empty file */
 #define IOf_DIDTOP     8       /* just did top of form */
 #define IOf_UNTAINT    16      /* consider this fp (and its data) "safe" */
 #define IOf_NOLINE     32      /* slurped a pseudo-line from empty file */
-#define IOf_FAKE_DIRP  64      /* xio_dirp is fake (source filters kludge) */
+#define IOf_FAKE_DIRP  64      /* xio_dirp is fake (source filters kludge)
+                                  Also, when this is set, SvPVX() is valid */
 
 /* 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.
@@ -731,14 +599,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.
@@ -749,8 +617,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
@@ -766,13 +634,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
@@ -861,7 +731,9 @@ Set the actual length of the string which is in the SV.  See C<SvIV_set>.
 #define assert_not_glob(sv)    
 #endif
 
 #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), \
 #define SvOK_off(sv)           (assert_not_ROK(sv) assert_not_glob(sv) \
                                 SvFLAGS(sv) &= ~(SVf_OK|               \
                                                  SVf_IVisUV|SVf_UTF8), \
@@ -873,7 +745,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)
@@ -882,7 +754,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), \
@@ -908,8 +780,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.
 
@@ -997,7 +869,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
@@ -1010,7 +882,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))
@@ -1060,23 +932,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);            \
                        })
@@ -1092,14 +964,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))
 
@@ -1111,19 +975,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)
@@ -1131,18 +995,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)
 
@@ -1152,6 +1014,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))
@@ -1176,60 +1040,96 @@ 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));                              \
+           assert(!(SvTYPE(_svpvx) == SVt_PVIO                         \
+                    && !(IoFLAGS(_svpvx) & IOf_FAKE_DIRP)));           \
+           &((_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));                              \
+           assert(!(SvTYPE(_svcur) == SVt_PVIO                         \
+                    && !(IoFLAGS(_svcur) & IOf_FAKE_DIRP)));           \
+           &(((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(SvTYPE(_svivx) != SVt_REGEXP);                       \
+           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(SvTYPE(_svuvx) != SVt_REGEXP);                       \
+           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(SvTYPE(_svnvx) != SVt_REGEXP);                       \
+           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));                               \
+           assert(!(SvTYPE(_svrv) == SVt_PVIO                          \
+                    && !(IoFLAGS(_svrv) & IOf_FAKE_DIRP)));            \
+           &((_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));                               \
+           assert(!(SvTYPE(_svrv) == SVt_PVIO                          \
+                    && !(IoFLAGS(_svrv) & IOf_FAKE_DIRP)));            \
+           (_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)
@@ -1237,6 +1137,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
@@ -1268,6 +1170,9 @@ the scalar's value cannot change unless written to.
 #define SvIV_please(sv) \
        STMT_START {if (!SvIOKp(sv) && (SvNOK(sv) || SvPOK(sv))) \
                (void) SvIV(sv); } STMT_END
 #define SvIV_please(sv) \
        STMT_START {if (!SvIOKp(sv) && (SvNOK(sv) || SvPOK(sv))) \
                (void) SvIV(sv); } STMT_END
+#define SvIV_please_nomg(sv) \
+       STMT_START {if (!SvIOKp(sv) && (SvNOK(sv) || SvPOK(sv))) \
+               (void) SvIV_nomg(sv); } STMT_END
 #define SvIV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
                assert(SvTYPE(sv) != SVt_PVAV);         \
 #define SvIV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
                assert(SvTYPE(sv) != SVt_PVAV);         \
@@ -1279,6 +1184,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) \
@@ -1286,6 +1192,8 @@ the scalar's value cannot change unless written to.
                assert(SvTYPE(sv) != SVt_PVAV);         \
                assert(SvTYPE(sv) != SVt_PVHV);         \
                assert(!isGV_with_GP(sv));              \
                assert(SvTYPE(sv) != SVt_PVAV);         \
                assert(SvTYPE(sv) != SVt_PVHV);         \
                assert(!isGV_with_GP(sv));              \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                ((sv)->sv_u.svu_pv = (val)); } STMT_END
 #define SvUV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
                ((sv)->sv_u.svu_pv = (val)); } STMT_END
 #define SvUV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
@@ -1295,8 +1203,14 @@ 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));              \
                assert(!isGV_with_GP(sv));              \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                 ((sv)->sv_u.svu_rv = (val)); } STMT_END
 #define SvMAGIC_set(sv, val) \
         STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
                 ((sv)->sv_u.svu_rv = (val)); } STMT_END
 #define SvMAGIC_set(sv, val) \
         STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
@@ -1309,16 +1223,20 @@ the scalar's value cannot change unless written to.
                assert(SvTYPE(sv) != SVt_PVAV);         \
                assert(SvTYPE(sv) != SVt_PVHV);         \
                assert(!isGV_with_GP(sv));              \
                assert(SvTYPE(sv) != SVt_PVAV);         \
                assert(SvTYPE(sv) != SVt_PVHV);         \
                assert(!isGV_with_GP(sv));              \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                (((XPV*)  SvANY(sv))->xpv_cur = (val)); } STMT_END
 #define SvLEN_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
                assert(SvTYPE(sv) != SVt_PVAV); \
                assert(SvTYPE(sv) != SVt_PVHV); \
                assert(!isGV_with_GP(sv));      \
                (((XPV*)  SvANY(sv))->xpv_cur = (val)); } STMT_END
 #define SvLEN_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
                assert(SvTYPE(sv) != SVt_PVAV); \
                assert(SvTYPE(sv) != SVt_PVHV); \
                assert(!isGV_with_GP(sv));      \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                (((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); \
@@ -1336,83 +1254,70 @@ 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
 
-
-#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
+#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
 #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)
 
 /* 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 _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));                                  \
-               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); \
+       (*({ 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));                                       \
-          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 _bmprevious = MUTABLE_SV(sv);                       \
+               assert(SvTYPE(_bmprevious) == SVt_PVGV);                \
+               assert(SvVALID(_bmprevious));                           \
+           &(((XPVGV*) SvANY(_bmprevious))->xnv_u.xbm_s.xbm_previous); \
+        }))
 #else
 #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
 
 #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
 
 
 #define FmLINES(sv)    ((XPVFM*)  SvANY(sv))->xfm_lines
 
@@ -1421,11 +1326,11 @@ the scalar's value cannot change unless written to.
 #define LvTARGOFF(sv)  ((XPVLV*)  SvANY(sv))->xlv_targoff
 #define LvTARGLEN(sv)  ((XPVLV*)  SvANY(sv))->xlv_targlen
 
 #define LvTARGOFF(sv)  ((XPVLV*)  SvANY(sv))->xlv_targoff
 #define LvTARGLEN(sv)  ((XPVLV*)  SvANY(sv))->xlv_targlen
 
-#define IoIFP(sv)      ((XPVIO*)  SvANY(sv))->xio_ifp
+#define IoIFP(sv)      (sv)->sv_u.svu_fp
 #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
@@ -1435,7 +1340,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
 
@@ -1505,7 +1409,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.
@@ -1516,7 +1422,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
@@ -1524,15 +1430,20 @@ 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.
 
 which guarantees to evaluate sv only once.
 
+=for apidoc Am|NV|SvNV_nomg|SV* sv
+Like C<SvNV> but doesn't process magic.
+
 =for apidoc Am|NV|SvNVx|SV* sv
 Coerces the given SV to a double and returns it. Guarantees to evaluate
 =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>
@@ -1543,11 +1454,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.
@@ -1605,6 +1517,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
 */
 
@@ -1615,6 +1531,7 @@ Like C<sv_catsv> but doesn't process magic.
 
 #define SvIV_nomg(sv) (SvIOK(sv) ? SvIVX(sv) : sv_2iv_flags(sv, 0))
 #define SvUV_nomg(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv_flags(sv, 0))
 
 #define SvIV_nomg(sv) (SvIOK(sv) ? SvIVX(sv) : sv_2iv_flags(sv, 0))
 #define SvUV_nomg(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv_flags(sv, 0))
+#define SvNV_nomg(sv) (SvNOK(sv) ? SvNVX(sv) : sv_2nv_flags(sv, 0))
 
 /* ----*/
 
 
 /* ----*/
 
@@ -1675,7 +1592,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))
 
 
@@ -1710,9 +1627,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); })
@@ -1790,13 +1707,24 @@ 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
+/* if (after resolving magic etc), the SV is found to be overloaded,
+ * don't call the overload magic, just return as-is */
+#define SV_SKIP_OVERLOAD       8192
 
 /* 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
 
@@ -1820,11 +1748,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| \
@@ -1843,6 +1777,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) \
@@ -1863,12 +1798,16 @@ 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_2nv(sv) sv_2nv_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);                            \
@@ -1940,6 +1879,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
@@ -2014,9 +1954,79 @@ struct clone_params {
   AV* stashes;
   UV  flags;
   PerlInterpreter *proto_perl;
   AV* stashes;
   UV  flags;
   PerlInterpreter *proto_perl;
+  PerlInterpreter *new_perl;
+  AV *unreferenced;
 };
 
 /*
 };
 
 /*
+=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