7 /* "structured exception" handling is a Microsoft extension to C and C++.
8 It's *not* C++ exception handling - C++ exception handling can't capture
9 SEGVs and suchlike, whereas this can. There's no known analagous
10 functionality on other platforms. */
12 # define TRY_TO_CATCH_SEGV __try
13 # define CAUGHT_EXCEPTION __except(EXCEPTION EXCEPTION_EXECUTE_HANDLER)
15 # define TRY_TO_CATCH_SEGV if(1)
16 # define CAUGHT_EXCEPTION else
20 # define __attribute__(x)
23 static int regex_whine;
25 static int dangle_whine = 0;
27 #if 0 && defined(DEBUGGING)
28 #define dbg_printf(x) printf x
33 #define TAG //printf( "# %s(%d)\n", __FILE__, __LINE__ )
36 /* The idea is to have a tree structure to store 1 bit per possible pointer
37 address. The lowest 16 bits are stored in a block of 8092 bytes.
38 The blocks are in a 256-way tree, indexed by the reset of the pointer.
39 This can cope with 32 and 64 bit pointers, and any address space layout,
40 without excessive memory needs. The assumption is that your CPU cache
41 works :-) (And that we're not going to bust it) */
43 #define ALIGN_BITS ( sizeof(void*) >> 1 )
45 #define LEAF_BITS (16 - BYTE_BITS)
46 #define LEAF_MASK 0x1FFF
48 typedef void * TRACKING[256];
51 Checks to see if thing is in the bitstring.
52 Returns true or false, and
53 notes thing in the segmented bitstring.
56 check_new(TRACKING *tv, const void *const p) {
57 unsigned int bits = 8 * sizeof(void*);
58 const size_t raw_p = PTR2nat(p);
59 /* This effectively rotates the value right by the number of low always-0
60 bits in an aligned pointer. The assmption is that most (if not all)
61 pointers are aligned, and these will be in the same chain of nodes
62 (and hence hot in the cache) but we can still deal with any unaligned
65 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
66 const U8 this_bit = 1 << (cooked_p & 0x7);
70 void **tv_p = (void **) tv;
73 if (NULL == p) return FALSE;
75 const char c = *(const char *)p;
79 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
85 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
87 /* First level is always present. */
89 i = (unsigned int)((cooked_p >> bits) & 0xFF);
91 Newxz(tv_p[i], 256, void *);
92 tv_p = (void **)(tv_p[i]);
94 } while (bits > LEAF_BITS + BYTE_BITS);
95 /* bits now 16 always */
98 i = (unsigned int)((cooked_p >> bits) & 0xFF);
100 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
105 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
107 if(leaf[i] & this_bit)
115 free_tracking_at(void **tv, int level)
123 free_tracking_at(tv[i], level);
137 free_tracking(TRACKING *tv)
139 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
140 free_tracking_at((void **)tv, top_level);
144 UV thing_size(const SV *const, TRACKING *);
161 cc_opclass(const OP * const o)
167 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
169 if (o->op_type == OP_SASSIGN)
170 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
173 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
177 if ((o->op_type == OP_TRANS)) {
181 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
206 case OA_PVOP_OR_SVOP: TAG;
208 * Character translations (tr///) are usually a PVOP, keeping a
209 * pointer to a table of shorts used to look up translations.
210 * Under utf8, however, a simple table isn't practical; instead,
211 * the OP is an SVOP, and the SV is a reference to a swash
212 * (i.e., an RV pointing to an HV).
214 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
215 ? OPc_SVOP : OPc_PVOP;
223 case OA_BASEOP_OR_UNOP: TAG;
225 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
226 * whether parens were seen. perly.y uses OPf_SPECIAL to
227 * signal whether a BASEOP had empty parens or none.
228 * Some other UNOPs are created later, though, so the best
229 * test is OPf_KIDS, which is set in newUNOP.
231 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
233 case OA_FILESTATOP: TAG;
235 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
236 * the OPf_REF flag to distinguish between OP types instead of the
237 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
238 * return OPc_UNOP so that walkoptree can find our children. If
239 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
240 * (no argument to the operator) it's an OP; with OPf_REF set it's
241 * an SVOP (and op_sv is the GV for the filehandle argument).
243 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
245 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
247 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
249 case OA_LOOPEXOP: TAG;
251 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
252 * label was omitted (in which case it's a BASEOP) or else a term was
253 * seen. In this last case, all except goto are definitely PVOP but
254 * goto is either a PVOP (with an ordinary constant label), an UNOP
255 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
256 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
259 if (o->op_flags & OPf_STACKED)
261 else if (o->op_flags & OPf_SPECIAL)
266 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
267 PL_op_name[o->op_type]);
278 static int go_yell = 1;
280 /* Figure out how much magic is attached to the SV and return the
282 IV magic_size(const SV * const thing, TRACKING *tv) {
284 MAGIC *magic_pointer;
287 if (!SvMAGIC(thing)) {
292 /* Get the base magic pointer */
293 magic_pointer = SvMAGIC(thing);
295 /* Have we seen the magic pointer? */
296 while (magic_pointer && check_new(tv, magic_pointer)) {
297 total_size += sizeof(MAGIC);
300 /* Have we seen the magic vtable? */
301 if (magic_pointer->mg_virtual &&
302 check_new(tv, magic_pointer->mg_virtual)) {
303 total_size += sizeof(MGVTBL);
306 /* Get the next in the chain */ // ?try
307 magic_pointer = magic_pointer->mg_moremagic;
311 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
317 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
320 total_size += sizeof(REGEXP);
321 #if (PERL_VERSION < 11)
322 /* Note the size of the paren offset thing */
323 total_size += sizeof(I32) * baseregex->nparens * 2;
324 total_size += strlen(baseregex->precomp);
326 total_size += sizeof(struct regexp);
327 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
328 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
330 if (go_yell && !regex_whine) {
331 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
338 UV op_size(const OP * const baseop, TRACKING *tv) {
342 if (check_new(tv, baseop->op_next)) {
343 total_size += op_size(baseop->op_next, tv);
346 switch (cc_opclass(baseop)) {
347 case OPc_BASEOP: TAG;
348 total_size += sizeof(struct op);
351 total_size += sizeof(struct unop);
352 if (check_new(tv, cUNOPx(baseop)->op_first)) {
353 total_size += op_size(cUNOPx(baseop)->op_first, tv);
357 total_size += sizeof(struct binop);
358 if (check_new(tv, cBINOPx(baseop)->op_first)) {
359 total_size += op_size(cBINOPx(baseop)->op_first, tv);
361 if (check_new(tv, cBINOPx(baseop)->op_last)) {
362 total_size += op_size(cBINOPx(baseop)->op_last, tv);
366 total_size += sizeof(struct logop);
367 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
368 total_size += op_size(cBINOPx(baseop)->op_first, tv);
370 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
371 total_size += op_size(cLOGOPx(baseop)->op_other, tv);
374 case OPc_LISTOP: TAG;
375 total_size += sizeof(struct listop);
376 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
377 total_size += op_size(cLISTOPx(baseop)->op_first, tv);
379 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
380 total_size += op_size(cLISTOPx(baseop)->op_last, tv);
384 total_size += sizeof(struct pmop);
385 if (check_new(tv, cPMOPx(baseop)->op_first)) {
386 total_size += op_size(cPMOPx(baseop)->op_first, tv);
388 if (check_new(tv, cPMOPx(baseop)->op_last)) {
389 total_size += op_size(cPMOPx(baseop)->op_last, tv);
391 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
392 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
393 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tv);
395 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
396 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tv);
398 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
399 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tv);
402 /* This is defined away in perl 5.8.x, but it is in there for
405 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
406 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
409 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
410 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
415 total_size += sizeof(struct pmop);
416 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
417 total_size += thing_size(cSVOPx(baseop)->op_sv, tv);
421 total_size += sizeof(struct padop);
424 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
425 total_size += strlen(cPVOPx(baseop)->op_pv);
428 total_size += sizeof(struct loop);
429 if (check_new(tv, cLOOPx(baseop)->op_first)) {
430 total_size += op_size(cLOOPx(baseop)->op_first, tv);
432 if (check_new(tv, cLOOPx(baseop)->op_last)) {
433 total_size += op_size(cLOOPx(baseop)->op_last, tv);
435 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
436 total_size += op_size(cLOOPx(baseop)->op_redoop, tv);
438 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
439 total_size += op_size(cLOOPx(baseop)->op_nextop, tv);
441 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
442 total_size += op_size(cLOOPx(baseop)->op_lastop, tv);
449 basecop = (COP *)baseop;
450 total_size += sizeof(struct cop);
452 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
453 Eliminate cop_label from struct cop by storing a label as the first
454 entry in the hints hash. Most statements don't have labels, so this
455 will save memory. Not sure how much.
456 The check below will be incorrect fail on bleadperls
457 before 5.11 @33656, but later than 5.10, producing slightly too
458 small memory sizes on these Perls. */
459 #if (PERL_VERSION < 11)
460 if (check_new(tv, basecop->cop_label)) {
461 total_size += strlen(basecop->cop_label);
465 if (check_new(tv, basecop->cop_file)) {
466 total_size += strlen(basecop->cop_file);
468 if (check_new(tv, basecop->cop_stashpv)) {
469 total_size += strlen(basecop->cop_stashpv);
472 if (check_new(tv, basecop->cop_stash)) {
473 total_size += thing_size((SV *)basecop->cop_stash, tv);
475 if (check_new(tv, basecop->cop_filegv)) {
476 total_size += thing_size((SV *)basecop->cop_filegv, tv);
488 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
493 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
494 # define NEW_HEAD_LAYOUT
497 UV thing_size(const SV * const orig_thing, TRACKING *tv) {
498 const SV *thing = orig_thing;
499 UV total_size = sizeof(SV);
501 switch (SvTYPE(thing)) {
505 /* Just a plain integer. This will be differently sized depending
506 on whether purify's been compiled in */
508 #ifndef NEW_HEAD_LAYOUT
510 total_size += sizeof(sizeof(XPVIV));
512 total_size += sizeof(IV);
516 /* Is it a float? Like the int, it depends on purify */
519 total_size += sizeof(sizeof(XPVNV));
521 total_size += sizeof(NV);
524 #if (PERL_VERSION < 11)
525 /* Is it a reference? */
527 #ifndef NEW_HEAD_LAYOUT
528 total_size += sizeof(XRV);
532 /* How about a plain string? In which case we need to add in how
533 much has been allocated */
535 total_size += sizeof(XPV);
536 #if (PERL_VERSION < 11)
537 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
539 total_size += SvLEN(thing);
542 /* A string with an integer part? */
544 total_size += sizeof(XPVIV);
545 #if (PERL_VERSION < 11)
546 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
548 total_size += SvLEN(thing);
551 total_size += SvIVX(thing);
554 /* A scalar/string/reference with a float part? */
556 total_size += sizeof(XPVNV);
557 #if (PERL_VERSION < 11)
558 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
560 total_size += SvLEN(thing);
564 total_size += sizeof(XPVMG);
565 #if (PERL_VERSION < 11)
566 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
568 total_size += SvLEN(thing);
570 total_size += magic_size(thing, tv);
572 #if PERL_VERSION <= 8
574 total_size += sizeof(XPVBM);
575 #if (PERL_VERSION < 11)
576 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
578 total_size += SvLEN(thing);
580 total_size += magic_size(thing, tv);
584 total_size += sizeof(XPVLV);
585 #if (PERL_VERSION < 11)
586 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
588 total_size += SvLEN(thing);
590 total_size += magic_size(thing, tv);
592 /* How much space is dedicated to the array? Not counting the
593 elements in the array, mind, just the array itself */
595 total_size += sizeof(XPVAV);
596 /* Is there anything in the array? */
597 if (AvMAX(thing) != -1) {
598 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
599 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
600 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
602 /* Add in the bits on the other side of the beginning */
604 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
605 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
607 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
608 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
609 if (AvALLOC(thing) != 0) {
610 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
612 #if (PERL_VERSION < 9)
613 /* Is there something hanging off the arylen element?
614 Post 5.9.something this is stored in magic, so will be found there,
615 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
616 complain about AvARYLEN() passing thing to it. */
617 if (AvARYLEN(thing)) {
618 if (check_new(tv, AvARYLEN(thing))) {
619 total_size += thing_size(AvARYLEN(thing), tv);
623 total_size += magic_size(thing, tv);
626 /* First the base struct */
627 total_size += sizeof(XPVHV);
628 /* Now the array of buckets */
629 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
630 /* Now walk the bucket chain */
631 if (HvARRAY(thing)) {
634 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
635 cur_entry = *(HvARRAY(thing) + cur_bucket);
637 total_size += sizeof(HE);
638 if (cur_entry->hent_hek) {
639 /* Hash keys can be shared. Have we seen this before? */
640 if (check_new(tv, cur_entry->hent_hek)) {
641 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
644 cur_entry = cur_entry->hent_next;
648 total_size += magic_size(thing, tv);
651 total_size += sizeof(XPVCV);
652 total_size += magic_size(thing, tv);
654 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
655 if (check_new(tv, CvSTASH(thing))) {
656 total_size += thing_size((SV *)CvSTASH(thing), tv);
658 if (check_new(tv, SvSTASH(thing))) {
659 total_size += thing_size( (SV *)SvSTASH(thing), tv);
661 if (check_new(tv, CvGV(thing))) {
662 total_size += thing_size((SV *)CvGV(thing), tv);
664 if (check_new(tv, CvPADLIST(thing))) {
665 total_size += thing_size((SV *)CvPADLIST(thing), tv);
667 if (check_new(tv, CvOUTSIDE(thing))) {
668 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
670 if (check_new(tv, CvSTART(thing))) {
671 total_size += op_size(CvSTART(thing), tv);
673 if (check_new(tv, CvROOT(thing))) {
674 total_size += op_size(CvROOT(thing), tv);
679 total_size += magic_size(thing, tv);
680 total_size += sizeof(XPVGV);
681 total_size += GvNAMELEN(thing);
683 /* Is there a file? */
685 if (check_new(tv, GvFILE(thing))) {
686 total_size += strlen(GvFILE(thing));
690 /* Is there something hanging off the glob? */
692 if (check_new(tv, GvGP(thing))) {
693 total_size += sizeof(GP);
696 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
697 total_size += thing_size(generic_thing, tv);
699 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
700 total_size += thing_size(generic_thing, tv);
702 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
703 total_size += thing_size(generic_thing, tv);
705 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
706 total_size += thing_size(generic_thing, tv);
708 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
709 total_size += thing_size(generic_thing, tv);
711 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
712 total_size += thing_size(generic_thing, tv);
719 total_size += sizeof(XPVFM);
720 total_size += magic_size(thing, tv);
721 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
722 if (check_new(tv, CvPADLIST(thing))) {
723 total_size += thing_size((SV *)CvPADLIST(thing), tv);
725 if (check_new(tv, CvOUTSIDE(thing))) {
726 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
729 if (go_yell && !fm_whine) {
730 carp("Devel::Size: Calculated sizes for FMs are incomplete");
735 total_size += sizeof(XPVIO);
736 total_size += magic_size(thing, tv);
737 if (check_new(tv, (SvPVX_const(thing)))) {
738 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
740 /* Some embedded char pointers */
741 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
742 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
744 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
745 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
747 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
748 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
750 /* Throw the GVs on the list to be walked if they're not-null */
751 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
752 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
755 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
756 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
759 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
760 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
764 /* Only go trotting through the IO structures if they're really
765 trottable. If USE_PERLIO is defined we can do this. If
766 not... we can't, so we don't even try */
768 /* Dig into xio_ifp and xio_ofp here */
769 warn("Devel::Size: Can't size up perlio layers yet\n");
773 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
778 MODULE = Devel::Size PACKAGE = Devel::Size
787 SV *thing = orig_thing;
788 /* Hash to track our seen pointers */
789 //HV *tracking_hash = newHV();
792 Newz( 0xfc0ff, tv, 1, TRACKING );
794 /* Check warning status */
799 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
800 dangle_whine = go_yell = SvIV(warn_flag);
802 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
803 dangle_whine = SvIV(warn_flag);
806 /* If they passed us a reference then dereference it. This is the
807 only way we can check the sizes of arrays and hashes */
808 #if (PERL_VERSION < 11)
809 if (SvOK(thing) && SvROK(thing)) {
818 RETVAL = thing_size(thing, tv);
826 total_size(orig_thing)
830 SV *thing = orig_thing;
831 /* Hash to track our seen pointers */
834 /* Array with things we still need to do */
839 /* Size starts at zero */
842 /* Check warning status */
847 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
848 dangle_whine = go_yell = SvIV(warn_flag);
850 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
851 dangle_whine = SvIV(warn_flag);
854 /* init these after the go_yell above */
855 //tracking_hash = newHV();
856 Newz( 0xfc0ff, tv, 1, TRACKING );
857 pending_array = newAV();
859 /* We cannot push HV/AV directly, only the RV. So deref it
860 later (see below for "*** dereference later") and adjust here for
862 This is the only way we can check the sizes of arrays and hashes. */
864 RETVAL -= thing_size(thing, NULL);
867 /* Put it on the pending array */
868 av_push(pending_array, thing);
870 /* Now just yank things off the end of the array until it's done */
871 while (av_len(pending_array) >= 0) {
872 thing = av_pop(pending_array);
873 /* Process it if we've not seen it */
874 if (check_new(tv, thing)) {
875 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
878 /* Yes, it is. So let's check the type */
879 switch (SvTYPE(thing)) {
880 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
884 av_push(pending_array, SvRV(thing));
888 /* this is the "*** dereference later" part - see above */
889 #if (PERL_VERSION < 11)
894 dbg_printf(("# Found RV\n"));
896 dbg_printf(("# Found RV\n"));
897 av_push(pending_array, SvRV(thing));
903 AV *tempAV = (AV *)thing;
906 dbg_printf(("# Found type AV\n"));
907 /* Quick alias to cut down on casting */
910 if (av_len(tempAV) != -1) {
912 /* Run through them all */
913 for (index = 0; index <= av_len(tempAV); index++) {
914 /* Did we get something? */
915 if ((tempSV = av_fetch(tempAV, index, 0))) {
917 if (*tempSV != &PL_sv_undef) {
918 /* Apparently not. Save it for later */
919 av_push(pending_array, *tempSV);
928 dbg_printf(("# Found type HV\n"));
929 /* Is there anything in here? */
930 if (hv_iterinit((HV *)thing)) {
932 while ((temp_he = hv_iternext((HV *)thing))) {
933 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
939 dbg_printf(("# Found type GV\n"));
940 /* Run through all the pieces and push the ones with bits */
942 av_push(pending_array, (SV *)GvSV(thing));
945 av_push(pending_array, (SV *)GvFORM(thing));
948 av_push(pending_array, (SV *)GvAV(thing));
951 av_push(pending_array, (SV *)GvHV(thing));
954 av_push(pending_array, (SV *)GvCV(thing));
962 size = thing_size(thing, tv);
965 /* check_new() returned false: */
966 #ifdef DEVEL_SIZE_DEBUGGING
967 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
968 else printf("# Ignore non-sv 0x%x\n", sv);
974 SvREFCNT_dec(pending_array);