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. */
63 Checks to see if thing is in the bitstring.
64 Returns true or false, and
65 notes thing in the segmented bitstring.
68 check_new(struct state *st, const void *const p) {
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
77 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
78 const U8 this_bit = 1 << (cooked_p & 0x7);
82 void **tv_p = (void **) (st->tracking);
85 if (NULL == p) return FALSE;
87 const char c = *(const char *)p;
91 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
97 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
99 /* First level is always present. */
101 i = (unsigned int)((cooked_p >> bits) & 0xFF);
103 Newxz(tv_p[i], 256, void *);
104 tv_p = (void **)(tv_p[i]);
106 } while (bits > LEAF_BITS + BYTE_BITS);
107 /* bits now 16 always */
109 leaf_p = (U8 **)tv_p;
110 i = (unsigned int)((cooked_p >> bits) & 0xFF);
112 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
117 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
119 if(leaf[i] & this_bit)
127 free_tracking_at(void **tv, int level)
135 free_tracking_at(tv[i], level);
149 free_state(struct state *st)
151 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
152 free_tracking_at((void **)st->tracking, top_level);
156 static UV thing_size(pTHX_ const SV *const, struct state *);
173 cc_opclass(const OP * const o)
179 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
181 if (o->op_type == OP_SASSIGN)
182 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
185 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
189 if ((o->op_type == OP_TRANS)) {
193 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
218 case OA_PVOP_OR_SVOP: TAG;
220 * Character translations (tr///) are usually a PVOP, keeping a
221 * pointer to a table of shorts used to look up translations.
222 * Under utf8, however, a simple table isn't practical; instead,
223 * the OP is an SVOP, and the SV is a reference to a swash
224 * (i.e., an RV pointing to an HV).
226 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
227 ? OPc_SVOP : OPc_PVOP;
235 case OA_BASEOP_OR_UNOP: TAG;
237 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
238 * whether parens were seen. perly.y uses OPf_SPECIAL to
239 * signal whether a BASEOP had empty parens or none.
240 * Some other UNOPs are created later, though, so the best
241 * test is OPf_KIDS, which is set in newUNOP.
243 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
245 case OA_FILESTATOP: TAG;
247 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
248 * the OPf_REF flag to distinguish between OP types instead of the
249 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
250 * return OPc_UNOP so that walkoptree can find our children. If
251 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
252 * (no argument to the operator) it's an OP; with OPf_REF set it's
253 * an SVOP (and op_sv is the GV for the filehandle argument).
255 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
257 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
259 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
261 case OA_LOOPEXOP: TAG;
263 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
264 * label was omitted (in which case it's a BASEOP) or else a term was
265 * seen. In this last case, all except goto are definitely PVOP but
266 * goto is either a PVOP (with an ordinary constant label), an UNOP
267 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
268 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
271 if (o->op_flags & OPf_STACKED)
273 else if (o->op_flags & OPf_SPECIAL)
278 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
279 PL_op_name[o->op_type]);
290 /* Figure out how much magic is attached to the SV and return the
292 IV magic_size(const SV * const thing, struct state *st) {
294 MAGIC *magic_pointer;
297 if (!SvMAGIC(thing)) {
302 /* Get the base magic pointer */
303 magic_pointer = SvMAGIC(thing);
305 /* Have we seen the magic pointer? */
306 while (magic_pointer && check_new(st, magic_pointer)) {
307 total_size += sizeof(MAGIC);
310 /* Have we seen the magic vtable? */
311 if (magic_pointer->mg_virtual &&
312 check_new(st, magic_pointer->mg_virtual)) {
313 total_size += sizeof(MGVTBL);
316 /* Get the next in the chain */
317 magic_pointer = magic_pointer->mg_moremagic;
320 if (st->dangle_whine)
321 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
327 UV regex_size(const REGEXP * const baseregex, struct state *st) {
330 total_size += sizeof(REGEXP);
331 #if (PERL_VERSION < 11)
332 /* Note the size of the paren offset thing */
333 total_size += sizeof(I32) * baseregex->nparens * 2;
334 total_size += strlen(baseregex->precomp);
336 total_size += sizeof(struct regexp);
337 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
338 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
340 if (st->go_yell && !st->regex_whine) {
341 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
349 op_size(pTHX_ const OP * const baseop, struct state *st) {
353 if (check_new(st, baseop->op_next)) {
354 total_size += op_size(aTHX_ baseop->op_next, st);
357 switch (cc_opclass(baseop)) {
358 case OPc_BASEOP: TAG;
359 total_size += sizeof(struct op);
362 total_size += sizeof(struct unop);
363 if (check_new(st, cUNOPx(baseop)->op_first)) {
364 total_size += op_size(aTHX_ cUNOPx(baseop)->op_first, st);
368 total_size += sizeof(struct binop);
369 if (check_new(st, cBINOPx(baseop)->op_first)) {
370 total_size += op_size(aTHX_ cBINOPx(baseop)->op_first, st);
372 if (check_new(st, cBINOPx(baseop)->op_last)) {
373 total_size += op_size(aTHX_ cBINOPx(baseop)->op_last, st);
377 total_size += sizeof(struct logop);
378 if (check_new(st, cLOGOPx(baseop)->op_first)) {
379 total_size += op_size(aTHX_ cBINOPx(baseop)->op_first, st);
381 if (check_new(st, cLOGOPx(baseop)->op_other)) {
382 total_size += op_size(aTHX_ cLOGOPx(baseop)->op_other, st);
385 case OPc_LISTOP: TAG;
386 total_size += sizeof(struct listop);
387 if (check_new(st, cLISTOPx(baseop)->op_first)) {
388 total_size += op_size(aTHX_ cLISTOPx(baseop)->op_first, st);
390 if (check_new(st, cLISTOPx(baseop)->op_last)) {
391 total_size += op_size(aTHX_ cLISTOPx(baseop)->op_last, st);
395 total_size += sizeof(struct pmop);
396 if (check_new(st, cPMOPx(baseop)->op_first)) {
397 total_size += op_size(aTHX_ cPMOPx(baseop)->op_first, st);
399 if (check_new(st, cPMOPx(baseop)->op_last)) {
400 total_size += op_size(aTHX_ cPMOPx(baseop)->op_last, st);
402 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
403 if (check_new(st, cPMOPx(baseop)->op_pmreplroot)) {
404 total_size += op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, st);
406 if (check_new(st, cPMOPx(baseop)->op_pmreplstart)) {
407 total_size += op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, st);
409 if (check_new(st, cPMOPx(baseop)->op_pmnext)) {
410 total_size += op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, st);
413 /* This is defined away in perl 5.8.x, but it is in there for
416 if (check_new(st, PM_GETRE((cPMOPx(baseop))))) {
417 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), st);
420 if (check_new(st, cPMOPx(baseop)->op_pmregexp)) {
421 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, st);
426 total_size += sizeof(struct pmop);
427 if (check_new(st, cSVOPx(baseop)->op_sv)) {
428 total_size += thing_size(aTHX_ cSVOPx(baseop)->op_sv, st);
432 total_size += sizeof(struct padop);
435 if (check_new(st, cPVOPx(baseop)->op_pv)) {
436 total_size += strlen(cPVOPx(baseop)->op_pv);
439 total_size += sizeof(struct loop);
440 if (check_new(st, cLOOPx(baseop)->op_first)) {
441 total_size += op_size(aTHX_ cLOOPx(baseop)->op_first, st);
443 if (check_new(st, cLOOPx(baseop)->op_last)) {
444 total_size += op_size(aTHX_ cLOOPx(baseop)->op_last, st);
446 if (check_new(st, cLOOPx(baseop)->op_redoop)) {
447 total_size += op_size(aTHX_ cLOOPx(baseop)->op_redoop, st);
449 if (check_new(st, cLOOPx(baseop)->op_nextop)) {
450 total_size += op_size(aTHX_ cLOOPx(baseop)->op_nextop, st);
452 if (check_new(st, cLOOPx(baseop)->op_lastop)) {
453 total_size += op_size(aTHX_ cLOOPx(baseop)->op_lastop, st);
460 basecop = (COP *)baseop;
461 total_size += sizeof(struct cop);
463 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
464 Eliminate cop_label from struct cop by storing a label as the first
465 entry in the hints hash. Most statements don't have labels, so this
466 will save memory. Not sure how much.
467 The check below will be incorrect fail on bleadperls
468 before 5.11 @33656, but later than 5.10, producing slightly too
469 small memory sizes on these Perls. */
470 #if (PERL_VERSION < 11)
471 if (check_new(st, basecop->cop_label)) {
472 total_size += strlen(basecop->cop_label);
476 if (check_new(st, basecop->cop_file)) {
477 total_size += strlen(basecop->cop_file);
479 if (check_new(st, basecop->cop_stashpv)) {
480 total_size += strlen(basecop->cop_stashpv);
483 if (check_new(st, basecop->cop_stash)) {
484 total_size += thing_size(aTHX_ (SV *)basecop->cop_stash, st);
486 if (check_new(st, basecop->cop_filegv)) {
487 total_size += thing_size(aTHX_ (SV *)basecop->cop_filegv, st);
498 if (st->dangle_whine)
499 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
504 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
505 # define NEW_HEAD_LAYOUT
509 thing_size(pTHX_ const SV * const orig_thing, struct state *st) {
510 const SV *thing = orig_thing;
511 UV total_size = sizeof(SV);
513 switch (SvTYPE(thing)) {
517 /* Just a plain integer. This will be differently sized depending
518 on whether purify's been compiled in */
520 #ifndef NEW_HEAD_LAYOUT
522 total_size += sizeof(sizeof(XPVIV));
524 total_size += sizeof(IV);
528 /* Is it a float? Like the int, it depends on purify */
531 total_size += sizeof(sizeof(XPVNV));
533 total_size += sizeof(NV);
536 #if (PERL_VERSION < 11)
537 /* Is it a reference? */
539 #ifndef NEW_HEAD_LAYOUT
540 total_size += sizeof(XRV);
544 /* How about a plain string? In which case we need to add in how
545 much has been allocated */
547 total_size += sizeof(XPV);
548 #if (PERL_VERSION < 11)
549 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), st) : SvLEN(thing);
551 total_size += SvLEN(thing);
554 /* A string with an integer part? */
556 total_size += sizeof(XPVIV);
557 #if (PERL_VERSION < 11)
558 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), st) : SvLEN(thing);
560 total_size += SvLEN(thing);
563 total_size += SvIVX(thing);
566 /* A scalar/string/reference with a float part? */
568 total_size += sizeof(XPVNV);
569 #if (PERL_VERSION < 11)
570 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), st) : SvLEN(thing);
572 total_size += SvLEN(thing);
576 total_size += sizeof(XPVMG);
577 #if (PERL_VERSION < 11)
578 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), st) : SvLEN(thing);
580 total_size += SvLEN(thing);
582 total_size += magic_size(thing, st);
584 #if PERL_VERSION <= 8
586 total_size += sizeof(XPVBM);
587 #if (PERL_VERSION < 11)
588 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), st) : SvLEN(thing);
590 total_size += SvLEN(thing);
592 total_size += magic_size(thing, st);
596 total_size += sizeof(XPVLV);
597 #if (PERL_VERSION < 11)
598 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV(thing), st) : SvLEN(thing);
600 total_size += SvLEN(thing);
602 total_size += magic_size(thing, st);
604 /* How much space is dedicated to the array? Not counting the
605 elements in the array, mind, just the array itself */
607 total_size += sizeof(XPVAV);
608 /* Is there anything in the array? */
609 if (AvMAX(thing) != -1) {
610 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
611 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
612 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
614 /* Add in the bits on the other side of the beginning */
616 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
617 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
619 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
620 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
621 if (AvALLOC(thing) != 0) {
622 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
624 #if (PERL_VERSION < 9)
625 /* Is there something hanging off the arylen element?
626 Post 5.9.something this is stored in magic, so will be found there,
627 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
628 complain about AvARYLEN() passing thing to it. */
629 if (AvARYLEN(thing)) {
630 if (check_new(st, AvARYLEN(thing))) {
631 total_size += thing_size(aTHX_ AvARYLEN(thing), st);
635 total_size += magic_size(thing, st);
638 /* First the base struct */
639 total_size += sizeof(XPVHV);
640 /* Now the array of buckets */
641 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
642 /* Now walk the bucket chain */
643 if (HvARRAY(thing)) {
646 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
647 cur_entry = *(HvARRAY(thing) + cur_bucket);
649 total_size += sizeof(HE);
650 if (cur_entry->hent_hek) {
651 /* Hash keys can be shared. Have we seen this before? */
652 if (check_new(st, cur_entry->hent_hek)) {
653 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
656 cur_entry = cur_entry->hent_next;
660 total_size += magic_size(thing, st);
663 total_size += sizeof(XPVCV);
664 total_size += magic_size(thing, st);
666 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
667 if (check_new(st, CvSTASH(thing))) {
668 total_size += thing_size(aTHX_ (SV *)CvSTASH(thing), st);
670 if (check_new(st, SvSTASH(thing))) {
671 total_size += thing_size(aTHX_ (SV *)SvSTASH(thing), st);
673 if (check_new(st, CvGV(thing))) {
674 total_size += thing_size(aTHX_ (SV *)CvGV(thing), st);
676 if (check_new(st, CvPADLIST(thing))) {
677 total_size += thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
679 if (check_new(st, CvOUTSIDE(thing))) {
680 total_size += thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
682 if (CvISXSUB(thing)) {
683 SV *sv = cv_const_sv((CV *)thing);
685 total_size += thing_size(aTHX_ sv, st);
688 if (check_new(st, CvSTART(thing))) {
689 total_size += op_size(aTHX_ CvSTART(thing), st);
691 if (check_new(st, CvROOT(thing))) {
692 total_size += op_size(aTHX_ CvROOT(thing), st);
698 total_size += magic_size(thing, st);
699 total_size += sizeof(XPVGV);
700 total_size += GvNAMELEN(thing);
702 /* Is there a file? */
704 if (check_new(st, GvFILE(thing))) {
705 total_size += strlen(GvFILE(thing));
709 /* Is there something hanging off the glob? */
711 if (check_new(st, GvGP(thing))) {
712 total_size += sizeof(GP);
715 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
716 total_size += thing_size(aTHX_ generic_thing, st);
718 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
719 total_size += thing_size(aTHX_ generic_thing, st);
721 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
722 total_size += thing_size(aTHX_ generic_thing, st);
724 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
725 total_size += thing_size(aTHX_ generic_thing, st);
727 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
728 total_size += thing_size(aTHX_ generic_thing, st);
730 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
731 total_size += thing_size(aTHX_ generic_thing, st);
738 total_size += sizeof(XPVFM);
739 total_size += magic_size(thing, st);
740 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
741 if (check_new(st, CvPADLIST(thing))) {
742 total_size += thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
744 if (check_new(st, CvOUTSIDE(thing))) {
745 total_size += thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
748 if (st->go_yell && !st->fm_whine) {
749 carp("Devel::Size: Calculated sizes for FMs are incomplete");
754 total_size += sizeof(XPVIO);
755 total_size += magic_size(thing, st);
756 if (check_new(st, (SvPVX_const(thing)))) {
757 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
759 /* Some embedded char pointers */
760 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_top_name)) {
761 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
763 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
764 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
766 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
767 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
769 /* Throw the GVs on the list to be walked if they're not-null */
770 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
771 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
774 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
775 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
778 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
779 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
783 /* Only go trotting through the IO structures if they're really
784 trottable. If USE_PERLIO is defined we can do this. If
785 not... we can't, so we don't even try */
787 /* Dig into xio_ifp and xio_ofp here */
788 warn("Devel::Size: Can't size up perlio layers yet\n");
792 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
797 static struct state *
802 Newxz(st, 1, struct state);
804 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
805 st->dangle_whine = st->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
807 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
808 st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
813 MODULE = Devel::Size PACKAGE = Devel::Size
822 SV *thing = orig_thing;
823 struct state *st = new_state(aTHX);
825 /* If they passed us a reference then dereference it. This is the
826 only way we can check the sizes of arrays and hashes */
827 #if (PERL_VERSION < 11)
828 if (SvOK(thing) && SvROK(thing)) {
837 RETVAL = thing_size(aTHX_ thing, st);
845 total_size(orig_thing)
849 SV *thing = orig_thing;
850 /* Array with things we still need to do */
853 struct state *st = new_state(aTHX);
855 /* Size starts at zero */
858 pending_array = newAV();
860 /* We cannot push HV/AV directly, only the RV. So deref it
861 later (see below for "*** dereference later") and adjust here for
863 This is the only way we can check the sizes of arrays and hashes. */
865 RETVAL -= thing_size(aTHX_ thing, NULL);
868 /* Put it on the pending array */
869 av_push(pending_array, thing);
871 /* Now just yank things off the end of the array until it's done */
872 while (av_len(pending_array) >= 0) {
873 thing = av_pop(pending_array);
874 /* Process it if we've not seen it */
875 if (check_new(st, thing)) {
876 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
879 /* Yes, it is. So let's check the type */
880 switch (SvTYPE(thing)) {
881 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
885 av_push(pending_array, SvRV(thing));
889 /* this is the "*** dereference later" part - see above */
890 #if (PERL_VERSION < 11)
895 dbg_printf(("# Found RV\n"));
897 dbg_printf(("# Found RV\n"));
898 av_push(pending_array, SvRV(thing));
904 AV *tempAV = (AV *)thing;
907 dbg_printf(("# Found type AV\n"));
908 /* Quick alias to cut down on casting */
911 if (av_len(tempAV) != -1) {
913 /* Run through them all */
914 for (index = 0; index <= av_len(tempAV); index++) {
915 /* Did we get something? */
916 if ((tempSV = av_fetch(tempAV, index, 0))) {
918 if (*tempSV != &PL_sv_undef) {
919 /* Apparently not. Save it for later */
920 av_push(pending_array, *tempSV);
929 dbg_printf(("# Found type HV\n"));
930 /* Is there anything in here? */
931 if (hv_iterinit((HV *)thing)) {
933 while ((temp_he = hv_iternext((HV *)thing))) {
934 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
940 dbg_printf(("# Found type GV\n"));
941 /* Run through all the pieces and push the ones with bits */
943 av_push(pending_array, (SV *)GvSV(thing));
946 av_push(pending_array, (SV *)GvFORM(thing));
949 av_push(pending_array, (SV *)GvAV(thing));
952 av_push(pending_array, (SV *)GvHV(thing));
955 av_push(pending_array, (SV *)GvCV(thing));
963 size = thing_size(aTHX_ thing, st);
966 /* check_new() returned false: */
967 #ifdef DEVEL_SIZE_DEBUGGING
968 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
969 else printf("# Ignore non-sv 0x%x\n", sv);
975 SvREFCNT_dec(pending_array);