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;
57 if (NULL == p || NULL == tv) return FALSE;
59 const char c = *(const char *)p;
63 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
67 "address: %p slot: %p byte: %4x bit: %4x nop:%x\n",
68 p, slot, byte, bit, nop
71 if( slot >= TRACKING_SLOTS ) {
72 die( "Devel::Size: Please rebuild D::S with TRACKING_SLOTS > %u\n", slot );
75 if( (*tv)[ slot ] == NULL ) {
76 Newz( 0xfc0ff, (*tv)[ slot ], BYTES_PER_SLOT, char );
79 if( (*tv)[ slot ][ byte ] & ( 1 << bit ) ) {
83 (*tv)[ slot ][ byte ] |= ( 1 << bit );
88 UV thing_size(const SV *const, TRACKING *);
105 cc_opclass(const OP * const o)
111 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
113 if (o->op_type == OP_SASSIGN)
114 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
117 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
121 if ((o->op_type == OP_TRANS)) {
125 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
150 case OA_PVOP_OR_SVOP: TAG;
152 * Character translations (tr///) are usually a PVOP, keeping a
153 * pointer to a table of shorts used to look up translations.
154 * Under utf8, however, a simple table isn't practical; instead,
155 * the OP is an SVOP, and the SV is a reference to a swash
156 * (i.e., an RV pointing to an HV).
158 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
159 ? OPc_SVOP : OPc_PVOP;
167 case OA_BASEOP_OR_UNOP: TAG;
169 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
170 * whether parens were seen. perly.y uses OPf_SPECIAL to
171 * signal whether a BASEOP had empty parens or none.
172 * Some other UNOPs are created later, though, so the best
173 * test is OPf_KIDS, which is set in newUNOP.
175 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
177 case OA_FILESTATOP: TAG;
179 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
180 * the OPf_REF flag to distinguish between OP types instead of the
181 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
182 * return OPc_UNOP so that walkoptree can find our children. If
183 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
184 * (no argument to the operator) it's an OP; with OPf_REF set it's
185 * an SVOP (and op_sv is the GV for the filehandle argument).
187 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
189 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
191 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
193 case OA_LOOPEXOP: TAG;
195 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
196 * label was omitted (in which case it's a BASEOP) or else a term was
197 * seen. In this last case, all except goto are definitely PVOP but
198 * goto is either a PVOP (with an ordinary constant label), an UNOP
199 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
200 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
203 if (o->op_flags & OPf_STACKED)
205 else if (o->op_flags & OPf_SPECIAL)
210 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
211 PL_op_name[o->op_type]);
222 static int go_yell = 1;
224 /* Figure out how much magic is attached to the SV and return the
226 IV magic_size(const SV * const thing, TRACKING *tv) {
228 MAGIC *magic_pointer;
231 if (!SvMAGIC(thing)) {
236 /* Get the base magic pointer */
237 magic_pointer = SvMAGIC(thing);
239 /* Have we seen the magic pointer? */
240 while (magic_pointer && check_new(tv, magic_pointer)) {
241 total_size += sizeof(MAGIC);
244 /* Have we seen the magic vtable? */
245 if (magic_pointer->mg_virtual &&
246 check_new(tv, magic_pointer->mg_virtual)) {
247 total_size += sizeof(MGVTBL);
250 /* Get the next in the chain */ // ?try
251 magic_pointer = magic_pointer->mg_moremagic;
255 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
261 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
264 total_size += sizeof(REGEXP);
265 #if (PERL_VERSION < 11)
266 /* Note the size of the paren offset thing */
267 total_size += sizeof(I32) * baseregex->nparens * 2;
268 total_size += strlen(baseregex->precomp);
270 total_size += sizeof(struct regexp);
271 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
272 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
274 if (go_yell && !regex_whine) {
275 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
282 UV op_size(const OP * const baseop, TRACKING *tv) {
286 if (check_new(tv, baseop->op_next)) {
287 total_size += op_size(baseop->op_next, tv);
290 switch (cc_opclass(baseop)) {
291 case OPc_BASEOP: TAG;
292 total_size += sizeof(struct op);
295 total_size += sizeof(struct unop);
296 if (check_new(tv, cUNOPx(baseop)->op_first)) {
297 total_size += op_size(cUNOPx(baseop)->op_first, tv);
301 total_size += sizeof(struct binop);
302 if (check_new(tv, cBINOPx(baseop)->op_first)) {
303 total_size += op_size(cBINOPx(baseop)->op_first, tv);
305 if (check_new(tv, cBINOPx(baseop)->op_last)) {
306 total_size += op_size(cBINOPx(baseop)->op_last, tv);
310 total_size += sizeof(struct logop);
311 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
312 total_size += op_size(cBINOPx(baseop)->op_first, tv);
314 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
315 total_size += op_size(cLOGOPx(baseop)->op_other, tv);
318 case OPc_LISTOP: TAG;
319 total_size += sizeof(struct listop);
320 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
321 total_size += op_size(cLISTOPx(baseop)->op_first, tv);
323 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
324 total_size += op_size(cLISTOPx(baseop)->op_last, tv);
328 total_size += sizeof(struct pmop);
329 if (check_new(tv, cPMOPx(baseop)->op_first)) {
330 total_size += op_size(cPMOPx(baseop)->op_first, tv);
332 if (check_new(tv, cPMOPx(baseop)->op_last)) {
333 total_size += op_size(cPMOPx(baseop)->op_last, tv);
335 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
336 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
337 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tv);
339 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
340 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tv);
342 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
343 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tv);
346 /* This is defined away in perl 5.8.x, but it is in there for
349 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
350 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
353 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
354 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
359 total_size += sizeof(struct pmop);
360 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
361 total_size += thing_size(cSVOPx(baseop)->op_sv, tv);
365 total_size += sizeof(struct padop);
368 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
369 total_size += strlen(cPVOPx(baseop)->op_pv);
372 total_size += sizeof(struct loop);
373 if (check_new(tv, cLOOPx(baseop)->op_first)) {
374 total_size += op_size(cLOOPx(baseop)->op_first, tv);
376 if (check_new(tv, cLOOPx(baseop)->op_last)) {
377 total_size += op_size(cLOOPx(baseop)->op_last, tv);
379 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
380 total_size += op_size(cLOOPx(baseop)->op_redoop, tv);
382 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
383 total_size += op_size(cLOOPx(baseop)->op_nextop, tv);
385 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
386 total_size += op_size(cLOOPx(baseop)->op_lastop, tv);
393 basecop = (COP *)baseop;
394 total_size += sizeof(struct cop);
396 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
397 Eliminate cop_label from struct cop by storing a label as the first
398 entry in the hints hash. Most statements don't have labels, so this
399 will save memory. Not sure how much.
400 The check below will be incorrect fail on bleadperls
401 before 5.11 @33656, but later than 5.10, producing slightly too
402 small memory sizes on these Perls. */
403 #if (PERL_VERSION < 11)
404 if (check_new(tv, basecop->cop_label)) {
405 total_size += strlen(basecop->cop_label);
409 if (check_new(tv, basecop->cop_file)) {
410 total_size += strlen(basecop->cop_file);
412 if (check_new(tv, basecop->cop_stashpv)) {
413 total_size += strlen(basecop->cop_stashpv);
416 if (check_new(tv, basecop->cop_stash)) {
417 total_size += thing_size((SV *)basecop->cop_stash, tv);
419 if (check_new(tv, basecop->cop_filegv)) {
420 total_size += thing_size((SV *)basecop->cop_filegv, tv);
432 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
437 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
438 # define NEW_HEAD_LAYOUT
441 UV thing_size(const SV * const orig_thing, TRACKING *tv) {
442 const SV *thing = orig_thing;
443 UV total_size = sizeof(SV);
445 switch (SvTYPE(thing)) {
449 /* Just a plain integer. This will be differently sized depending
450 on whether purify's been compiled in */
452 #ifndef NEW_HEAD_LAYOUT
454 total_size += sizeof(sizeof(XPVIV));
456 total_size += sizeof(IV);
460 /* Is it a float? Like the int, it depends on purify */
463 total_size += sizeof(sizeof(XPVNV));
465 total_size += sizeof(NV);
468 #if (PERL_VERSION < 11)
469 /* Is it a reference? */
471 #ifndef NEW_HEAD_LAYOUT
472 total_size += sizeof(XRV);
476 /* How about a plain string? In which case we need to add in how
477 much has been allocated */
479 total_size += sizeof(XPV);
480 #if (PERL_VERSION < 11)
481 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
483 total_size += SvLEN(thing);
486 /* A string with an integer part? */
488 total_size += sizeof(XPVIV);
489 #if (PERL_VERSION < 11)
490 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
492 total_size += SvLEN(thing);
495 total_size += SvIVX(thing);
498 /* A scalar/string/reference with a float part? */
500 total_size += sizeof(XPVNV);
501 #if (PERL_VERSION < 11)
502 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
504 total_size += SvLEN(thing);
508 total_size += sizeof(XPVMG);
509 #if (PERL_VERSION < 11)
510 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
512 total_size += SvLEN(thing);
514 total_size += magic_size(thing, tv);
516 #if PERL_VERSION <= 8
518 total_size += sizeof(XPVBM);
519 #if (PERL_VERSION < 11)
520 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
522 total_size += SvLEN(thing);
524 total_size += magic_size(thing, tv);
528 total_size += sizeof(XPVLV);
529 #if (PERL_VERSION < 11)
530 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
532 total_size += SvLEN(thing);
534 total_size += magic_size(thing, tv);
536 /* How much space is dedicated to the array? Not counting the
537 elements in the array, mind, just the array itself */
539 total_size += sizeof(XPVAV);
540 /* Is there anything in the array? */
541 if (AvMAX(thing) != -1) {
542 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
543 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
544 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
546 /* Add in the bits on the other side of the beginning */
548 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
549 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
551 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
552 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
553 if (AvALLOC(thing) != 0) {
554 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
556 #if (PERL_VERSION < 9)
557 /* Is there something hanging off the arylen element?
558 Post 5.9.something this is stored in magic, so will be found there,
559 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
560 complain about AvARYLEN() passing thing to it. */
561 if (AvARYLEN(thing)) {
562 if (check_new(tv, AvARYLEN(thing))) {
563 total_size += thing_size(AvARYLEN(thing), tv);
567 total_size += magic_size(thing, tv);
570 /* First the base struct */
571 total_size += sizeof(XPVHV);
572 /* Now the array of buckets */
573 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
574 /* Now walk the bucket chain */
575 if (HvARRAY(thing)) {
578 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
579 cur_entry = *(HvARRAY(thing) + cur_bucket);
581 total_size += sizeof(HE);
582 if (cur_entry->hent_hek) {
583 /* Hash keys can be shared. Have we seen this before? */
584 if (check_new(tv, cur_entry->hent_hek)) {
585 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
588 cur_entry = cur_entry->hent_next;
592 total_size += magic_size(thing, tv);
595 total_size += sizeof(XPVCV);
596 total_size += magic_size(thing, tv);
598 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
599 if (check_new(tv, CvSTASH(thing))) {
600 total_size += thing_size((SV *)CvSTASH(thing), tv);
602 if (check_new(tv, SvSTASH(thing))) {
603 total_size += thing_size( (SV *)SvSTASH(thing), tv);
605 if (check_new(tv, CvGV(thing))) {
606 total_size += thing_size((SV *)CvGV(thing), tv);
608 if (check_new(tv, CvPADLIST(thing))) {
609 total_size += thing_size((SV *)CvPADLIST(thing), tv);
611 if (check_new(tv, CvOUTSIDE(thing))) {
612 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
614 if (check_new(tv, CvSTART(thing))) {
615 total_size += op_size(CvSTART(thing), tv);
617 if (check_new(tv, CvROOT(thing))) {
618 total_size += op_size(CvROOT(thing), tv);
623 total_size += magic_size(thing, tv);
624 total_size += sizeof(XPVGV);
625 total_size += GvNAMELEN(thing);
627 /* Is there a file? */
629 if (check_new(tv, GvFILE(thing))) {
630 total_size += strlen(GvFILE(thing));
634 /* Is there something hanging off the glob? */
636 if (check_new(tv, GvGP(thing))) {
637 total_size += sizeof(GP);
640 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
641 total_size += thing_size(generic_thing, tv);
643 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
644 total_size += thing_size(generic_thing, tv);
646 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
647 total_size += thing_size(generic_thing, tv);
649 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
650 total_size += thing_size(generic_thing, tv);
652 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
653 total_size += thing_size(generic_thing, tv);
655 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
656 total_size += thing_size(generic_thing, tv);
663 total_size += sizeof(XPVFM);
664 total_size += magic_size(thing, tv);
665 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
666 if (check_new(tv, CvPADLIST(thing))) {
667 total_size += thing_size((SV *)CvPADLIST(thing), tv);
669 if (check_new(tv, CvOUTSIDE(thing))) {
670 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
673 if (go_yell && !fm_whine) {
674 carp("Devel::Size: Calculated sizes for FMs are incomplete");
679 total_size += sizeof(XPVIO);
680 total_size += magic_size(thing, tv);
681 if (check_new(tv, (SvPVX_const(thing)))) {
682 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
684 /* Some embedded char pointers */
685 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
686 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
688 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
689 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
691 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
692 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
694 /* Throw the GVs on the list to be walked if they're not-null */
695 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
696 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
699 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
700 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
703 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
704 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
708 /* Only go trotting through the IO structures if they're really
709 trottable. If USE_PERLIO is defined we can do this. If
710 not... we can't, so we don't even try */
712 /* Dig into xio_ifp and xio_ofp here */
713 warn("Devel::Size: Can't size up perlio layers yet\n");
717 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
722 MODULE = Devel::Size PACKAGE = Devel::Size
732 SV *thing = orig_thing;
733 /* Hash to track our seen pointers */
734 //HV *tracking_hash = newHV();
737 Newz( 0xfc0ff, tv, 1, TRACKING );
739 /* Check warning status */
744 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
745 dangle_whine = go_yell = SvIV(warn_flag);
747 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
748 dangle_whine = SvIV(warn_flag);
751 /* If they passed us a reference then dereference it. This is the
752 only way we can check the sizes of arrays and hashes */
753 #if (PERL_VERSION < 11)
754 if (SvOK(thing) && SvROK(thing)) {
763 RETVAL = thing_size(thing, tv);
764 /* Clean up after ourselves */
765 //SvREFCNT_dec(tracking_hash);
766 for( i = 0; i < TRACKING_SLOTS; ++i ) {
768 Safefree( (*tv)[ i ] );
777 total_size(orig_thing)
782 SV *thing = orig_thing;
783 /* Hash to track our seen pointers */
786 /* Array with things we still need to do */
791 /* Size starts at zero */
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 /* init these after the go_yell above */
807 //tracking_hash = newHV();
808 Newz( 0xfc0ff, tv, 1, TRACKING );
809 pending_array = newAV();
811 /* We cannot push HV/AV directly, only the RV. So deref it
812 later (see below for "*** dereference later") and adjust here for
814 This is the only way we can check the sizes of arrays and hashes. */
816 RETVAL -= thing_size(thing, NULL);
819 /* Put it on the pending array */
820 av_push(pending_array, thing);
822 /* Now just yank things off the end of the array until it's done */
823 while (av_len(pending_array) >= 0) {
824 thing = av_pop(pending_array);
825 /* Process it if we've not seen it */
826 if (check_new(tv, thing)) {
827 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
830 /* Yes, it is. So let's check the type */
831 switch (SvTYPE(thing)) {
832 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
836 av_push(pending_array, SvRV(thing));
840 /* this is the "*** dereference later" part - see above */
841 #if (PERL_VERSION < 11)
846 dbg_printf(("# Found RV\n"));
848 dbg_printf(("# Found RV\n"));
849 av_push(pending_array, SvRV(thing));
855 AV *tempAV = (AV *)thing;
858 dbg_printf(("# Found type AV\n"));
859 /* Quick alias to cut down on casting */
862 if (av_len(tempAV) != -1) {
864 /* Run through them all */
865 for (index = 0; index <= av_len(tempAV); index++) {
866 /* Did we get something? */
867 if ((tempSV = av_fetch(tempAV, index, 0))) {
869 if (*tempSV != &PL_sv_undef) {
870 /* Apparently not. Save it for later */
871 av_push(pending_array, *tempSV);
880 dbg_printf(("# Found type HV\n"));
881 /* Is there anything in here? */
882 if (hv_iterinit((HV *)thing)) {
884 while ((temp_he = hv_iternext((HV *)thing))) {
885 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
891 dbg_printf(("# Found type GV\n"));
892 /* Run through all the pieces and push the ones with bits */
894 av_push(pending_array, (SV *)GvSV(thing));
897 av_push(pending_array, (SV *)GvFORM(thing));
900 av_push(pending_array, (SV *)GvAV(thing));
903 av_push(pending_array, (SV *)GvHV(thing));
906 av_push(pending_array, (SV *)GvCV(thing));
914 size = thing_size(thing, tv);
917 /* check_new() returned false: */
918 #ifdef DEVEL_SIZE_DEBUGGING
919 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
920 else printf("# Ignore non-sv 0x%x\n", sv);
925 /* Clean up after ourselves */
926 //SvREFCNT_dec(tracking_hash);
927 for( i = 0; i < TRACKING_SLOTS; ++i ) {
929 Safefree( (*tv)[ i ] );
932 SvREFCNT_dec(pending_array);