1 #define PERL_NO_GET_CONTEXT
8 /* Not yet in ppport.h */
10 # define CvISXSUB(cv) (CvXSUB(cv) ? TRUE : FALSE)
13 # define SvRV_const(rv) SvRV(rv)
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. */
22 # define TRY_TO_CATCH_SEGV __try
23 # define CAUGHT_EXCEPTION __except(EXCEPTION EXCEPTION_EXECUTE_HANDLER)
25 # define TRY_TO_CATCH_SEGV if(1)
26 # define CAUGHT_EXCEPTION else
30 # define __attribute__(x)
33 #if 0 && defined(DEBUGGING)
34 #define dbg_printf(x) printf x
39 #define TAG /* printf( "# %s(%d)\n", __FILE__, __LINE__ ) */
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) */
49 #define ALIGN_BITS ( sizeof(void*) >> 1 )
51 #define LEAF_BITS (16 - BYTE_BITS)
52 #define LEAF_MASK 0x1FFF
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. */
67 Checks to see if thing is in the bitstring.
68 Returns true or false, and
69 notes thing in the segmented bitstring.
72 check_new(struct state *st, const void *const p) {
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
81 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
82 const U8 this_bit = 1 << (cooked_p & 0x7);
89 if (NULL == p || NULL == st) return FALSE;
90 tv_p = (void **) (st->tracking);
92 const char c = *(const char *)p;
96 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
102 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
104 /* First level is always present. */
106 i = (unsigned int)((cooked_p >> bits) & 0xFF);
108 Newxz(tv_p[i], 256, void *);
109 tv_p = (void **)(tv_p[i]);
111 } while (bits > LEAF_BITS + BYTE_BITS);
112 /* bits now 16 always */
113 #if !defined(MULTIPLICITY) || PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8)
114 /* 5.8.8 and early have an assert() macro that uses Perl_croak, hence needs
115 a my_perl under multiplicity */
118 leaf_p = (U8 **)tv_p;
119 i = (unsigned int)((cooked_p >> bits) & 0xFF);
121 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
126 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
128 if(leaf[i] & this_bit)
136 free_tracking_at(void **tv, int level)
144 free_tracking_at(tv[i], level);
158 free_state(struct state *st)
160 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
161 free_tracking_at((void **)st->tracking, top_level);
165 static void thing_size(pTHX_ const SV *const, struct state *);
182 cc_opclass(const OP * const o)
188 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
190 if (o->op_type == OP_SASSIGN)
191 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
194 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
198 if ((o->op_type == OP_TRANS)) {
202 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
227 case OA_PVOP_OR_SVOP: TAG;
229 * Character translations (tr///) are usually a PVOP, keeping a
230 * pointer to a table of shorts used to look up translations.
231 * Under utf8, however, a simple table isn't practical; instead,
232 * the OP is an SVOP, and the SV is a reference to a swash
233 * (i.e., an RV pointing to an HV).
235 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
236 ? OPc_SVOP : OPc_PVOP;
244 case OA_BASEOP_OR_UNOP: TAG;
246 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
247 * whether parens were seen. perly.y uses OPf_SPECIAL to
248 * signal whether a BASEOP had empty parens or none.
249 * Some other UNOPs are created later, though, so the best
250 * test is OPf_KIDS, which is set in newUNOP.
252 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
254 case OA_FILESTATOP: TAG;
256 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
257 * the OPf_REF flag to distinguish between OP types instead of the
258 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
259 * return OPc_UNOP so that walkoptree can find our children. If
260 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
261 * (no argument to the operator) it's an OP; with OPf_REF set it's
262 * an SVOP (and op_sv is the GV for the filehandle argument).
264 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
266 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
268 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
270 case OA_LOOPEXOP: TAG;
272 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
273 * label was omitted (in which case it's a BASEOP) or else a term was
274 * seen. In this last case, all except goto are definitely PVOP but
275 * goto is either a PVOP (with an ordinary constant label), an UNOP
276 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
277 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
280 if (o->op_flags & OPf_STACKED)
282 else if (o->op_flags & OPf_SPECIAL)
287 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
288 PL_op_name[o->op_type]);
299 /* Figure out how much magic is attached to the SV and return the
302 magic_size(const SV * const thing, struct state *st) {
303 MAGIC *magic_pointer;
306 if (!SvMAGIC(thing)) {
311 /* Get the base magic pointer */
312 magic_pointer = SvMAGIC(thing);
314 /* Have we seen the magic pointer? */
315 while (magic_pointer && check_new(st, magic_pointer)) {
316 st->total_size += sizeof(MAGIC);
319 /* Have we seen the magic vtable? */
320 if (magic_pointer->mg_virtual &&
321 check_new(st, magic_pointer->mg_virtual)) {
322 st->total_size += sizeof(MGVTBL);
325 /* Get the next in the chain */
326 magic_pointer = magic_pointer->mg_moremagic;
329 if (st->dangle_whine)
330 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
336 regex_size(const REGEXP * const baseregex, struct state *st) {
337 st->total_size += sizeof(REGEXP);
338 #if (PERL_VERSION < 11)
339 /* Note the size of the paren offset thing */
340 st->total_size += sizeof(I32) * baseregex->nparens * 2;
341 st->total_size += strlen(baseregex->precomp);
343 st->total_size += sizeof(struct regexp);
344 st->total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
345 /*st->total_size += strlen(SvANY(baseregex)->subbeg);*/
347 if (st->go_yell && !st->regex_whine) {
348 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
354 op_size(pTHX_ const OP * const baseop, struct state *st) {
357 if (check_new(st, baseop->op_next)) {
358 op_size(aTHX_ baseop->op_next, st);
361 switch (cc_opclass(baseop)) {
362 case OPc_BASEOP: TAG;
363 st->total_size += sizeof(struct op);
366 st->total_size += sizeof(struct unop);
367 if (check_new(st, cUNOPx(baseop)->op_first)) {
368 op_size(aTHX_ cUNOPx(baseop)->op_first, st);
372 st->total_size += sizeof(struct binop);
373 if (check_new(st, cBINOPx(baseop)->op_first)) {
374 op_size(aTHX_ cBINOPx(baseop)->op_first, st);
376 if (check_new(st, cBINOPx(baseop)->op_last)) {
377 op_size(aTHX_ cBINOPx(baseop)->op_last, st);
381 st->total_size += sizeof(struct logop);
382 if (check_new(st, cLOGOPx(baseop)->op_first)) {
383 op_size(aTHX_ cBINOPx(baseop)->op_first, st);
385 if (check_new(st, cLOGOPx(baseop)->op_other)) {
386 op_size(aTHX_ cLOGOPx(baseop)->op_other, st);
389 case OPc_LISTOP: TAG;
390 st->total_size += sizeof(struct listop);
391 if (check_new(st, cLISTOPx(baseop)->op_first)) {
392 op_size(aTHX_ cLISTOPx(baseop)->op_first, st);
394 if (check_new(st, cLISTOPx(baseop)->op_last)) {
395 op_size(aTHX_ cLISTOPx(baseop)->op_last, st);
399 st->total_size += sizeof(struct pmop);
400 if (check_new(st, cPMOPx(baseop)->op_first)) {
401 op_size(aTHX_ cPMOPx(baseop)->op_first, st);
403 if (check_new(st, cPMOPx(baseop)->op_last)) {
404 op_size(aTHX_ cPMOPx(baseop)->op_last, st);
406 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
407 if (check_new(st, cPMOPx(baseop)->op_pmreplroot)) {
408 op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, st);
410 if (check_new(st, cPMOPx(baseop)->op_pmreplstart)) {
411 op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, st);
413 if (check_new(st, cPMOPx(baseop)->op_pmnext)) {
414 op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, st);
417 /* This is defined away in perl 5.8.x, but it is in there for
420 if (check_new(st, PM_GETRE((cPMOPx(baseop))))) {
421 regex_size(PM_GETRE(cPMOPx(baseop)), st);
424 if (check_new(st, cPMOPx(baseop)->op_pmregexp)) {
425 regex_size(cPMOPx(baseop)->op_pmregexp, st);
430 st->total_size += sizeof(struct pmop);
431 if (check_new(st, cSVOPx(baseop)->op_sv)) {
432 thing_size(aTHX_ cSVOPx(baseop)->op_sv, st);
436 st->total_size += sizeof(struct padop);
439 if (check_new(st, cPVOPx(baseop)->op_pv)) {
440 st->total_size += strlen(cPVOPx(baseop)->op_pv);
443 st->total_size += sizeof(struct loop);
444 if (check_new(st, cLOOPx(baseop)->op_first)) {
445 op_size(aTHX_ cLOOPx(baseop)->op_first, st);
447 if (check_new(st, cLOOPx(baseop)->op_last)) {
448 op_size(aTHX_ cLOOPx(baseop)->op_last, st);
450 if (check_new(st, cLOOPx(baseop)->op_redoop)) {
451 op_size(aTHX_ cLOOPx(baseop)->op_redoop, st);
453 if (check_new(st, cLOOPx(baseop)->op_nextop)) {
454 op_size(aTHX_ cLOOPx(baseop)->op_nextop, st);
456 if (check_new(st, cLOOPx(baseop)->op_lastop)) {
457 op_size(aTHX_ cLOOPx(baseop)->op_lastop, st);
464 basecop = (COP *)baseop;
465 st->total_size += sizeof(struct cop);
467 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
468 Eliminate cop_label from struct cop by storing a label as the first
469 entry in the hints hash. Most statements don't have labels, so this
470 will save memory. Not sure how much.
471 The check below will be incorrect fail on bleadperls
472 before 5.11 @33656, but later than 5.10, producing slightly too
473 small memory sizes on these Perls. */
474 #if (PERL_VERSION < 11)
475 if (check_new(st, basecop->cop_label)) {
476 st->total_size += strlen(basecop->cop_label);
480 if (check_new(st, basecop->cop_file)) {
481 st->total_size += strlen(basecop->cop_file);
483 if (check_new(st, basecop->cop_stashpv)) {
484 st->total_size += strlen(basecop->cop_stashpv);
487 if (check_new(st, basecop->cop_stash)) {
488 thing_size(aTHX_ (SV *)basecop->cop_stash, st);
490 if (check_new(st, basecop->cop_filegv)) {
491 thing_size(aTHX_ (SV *)basecop->cop_filegv, st);
502 if (st->dangle_whine)
503 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
507 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
508 # define NEW_HEAD_LAYOUT
512 thing_size(pTHX_ const SV * const orig_thing, struct state *st) {
513 const SV *thing = orig_thing;
515 st->total_size += sizeof(SV);
517 switch (SvTYPE(thing)) {
521 /* Just a plain integer. This will be differently sized depending
522 on whether purify's been compiled in */
524 #ifndef NEW_HEAD_LAYOUT
526 st->total_size += sizeof(sizeof(XPVIV));
528 st->total_size += sizeof(IV);
532 /* Is it a float? Like the int, it depends on purify */
535 st->total_size += sizeof(sizeof(XPVNV));
537 st->total_size += sizeof(NV);
540 #if (PERL_VERSION < 11)
541 /* Is it a reference? */
543 #ifndef NEW_HEAD_LAYOUT
544 st->total_size += sizeof(XRV);
548 /* How about a plain string? In which case we need to add in how
549 much has been allocated */
551 st->total_size += sizeof(XPV);
553 thing_size(aTHX_ SvRV_const(thing), st);
555 st->total_size += SvLEN(thing);
557 /* A string with an integer part? */
559 st->total_size += sizeof(XPVIV);
561 thing_size(aTHX_ SvRV_const(thing), st);
563 st->total_size += SvLEN(thing);
565 st->total_size += SvIVX(thing);
568 /* A scalar/string/reference with a float part? */
570 st->total_size += sizeof(XPVNV);
572 thing_size(aTHX_ SvRV_const(thing), st);
574 st->total_size += SvLEN(thing);
577 st->total_size += sizeof(XPVMG);
579 thing_size(aTHX_ SvRV_const(thing), st);
581 st->total_size += SvLEN(thing);
582 magic_size(thing, st);
584 #if PERL_VERSION <= 8
586 st->total_size += sizeof(XPVBM);
588 thing_size(aTHX_ SvRV_const(thing), st);
590 st->total_size += SvLEN(thing);
591 magic_size(thing, st);
595 st->total_size += sizeof(XPVLV);
597 thing_size(aTHX_ SvRV_const(thing), st);
599 st->total_size += SvLEN(thing);
600 magic_size(thing, st);
602 /* How much space is dedicated to the array? Not counting the
603 elements in the array, mind, just the array itself */
605 st->total_size += sizeof(XPVAV);
606 /* Is there anything in the array? */
607 if (AvMAX(thing) != -1) {
608 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
609 st->total_size += sizeof(SV *) * (AvMAX(thing) + 1);
610 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", st->total_size, AvMAX(thing), av_len((AV*)thing)));
612 /* Add in the bits on the other side of the beginning */
614 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
615 st->total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
617 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
618 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
619 if (AvALLOC(thing) != 0) {
620 st->total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
622 #if (PERL_VERSION < 9)
623 /* Is there something hanging off the arylen element?
624 Post 5.9.something this is stored in magic, so will be found there,
625 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
626 complain about AvARYLEN() passing thing to it. */
627 if (AvARYLEN(thing)) {
628 if (check_new(st, AvARYLEN(thing))) {
629 thing_size(aTHX_ AvARYLEN(thing), st);
633 magic_size(thing, st);
636 /* First the base struct */
637 st->total_size += sizeof(XPVHV);
638 /* Now the array of buckets */
639 st->total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
640 /* Now walk the bucket chain */
641 if (HvARRAY(thing)) {
644 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
645 cur_entry = *(HvARRAY(thing) + cur_bucket);
647 st->total_size += sizeof(HE);
648 if (cur_entry->hent_hek) {
649 /* Hash keys can be shared. Have we seen this before? */
650 if (check_new(st, cur_entry->hent_hek)) {
651 st->total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
654 cur_entry = cur_entry->hent_next;
658 magic_size(thing, st);
661 st->total_size += sizeof(XPVCV);
662 magic_size(thing, st);
664 st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
665 if (check_new(st, CvSTASH(thing))) {
666 thing_size(aTHX_ (SV *)CvSTASH(thing), st);
668 if (check_new(st, SvSTASH(thing))) {
669 thing_size(aTHX_ (SV *)SvSTASH(thing), st);
671 if (check_new(st, CvGV(thing))) {
672 thing_size(aTHX_ (SV *)CvGV(thing), st);
674 if (check_new(st, CvPADLIST(thing))) {
675 thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
677 if (check_new(st, CvOUTSIDE(thing))) {
678 thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
680 if (CvISXSUB(thing)) {
681 SV *sv = cv_const_sv((CV *)thing);
683 thing_size(aTHX_ sv, st);
686 if (check_new(st, CvSTART(thing))) {
687 op_size(aTHX_ CvSTART(thing), st);
689 if (check_new(st, CvROOT(thing))) {
690 op_size(aTHX_ CvROOT(thing), st);
696 magic_size(thing, st);
697 st->total_size += sizeof(XPVGV);
698 st->total_size += GvNAMELEN(thing);
700 /* Is there a file? */
702 if (check_new(st, GvFILE(thing))) {
703 st->total_size += strlen(GvFILE(thing));
707 /* Is there something hanging off the glob? */
709 if (check_new(st, GvGP(thing))) {
710 st->total_size += sizeof(GP);
713 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
714 thing_size(aTHX_ generic_thing, st);
716 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
717 thing_size(aTHX_ generic_thing, st);
719 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
720 thing_size(aTHX_ generic_thing, st);
722 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
723 thing_size(aTHX_ generic_thing, st);
725 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
726 thing_size(aTHX_ generic_thing, st);
728 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
729 thing_size(aTHX_ generic_thing, st);
736 st->total_size += sizeof(XPVFM);
737 magic_size(thing, st);
738 st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
739 if (check_new(st, CvPADLIST(thing))) {
740 thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
742 if (check_new(st, CvOUTSIDE(thing))) {
743 thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
746 if (st->go_yell && !st->fm_whine) {
747 carp("Devel::Size: Calculated sizes for FMs are incomplete");
752 st->total_size += sizeof(XPVIO);
753 magic_size(thing, st);
754 if (check_new(st, (SvPVX_const(thing)))) {
755 st->total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
757 /* Some embedded char pointers */
758 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_top_name)) {
759 st->total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
761 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
762 st->total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
764 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
765 st->total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
767 /* Throw the GVs on the list to be walked if they're not-null */
768 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
769 thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_top_gv, st);
771 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
772 thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv, st);
774 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
775 thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv, st);
778 /* Only go trotting through the IO structures if they're really
779 trottable. If USE_PERLIO is defined we can do this. If
780 not... we can't, so we don't even try */
782 /* Dig into xio_ifp and xio_ofp here */
783 warn("Devel::Size: Can't size up perlio layers yet\n");
787 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
791 static struct state *
796 Newxz(st, 1, struct state);
798 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
799 st->dangle_whine = st->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
801 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
802 st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
807 MODULE = Devel::Size PACKAGE = Devel::Size
816 SV *thing = orig_thing;
817 struct state *st = new_state(aTHX);
819 /* If they passed us a reference then dereference it. This is the
820 only way we can check the sizes of arrays and hashes */
821 #if (PERL_VERSION < 11)
822 if (SvOK(thing) && SvROK(thing)) {
831 thing_size(aTHX_ thing, st);
832 RETVAL = st->total_size;
840 total_size(orig_thing)
844 SV *thing = orig_thing;
845 /* Array with things we still need to do */
848 struct state *st = new_state(aTHX);
850 /* Size starts at zero */
853 pending_array = newAV();
855 /* If they passed us a reference then dereference it.
856 This is the only way we can check the sizes of arrays and hashes. */
861 /* Put it on the pending array */
862 av_push(pending_array, thing);
864 /* Now just yank things off the end of the array until it's done */
865 while (av_len(pending_array) >= 0) {
866 thing = av_pop(pending_array);
867 /* Process it if we've not seen it */
868 if (check_new(st, thing)) {
869 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
872 /* Yes, it is. So let's check the type */
873 switch (SvTYPE(thing)) {
874 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
878 av_push(pending_array, SvRV(thing));
881 #if (PERL_VERSION < 11)
886 dbg_printf(("# Found RV\n"));
888 dbg_printf(("# Found RV\n"));
889 av_push(pending_array, SvRV(thing));
895 AV *tempAV = (AV *)thing;
898 dbg_printf(("# Found type AV\n"));
899 /* Quick alias to cut down on casting */
902 if (av_len(tempAV) != -1) {
904 /* Run through them all */
905 for (index = 0; index <= av_len(tempAV); index++) {
906 /* Did we get something? */
907 if ((tempSV = av_fetch(tempAV, index, 0))) {
909 if (*tempSV != &PL_sv_undef) {
910 /* Apparently not. Save it for later */
911 av_push(pending_array, *tempSV);
920 dbg_printf(("# Found type HV\n"));
921 /* Is there anything in here? */
922 if (hv_iterinit((HV *)thing)) {
924 while ((temp_he = hv_iternext((HV *)thing))) {
925 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
931 dbg_printf(("# Found type GV\n"));
932 /* Run through all the pieces and push the ones with bits */
934 av_push(pending_array, (SV *)GvSV(thing));
937 av_push(pending_array, (SV *)GvFORM(thing));
940 av_push(pending_array, (SV *)GvAV(thing));
943 av_push(pending_array, (SV *)GvHV(thing));
946 av_push(pending_array, (SV *)GvCV(thing));
954 thing_size(aTHX_ thing, st);
956 /* check_new() returned false: */
957 #ifdef DEVEL_SIZE_DEBUGGING
958 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
959 else printf("# Ignore non-sv 0x%x\n", sv);
964 RETVAL = st->total_size;
966 SvREFCNT_dec(pending_array);