create an "allocated" structure for PVs, PVAVs and PVHVs
Nicholas Clark [Mon, 23 May 2005 08:09:58 +0000 (08:09 +0000)]
p4raw-id: //depot/perl@24544

av.h
hv.h
intrpvar.h
sv.c
sv.h

diff --git a/av.h b/av.h
index f9721d9..cc5dd5e 100644 (file)
--- a/av.h
+++ b/av.h
@@ -26,6 +26,8 @@ struct xpvav {
     HV*                xmg_stash;      /* class package */
 };
 
+typedef struct xpvav xpvav_allocated;
+
 /* SV**        xav_alloc; */
 #define xav_alloc xnv_u.xnv_s.xnv_p1
 /* SV* xav_arylen; */
diff --git a/hv.h b/hv.h
index e0dd646..90d9115 100644 (file)
--- a/hv.h
+++ b/hv.h
@@ -63,6 +63,7 @@ struct xpvhv {
 #define xhv_aux xnv_u.xnv_s.xnv_p1
 #define xhv_keys xnv_u.xnv_s.xnv_u2.xnv_i2
 
+typedef struct xpvhv xpvhv_allocated;
 
 /* hash a key */
 /* FYI: This is the "One-at-a-Time" algorithm by Bob Jenkins
index c879e9e..7e243dd 100644 (file)
@@ -253,12 +253,12 @@ PERLVAR(Ixiv_arenaroot,   XPV*)           /* list of allocated xiv areas */
 PERLVAR(Ixiv_root,     IV *)           /* free xiv list */
 PERLVAR(Ixnv_root,     NV *)           /* free xnv list */
 PERLVAR(Ixrv_root,     XRV *)          /* free xrv list */
-PERLVAR(Ixpv_root,     XPV *)          /* free xpv list */
+PERLVAR(Ixpv_root,     xpv_allocated *)        /* free xpv list */
 PERLVAR(Ixpviv_root,   XPVIV *)        /* free xpviv list */
 PERLVAR(Ixpvnv_root,   XPVNV *)        /* free xpvnv list */
 PERLVAR(Ixpvcv_root,   XPVCV *)        /* free xpvcv list */
-PERLVAR(Ixpvav_root,   XPVAV *)        /* free xpvav list */
-PERLVAR(Ixpvhv_root,   XPVHV *)        /* free xpvhv list */
+PERLVAR(Ixpvav_root,   xpvav_allocated *)      /* free xpvav list */
+PERLVAR(Ixpvhv_root,   xpvhv_allocated *)      /* free xpvhv list */
 PERLVAR(Ixpvmg_root,   XPVMG *)        /* free xpvmg list */
 PERLVAR(Ixpvgv_root,   XPVGV *)        /* free xpvgv list */
 PERLVAR(Ixpvlv_root,   XPVLV *)        /* free xpvlv list */
@@ -433,12 +433,12 @@ PERLVARI(Ibeginav_save, AV*, Nullav)      /* save BEGIN{}s when compiling */
 
 PERLVAR(Ixnv_arenaroot,        XPV*)           /* list of allocated xnv areas */
 PERLVAR(Ixrv_arenaroot,        XPV*)           /* list of allocated xrv areas */
-PERLVAR(Ixpv_arenaroot,        XPV*)           /* list of allocated xpv areas */
+PERLVAR(Ixpv_arenaroot,        xpv_allocated *)        /* list of allocated xpv areas */
 PERLVAR(Ixpviv_arenaroot,XPVIV*)       /* list of allocated xpviv areas */
 PERLVAR(Ixpvnv_arenaroot,XPVNV*)       /* list of allocated xpvnv areas */
 PERLVAR(Ixpvcv_arenaroot,XPVCV*)       /* list of allocated xpvcv areas */
-PERLVAR(Ixpvav_arenaroot,XPVAV*)       /* list of allocated xpvav areas */
-PERLVAR(Ixpvhv_arenaroot,XPVHV*)       /* list of allocated xpvhv areas */
+PERLVAR(Ixpvav_arenaroot,xpvav_allocated*)     /* list of allocated xpvav areas */
+PERLVAR(Ixpvhv_arenaroot,xpvhv_allocated*)     /* list of allocated xpvhv areas */
 PERLVAR(Ixpvmg_arenaroot,XPVMG*)       /* list of allocated xpvmg areas */
 PERLVAR(Ixpvgv_arenaroot,XPVGV*)       /* list of allocated xpvgv areas */
 PERLVAR(Ixpvlv_arenaroot,XPVLV*)       /* list of allocated xpvlv areas */
diff --git a/sv.c b/sv.c
index 9658505..a2c4835 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1153,19 +1153,19 @@ S_more_xnv(pTHX)
 STATIC void
 S_more_xpv(pTHX)
 {
-    XPV* xpv;
-    XPV* xpvend;
-    New(713, xpv, PERL_ARENA_SIZE/sizeof(XPV), XPV);
-    *((XPV**)xpv) = PL_xpv_arenaroot;
+    xpv_allocated* xpv;
+    xpv_allocated* xpvend;
+    New(713, xpv, PERL_ARENA_SIZE/sizeof(xpv_allocated), xpv_allocated);
+    *((xpv_allocated**)xpv) = PL_xpv_arenaroot;
     PL_xpv_arenaroot = xpv;
 
-    xpvend = &xpv[PERL_ARENA_SIZE / sizeof(XPV) - 1];
+    xpvend = &xpv[PERL_ARENA_SIZE / sizeof(xpv_allocated) - 1];
     PL_xpv_root = ++xpv;
     while (xpv < xpvend) {
-       *((XPV**)xpv) = xpv + 1;
+       *((xpv_allocated**)xpv) = xpv + 1;
        xpv++;
     }
-    *((XPV**)xpv) = 0;
+    *((xpv_allocated**)xpv) = 0;
 }
 
 /* allocate another arena's worth of struct xpviv */
@@ -1233,19 +1233,20 @@ S_more_xpvcv(pTHX)
 STATIC void
 S_more_xpvav(pTHX)
 {
-    XPVAV* xpvav;
-    XPVAV* xpvavend;
-    New(717, xpvav, PERL_ARENA_SIZE/sizeof(XPVAV), XPVAV);
-    *((XPVAV**)xpvav) = PL_xpvav_arenaroot;
+    xpvav_allocated* xpvav;
+     xpvav_allocated* xpvavend;
+    New(717, xpvav, PERL_ARENA_SIZE/sizeof(xpvav_allocated),
+       xpvav_allocated);
+    *((xpvav_allocated**)xpvav) = PL_xpvav_arenaroot;
     PL_xpvav_arenaroot = xpvav;
 
-    xpvavend = &xpvav[PERL_ARENA_SIZE / sizeof(XPVAV) - 1];
+    xpvavend = &xpvav[PERL_ARENA_SIZE / sizeof(xpvav_allocated) - 1];
     PL_xpvav_root = ++xpvav;
     while (xpvav < xpvavend) {
-       *((XPVAV**)xpvav) = xpvav + 1;
+       *((xpvav_allocated**)xpvav) = xpvav + 1;
        xpvav++;
     }
-    *((XPVAV**)xpvav) = 0;
+    *((xpvav_allocated**)xpvav) = 0;
 }
 
 /* allocate another arena's worth of struct xpvhv */
@@ -1253,19 +1254,20 @@ S_more_xpvav(pTHX)
 STATIC void
 S_more_xpvhv(pTHX)
 {
-    XPVHV* xpvhv;
-    XPVHV* xpvhvend;
-    New(718, xpvhv, PERL_ARENA_SIZE/sizeof(XPVHV), XPVHV);
-    *((XPVHV**)xpvhv) = PL_xpvhv_arenaroot;
+    xpvhv_allocated* xpvhv;
+    xpvhv_allocated* xpvhvend;
+    New(718, xpvhv, PERL_ARENA_SIZE/sizeof(xpvhv_allocated),
+       xpvhv_allocated);
+    *((xpvhv_allocated**)xpvhv) = PL_xpvhv_arenaroot;
     PL_xpvhv_arenaroot = xpvhv;
 
-    xpvhvend = &xpvhv[PERL_ARENA_SIZE / sizeof(XPVHV) - 1];
+    xpvhvend = &xpvhv[PERL_ARENA_SIZE / sizeof(xpvhv_allocated) - 1];
     PL_xpvhv_root = ++xpvhv;
     while (xpvhv < xpvhvend) {
-       *((XPVHV**)xpvhv) = xpvhv + 1;
+       *((xpvhv_allocated**)xpvhv) = xpvhv + 1;
        xpvhv++;
     }
-    *((XPVHV**)xpvhv) = 0;
+    *((xpvhv_allocated**)xpvhv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvmg */
@@ -1380,14 +1382,20 @@ S_del_xnv(pTHX_ XPVNV *p)
 STATIC XPV*
 S_new_xpv(pTHX)
 {
-    XPV* xpv;
+    xpv_allocated* xpv;
     LOCK_SV_MUTEX;
     if (!PL_xpv_root)
        S_more_xpv(aTHX);
     xpv = PL_xpv_root;
-    PL_xpv_root = *(XPV**)xpv;
+    PL_xpv_root = *(xpv_allocated**)xpv;
     UNLOCK_SV_MUTEX;
-    return xpv;
+    /* If xpv_allocated is the same structure as XPV then the two OFFSETs
+       sum to zero, and the pointer is unchanged. If the allocated structure
+       is smaller (no initial IV actually allocated) then the net effect is
+       to subtract the size of the IV from the pointer, to return a new pointer
+       as if an initial IV were actually allocated.  */
+    return (XPV*)((char*)xpv - STRUCT_OFFSET(XPV, xpv_cur)
+                 + STRUCT_OFFSET(xpv_allocated, xpv_cur));
 }
 
 /* return a struct xpv to the free list */
@@ -1395,9 +1403,12 @@ S_new_xpv(pTHX)
 STATIC void
 S_del_xpv(pTHX_ XPV *p)
 {
+    xpv_allocated* xpv
+       = (xpv_allocated*)((char*)(p) + STRUCT_OFFSET(XPV, xpv_cur)
+                          - STRUCT_OFFSET(xpv_allocated, xpv_cur));
     LOCK_SV_MUTEX;
-    *(XPV**)p = PL_xpv_root;
-    PL_xpv_root = p;
+    *(xpv_allocated**)xpv = PL_xpv_root;
+    PL_xpv_root = xpv;
     UNLOCK_SV_MUTEX;
 }
 
@@ -1484,14 +1495,15 @@ S_del_xpvcv(pTHX_ XPVCV *p)
 STATIC XPVAV*
 S_new_xpvav(pTHX)
 {
-    XPVAV* xpvav;
+    xpvav_allocated* xpvav;
     LOCK_SV_MUTEX;
     if (!PL_xpvav_root)
        S_more_xpvav(aTHX);
     xpvav = PL_xpvav_root;
-    PL_xpvav_root = *(XPVAV**)xpvav;
+    PL_xpvav_root = *(xpvav_allocated**)xpvav;
     UNLOCK_SV_MUTEX;
-    return xpvav;
+    return (XPVAV*)((char*)xpvav - STRUCT_OFFSET(XPVAV, xav_fill)
+                   + STRUCT_OFFSET(xpvav_allocated, xav_fill));
 }
 
 /* return a struct xpvav to the free list */
@@ -1499,9 +1511,12 @@ S_new_xpvav(pTHX)
 STATIC void
 S_del_xpvav(pTHX_ XPVAV *p)
 {
+    xpvav_allocated* xpvav
+       = (xpvav_allocated*)((char*)(p) + STRUCT_OFFSET(XPVAV, xav_fill)
+                            - STRUCT_OFFSET(xpvav_allocated, xav_fill));
     LOCK_SV_MUTEX;
-    *(XPVAV**)p = PL_xpvav_root;
-    PL_xpvav_root = p;
+    *(xpvav_allocated**)xpvav = PL_xpvav_root;
+    PL_xpvav_root = xpvav;
     UNLOCK_SV_MUTEX;
 }
 
@@ -1510,14 +1525,15 @@ S_del_xpvav(pTHX_ XPVAV *p)
 STATIC XPVHV*
 S_new_xpvhv(pTHX)
 {
-    XPVHV* xpvhv;
+    xpvhv_allocated* xpvhv;
     LOCK_SV_MUTEX;
     if (!PL_xpvhv_root)
        S_more_xpvhv(aTHX);
     xpvhv = PL_xpvhv_root;
-    PL_xpvhv_root = *(XPVHV**)xpvhv;
+    PL_xpvhv_root = *(xpvhv_allocated**)xpvhv;
     UNLOCK_SV_MUTEX;
-    return xpvhv;
+    return (XPVHV*)((char*)xpvhv - STRUCT_OFFSET(XPVHV, xhv_fill)
+                   + STRUCT_OFFSET(xpvhv_allocated, xhv_fill));
 }
 
 /* return a struct xpvhv to the free list */
@@ -1525,9 +1541,12 @@ S_new_xpvhv(pTHX)
 STATIC void
 S_del_xpvhv(pTHX_ XPVHV *p)
 {
+    xpvhv_allocated* xpvhv
+       = (xpvhv_allocated*)((char*)(p) + STRUCT_OFFSET(XPVHV, xhv_fill)
+                            - STRUCT_OFFSET(xpvhv_allocated, xhv_fill));
     LOCK_SV_MUTEX;
-    *(XPVHV**)p = PL_xpvhv_root;
-    PL_xpvhv_root = p;
+    *(xpvhv_allocated**)xpvhv = PL_xpvhv_root;
+    PL_xpvhv_root = xpvhv;
     UNLOCK_SV_MUTEX;
 }
 
diff --git a/sv.h b/sv.h
index 518621d..bfc4778 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -280,6 +280,8 @@ struct xpv {
     STRLEN     xpv_len;        /* allocated size */
 };
 
+typedef struct xpv xpv_allocated;
+
 struct xpviv {
     IV         xiv_iv;         /* integer value or pv offset */
     STRLEN     xpv_cur;        /* length of sv_pv as a C string */