#define uiv_2buf S_uiv_2buf
#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_xpvnv S_new_xpvnv
-#define new_xpvcv S_new_xpvcv
-#define new_xpvav S_new_xpvav
-#define new_xpvhv S_new_xpvhv
-#define new_xpvmg S_new_xpvmg
-#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_xpvnv S_del_xpvnv
-#define del_xpvcv S_del_xpvcv
-#define del_xpvav S_del_xpvav
-#define del_xpvhv S_del_xpvhv
-#define del_xpvmg S_del_xpvmg
-#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
#define uiv_2buf S_uiv_2buf
#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_xpvnv() S_new_xpvnv(aTHX)
-#define new_xpvcv() S_new_xpvcv(aTHX)
-#define new_xpvav() S_new_xpvav(aTHX)
-#define new_xpvhv() S_new_xpvhv(aTHX)
-#define new_xpvmg() S_new_xpvmg(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_xpvnv(a) S_del_xpvnv(aTHX_ a)
-#define del_xpvcv(a) S_del_xpvcv(aTHX_ a)
-#define del_xpvav(a) S_del_xpvav(aTHX_ a)
-#define del_xpvhv(a) S_del_xpvhv(aTHX_ a)
-#define del_xpvmg(a) S_del_xpvmg(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)
else
Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit, "", "");
}
-/* allocate another arena's worth of struct xrv */
STATIC void *
S_more_bodies (pTHX_ void **arena_root, void **root, size_t size)
return *root;
}
-#define more_thingy(TYPE,lctype) \
- S_more_bodies(aTHX_ (void**)&PL_## lctype ## _arenaroot, \
- (void**)&PL_ ## lctype ## _root, \
- sizeof(TYPE))
+/* grab a new thing from the free list, allocating more if necessary */
-#define more_thingy_allocated(lctype) \
- S_more_bodies(aTHX_ (void**)&PL_## lctype ## _arenaroot, \
- (void**)&PL_ ## lctype ## _root, \
- sizeof(lctype ## _allocated))
-
-
-#define more_xiv() more_thingy_allocated(xiv)
-#define more_xrv() more_thingy(XRV, xrv)
-#define more_xnv() more_thingy_allocated(xnv)
-#define more_xpv() more_thingy_allocated(xpv)
-#define more_xpviv() more_thingy_allocated(xpviv)
-#define more_xpvnv() more_thingy(XPVNV, xpvnv)
-#define more_xpvcv() more_thingy(XPVCV, xpvcv)
-#define more_xpvav() more_thingy_allocated(xpvav)
-#define more_xpvhv() more_thingy_allocated(xpvhv)
-#define more_xpvgv() more_thingy(XPVGV, xpvgv)
-#define more_xpvmg() more_thingy(XPVMG, xpvmg)
-#define more_xpvbm() more_thingy(XPVBM, xpvbm)
-#define more_xpvlv() more_thingy(XPVLV, xpvlv)
-
-
-/* grab a new struct xrv from the free list, allocating more if necessary */
-
-STATIC XRV*
-S_new_xrv(pTHX)
-{
- XRV* xrv;
- LOCK_SV_MUTEX;
- xrv = PL_xrv_root ? PL_xrv_root : more_xrv();
- 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)
-{
- xiv_allocated* xiv;
- LOCK_SV_MUTEX;
- xiv = PL_xiv_root ? PL_xiv_root : more_xiv();
- PL_xiv_root = *(xiv_allocated**)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)
-{
- xiv_allocated * xiv = (xiv_allocated*)((char*)(p) + STRUCT_OFFSET(XPVIV, xiv_iv));
- LOCK_SV_MUTEX;
- *(xiv_allocated**)xiv = PL_xiv_root;
- PL_xiv_root = xiv;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new NV body from the free list, allocating more if necessary */
-
-STATIC XPVNV*
-S_new_xnv(pTHX)
-{
- xnv_allocated* xnv;
- LOCK_SV_MUTEX;
- xnv = PL_xnv_root ? PL_xnv_root : more_xnv();
- PL_xnv_root = *(xnv_allocated **)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)
-{
- xnv_allocated * xnv = (xnv_allocated*)((char*)(p) + STRUCT_OFFSET(XPVNV, xnv_nv));
- LOCK_SV_MUTEX;
- *(xnv_allocated**)xnv = PL_xnv_root;
- PL_xnv_root = xnv;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpv from the free list, allocating more if necessary */
-
-STATIC XPV*
-S_new_xpv(pTHX)
-{
- xpv_allocated* xpv;
- LOCK_SV_MUTEX;
- xpv = PL_xpv_root ? PL_xpv_root : more_xpv();
- PL_xpv_root = *(xpv_allocated**)xpv;
- UNLOCK_SV_MUTEX;
- /* 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 */
-
-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_allocated**)xpv = PL_xpv_root;
- PL_xpv_root = xpv;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpviv from the free list, allocating more if necessary */
-
-STATIC XPVIV*
-S_new_xpviv(pTHX)
-{
- XPVIV* xpviv;
- LOCK_SV_MUTEX;
- xpviv = PL_xpviv_root ? PL_xpviv_root : more_xpviv();
- PL_xpviv_root = (XPVIV*)xpviv->xpv_pv;
- UNLOCK_SV_MUTEX;
- return xpviv;
-}
-
-/* return a struct xpviv to the free list */
-
-STATIC void
-S_del_xpviv(pTHX_ XPVIV *p)
-{
- LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpviv_root;
- PL_xpviv_root = p;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvnv from the free list, allocating more if necessary */
-
-STATIC XPVNV*
-S_new_xpvnv(pTHX)
-{
- XPVNV* xpvnv;
- LOCK_SV_MUTEX;
- xpvnv = PL_xpvnv_root ? PL_xpvnv_root : more_xpvnv();
- PL_xpvnv_root = (XPVNV*)xpvnv->xpv_pv;
- UNLOCK_SV_MUTEX;
- return xpvnv;
-}
-
-/* return a struct xpvnv to the free list */
-
-STATIC void
-S_del_xpvnv(pTHX_ XPVNV *p)
-{
- LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpvnv_root;
- PL_xpvnv_root = p;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvcv from the free list, allocating more if necessary */
-
-STATIC XPVCV*
-S_new_xpvcv(pTHX)
-{
- XPVCV* xpvcv;
- LOCK_SV_MUTEX;
- xpvcv = PL_xpvcv_root ? PL_xpvcv_root : more_xpvcv();
- PL_xpvcv_root = (XPVCV*)xpvcv->xpv_pv;
- UNLOCK_SV_MUTEX;
- return xpvcv;
-}
-
-/* return a struct xpvcv to the free list */
-
-STATIC void
-S_del_xpvcv(pTHX_ XPVCV *p)
-{
- LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpvcv_root;
- PL_xpvcv_root = p;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvav from the free list, allocating more if necessary */
-
-STATIC XPVAV*
-S_new_xpvav(pTHX)
-{
- xpvav_allocated* xpvav;
- LOCK_SV_MUTEX;
- xpvav = PL_xpvav_root ? PL_xpvav_root : more_xpvav();
- PL_xpvav_root = *(xpvav_allocated**)xpvav;
- UNLOCK_SV_MUTEX;
- return (XPVAV*)((char*)xpvav - STRUCT_OFFSET(XPVAV, xav_fill)
- + STRUCT_OFFSET(xpvav_allocated, xav_fill));
-}
-
-/* return a struct xpvav to the free list */
-
-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_allocated**)xpvav = PL_xpvav_root;
- PL_xpvav_root = xpvav;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvhv from the free list, allocating more if necessary */
-
-STATIC XPVHV*
-S_new_xpvhv(pTHX)
-{
- xpvhv_allocated* xpvhv;
- LOCK_SV_MUTEX;
- xpvhv = PL_xpvhv_root ? PL_xpvhv_root : more_xpvhv();
- PL_xpvhv_root = *(xpvhv_allocated**)xpvhv;
- UNLOCK_SV_MUTEX;
- return (XPVHV*)((char*)xpvhv - STRUCT_OFFSET(XPVHV, xhv_fill)
- + STRUCT_OFFSET(xpvhv_allocated, xhv_fill));
-}
-
-/* return a struct xpvhv to the free list */
-
-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_allocated**)xpvhv = PL_xpvhv_root;
- PL_xpvhv_root = xpvhv;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvmg from the free list, allocating more if necessary */
-
-STATIC XPVMG*
-S_new_xpvmg(pTHX)
-{
- XPVMG* xpvmg;
- LOCK_SV_MUTEX;
- xpvmg = PL_xpvmg_root ? PL_xpvmg_root : more_xpvmg();
- PL_xpvmg_root = (XPVMG*)xpvmg->xpv_pv;
- UNLOCK_SV_MUTEX;
- return xpvmg;
-}
-
-/* return a struct xpvmg to the free list */
-
-STATIC void
-S_del_xpvmg(pTHX_ XPVMG *p)
-{
- LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpvmg_root;
- PL_xpvmg_root = p;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvgv from the free list, allocating more if necessary */
-
-STATIC XPVGV*
-S_new_xpvgv(pTHX)
-{
- XPVGV* xpvgv;
- LOCK_SV_MUTEX;
- xpvgv = PL_xpvgv_root ? PL_xpvgv_root : more_xpvgv();
- PL_xpvgv_root = (XPVGV*)xpvgv->xpv_pv;
- UNLOCK_SV_MUTEX;
- return xpvgv;
-}
-
-/* return a struct xpvgv to the free list */
-
-STATIC void
-S_del_xpvgv(pTHX_ XPVGV *p)
-{
- LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpvgv_root;
- PL_xpvgv_root = p;
- UNLOCK_SV_MUTEX;
-}
-
-/* grab a new struct xpvlv from the free list, allocating more if necessary */
-
-STATIC XPVLV*
-S_new_xpvlv(pTHX)
+STATIC void *
+S_new_body(pTHX_ void **arena_root, void **root, size_t size, size_t offset)
{
- XPVLV* xpvlv;
+ void *xpv;
LOCK_SV_MUTEX;
- xpvlv = PL_xpvlv_root ? PL_xpvlv_root : more_xpvlv();
- PL_xpvlv_root = (XPVLV*)xpvlv->xpv_pv;
+ xpv = *root ? *root : S_more_bodies(aTHX_ arena_root, root, size);
+ *root = *(void**)xpv;
UNLOCK_SV_MUTEX;
- return xpvlv;
+ return (void*)((char*)xpv - offset);
}
-/* return a struct xpvlv to the free list */
+/* return a thing to the free list */
STATIC void
-S_del_xpvlv(pTHX_ XPVLV *p)
+S_del_body(pTHX_ void *thing, void **root, size_t offset)
{
+ void **real_thing = (void**)((char *)thing + offset);
LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpvlv_root;
- PL_xpvlv_root = p;
+ *real_thing = *root;
+ *root = (void*)real_thing;
UNLOCK_SV_MUTEX;
}
-/* grab a new struct xpvbm from the free list, allocating more if necessary */
+/* Conventionally we simply malloc() a big block of memory, then divide it
+ up into lots of the thing that we're allocating.
-STATIC XPVBM*
-S_new_xpvbm(pTHX)
-{
- XPVBM* xpvbm;
- LOCK_SV_MUTEX;
- xpvbm = PL_xpvbm_root ? PL_xpvbm_root : more_xpvbm();
- PL_xpvbm_root = (XPVBM*)xpvbm->xpv_pv;
- UNLOCK_SV_MUTEX;
- return xpvbm;
-}
+ This macro will expand to call to S_new_body. So for XPVBM (with ithreads),
+ it would become
-/* return a struct xpvbm to the free list */
+ S_new_body(my_perl, (void**)&(my_perl->Ixpvbm_arenaroot),
+ (void**)&(my_perl->Ixpvbm_root), sizeof(XPVBM), 0)
+*/
-STATIC void
-S_del_xpvbm(pTHX_ XPVBM *p)
-{
- LOCK_SV_MUTEX;
- p->xpv_pv = (char*)PL_xpvbm_root;
- PL_xpvbm_root = p;
- UNLOCK_SV_MUTEX;
-}
+#define new_body(TYPE,lctype) \
+ S_new_body(aTHX_ (void**)&PL_ ## lctype ## _arenaroot, \
+ (void**)&PL_ ## lctype ## _root, \
+ sizeof(TYPE), \
+ 0)
+
+/* But for some types, we cheat. The type starts with some members that are
+ never accessed. So we allocate the substructure, starting at the first used
+ member, then adjust the pointer back in memory by the size of the bit not
+ allocated, so it's as if we allocated the full structure.
+ (But things will all go boom if you write to the part that is "not there",
+ because you'll be overwriting the last members of the preceding structure
+ in memory.)
+
+ We calculate the correction using the STRUCT_OFFSET macro. For example, 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 NV actually allocated) then the net effect is to subtract the size
+ of the NV from the pointer, to return a new pointer as if an initial NV were
+ actually allocated.
+
+ This is the same trick as was used for NV and IV bodies. Ironically it
+ doesn't need to be used for NV bodies any more, because NV is now at the
+ start of the structure. IV bodies don't need it either, because they are
+ no longer allocated. */
+
+#define new_body_allocated(TYPE,lctype,member) \
+ S_new_body(aTHX_ (void**)&PL_ ## lctype ## _arenaroot, \
+ (void**)&PL_ ## lctype ## _root, \
+ sizeof(lctype ## _allocated), \
+ STRUCT_OFFSET(TYPE, member) \
+ - STRUCT_OFFSET(lctype ## _allocated, member))
+
+
+#define del_body(p,TYPE,lctype) \
+ S_del_body(aTHX_ (void*)p, (void**)&PL_ ## lctype ## _root, 0)
+
+#define del_body_allocated(p,TYPE,lctype,member) \
+ S_del_body(aTHX_ (void*)p, (void**)&PL_ ## lctype ## _root, \
+ STRUCT_OFFSET(TYPE, member) \
+ - STRUCT_OFFSET(lctype ## _allocated, member))
#define my_safemalloc(s) (void*)safemalloc(s)
#define my_safefree(p) safefree((char*)p)
#else /* !PURIFY */
-#define new_XIV() (void*)new_xiv()
-#define del_XIV(p) del_xiv((XPVIV*) p)
+typedef struct xpviv XIV;
+typedef struct xpvnv XNV;
+
+#define new_XIV() new_body_allocated(XIV, xiv, xiv_iv)
+#define del_XIV(p) del_body_allocated(p, XIV, xiv, xiv_iv)
-#define new_XNV() (void*)new_xnv()
-#define del_XNV(p) del_xnv((XPVNV*) p)
+#define new_XNV() new_body_allocated(XNV, xnv, xnv_nv)
+#define del_XNV(p) del_body_allocated(p, XNV, xnv, xnv_nv)
-#define new_XRV() (void*)new_xrv()
-#define del_XRV(p) del_xrv((XRV*) p)
+#define new_XRV() new_body(XRV, xrv)
+#define del_XRV(p) del_body(p, XRV, xrv)
-#define new_XPV() (void*)new_xpv()
-#define del_XPV(p) del_xpv((XPV *)p)
+#define new_XPV() new_body_allocated(XPV, xpv, xpv_cur)
+#define del_XPV(p) del_body_allocated(p, XPV, xpv, xpv_cur)
-#define new_XPVIV() (void*)new_xpviv()
-#define del_XPVIV(p) del_xpviv((XPVIV *)p)
+#define new_XPVIV() new_body_allocated(XPVIV, xpviv, xpv_cur)
+#define del_XPVIV(p) del_body_allocated(p, XPVIV, xpviv, xpv_cur)
-#define new_XPVNV() (void*)new_xpvnv()
-#define del_XPVNV(p) del_xpvnv((XPVNV *)p)
+#define new_XPVNV() new_body(XPVNV, xpvnv)
+#define del_XPVNV(p) del_body(p, XPVNV, xpvnv)
-#define new_XPVCV() (void*)new_xpvcv()
-#define del_XPVCV(p) del_xpvcv((XPVCV *)p)
+#define new_XPVCV() new_body(XPVCV, xpvcv)
+#define del_XPVCV(p) del_body(p, XPVCV, xpvcv)
-#define new_XPVAV() (void*)new_xpvav()
-#define del_XPVAV(p) del_xpvav((XPVAV *)p)
+#define new_XPVAV() new_body_allocated(XPVAV, xpvav, xav_fill)
+#define del_XPVAV(p) del_body_allocated(p, XPVAV, xpvav, xav_fill)
-#define new_XPVHV() (void*)new_xpvhv()
-#define del_XPVHV(p) del_xpvhv((XPVHV *)p)
+#define new_XPVHV() new_body_allocated(XPVHV, xpvhv, xhv_fill)
+#define del_XPVHV(p) del_body_allocated(p, XPVHV, xpvhv, xhv_fill)
-#define new_XPVMG() (void*)new_xpvmg()
-#define del_XPVMG(p) del_xpvmg((XPVMG *)p)
+#define new_XPVMG() new_body(XPVMG, xpvmg)
+#define del_XPVMG(p) del_body(p, XPVMG, xpvmg)
-#define new_XPVGV() (void*)new_xpvgv()
-#define del_XPVGV(p) del_xpvgv((XPVGV *)p)
+#define new_XPVGV() new_body(XPVGV, xpvgv)
+#define del_XPVGV(p) del_body(p, XPVGV, xpvgv)
-#define new_XPVLV() (void*)new_xpvlv()
-#define del_XPVLV(p) del_xpvlv((XPVLV *)p)
+#define new_XPVLV() new_body(XPVLV, xpvlv)
+#define del_XPVLV(p) del_body(p, XPVLV, xpvlv)
-#define new_XPVBM() (void*)new_xpvbm()
-#define del_XPVBM(p) del_xpvbm((XPVBM *)p)
+#define new_XPVBM() new_body(XPVBM, xpvbm)
+#define del_XPVBM(p) del_body(p, XPVBM, xpvbm)
#endif /* PURIFY */