Reorder the *more* arena allocation functions into a block
Nicholas Clark [Fri, 13 May 2005 11:59:26 +0000 (11:59 +0000)]
As they are now ahead of their corresponding *new* functions, no need
for all the embedding guff.
Remove all the "register" keywords.

p4raw-id: //depot/perl@24460

embed.fnc
embed.h
hv.c
proto.h
sv.c

index 1260bad..c4ffe37 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -993,7 +993,6 @@ s   |void   |require_errno  |GV *gv
 #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT)
 s      |void   |hsplit         |HV *hv
 s      |void   |hfreeentries   |HV *hv
-s      |void   |more_he
 s      |HE*    |new_he
 s      |void   |del_he         |HE *p
 s      |HEK*   |save_hek_flags |const char *str|I32 len|U32 hash|int flags
@@ -1181,20 +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      |SV*    |more_sv
-s      |void   |more_xiv
-s      |void   |more_xnv
-s      |void   |more_xpv
-s      |void   |more_xpviv
-s      |void   |more_xpvnv
-s      |void   |more_xpvcv
-s      |void   |more_xpvav
-s      |void   |more_xpvhv
-s      |void   |more_xpvmg
-s      |void   |more_xpvgv
-s      |void   |more_xpvlv
-s      |void   |more_xpvbm
-s      |void   |more_xrv
 s      |XPVIV* |new_xiv
 s      |XPVNV* |new_xnv
 s      |XPV*   |new_xpv
diff --git a/embed.h b/embed.h
index b7ae6da..e72cd8a 100644 (file)
--- a/embed.h
+++ b/embed.h
 #ifdef PERL_CORE
 #define hsplit                 S_hsplit
 #define hfreeentries           S_hfreeentries
-#define more_he                        S_more_he
 #define new_he                 S_new_he
 #define del_he                 S_del_he
 #define save_hek_flags         S_save_hek_flags
 #ifdef PERL_CORE
 #define asIV                   S_asIV
 #define asUV                   S_asUV
-#define more_sv                        S_more_sv
-#define more_xiv               S_more_xiv
-#define more_xnv               S_more_xnv
-#define more_xpv               S_more_xpv
-#define more_xpviv             S_more_xpviv
-#define more_xpvnv             S_more_xpvnv
-#define more_xpvcv             S_more_xpvcv
-#define more_xpvav             S_more_xpvav
-#define more_xpvhv             S_more_xpvhv
-#define more_xpvmg             S_more_xpvmg
-#define more_xpvgv             S_more_xpvgv
-#define more_xpvlv             S_more_xpvlv
-#define more_xpvbm             S_more_xpvbm
-#define more_xrv               S_more_xrv
 #define new_xiv                        S_new_xiv
 #define new_xnv                        S_new_xnv
 #define new_xpv                        S_new_xpv
 #ifdef PERL_CORE
 #define hsplit(a)              S_hsplit(aTHX_ a)
 #define hfreeentries(a)                S_hfreeentries(aTHX_ a)
-#define more_he()              S_more_he(aTHX)
 #define new_he()               S_new_he(aTHX)
 #define del_he(a)              S_del_he(aTHX_ a)
 #define save_hek_flags(a,b,c,d)        S_save_hek_flags(aTHX_ a,b,c,d)
 #ifdef PERL_CORE
 #define asIV(a)                        S_asIV(aTHX_ a)
 #define asUV(a)                        S_asUV(aTHX_ a)
-#define more_sv()              S_more_sv(aTHX)
-#define more_xiv()             S_more_xiv(aTHX)
-#define more_xnv()             S_more_xnv(aTHX)
-#define more_xpv()             S_more_xpv(aTHX)
-#define more_xpviv()           S_more_xpviv(aTHX)
-#define more_xpvnv()           S_more_xpvnv(aTHX)
-#define more_xpvcv()           S_more_xpvcv(aTHX)
-#define more_xpvav()           S_more_xpvav(aTHX)
-#define more_xpvhv()           S_more_xpvhv(aTHX)
-#define more_xpvmg()           S_more_xpvmg(aTHX)
-#define more_xpvgv()           S_more_xpvgv(aTHX)
-#define more_xpvlv()           S_more_xpvlv(aTHX)
-#define more_xpvbm()           S_more_xpvbm(aTHX)
-#define more_xrv()             S_more_xrv(aTHX)
 #define new_xiv()              S_new_xiv(aTHX)
 #define new_xnv()              S_new_xnv(aTHX)
 #define new_xpv()              S_new_xpv(aTHX)
