This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Move the xpv_pv/xrv_rv member into the SV head, in a union with
authorNicholas Clark <nick@ccl4.org>
Sat, 21 May 2005 18:19:43 +0000 (18:19 +0000)
committerNicholas Clark <nick@ccl4.org>
Sat, 21 May 2005 18:19:43 +0000 (18:19 +0000)
IV and UV. Avoid allocating a body for IVs and RVs.

p4raw-id: //depot/perl@24531

14 files changed:
av.h
bytecode.pl
cv.h
embed.fnc
embed.h
ext/B/B/C.pm
ext/ByteLoader/bytecode.h
ext/ByteLoader/byterun.c
ext/ByteLoader/byterun.h
hv.c
hv.h
proto.h
sv.c
sv.h

diff --git a/av.h b/av.h
index c471136..186ec35 100644 (file)
--- a/av.h
+++ b/av.h
@@ -9,7 +9,6 @@
  */
 
 struct xpvav {
-    char*      xav_array;      /* pointer to first array element */
     SSize_t    xav_fill;       /* Index of last element present */
     SSize_t    xav_max;        /* max index for which array has space */
     IV         xof_off;        /* ptr is incremented by offset */
@@ -56,7 +55,7 @@ Same as C<av_len()>.  Deprecated, use C<av_len()> instead.
 
 #define Nullav Null(AV*)
 
-#define AvARRAY(av)    ((SV**)((XPVAV*)  SvANY(av))->xav_array)
+#define AvARRAY(av)    ((av)->sv_u.sv_array)
 #define AvALLOC(av)    ((XPVAV*)  SvANY(av))->xav_alloc
 #define AvMAX(av)      ((XPVAV*)  SvANY(av))->xav_max
 #define AvFILLp(av)    ((XPVAV*)  SvANY(av))->xav_fill
index 5747eae..1a090af 100644 (file)
@@ -212,13 +212,18 @@ struct byteloader_fdata {
     int        idx;
 };
 
+struct byteloader_pv_state {
+    char                       *pvx;
+    XPV                                xpv;
+};
+
 struct byteloader_state {
     struct byteloader_fdata    *bs_fdata;
     SV                         *bs_sv;
     void                       **bs_obj_list;
     int                                bs_obj_list_fill;
     int                                bs_ix;
-    XPV                                bs_pv;
+    struct byteloader_pv_state bs_pv;
     int                                bs_iv_overflows;
 };
 
@@ -361,7 +366,7 @@ ldsv                bstate->bs_sv                           svindex
 ldop           PL_op                                   opindex
 stsv           bstate->bs_sv                           U32             s
 stop           PL_op                                   U32             s
-stpv           bstate->bs_pv.xpv_pv                    U32             x
+stpv           bstate->bs_pv.pvx                       U32             x
 ldspecsv       bstate->bs_sv                           U8              x
 ldspecsvx      bstate->bs_sv                           U8              x
 newsv          bstate->bs_sv                           U8              x
@@ -370,8 +375,8 @@ newop               PL_op                                   U8              x
 newopx         PL_op                                   U16             x
 newopn         PL_op                                   U8              x
 newpv          none                                    PV
-pv_cur         bstate->bs_pv.xpv_cur                   STRLEN
-pv_free                bstate->bs_pv                           none            x
+pv_cur         bstate->bs_pv.xpv.xpv_cur               STRLEN
+pv_free                bstate->bs_pv.pvx                       none            x
 sv_upgrade     bstate->bs_sv                           U8              x
 sv_refcnt      SvREFCNT(bstate->bs_sv)                 U32
 sv_refcnt_add  SvREFCNT(bstate->bs_sv)                 I32             x
diff --git a/cv.h b/cv.h
index 825a968..90eef1b 100644 (file)
--- a/cv.h
+++ b/cv.h
@@ -12,7 +12,6 @@
  * in sv.h  */
 
 struct xpvcv {
-    char *     xpv_pv;         /* pointer to malloced string (for prototype) */
     STRLEN     xpv_cur;        /* length of xp_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xof_off;        /* integer value */
index 02b75ec..addd69f 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -1180,7 +1180,6 @@ s |SV*    |save_scalar_at |SV **sptr
 #if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
 s      |IV     |asIV           |SV* sv
 s      |UV     |asUV           |SV* sv
-s      |XPVIV* |new_xiv
 s      |XPVNV* |new_xnv
 s      |XPV*   |new_xpv
 s      |XPVIV* |new_xpviv
@@ -1192,8 +1191,6 @@ s |XPVMG* |new_xpvmg
 s      |XPVGV* |new_xpvgv
 s      |XPVLV* |new_xpvlv
 s      |XPVBM* |new_xpvbm
-s      |XRV*   |new_xrv
-s      |void   |del_xiv        |XPVIV* p
 s      |void   |del_xnv        |XPVNV* p
 s      |void   |del_xpv        |XPV* p
 s      |void   |del_xpviv      |XPVIV* p
@@ -1205,7 +1202,6 @@ s |void   |del_xpvmg      |XPVMG* p
 s      |void   |del_xpvgv      |XPVGV* p
 s      |void   |del_xpvlv      |XPVLV* p
 s      |void   |del_xpvbm      |XPVBM* p
-s      |void   |del_xrv        |XRV* p
 s      |void   |sv_unglob      |SV* sv
 s      |void   |not_a_number   |SV *sv
 s      |I32    |visit          |SVFUNC_t f|U32 flags|U32 mask
diff --git a/embed.h b/embed.h
index 45d43a3..71a136c 100644 (file)
--- a/embed.h
+++ b/embed.h
 #ifdef PERL_CORE
 #define asIV                   S_asIV
 #define asUV                   S_asUV
-#define new_xiv                        S_new_xiv
 #define new_xnv                        S_new_xnv
 #define new_xpv                        S_new_xpv
 #define new_xpviv              S_new_xpviv
 #define new_xpvgv              S_new_xpvgv
 #define new_xpvlv              S_new_xpvlv
 #define new_xpvbm              S_new_xpvbm
-#define new_xrv                        S_new_xrv
-#define del_xiv                        S_del_xiv
 #define del_xnv                        S_del_xnv
 #define del_xpv                        S_del_xpv
 #define del_xpviv              S_del_xpviv
 #define del_xpvgv              S_del_xpvgv
 #define del_xpvlv              S_del_xpvlv
 #define del_xpvbm              S_del_xpvbm
-#define del_xrv                        S_del_xrv
 #define sv_unglob              S_sv_unglob
 #define not_a_number           S_not_a_number
 #define visit                  S_visit
 #ifdef PERL_CORE
 #define asIV(a)                        S_asIV(aTHX_ a)
 #define asUV(a)                        S_asUV(aTHX_ a)
-#define new_xiv()              S_new_xiv(aTHX)
 #define new_xnv()              S_new_xnv(aTHX)
 #define new_xpv()              S_new_xpv(aTHX)
 #define new_xpviv()            S_new_xpviv(aTHX)
 #define new_xpvgv()            S_new_xpvgv(aTHX)
 #define new_xpvlv()            S_new_xpvlv(aTHX)
 #define new_xpvbm()            S_new_xpvbm(aTHX)
-#define new_xrv()              S_new_xrv(aTHX)
-#define del_xiv(a)             S_del_xiv(aTHX_ a)
 #define del_xnv(a)             S_del_xnv(aTHX_ a)
 #define del_xpv(a)             S_del_xpv(aTHX_ a)
 #define del_xpviv(a)           S_del_xpviv(aTHX_ a)
 #define del_xpvgv(a)           S_del_xpvgv(aTHX_ a)
 #define del_xpvlv(a)           S_del_xpvlv(aTHX_ a)
 #define del_xpvbm(a)           S_del_xpvbm(aTHX_ a)
-#define del_xrv(a)             S_del_xrv(aTHX_ a)
 #define sv_unglob(a)           S_sv_unglob(aTHX_ a)
 #define not_a_number(a)                S_not_a_number(aTHX_ a)
 #define visit(a,b,c)           S_visit(aTHX_ a,b,c)
index 906c1a4..51b357e 100644 (file)
@@ -1416,7 +1416,6 @@ sub output_declarations {
  * Some pre-Standard compilers can't cope with initialising unions. Ho hum.
  */
 typedef struct {
-    char *     xpv_pv;         /* pointer to malloced string */
     STRLEN     xpv_cur;        /* length of xp_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xof_off;        /* integer value */
index 40c1e99..087e151 100644 (file)
@@ -31,14 +31,14 @@ typedef char *pvindex;
 #define BGET_PV(arg)   STMT_START {                                    \
        BGET_U32(arg);                                                  \
        if (arg) {                                                      \
-           New(666, bstate->bs_pv.xpv_pv, arg, char);                  \
-           bl_read(bstate->bs_fdata, bstate->bs_pv.xpv_pv, arg, 1);    \
-           bstate->bs_pv.xpv_len = arg;                                \
-           bstate->bs_pv.xpv_cur = arg - 1;                            \
+           New(666, bstate->bs_pv.pvx, arg, char);                     \
+           bl_read(bstate->bs_fdata, bstate->bs_pv.pvx, arg, 1);       \
+           bstate->bs_pv.xpv.xpv_len = arg;                            \
+           bstate->bs_pv.xpv.xpv_cur = arg - 1;                        \
        } else {                                                        \
-           bstate->bs_pv.xpv_pv = 0;                                   \
-           bstate->bs_pv.xpv_len = 0;                                  \
-           bstate->bs_pv.xpv_cur = 0;                                  \
+           bstate->bs_pv.pvx = 0;                                      \
+           bstate->bs_pv.xpv.xpv_len = 0;                              \
+           bstate->bs_pv.xpv.xpv_cur = 0;                              \
        }                                                               \
     } STMT_END
 
@@ -68,7 +68,7 @@ typedef char *pvindex;
        arg = (char *) ary;                             \
     } while (0)
 
-#define BGET_pvcontents(arg)   arg = bstate->bs_pv.xpv_pv
+#define BGET_pvcontents(arg)   arg = bstate->bs_pv.pvx
 #define BGET_strconst(arg) STMT_START {        \
        for (arg = PL_tokenbuf; (*arg = BGET_FGETC()); arg++) /* nothing */; \
        arg = PL_tokenbuf;                      \
@@ -122,7 +122,7 @@ typedef char *pvindex;
     } STMT_END
 
 #define BSET_sv_magic(sv, arg)         sv_magic(sv, Nullsv, arg, 0, 0)
-#define BSET_mg_name(mg, arg)  mg->mg_ptr = arg; mg->mg_len = bstate->bs_pv.xpv_cur
+#define BSET_mg_name(mg, arg)  mg->mg_ptr = arg; mg->mg_len = bstate->bs_pv.xpv.xpv_cur
 #define BSET_mg_namex(mg, arg)                 \
        (mg->mg_ptr = (char*)SvREFCNT_inc((SV*)arg),    \
         mg->mg_len = HEf_SVKEY)
@@ -130,9 +130,9 @@ typedef char *pvindex;
 #define BSET_sv_upgrade(sv, arg)       (void)SvUPGRADE(sv, arg)
 #define BSET_xrv(sv, arg) SvRV_set(sv, arg)
 #define BSET_xpv(sv)   do {    \
-       SvPV_set(sv, bstate->bs_pv.xpv_pv);     \
-       SvCUR_set(sv, bstate->bs_pv.xpv_cur);   \
-       SvLEN_set(sv, bstate->bs_pv.xpv_len);   \
+       SvPV_set(sv, bstate->bs_pv.pvx);        \
+       SvCUR_set(sv, bstate->bs_pv.xpv.xpv_cur);       \
+       SvLEN_set(sv, bstate->bs_pv.xpv.xpv_len);       \
     } while (0)
 #define BSET_xpv_cur(sv, arg) SvCUR_set(sv, arg)
 #define BSET_xpv_len(sv, arg) SvLEN_set(sv, arg)
