X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=Size.xs;h=e958bef2ba7e8fe6a05e471c7aad575dca096b29;hb=384ebd3ff6310db79700990db048c774d0188889;hp=7ac3d3e331bbb19ba590df7ae09ad9f3ca9a12cc;hpb=b6558d1de5351fab457d9d98ce3f8a5f17b87a91;p=p5sagit%2FDevel-Size.git diff --git a/Size.xs b/Size.xs index 7ac3d3e..e958bef 100644 --- a/Size.xs +++ b/Size.xs @@ -12,6 +12,14 @@ #ifndef SvRV_const # define SvRV_const(rv) SvRV(rv) #endif +#ifndef SvOOK_offset +# define SvOOK_offset(sv, len) STMT_START { len = SvIVX(sv); } STMT_END +#endif + +#if PERL_VERSION < 6 +# define PL_opargs opargs +# define PL_op_name op_name +#endif #ifdef _MSC_VER /* "structured exception" handling is a Microsoft extension to C and C++. @@ -138,7 +146,7 @@ free_tracking_at(void **tv, int level) /* Nodes */ do { if (tv[i]) { - free_tracking_at(tv[i], level); + free_tracking_at((void **) tv[i], level); Safefree(tv[i]); } } while (i--); @@ -173,7 +181,7 @@ free_state(struct state *st) #define SOME_RECURSION 1 #define TOTAL_SIZE_RECURSION 2 -static bool sv_size(pTHX_ struct state *, const SV *const, const int recurse); +static void sv_size(pTHX_ struct state *, const SV *const, const int recurse); typedef enum { OPc_NULL, /* 0 */ @@ -188,6 +196,13 @@ typedef enum { OPc_PVOP, /* 9 */ OPc_LOOP, /* 10 */ OPc_COP /* 11 */ +#ifdef OA_CONDOP + , OPc_CONDOP /* 12 */ +#endif +#ifdef OA_GVOP + , OPc_GVOP /* 13 */ +#endif + } opclass; static opclass @@ -233,9 +248,17 @@ cc_opclass(const OP * const o) case OA_SVOP: TAG; return OPc_SVOP; +#ifdef OA_PADOP case OA_PADOP: TAG; return OPc_PADOP; +#endif + +#ifdef OA_GVOP + case OA_GVOP: TAG; + return OPc_GVOP; +#endif +#ifdef OA_PVOP_OR_SVOP case OA_PVOP_OR_SVOP: TAG; /* * Character translations (tr///) are usually a PVOP, keeping a @@ -246,6 +269,7 @@ cc_opclass(const OP * const o) */ return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF)) ? OPc_SVOP : OPc_PVOP; +#endif case OA_LOOP: TAG; return OPc_LOOP; @@ -295,6 +319,11 @@ cc_opclass(const OP * const o) return OPc_BASEOP; else return OPc_PVOP; + +#ifdef OA_CONDOP + case OA_CONDOP: TAG; + return OPc_CONDOP; +#endif } warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n", PL_op_name[o->op_type]); @@ -303,11 +332,6 @@ cc_opclass(const OP * const o) return OPc_BASEOP; } - -#if !defined(NV) -#define NV double -#endif - /* Figure out how much magic is attached to the SV and return the size */ static void @@ -317,12 +341,12 @@ magic_size(pTHX_ const SV * const thing, struct state *st) { /* Have we seen the magic pointer? (NULL has always been seen before) */ while (check_new(st, magic_pointer)) { st->total_size += sizeof(MAGIC); + /* magic vtables aren't freed when magic is freed, so don't count them. + (They are static structures. Anything that assumes otherwise is buggy.) + */ + TRY_TO_CATCH_SEGV { - /* Have we seen the magic vtable? */ - if (check_new(st, magic_pointer->mg_virtual)) { - st->total_size += sizeof(MGVTBL); - } sv_size(aTHX_ st, magic_pointer->mg_obj, TOTAL_SIZE_RECURSION); if (magic_pointer->mg_len == HEf_SVKEY) { sv_size(aTHX_ st, (SV *)magic_pointer->mg_ptr, TOTAL_SIZE_RECURSION); @@ -392,38 +416,45 @@ op_size(pTHX_ const OP * const baseop, struct state *st) TAG;break; case OPc_UNOP: TAG; st->total_size += sizeof(struct unop); - op_size(aTHX_ cUNOPx(baseop)->op_first, st); + op_size(aTHX_ ((UNOP *)baseop)->op_first, st); TAG;break; case OPc_BINOP: TAG; st->total_size += sizeof(struct binop); - op_size(aTHX_ cBINOPx(baseop)->op_first, st); - op_size(aTHX_ cBINOPx(baseop)->op_last, st); + op_size(aTHX_ ((BINOP *)baseop)->op_first, st); + op_size(aTHX_ ((BINOP *)baseop)->op_last, st); TAG;break; case OPc_LOGOP: TAG; st->total_size += sizeof(struct logop); - op_size(aTHX_ cBINOPx(baseop)->op_first, st); - op_size(aTHX_ cLOGOPx(baseop)->op_other, st); + op_size(aTHX_ ((BINOP *)baseop)->op_first, st); + op_size(aTHX_ ((LOGOP *)baseop)->op_other, st); TAG;break; +#ifdef OA_CONDOP + case OPc_CONDOP: TAG; + st->total_size += sizeof(struct condop); + op_size(aTHX_ ((BINOP *)baseop)->op_first, st); + op_size(aTHX_ ((CONDOP *)baseop)->op_true, st); + op_size(aTHX_ ((CONDOP *)baseop)->op_false, st); + TAG;break; +#endif case OPc_LISTOP: TAG; st->total_size += sizeof(struct listop); - op_size(aTHX_ cLISTOPx(baseop)->op_first, st); - op_size(aTHX_ cLISTOPx(baseop)->op_last, st); + op_size(aTHX_ ((LISTOP *)baseop)->op_first, st); + op_size(aTHX_ ((LISTOP *)baseop)->op_last, st); TAG;break; case OPc_PMOP: TAG; st->total_size += sizeof(struct pmop); - op_size(aTHX_ cPMOPx(baseop)->op_first, st); - op_size(aTHX_ cPMOPx(baseop)->op_last, st); + op_size(aTHX_ ((PMOP *)baseop)->op_first, st); + op_size(aTHX_ ((PMOP *)baseop)->op_last, st); #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5) - op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, st); - op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, st); - op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, st); + op_size(aTHX_ ((PMOP *)baseop)->op_pmreplroot, st); + op_size(aTHX_ ((PMOP *)baseop)->op_pmreplstart, st); #endif /* This is defined away in perl 5.8.x, but it is in there for 5.6.x */ #ifdef PM_GETRE - regex_size(PM_GETRE(cPMOPx(baseop)), st); + regex_size(PM_GETRE((PMOP *)baseop), st); #else - regex_size(cPMOPx(baseop)->op_pmregexp, st); + regex_size(((PMOP *)baseop)->op_pmregexp, st); #endif TAG;break; case OPc_SVOP: TAG; @@ -431,22 +462,30 @@ op_size(pTHX_ const OP * const baseop, struct state *st) if (!(baseop->op_type == OP_AELEMFAST && baseop->op_flags & OPf_SPECIAL)) { /* not an OP_PADAV replacement */ - sv_size(aTHX_ st, cSVOPx(baseop)->op_sv, SOME_RECURSION); + sv_size(aTHX_ st, ((SVOP *)baseop)->op_sv, SOME_RECURSION); } TAG;break; +#ifdef OA_PADOP case OPc_PADOP: TAG; st->total_size += sizeof(struct padop); TAG;break; +#endif +#ifdef OA_GVOP + case OPc_GVOP: TAG; + st->total_size += sizeof(struct gvop); + sv_size(aTHX_ st, ((GVOP *)baseop)->op_gv, SOME_RECURSION); + TAG;break; +#endif case OPc_PVOP: TAG; - check_new_and_strlen(st, cPVOPx(baseop)->op_pv); + check_new_and_strlen(st, ((PVOP *)baseop)->op_pv); TAG;break; case OPc_LOOP: TAG; st->total_size += sizeof(struct loop); - op_size(aTHX_ cLOOPx(baseop)->op_first, st); - op_size(aTHX_ cLOOPx(baseop)->op_last, st); - op_size(aTHX_ cLOOPx(baseop)->op_redoop, st); - op_size(aTHX_ cLOOPx(baseop)->op_nextop, st); - op_size(aTHX_ cLOOPx(baseop)->op_lastop, st); + op_size(aTHX_ ((LOOP *)baseop)->op_first, st); + op_size(aTHX_ ((LOOP *)baseop)->op_last, st); + op_size(aTHX_ ((LOOP *)baseop)->op_redoop, st); + op_size(aTHX_ ((LOOP *)baseop)->op_nextop, st); + op_size(aTHX_ ((LOOP *)baseop)->op_lastop, st); TAG;break; case OPc_COP: TAG; { @@ -488,108 +527,116 @@ op_size(pTHX_ const OP * const baseop, struct state *st) # define SVt_LAST 16 #endif +#ifdef PURIFY +# define MAYBE_PURIFY(normal, pure) (pure) +# define MAYBE_OFFSET(struct_name, member) 0 +#else +# define MAYBE_PURIFY(normal, pure) (normal) +# define MAYBE_OFFSET(struct_name, member) STRUCT_OFFSET(struct_name, member) +#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 */ + 0, /* SVt_NULL */ + MAYBE_PURIFY(sizeof(IV), sizeof(XPVIV)), /* SVt_IV */ + MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* 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 */ + 0, /* SVt_NULL */ + 0, /* SVt_BIND */ + 0, /* SVt_IV */ + MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */ + 0, /* SVt_RV */ + MAYBE_PURIFY(sizeof(xpv_allocated), sizeof(XPV)), /* SVt_PV */ + MAYBE_PURIFY(sizeof(xpviv_allocated), sizeof(XPVIV)),/* SVt_PVIV */ + sizeof(XPVNV), /* SVt_PVNV */ + sizeof(XPVMG), /* SVt_PVMG */ + sizeof(XPVGV), /* SVt_PVGV */ + sizeof(XPVLV), /* SVt_PVLV */ + MAYBE_PURIFY(sizeof(xpvav_allocated), sizeof(XPVAV)),/* SVt_PVAV */ + MAYBE_PURIFY(sizeof(xpvhv_allocated), sizeof(XPVHV)),/* SVt_PVHV */ + MAYBE_PURIFY(sizeof(xpvcv_allocated), sizeof(XPVCV)),/* SVt_PVCV */ + MAYBE_PURIFY(sizeof(xpvfm_allocated), sizeof(XPVFM)),/* 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 */ + 0, /* SVt_NULL */ + 0, /* SVt_BIND */ + 0, /* SVt_IV */ + MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */ + 0, /* SVt_RV */ + sizeof(XPV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PV */ + sizeof(XPVIV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVIV */ + sizeof(XPVNV), /* SVt_PVNV */ + sizeof(XPVMG), /* SVt_PVMG */ + sizeof(XPVGV), /* SVt_PVGV */ + sizeof(XPVLV), /* SVt_PVLV */ + sizeof(XPVAV) - MAYBE_OFFSET(XPVAV, xav_fill), /* SVt_PVAV */ + sizeof(XPVHV) - MAYBE_OFFSET(XPVHV, xhv_fill), /* SVt_PVHV */ + sizeof(XPVCV) - MAYBE_OFFSET(XPVCV, xpv_cur), /* SVt_PVCV */ + sizeof(XPVFM) - MAYBE_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 */ + 0, /* SVt_NULL */ + 0, /* SVt_BIND */ + 0, /* SVt_IV */ + MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */ + sizeof(XPV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PV */ + sizeof(XPVIV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVIV */ + sizeof(XPVNV), /* SVt_PVNV */ + sizeof(XPVMG), /* SVt_PVMG */ + sizeof(regexp) - MAYBE_OFFSET(regexp, xpv_cur), /* SVt_REGEXP */ + sizeof(XPVGV), /* SVt_PVGV */ + sizeof(XPVLV), /* SVt_PVLV */ + sizeof(XPVAV) - MAYBE_OFFSET(XPVAV, xav_fill), /* SVt_PVAV */ + sizeof(XPVHV) - MAYBE_OFFSET(XPVHV, xhv_fill), /* SVt_PVHV */ + sizeof(XPVCV) - MAYBE_OFFSET(XPVCV, xpv_cur), /* SVt_PVCV */ + sizeof(XPVFM) - MAYBE_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 */ + 0, /* SVt_NULL */ + 0, /* SVt_BIND */ + 0, /* SVt_IV */ + MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */ + sizeof(XPV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PV */ + sizeof(XPVIV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVIV */ + sizeof(XPVNV) - MAYBE_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 +static void 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; + return; type = SvTYPE(thing); if (type > SVt_LAST) { warn("Devel::Size: Unknown variable type: %d encountered\n", type); - return TRUE; + return; } st->total_size += sizeof(SV) + body_sizes[type]; @@ -757,35 +804,21 @@ sv_size(pTHX_ struct state *const st, const SV * const orig_thing, st->total_size += SvLEN(thing); if(SvOOK(thing)) { - st->total_size += SvIVX(thing); + STRLEN len; + SvOOK_offset(thing, len); + st->total_size += len; } TAG;break; } - return TRUE; + return; } -/* 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; @@ -798,11 +831,8 @@ new_state(pTHX) 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" +#if PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 0) + check_new(st, &PL_sv_placeholder); #endif return st; }