diff --git a/hv.c b/hv.c
index f7c3761..fa34b70 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -33,13 +33,31 @@ holds the key and hash value.
 
 #define HV_MAX_LENGTH_BEFORE_SPLIT 14
 
+STATIC void
+S_more_he(pTHX)
+{
+    HE* he;
+    HE* heend;
+    New(54, he, PERL_ARENA_SIZE/sizeof(HE), HE);
+    HeNEXT(he) = PL_he_arenaroot;
+    PL_he_arenaroot = he;
+
+    heend = &he[PERL_ARENA_SIZE / sizeof(HE) - 1];
+    PL_he_root = ++he;
+    while (he < heend) {
+       HeNEXT(he) = (HE*)(he + 1);
+       he++;
+    }
+    HeNEXT(he) = 0;
+}
+
 STATIC HE*
 S_new_he(pTHX)
 {
     HE* he;
     LOCK_SV_MUTEX;
     if (!PL_he_root)
-       more_he();
+       S_more_he(aTHX);
     he = PL_he_root;
     PL_he_root = HeNEXT(he);
     UNLOCK_SV_MUTEX;
@@ -55,24 +73,6 @@ S_del_he(pTHX_ HE *p)
     UNLOCK_SV_MUTEX;
 }
 
-STATIC void
-S_more_he(pTHX)
-{
-    register HE* he;
-    register HE* heend;
-    New(54, he, PERL_ARENA_SIZE/sizeof(HE), HE);
-    HeNEXT(he) = PL_he_arenaroot;
-    PL_he_arenaroot = he;
-
-    heend = &he[PERL_ARENA_SIZE / sizeof(HE) - 1];
-    PL_he_root = ++he;
-    while (he < heend) {
-       HeNEXT(he) = (HE*)(he + 1);
-       he++;
-    }
-    HeNEXT(he) = 0;
-}
-
 #ifdef PURIFY
 
 #define new_HE() (HE*)safemalloc(sizeof(HE))
diff --git a/proto.h b/proto.h
index 7b0764c..ffcb8d9 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1635,7 +1635,6 @@ STATIC void       S_require_errno(pTHX_ GV *gv);
 #if defined(PERL_IN_HV_C) || defined(PERL_DECL_PROT)
 STATIC void    S_hsplit(pTHX_ HV *hv);
 STATIC void    S_hfreeentries(pTHX_ HV *hv);
-STATIC void    S_more_he(pTHX);
 STATIC HE*     S_new_he(pTHX);
 STATIC void    S_del_he(pTHX_ HE *p);
 STATIC HEK*    S_save_hek_flags(pTHX_ const char *str, I32 len, U32 hash, int flags);
@@ -1841,20 +1840,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 SV*     S_more_sv(pTHX);
-STATIC void    S_more_xiv(pTHX);
-STATIC void    S_more_xnv(pTHX);
-STATIC void    S_more_xpv(pTHX);
-STATIC void    S_more_xpviv(pTHX);
-STATIC void    S_more_xpvnv(pTHX);
-STATIC void    S_more_xpvcv(pTHX);
-STATIC void    S_more_xpvav(pTHX);
-STATIC void    S_more_xpvhv(pTHX);
-STATIC void    S_more_xpvmg(pTHX);
-STATIC void    S_more_xpvgv(pTHX);
-STATIC void    S_more_xpvlv(pTHX);
-STATIC void    S_more_xpvbm(pTHX);
-STATIC void    S_more_xrv(pTHX);
 STATIC XPVIV*  S_new_xiv(pTHX);
 STATIC XPVNV*  S_new_xnv(pTHX);
 STATIC XPV*    S_new_xpv(pTHX);
