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