@@ -144,8 +144,8 @@ typedef char *pvindex;
 #define BSET_av_push(sv, arg)  av_push((AV*)sv, arg)
 #define BSET_av_pushx(sv, arg) (AvARRAY(sv)[++AvFILLp(sv)] = arg)
 #define BSET_hv_store(sv, arg) \
-       hv_store((HV*)sv, bstate->bs_pv.xpv_pv, bstate->bs_pv.xpv_cur, arg, 0)
-#define BSET_pv_free(pv)       Safefree(pv.xpv_pv)
+       hv_store((HV*)sv, bstate->bs_pv.pvx, bstate->bs_pv.xpv.xpv_cur, arg, 0)
+#define BSET_pv_free(p)        Safefree(p)
 
 
 #ifdef USE_ITHREADS
@@ -155,7 +155,7 @@ typedef char *pvindex;
     STMT_START { \
         SV* repointer; \
        REGEXP* rx = arg ? \
-           CALLREGCOMP(aTHX_ arg, arg + bstate->bs_pv.xpv_cur, cPMOPx(o)) : \
+           CALLREGCOMP(aTHX_ arg, arg + bstate->bs_pv.xpv.xpv_cur, cPMOPx(o)) : \
            Null(REGEXP*); \
         if(av_len((AV*) PL_regex_pad[0]) > -1) { \
             repointer = av_pop((AV*)PL_regex_pad[0]); \
@@ -174,7 +174,7 @@ typedef char *pvindex;
 #define BSET_pregcomp(o, arg) \
     STMT_START { \
        PM_SETRE(((PMOP*)o), (arg ? \
-            CALLREGCOMP(aTHX_ arg, arg + bstate->bs_pv.xpv_cur, cPMOPx(o)): \
+            CALLREGCOMP(aTHX_ arg, arg + bstate->bs_pv.xpv.xpv_cur, cPMOPx(o)): \
             Null(REGEXP*))); \
     } STMT_END
 
index 4506066..7a8d378 100644 (file)
@@ -116,7 +116,7 @@ byterun(pTHX_ register struct byteloader_state *bstate)
            {
                U32 arg;
                BGET_U32(arg);
-               BSET_stpv(bstate->bs_pv.xpv_pv, arg);
+               BSET_stpv(bstate->bs_pv.pvx, arg);
                break;
            }
          case INSN_LDSPECSV:           /* 6 */
@@ -178,12 +178,12 @@ byterun(pTHX_ register struct byteloader_state *bstate)
            {
                STRLEN arg;
                BGET_PADOFFSET(arg);
-               bstate->bs_pv.xpv_cur = arg;
+               bstate->bs_pv.xpv.xpv_cur = arg;
                break;
            }
          case INSN_PV_FREE:            /* 16 */
            {
-               BSET_pv_free(bstate->bs_pv);
+               BSET_pv_free(bstate->bs_pv.pvx);
                break;
            }
          case INSN_SV_UPGRADE:         /* 17 */
index dcd3374..0ba48c6 100644 (file)
@@ -15,13 +15,18 @@ struct byteloader_fdata {
     int        idx;
 };
 
+struct byteloader_pv_state {
+    char                       *pvx;
+    XPV                                xpv;
+};
+
 struct byteloader_state {
     struct byteloader_fdata    *bs_fdata;
     SV                         *bs_sv;
     void                       **bs_obj_list;
     int                                bs_obj_list_fill;
     int                                bs_ix;
-    XPV                                bs_pv;
+    struct byteloader_pv_state bs_pv;
     int                                bs_iv_overflows;
 };
 
diff --git a/hv.c b/hv.c
index 4bc252e..e14f7ab 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -542,7 +542,7 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
                }
 
                TAINT_IF(save_taint);
-               if (!xhv->xhv_array /* !HvARRAY(hv) */ && !needs_store) {
+               if (!HvARRAY(hv) && !needs_store) {
                    if (flags & HVhek_FREEKEY)
                        Safefree(key);
                    return Nullhe;
@@ -568,15 +568,15 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
        } /* ISSTORE */
     } /* SvMAGICAL */
 
-    if (!xhv->xhv_array /* !HvARRAY(hv) */) {
+    if (!HvARRAY(hv)) {
        if ((action & (HV_FETCH_LVALUE | HV_FETCH_ISSTORE))
 #ifdef DYNAMIC_ENV_FETCH  /* if it's an %ENV lookup, we may get it on the fly */
                 || (SvRMAGICAL((SV*)hv) && mg_find((SV*)hv, PERL_MAGIC_env))
 #endif
                                                                  )
-           Newz(503, xhv->xhv_array /* HvARRAY(hv) */,
+           Newz(503, HvARRAY(hv),
                 PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */),
-                char);
+                HE*);
 #ifdef DYNAMIC_ENV_FETCH
        else if (action & HV_FETCH_ISEXISTS) {
            /* for an %ENV exists, if we do an insert it's by a recursive
@@ -626,12 +626,11 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
     n_links = 0;
 
 #ifdef DYNAMIC_ENV_FETCH
-    if (!xhv->xhv_array /* !HvARRAY(hv) */) entry = Null(HE*);
+    if (!HvARRAY(hv)) entry = Null(HE*);
     else
 #endif
     {
-       /* entry = (HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
-       entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
+       entry = (HvARRAY(hv))[hash & (I32) HvMAX(hv)];
     }
     for (; entry; ++n_links, entry = HeNEXT(entry)) {
        if (HeHASH(entry) != hash)              /* strings can't be equal */
@@ -741,16 +740,16 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
 
     /* Welcome to hv_store...  */
 
-    if (!xhv->xhv_array) {
+    if (!HvARRAY(hv)) {
        /* Not sure if we can get here.  I think the only case of oentry being
           NULL is for %ENV with dynamic env fetch.  But that should disappear
           with magic in the previous code.  */
-       Newz(503, xhv->xhv_array /* HvARRAY(hv) */,
+       Newz(503, HvARRAY(hv),
             PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */),
-            char);
+            HE*);
     }
 
-    oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
+    oentry = &(HvARRAY(hv))[hash & (I32) xhv->xhv_max];
 
     entry = new_HE();
     /* share_hek_flags will do the free for us.  This might be considered
@@ -941,7 +940,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
        }
     }
     xhv = (XPVHV*)SvANY(hv);
-    if (!xhv->xhv_array /* !HvARRAY(hv) */)
+    if (!HvARRAY(hv))
        return Nullsv;
 
     if (is_utf8) {
@@ -975,8 +974,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
 
     masked_flags = (k_flags & HVhek_MASK);
 
-    /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
-    oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
+    oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)];
     entry = *oentry;
     i = 1;
     for (; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) {
@@ -1056,7 +1054,7 @@ S_hsplit(pTHX_ HV *hv)
     const I32 oldsize = (I32) xhv->xhv_max+1; /* HvMAX(hv)+1 (sick) */
     register I32 newsize = oldsize * 2;
     register I32 i;
-    register char *a = xhv->xhv_array; /* HvARRAY(hv) */
+    char *a = (char*) HvARRAY(hv);
     register HE **aep;
     register HE **oentry;
     int longest_chain = 0;
@@ -1086,19 +1084,19 @@ S_hsplit(pTHX_ HV *hv)
       PL_nomemok = FALSE;
       return;
     }
-    Copy(xhv->xhv_array /* HvARRAY(hv) */, a, oldsize * sizeof(HE*), char);
+    Copy(HvARRAY(hv), a, oldsize * sizeof(HE*), char);
     if (oldsize >= 64) {
-       offer_nice_chunk(xhv->xhv_array /* HvARRAY(hv) */,
+       offer_nice_chunk(HvARRAY(hv),
                        PERL_HV_ARRAY_ALLOC_BYTES(oldsize));
     }
     else
-       Safefree(xhv->xhv_array /* HvARRAY(hv) */);
+       Safefree(HvARRAY(hv));
 #endif
 
     PL_nomemok = FALSE;
     Zero(&a[oldsize * sizeof(HE*)], (newsize-oldsize) * sizeof(HE*), char);    /* zero 2nd half*/
     xhv->xhv_max = --newsize;  /* HvMAX(hv) = --newsize */
-    xhv->xhv_array = a;                /* HvARRAY(hv) = a */
+    HvARRAY(hv) = (HE**) a;
     aep = (HE**)a;
 
     for (i=0; i<oldsize; i++,aep++) {
@@ -1161,7 +1159,7 @@ S_hsplit(pTHX_ HV *hv)
     HvSHAREKEYS_off(hv);
     HvREHASH_on(hv);
 
-    aep = (HE **) xhv->xhv_array;
+    aep = HvARRAY(hv);
 
     for (i=0; i<newsize; i++,aep++) {
        register HE *entry = *aep;
@@ -1200,8 +1198,8 @@ S_hsplit(pTHX_ HV *hv)
            entry = next;
        }
     }
-    Safefree (xhv->xhv_array);
-    xhv->xhv_array = a;                /* HvARRAY(hv) = a */
+    Safefree (HvARRAY(hv));
+    HvARRAY(hv) = (HE **)a;
 }
 
 void
@@ -1227,7 +1225,7 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
     if (newsize < newmax)
        return;                                 /* overflow detection */
 
-    a = xhv->xhv_array; /* HvARRAY(hv) */
+    a = (char *) HvARRAY(hv);
     if (a) {
        PL_nomemok = TRUE;
 #if defined(STRANGE_MALLOC) || defined(MYMALLOC)
@@ -1242,13 +1240,13 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
          PL_nomemok = FALSE;
          return;
        }
-       Copy(xhv->xhv_array /* HvARRAY(hv) */, a, oldsize * sizeof(HE*), char);
+       Copy(HvARRAY(hv), a, oldsize * sizeof(HE*), char);
        if (oldsize >= 64) {
-           offer_nice_chunk(xhv->xhv_array /* HvARRAY(hv) */,
+           offer_nice_chunk(HvARRAY(hv),
                            PERL_HV_ARRAY_ALLOC_BYTES(oldsize));
        }
        else
-           Safefree(xhv->xhv_array /* HvARRAY(hv) */);
+           Safefree(HvARRAY(hv));
 #endif
        PL_nomemok = FALSE;
        Zero(&a[oldsize * sizeof(HE*)], (newsize-oldsize) * sizeof(HE*), char); /* zero 2nd half*/
@@ -1257,7 +1255,7 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
        Newz(0, a, PERL_HV_ARRAY_ALLOC_BYTES(newsize), char);
     }
     xhv->xhv_max = --newsize;  /* HvMAX(hv) = --newsize */
-    xhv->xhv_array = a;        /* HvARRAY(hv) = a */
+    HvARRAY(hv) = (HE **) a;
     if (!xhv->xhv_fill /* !HvFILL(hv) */)      /* skip rest if no entries */
        return;
 
@@ -1451,11 +1449,11 @@ Perl_hv_clear(pTHX_ HV *hv)
 
     xhv = (XPVHV*)SvANY(hv);
 
-    if (SvREADONLY(hv) && xhv->xhv_array != NULL) {
+    if (SvREADONLY(hv) && HvARRAY(hv) != NULL) {
        /* restricted hash: convert all keys to placeholders */
        I32 i;
        for (i = 0; i <= (I32) xhv->xhv_max; i++) {
-           HE *entry = ((HE**)xhv->xhv_array)[i];
+           HE *entry = (HvARRAY(hv))[i];
            for (; entry; entry = HeNEXT(entry)) {
                /* not already placeholder */
                if (HeVAL(entry) != &PL_sv_placeholder) {
@@ -1476,8 +1474,8 @@ Perl_hv_clear(pTHX_ HV *hv)
 
     hfreeentries(hv);
     HvPLACEHOLDERS_set(hv, 0);
-    if (xhv->xhv_array /* HvARRAY(hv) */)
-       (void)memzero(xhv->xhv_array /* HvARRAY(hv) */,
+    if (HvARRAY(hv))
+       (void)memzero(HvARRAY(hv),
                      (xhv->xhv_max+1 /* HvMAX(hv)+1 */) * sizeof(HE*));
 
     if (SvRMAGICAL(hv))
@@ -1621,7 +1619,7 @@ Perl_hv_undef(pTHX_ HV *hv)
     DEBUG_A(Perl_hv_assert(aTHX_ hv));
     xhv = (XPVHV*)SvANY(hv);
     hfreeentries(hv);
-    Safefree(xhv->xhv_array /* HvARRAY(hv) */);
+    Safefree(HvARRAY(hv));
     if ((name = HvNAME_get(hv))) {
        /* FIXME - strlen HvNAME  */
         if(PL_stashcache)
@@ -1629,7 +1627,7 @@ Perl_hv_undef(pTHX_ HV *hv)
        Perl_hv_name_set(aTHX_ hv, 0, 0, 0);
     }
     xhv->xhv_max   = 7;        /* HvMAX(hv) = 7 (it's a normal hash) */
-    xhv->xhv_array = 0;        /* HvARRAY(hv) = 0 */
+    HvARRAY(hv) = 0;
     HvPLACEHOLDERS_set(hv, 0);
 
     if (SvRMAGICAL(hv))
@@ -1881,10 +1879,13 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags)
        prime_env_iter();
 #endif
 
-    if (!xhv->xhv_array /* !HvARRAY(hv) */)
-       Newz(506, xhv->xhv_array /* HvARRAY(hv) */,
+    if (!HvARRAY(hv)) {
+       char *darray;
+       Newz(506, darray,
             PERL_HV_ARRAY_ALLOC_BYTES(xhv->xhv_max+1 /* HvMAX(hv)+1 */),
             char);
+       HvARRAY(hv) = (HE**) darray;
+    }
     /* At start of hash, entry is NULL.  */
     if (entry)
     {
@@ -1908,8 +1909,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags)
            iter->xhv_riter = -1; /* HvRITER(hv) = -1 */
            break;
        }
-       /* entry = (HvARRAY(hv))[HvRITER(hv)]; */
-       entry = ((HE**)xhv->xhv_array)[iter->xhv_riter];
+       entry = (HvARRAY(hv))[iter->xhv_riter];
 
         if (!(flags & HV_ITERNEXT_WANTPLACEHOLDERS)) {
             /* If we have an entry, but it's a placeholder, don't count it.
@@ -2129,8 +2129,7 @@ S_unshare_hek_or_pvn(pTHX_ HEK *hek, const char *str, I32 len, U32 hash)
     xhv = (XPVHV*)SvANY(PL_strtab);
     /* assert(xhv_array != 0) */
     LOCK_STRTAB_MUTEX;
-    /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
-    oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
+    oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)];
     if (hek) {
         for (entry = *oentry; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) {
             if (HeKEY_hek(entry) != hek)
@@ -2228,8 +2227,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags)
     xhv = (XPVHV*)SvANY(PL_strtab);
     /* assert(xhv_array != 0) */
     LOCK_STRTAB_MUTEX;
-    /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
-    oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
+    oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)];
     for (entry = *oentry; entry; i=0, entry = HeNEXT(entry)) {
        if (HeHASH(entry) != hash)              /* strings can't be equal */
            continue;
diff --git a/hv.h b/hv.h
index 2388113..63454b9 100644 (file)
--- a/hv.h
+++ b/hv.h
@@ -42,7 +42,6 @@ struct xpvhv_aux {
 /* hash structure: */
 /* This structure must match the beginning of struct xpvmg in sv.h. */
 struct xpvhv {
-    char *     xhv_array;      /* pointer to malloced string */
     STRLEN     xhv_fill;       /* how full xhv_array currently is */
     STRLEN     xhv_max;        /* subscript of last element of xhv_array */
     IV         xhv_keys;       /* how many elements in the array */
@@ -183,7 +182,7 @@ C<SV*>.
 
 
 #define Nullhv Null(HV*)
-#define HvARRAY(hv)    (*(HE***)&((XPVHV*)  SvANY(hv))->xhv_array)
+#define HvARRAY(hv)    (*(HE***)&((hv)->sv_u.sv_array))
 #define HvFILL(hv)     ((XPVHV*)  SvANY(hv))->xhv_fill
 #define HvMAX(hv)      ((XPVHV*)  SvANY(hv))->xhv_max
 #define HvRITER(hv)    (*Perl_hv_riter_p(aTHX_ (HV*)(hv)))
diff --git a/proto.h b/proto.h
index 3b07c32..8718035 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -2053,7 +2053,6 @@ STATIC SV*        S_save_scalar_at(pTHX_ SV **sptr);
 #if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
 STATIC IV      S_asIV(pTHX_ SV* sv);
 STATIC UV      S_asUV(pTHX_ SV* sv);
-STATIC XPVIV*  S_new_xiv(pTHX);
 STATIC XPVNV*  S_new_xnv(pTHX);
 STATIC XPV*    S_new_xpv(pTHX);
 STATIC XPVIV*  S_new_xpviv(pTHX);
@@ -2065,8 +2064,6 @@ STATIC XPVMG*     S_new_xpvmg(pTHX);
 STATIC XPVGV*  S_new_xpvgv(pTHX);
 STATIC XPVLV*  S_new_xpvlv(pTHX);
 STATIC XPVBM*  S_new_xpvbm(pTHX);
-STATIC XRV*    S_new_xrv(pTHX);
-STATIC void    S_del_xiv(pTHX_ XPVIV* p);
 STATIC void    S_del_xnv(pTHX_ XPVNV* p);
 STATIC void    S_del_xpv(pTHX_ XPV* p);
 STATIC void    S_del_xpviv(pTHX_ XPVIV* p);
@@ -2078,7 +2075,6 @@ STATIC void       S_del_xpvmg(pTHX_ XPVMG* p);
 STATIC void    S_del_xpvgv(pTHX_ XPVGV* p);
 STATIC void    S_del_xpvlv(pTHX_ XPVLV* p);
 STATIC void    S_del_xpvbm(pTHX_ XPVBM* p);
-STATIC void    S_del_xrv(pTHX_ XRV* p);
 STATIC void    S_sv_unglob(pTHX_ SV* sv);
 STATIC void    S_not_a_number(pTHX_ SV *sv);
 STATIC I32     S_visit(pTHX_ SVFUNC_t f, U32 flags, U32 mask);
diff --git a/sv.c b/sv.c
index 51a3896..9658505 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -523,7 +523,7 @@ Perl_sv_free_arenas(pTHX)
 {
     SV* sva;
     SV* svanext;
-    XPV *arena, *arenanext;
+    void *arena, *arenanext;
 
     /* Free arenas here, but be careful about fake ones.  (We assume
        contiguity of the fake ones with the corresponding real ones.) */
@@ -537,92 +537,78 @@ Perl_sv_free_arenas(pTHX)
            Safefree((void *)sva);
     }
 
-    for (arena = PL_xiv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
-       Safefree(arena);
-    }
-    PL_xiv_arenaroot = 0;
-    PL_xiv_root = 0;
-
     for (arena = PL_xnv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xnv_arenaroot = 0;
     PL_xnv_root = 0;
 
-    for (arena = PL_xrv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
-       Safefree(arena);
-    }
-    PL_xrv_arenaroot = 0;
-    PL_xrv_root = 0;
-
     for (arena = PL_xpv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpv_arenaroot = 0;
     PL_xpv_root = 0;
 
-    for (arena = (XPV*)PL_xpviv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpviv_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpviv_arenaroot = 0;
     PL_xpviv_root = 0;
 
-    for (arena = (XPV*)PL_xpvnv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvnv_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvnv_arenaroot = 0;
     PL_xpvnv_root = 0;
 
-    for (arena = (XPV*)PL_xpvcv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvcv_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvcv_arenaroot = 0;
     PL_xpvcv_root = 0;
 
-    for (arena = (XPV*)PL_xpvav_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvav_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvav_arenaroot = 0;
     PL_xpvav_root = 0;
 
-    for (arena = (XPV*)PL_xpvhv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvhv_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvhv_arenaroot = 0;
     PL_xpvhv_root = 0;
 
-    for (arena = (XPV*)PL_xpvmg_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvmg_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvmg_arenaroot = 0;
     PL_xpvmg_root = 0;
 
-    for (arena = (XPV*)PL_xpvgv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvgv_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvgv_arenaroot = 0;
     PL_xpvgv_root = 0;
 
-    for (arena = (XPV*)PL_xpvlv_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvlv_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvlv_arenaroot = 0;
     PL_xpvlv_root = 0;
 
-    for (arena = (XPV*)PL_xpvbm_arenaroot; arena; arena = arenanext) {
-       arenanext = (XPV*)arena->xpv_pv;
+    for (arena = PL_xpvbm_arenaroot; arena; arena = arenanext) {
+       arenanext = *(void **)arena;
        Safefree(arena);
     }
     PL_xpvbm_arenaroot = 0;
@@ -1139,53 +1125,6 @@ Perl_report_uninit(pTHX_ SV* uninit_sv)
                    "", "", "");
 }
 
-
-/* allocate another arena's worth of struct xrv */
-
-STATIC void
-S_more_xrv(pTHX)
-{
-    XRV* xrv;
-    XRV* xrvend;
-    XPV *ptr;
-    New(712, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    ptr->xpv_pv = (char*)PL_xrv_arenaroot;
-    PL_xrv_arenaroot = ptr;
-
-    xrv = (XRV*) ptr;
-    xrvend = &xrv[PERL_ARENA_SIZE / sizeof(XRV) - 1];
-    xrv += (sizeof(XPV) - 1) / sizeof(XRV) + 1;
-    PL_xrv_root = xrv;
-    while (xrv < xrvend) {
-       xrv->xrv_rv = (SV*)(xrv + 1);
-       xrv++;
-    }
-    xrv->xrv_rv = 0;
-}
-
-/* allocate another arena's worth of IV bodies */
-
-STATIC void
-S_more_xiv(pTHX)
-{
-    IV* xiv;
-    IV* xivend;
-    XPV* ptr;
-    New(705, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    ptr->xpv_pv = (char*)PL_xiv_arenaroot;     /* linked list of xiv arenas */
-    PL_xiv_arenaroot = ptr;                    /* to keep Purify happy */
-
-    xiv = (IV*) ptr;
-    xivend = &xiv[PERL_ARENA_SIZE / sizeof(IV) - 1];
-    xiv += (sizeof(XPV) - 1) / sizeof(IV) + 1; /* fudge by size of XPV */
-    PL_xiv_root = xiv;
-    while (xiv < xivend) {
-       *(IV**)xiv = (IV *)(xiv + 1);
-       xiv++;
-    }
-    *(IV**)xiv = 0;
-}
-
 /* allocate another arena's worth of NV bodies */
 
 STATIC void
@@ -1193,9 +1132,9 @@ S_more_xnv(pTHX)
 {
     NV* xnv;
     NV* xnvend;
-    XPV *ptr;
-    New(711, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    ptr->xpv_pv = (char*)PL_xnv_arenaroot;
+    void *ptr;
+    New(711, ptr, PERL_ARENA_SIZE/sizeof(NV), NV);
+    *((void **) ptr) = (void *)PL_xnv_arenaroot;
     PL_xnv_arenaroot = ptr;
 
     xnv = (NV*) ptr;
@@ -1217,16 +1156,16 @@ S_more_xpv(pTHX)
     XPV* xpv;
     XPV* xpvend;
     New(713, xpv, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    xpv->xpv_pv = (char*)PL_xpv_arenaroot;
+    *((XPV**)xpv) = PL_xpv_arenaroot;
     PL_xpv_arenaroot = xpv;
 
     xpvend = &xpv[PERL_ARENA_SIZE / sizeof(XPV) - 1];
     PL_xpv_root = ++xpv;
     while (xpv < xpvend) {
-       xpv->xpv_pv = (char*)(xpv + 1);
+       *((XPV**)xpv) = xpv + 1;
        xpv++;
     }
-    xpv->xpv_pv = 0;
+    *((XPV**)xpv) = 0;
 }
 
 /* allocate another arena's worth of struct xpviv */
@@ -1237,16 +1176,16 @@ S_more_xpviv(pTHX)
     XPVIV* xpviv;
     XPVIV* xpvivend;
     New(714, xpviv, PERL_ARENA_SIZE/sizeof(XPVIV), XPVIV);
-    xpviv->xpv_pv = (char*)PL_xpviv_arenaroot;
+    *((XPVIV**)xpviv) = PL_xpviv_arenaroot;
     PL_xpviv_arenaroot = xpviv;
 
     xpvivend = &xpviv[PERL_ARENA_SIZE / sizeof(XPVIV) - 1];
     PL_xpviv_root = ++xpviv;
     while (xpviv < xpvivend) {
-       xpviv->xpv_pv = (char*)(xpviv + 1);
+       *((XPVIV**)xpviv) = xpviv + 1;
        xpviv++;
     }
-    xpviv->xpv_pv = 0;
+    *((XPVIV**)xpviv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvnv */
@@ -1257,16 +1196,16 @@ S_more_xpvnv(pTHX)
     XPVNV* xpvnv;
     XPVNV* xpvnvend;
     New(715, xpvnv, PERL_ARENA_SIZE/sizeof(XPVNV), XPVNV);
-    xpvnv->xpv_pv = (char*)PL_xpvnv_arenaroot;
+    *((XPVNV**)xpvnv) = PL_xpvnv_arenaroot;
     PL_xpvnv_arenaroot = xpvnv;
 
     xpvnvend = &xpvnv[PERL_ARENA_SIZE / sizeof(XPVNV) - 1];
     PL_xpvnv_root = ++xpvnv;
     while (xpvnv < xpvnvend) {
-       xpvnv->xpv_pv = (char*)(xpvnv + 1);
+       *((XPVNV**)xpvnv) = xpvnv + 1;
        xpvnv++;
     }
-    xpvnv->xpv_pv = 0;
+    *((XPVNV**)xpvnv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvcv */
@@ -1277,16 +1216,16 @@ S_more_xpvcv(pTHX)
     XPVCV* xpvcv;
     XPVCV* xpvcvend;
     New(716, xpvcv, PERL_ARENA_SIZE/sizeof(XPVCV), XPVCV);
-    xpvcv->xpv_pv = (char*)PL_xpvcv_arenaroot;
+    *((XPVCV**)xpvcv) = PL_xpvcv_arenaroot;
     PL_xpvcv_arenaroot = xpvcv;
 
     xpvcvend = &xpvcv[PERL_ARENA_SIZE / sizeof(XPVCV) - 1];
     PL_xpvcv_root = ++xpvcv;
     while (xpvcv < xpvcvend) {
-       xpvcv->xpv_pv = (char*)(xpvcv + 1);
+       *((XPVCV**)xpvcv) = xpvcv + 1;
        xpvcv++;
     }
-    xpvcv->xpv_pv = 0;
+    *((XPVCV**)xpvcv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvav */
@@ -1297,16 +1236,16 @@ S_more_xpvav(pTHX)
     XPVAV* xpvav;
     XPVAV* xpvavend;
     New(717, xpvav, PERL_ARENA_SIZE/sizeof(XPVAV), XPVAV);
-    xpvav->xav_array = (char*)PL_xpvav_arenaroot;
+    *((XPVAV**)xpvav) = PL_xpvav_arenaroot;
     PL_xpvav_arenaroot = xpvav;
 
     xpvavend = &xpvav[PERL_ARENA_SIZE / sizeof(XPVAV) - 1];
     PL_xpvav_root = ++xpvav;
     while (xpvav < xpvavend) {
-       xpvav->xav_array = (char*)(xpvav + 1);
+       *((XPVAV**)xpvav) = xpvav + 1;
        xpvav++;
     }
-    xpvav->xav_array = 0;
+    *((XPVAV**)xpvav) = 0;
 }
 
 /* allocate another arena's worth of struct xpvhv */
@@ -1317,16 +1256,16 @@ S_more_xpvhv(pTHX)
     XPVHV* xpvhv;
     XPVHV* xpvhvend;
     New(718, xpvhv, PERL_ARENA_SIZE/sizeof(XPVHV), XPVHV);
-    xpvhv->xhv_array = (char*)PL_xpvhv_arenaroot;
+    *((XPVHV**)xpvhv) = PL_xpvhv_arenaroot;
     PL_xpvhv_arenaroot = xpvhv;
 
     xpvhvend = &xpvhv[PERL_ARENA_SIZE / sizeof(XPVHV) - 1];
     PL_xpvhv_root = ++xpvhv;
     while (xpvhv < xpvhvend) {
-       xpvhv->xhv_array = (char*)(xpvhv + 1);
+       *((XPVHV**)xpvhv) = xpvhv + 1;
        xpvhv++;
     }
-    xpvhv->xhv_array = 0;
+    *((XPVHV**)xpvhv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvmg */
@@ -1337,16 +1276,16 @@ S_more_xpvmg(pTHX)
     XPVMG* xpvmg;
     XPVMG* xpvmgend;
     New(719, xpvmg, PERL_ARENA_SIZE/sizeof(XPVMG), XPVMG);
-    xpvmg->xpv_pv = (char*)PL_xpvmg_arenaroot;
+    *((XPVMG**)xpvmg) = PL_xpvmg_arenaroot;
     PL_xpvmg_arenaroot = xpvmg;
 
     xpvmgend = &xpvmg[PERL_ARENA_SIZE / sizeof(XPVMG) - 1];
     PL_xpvmg_root = ++xpvmg;
     while (xpvmg < xpvmgend) {
-       xpvmg->xpv_pv = (char*)(xpvmg + 1);
+       *((XPVMG**)xpvmg) = xpvmg + 1;
        xpvmg++;
     }
-    xpvmg->xpv_pv = 0;
+    *((XPVMG**)xpvmg) = 0;
 }
 
 /* allocate another arena's worth of struct xpvgv */
@@ -1357,16 +1296,16 @@ S_more_xpvgv(pTHX)
     XPVGV* xpvgv;
     XPVGV* xpvgvend;
     New(720, xpvgv, PERL_ARENA_SIZE/sizeof(XPVGV), XPVGV);
-    xpvgv->xpv_pv = (char*)PL_xpvgv_arenaroot;
+    *((XPVGV**)xpvgv) = PL_xpvgv_arenaroot;
     PL_xpvgv_arenaroot = xpvgv;
 
     xpvgvend = &xpvgv[PERL_ARENA_SIZE / sizeof(XPVGV) - 1];
     PL_xpvgv_root = ++xpvgv;
     while (xpvgv < xpvgvend) {
-       xpvgv->xpv_pv = (char*)(xpvgv + 1);
+       *((XPVGV**)xpvgv) = xpvgv + 1;
        xpvgv++;
     }
-    xpvgv->xpv_pv = 0;
+    *((XPVGV**)xpvgv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvlv */
@@ -1377,16 +1316,16 @@ S_more_xpvlv(pTHX)
     XPVLV* xpvlv;
     XPVLV* xpvlvend;
     New(720, xpvlv, PERL_ARENA_SIZE/sizeof(XPVLV), XPVLV);
-    xpvlv->xpv_pv = (char*)PL_xpvlv_arenaroot;
+    *((XPVLV**)xpvlv) = PL_xpvlv_arenaroot;
     PL_xpvlv_arenaroot = xpvlv;
 
     xpvlvend = &xpvlv[PERL_ARENA_SIZE / sizeof(XPVLV) - 1];
     PL_xpvlv_root = ++xpvlv;
     while (xpvlv < xpvlvend) {
-       xpvlv->xpv_pv = (char*)(xpvlv + 1);
+       *((XPVLV**)xpvlv) = xpvlv + 1;
        xpvlv++;
     }
-    xpvlv->xpv_pv = 0;
+    *((XPVLV**)xpvlv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvbm */
@@ -1397,72 +1336,16 @@ S_more_xpvbm(pTHX)
     XPVBM* xpvbm;
     XPVBM* xpvbmend;
     New(721, xpvbm, PERL_ARENA_SIZE/sizeof(XPVBM), XPVBM);
-    xpvbm->xpv_pv = (char*)PL_xpvbm_arenaroot;
+    *((XPVBM**)xpvbm) = PL_xpvbm_arenaroot;
     PL_xpvbm_arenaroot = xpvbm;
 
     xpvbmend = &xpvbm[PERL_ARENA_SIZE / sizeof(XPVBM) - 1];
     PL_xpvbm_root = ++xpvbm;
     while (xpvbm < xpvbmend) {
-       xpvbm->xpv_pv = (char*)(xpvbm + 1);
+       *((XPVBM**)xpvbm) = xpvbm + 1;
        xpvbm++;
     }
-    xpvbm->xpv_pv = 0;
-}
-
-/* grab a new struct xrv from the free list, allocating more if necessary */
-
-STATIC XRV*
-S_new_xrv(pTHX)
-{
-    XRV* xrv;
-    LOCK_SV_MUTEX;
-    if (!PL_xrv_root)
-       S_more_xrv(aTHX);
-    xrv = PL_xrv_root;
-    PL_xrv_root = (XRV*)xrv->xrv_rv;
-    UNLOCK_SV_MUTEX;
-    return xrv;
-}
-
-/* return a struct xrv to the free list */
-
-STATIC void
-S_del_xrv(pTHX_ XRV *p)
-{
-    LOCK_SV_MUTEX;
-    p->xrv_rv = (SV*)PL_xrv_root;
-    PL_xrv_root = p;
-    UNLOCK_SV_MUTEX;
-}
-
-/* grab a new IV body from the free list, allocating more if necessary */
-
-STATIC XPVIV*
-S_new_xiv(pTHX)
-{
-    IV* xiv;
-    LOCK_SV_MUTEX;
-    if (!PL_xiv_root)
-       S_more_xiv(aTHX);
-    xiv = PL_xiv_root;
-    /*
-     * See comment in more_xiv() -- RAM.
-     */
-    PL_xiv_root = *(IV**)xiv;
-    UNLOCK_SV_MUTEX;
-    return (XPVIV*)((char*)xiv - STRUCT_OFFSET(XPVIV, xiv_iv));
-}
-
-/* return an IV body to the free list */
-
-STATIC void
-S_del_xiv(pTHX_ XPVIV *p)
-{
-    IV* xiv = (IV*)((char*)(p) + STRUCT_OFFSET(XPVIV, xiv_iv));
-    LOCK_SV_MUTEX;
-    *(IV**)xiv = PL_xiv_root;
-    PL_xiv_root = xiv;
-    UNLOCK_SV_MUTEX;
+    *((XPVBM**)xpvbm) = 0;
 }
 
 /* grab a new NV body from the free list, allocating more if necessary */
@@ -1502,7 +1385,7 @@ S_new_xpv(pTHX)
     if (!PL_xpv_root)
        S_more_xpv(aTHX);
     xpv = PL_xpv_root;
-    PL_xpv_root = (XPV*)xpv->xpv_pv;
+    PL_xpv_root = *(XPV**)xpv;
     UNLOCK_SV_MUTEX;
     return xpv;
 }
@@ -1513,7 +1396,7 @@ STATIC void
 S_del_xpv(pTHX_ XPV *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpv_root;
+    *(XPV**)p = PL_xpv_root;
     PL_xpv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1528,7 +1411,7 @@ S_new_xpviv(pTHX)
     if (!PL_xpviv_root)
        S_more_xpviv(aTHX);
     xpviv = PL_xpviv_root;
-    PL_xpviv_root = (XPVIV*)xpviv->xpv_pv;
+    PL_xpviv_root = *(XPVIV**)xpviv;
     UNLOCK_SV_MUTEX;
     return xpviv;
 }
@@ -1539,7 +1422,7 @@ STATIC void
 S_del_xpviv(pTHX_ XPVIV *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpviv_root;
+    *(XPVIV**)p = PL_xpviv_root;
     PL_xpviv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1554,7 +1437,7 @@ S_new_xpvnv(pTHX)
     if (!PL_xpvnv_root)
        S_more_xpvnv(aTHX);
     xpvnv = PL_xpvnv_root;
-    PL_xpvnv_root = (XPVNV*)xpvnv->xpv_pv;
+    PL_xpvnv_root = *(XPVNV**)xpvnv;
     UNLOCK_SV_MUTEX;
     return xpvnv;
 }
@@ -1565,7 +1448,7 @@ STATIC void
 S_del_xpvnv(pTHX_ XPVNV *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpvnv_root;
+    *(XPVNV**)p = PL_xpvnv_root;
     PL_xpvnv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1580,7 +1463,7 @@ S_new_xpvcv(pTHX)
     if (!PL_xpvcv_root)
        S_more_xpvcv(aTHX);
     xpvcv = PL_xpvcv_root;
-    PL_xpvcv_root = (XPVCV*)xpvcv->xpv_pv;
+    PL_xpvcv_root = *(XPVCV**)xpvcv;
     UNLOCK_SV_MUTEX;
     return xpvcv;
 }
@@ -1591,7 +1474,7 @@ STATIC void
 S_del_xpvcv(pTHX_ XPVCV *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpvcv_root;
+    *(XPVCV**)p = PL_xpvcv_root;
     PL_xpvcv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1606,7 +1489,7 @@ S_new_xpvav(pTHX)
     if (!PL_xpvav_root)
        S_more_xpvav(aTHX);
     xpvav = PL_xpvav_root;
-    PL_xpvav_root = (XPVAV*)xpvav->xav_array;
+    PL_xpvav_root = *(XPVAV**)xpvav;
     UNLOCK_SV_MUTEX;
     return xpvav;
 }
@@ -1617,7 +1500,7 @@ STATIC void
 S_del_xpvav(pTHX_ XPVAV *p)
 {
     LOCK_SV_MUTEX;
-    p->xav_array = (char*)PL_xpvav_root;
+    *(XPVAV**)p = PL_xpvav_root;
     PL_xpvav_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1632,7 +1515,7 @@ S_new_xpvhv(pTHX)
     if (!PL_xpvhv_root)
        S_more_xpvhv(aTHX);
     xpvhv = PL_xpvhv_root;
-    PL_xpvhv_root = (XPVHV*)xpvhv->xhv_array;
+    PL_xpvhv_root = *(XPVHV**)xpvhv;
     UNLOCK_SV_MUTEX;
     return xpvhv;
 }
@@ -1643,7 +1526,7 @@ STATIC void
 S_del_xpvhv(pTHX_ XPVHV *p)
 {
     LOCK_SV_MUTEX;
-    p->xhv_array = (char*)PL_xpvhv_root;
+    *(XPVHV**)p = PL_xpvhv_root;
     PL_xpvhv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1658,7 +1541,7 @@ S_new_xpvmg(pTHX)
     if (!PL_xpvmg_root)
        S_more_xpvmg(aTHX);
     xpvmg = PL_xpvmg_root;
-    PL_xpvmg_root = (XPVMG*)xpvmg->xpv_pv;
+    PL_xpvmg_root = *(XPVMG**)xpvmg;
     UNLOCK_SV_MUTEX;
     return xpvmg;
 }
@@ -1669,7 +1552,7 @@ STATIC void
 S_del_xpvmg(pTHX_ XPVMG *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpvmg_root;
+    *(XPVMG**)p = PL_xpvmg_root;
     PL_xpvmg_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1684,7 +1567,7 @@ S_new_xpvgv(pTHX)
     if (!PL_xpvgv_root)
        S_more_xpvgv(aTHX);
     xpvgv = PL_xpvgv_root;
-    PL_xpvgv_root = (XPVGV*)xpvgv->xpv_pv;
+    PL_xpvgv_root = *(XPVGV**)xpvgv;
     UNLOCK_SV_MUTEX;
     return xpvgv;
 }
@@ -1695,7 +1578,7 @@ STATIC void
 S_del_xpvgv(pTHX_ XPVGV *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpvgv_root;
+    *(XPVGV**)p = PL_xpvgv_root;
     PL_xpvgv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1710,7 +1593,7 @@ S_new_xpvlv(pTHX)
     if (!PL_xpvlv_root)
        S_more_xpvlv(aTHX);
     xpvlv = PL_xpvlv_root;
-    PL_xpvlv_root = (XPVLV*)xpvlv->xpv_pv;
+    PL_xpvlv_root = *(XPVLV**)xpvlv;
     UNLOCK_SV_MUTEX;
     return xpvlv;
 }
@@ -1721,7 +1604,7 @@ STATIC void
 S_del_xpvlv(pTHX_ XPVLV *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpvlv_root;
+    *(XPVLV**)p = PL_xpvlv_root;
     PL_xpvlv_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1736,7 +1619,7 @@ S_new_xpvbm(pTHX)
     if (!PL_xpvbm_root)
        S_more_xpvbm(aTHX);
     xpvbm = PL_xpvbm_root;
-    PL_xpvbm_root = (XPVBM*)xpvbm->xpv_pv;
+    PL_xpvbm_root = *(XPVBM**)xpvbm;
     UNLOCK_SV_MUTEX;
     return xpvbm;
 }
@@ -1747,7 +1630,7 @@ STATIC void
 S_del_xpvbm(pTHX_ XPVBM *p)
 {
     LOCK_SV_MUTEX;
-    p->xpv_pv = (char*)PL_xpvbm_root;
+    *(XPVBM**)p = PL_xpvbm_root;
     PL_xpvbm_root = p;
     UNLOCK_SV_MUTEX;
 }
@@ -1757,15 +1640,9 @@ S_del_xpvbm(pTHX_ XPVBM *p)
 
 #ifdef PURIFY
 
-#define new_XIV()      my_safemalloc(sizeof(XPVIV))
-#define del_XIV(p)     my_safefree(p)
-
 #define new_XNV()      my_safemalloc(sizeof(XPVNV))
 #define del_XNV(p)     my_safefree(p)
 
-#define new_XRV()      my_safemalloc(sizeof(XRV))
-#define del_XRV(p)     my_safefree(p)
-
 #define new_XPV()      my_safemalloc(sizeof(XPV))
 #define del_XPV(p)     my_safefree(p)
 
@@ -1798,15 +1675,9 @@ S_del_xpvbm(pTHX_ XPVBM *p)
 
 #else /* !PURIFY */
 
-#define new_XIV()      (void*)new_xiv()
-#define del_XIV(p)     del_xiv((XPVIV*) p)
-
 #define new_XNV()      (void*)new_xnv()
 #define del_XNV(p)     del_xnv((XPVNV*) p)
 
-#define new_XRV()      (void*)new_xrv()
-#define del_XRV(p)     del_xrv((XRV*) p)
-
 #define new_XPV()      (void*)new_xpv()
 #define del_XPV(p)     del_xpv((XPV *)p)
 
@@ -1887,7 +1758,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        break;
     case SVt_IV:
        iv      = SvIVX(sv);
-       del_XIV(SvANY(sv));
        if (mt == SVt_NV)
            mt = SVt_PVNV;
        else if (mt < SVt_PVIV)
@@ -1901,7 +1771,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        break;
     case SVt_RV:
        pv      = (char*)SvRV(sv);
-       del_XRV(SvANY(sv));
        break;
     case SVt_PV:
        pv      = SvPVX(sv);
@@ -1957,7 +1826,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
     case SVt_NULL:
        Perl_croak(aTHX_ "Can't upgrade to undef");
     case SVt_IV:
-       SvANY(sv) = new_XIV();
+       SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
        SvIV_set(sv, iv);
        break;
     case SVt_NV:
@@ -1965,7 +1834,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        SvNV_set(sv, nv);
        break;
     case SVt_RV:
-       SvANY(sv) = new_XRV();
+       SvANY(sv) = &sv->sv_u.sv_rv;
        SvRV_set(sv, (SV*)pv);
        break;
     case SVt_PVHV:
@@ -3911,9 +3780,9 @@ Perl_sv_2bool(pTHX_ register SV *sv)
     if (SvPOKp(sv)) {
        register XPV* Xpvtmp;
        if ((Xpvtmp = (XPV*)SvANY(sv)) &&
-               (*Xpvtmp->xpv_pv > '0' ||
+               (*sv->sv_u.sv_pv > '0' ||
                Xpvtmp->xpv_cur > 1 ||
-               (Xpvtmp->xpv_cur && *Xpvtmp->xpv_pv != '0')))
+               (Xpvtmp->xpv_cur && *sv->sv_u.sv_pv != '0')))
            return 1;
        else
            return 0;
@@ -5870,6 +5739,15 @@ Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
 #else
     StructCopy(nsv,sv,SV);
 #endif
+    /* Currently could join these into one piece of pointer arithmetic, but
+       it would be unclear.  */
+    if(SvTYPE(sv) == SVt_IV)
+       SvANY(sv)
+           = (XPVIV*)((char*)&(sv->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+    else if (SvTYPE(sv) == SVt_RV) {
+       SvANY(sv) = &sv->sv_u.sv_rv;
+    }
+       
 
 #ifdef PERL_COPY_ON_WRITE
     if (SvIsCOW_normal(nsv)) {
@@ -6084,13 +5962,11 @@ Perl_sv_clear(pTHX_ register SV *sv)
     case SVt_NULL:
        break;
     case SVt_IV:
-       del_XIV(SvANY(sv));
        break;
     case SVt_NV:
        del_XNV(SvANY(sv));
        break;
     case SVt_RV:
-       del_XRV(SvANY(sv));
        break;
     case SVt_PV:
        del_XPV(SvANY(sv));
@@ -8146,7 +8022,7 @@ Perl_sv_true(pTHX_ register SV *sv)
        const register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
                (tXpv->xpv_cur > 1 ||
-               (tXpv->xpv_cur && *tXpv->xpv_pv != '0')))
+               (tXpv->xpv_cur && *sv->sv_u.sv_pv != '0')))
            return 1;
        else
            return 0;
@@ -10833,7 +10709,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvANY(dstr)     = NULL;
        break;
     case SVt_IV:
-       SvANY(dstr)     = new_XIV();
+       SvANY(dstr)     = (XPVIV*)((char*)&(dstr->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
        SvIV_set(dstr, SvIVX(sstr));
        break;
     case SVt_NV:
@@ -10841,7 +10717,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvNV_set(dstr, SvNVX(sstr));
        break;
     case SVt_RV:
-       SvANY(dstr)     = new_XRV();
+       SvANY(dstr)     = &(dstr->sv_u.sv_rv);
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PV:
@@ -11040,11 +10916,14 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
                STRLEN i = 0;
                XPVHV *dxhv = (XPVHV*)SvANY(dstr);
                XPVHV *sxhv = (XPVHV*)SvANY(sstr);
-               Newz(0, dxhv->xhv_array,
+               char *darray;
+               /* FIXME - surely this doesn't need to be zeroed?  */
+               Newz(0, darray,
                     PERL_HV_ARRAY_ALLOC_BYTES(dxhv->xhv_max+1), char);
+               HvARRAY(dstr) = (HE**)darray;
                while (i <= sxhv->xhv_max) {
-                   ((HE**)dxhv->xhv_array)[i]
-                       = he_dup(((HE**)sxhv->xhv_array)[i],
+                   HvARRAY(dstr)[i]
+                       = he_dup(HvARRAY(sstr)[i],
                                 (bool)!!HvSHAREKEYS(sstr), param);
                    ++i;
                }
@@ -11728,12 +11607,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     param->proto_perl = proto_perl;
 
     /* arena roots */
-    PL_xiv_arenaroot   = NULL;
-    PL_xiv_root                = NULL;
     PL_xnv_arenaroot   = NULL;
     PL_xnv_root                = NULL;
-    PL_xrv_arenaroot   = NULL;
-    PL_xrv_root                = NULL;
     PL_xpv_arenaroot   = NULL;
     PL_xpv_root                = NULL;
     PL_xpviv_arenaroot = NULL;
diff --git a/sv.h b/sv.h
index 6c5c451..04fef7c 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -68,6 +68,13 @@ struct STRUCT_SV {           /* struct sv { */
     void*      sv_any;         /* pointer to something */
     U32                sv_refcnt;      /* how many references to us */
     U32                sv_flags;       /* what we are */
+    union {
+       IV      sv_iv;
+       UV      sv_uv;
+       SV*     sv_rv;          /* pointer to another SV */
+       char*   sv_pv;          /* pointer to malloced string */
+       SV**    sv_array;
+    }          sv_u;
 #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 */
@@ -81,30 +88,65 @@ struct gv {
     XPVGV*     sv_any;         /* pointer to something */
     U32                sv_refcnt;      /* how many references to us */
     U32                sv_flags;       /* what we are */
+    union {
+       IV      sv_iv;
+       UV      sv_uv;
+       SV*     sv_rv;
+       char*   sv_pv;
+       SV**    sv_array;
+    }          sv_u;
 };
 
 struct cv {
     XPVCV*     sv_any;         /* pointer to something */
     U32                sv_refcnt;      /* how many references to us */
     U32                sv_flags;       /* what we are */
+    union {
+       IV      sv_iv;
+       UV      sv_uv;
+       SV*     sv_rv;
+       char*   sv_pv;
+       SV**    sv_array;
+    }          sv_u;
 };
 
 struct av {
     XPVAV*     sv_any;         /* pointer to something */
     U32                sv_refcnt;      /* how many references to us */
     U32                sv_flags;       /* what we are */
+    union {
+       IV      sv_iv;
+       UV      sv_uv;
+       SV*     sv_rv;
+       char*   sv_pv;          /* pointer to first array element */
+       SV**    sv_array;
+    }          sv_u;
 };
 
 struct hv {
     XPVHV*     sv_any;         /* pointer to something */
     U32                sv_refcnt;      /* how many references to us */
     U32                sv_flags;       /* what we are */
+    union {
+       IV      sv_iv;
+       UV      sv_uv;
+       SV*     sv_rv;
+       char*   sv_pv;
+       SV**    sv_array;
+    }          sv_u;
 };
 
 struct io {
     XPVIO*     sv_any;         /* pointer to something */
     U32                sv_refcnt;      /* how many references to us */
     U32                sv_flags;       /* what we are */
+    union {
+       IV      sv_iv;
+       UV      sv_uv;
+       SV*     sv_rv;
+       char*   sv_pv;
+       SV**    sv_array;
+    }          sv_u;
 };
 
 /*
@@ -232,33 +274,25 @@ perform the upgrade if necessary.  See C<svtype>.
 #define SVpav_REAL     0x40000000      /* free old entries */
 #define SVpav_REIFY    0x80000000      /* can become real */
 
-struct xrv {
-    SV *       xrv_rv;         /* pointer to another SV */
-};
-
 struct xpv {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
 };
 
 struct xpviv {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
 };
 
 struct xpvuv {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     UV         xuv_uv;         /* unsigned value or pv offset */
 };
 
 struct xpvnv {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -266,8 +300,7 @@ struct xpvnv {
 
 /* These structure must match the beginning of struct xpvhv in hv.h. */
 struct xpvmg {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -276,8 +309,7 @@ struct xpvmg {
 };
 
 struct xpvlv {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -299,8 +331,7 @@ struct xpvlv {
 };
 
 struct xpvgv {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -315,8 +346,7 @@ struct xpvgv {
 };
 
 struct xpvbm {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -333,8 +363,7 @@ struct xpvbm {
 typedef U16 cv_flags_t;
 
 struct xpvfm {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -359,8 +388,7 @@ struct xpvfm {
 };
 
 struct xpvio {
-    char *     xpv_pv;         /* pointer to malloced string */
-    STRLEN     xpv_cur;        /* length of xpv_pv as a C string */
+    STRLEN     xpv_cur;        /* length of sv_pv as a C string */
     STRLEN     xpv_len;        /* allocated size */
     IV         xiv_iv;         /* integer value or pv offset */
     NV         xnv_nv;         /* numeric value, if any */
@@ -762,9 +790,9 @@ in gv.h: */
 #endif
 
 #ifdef PERL_DEBUG_COW
-#define SvRV(sv) (0 + ((XRV*)  SvANY(sv))->xrv_rv)
+#define SvRV(sv) (0 + (sv)->sv_u.sv_rv)
 #else
-#define SvRV(sv) ((XRV*)  SvANY(sv))->xrv_rv
+#define SvRV(sv) ((sv)->sv_u.sv_rv)
 #endif
 #define SvRVx(sv) SvRV(sv)
 
@@ -772,10 +800,10 @@ in gv.h: */
 #define SvIVX(sv) (0 + ((XPVIV*) SvANY(sv))->xiv_iv)
 #define SvUVX(sv) (0 + ((XPVUV*) SvANY(sv))->xuv_uv)
 #define SvNVX(sv) (0 + ((XPVNV*) SvANY(sv))->xnv_nv)
-#define SvPVX(sv) (0 + ((XPV*) SvANY(sv))->xpv_pv)
+#define SvPVX(sv) (0 + (sv)->sv_u.sv_pv)
 #define SvCUR(sv) (0 + ((XPV*) SvANY(sv))->xpv_cur)
 #define SvLEN(sv) (0 + ((XPV*) SvANY(sv))->xpv_len)
-#define SvEND(sv) (((XPV*)  SvANY(sv))->xpv_pv + ((XPV*)SvANY(sv))->xpv_cur)
+#define SvEND(sv) ((sv)->sv_u.sv_pv + ((XPV*)SvANY(sv))->xpv_cur)
 
 #ifdef DEBUGGING
 #  ifdef PERL_IN_SV_C
@@ -797,10 +825,10 @@ in gv.h: */
 #define SvIVX(sv) ((XPVIV*) SvANY(sv))->xiv_iv
 #define SvUVX(sv) ((XPVUV*) SvANY(sv))->xuv_uv
 #define SvNVX(sv) ((XPVNV*) SvANY(sv))->xnv_nv
-#define SvPVX(sv) ((XPV*) SvANY(sv))->xpv_pv
+#define SvPVX(sv) ((sv)->sv_u.sv_pv)
 #define SvCUR(sv) ((XPV*) SvANY(sv))->xpv_cur
 #define SvLEN(sv) ((XPV*) SvANY(sv))->xpv_len
-#define SvEND(sv) (((XPV*) SvANY(sv))->xpv_pv + ((XPV*)SvANY(sv))->xpv_cur)
+#define SvEND(sv) ((sv)->sv_u.sv_pv + ((XPV*)SvANY(sv))->xpv_cur)
 
 #ifdef DEBUGGING
 #define SvMAGIC(sv)    (*(assert(SvTYPE(sv) >= SVt_PVMG), &((XPVMG*)  SvANY(sv))->xmg_magic))
@@ -834,13 +862,13 @@ in gv.h: */
                (((XPVNV*)SvANY(sv))->xnv_nv = (val)); } STMT_END
 #define SvPV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
-               (((XPV*)  SvANY(sv))->xpv_pv = (val)); } STMT_END
+               ((sv)->sv_u.sv_pv = (val)); } STMT_END
 #define SvUV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
                (((XPVUV*)SvANY(sv))->xuv_uv = (val)); } STMT_END
 #define SvRV_set(sv, val) \
         STMT_START { assert(SvTYPE(sv) >=  SVt_RV); \
-                (((XRV*)SvANY(sv))->xrv_rv = (val)); } STMT_END
+                ((sv)->sv_u.sv_rv = (val)); } STMT_END
 #define SvMAGIC_set(sv, val) \
         STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
                 (((XPVMG*)SvANY(sv))->xmg_magic = (val)); } STMT_END
@@ -1164,7 +1192,7 @@ Like C<sv_catsv> but doesn't process magic.
        ?   (({XPV *nxpv = (XPV*)SvANY(sv);                     \
             nxpv &&                                            \
             (nxpv->xpv_cur > 1 ||                              \
-             (nxpv->xpv_cur && *nxpv->xpv_pv != '0')); })      \
+             (nxpv->xpv_cur && *(sv)->sv_u.sv_pv != '0')); })  \
             ? 1                                                \
             : 0)                                               \
        :                                                       \
@@ -1190,9 +1218,9 @@ Like C<sv_catsv> but doesn't process magic.
     !sv                                                                \
     ? 0                                                                \
     :    SvPOK(sv)                                             \
-       ?   ((PL_Xpv = (XPV*)SvANY(sv)) &&                      \
+       ?   ((PL_Xpv = (XPV*)SvANY(PL_Sv = (sv))) &&            \
             (PL_Xpv->xpv_cur > 1 ||                            \
-             (PL_Xpv->xpv_cur && *PL_Xpv->xpv_pv != '0'))      \
+             (PL_Xpv->xpv_cur && *PL_Sv->sv_u.sv_pv != '0'))   \
             ? 1                                                \
             : 0)                                               \
        :                                                       \