#include "perl.h"
#include "XSUB.h"
+static int regex_whine;
+static int fm_whine;
+
+
#define carp puts
UV thing_size(SV *, HV *);
typedef enum {
OPc_SVOP, /* 7 */
OPc_PADOP, /* 8 */
OPc_PVOP, /* 9 */
- OPc_CVOP, /* 10 */
- OPc_LOOP, /* 11 */
- OPc_COP /* 12 */
+ OPc_LOOP, /* 10 */
+ OPc_COP /* 11 */
} opclass;
static opclass
return OPc_PADOP;
#endif
+ if ((o->op_type = OP_TRANS)) {
+ return OPc_BASEOP;
+ }
+
switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
case OA_BASEOP:
return OPc_BASEOP;
pointer as the length. Perl then uses the four (or eight, on
64-bit machines) bytes of the address as the string we're using as
the key */
-IV check_new(HV *tracking_hash, void *thing) {
+IV check_new(HV *tracking_hash, const void *thing) {
if (NULL == thing) {
return FALSE;
}
UV regex_size(REGEXP *baseregex, HV *tracking_hash) {
UV total_size = 0;
+ total_size += sizeof(REGEXP);
+ /* Note hte size of the paren offset thing */
+ total_size += sizeof(I32) * baseregex->nparens * 2;
+ total_size += strlen(baseregex->precomp);
+
+ if (go_yell && !regex_whine) {
+ carp("Devel::Size: Calculated sizes for compiled regexes are incomple, and probably always will be");
+ regex_whine = 1;
+ }
+
return total_size;
}
if (check_new(tracking_hash, cPMOPx(baseop)->op_pmnext)) {
total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tracking_hash);
}
- // if (check_new(tracking_hash, cPMOPx(baseop)->op_pmregexp)) {
- // total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tracking_hash);
- //}
+ /* This is defined away in perl 5.8.x, but it is in there for
+ 5.6.x */
+#ifdef PM_GETRE
+ if (check_new(tracking_hash, PM_GETRE((cPMOPx(baseop))))) {
+ total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tracking_hash);
+ }
+#else
+ if (check_new(tracking_hash, cPMOPx(baseop)->op_pmregexp)) {
+ total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tracking_hash);
+ }
+#endif
break;
case OPc_SVOP:
total_size += sizeof(struct pmop);
if (check_new(tracking_hash, cLOOPx(baseop)->op_nextop)) {
total_size += op_size(cLOOPx(baseop)->op_nextop, tracking_hash);
}
-// if (check_new(tracking_hash, cLOOPx(baseop)->op_lastop)) {
-// total_size += op_size(cLOOPx(baseop)->op_lastop, tracking_hash);
-// }
+ /* Not working for some reason, but the code's here for later
+ fixing
+ if (check_new(tracking_hash, cLOOPx(baseop)->op_lastop)) {
+ total_size += op_size(cLOOPx(baseop)->op_lastop, tracking_hash);
+ }
+ */
+ break;
case OPc_COP:
{
COP *basecop;
return total_size;
}
+#if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
+# define NEW_HEAD_LAYOUT
+#endif
+
UV thing_size(SV *orig_thing, HV *tracking_hash) {
SV *thing = orig_thing;
UV total_size = sizeof(SV);
/* Just a plain integer. This will be differently sized depending
on whether purify's been compiled in */
case SVt_IV:
-#ifdef PURIFY
+#ifndef NEW_HEAD_LAYOUT
+# ifdef PURIFY
total_size += sizeof(sizeof(XPVIV));
-#else
+# else
total_size += sizeof(IV);
+# endif
#endif
break;
/* Is it a float? Like the int, it depends on purify */
break;
/* Is it a reference? */
case SVt_RV:
+#ifndef NEW_HEAD_LAYOUT
total_size += sizeof(XRV);
+#endif
break;
/* How about a plain string? In which case we need to add in how
much has been allocated */
case SVt_PVIV:
total_size += sizeof(XPVIV);
total_size += SvLEN(thing);
+ if(SvOOK(thing)) {
+ total_size += SvIVX(thing);
+ }
break;
/* A string with a float part? */
case SVt_PVNV:
total_size += SvLEN(thing);
total_size += magic_size(thing, tracking_hash);
break;
+#if PERL_VERSION <= 8
case SVt_PVBM:
total_size += sizeof(XPVBM);
total_size += SvLEN(thing);
total_size += magic_size(thing, tracking_hash);
break;
+#endif
case SVt_PVLV:
total_size += sizeof(XPVLV);
total_size += SvLEN(thing);
total_size += sizeof(SV *) * AvMAX(thing);
}
/* Add in the bits on the other side of the beginning */
- total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
+
+ /*
+ printf ("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
+ total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )); */
+
+ /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
+ resulting in grossly overstated sized for arrays */
+ if (AvALLOC(thing) != 0) {
+ total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
+ }
/* Is there something hanging off the arylen element? */
if (AvARYLEN(thing)) {
if (check_new(tracking_hash, AvARYLEN(thing))) {
total_size += sizeof(GP);
{
SV *generic_thing;
- if (generic_thing = (SV *)(GvGP(thing)->gp_sv)) {
+ if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
total_size += thing_size(generic_thing, tracking_hash);
}
- if (generic_thing = (SV *)(GvGP(thing)->gp_form)) {
+ if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
total_size += thing_size(generic_thing, tracking_hash);
}
- if (generic_thing = (SV *)(GvGP(thing)->gp_av)) {
+ if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
total_size += thing_size(generic_thing, tracking_hash);
}
- if (generic_thing = (SV *)(GvGP(thing)->gp_hv)) {
+ if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
total_size += thing_size(generic_thing, tracking_hash);
}
- if (generic_thing = (SV *)(GvGP(thing)->gp_egv)) {
+ if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
total_size += thing_size(generic_thing, tracking_hash);
}
- if (generic_thing = (SV *)(GvGP(thing)->gp_cv)) {
+ if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
total_size += thing_size(generic_thing, tracking_hash);
}
}
total_size += thing_size((SV *)CvOUTSIDE(thing), tracking_hash);
}
- if (go_yell) {
+ if (go_yell && !fm_whine) {
carp("Devel::Size: Calculated sizes for FMs are incomplete");
+ fm_whine = 1;
}
break;
case SVt_PVIO:
total_size += sizeof(XPVIO);
total_size += magic_size(thing, tracking_hash);
- if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xpv_pv)) {
+ if (check_new(tracking_hash, (SvPVX(thing)))) {
total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
}
/* Some embedded char pointers */
/* Check warning status */
go_yell = 0;
+ regex_whine = 0;
+ fm_whine = 0;
if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
go_yell = SvIV(warn_flag);
IV size = 0;
SV *warn_flag;
- IV count = 0;
-
/* Size starts at zero */
RETVAL = 0;
/* Check warning status */
go_yell = 0;
+ regex_whine = 0;
+ fm_whine = 0;
if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
go_yell = SvIV(warn_flag);
/* Run through them all */
for (index = 0; index <= av_len(tempAV); index++) {
/* Did we get something? */
- if (tempSV = av_fetch(tempAV, index, 0)) {
+ if ((tempSV = av_fetch(tempAV, index, 0))) {
/* Was it undef? */
if (*tempSV != &PL_sv_undef) {
/* Apparently not. Save it for later */
/* Is there anything in here? */
if (hv_iterinit((HV *)thing)) {
HE *temp_he;
- while (temp_he = hv_iternext((HV *)thing)) {
+ while ((temp_he = hv_iternext((HV *)thing))) {
av_push(pending_array, hv_iterval((HV *)thing, temp_he));
}
}