diff --git a/sv.c b/sv.c
index e80f7ca..2536594 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -165,6 +165,7 @@ Public API:
  * "A time to plant, and a time to uproot what was planted..."
  */
 
+
 #ifdef DEBUG_LEAKING_SCALARS
 #  ifdef NETWARE
 #    define FREE_SV_DEBUG_FILE(sv) PerlMemfree((sv)->sv_debug_file)
@@ -193,6 +194,28 @@ Public API:
     } STMT_END
 
 
+/* make some more SVs by adding another arena */
+
+/* sv_mutex must be held while calling more_sv() */
+STATIC SV*
+S_more_sv(pTHX)
+{
+    SV* sv;
+
+    if (PL_nice_chunk) {
+       sv_add_arena(PL_nice_chunk, PL_nice_chunk_size, 0);
+       PL_nice_chunk = Nullch;
+        PL_nice_chunk_size = 0;
+    }
+    else {
+       char *chunk;                /* must use New here to match call to */
+       New(704,chunk,1008,char);   /* Safefree() in sv_free_arenas()     */
+       sv_add_arena(chunk, 1008, 0);
+    }
+    uproot_SV(sv);
+    return sv;
+}
+
 /* new_SV(): return a new, empty SV head */
 
 #ifdef DEBUG_LEAKING_SCALARS
@@ -206,7 +229,7 @@ S_new_SV(pTHX)
     if (PL_sv_root)
        uproot_SV(sv);
     else
-       sv = more_sv();
+       sv = S_more_sv(aTHX);
     UNLOCK_SV_MUTEX;
     SvANY(sv) = 0;
     SvREFCNT(sv) = 1;
@@ -233,7 +256,7 @@ S_new_SV(pTHX)
        if (PL_sv_root)                                 \
            uproot_SV(p);                               \
        else                                            \
-           (p) = more_sv();                            \
+           (p) = S_more_sv(aTHX);                      \
        UNLOCK_SV_MUTEX;                                \
        SvANY(p) = 0;                                   \
        SvREFCNT(p) = 1;                                \
@@ -335,28 +358,6 @@ Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
     SvFLAGS(sv) = SVTYPEMASK;
 }
 
-/* make some more SVs by adding another arena */
-
-/* sv_mutex must be held while calling more_sv() */
-STATIC SV*
-S_more_sv(pTHX)
-{
-    register SV* sv;
-
-    if (PL_nice_chunk) {
-       sv_add_arena(PL_nice_chunk, PL_nice_chunk_size, 0);
-       PL_nice_chunk = Nullch;
-        PL_nice_chunk_size = 0;
-    }
-    else {
-       char *chunk;                /* must use New here to match call to */
-       New(704,chunk,1008,char);   /* Safefree() in sv_free_arenas()     */
-       sv_add_arena(chunk, 1008, 0);
-    }
-    uproot_SV(sv);
-    return sv;
-}
-
 /* visit(): call the named function for each non-free SV in the arenas
  * whose flags field matches the flags/mask args. */
 
@@ -1142,34 +1143,28 @@ Perl_report_uninit(pTHX_ SV* uninit_sv)
                    "", "", "");
 }
 
-/* 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)
-       more_xiv();
-    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 */
+/* allocate another arena's worth of struct xrv */
 
 STATIC void
