1 #define PERL_NO_GET_CONTEXT
8 /* Not yet in ppport.h */
10 # define CvISXSUB(cv) (CvXSUB(cv) ? TRUE : FALSE)
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. */
19 # define TRY_TO_CATCH_SEGV __try
20 # define CAUGHT_EXCEPTION __except(EXCEPTION EXCEPTION_EXECUTE_HANDLER)
22 # define TRY_TO_CATCH_SEGV if(1)
23 # define CAUGHT_EXCEPTION else
27 # define __attribute__(x)
30 #if 0 && defined(DEBUGGING)
31 #define dbg_printf(x) printf x
36 #define TAG /* printf( "# %s(%d)\n", __FILE__, __LINE__ ) */
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) */
46 #define ALIGN_BITS ( sizeof(void*) >> 1 )
48 #define LEAF_BITS (16 - BYTE_BITS)
49 #define LEAF_MASK 0x1FFF
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. */
62 typedef struct state TRACKING;
65 Checks to see if thing is in the bitstring.
66 Returns true or false, and
67 notes thing in the segmented bitstring.
70 check_new(TRACKING *tv, const void *const p) {
71 unsigned int bits = 8 * sizeof(void*);
72 const size_t raw_p = PTR2nat(p);
73 /* This effectively rotates the value right by the number of low always-0
74 bits in an aligned pointer. The assmption is that most (if not all)
75 pointers are aligned, and these will be in the same chain of nodes
76 (and hence hot in the cache) but we can still deal with any unaligned
79 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
80 const U8 this_bit = 1 << (cooked_p & 0x7);
84 void **tv_p = (void **) (tv->tracking);
87 if (NULL == p) return FALSE;
89 const char c = *(const char *)p;
93 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
99 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
101 /* First level is always present. */
103 i = (unsigned int)((cooked_p >> bits) & 0xFF);
105 Newxz(tv_p[i], 256, void *);
106 tv_p = (void **)(tv_p[i]);
108 } while (bits > LEAF_BITS + BYTE_BITS);
109 /* bits now 16 always */
111 leaf_p = (U8 **)tv_p;
112 i = (unsigned int)((cooked_p >> bits) & 0xFF);
114 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
119 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
121 if(leaf[i] & this_bit)
129 free_tracking_at(void **tv, int level)
137 free_tracking_at(tv[i], level);
151 free_tracking(TRACKING *tv)
153 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
154 free_tracking_at((void **)tv->tracking, top_level);
158 static UV thing_size(pTHX_ const SV *const, TRACKING *);
175 cc_opclass(const OP * const o)
181 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
183 if (o->op_type == OP_SASSIGN)
184 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
187 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
191 if ((o->op_type == OP_TRANS)) {
195 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
220 case OA_PVOP_OR_SVOP: TAG;
222 * Character translations (tr///) are usually a PVOP, keeping a
223 * pointer to a table of shorts used to look up translations.
224 * Under utf8, however, a simple table isn't practical; instead,
225 * the OP is an SVOP, and the SV is a reference to a swash
226 * (i.e., an RV pointing to an HV).
228 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
229 ? OPc_SVOP : OPc_PVOP;
237 case OA_BASEOP_OR_UNOP: TAG;
239 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
240 * whether parens were seen. perly.y uses OPf_SPECIAL to
241 * signal whether a BASEOP had empty parens or none.
242 * Some other UNOPs are created later, though, so the best
243 * test is OPf_KIDS, which is set in newUNOP.
245 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
247 case OA_FILESTATOP: TAG;
249 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
250 * the OPf_REF flag to distinguish between OP types instead of the
251 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
252 * return OPc_UNOP so that walkoptree can find our children. If
253 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
254 * (no argument to the operator) it's an OP; with OPf_REF set it's
255 * an SVOP (and op_sv is the GV for the filehandle argument).
257 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
259 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
261 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
263 case OA_LOOPEXOP: TAG;
265 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
266 * label was omitted (in which case it's a BASEOP) or else a term was
267 * seen. In this last case, all except goto are definitely PVOP but
268 * goto is either a PVOP (with an ordinary constant label), an UNOP
269 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
270 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
273 if (o->op_flags & OPf_STACKED)
275 else if (o->op_flags & OPf_SPECIAL)
280 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
281 PL_op_name[o->op_type]);
292 /* Figure out how much magic is attached to the SV and return the
294 IV magic_size(const SV * const thing, TRACKING *tv) {
296 MAGIC *magic_pointer;
299 if (!SvMAGIC(thing)) {
304 /* Get the base magic pointer */
305 magic_pointer = SvMAGIC(thing);
307 /* Have we seen the magic pointer? */
308 while (magic_pointer && check_new(tv, magic_pointer)) {
309 total_size += sizeof(MAGIC);
312 /* Have we seen the magic vtable? */
313 if (magic_pointer->mg_virtual &&
314 check_new(tv, magic_pointer->mg_virtual)) {
315 total_size += sizeof(MGVTBL);
318 /* Get the next in the chain */
319 magic_pointer = magic_pointer->mg_moremagic;
322 if (tv->dangle_whine)
323 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
329 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
332 total_size += sizeof(REGEXP);
333 #if (PERL_VERSION < 11)
334 /* Note the size of the paren offset thing */
335 total_size += sizeof(I32) * baseregex->nparens * 2;
336 total_size += strlen(baseregex->precomp);
338 total_size += sizeof(struct regexp);
339 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
340 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
342 if (tv->go_yell && !tv->regex_whine) {
343 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
351 op_size(pTHX_ const OP * const baseop, TRACKING *tv) {
355 if (check_new(tv, baseop->op_next)) {
356 total_size += op_size(aTHX_ baseop->op_next, tv);
359 switch (cc_opclass(baseop)) {
360 case OPc_BASEOP: TAG;
361 total_size += sizeof(struct op);
364 total_size += sizeof(struct unop);
365 if (check_new(tv, cUNOPx(baseop)->op_first)) {
366 total_size += op_size(aTHX_ cUNOPx(baseop)->op_first, tv);
370 total_size += sizeof(struct binop);
371 if (check_new(tv, cBINOPx(baseop)->op_first)) {
372 total_size += op_size(aTHX_ cBINOPx(baseop)->op_first, tv);
374 if (check_new(tv, cBINOPx(baseop)->op_last)) {
375 total_size += op_size(aTHX_ cBINOPx(baseop)->op_last, tv);
379 total_size += sizeof(struct logop);
380 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
381 total_size += op_size(aTHX_ cBINOPx(baseop)->op_first, tv);
383 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
384 total_size += op_size(aTHX_ cLOGOPx(baseop)->op_other, tv);
387 case OPc_LISTOP: TAG;
388 total_size += sizeof(struct listop);
389 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
390 total_size += op_size(aTHX_ cLISTOPx(baseop)->op_first, tv);
392 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
393 total_size += op_size(aTHX_ cLISTOPx(baseop)->op_last, tv);
397 total_size += sizeof(struct pmop);
398 if (check_new(tv, cPMOPx(baseop)->op_first)) {
399 total_size += op_size(aTHX_ cPMOPx(baseop)->op_first, tv);
401 if (check_new(tv, cPMOPx(baseop)->op_last)) {
402 total_size += op_size(aTHX_ cPMOPx(baseop)->op_last, tv);
404 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
405 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
406 total_size += op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, tv);
408 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
409 total_size += op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, tv);
411 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
412 total_size += op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, tv);
415 /* This is defined away in perl 5.8.x, but it is in there for
418 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
419 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
422 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
423 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
428 total_size += sizeof(struct pmop);
429 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
430 total_size += thing_size(aTHX_ cSVOPx(baseop)->op_sv, tv);
434 total_size += sizeof(struct padop);
437 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
438 total_size += strlen(cPVOPx(baseop)->op_pv);
441 total_size += sizeof(struct loop);
442 if (check_new(tv, cLOOPx(baseop)->op_first)) {
443 total_size += op_size(aTHX_ cLOOPx(baseop)->op_first, tv);
445 if (check_new(tv, cLOOPx(baseop)->op_last)) {
446 total_size += op_size(aTHX_ cLOOPx(baseop)->op_last, tv);
448 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
449 total_size += op_size(aTHX_ cLOOPx(baseop)->op_redoop, tv);
451 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
452 total_size += op_size(aTHX_ cLOOPx(baseop)->op_nextop, tv);
454 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
455 total_size += op_size(aTHX_ cLOOPx(baseop)->op_lastop, tv);
462 basecop = (COP *)baseop;
463 total_size += sizeof(struct cop);
465 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
466 Eliminate cop_label from struct cop by storing a label as the first
467 entry in the hints hash. Most statements don't have labels, so this
468 will save memory. Not sure how much.
469 The check below will be incorrect fail on bleadperls
470 before 5.11 @33656, but later than 5.10, producing slightly too
471 small memory sizes on these Perls. */
472 #if (PERL_VERSION < 11)
473 if (check_new(tv, basecop->cop_label)) {
474 total_size += strlen(basecop->cop_label);
478 if (check_new(tv, basecop->cop_file)) {
479 total_size += strlen(basecop->cop_file);
481 if (check_new(tv, basecop->cop_stashpv)) {
482 total_size += strlen(basecop->cop_stashpv);
485 if (check_new(tv, basecop->cop_stash)) {
486 total_size += thing_size(aTHX_ (SV *)basecop->cop_stash, tv);
488 if (check_new(tv, basecop->cop_filegv)) {
489 total_size += thing_size(aTHX_ (SV *)basecop->cop_filegv, tv);
500 if (tv->dangle_whine)
501 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
506 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
507 # define NEW_HEAD_LAYOUT
511 thing_size(pTHX_ const SV * const orig_thing, TRACKING *tv) {
512 const SV *thing = orig_thing;
513 UV total_size = sizeof(SV);
515 switch (SvTYPE(thing)) {
519 /* Just a plain integer. This will be differently sized depending
520 on whether purify's been compiled in */
522 #ifndef NEW_HEAD_LAYOUT
524 total_size += sizeof(sizeof(XPVIV));
526 total_size += sizeof(IV);
530 /* Is it a float? Like the int, it depends on purify */
533 total_size += sizeof(sizeof(XPVNV));
535 total_size += sizeof(NV);
538 #if (PERL_VERSION < 11)
539 /* Is it a reference? */
541 #ifndef NEW_HEAD_LAYOUT
542 total_size += sizeof(XRV);
546 /* How about a plain string? In which case we need to add in how
547 much has been allocated */
549 total_size += sizeof(XPV);
550 #if (PERL_VERSION < 11)
551 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), tv) : SvLEN(thing);
553 total_size += SvLEN(thing);
556 /* A string with an integer part? */
558 total_size += sizeof(XPVIV);
559 #if (PERL_VERSION < 11)
560 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), tv) : SvLEN(thing);
562 total_size += SvLEN(thing);
565 total_size += SvIVX(thing);
568 /* A scalar/string/reference with a float part? */
570 total_size += sizeof(XPVNV);
571 #if (PERL_VERSION < 11)
572 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), tv) : SvLEN(thing);
574 total_size += SvLEN(thing);
578 total_size += sizeof(XPVMG);
579 #if (PERL_VERSION < 11)
580 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), tv) : SvLEN(thing);
582 total_size += SvLEN(thing);
584 total_size += magic_size(thing, tv);
586 #if PERL_VERSION <= 8
588 total_size += sizeof(XPVBM);
589 #if (PERL_VERSION < 11)
590 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), tv) : SvLEN(thing);
592 total_size += SvLEN(thing);
594 total_size += magic_size(thing, tv);
598 total_size += sizeof(XPVLV);
599 #if (PERL_VERSION < 11)
600 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), tv) : SvLEN(thing);
602 total_size += SvLEN(thing);
604 total_size += magic_size(thing, tv);
606 /* How much space is dedicated to the array? Not counting the
607 elements in the array, mind, just the array itself */
609 total_size += sizeof(XPVAV);
610 /* Is there anything in the array? */
611 if (AvMAX(thing) != -1) {
612 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
613 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
614 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
616 /* Add in the bits on the other side of the beginning */
618 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
619 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
621 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
622 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
623 if (AvALLOC(thing) != 0) {
624 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
626 #if (PERL_VERSION < 9)
627 /* Is there something hanging off the arylen element?
628 Post 5.9.something this is stored in magic, so will be found there,
629 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
630 complain about AvARYLEN() passing thing to it. */
631 if (AvARYLEN(thing)) {
632 if (check_new(tv, AvARYLEN(thing))) {
633 total_size += thing_size(aTHX_ AvARYLEN(thing), tv);
637 total_size += magic_size(thing, tv);
640 /* First the base struct */
641 total_size += sizeof(XPVHV);
642 /* Now the array of buckets */
643 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
644 /* Now walk the bucket chain */
645 if (HvARRAY(thing)) {
648 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
649 cur_entry = *(HvARRAY(thing) + cur_bucket);
651 total_size += sizeof(HE);
652 if (cur_entry->hent_hek) {
653 /* Hash keys can be shared. Have we seen this before? */
654 if (check_new(tv, cur_entry->hent_hek)) {
655 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
658 cur_entry = cur_entry->hent_next;
662 total_size += magic_size(thing, tv);
665 total_size += sizeof(XPVCV);
666 total_size += magic_size(thing, tv);
668 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
669 if (check_new(tv, CvSTASH(thing))) {
670 total_size += thing_size(aTHX_ (SV *)CvSTASH(thing), tv);
672 if (check_new(tv, SvSTASH(thing))) {
673 total_size += thing_size(aTHX_ (SV *)SvSTASH(thing), tv);
675 if (check_new(tv, CvGV(thing))) {
676 total_size += thing_size(aTHX_ (SV *)CvGV(thing), tv);
678 if (check_new(tv, CvPADLIST(thing))) {
679 total_size += thing_size(aTHX_ (SV *)CvPADLIST(thing), tv);
681 if (check_new(tv, CvOUTSIDE(thing))) {
682 total_size += thing_size(aTHX_ (SV *)CvOUTSIDE(thing), tv);
684 if (CvISXSUB(thing)) {
685 SV *sv = cv_const_sv((CV *)thing);
687 total_size += thing_size(aTHX_ sv, tv);
690 if (check_new(tv, CvSTART(thing))) {
691 total_size += op_size(aTHX_ CvSTART(thing), tv);
693 if (check_new(tv, CvROOT(thing))) {
694 total_size += op_size(aTHX_ CvROOT(thing), tv);
700 total_size += magic_size(thing, tv);
701 total_size += sizeof(XPVGV);
702 total_size += GvNAMELEN(thing);
704 /* Is there a file? */
706 if (check_new(tv, GvFILE(thing))) {
707 total_size += strlen(GvFILE(thing));
711 /* Is there something hanging off the glob? */
713 if (check_new(tv, GvGP(thing))) {
714 total_size += sizeof(GP);
717 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
718 total_size += thing_size(aTHX_ generic_thing, tv);
720 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
721 total_size += thing_size(aTHX_ generic_thing, tv);
723 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
724 total_size += thing_size(aTHX_ generic_thing, tv);
726 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
727 total_size += thing_size(aTHX_ generic_thing, tv);
729 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
730 total_size += thing_size(aTHX_ generic_thing, tv);
732 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
733 total_size += thing_size(aTHX_ generic_thing, tv);
740 total_size += sizeof(XPVFM);
741 total_size += magic_size(thing, tv);
742 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
743 if (check_new(tv, CvPADLIST(thing))) {
744 total_size += thing_size(aTHX_ (SV *)CvPADLIST(thing), tv);
746 if (check_new(tv, CvOUTSIDE(thing))) {
747 total_size += thing_size(aTHX_ (SV *)CvOUTSIDE(thing), tv);
750 if (tv->go_yell && !tv->fm_whine) {
751 carp("Devel::Size: Calculated sizes for FMs are incomplete");
756 total_size += sizeof(XPVIO);
757 total_size += magic_size(thing, tv);
758 if (check_new(tv, (SvPVX_const(thing)))) {
759 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
761 /* Some embedded char pointers */
762 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
763 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
765 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
766 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
768 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
769 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
771 /* Throw the GVs on the list to be walked if they're not-null */
772 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
773 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
776 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
777 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
780 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
781 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
785 /* Only go trotting through the IO structures if they're really
786 trottable. If USE_PERLIO is defined we can do this. If
787 not... we can't, so we don't even try */
789 /* Dig into xio_ifp and xio_ofp here */
790 warn("Devel::Size: Can't size up perlio layers yet\n");
794 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
804 Newxz(tv, 1, TRACKING);
806 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
807 tv->dangle_whine = tv->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
809 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
810 tv->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
815 MODULE = Devel::Size PACKAGE = Devel::Size
824 SV *thing = orig_thing;
825 TRACKING *tv = new_tracking(aTHX);
827 /* If they passed us a reference then dereference it. This is the
828 only way we can check the sizes of arrays and hashes */
829 #if (PERL_VERSION < 11)
830 if (SvOK(thing) && SvROK(thing)) {
839 RETVAL = thing_size(aTHX_ thing, tv);
847 total_size(orig_thing)
851 SV *thing = orig_thing;
852 /* Array with things we still need to do */
855 TRACKING *tv = new_tracking(aTHX);
857 /* Size starts at zero */
860 pending_array = newAV();
862 /* We cannot push HV/AV directly, only the RV. So deref it
863 later (see below for "*** dereference later") and adjust here for
865 This is the only way we can check the sizes of arrays and hashes. */
867 RETVAL -= thing_size(aTHX_ thing, NULL);
870 /* Put it on the pending array */
871 av_push(pending_array, thing);
873 /* Now just yank things off the end of the array until it's done */
874 while (av_len(pending_array) >= 0) {
875 thing = av_pop(pending_array);
876 /* Process it if we've not seen it */
877 if (check_new(tv, thing)) {
878 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
881 /* Yes, it is. So let's check the type */
882 switch (SvTYPE(thing)) {
883 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
887 av_push(pending_array, SvRV(thing));
891 /* this is the "*** dereference later" part - see above */
892 #if (PERL_VERSION < 11)
897 dbg_printf(("# Found RV\n"));
899 dbg_printf(("# Found RV\n"));
900 av_push(pending_array, SvRV(thing));
906 AV *tempAV = (AV *)thing;
909 dbg_printf(("# Found type AV\n"));
910 /* Quick alias to cut down on casting */
913 if (av_len(tempAV) != -1) {
915 /* Run through them all */
916 for (index = 0; index <= av_len(tempAV); index++) {
917 /* Did we get something? */
918 if ((tempSV = av_fetch(tempAV, index, 0))) {
920 if (*tempSV != &PL_sv_undef) {
921 /* Apparently not. Save it for later */
922 av_push(pending_array, *tempSV);
931 dbg_printf(("# Found type HV\n"));
932 /* Is there anything in here? */
933 if (hv_iterinit((HV *)thing)) {
935 while ((temp_he = hv_iternext((HV *)thing))) {
936 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
942 dbg_printf(("# Found type GV\n"));
943 /* Run through all the pieces and push the ones with bits */
945 av_push(pending_array, (SV *)GvSV(thing));
948 av_push(pending_array, (SV *)GvFORM(thing));
951 av_push(pending_array, (SV *)GvAV(thing));
954 av_push(pending_array, (SV *)GvHV(thing));
957 av_push(pending_array, (SV *)GvCV(thing));
965 size = thing_size(aTHX_ thing, tv);
968 /* check_new() returned false: */
969 #ifdef DEVEL_SIZE_DEBUGGING
970 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
971 else printf("# Ignore non-sv 0x%x\n", sv);
977 SvREFCNT_dec(pending_array);