size */
static void
magic_size(pTHX_ const SV * const thing, struct state *st) {
- MAGIC *magic_pointer;
+ MAGIC *magic_pointer = SvMAGIC(thing);
- /* Is there any? */
- if (!SvMAGIC(thing)) {
- /* No, bail */
- return;
- }
-
- /* Get the base magic pointer */
- magic_pointer = SvMAGIC(thing);
-
- /* Have we seen the magic pointer? */
+ /* Have we seen the magic pointer? (NULL has always been seen before) */
while (check_new(st, magic_pointer)) {
st->total_size += sizeof(MAGIC);
}
}
-#if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
-# define NEW_HEAD_LAYOUT
+#if PERL_VERSION < 8 || PERL_SUBVERSION < 9
+# define SVt_LAST 16
+#endif
+
+const U8 body_sizes[SVt_LAST] = {
+#if PERL_VERSION < 9
+ 0, /* SVt_NULL */
+ sizeof(IV), /* SVt_IV */
+ sizeof(NV), /* SVt_NV */
+ sizeof(XRV), /* SVt_RV */
+ sizeof(XPV), /* SVt_PV */
+ sizeof(XPVIV), /* SVt_PVIV */
+ sizeof(XPVNV), /* SVt_PVNV */
+ sizeof(XPVMG), /* SVt_PVMG */
+ sizeof(XPVBM), /* SVt_PVBM */
+ sizeof(XPVLV), /* SVt_PVLV */
+ sizeof(XPVAV), /* SVt_PVAV */
+ sizeof(XPVHV), /* SVt_PVHV */
+ sizeof(XPVCV), /* SVt_PVCV */
+ sizeof(XPVGV), /* SVt_PVGV */
+ sizeof(XPVFM), /* SVt_PVFM */
+ sizeof(XPVIO) /* SVt_PVIO */
+#elif PERL_VERSION == 10 && PERL_SUBVERSION == 0
+ 0, /* SVt_NULL */
+ 0, /* SVt_BIND */
+ 0, /* SVt_IV */
+ sizeof(NV), /* SVt_NV */
+ 0, /* SVt_RV */
+ sizeof(xpv_allocated), /* SVt_PV */
+ sizeof(xpviv_allocated), /* SVt_PVIV */
+ sizeof(XPVNV), /* SVt_PVNV */
+ sizeof(XPVMG), /* SVt_PVMG */
+ sizeof(XPVGV), /* SVt_PVGV */
+ sizeof(XPVLV), /* SVt_PVLV */
+ sizeof(xpvav_allocated), /* SVt_PVAV */
+ sizeof(xpvhv_allocated), /* SVt_PVHV */
+ sizeof(xpvcv_allocated), /* SVt_PVCV */
+ sizeof(xpvfm_allocated), /* SVt_PVFM */
+ sizeof(XPVIO), /* SVt_PVIO */
+#elif PERL_VERSION == 10 && PERL_SUBVERSION == 1
+ 0, /* SVt_NULL */
+ 0, /* SVt_BIND */
+ 0, /* SVt_IV */
+ sizeof(NV), /* SVt_NV */
+ 0, /* SVt_RV */
+ sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PV */
+ sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PVIV */
+ sizeof(XPVNV), /* SVt_PVNV */
+ sizeof(XPVMG), /* SVt_PVMG */
+ sizeof(XPVGV), /* SVt_PVGV */
+ sizeof(XPVLV), /* SVt_PVLV */
+ sizeof(XPVAV) - STRUCT_OFFSET(XPVAV, xav_fill), /* SVt_PVAV */
+ sizeof(XPVHV) - STRUCT_OFFSET(XPVHV, xhv_fill), /* SVt_PVHV */
+ sizeof(XPVCV) - STRUCT_OFFSET(XPVCV, xpv_cur), /* SVt_PVCV */
+ sizeof(XPVFM) - STRUCT_OFFSET(XPVFM, xpv_cur), /* SVt_PVFM */
+ sizeof(XPVIO) /* SVt_PVIO */
+#elif PERL_VERSION < 13
+ 0, /* SVt_NULL */
+ 0, /* SVt_BIND */
+ 0, /* SVt_IV */
+ sizeof(NV), /* SVt_NV */
+ sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PV */
+ sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PVIV */
+ sizeof(XPVNV), /* SVt_PVNV */
+ sizeof(XPVMG), /* SVt_PVMG */
+ sizeof(regexp) - STRUCT_OFFSET(regexp, xpv_cur), /* SVt_REGEXP */
+ sizeof(XPVGV), /* SVt_PVGV */
+ sizeof(XPVLV), /* SVt_PVLV */
+ sizeof(XPVAV) - STRUCT_OFFSET(XPVAV, xav_fill), /* SVt_PVAV */
+ sizeof(XPVHV) - STRUCT_OFFSET(XPVHV, xhv_fill), /* SVt_PVHV */
+ sizeof(XPVCV) - STRUCT_OFFSET(XPVCV, xpv_cur), /* SVt_PVCV */
+ sizeof(XPVFM) - STRUCT_OFFSET(XPVFM, xpv_cur), /* SVt_PVFM */
+ sizeof(XPVIO) /* SVt_PVIO */
+#else
+ 0, /* SVt_NULL */
+ 0, /* SVt_BIND */
+ 0, /* SVt_IV */
+ sizeof(NV), /* SVt_NV */
+ sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PV */
+ sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PVIV */
+ sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur), /* SVt_PVNV */
+ sizeof(XPVMG), /* SVt_PVMG */
+ sizeof(regexp), /* SVt_REGEXP */
+ sizeof(XPVGV), /* SVt_PVGV */
+ sizeof(XPVLV), /* SVt_PVLV */
+ sizeof(XPVAV), /* SVt_PVAV */
+ sizeof(XPVHV), /* SVt_PVHV */
+ sizeof(XPVCV), /* SVt_PVCV */
+ sizeof(XPVFM), /* SVt_PVFM */
+ sizeof(XPVIO) /* SVt_PVIO */
#endif
+};
static bool
sv_size(pTHX_ struct state *const st, const SV * const orig_thing,
const int recurse) {
const SV *thing = orig_thing;
+ U32 type;
if(!check_new(st, thing))
return FALSE;
- st->total_size += sizeof(SV);
+ type = SvTYPE(thing);
+ if (type > SVt_LAST) {
+ warn("Devel::Size: Unknown variable type: %d encountered\n", type);
+ return TRUE;
+ }
+ st->total_size += sizeof(SV) + body_sizes[type];
- switch (SvTYPE(thing)) {
- /* Is it undef? */
- case SVt_NULL: TAG;
- TAG;break;
- /* Just a plain integer. This will be differently sized depending
- on whether purify's been compiled in */
- case SVt_IV: TAG;
-#ifndef NEW_HEAD_LAYOUT
-# ifdef PURIFY
- st->total_size += sizeof(sizeof(XPVIV));
-# else
- st->total_size += sizeof(IV);
-# endif
-#endif
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- TAG;break;
- /* Is it a float? Like the int, it depends on purify */
- case SVt_NV: TAG;
-#ifdef PURIFY
- st->total_size += sizeof(sizeof(XPVNV));
-#else
- st->total_size += sizeof(NV);
-#endif
- TAG;break;
-#if (PERL_VERSION < 11)
+ if (type >= SVt_PVMG) {
+ magic_size(aTHX_ thing, st);
+ }
+
+ switch (type) {
+#if (PERL_VERSION < 11)
/* Is it a reference? */
case SVt_RV: TAG;
-#ifndef NEW_HEAD_LAYOUT
- st->total_size += sizeof(XRV);
-#endif
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- TAG;break;
-#endif
- /* How about a plain string? In which case we need to add in how
- much has been allocated */
- case SVt_PV: TAG;
- st->total_size += sizeof(XPV);
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- else
- st->total_size += SvLEN(thing);
- TAG;break;
- /* A string with an integer part? */
- case SVt_PVIV: TAG;
- st->total_size += sizeof(XPVIV);
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- else
- st->total_size += SvLEN(thing);
- if(SvOOK(thing)) {
- st->total_size += SvIVX(thing);
- }
- TAG;break;
- /* A scalar/string/reference with a float part? */
- case SVt_PVNV: TAG;
- st->total_size += sizeof(XPVNV);
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- else
- st->total_size += SvLEN(thing);
- TAG;break;
- case SVt_PVMG: TAG;
- st->total_size += sizeof(XPVMG);
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- else
- st->total_size += SvLEN(thing);
- magic_size(aTHX_ thing, st);
- TAG;break;
-#if PERL_VERSION <= 8
- case SVt_PVBM: TAG;
- st->total_size += sizeof(XPVBM);
- if(recurse && SvROK(thing))
- sv_size(aTHX_ st, SvRV_const(thing), recurse);
- else
- st->total_size += SvLEN(thing);
- magic_size(aTHX_ thing, st);
- TAG;break;
+#else
+ case SVt_IV: TAG;
#endif
- case SVt_PVLV: TAG;
- st->total_size += sizeof(XPVLV);
if(recurse && SvROK(thing))
sv_size(aTHX_ st, SvRV_const(thing), recurse);
- else
- st->total_size += SvLEN(thing);
- magic_size(aTHX_ thing, st);
TAG;break;
- /* How much space is dedicated to the array? Not counting the
- elements in the array, mind, just the array itself */
+
case SVt_PVAV: TAG;
- st->total_size += sizeof(XPVAV);
/* Is there anything in the array? */
if (AvMAX(thing) != -1) {
/* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
complain about AvARYLEN() passing thing to it. */
sv_size(aTHX_ st, AvARYLEN(thing), recurse);
#endif
- magic_size(aTHX_ thing, st);
TAG;break;
case SVt_PVHV: TAG;
- /* First the base struct */
- st->total_size += sizeof(XPVHV);
/* Now the array of buckets */
st->total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
/* Now walk the bucket chain */
}
}
}
- magic_size(aTHX_ thing, st);
TAG;break;
- case SVt_PVCV: TAG;
- st->total_size += sizeof(XPVCV);
- magic_size(aTHX_ thing, st);
- st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
+
+ case SVt_PVFM: TAG;
+ sv_size(aTHX_ st, (SV *)CvPADLIST(thing), SOME_RECURSION);
+ sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
+
+ if (st->go_yell && !st->fm_whine) {
+ carp("Devel::Size: Calculated sizes for FMs are incomplete");
+ st->fm_whine = 1;
+ }
+ goto freescalar;
+
+ case SVt_PVCV: TAG;
sv_size(aTHX_ st, (SV *)CvSTASH(thing), SOME_RECURSION);
sv_size(aTHX_ st, (SV *)SvSTASH(thing), SOME_RECURSION);
sv_size(aTHX_ st, (SV *)CvGV(thing), SOME_RECURSION);
op_size(aTHX_ CvSTART(thing), st);
op_size(aTHX_ CvROOT(thing), st);
}
+ goto freescalar;
+
+ case SVt_PVIO: TAG;
+ /* Some embedded char pointers */
+ check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_top_name);
+ check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_fmt_name);
+ check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_bottom_name);
+ /* Throw the GVs on the list to be walked if they're not-null */
+ sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_top_gv, recurse);
+ sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv, recurse);
+ sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv, recurse);
+
+ /* Only go trotting through the IO structures if they're really
+ trottable. If USE_PERLIO is defined we can do this. If
+ not... we can't, so we don't even try */
+#ifdef USE_PERLIO
+ /* Dig into xio_ifp and xio_ofp here */
+ warn("Devel::Size: Can't size up perlio layers yet\n");
+#endif
+ goto freescalar;
+
+ case SVt_PVLV: TAG;
+#if (PERL_VERSION < 9)
+ goto freescalar;
+#endif
- TAG;break;
case SVt_PVGV: TAG;
- magic_size(aTHX_ thing, st);
- st->total_size += sizeof(XPVGV);
if(isGV_with_GP(thing)) {
st->total_size += GvNAMELEN(thing);
#ifdef GvFILE
sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_egv), recurse);
sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_cv), recurse);
}
+#if (PERL_VERSION >= 9)
+ TAG; break;
+#endif
}
- TAG;break;
- case SVt_PVFM: TAG;
- st->total_size += sizeof(XPVFM);
- magic_size(aTHX_ thing, st);
- st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
- sv_size(aTHX_ st, (SV *)CvPADLIST(thing), SOME_RECURSION);
- sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
+#if PERL_VERSION <= 8
+ case SVt_PVBM: TAG;
+#endif
+ case SVt_PVMG: TAG;
+ case SVt_PVNV: TAG;
+ case SVt_PVIV: TAG;
+ case SVt_PV: TAG;
+ freescalar:
+ if(recurse && SvROK(thing))
+ sv_size(aTHX_ st, SvRV_const(thing), recurse);
+ else
+ st->total_size += SvLEN(thing);
- if (st->go_yell && !st->fm_whine) {
- carp("Devel::Size: Calculated sizes for FMs are incomplete");
- st->fm_whine = 1;
+ if(SvOOK(thing)) {
+ st->total_size += SvIVX(thing);
}
TAG;break;
- case SVt_PVIO: TAG;
- st->total_size += sizeof(XPVIO);
- magic_size(aTHX_ thing, st);
- if (check_new(st, (SvPVX_const(thing)))) {
- st->total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
- }
- /* Some embedded char pointers */
- check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_top_name);
- check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_fmt_name);
- check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_bottom_name);
- /* Throw the GVs on the list to be walked if they're not-null */
- sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_top_gv, recurse);
- sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv, recurse);
- sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv, recurse);
- /* Only go trotting through the IO structures if they're really
- trottable. If USE_PERLIO is defined we can do this. If
- not... we can't, so we don't even try */
-#ifdef USE_PERLIO
- /* Dig into xio_ifp and xio_ofp here */
- warn("Devel::Size: Can't size up perlio layers yet\n");
-#endif
- TAG;break;
- default:
- warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
}
return TRUE;
}
+/* Frustratingly, the vtables aren't const in perl.h
+ gcc is happy enough to have non-const initialisers in a static array.
+ VC seems not to be. (Is it actually treating the file as C++?)
+ So do the maximally portable thing, unless we know it's gcc, in which case
+ we can do the more space efficient version. */
+
+#if __GNUC__
void *vtables[] = {
#include "vtables.inc"
NULL
};
+#endif
static struct state *
new_state(pTHX)
{
SV *warn_flag;
struct state *st;
+#if __GNUC__
void **vt_p = vtables;
+#endif
Newxz(st, 1, struct state);
st->go_yell = TRUE;
check_new(st, &PL_sv_undef);
check_new(st, &PL_sv_no);
check_new(st, &PL_sv_yes);
+#if __GNUC__
while(*vt_p)
check_new(st, *vt_p++);
+#else
+#include "vtables.inc"
+#endif
return st;
}