-S_del_xiv(pTHX_ XPVIV *p)
+S_more_xrv(pTHX)
 {
-    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;
+    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 */
@@ -1177,8 +1172,8 @@ S_del_xiv(pTHX_ XPVIV *p)
 STATIC void
 S_more_xiv(pTHX)
 {
-    register IV* xiv;
-    register IV* xivend;
+    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 */
@@ -1195,40 +1190,13 @@ S_more_xiv(pTHX)
     *(IV**)xiv = 0;
 }
 
-/* grab a new NV body from the free list, allocating more if necessary */
-
-STATIC XPVNV*
-S_new_xnv(pTHX)
-{
-    NV* xnv;
-    LOCK_SV_MUTEX;
-    if (!PL_xnv_root)
-       more_xnv();
-    xnv = PL_xnv_root;
-    PL_xnv_root = *(NV**)xnv;
-    UNLOCK_SV_MUTEX;
-    return (XPVNV*)((char*)xnv - STRUCT_OFFSET(XPVNV, xnv_nv));
-}
-
-/* return an NV body to the free list */
-
-STATIC void
-S_del_xnv(pTHX_ XPVNV *p)
-{
-    NV* xnv = (NV*)((char*)(p) + STRUCT_OFFSET(XPVNV, xnv_nv));
-    LOCK_SV_MUTEX;
-    *(NV**)xnv = PL_xnv_root;
-    PL_xnv_root = xnv;
-    UNLOCK_SV_MUTEX;
-}
-
 /* allocate another arena's worth of NV bodies */
 
 STATIC void
 S_more_xnv(pTHX)
 {
-    register NV* xnv;
-    register NV* xnvend;
+    NV* xnv;
+    NV* xnvend;
     XPV *ptr;
     New(711, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
     ptr->xpv_pv = (char*)PL_xnv_arenaroot;
@@ -1242,7 +1210,207 @@ S_more_xnv(pTHX)
        *(NV**)xnv = (NV*)(xnv + 1);
        xnv++;
     }
-    *(NV**)xnv = 0;
+    *(NV**)xnv = 0;
+}
+
+/* allocate another arena's worth of struct xpv */
+
+STATIC void
+S_more_xpv(pTHX)
+{
+    XPV* xpv;
+    XPV* xpvend;
+    New(713, xpv, PERL_ARENA_SIZE/sizeof(XPV), XPV);
+    xpv->xpv_pv = (char*)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_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpviv */
+
+STATIC void
+S_more_xpviv(pTHX)
+{
+    XPVIV* xpviv;
+    XPVIV* xpvivend;
+    New(714, xpviv, PERL_ARENA_SIZE/sizeof(XPVIV), XPVIV);
+    xpviv->xpv_pv = (char*)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->xpv_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpvnv */
+
+STATIC void
+S_more_xpvnv(pTHX)
+{
+    XPVNV* xpvnv;
+    XPVNV* xpvnvend;
+    New(715, xpvnv, PERL_ARENA_SIZE/sizeof(XPVNV), XPVNV);
+    xpvnv->xpv_pv = (char*)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->xpv_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpvcv */
+
+STATIC void
+S_more_xpvcv(pTHX)
+{
+    XPVCV* xpvcv;
+    XPVCV* xpvcvend;
+    New(716, xpvcv, PERL_ARENA_SIZE/sizeof(XPVCV), XPVCV);
+    xpvcv->xpv_pv = (char*)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->xpv_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpvav */
+
+STATIC void
+S_more_xpvav(pTHX)
+{
+    XPVAV* xpvav;
+    XPVAV* xpvavend;
+    New(717, xpvav, PERL_ARENA_SIZE/sizeof(XPVAV), XPVAV);
+    xpvav->xav_array = (char*)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->xav_array = 0;
+}
+
+/* allocate another arena's worth of struct xpvhv */
+
+STATIC void
+S_more_xpvhv(pTHX)
+{
+    XPVHV* xpvhv;
+    XPVHV* xpvhvend;
+    New(718, xpvhv, PERL_ARENA_SIZE/sizeof(XPVHV), XPVHV);
+    xpvhv->xhv_array = (char*)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->xhv_array = 0;
+}
+
+/* allocate another arena's worth of struct xpvmg */
+
+STATIC void
+S_more_xpvmg(pTHX)
+{
+    XPVMG* xpvmg;
+    XPVMG* xpvmgend;
+    New(719, xpvmg, PERL_ARENA_SIZE/sizeof(XPVMG), XPVMG);
+    xpvmg->xpv_pv = (char*)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->xpv_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpvgv */
+
+STATIC void
+S_more_xpvgv(pTHX)
+{
+    XPVGV* xpvgv;
+    XPVGV* xpvgvend;
+    New(720, xpvgv, PERL_ARENA_SIZE/sizeof(XPVGV), XPVGV);
+    xpvgv->xpv_pv = (char*)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->xpv_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpvlv */
+
+STATIC void
+S_more_xpvlv(pTHX)
+{
+    XPVLV* xpvlv;
+    XPVLV* xpvlvend;
+    New(720, xpvlv, PERL_ARENA_SIZE/sizeof(XPVLV), XPVLV);
+    xpvlv->xpv_pv = (char*)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->xpv_pv = 0;
+}
+
+/* allocate another arena's worth of struct xpvbm */
+
+STATIC void
+S_more_xpvbm(pTHX)
+{
+    XPVBM* xpvbm;
+    XPVBM* xpvbmend;
+    New(721, xpvbm, PERL_ARENA_SIZE/sizeof(XPVBM), XPVBM);
+    xpvbm->xpv_pv = (char*)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->xpv_pv = 0;
 }
 
 /* grab a new struct xrv from the free list, allocating more if necessary */
@@ -1253,7 +1421,7 @@ S_new_xrv(pTHX)
     XRV* xrv;
     LOCK_SV_MUTEX;
     if (!PL_xrv_root)
-       more_xrv();
+       S_more_xrv(aTHX);
     xrv = PL_xrv_root;
     PL_xrv_root = (XRV*)xrv->xrv_rv;
     UNLOCK_SV_MUTEX;
@@ -1271,27 +1439,61 @@ S_del_xrv(pTHX_ XRV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xrv */
+/* 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_more_xrv(pTHX)
+S_del_xiv(pTHX_ XPVIV *p)
 {
-    register XRV* xrv;
-    register XRV* xrvend;
-    XPV *ptr;
-    New(712, ptr, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    ptr->xpv_pv = (char*)PL_xrv_arenaroot;
-    PL_xrv_arenaroot = ptr;
+    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;
+}
 
-    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;
+/* grab a new NV body from the free list, allocating more if necessary */
+
+STATIC XPVNV*
+S_new_xnv(pTHX)
+{
+    NV* xnv;
+    LOCK_SV_MUTEX;
+    if (!PL_xnv_root)
+       S_more_xnv(aTHX);
+    xnv = PL_xnv_root;
+    PL_xnv_root = *(NV**)xnv;
+    UNLOCK_SV_MUTEX;
+    return (XPVNV*)((char*)xnv - STRUCT_OFFSET(XPVNV, xnv_nv));
+}
+
+/* return an NV body to the free list */
+
+STATIC void
+S_del_xnv(pTHX_ XPVNV *p)
+{
+    NV* xnv = (NV*)((char*)(p) + STRUCT_OFFSET(XPVNV, xnv_nv));
+    LOCK_SV_MUTEX;
+    *(NV**)xnv = PL_xnv_root;
+    PL_xnv_root = xnv;
+    UNLOCK_SV_MUTEX;
 }
 
 /* grab a new struct xpv from the free list, allocating more if necessary */
@@ -1302,7 +1504,7 @@ S_new_xpv(pTHX)
     XPV* xpv;
     LOCK_SV_MUTEX;
     if (!PL_xpv_root)
-       more_xpv();
+       S_more_xpv(aTHX);
     xpv = PL_xpv_root;
     PL_xpv_root = (XPV*)xpv->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1320,26 +1522,6 @@ S_del_xpv(pTHX_ XPV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpv */
-
-STATIC void
-S_more_xpv(pTHX)
-{
-    register XPV* xpv;
-    register XPV* xpvend;
-    New(713, xpv, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    xpv->xpv_pv = (char*)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_pv = 0;
-}
-
 /* grab a new struct xpviv from the free list, allocating more if necessary */
 
 STATIC XPVIV*
@@ -1348,7 +1530,7 @@ S_new_xpviv(pTHX)
     XPVIV* xpviv;
     LOCK_SV_MUTEX;
     if (!PL_xpviv_root)
-       more_xpviv();
+       S_more_xpviv(aTHX);
     xpviv = PL_xpviv_root;
     PL_xpviv_root = (XPVIV*)xpviv->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1366,26 +1548,6 @@ S_del_xpviv(pTHX_ XPVIV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpviv */
-
-STATIC void
-S_more_xpviv(pTHX)
-{
-    register XPVIV* xpviv;
-    register XPVIV* xpvivend;
-    New(714, xpviv, PERL_ARENA_SIZE/sizeof(XPVIV), XPVIV);
-    xpviv->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
 /* grab a new struct xpvnv from the free list, allocating more if necessary */
 
 STATIC XPVNV*
@@ -1394,7 +1556,7 @@ S_new_xpvnv(pTHX)
     XPVNV* xpvnv;
     LOCK_SV_MUTEX;
     if (!PL_xpvnv_root)
-       more_xpvnv();
+       S_more_xpvnv(aTHX);
     xpvnv = PL_xpvnv_root;
     PL_xpvnv_root = (XPVNV*)xpvnv->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1412,26 +1574,6 @@ S_del_xpvnv(pTHX_ XPVNV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvnv */
-
-STATIC void
-S_more_xpvnv(pTHX)
-{
-    register XPVNV* xpvnv;
-    register XPVNV* xpvnvend;
-    New(715, xpvnv, PERL_ARENA_SIZE/sizeof(XPVNV), XPVNV);
-    xpvnv->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
 /* grab a new struct xpvcv from the free list, allocating more if necessary */
 
 STATIC XPVCV*
@@ -1440,7 +1582,7 @@ S_new_xpvcv(pTHX)
     XPVCV* xpvcv;
     LOCK_SV_MUTEX;
     if (!PL_xpvcv_root)
-       more_xpvcv();
+       S_more_xpvcv(aTHX);
     xpvcv = PL_xpvcv_root;
     PL_xpvcv_root = (XPVCV*)xpvcv->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1458,26 +1600,6 @@ S_del_xpvcv(pTHX_ XPVCV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvcv */
-
-STATIC void
-S_more_xpvcv(pTHX)
-{
-    register XPVCV* xpvcv;
-    register XPVCV* xpvcvend;
-    New(716, xpvcv, PERL_ARENA_SIZE/sizeof(XPVCV), XPVCV);
-    xpvcv->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
 /* grab a new struct xpvav from the free list, allocating more if necessary */
 
 STATIC XPVAV*
@@ -1486,7 +1608,7 @@ S_new_xpvav(pTHX)
     XPVAV* xpvav;
     LOCK_SV_MUTEX;
     if (!PL_xpvav_root)
-       more_xpvav();
+       S_more_xpvav(aTHX);
     xpvav = PL_xpvav_root;
     PL_xpvav_root = (XPVAV*)xpvav->xav_array;
     UNLOCK_SV_MUTEX;
@@ -1504,26 +1626,6 @@ S_del_xpvav(pTHX_ XPVAV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvav */
-
-STATIC void
-S_more_xpvav(pTHX)
-{
-    register XPVAV* xpvav;
-    register XPVAV* xpvavend;
-    New(717, xpvav, PERL_ARENA_SIZE/sizeof(XPVAV), XPVAV);
-    xpvav->xav_array = (char*)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->xav_array = 0;
-}
-
 /* grab a new struct xpvhv from the free list, allocating more if necessary */
 
 STATIC XPVHV*
@@ -1532,7 +1634,7 @@ S_new_xpvhv(pTHX)
     XPVHV* xpvhv;
     LOCK_SV_MUTEX;
     if (!PL_xpvhv_root)
-       more_xpvhv();
+       S_more_xpvhv(aTHX);
     xpvhv = PL_xpvhv_root;
     PL_xpvhv_root = (XPVHV*)xpvhv->xhv_array;
     UNLOCK_SV_MUTEX;
@@ -1550,26 +1652,6 @@ S_del_xpvhv(pTHX_ XPVHV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvhv */
-
-STATIC void
-S_more_xpvhv(pTHX)
-{
-    register XPVHV* xpvhv;
-    register XPVHV* xpvhvend;
-    New(718, xpvhv, PERL_ARENA_SIZE/sizeof(XPVHV), XPVHV);
-    xpvhv->xhv_array = (char*)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->xhv_array = 0;
-}
-
 /* grab a new struct xpvmg from the free list, allocating more if necessary */
 
 STATIC XPVMG*
@@ -1578,7 +1660,7 @@ S_new_xpvmg(pTHX)
     XPVMG* xpvmg;
     LOCK_SV_MUTEX;
     if (!PL_xpvmg_root)
-       more_xpvmg();
+       S_more_xpvmg(aTHX);
     xpvmg = PL_xpvmg_root;
     PL_xpvmg_root = (XPVMG*)xpvmg->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1596,46 +1678,6 @@ S_del_xpvmg(pTHX_ XPVMG *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvmg */
-
-STATIC void
-S_more_xpvmg(pTHX)
-{
-    register XPVMG* xpvmg;
-    register XPVMG* xpvmgend;
-    New(719, xpvmg, PERL_ARENA_SIZE/sizeof(XPVMG), XPVMG);
-    xpvmg->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
-/* allocate another arena's worth of struct xpvgv */
-
-STATIC void
-S_more_xpvgv(pTHX)
-{
-    XPVGV* xpvgv;
-    XPVGV* xpvgvend;
-    New(720, xpvgv, PERL_ARENA_SIZE/sizeof(XPVGV), XPVGV);
-    xpvgv->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
 /* grab a new struct xpvgv from the free list, allocating more if necessary */
 
 STATIC XPVGV*
@@ -1644,7 +1686,7 @@ S_new_xpvgv(pTHX)
     XPVGV* xpvgv;
     LOCK_SV_MUTEX;
     if (!PL_xpvgv_root)
-       more_xpvgv();
+       S_more_xpvgv(aTHX);
     xpvgv = PL_xpvgv_root;
     PL_xpvgv_root = (XPVGV*)xpvgv->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1670,7 +1712,7 @@ S_new_xpvlv(pTHX)
     XPVLV* xpvlv;
     LOCK_SV_MUTEX;
     if (!PL_xpvlv_root)
-       more_xpvlv();
+       S_more_xpvlv(aTHX);
     xpvlv = PL_xpvlv_root;
     PL_xpvlv_root = (XPVLV*)xpvlv->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1688,26 +1730,6 @@ S_del_xpvlv(pTHX_ XPVLV *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvlv */
-
-STATIC void
-S_more_xpvlv(pTHX)
-{
-    register XPVLV* xpvlv;
-    register XPVLV* xpvlvend;
-    New(720, xpvlv, PERL_ARENA_SIZE/sizeof(XPVLV), XPVLV);
-    xpvlv->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
 /* grab a new struct xpvbm from the free list, allocating more if necessary */
 
 STATIC XPVBM*
@@ -1716,7 +1738,7 @@ S_new_xpvbm(pTHX)
     XPVBM* xpvbm;
     LOCK_SV_MUTEX;
     if (!PL_xpvbm_root)
-       more_xpvbm();
+       S_more_xpvbm(aTHX);
     xpvbm = PL_xpvbm_root;
     PL_xpvbm_root = (XPVBM*)xpvbm->xpv_pv;
     UNLOCK_SV_MUTEX;
@@ -1734,26 +1756,6 @@ S_del_xpvbm(pTHX_ XPVBM *p)
     UNLOCK_SV_MUTEX;
 }
 
-/* allocate another arena's worth of struct xpvbm */
-
-STATIC void
-S_more_xpvbm(pTHX)
-{
-    register XPVBM* xpvbm;
-    register XPVBM* xpvbmend;
-    New(721, xpvbm, PERL_ARENA_SIZE/sizeof(XPVBM), XPVBM);
-    xpvbm->xpv_pv = (char*)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->xpv_pv = 0;
-}
-
 #define my_safemalloc(s)       (void*)safemalloc(s)
 #define my_safefree(p) safefree((char*)p)
 
@@ -10498,8 +10500,8 @@ Perl_ptr_table_new(pTHX)
 STATIC void
 S_more_pte(pTHX)
 {
-    register struct ptr_tbl_ent* pte;
-    register struct ptr_tbl_ent* pteend;
+    struct ptr_tbl_ent* pte;
+    struct ptr_tbl_ent* pteend;
     New(0, pte, PERL_ARENA_SIZE/sizeof(struct ptr_tbl_ent), struct ptr_tbl_ent);
     pte->next = PL_pte_arenaroot;
     PL_pte_arenaroot = pte;