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
59 /* My hunch (not measured) is that for most architectures pointers will
60 start with 0 bits, hence the start of this array will be hot, and the
61 end unused. So put the flags next to the hot end. */
66 Checks to see if thing is in the bitstring.
67 Returns true or false, and
68 notes thing in the segmented bitstring.
71 check_new(struct state *st, const void *const p) {
72 unsigned int bits = 8 * sizeof(void*);
73 const size_t raw_p = PTR2nat(p);
74 /* This effectively rotates the value right by the number of low always-0
75 bits in an aligned pointer. The assmption is that most (if not all)
76 pointers are aligned, and these will be in the same chain of nodes
77 (and hence hot in the cache) but we can still deal with any unaligned
80 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
81 const U8 this_bit = 1 << (cooked_p & 0x7);
88 if (NULL == p || NULL == st) return FALSE;
89 tv_p = (void **) (st->tracking);
91 const char c = *(const char *)p;
95 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
101 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
103 /* First level is always present. */
105 i = (unsigned int)((cooked_p >> bits) & 0xFF);
107 Newxz(tv_p[i], 256, void *);
108 tv_p = (void **)(tv_p[i]);
110 } while (bits > LEAF_BITS + BYTE_BITS);
111 /* bits now 16 always */
112 #if !defined(MULTIPLICITY) || PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8)
113 /* 5.8.8 and early have an assert() macro that uses Perl_croak, hence needs
114 a my_perl under multiplicity */
117 leaf_p = (U8 **)tv_p;
118 i = (unsigned int)((cooked_p >> bits) & 0xFF);
120 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
125 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
127 if(leaf[i] & this_bit)
135 free_tracking_at(void **tv, int level)
143 free_tracking_at(tv[i], level);
157 free_state(struct state *st)
159 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
160 free_tracking_at((void **)st->tracking, top_level);
164 static UV thing_size(pTHX_ const SV *const, struct state *);
181 cc_opclass(const OP * const o)
187 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
189 if (o->op_type == OP_SASSIGN)
190 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
193 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
197 if ((o->op_type == OP_TRANS)) {
201 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
226 case OA_PVOP_OR_SVOP: TAG;
228 * Character translations (tr///) are usually a PVOP, keeping a
229 * pointer to a table of shorts used to look up translations.
230 * Under utf8, however, a simple table isn't practical; instead,
231 * the OP is an SVOP, and the SV is a reference to a swash
232 * (i.e., an RV pointing to an HV).
234 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
235 ? OPc_SVOP : OPc_PVOP;
243 case OA_BASEOP_OR_UNOP: TAG;
245 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
246 * whether parens were seen. perly.y uses OPf_SPECIAL to
247 * signal whether a BASEOP had empty parens or none.
248 * Some other UNOPs are created later, though, so the best
249 * test is OPf_KIDS, which is set in newUNOP.
251 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
253 case OA_FILESTATOP: TAG;
255 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
256 * the OPf_REF flag to distinguish between OP types instead of the
257 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
258 * return OPc_UNOP so that walkoptree can find our children. If
259 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
260 * (no argument to the operator) it's an OP; with OPf_REF set it's
261 * an SVOP (and op_sv is the GV for the filehandle argument).
263 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
265 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
267 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
269 case OA_LOOPEXOP: TAG;
271 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
272 * label was omitted (in which case it's a BASEOP) or else a term was
273 * seen. In this last case, all except goto are definitely PVOP but
274 * goto is either a PVOP (with an ordinary constant label), an UNOP
275 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
276 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
279 if (o->op_flags & OPf_STACKED)
281 else if (o->op_flags & OPf_SPECIAL)
286 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
287 PL_op_name[o->op_type]);
298 /* Figure out how much magic is attached to the SV and return the
300 IV magic_size(const SV * const thing, struct state *st) {
302 MAGIC *magic_pointer;
305 if (!SvMAGIC(thing)) {
310 /* Get the base magic pointer */
311 magic_pointer = SvMAGIC(thing);
313 /* Have we seen the magic pointer? */
314 while (magic_pointer && check_new(st, magic_pointer)) {
315 total_size += sizeof(MAGIC);
318 /* Have we seen the magic vtable? */
319 if (magic_pointer->mg_virtual &&
320 check_new(st, magic_pointer->mg_virtual)) {
321 total_size += sizeof(MGVTBL);
324 /* Get the next in the chain */
325 magic_pointer = magic_pointer->mg_moremagic;
328 if (st->dangle_whine)
329 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
335 UV regex_size(const REGEXP * const baseregex, struct state *st) {
338 total_size += sizeof(REGEXP);
339 #if (PERL_VERSION < 11)
340 /* Note the size of the paren offset thing */
341 total_size += sizeof(I32) * baseregex->nparens * 2;
342 total_size += strlen(baseregex->precomp);
344 total_size += sizeof(struct regexp);
345 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
346 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
348 if (st->go_yell && !st->regex_whine) {
349 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
357 op_size(pTHX_ const OP * const baseop, struct state *st) {
361 if (check_new(st, baseop->op_next)) {
362 total_size += op_size(aTHX_ baseop->op_next, st);
365 switch (cc_opclass(baseop)) {
366 case OPc_BASEOP: TAG;
367 total_size += sizeof(struct op);
370 total_size += sizeof(struct unop);
371 if (check_new(st, cUNOPx(baseop)->op_first)) {
372 total_size += op_size(aTHX_ cUNOPx(baseop)->op_first, st);
376 total_size += sizeof(struct binop);
377 if (check_new(st, cBINOPx(baseop)->op_first)) {
378 total_size += op_size(aTHX_ cBINOPx(baseop)->op_first, st);
380 if (check_new(st, cBINOPx(baseop)->op_last)) {
381 total_size += op_size(aTHX_ cBINOPx(baseop)->op_last, st);
385 total_size += sizeof(struct logop);
386 if (check_new(st, cLOGOPx(baseop)->op_first)) {
387 total_size += op_size(aTHX_ cBINOPx(baseop)->op_first, st);
389 if (check_new(st, cLOGOPx(baseop)->op_other)) {
390 total_size += op_size(aTHX_ cLOGOPx(baseop)->op_other, st);
393 case OPc_LISTOP: TAG;
394 total_size += sizeof(struct listop);
395 if (check_new(st, cLISTOPx(baseop)->op_first)) {
396 total_size += op_size(aTHX_ cLISTOPx(baseop)->op_first, st);
398 if (check_new(st, cLISTOPx(baseop)->op_last)) {
399 total_size += op_size(aTHX_ cLISTOPx(baseop)->op_last, st);
403 total_size += sizeof(struct pmop);
404 if (check_new(st, cPMOPx(baseop)->op_first)) {
405 total_size += op_size(aTHX_ cPMOPx(baseop)->op_first, st);
407 if (check_new(st, cPMOPx(baseop)->op_last)) {
408 total_size += op_size(aTHX_ cPMOPx(baseop)->op_last, st);
410 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
411 if (check_new(st, cPMOPx(baseop)->op_pmreplroot)) {
412 total_size += op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, st);
414 if (check_new(st, cPMOPx(baseop)->op_pmreplstart)) {
415 total_size += op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, st);
417 if (check_new(st, cPMOPx(baseop)->op_pmnext)) {
418 total_size += op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, st);
421 /* This is defined away in perl 5.8.x, but it is in there for
424 if (check_new(st, PM_GETRE((cPMOPx(baseop))))) {
425 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), st);
428 if (check_new(st, cPMOPx(baseop)->op_pmregexp)) {
429 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, st);
434 total_size += sizeof(struct pmop);
435 if (check_new(st, cSVOPx(baseop)->op_sv)) {
436 total_size += thing_size(aTHX_ cSVOPx(baseop)->op_sv, st);
440 total_size += sizeof(struct padop);
443 if (check_new(st, cPVOPx(baseop)->op_pv)) {
444 total_size += strlen(cPVOPx(baseop)->op_pv);
447 total_size += sizeof(struct loop);
448 if (check_new(st, cLOOPx(baseop)->op_first)) {
449 total_size += op_size(aTHX_ cLOOPx(baseop)->op_first, st);
451 if (check_new(st, cLOOPx(baseop)->op_last)) {
452 total_size += op_size(aTHX_ cLOOPx(baseop)->op_last, st);
454 if (check_new(st, cLOOPx(baseop)->op_redoop)) {
455 total_size += op_size(aTHX_ cLOOPx(baseop)->op_redoop, st);
457 if (check_new(st, cLOOPx(baseop)->op_nextop)) {
458 total_size += op_size(aTHX_ cLOOPx(baseop)->op_nextop, st);
460 if (check_new(st, cLOOPx(baseop)->op_lastop)) {
461 total_size += op_size(aTHX_ cLOOPx(baseop)->op_lastop, st);
468 basecop = (COP *)baseop;
469 total_size += sizeof(struct cop);
471 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
472 Eliminate cop_label from struct cop by storing a label as the first
473 entry in the hints hash. Most statements don't have labels, so this
474 will save memory. Not sure how much.
475 The check below will be incorrect fail on bleadperls
476 before 5.11 @33656, but later than 5.10, producing slightly too
477 small memory sizes on these Perls. */
478 #if (PERL_VERSION < 11)
479 if (check_new(st, basecop->cop_label)) {
480 total_size += strlen(basecop->cop_label);
484 if (check_new(st, basecop->cop_file)) {
485 total_size += strlen(basecop->cop_file);
487 if (check_new(st, basecop->cop_stashpv)) {
488 total_size += strlen(basecop->cop_stashpv);
491 if (check_new(st, basecop->cop_stash)) {
492 total_size += thing_size(aTHX_ (SV *)basecop->cop_stash, st);
494 if (check_new(st, basecop->cop_filegv)) {
495 total_size += thing_size(aTHX_ (SV *)basecop->cop_filegv, st);
506 if (st->dangle_whine)
507 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
512 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
513 # define NEW_HEAD_LAYOUT
517 thing_size(pTHX_ const SV * const orig_thing, struct state *st) {
518 const SV *thing = orig_thing;
519 UV total_size = sizeof(SV);
521 switch (SvTYPE(thing)) {
525 /* Just a plain integer. This will be differently sized depending
526 on whether purify's been compiled in */
528 #ifndef NEW_HEAD_LAYOUT
530 total_size += sizeof(sizeof(XPVIV));
532 total_size += sizeof(IV);
536 /* Is it a float? Like the int, it depends on purify */
539 total_size += sizeof(sizeof(XPVNV));
541 total_size += sizeof(NV);
544 #if (PERL_VERSION < 11)
545 /* Is it a reference? */
547 #ifndef NEW_HEAD_LAYOUT
548 total_size += sizeof(XRV);
552 /* How about a plain string? In which case we need to add in how
553 much has been allocated */
555 total_size += sizeof(XPV);
556 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV_const(thing), st) : SvLEN(thing);
558 /* A string with an integer part? */
560 total_size += sizeof(XPVIV);
561 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV_const(thing), st) : SvLEN(thing);
563 total_size += SvIVX(thing);
566 /* A scalar/string/reference with a float part? */
568 total_size += sizeof(XPVNV);
569 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV_const(thing), st) : SvLEN(thing);
572 total_size += sizeof(XPVMG);
573 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV_const(thing), st) : SvLEN(thing);
574 total_size += magic_size(thing, st);
576 #if PERL_VERSION <= 8
578 total_size += sizeof(XPVBM);
579 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV_const(thing), st) : SvLEN(thing);
580 total_size += magic_size(thing, st);
584 total_size += sizeof(XPVLV);
585 total_size += SvROK(thing) ? thing_size(aTHX_ SvRV_const(thing), st) : SvLEN(thing);
586 total_size += magic_size(thing, st);
588 /* How much space is dedicated to the array? Not counting the
589 elements in the array, mind, just the array itself */
591 total_size += sizeof(XPVAV);
592 /* Is there anything in the array? */
593 if (AvMAX(thing) != -1) {
594 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
595 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
596 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
598 /* Add in the bits on the other side of the beginning */
600 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
601 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
603 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
604 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
605 if (AvALLOC(thing) != 0) {
606 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
608 #if (PERL_VERSION < 9)
609 /* Is there something hanging off the arylen element?
610 Post 5.9.something this is stored in magic, so will be found there,
611 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
612 complain about AvARYLEN() passing thing to it. */
613 if (AvARYLEN(thing)) {
614 if (check_new(st, AvARYLEN(thing))) {
615 total_size += thing_size(aTHX_ AvARYLEN(thing), st);
619 total_size += magic_size(thing, st);
622 /* First the base struct */
623 total_size += sizeof(XPVHV);
624 /* Now the array of buckets */
625 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
626 /* Now walk the bucket chain */
627 if (HvARRAY(thing)) {
630 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
631 cur_entry = *(HvARRAY(thing) + cur_bucket);
633 total_size += sizeof(HE);
634 if (cur_entry->hent_hek) {
635 /* Hash keys can be shared. Have we seen this before? */
636 if (check_new(st, cur_entry->hent_hek)) {
637 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
640 cur_entry = cur_entry->hent_next;
644 total_size += magic_size(thing, st);
647 total_size += sizeof(XPVCV);
648 total_size += magic_size(thing, st);
650 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
651 if (check_new(st, CvSTASH(thing))) {
652 total_size += thing_size(aTHX_ (SV *)CvSTASH(thing), st);
654 if (check_new(st, SvSTASH(thing))) {
655 total_size += thing_size(aTHX_ (SV *)SvSTASH(thing), st);
657 if (check_new(st, CvGV(thing))) {
658 total_size += thing_size(aTHX_ (SV *)CvGV(thing), st);
660 if (check_new(st, CvPADLIST(thing))) {
661 total_size += thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
663 if (check_new(st, CvOUTSIDE(thing))) {
664 total_size += thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
666 if (CvISXSUB(thing)) {
667 SV *sv = cv_const_sv((CV *)thing);
669 total_size += thing_size(aTHX_ sv, st);
672 if (check_new(st, CvSTART(thing))) {
673 total_size += op_size(aTHX_ CvSTART(thing), st);
675 if (check_new(st, CvROOT(thing))) {
676 total_size += op_size(aTHX_ CvROOT(thing), st);
682 total_size += magic_size(thing, st);
683 total_size += sizeof(XPVGV);
684 total_size += GvNAMELEN(thing);
686 /* Is there a file? */
688 if (check_new(st, GvFILE(thing))) {
689 total_size += strlen(GvFILE(thing));
693 /* Is there something hanging off the glob? */
695 if (check_new(st, GvGP(thing))) {
696 total_size += sizeof(GP);
699 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
700 total_size += thing_size(aTHX_ generic_thing, st);
702 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
703 total_size += thing_size(aTHX_ generic_thing, st);
705 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
706 total_size += thing_size(aTHX_ generic_thing, st);
708 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
709 total_size += thing_size(aTHX_ generic_thing, st);
711 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
712 total_size += thing_size(aTHX_ generic_thing, st);
714 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
715 total_size += thing_size(aTHX_ generic_thing, st);
722 total_size += sizeof(XPVFM);
723 total_size += magic_size(thing, st);
724 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
725 if (check_new(st, CvPADLIST(thing))) {
726 total_size += thing_size(aTHX_ (SV *)CvPADLIST(thing), st);
728 if (check_new(st, CvOUTSIDE(thing))) {
729 total_size += thing_size(aTHX_ (SV *)CvOUTSIDE(thing), st);
732 if (st->go_yell && !st->fm_whine) {
733 carp("Devel::Size: Calculated sizes for FMs are incomplete");
738 total_size += sizeof(XPVIO);
739 total_size += magic_size(thing, st);
740 if (check_new(st, (SvPVX_const(thing)))) {
741 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
743 /* Some embedded char pointers */
744 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_top_name)) {
745 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
747 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
748 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
750 if (check_new(st, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
751 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
753 /* Throw the GVs on the list to be walked if they're not-null */
754 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
755 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
758 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
759 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
762 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
763 total_size += thing_size(aTHX_ (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
767 /* Only go trotting through the IO structures if they're really
768 trottable. If USE_PERLIO is defined we can do this. If
769 not... we can't, so we don't even try */
771 /* Dig into xio_ifp and xio_ofp here */
772 warn("Devel::Size: Can't size up perlio layers yet\n");
776 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
781 static struct state *
786 Newxz(st, 1, struct state);
788 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
789 st->dangle_whine = st->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
791 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
792 st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
797 MODULE = Devel::Size PACKAGE = Devel::Size
806 SV *thing = orig_thing;
807 struct state *st = new_state(aTHX);
809 /* If they passed us a reference then dereference it. This is the
810 only way we can check the sizes of arrays and hashes */
811 #if (PERL_VERSION < 11)
812 if (SvOK(thing) && SvROK(thing)) {
821 RETVAL = thing_size(aTHX_ thing, st);
829 total_size(orig_thing)
833 SV *thing = orig_thing;
834 /* Array with things we still need to do */
837 struct state *st = new_state(aTHX);
839 /* Size starts at zero */
842 pending_array = newAV();
844 /* If they passed us a reference then dereference it.
845 This is the only way we can check the sizes of arrays and hashes. */
850 /* Put it on the pending array */
851 av_push(pending_array, thing);
853 /* Now just yank things off the end of the array until it's done */
854 while (av_len(pending_array) >= 0) {
855 thing = av_pop(pending_array);
856 /* Process it if we've not seen it */
857 if (check_new(st, thing)) {
858 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
861 /* Yes, it is. So let's check the type */
862 switch (SvTYPE(thing)) {
863 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
867 av_push(pending_array, SvRV(thing));
870 #if (PERL_VERSION < 11)
875 dbg_printf(("# Found RV\n"));
877 dbg_printf(("# Found RV\n"));
878 av_push(pending_array, SvRV(thing));
884 AV *tempAV = (AV *)thing;
887 dbg_printf(("# Found type AV\n"));
888 /* Quick alias to cut down on casting */
891 if (av_len(tempAV) != -1) {
893 /* Run through them all */
894 for (index = 0; index <= av_len(tempAV); index++) {
895 /* Did we get something? */
896 if ((tempSV = av_fetch(tempAV, index, 0))) {
898 if (*tempSV != &PL_sv_undef) {
899 /* Apparently not. Save it for later */
900 av_push(pending_array, *tempSV);
909 dbg_printf(("# Found type HV\n"));
910 /* Is there anything in here? */
911 if (hv_iterinit((HV *)thing)) {
913 while ((temp_he = hv_iternext((HV *)thing))) {
914 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
920 dbg_printf(("# Found type GV\n"));
921 /* Run through all the pieces and push the ones with bits */
923 av_push(pending_array, (SV *)GvSV(thing));
926 av_push(pending_array, (SV *)GvFORM(thing));
929 av_push(pending_array, (SV *)GvAV(thing));
932 av_push(pending_array, (SV *)GvHV(thing));
935 av_push(pending_array, (SV *)GvCV(thing));
943 size = thing_size(aTHX_ thing, st);
946 /* check_new() returned false: */
947 #ifdef DEVEL_SIZE_DEBUGGING
948 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
949 else printf("# Ignore non-sv 0x%x\n", sv);
955 SvREFCNT_dec(pending_array);