9 # define catch __except
10 # define EXCEPTION EXCEPTION_EXECUTE_HANDLER
12 # define EXCEPTION ...
16 # define __attribute__(x)
19 static int regex_whine;
21 static int dangle_whine = 0;
23 #if 0 && defined(DEBUGGING)
24 #define dbg_printf(x) printf x
29 #define TAG //printf( "# %s(%d)\n", __FILE__, __LINE__ )
32 #define ALIGN_BITS ( sizeof(void*) >> 1 )
35 #define SLOT_BITS ( sizeof( void*) * 8 ) - ( ALIGN_BITS + BIT_BITS + BYTE_BITS )
36 #define BYTES_PER_SLOT 1 << BYTE_BITS
37 #define TRACKING_SLOTS 8192 // max. 8192 for 4GB/32-bit machine
39 typedef char* TRACKING[ TRACKING_SLOTS ];
42 Checks to see if thing is in the bitstring.
43 Returns true or false, and
44 notes thing in the segmented bitstring.
46 IV check_new( TRACKING *tv, void *p ) {
47 unsigned long slot = (unsigned long)p >> (SLOT_BITS + BIT_BITS + ALIGN_BITS);
48 unsigned int byte = ((unsigned long)p >> (ALIGN_BITS + BIT_BITS)) & 0x00003fffU;
49 unsigned int bit = ((unsigned long)p >> ALIGN_BITS) & 0x00000007U;
50 unsigned int nop = (unsigned long)p & 0x3U;
52 if (NULL == p || NULL == tv) return FALSE;
58 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
62 "address: %p slot: %p byte: %4x bit: %4x nop:%x\n",
63 p, slot, byte, bit, nop
66 if( slot >= TRACKING_SLOTS ) {
67 die( "Devel::Size: Please rebuild D::S with TRACKING_SLOTS > %u\n", slot );
70 if( (*tv)[ slot ] == NULL ) {
71 Newz( 0xfc0ff, (*tv)[ slot ], BYTES_PER_SLOT, char );
74 if( (*tv)[ slot ][ byte ] & ( 1 << bit ) ) {
78 (*tv)[ slot ][ byte ] |= ( 1 << bit );
83 UV thing_size(const SV *const, TRACKING *);
100 cc_opclass(const OP * const o)
106 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
108 if (o->op_type == OP_SASSIGN)
109 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
112 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
116 if ((o->op_type == OP_TRANS)) {
120 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
145 case OA_PVOP_OR_SVOP: TAG;
147 * Character translations (tr///) are usually a PVOP, keeping a
148 * pointer to a table of shorts used to look up translations.
149 * Under utf8, however, a simple table isn't practical; instead,
150 * the OP is an SVOP, and the SV is a reference to a swash
151 * (i.e., an RV pointing to an HV).
153 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
154 ? OPc_SVOP : OPc_PVOP;
162 case OA_BASEOP_OR_UNOP: TAG;
164 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
165 * whether parens were seen. perly.y uses OPf_SPECIAL to
166 * signal whether a BASEOP had empty parens or none.
167 * Some other UNOPs are created later, though, so the best
168 * test is OPf_KIDS, which is set in newUNOP.
170 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
172 case OA_FILESTATOP: TAG;
174 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
175 * the OPf_REF flag to distinguish between OP types instead of the
176 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
177 * return OPc_UNOP so that walkoptree can find our children. If
178 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
179 * (no argument to the operator) it's an OP; with OPf_REF set it's
180 * an SVOP (and op_sv is the GV for the filehandle argument).
182 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
184 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
186 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
188 case OA_LOOPEXOP: TAG;
190 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
191 * label was omitted (in which case it's a BASEOP) or else a term was
192 * seen. In this last case, all except goto are definitely PVOP but
193 * goto is either a PVOP (with an ordinary constant label), an UNOP
194 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
195 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
198 if (o->op_flags & OPf_STACKED)
200 else if (o->op_flags & OPf_SPECIAL)
205 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
206 PL_op_name[o->op_type]);
208 catch( EXCEPTION ) { }
217 static int go_yell = 1;
219 /* Figure out how much magic is attached to the SV and return the
221 IV magic_size(const SV * const thing, TRACKING *tv) {
223 MAGIC *magic_pointer;
226 if (!SvMAGIC(thing)) {
231 /* Get the base magic pointer */
232 magic_pointer = SvMAGIC(thing);
234 /* Have we seen the magic pointer? */
235 while (magic_pointer && check_new(tv, magic_pointer)) {
236 total_size += sizeof(MAGIC);
239 /* Have we seen the magic vtable? */
240 if (magic_pointer->mg_virtual &&
241 check_new(tv, magic_pointer->mg_virtual)) {
242 total_size += sizeof(MGVTBL);
245 /* Get the next in the chain */ // ?try
246 magic_pointer = magic_pointer->mg_moremagic;
250 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
256 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
259 total_size += sizeof(REGEXP);
260 #if (PERL_VERSION < 11)
261 /* Note the size of the paren offset thing */
262 total_size += sizeof(I32) * baseregex->nparens * 2;
263 total_size += strlen(baseregex->precomp);
265 total_size += sizeof(struct regexp);
266 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
267 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
269 if (go_yell && !regex_whine) {
270 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
277 UV op_size(const OP * const baseop, TRACKING *tv) {
281 if (check_new(tv, baseop->op_next)) {
282 total_size += op_size(baseop->op_next, tv);
285 switch (cc_opclass(baseop)) {
286 case OPc_BASEOP: TAG;
287 total_size += sizeof(struct op);
290 total_size += sizeof(struct unop);
291 if (check_new(tv, cUNOPx(baseop)->op_first)) {
292 total_size += op_size(cUNOPx(baseop)->op_first, tv);
296 total_size += sizeof(struct binop);
297 if (check_new(tv, cBINOPx(baseop)->op_first)) {
298 total_size += op_size(cBINOPx(baseop)->op_first, tv);
300 if (check_new(tv, cBINOPx(baseop)->op_last)) {
301 total_size += op_size(cBINOPx(baseop)->op_last, tv);
305 total_size += sizeof(struct logop);
306 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
307 total_size += op_size(cBINOPx(baseop)->op_first, tv);
309 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
310 total_size += op_size(cLOGOPx(baseop)->op_other, tv);
313 case OPc_LISTOP: TAG;
314 total_size += sizeof(struct listop);
315 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
316 total_size += op_size(cLISTOPx(baseop)->op_first, tv);
318 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
319 total_size += op_size(cLISTOPx(baseop)->op_last, tv);
323 total_size += sizeof(struct pmop);
324 if (check_new(tv, cPMOPx(baseop)->op_first)) {
325 total_size += op_size(cPMOPx(baseop)->op_first, tv);
327 if (check_new(tv, cPMOPx(baseop)->op_last)) {
328 total_size += op_size(cPMOPx(baseop)->op_last, tv);
330 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
331 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
332 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tv);
334 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
335 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tv);
337 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
338 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tv);
341 /* This is defined away in perl 5.8.x, but it is in there for
344 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
345 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
348 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
349 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
354 total_size += sizeof(struct pmop);
355 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
356 total_size += thing_size(cSVOPx(baseop)->op_sv, tv);
360 total_size += sizeof(struct padop);
363 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
364 total_size += strlen(cPVOPx(baseop)->op_pv);
367 total_size += sizeof(struct loop);
368 if (check_new(tv, cLOOPx(baseop)->op_first)) {
369 total_size += op_size(cLOOPx(baseop)->op_first, tv);
371 if (check_new(tv, cLOOPx(baseop)->op_last)) {
372 total_size += op_size(cLOOPx(baseop)->op_last, tv);
374 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
375 total_size += op_size(cLOOPx(baseop)->op_redoop, tv);
377 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
378 total_size += op_size(cLOOPx(baseop)->op_nextop, tv);
380 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
381 total_size += op_size(cLOOPx(baseop)->op_lastop, tv);
388 basecop = (COP *)baseop;
389 total_size += sizeof(struct cop);
391 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
392 Eliminate cop_label from struct cop by storing a label as the first
393 entry in the hints hash. Most statements don't have labels, so this
394 will save memory. Not sure how much.
395 The check below will be incorrect fail on bleadperls
396 before 5.11 @33656, but later than 5.10, producing slightly too
397 small memory sizes on these Perls. */
398 #if (PERL_VERSION < 11)
399 if (check_new(tv, basecop->cop_label)) {
400 total_size += strlen(basecop->cop_label);
404 if (check_new(tv, basecop->cop_file)) {
405 total_size += strlen(basecop->cop_file);
407 if (check_new(tv, basecop->cop_stashpv)) {
408 total_size += strlen(basecop->cop_stashpv);
411 if (check_new(tv, basecop->cop_stash)) {
412 total_size += thing_size((SV *)basecop->cop_stash, tv);
414 if (check_new(tv, basecop->cop_filegv)) {
415 total_size += thing_size((SV *)basecop->cop_filegv, tv);
427 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
432 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
433 # define NEW_HEAD_LAYOUT
436 UV thing_size(const SV * const orig_thing, TRACKING *tv) {
437 const SV *thing = orig_thing;
438 UV total_size = sizeof(SV);
440 switch (SvTYPE(thing)) {
444 /* Just a plain integer. This will be differently sized depending
445 on whether purify's been compiled in */
447 #ifndef NEW_HEAD_LAYOUT
449 total_size += sizeof(sizeof(XPVIV));
451 total_size += sizeof(IV);
455 /* Is it a float? Like the int, it depends on purify */
458 total_size += sizeof(sizeof(XPVNV));
460 total_size += sizeof(NV);
463 #if (PERL_VERSION < 11)
464 /* Is it a reference? */
466 #ifndef NEW_HEAD_LAYOUT
467 total_size += sizeof(XRV);
471 /* How about a plain string? In which case we need to add in how
472 much has been allocated */
474 total_size += sizeof(XPV);
475 #if (PERL_VERSION < 11)
476 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
478 total_size += SvLEN(thing);
481 /* A string with an integer part? */
483 total_size += sizeof(XPVIV);
484 #if (PERL_VERSION < 11)
485 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
487 total_size += SvLEN(thing);
490 total_size += SvIVX(thing);
493 /* A scalar/string/reference with a float part? */
495 total_size += sizeof(XPVNV);
496 #if (PERL_VERSION < 11)
497 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
499 total_size += SvLEN(thing);
503 total_size += sizeof(XPVMG);
504 #if (PERL_VERSION < 11)
505 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
507 total_size += SvLEN(thing);
509 total_size += magic_size(thing, tv);
511 #if PERL_VERSION <= 8
513 total_size += sizeof(XPVBM);
514 #if (PERL_VERSION < 11)
515 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
517 total_size += SvLEN(thing);
519 total_size += magic_size(thing, tv);
523 total_size += sizeof(XPVLV);
524 #if (PERL_VERSION < 11)
525 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
527 total_size += SvLEN(thing);
529 total_size += magic_size(thing, tv);
531 /* How much space is dedicated to the array? Not counting the
532 elements in the array, mind, just the array itself */
534 total_size += sizeof(XPVAV);
535 /* Is there anything in the array? */
536 if (AvMAX(thing) != -1) {
537 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
538 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
539 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
541 /* Add in the bits on the other side of the beginning */
543 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
544 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
546 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
547 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
548 if (AvALLOC(thing) != 0) {
549 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
551 #if (PERL_VERSION < 9)
552 /* Is there something hanging off the arylen element?
553 Post 5.9.something this is stored in magic, so will be found there,
554 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
555 complain about AvARYLEN() passing thing to it. */
556 if (AvARYLEN(thing)) {
557 if (check_new(tv, AvARYLEN(thing))) {
558 total_size += thing_size(AvARYLEN(thing), tv);
562 total_size += magic_size(thing, tv);
565 /* First the base struct */
566 total_size += sizeof(XPVHV);
567 /* Now the array of buckets */
568 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
569 /* Now walk the bucket chain */
570 if (HvARRAY(thing)) {
573 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
574 cur_entry = *(HvARRAY(thing) + cur_bucket);
576 total_size += sizeof(HE);
577 if (cur_entry->hent_hek) {
578 /* Hash keys can be shared. Have we seen this before? */
579 if (check_new(tv, cur_entry->hent_hek)) {
580 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
583 cur_entry = cur_entry->hent_next;
587 total_size += magic_size(thing, tv);
590 total_size += sizeof(XPVCV);
591 total_size += magic_size(thing, tv);
593 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
594 if (check_new(tv, CvSTASH(thing))) {
595 total_size += thing_size((SV *)CvSTASH(thing), tv);
597 if (check_new(tv, SvSTASH(thing))) {
598 total_size += thing_size( (SV *)SvSTASH(thing), tv);
600 if (check_new(tv, CvGV(thing))) {
601 total_size += thing_size((SV *)CvGV(thing), tv);
603 if (check_new(tv, CvPADLIST(thing))) {
604 total_size += thing_size((SV *)CvPADLIST(thing), tv);
606 if (check_new(tv, CvOUTSIDE(thing))) {
607 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
609 if (check_new(tv, CvSTART(thing))) {
610 total_size += op_size(CvSTART(thing), tv);
612 if (check_new(tv, CvROOT(thing))) {
613 total_size += op_size(CvROOT(thing), tv);
618 total_size += magic_size(thing, tv);
619 total_size += sizeof(XPVGV);
620 total_size += GvNAMELEN(thing);
622 /* Is there a file? */
624 if (check_new(tv, GvFILE(thing))) {
625 total_size += strlen(GvFILE(thing));
629 /* Is there something hanging off the glob? */
631 if (check_new(tv, GvGP(thing))) {
632 total_size += sizeof(GP);
635 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
636 total_size += thing_size(generic_thing, tv);
638 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
639 total_size += thing_size(generic_thing, tv);
641 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
642 total_size += thing_size(generic_thing, tv);
644 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
645 total_size += thing_size(generic_thing, tv);
647 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
648 total_size += thing_size(generic_thing, tv);
650 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
651 total_size += thing_size(generic_thing, tv);
658 total_size += sizeof(XPVFM);
659 total_size += magic_size(thing, tv);
660 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
661 if (check_new(tv, CvPADLIST(thing))) {
662 total_size += thing_size((SV *)CvPADLIST(thing), tv);
664 if (check_new(tv, CvOUTSIDE(thing))) {
665 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
668 if (go_yell && !fm_whine) {
669 carp("Devel::Size: Calculated sizes for FMs are incomplete");
674 total_size += sizeof(XPVIO);
675 total_size += magic_size(thing, tv);
676 if (check_new(tv, (SvPVX(thing)))) {
677 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
679 /* Some embedded char pointers */
680 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
681 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
683 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
684 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
686 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
687 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
689 /* Throw the GVs on the list to be walked if they're not-null */
690 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
691 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
694 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
695 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
698 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
699 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
703 /* Only go trotting through the IO structures if they're really
704 trottable. If USE_PERLIO is defined we can do this. If
705 not... we can't, so we don't even try */
707 /* Dig into xio_ifp and xio_ofp here */
708 warn("Devel::Size: Can't size up perlio layers yet\n");
712 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
717 MODULE = Devel::Size PACKAGE = Devel::Size
727 SV *thing = orig_thing;
728 /* Hash to track our seen pointers */
729 //HV *tracking_hash = newHV();
732 Newz( 0xfc0ff, tv, 1, TRACKING );
734 /* Check warning status */
739 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
740 dangle_whine = go_yell = SvIV(warn_flag);
742 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
743 dangle_whine = SvIV(warn_flag);
746 /* If they passed us a reference then dereference it. This is the
747 only way we can check the sizes of arrays and hashes */
748 #if (PERL_VERSION < 11)
749 if (SvOK(thing) && SvROK(thing)) {
758 RETVAL = thing_size(thing, tv);
759 /* Clean up after ourselves */
760 //SvREFCNT_dec(tracking_hash);
761 for( i = 0; i < TRACKING_SLOTS; ++i ) {
763 Safefree( (*tv)[ i ] );
772 total_size(orig_thing)
777 SV *thing = orig_thing;
778 /* Hash to track our seen pointers */
781 /* Array with things we still need to do */
786 /* Size starts at zero */
789 /* Check warning status */
794 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
795 dangle_whine = go_yell = SvIV(warn_flag);
797 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
798 dangle_whine = SvIV(warn_flag);
801 /* init these after the go_yell above */
802 //tracking_hash = newHV();
803 Newz( 0xfc0ff, tv, 1, TRACKING );
804 pending_array = newAV();
806 /* We cannot push HV/AV directly, only the RV. So deref it
807 later (see below for "*** dereference later") and adjust here for
809 This is the only way we can check the sizes of arrays and hashes. */
811 RETVAL -= thing_size(thing, NULL);
814 /* Put it on the pending array */
815 av_push(pending_array, thing);
817 /* Now just yank things off the end of the array until it's done */
818 while (av_len(pending_array) >= 0) {
819 thing = av_pop(pending_array);
820 /* Process it if we've not seen it */
821 if (check_new(tv, thing)) {
822 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
825 /* Yes, it is. So let's check the type */
826 switch (SvTYPE(thing)) {
827 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
831 av_push(pending_array, SvRV(thing));
835 /* this is the "*** dereference later" part - see above */
836 #if (PERL_VERSION < 11)
841 dbg_printf(("# Found RV\n"));
843 dbg_printf(("# Found RV\n"));
844 av_push(pending_array, SvRV(thing));
850 AV *tempAV = (AV *)thing;
853 dbg_printf(("# Found type AV\n"));
854 /* Quick alias to cut down on casting */
857 if (av_len(tempAV) != -1) {
859 /* Run through them all */
860 for (index = 0; index <= av_len(tempAV); index++) {
861 /* Did we get something? */
862 if ((tempSV = av_fetch(tempAV, index, 0))) {
864 if (*tempSV != &PL_sv_undef) {
865 /* Apparently not. Save it for later */
866 av_push(pending_array, *tempSV);
875 dbg_printf(("# Found type HV\n"));
876 /* Is there anything in here? */
877 if (hv_iterinit((HV *)thing)) {
879 while ((temp_he = hv_iternext((HV *)thing))) {
880 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
886 dbg_printf(("# Found type GV\n"));
887 /* Run through all the pieces and push the ones with bits */
889 av_push(pending_array, (SV *)GvSV(thing));
892 av_push(pending_array, (SV *)GvFORM(thing));
895 av_push(pending_array, (SV *)GvAV(thing));
898 av_push(pending_array, (SV *)GvHV(thing));
901 av_push(pending_array, (SV *)GvCV(thing));
909 size = thing_size(thing, tv);
912 /* check_new() returned false: */
913 #ifdef DEVEL_SIZE_DEBUGGING
914 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
915 else printf("# Ignore non-sv 0x%x\n", sv);
920 /* Clean up after ourselves */
921 //SvREFCNT_dec(tracking_hash);
922 for( i = 0; i < TRACKING_SLOTS; ++i ) {
924 Safefree( (*tv)[ i ] );
927 SvREFCNT_dec(pending_array);