X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=Size.xs;h=b18e046e69996a370c693b6be3b1ca27a6fa4806;hb=a5c6bdd7895f5ca3ffe055e7c914a39937fdf69b;hp=c77a39154240a138092221a7db77c3eff3f0a2f8;hpb=35b71bcad21c9fb3ab22636b260608c89542e48f;p=p5sagit%2FDevel-Size.git diff --git a/Size.xs b/Size.xs index c77a391..b18e046 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++. @@ -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]); @@ -312,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); @@ -387,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; @@ -426,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; { @@ -580,19 +624,19 @@ const U8 body_sizes[SVt_LAST] = { #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]; @@ -760,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; @@ -801,12 +831,6 @@ 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" -#endif return st; }