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 #define ALIGN_BITS ( sizeof(void*) >> 1 )
39 #define SLOT_BITS ( sizeof( void*) * 8 ) - ( ALIGN_BITS + BIT_BITS + BYTE_BITS )
40 #define BYTES_PER_SLOT 1 << BYTE_BITS
41 #define TRACKING_SLOTS 8192 // max. 8192 for 4GB/32-bit machine
43 typedef char* TRACKING[ TRACKING_SLOTS ];
46 Checks to see if thing is in the bitstring.
47 Returns true or false, and
48 notes thing in the segmented bitstring.
51 check_new(TRACKING *tv, const void *const p) {
52 unsigned long slot = (unsigned long)p >> (SLOT_BITS + BIT_BITS + ALIGN_BITS);
53 unsigned int byte = ((unsigned long)p >> (ALIGN_BITS + BIT_BITS)) & 0x00003fffU;
54 unsigned int bit = ((unsigned long)p >> ALIGN_BITS) & 0x00000007U;
55 unsigned int nop = (unsigned long)p & 0x3U;
58 if (NULL == p) return FALSE;
60 const char c = *(const char *)p;
64 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
68 "address: %p slot: %p byte: %4x bit: %4x nop:%x\n",
69 p, slot, byte, bit, nop
72 if( slot >= TRACKING_SLOTS ) {
73 die( "Devel::Size: Please rebuild D::S with TRACKING_SLOTS > %u\n", slot );
76 if( (*tv)[ slot ] == NULL ) {
77 Newz( 0xfc0ff, (*tv)[ slot ], BYTES_PER_SLOT, char );
80 if( (*tv)[ slot ][ byte ] & ( 1 << bit ) ) {
84 (*tv)[ slot ][ byte ] |= ( 1 << bit );
89 UV thing_size(const SV *const, TRACKING *);
106 cc_opclass(const OP * const o)
112 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
114 if (o->op_type == OP_SASSIGN)
115 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
118 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
122 if ((o->op_type == OP_TRANS)) {
126 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
151 case OA_PVOP_OR_SVOP: TAG;
153 * Character translations (tr///) are usually a PVOP, keeping a
154 * pointer to a table of shorts used to look up translations.
155 * Under utf8, however, a simple table isn't practical; instead,
156 * the OP is an SVOP, and the SV is a reference to a swash
157 * (i.e., an RV pointing to an HV).
159 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
160 ? OPc_SVOP : OPc_PVOP;
168 case OA_BASEOP_OR_UNOP: TAG;
170 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
171 * whether parens were seen. perly.y uses OPf_SPECIAL to
172 * signal whether a BASEOP had empty parens or none.
173 * Some other UNOPs are created later, though, so the best
174 * test is OPf_KIDS, which is set in newUNOP.
176 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
178 case OA_FILESTATOP: TAG;
180 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
181 * the OPf_REF flag to distinguish between OP types instead of the
182 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
183 * return OPc_UNOP so that walkoptree can find our children. If
184 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
185 * (no argument to the operator) it's an OP; with OPf_REF set it's
186 * an SVOP (and op_sv is the GV for the filehandle argument).
188 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
190 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
192 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
194 case OA_LOOPEXOP: TAG;
196 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
197 * label was omitted (in which case it's a BASEOP) or else a term was
198 * seen. In this last case, all except goto are definitely PVOP but
199 * goto is either a PVOP (with an ordinary constant label), an UNOP
200 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
201 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
204 if (o->op_flags & OPf_STACKED)
206 else if (o->op_flags & OPf_SPECIAL)
211 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
212 PL_op_name[o->op_type]);
223 static int go_yell = 1;
225 /* Figure out how much magic is attached to the SV and return the
227 IV magic_size(const SV * const thing, TRACKING *tv) {
229 MAGIC *magic_pointer;
232 if (!SvMAGIC(thing)) {
237 /* Get the base magic pointer */
238 magic_pointer = SvMAGIC(thing);
240 /* Have we seen the magic pointer? */
241 while (magic_pointer && check_new(tv, magic_pointer)) {
242 total_size += sizeof(MAGIC);
245 /* Have we seen the magic vtable? */
246 if (magic_pointer->mg_virtual &&
247 check_new(tv, magic_pointer->mg_virtual)) {
248 total_size += sizeof(MGVTBL);
251 /* Get the next in the chain */ // ?try
252 magic_pointer = magic_pointer->mg_moremagic;
256 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
262 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
265 total_size += sizeof(REGEXP);
266 #if (PERL_VERSION < 11)
267 /* Note the size of the paren offset thing */
268 total_size += sizeof(I32) * baseregex->nparens * 2;
269 total_size += strlen(baseregex->precomp);
271 total_size += sizeof(struct regexp);
272 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
273 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
275 if (go_yell && !regex_whine) {
276 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
283 UV op_size(const OP * const baseop, TRACKING *tv) {
287 if (check_new(tv, baseop->op_next)) {
288 total_size += op_size(baseop->op_next, tv);
291 switch (cc_opclass(baseop)) {
292 case OPc_BASEOP: TAG;
293 total_size += sizeof(struct op);
296 total_size += sizeof(struct unop);
297 if (check_new(tv, cUNOPx(baseop)->op_first)) {
298 total_size += op_size(cUNOPx(baseop)->op_first, tv);
302 total_size += sizeof(struct binop);
303 if (check_new(tv, cBINOPx(baseop)->op_first)) {
304 total_size += op_size(cBINOPx(baseop)->op_first, tv);
306 if (check_new(tv, cBINOPx(baseop)->op_last)) {
307 total_size += op_size(cBINOPx(baseop)->op_last, tv);
311 total_size += sizeof(struct logop);
312 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
313 total_size += op_size(cBINOPx(baseop)->op_first, tv);
315 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
316 total_size += op_size(cLOGOPx(baseop)->op_other, tv);
319 case OPc_LISTOP: TAG;
320 total_size += sizeof(struct listop);
321 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
322 total_size += op_size(cLISTOPx(baseop)->op_first, tv);
324 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
325 total_size += op_size(cLISTOPx(baseop)->op_last, tv);
329 total_size += sizeof(struct pmop);
330 if (check_new(tv, cPMOPx(baseop)->op_first)) {
331 total_size += op_size(cPMOPx(baseop)->op_first, tv);
333 if (check_new(tv, cPMOPx(baseop)->op_last)) {
334 total_size += op_size(cPMOPx(baseop)->op_last, tv);
336 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
337 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
338 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tv);
340 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
341 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tv);
343 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
344 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tv);
347 /* This is defined away in perl 5.8.x, but it is in there for
350 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
351 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
354 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
355 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
360 total_size += sizeof(struct pmop);
361 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
362 total_size += thing_size(cSVOPx(baseop)->op_sv, tv);
366 total_size += sizeof(struct padop);
369 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
370 total_size += strlen(cPVOPx(baseop)->op_pv);
373 total_size += sizeof(struct loop);
374 if (check_new(tv, cLOOPx(baseop)->op_first)) {
375 total_size += op_size(cLOOPx(baseop)->op_first, tv);
377 if (check_new(tv, cLOOPx(baseop)->op_last)) {
378 total_size += op_size(cLOOPx(baseop)->op_last, tv);
380 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
381 total_size += op_size(cLOOPx(baseop)->op_redoop, tv);
383 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
384 total_size += op_size(cLOOPx(baseop)->op_nextop, tv);
386 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
387 total_size += op_size(cLOOPx(baseop)->op_lastop, tv);
394 basecop = (COP *)baseop;
395 total_size += sizeof(struct cop);
397 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
398 Eliminate cop_label from struct cop by storing a label as the first
399 entry in the hints hash. Most statements don't have labels, so this
400 will save memory. Not sure how much.
401 The check below will be incorrect fail on bleadperls
402 before 5.11 @33656, but later than 5.10, producing slightly too
403 small memory sizes on these Perls. */
404 #if (PERL_VERSION < 11)
405 if (check_new(tv, basecop->cop_label)) {
406 total_size += strlen(basecop->cop_label);
410 if (check_new(tv, basecop->cop_file)) {
411 total_size += strlen(basecop->cop_file);
413 if (check_new(tv, basecop->cop_stashpv)) {
414 total_size += strlen(basecop->cop_stashpv);
417 if (check_new(tv, basecop->cop_stash)) {
418 total_size += thing_size((SV *)basecop->cop_stash, tv);
420 if (check_new(tv, basecop->cop_filegv)) {
421 total_size += thing_size((SV *)basecop->cop_filegv, tv);
433 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
438 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
439 # define NEW_HEAD_LAYOUT
442 UV thing_size(const SV * const orig_thing, TRACKING *tv) {
443 const SV *thing = orig_thing;
444 UV total_size = sizeof(SV);
446 switch (SvTYPE(thing)) {
450 /* Just a plain integer. This will be differently sized depending
451 on whether purify's been compiled in */
453 #ifndef NEW_HEAD_LAYOUT
455 total_size += sizeof(sizeof(XPVIV));
457 total_size += sizeof(IV);
461 /* Is it a float? Like the int, it depends on purify */
464 total_size += sizeof(sizeof(XPVNV));
466 total_size += sizeof(NV);
469 #if (PERL_VERSION < 11)
470 /* Is it a reference? */
472 #ifndef NEW_HEAD_LAYOUT
473 total_size += sizeof(XRV);
477 /* How about a plain string? In which case we need to add in how
478 much has been allocated */
480 total_size += sizeof(XPV);
481 #if (PERL_VERSION < 11)
482 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
484 total_size += SvLEN(thing);
487 /* A string with an integer part? */
489 total_size += sizeof(XPVIV);
490 #if (PERL_VERSION < 11)
491 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
493 total_size += SvLEN(thing);
496 total_size += SvIVX(thing);
499 /* A scalar/string/reference with a float part? */
501 total_size += sizeof(XPVNV);
502 #if (PERL_VERSION < 11)
503 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
505 total_size += SvLEN(thing);
509 total_size += sizeof(XPVMG);
510 #if (PERL_VERSION < 11)
511 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
513 total_size += SvLEN(thing);
515 total_size += magic_size(thing, tv);
517 #if PERL_VERSION <= 8
519 total_size += sizeof(XPVBM);
520 #if (PERL_VERSION < 11)
521 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
523 total_size += SvLEN(thing);
525 total_size += magic_size(thing, tv);
529 total_size += sizeof(XPVLV);
530 #if (PERL_VERSION < 11)
531 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
533 total_size += SvLEN(thing);
535 total_size += magic_size(thing, tv);
537 /* How much space is dedicated to the array? Not counting the
538 elements in the array, mind, just the array itself */
540 total_size += sizeof(XPVAV);
541 /* Is there anything in the array? */
542 if (AvMAX(thing) != -1) {
543 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
544 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
545 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
547 /* Add in the bits on the other side of the beginning */
549 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
550 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
552 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
553 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
554 if (AvALLOC(thing) != 0) {
555 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
557 #if (PERL_VERSION < 9)
558 /* Is there something hanging off the arylen element?
559 Post 5.9.something this is stored in magic, so will be found there,
560 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
561 complain about AvARYLEN() passing thing to it. */
562 if (AvARYLEN(thing)) {
563 if (check_new(tv, AvARYLEN(thing))) {
564 total_size += thing_size(AvARYLEN(thing), tv);
568 total_size += magic_size(thing, tv);
571 /* First the base struct */
572 total_size += sizeof(XPVHV);
573 /* Now the array of buckets */
574 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
575 /* Now walk the bucket chain */
576 if (HvARRAY(thing)) {
579 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
580 cur_entry = *(HvARRAY(thing) + cur_bucket);
582 total_size += sizeof(HE);
583 if (cur_entry->hent_hek) {
584 /* Hash keys can be shared. Have we seen this before? */
585 if (check_new(tv, cur_entry->hent_hek)) {
586 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
589 cur_entry = cur_entry->hent_next;
593 total_size += magic_size(thing, tv);
596 total_size += sizeof(XPVCV);
597 total_size += magic_size(thing, tv);
599 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
600 if (check_new(tv, CvSTASH(thing))) {
601 total_size += thing_size((SV *)CvSTASH(thing), tv);
603 if (check_new(tv, SvSTASH(thing))) {
604 total_size += thing_size( (SV *)SvSTASH(thing), tv);
606 if (check_new(tv, CvGV(thing))) {
607 total_size += thing_size((SV *)CvGV(thing), tv);
609 if (check_new(tv, CvPADLIST(thing))) {
610 total_size += thing_size((SV *)CvPADLIST(thing), tv);
612 if (check_new(tv, CvOUTSIDE(thing))) {
613 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
615 if (check_new(tv, CvSTART(thing))) {
616 total_size += op_size(CvSTART(thing), tv);
618 if (check_new(tv, CvROOT(thing))) {
619 total_size += op_size(CvROOT(thing), tv);
624 total_size += magic_size(thing, tv);
625 total_size += sizeof(XPVGV);
626 total_size += GvNAMELEN(thing);
628 /* Is there a file? */
630 if (check_new(tv, GvFILE(thing))) {
631 total_size += strlen(GvFILE(thing));
635 /* Is there something hanging off the glob? */
637 if (check_new(tv, GvGP(thing))) {
638 total_size += sizeof(GP);
641 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
642 total_size += thing_size(generic_thing, tv);
644 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
645 total_size += thing_size(generic_thing, tv);
647 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
648 total_size += thing_size(generic_thing, tv);
650 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
651 total_size += thing_size(generic_thing, tv);
653 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
654 total_size += thing_size(generic_thing, tv);
656 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
657 total_size += thing_size(generic_thing, tv);
664 total_size += sizeof(XPVFM);
665 total_size += magic_size(thing, tv);
666 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
667 if (check_new(tv, CvPADLIST(thing))) {
668 total_size += thing_size((SV *)CvPADLIST(thing), tv);
670 if (check_new(tv, CvOUTSIDE(thing))) {
671 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
674 if (go_yell && !fm_whine) {
675 carp("Devel::Size: Calculated sizes for FMs are incomplete");
680 total_size += sizeof(XPVIO);
681 total_size += magic_size(thing, tv);
682 if (check_new(tv, (SvPVX_const(thing)))) {
683 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
685 /* Some embedded char pointers */
686 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
687 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
689 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
690 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
692 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
693 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
695 /* Throw the GVs on the list to be walked if they're not-null */
696 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
697 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
700 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
701 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
704 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
705 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
709 /* Only go trotting through the IO structures if they're really
710 trottable. If USE_PERLIO is defined we can do this. If
711 not... we can't, so we don't even try */
713 /* Dig into xio_ifp and xio_ofp here */
714 warn("Devel::Size: Can't size up perlio layers yet\n");
718 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
723 MODULE = Devel::Size PACKAGE = Devel::Size
733 SV *thing = orig_thing;
734 /* Hash to track our seen pointers */
735 //HV *tracking_hash = newHV();
738 Newz( 0xfc0ff, tv, 1, TRACKING );
740 /* Check warning status */
745 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
746 dangle_whine = go_yell = SvIV(warn_flag);
748 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
749 dangle_whine = SvIV(warn_flag);
752 /* If they passed us a reference then dereference it. This is the
753 only way we can check the sizes of arrays and hashes */
754 #if (PERL_VERSION < 11)
755 if (SvOK(thing) && SvROK(thing)) {
764 RETVAL = thing_size(thing, tv);
765 /* Clean up after ourselves */
766 //SvREFCNT_dec(tracking_hash);
767 for( i = 0; i < TRACKING_SLOTS; ++i ) {
769 Safefree( (*tv)[ i ] );
778 total_size(orig_thing)
783 SV *thing = orig_thing;
784 /* Hash to track our seen pointers */
787 /* Array with things we still need to do */
792 /* Size starts at zero */
795 /* Check warning status */
800 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
801 dangle_whine = go_yell = SvIV(warn_flag);
803 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
804 dangle_whine = SvIV(warn_flag);
807 /* init these after the go_yell above */
808 //tracking_hash = newHV();
809 Newz( 0xfc0ff, tv, 1, TRACKING );
810 pending_array = newAV();
812 /* We cannot push HV/AV directly, only the RV. So deref it
813 later (see below for "*** dereference later") and adjust here for
815 This is the only way we can check the sizes of arrays and hashes. */
817 RETVAL -= thing_size(thing, NULL);
820 /* Put it on the pending array */
821 av_push(pending_array, thing);
823 /* Now just yank things off the end of the array until it's done */
824 while (av_len(pending_array) >= 0) {
825 thing = av_pop(pending_array);
826 /* Process it if we've not seen it */
827 if (check_new(tv, thing)) {
828 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
831 /* Yes, it is. So let's check the type */
832 switch (SvTYPE(thing)) {
833 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
837 av_push(pending_array, SvRV(thing));
841 /* this is the "*** dereference later" part - see above */
842 #if (PERL_VERSION < 11)
847 dbg_printf(("# Found RV\n"));
849 dbg_printf(("# Found RV\n"));
850 av_push(pending_array, SvRV(thing));
856 AV *tempAV = (AV *)thing;
859 dbg_printf(("# Found type AV\n"));
860 /* Quick alias to cut down on casting */
863 if (av_len(tempAV) != -1) {
865 /* Run through them all */
866 for (index = 0; index <= av_len(tempAV); index++) {
867 /* Did we get something? */
868 if ((tempSV = av_fetch(tempAV, index, 0))) {
870 if (*tempSV != &PL_sv_undef) {
871 /* Apparently not. Save it for later */
872 av_push(pending_array, *tempSV);
881 dbg_printf(("# Found type HV\n"));
882 /* Is there anything in here? */
883 if (hv_iterinit((HV *)thing)) {
885 while ((temp_he = hv_iternext((HV *)thing))) {
886 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
892 dbg_printf(("# Found type GV\n"));
893 /* Run through all the pieces and push the ones with bits */
895 av_push(pending_array, (SV *)GvSV(thing));
898 av_push(pending_array, (SV *)GvFORM(thing));
901 av_push(pending_array, (SV *)GvAV(thing));
904 av_push(pending_array, (SV *)GvHV(thing));
907 av_push(pending_array, (SV *)GvCV(thing));
915 size = thing_size(thing, tv);
918 /* check_new() returned false: */
919 #ifdef DEVEL_SIZE_DEBUGGING
920 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
921 else printf("# Ignore non-sv 0x%x\n", sv);
926 /* Clean up after ourselves */
927 //SvREFCNT_dec(tracking_hash);
928 for( i = 0; i < TRACKING_SLOTS; ++i ) {
930 Safefree( (*tv)[ i ] );
933 SvREFCNT_dec(pending_array);