Bump $VERSION to 0.74_50
[p5sagit/Devel-Size.git] / Size.xs
CommitLineData
265a0548 1#define PERL_NO_GET_CONTEXT
2
e98cedbf 3#include "EXTERN.h"
4#include "perl.h"
5#include "XSUB.h"
2eb93d08 6#include "ppport.h"
e98cedbf 7
87372f42 8/* Not yet in ppport.h */
9#ifndef CvISXSUB
10# define CvISXSUB(cv) (CvXSUB(cv) ? TRUE : FALSE)
11#endif
0e1f978f 12#ifndef SvRV_const
13# define SvRV_const(rv) SvRV(rv)
14#endif
87372f42 15
9fc9ab86 16#ifdef _MSC_VER
1a36ac09 17/* "structured exception" handling is a Microsoft extension to C and C++.
18 It's *not* C++ exception handling - C++ exception handling can't capture
19 SEGVs and suchlike, whereas this can. There's no known analagous
20 functionality on other platforms. */
21# include <excpt.h>
22# define TRY_TO_CATCH_SEGV __try
23# define CAUGHT_EXCEPTION __except(EXCEPTION EXCEPTION_EXECUTE_HANDLER)
9fc9ab86 24#else
1a36ac09 25# define TRY_TO_CATCH_SEGV if(1)
26# define CAUGHT_EXCEPTION else
9fc9ab86 27#endif
28
29#ifdef __GNUC__
30# define __attribute__(x)
31#endif
32
b7621729 33#if 0 && defined(DEBUGGING)
34#define dbg_printf(x) printf x
35#else
36#define dbg_printf(x)
37#endif
98ecbbc6 38
0964064b 39#define TAG /* printf( "# %s(%d)\n", __FILE__, __LINE__ ) */
6a9ad7ec 40#define carp puts
9fc9ab86 41
30fe4f47 42/* The idea is to have a tree structure to store 1 bit per possible pointer
43 address. The lowest 16 bits are stored in a block of 8092 bytes.
44 The blocks are in a 256-way tree, indexed by the reset of the pointer.
45 This can cope with 32 and 64 bit pointers, and any address space layout,
46 without excessive memory needs. The assumption is that your CPU cache
47 works :-) (And that we're not going to bust it) */
48
9fc9ab86 49#define ALIGN_BITS ( sizeof(void*) >> 1 )
30fe4f47 50#define BYTE_BITS 3
51#define LEAF_BITS (16 - BYTE_BITS)
52#define LEAF_MASK 0x1FFF
9fc9ab86 53
65db36c0 54struct state {
eee00145 55 UV total_size;
65db36c0 56 bool regex_whine;
57 bool fm_whine;
58 bool dangle_whine;
59 bool go_yell;
60 /* My hunch (not measured) is that for most architectures pointers will
61 start with 0 bits, hence the start of this array will be hot, and the
62 end unused. So put the flags next to the hot end. */
63 void *tracking[256];
64};
65
9fc9ab86 66/*
67 Checks to see if thing is in the bitstring.
68 Returns true or false, and
69 notes thing in the segmented bitstring.
70 */
2eb93d08 71static bool
a4efdff3 72check_new(struct state *st, const void *const p) {
30fe4f47 73 unsigned int bits = 8 * sizeof(void*);
74 const size_t raw_p = PTR2nat(p);
75 /* This effectively rotates the value right by the number of low always-0
76 bits in an aligned pointer. The assmption is that most (if not all)
77 pointers are aligned, and these will be in the same chain of nodes
78 (and hence hot in the cache) but we can still deal with any unaligned
79 pointers. */
80 const size_t cooked_p
81 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
82 const U8 this_bit = 1 << (cooked_p & 0x7);
83 U8 **leaf_p;
84 U8 *leaf;
85 unsigned int i;
302077b6 86 void **tv_p = (void **) (st->tracking);
30fe4f47 87
302077b6 88 if (NULL == p) return FALSE;
1a36ac09 89 TRY_TO_CATCH_SEGV {
2eb93d08 90 const char c = *(const char *)p;
9fc9ab86 91 }
1a36ac09 92 CAUGHT_EXCEPTION {
a4efdff3 93 if (st->dangle_whine)
9fc9ab86 94 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
95 return FALSE;
96 }
9fc9ab86 97 TAG;
30fe4f47 98
99 bits -= 8;
100 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
101
102 /* First level is always present. */
103 do {
104 i = (unsigned int)((cooked_p >> bits) & 0xFF);
105 if (!tv_p[i])
106 Newxz(tv_p[i], 256, void *);
107 tv_p = (void **)(tv_p[i]);
108 bits -= 8;
109 } while (bits > LEAF_BITS + BYTE_BITS);
110 /* bits now 16 always */
5f04c81d 111#if !defined(MULTIPLICITY) || PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8)
112 /* 5.8.8 and early have an assert() macro that uses Perl_croak, hence needs
113 a my_perl under multiplicity */
30fe4f47 114 assert(bits == 16);
5f04c81d 115#endif
30fe4f47 116 leaf_p = (U8 **)tv_p;
117 i = (unsigned int)((cooked_p >> bits) & 0xFF);
118 if (!leaf_p[i])
119 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
120 leaf = leaf_p[i];
121
9fc9ab86 122 TAG;
30fe4f47 123
124 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
125
126 if(leaf[i] & this_bit)
127 return FALSE;
128
129 leaf[i] |= this_bit;
9fc9ab86 130 return TRUE;
131}
132
e9716740 133static void
30fe4f47 134free_tracking_at(void **tv, int level)
135{
136 int i = 255;
137
138 if (--level) {
139 /* Nodes */
140 do {
141 if (tv[i]) {
142 free_tracking_at(tv[i], level);
143 Safefree(tv[i]);
144 }
145 } while (i--);
146 } else {
147 /* Leaves */
148 do {
149 if (tv[i])
150 Safefree(tv[i]);
151 } while (i--);
152 }
153}
154
155static void
a4efdff3 156free_state(struct state *st)
e9716740 157{
30fe4f47 158 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
a4efdff3 159 free_tracking_at((void **)st->tracking, top_level);
160 Safefree(st);
e9716740 161}
162
eee00145 163static void thing_size(pTHX_ const SV *const, struct state *);
7ccc7d88 164typedef enum {
9fc9ab86 165 OPc_NULL, /* 0 */
166 OPc_BASEOP, /* 1 */
167 OPc_UNOP, /* 2 */
168 OPc_BINOP, /* 3 */
169 OPc_LOGOP, /* 4 */
170 OPc_LISTOP, /* 5 */
171 OPc_PMOP, /* 6 */
172 OPc_SVOP, /* 7 */
173 OPc_PADOP, /* 8 */
174 OPc_PVOP, /* 9 */
175 OPc_LOOP, /* 10 */
176 OPc_COP /* 11 */
7ccc7d88 177} opclass;
178
179static opclass
9fc9ab86 180cc_opclass(const OP * const o)
7ccc7d88 181{
182 if (!o)
9fc9ab86 183 return OPc_NULL;
1a36ac09 184 TRY_TO_CATCH_SEGV {
9fc9ab86 185 if (o->op_type == 0)
186 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
7ccc7d88 187
9fc9ab86 188 if (o->op_type == OP_SASSIGN)
189 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
7ccc7d88 190
9fc9ab86 191 #ifdef USE_ITHREADS
192 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
193 return OPc_PADOP;
194 #endif
7ccc7d88 195
9fc9ab86 196 if ((o->op_type == OP_TRANS)) {
197 return OPc_BASEOP;
198 }
7ccc7d88 199
9fc9ab86 200 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
201 case OA_BASEOP: TAG;
202 return OPc_BASEOP;
203
204 case OA_UNOP: TAG;
205 return OPc_UNOP;
206
207 case OA_BINOP: TAG;
208 return OPc_BINOP;
62691e7c 209
9fc9ab86 210 case OA_LOGOP: TAG;
211 return OPc_LOGOP;
7ccc7d88 212
9fc9ab86 213 case OA_LISTOP: TAG;
214 return OPc_LISTOP;
7ccc7d88 215
9fc9ab86 216 case OA_PMOP: TAG;
217 return OPc_PMOP;
7ccc7d88 218
9fc9ab86 219 case OA_SVOP: TAG;
220 return OPc_SVOP;
7ccc7d88 221
9fc9ab86 222 case OA_PADOP: TAG;
223 return OPc_PADOP;
7ccc7d88 224
9fc9ab86 225 case OA_PVOP_OR_SVOP: TAG;
226 /*
227 * Character translations (tr///) are usually a PVOP, keeping a
228 * pointer to a table of shorts used to look up translations.
229 * Under utf8, however, a simple table isn't practical; instead,
230 * the OP is an SVOP, and the SV is a reference to a swash
231 * (i.e., an RV pointing to an HV).
232 */
233 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
234 ? OPc_SVOP : OPc_PVOP;
7ccc7d88 235
9fc9ab86 236 case OA_LOOP: TAG;
237 return OPc_LOOP;
7ccc7d88 238
9fc9ab86 239 case OA_COP: TAG;
240 return OPc_COP;
7ccc7d88 241
9fc9ab86 242 case OA_BASEOP_OR_UNOP: TAG;
7ccc7d88 243 /*
9fc9ab86 244 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
245 * whether parens were seen. perly.y uses OPf_SPECIAL to
246 * signal whether a BASEOP had empty parens or none.
247 * Some other UNOPs are created later, though, so the best
248 * test is OPf_KIDS, which is set in newUNOP.
7ccc7d88 249 */
9fc9ab86 250 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
251
252 case OA_FILESTATOP: TAG;
253 /*
254 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
255 * the OPf_REF flag to distinguish between OP types instead of the
256 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
257 * return OPc_UNOP so that walkoptree can find our children. If
258 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
259 * (no argument to the operator) it's an OP; with OPf_REF set it's
260 * an SVOP (and op_sv is the GV for the filehandle argument).
261 */
262 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
263 #ifdef USE_ITHREADS
264 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
265 #else
266 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
267 #endif
268 case OA_LOOPEXOP: TAG;
269 /*
270 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
271 * label was omitted (in which case it's a BASEOP) or else a term was
272 * seen. In this last case, all except goto are definitely PVOP but
273 * goto is either a PVOP (with an ordinary constant label), an UNOP
274 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
275 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
276 * get set.
277 */
278 if (o->op_flags & OPf_STACKED)
279 return OPc_UNOP;
280 else if (o->op_flags & OPf_SPECIAL)
281 return OPc_BASEOP;
282 else
283 return OPc_PVOP;
284 }
285 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
286 PL_op_name[o->op_type]);
287 }
1a36ac09 288 CAUGHT_EXCEPTION { }
7ccc7d88 289 return OPc_BASEOP;
290}
291
6a9ad7ec 292
a6ea0805 293#if !defined(NV)
294#define NV double
295#endif
296
6a9ad7ec 297/* Figure out how much magic is attached to the SV and return the
298 size */
eee00145 299static void
300magic_size(const SV * const thing, struct state *st) {
6a9ad7ec 301 MAGIC *magic_pointer;
302
303 /* Is there any? */
304 if (!SvMAGIC(thing)) {
305 /* No, bail */
eee00145 306 return;
6a9ad7ec 307 }
308
309 /* Get the base magic pointer */
310 magic_pointer = SvMAGIC(thing);
311
312 /* Have we seen the magic pointer? */
e5c69bdd 313 while (check_new(st, magic_pointer)) {
eee00145 314 st->total_size += sizeof(MAGIC);
6a9ad7ec 315
1a36ac09 316 TRY_TO_CATCH_SEGV {
9fc9ab86 317 /* Have we seen the magic vtable? */
e5c69bdd 318 if (check_new(st, magic_pointer->mg_virtual)) {
eee00145 319 st->total_size += sizeof(MGVTBL);
9fc9ab86 320 }
6a9ad7ec 321
0964064b 322 /* Get the next in the chain */
9fc9ab86 323 magic_pointer = magic_pointer->mg_moremagic;
324 }
1a36ac09 325 CAUGHT_EXCEPTION {
a4efdff3 326 if (st->dangle_whine)
9fc9ab86 327 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
328 }
6a9ad7ec 329 }
6a9ad7ec 330}
331
eee00145 332static void
99684fd4 333check_new_and_strlen(struct state *st, const char *const p) {
334 if(check_new(st, p))
335 st->total_size += strlen(p);
336}
337
338static void
eee00145 339regex_size(const REGEXP * const baseregex, struct state *st) {
c1bfd7da 340 if(!check_new(st, baseregex))
341 return;
eee00145 342 st->total_size += sizeof(REGEXP);
9fc9ab86 343#if (PERL_VERSION < 11)
6ea94d90 344 /* Note the size of the paren offset thing */
eee00145 345 st->total_size += sizeof(I32) * baseregex->nparens * 2;
346 st->total_size += strlen(baseregex->precomp);
6ea94d90 347#else
eee00145 348 st->total_size += sizeof(struct regexp);
349 st->total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
350 /*st->total_size += strlen(SvANY(baseregex)->subbeg);*/
6ea94d90 351#endif
a4efdff3 352 if (st->go_yell && !st->regex_whine) {
6ea94d90 353 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
a4efdff3 354 st->regex_whine = 1;
98ecbbc6 355 }
7ccc7d88 356}
357
eee00145 358static void
1e5a8ad2 359op_size(pTHX_ const OP * const baseop, struct state *st)
360{
361 TRY_TO_CATCH_SEGV {
362 TAG;
363 if(!check_new(st, baseop))
364 return;
365 TAG;
366 op_size(aTHX_ baseop->op_next, st);
367 TAG;
368 switch (cc_opclass(baseop)) {
369 case OPc_BASEOP: TAG;
370 st->total_size += sizeof(struct op);
371 TAG;break;
372 case OPc_UNOP: TAG;
373 st->total_size += sizeof(struct unop);
374 op_size(aTHX_ cUNOPx(baseop)->op_first, st);
375 TAG;break;
376 case OPc_BINOP: TAG;
377 st->total_size += sizeof(struct binop);
378 op_size(aTHX_ cBINOPx(baseop)->op_first, st);
379 op_size(aTHX_ cBINOPx(baseop)->op_last, st);
380 TAG;break;
381 case OPc_LOGOP: TAG;
382 st->total_size += sizeof(struct logop);
383 op_size(aTHX_ cBINOPx(baseop)->op_first, st);
384 op_size(aTHX_ cLOGOPx(baseop)->op_other, st);
385 TAG;break;
386 case OPc_LISTOP: TAG;
387 st->total_size += sizeof(struct listop);
388 op_size(aTHX_ cLISTOPx(baseop)->op_first, st);
389 op_size(aTHX_ cLISTOPx(baseop)->op_last, st);
390 TAG;break;
391 case OPc_PMOP: TAG;
392 st->total_size += sizeof(struct pmop);
393 op_size(aTHX_ cPMOPx(baseop)->op_first, st);
394 op_size(aTHX_ cPMOPx(baseop)->op_last, st);
5a83b7cf 395#if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
1e5a8ad2 396 op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, st);
397 op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, st);
398 op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, st);
5a83b7cf 399#endif
c1bfd7da 400 /* This is defined away in perl 5.8.x, but it is in there for
401 5.6.x */
98ecbbc6 402#ifdef PM_GETRE
c1bfd7da 403 regex_size(PM_GETRE(cPMOPx(baseop)), st);
98ecbbc6 404#else
c1bfd7da 405 regex_size(cPMOPx(baseop)->op_pmregexp, st);
98ecbbc6 406#endif
c1bfd7da 407 TAG;break;
9fc9ab86 408 case OPc_SVOP: TAG;
eee00145 409 st->total_size += sizeof(struct pmop);
a4efdff3 410 if (check_new(st, cSVOPx(baseop)->op_sv)) {
eee00145 411 thing_size(aTHX_ cSVOPx(baseop)->op_sv, st);
9fc9ab86 412 }
413 TAG;break;
414 case OPc_PADOP: TAG;
eee00145 415 st->total_size += sizeof(struct padop);
99684fd4 416 TAG;break;
417 case OPc_PVOP: TAG;
418 check_new_and_strlen(st, cPVOPx(baseop)->op_pv);
1e5a8ad2 419 case OPc_LOOP: TAG;
420 st->total_size += sizeof(struct loop);
421 op_size(aTHX_ cLOOPx(baseop)->op_first, st);
422 op_size(aTHX_ cLOOPx(baseop)->op_last, st);
423 op_size(aTHX_ cLOOPx(baseop)->op_redoop, st);
424 op_size(aTHX_ cLOOPx(baseop)->op_nextop, st);
425 op_size(aTHX_ cLOOPx(baseop)->op_lastop, st);
426 TAG;break;
427 case OPc_COP: TAG;
9fc9ab86 428 {
429 COP *basecop;
430 basecop = (COP *)baseop;
eee00145 431 st->total_size += sizeof(struct cop);
9fc9ab86 432
433 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
434 Eliminate cop_label from struct cop by storing a label as the first
435 entry in the hints hash. Most statements don't have labels, so this
436 will save memory. Not sure how much.
437 The check below will be incorrect fail on bleadperls
438 before 5.11 @33656, but later than 5.10, producing slightly too
439 small memory sizes on these Perls. */
b7621729 440#if (PERL_VERSION < 11)
99684fd4 441 check_new_and_strlen(st, basecop->cop_label);
b7621729 442#endif
7ccc7d88 443#ifdef USE_ITHREADS
99684fd4 444 check_new_and_strlen(st, basecop->cop_file);
445 check_new_and_strlen(st, basecop->cop_stashpv);
7ccc7d88 446#else
a4efdff3 447 if (check_new(st, basecop->cop_stash)) {
eee00145 448 thing_size(aTHX_ (SV *)basecop->cop_stash, st);
9fc9ab86 449 }
a4efdff3 450 if (check_new(st, basecop->cop_filegv)) {
eee00145 451 thing_size(aTHX_ (SV *)basecop->cop_filegv, st);
9fc9ab86 452 }
7ccc7d88 453#endif
454
9fc9ab86 455 }
456 TAG;break;
457 default:
458 TAG;break;
459 }
460 }
1a36ac09 461 CAUGHT_EXCEPTION {
a4efdff3 462 if (st->dangle_whine)
9fc9ab86 463 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
7ccc7d88 464 }
7ccc7d88 465}
6a9ad7ec 466
24d37977 467#if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
468# define NEW_HEAD_LAYOUT
469#endif
470
eee00145 471static void
a4efdff3 472thing_size(pTHX_ const SV * const orig_thing, struct state *st) {
9fc9ab86 473 const SV *thing = orig_thing;
eee00145 474
475 st->total_size += sizeof(SV);
b1e5ad85 476
e98cedbf 477 switch (SvTYPE(thing)) {
478 /* Is it undef? */
9fc9ab86 479 case SVt_NULL: TAG;
480 TAG;break;
e98cedbf 481 /* Just a plain integer. This will be differently sized depending
482 on whether purify's been compiled in */
9fc9ab86 483 case SVt_IV: TAG;
24d37977 484#ifndef NEW_HEAD_LAYOUT
485# ifdef PURIFY
eee00145 486 st->total_size += sizeof(sizeof(XPVIV));
24d37977 487# else
eee00145 488 st->total_size += sizeof(IV);
24d37977 489# endif
e98cedbf 490#endif
9fc9ab86 491 TAG;break;
e98cedbf 492 /* Is it a float? Like the int, it depends on purify */
9fc9ab86 493 case SVt_NV: TAG;
e98cedbf 494#ifdef PURIFY
eee00145 495 st->total_size += sizeof(sizeof(XPVNV));
e98cedbf 496#else
eee00145 497 st->total_size += sizeof(NV);
e98cedbf 498#endif
9fc9ab86 499 TAG;break;
500#if (PERL_VERSION < 11)
e98cedbf 501 /* Is it a reference? */
9fc9ab86 502 case SVt_RV: TAG;
24d37977 503#ifndef NEW_HEAD_LAYOUT
eee00145 504 st->total_size += sizeof(XRV);
24d37977 505#endif
9fc9ab86 506 TAG;break;
6ea94d90 507#endif
e98cedbf 508 /* How about a plain string? In which case we need to add in how
509 much has been allocated */
9fc9ab86 510 case SVt_PV: TAG;
eee00145 511 st->total_size += sizeof(XPV);
512 if(SvROK(thing))
513 thing_size(aTHX_ SvRV_const(thing), st);
514 else
515 st->total_size += SvLEN(thing);
9fc9ab86 516 TAG;break;
e98cedbf 517 /* A string with an integer part? */
9fc9ab86 518 case SVt_PVIV: TAG;
eee00145 519 st->total_size += sizeof(XPVIV);
520 if(SvROK(thing))
521 thing_size(aTHX_ SvRV_const(thing), st);
522 else
523 st->total_size += SvLEN(thing);
0430b7f7 524 if(SvOOK(thing)) {
eee00145 525 st->total_size += SvIVX(thing);
9fc9ab86 526 }
527 TAG;break;
c8db37d3 528 /* A scalar/string/reference with a float part? */
9fc9ab86 529 case SVt_PVNV: TAG;
eee00145 530 st->total_size += sizeof(XPVNV);
531 if(SvROK(thing))
532 thing_size(aTHX_ SvRV_const(thing), st);
533 else
534 st->total_size += SvLEN(thing);
9fc9ab86 535 TAG;break;
536 case SVt_PVMG: TAG;
eee00145 537 st->total_size += sizeof(XPVMG);
538 if(SvROK(thing))
539 thing_size(aTHX_ SvRV_const(thing), st);
540 else
541 st->total_size += SvLEN(thing);
542 magic_size(thing, st);
9fc9ab86 543 TAG;break;
0430b7f7 544#if PERL_VERSION <= 8
9fc9ab86 545 case SVt_PVBM: TAG;
eee00145 546 st->total_size += sizeof(XPVBM);
547 if(SvROK(thing))
548 thing_size(aTHX_ SvRV_const(thing), st);
549 else
550 st->total_size += SvLEN(thing);
551 magic_size(thing, st);
9fc9ab86 552 TAG;break;
0430b7f7 553#endif
9fc9ab86 554 case SVt_PVLV: TAG;
eee00145 555 st->total_size += sizeof(XPVLV);
556 if(SvROK(thing))
557 thing_size(aTHX_ SvRV_const(thing), st);
558 else
559 st->total_size += SvLEN(thing);
560 magic_size(thing, st);
9fc9ab86 561 TAG;break;
e98cedbf 562 /* How much space is dedicated to the array? Not counting the
563 elements in the array, mind, just the array itself */
9fc9ab86 564 case SVt_PVAV: TAG;
eee00145 565 st->total_size += sizeof(XPVAV);
e98cedbf 566 /* Is there anything in the array? */
567 if (AvMAX(thing) != -1) {
c8db37d3 568 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
eee00145 569 st->total_size += sizeof(SV *) * (AvMAX(thing) + 1);
570 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", st->total_size, AvMAX(thing), av_len((AV*)thing)));
e98cedbf 571 }
572 /* Add in the bits on the other side of the beginning */
0430b7f7 573
b7621729 574 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
eee00145 575 st->total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
0430b7f7 576
577 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
b1e5ad85 578 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
0430b7f7 579 if (AvALLOC(thing) != 0) {
eee00145 580 st->total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
0430b7f7 581 }
795fc84c 582#if (PERL_VERSION < 9)
583 /* Is there something hanging off the arylen element?
584 Post 5.9.something this is stored in magic, so will be found there,
585 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
586 complain about AvARYLEN() passing thing to it. */
e98cedbf 587 if (AvARYLEN(thing)) {
a4efdff3 588 if (check_new(st, AvARYLEN(thing))) {
eee00145 589 thing_size(aTHX_ AvARYLEN(thing), st);
6a9ad7ec 590 }
e98cedbf 591 }
795fc84c 592#endif
eee00145 593 magic_size(thing, st);
9fc9ab86 594 TAG;break;
595 case SVt_PVHV: TAG;
a6ea0805 596 /* First the base struct */
eee00145 597 st->total_size += sizeof(XPVHV);
a6ea0805 598 /* Now the array of buckets */
eee00145 599 st->total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
a6ea0805 600 /* Now walk the bucket chain */
6a9ad7ec 601 if (HvARRAY(thing)) {
a6ea0805 602 HE *cur_entry;
9fc9ab86 603 UV cur_bucket = 0;
a6ea0805 604 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
9fc9ab86 605 cur_entry = *(HvARRAY(thing) + cur_bucket);
606 while (cur_entry) {
eee00145 607 st->total_size += sizeof(HE);
9fc9ab86 608 if (cur_entry->hent_hek) {
609 /* Hash keys can be shared. Have we seen this before? */
a4efdff3 610 if (check_new(st, cur_entry->hent_hek)) {
eee00145 611 st->total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
9fc9ab86 612 }
613 }
614 cur_entry = cur_entry->hent_next;
615 }
a6ea0805 616 }
617 }
eee00145 618 magic_size(thing, st);
9fc9ab86 619 TAG;break;
620 case SVt_PVCV: TAG;
eee00145 621 st->total_size += sizeof(XPVCV);
622 magic_size(thing, st);
7ccc7d88 623
eee00145 624 st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
a4efdff3 625 if (check_new(st, CvSTASH(thing))) {
eee00145 626 thing_size(aTHX_ (SV *)CvSTASH(thing), st);
7ccc7d88 627 }
a4efdff3 628 if (check_new(st, SvSTASH(thing))) {
eee00145 629 thing_size(aTHX_ (SV *)SvSTASH(thing), st);
7ccc7d88 630 }
a4efdff3 631 if (check_new(st, CvGV(thing))) {
eee00145 632 thing_size(aTHX_ (SV *)CvGV(thing), st);
ebb2c5b9 633 }
a4efdff3 634 if (check_new(st, CvPADLIST(thing))) {
eee00145 635 thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
7ccc7d88 636 }
a4efdff3 637 if (check_new(st, CvOUTSIDE(thing))) {
eee00145 638 thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
7ccc7d88 639 }
66f50dda 640 if (CvISXSUB(thing)) {
641 SV *sv = cv_const_sv((CV *)thing);
642 if (sv) {
eee00145 643 thing_size(aTHX_ sv, st);
66f50dda 644 }
645 } else {
1e5a8ad2 646 op_size(aTHX_ CvSTART(thing), st);
647 op_size(aTHX_ CvROOT(thing), st);
7ccc7d88 648 }
649
9fc9ab86 650 TAG;break;
651 case SVt_PVGV: TAG;
eee00145 652 magic_size(thing, st);
653 st->total_size += sizeof(XPVGV);
654 st->total_size += GvNAMELEN(thing);
78dfb4e7 655#ifdef GvFILE
0bff12d8 656 /* Is there a file? */
99684fd4 657 check_new_and_strlen(st, GvFILE(thing));
78dfb4e7 658#endif
5c2e1b12 659 /* Is there something hanging off the glob? */
660 if (GvGP(thing)) {
a4efdff3 661 if (check_new(st, GvGP(thing))) {
eee00145 662 st->total_size += sizeof(GP);
9fc9ab86 663 {
664 SV *generic_thing;
665 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
eee00145 666 thing_size(aTHX_ generic_thing, st);
9fc9ab86 667 }
668 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
eee00145 669 thing_size(aTHX_ generic_thing, st);
9fc9ab86 670 }
671 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
eee00145 672 thing_size(aTHX_ generic_thing, st);
9fc9ab86 673 }
674 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
eee00145 675 thing_size(aTHX_ generic_thing, st);
9fc9ab86 676 }
677 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
eee00145 678 thing_size(aTHX_ generic_thing, st);
9fc9ab86 679 }
680 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
eee00145 681 thing_size(aTHX_ generic_thing, st);
9fc9ab86 682 }
683 }
5c2e1b12 684 }
685 }
9fc9ab86 686 TAG;break;
687 case SVt_PVFM: TAG;
eee00145 688 st->total_size += sizeof(XPVFM);
689 magic_size(thing, st);
690 st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
a4efdff3 691 if (check_new(st, CvPADLIST(thing))) {
eee00145 692 thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
7ccc7d88 693 }
a4efdff3 694 if (check_new(st, CvOUTSIDE(thing))) {
eee00145 695 thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
7ccc7d88 696 }
697
a4efdff3 698 if (st->go_yell && !st->fm_whine) {
5073b933 699 carp("Devel::Size: Calculated sizes for FMs are incomplete");
a4efdff3 700 st->fm_whine = 1;
ebb2c5b9 701 }
9fc9ab86 702 TAG;break;
703 case SVt_PVIO: TAG;
eee00145 704 st->total_size += sizeof(XPVIO);
705 magic_size(thing, st);
a4efdff3 706 if (check_new(st, (SvPVX_const(thing)))) {
eee00145 707 st->total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
ebb2c5b9 708 }
5073b933 709 /* Some embedded char pointers */
99684fd4 710 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_top_name);
711 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_fmt_name);
712 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_bottom_name);
5073b933 713 /* Throw the GVs on the list to be walked if they're not-null */
714 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
eee00145 715 thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_top_gv, st);
5073b933 716 }
717 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
eee00145 718 thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv, st);
5073b933 719 }
720 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
eee00145 721 thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv, st);
5073b933 722 }
723
724 /* Only go trotting through the IO structures if they're really
725 trottable. If USE_PERLIO is defined we can do this. If
726 not... we can't, so we don't even try */
727#ifdef USE_PERLIO
728 /* Dig into xio_ifp and xio_ofp here */
9fc9ab86 729 warn("Devel::Size: Can't size up perlio layers yet\n");
5073b933 730#endif
9fc9ab86 731 TAG;break;
e98cedbf 732 default:
9fc9ab86 733 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
e98cedbf 734 }
e98cedbf 735}
736
a4efdff3 737static struct state *
738new_state(pTHX)
65db36c0 739{
740 SV *warn_flag;
a4efdff3 741 struct state *st;
742 Newxz(st, 1, struct state);
743 st->go_yell = TRUE;
65db36c0 744 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
a4efdff3 745 st->dangle_whine = st->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
65db36c0 746 }
747 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
a4efdff3 748 st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
65db36c0 749 }
a4efdff3 750 return st;
65db36c0 751}
752
9fc9ab86 753MODULE = Devel::Size PACKAGE = Devel::Size
e98cedbf 754
fea63ffa 755PROTOTYPES: DISABLE
756
eee00145 757UV
a6ea0805 758size(orig_thing)
759 SV *orig_thing
e98cedbf 760CODE:
761{
6a9ad7ec 762 SV *thing = orig_thing;
a4efdff3 763 struct state *st = new_state(aTHX);
ebb2c5b9 764
6a9ad7ec 765 /* If they passed us a reference then dereference it. This is the
766 only way we can check the sizes of arrays and hashes */
b7621729 767#if (PERL_VERSION < 11)
6a9ad7ec 768 if (SvOK(thing) && SvROK(thing)) {
769 thing = SvRV(thing);
770 }
b7621729 771#else
772 if (SvROK(thing)) {
773 thing = SvRV(thing);
774 }
775#endif
776
eee00145 777 thing_size(aTHX_ thing, st);
778 RETVAL = st->total_size;
a4efdff3 779 free_state(st);
6a9ad7ec 780}
781OUTPUT:
782 RETVAL
783
784
eee00145 785UV
6a9ad7ec 786total_size(orig_thing)
787 SV *orig_thing
788CODE:
789{
790 SV *thing = orig_thing;
b7621729 791 /* Array with things we still need to do */
792 AV *pending_array;
b98fcdb9 793 IV size = 0;
a4efdff3 794 struct state *st = new_state(aTHX);
b98fcdb9 795
6a9ad7ec 796 /* Size starts at zero */
797 RETVAL = 0;
798
b7621729 799 pending_array = newAV();
800
8c394e12 801 /* If they passed us a reference then dereference it.
b7621729 802 This is the only way we can check the sizes of arrays and hashes. */
803 if (SvROK(thing)) {
8c394e12 804 thing = SvRV(thing);
b7621729 805 }
6a9ad7ec 806
807 /* Put it on the pending array */
808 av_push(pending_array, thing);
809
810 /* Now just yank things off the end of the array until it's done */
e96acca9 811 while (av_len(pending_array) >= 0) {
812 thing = av_pop(pending_array);
6a9ad7ec 813 /* Process it if we've not seen it */
a4efdff3 814 if (check_new(st, thing)) {
b7621729 815 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
e96acca9 816 /* Is it valid? */
817 if (thing) {
9fc9ab86 818 /* Yes, it is. So let's check the type */
819 switch (SvTYPE(thing)) {
820 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
821 case SVt_PVNV: TAG;
822 if (SvROK(thing))
823 {
824 av_push(pending_array, SvRV(thing));
825 }
826 TAG;break;
b7621729 827#if (PERL_VERSION < 11)
9fc9ab86 828 case SVt_RV: TAG;
b7621729 829#else
9fc9ab86 830 case SVt_IV: TAG;
b7621729 831#endif
832 dbg_printf(("# Found RV\n"));
833 if (SvROK(thing)) {
834 dbg_printf(("# Found RV\n"));
835 av_push(pending_array, SvRV(thing));
836 }
9fc9ab86 837 TAG;break;
838
839 case SVt_PVAV: TAG;
840 {
841 AV *tempAV = (AV *)thing;
842 SV **tempSV;
843
844 dbg_printf(("# Found type AV\n"));
845 /* Quick alias to cut down on casting */
846
847 /* Any elements? */
848 if (av_len(tempAV) != -1) {
849 IV index;
850 /* Run through them all */
851 for (index = 0; index <= av_len(tempAV); index++) {
852 /* Did we get something? */
853 if ((tempSV = av_fetch(tempAV, index, 0))) {
854 /* Was it undef? */
855 if (*tempSV != &PL_sv_undef) {
856 /* Apparently not. Save it for later */
857 av_push(pending_array, *tempSV);
858 }
859 }
860 }
861 }
862 }
863 TAG;break;
864
865 case SVt_PVHV: TAG;
866 dbg_printf(("# Found type HV\n"));
867 /* Is there anything in here? */
868 if (hv_iterinit((HV *)thing)) {
869 HE *temp_he;
870 while ((temp_he = hv_iternext((HV *)thing))) {
871 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
872 }
873 }
874 TAG;break;
875
876 case SVt_PVGV: TAG;
877 dbg_printf(("# Found type GV\n"));
878 /* Run through all the pieces and push the ones with bits */
879 if (GvSV(thing)) {
880 av_push(pending_array, (SV *)GvSV(thing));
881 }
882 if (GvFORM(thing)) {
883 av_push(pending_array, (SV *)GvFORM(thing));
884 }
885 if (GvAV(thing)) {
886 av_push(pending_array, (SV *)GvAV(thing));
887 }
888 if (GvHV(thing)) {
889 av_push(pending_array, (SV *)GvHV(thing));
890 }
891 if (GvCV(thing)) {
892 av_push(pending_array, (SV *)GvCV(thing));
893 }
894 TAG;break;
895 default:
896 TAG;break;
897 }
6a9ad7ec 898 }
b98fcdb9 899
eee00145 900 thing_size(aTHX_ thing, st);
b7621729 901 } else {
902 /* check_new() returned false: */
903#ifdef DEVEL_SIZE_DEBUGGING
904 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
905 else printf("# Ignore non-sv 0x%x\n", sv);
906#endif
6a9ad7ec 907 }
b7621729 908 } /* end while */
e9716740 909
eee00145 910 RETVAL = st->total_size;
a4efdff3 911 free_state(st);
6a9ad7ec 912 SvREFCNT_dec(pending_array);
e98cedbf 913}
914OUTPUT:
915 RETVAL
6a9ad7ec 916