6 /* "structured exception" handling is a Microsoft extension to C and C++.
7 It's *not* C++ exception handling - C++ exception handling can't capture
8 SEGVs and suchlike, whereas this can. There's no known analagous
9 functionality on other platforms. */
11 # define TRY_TO_CATCH_SEGV __try
12 # define CAUGHT_EXCEPTION __except(EXCEPTION EXCEPTION_EXECUTE_HANDLER)
14 # define TRY_TO_CATCH_SEGV if(1)
15 # define CAUGHT_EXCEPTION else
19 # define __attribute__(x)
22 static int regex_whine;
24 static int dangle_whine = 0;
26 #if 0 && defined(DEBUGGING)
27 #define dbg_printf(x) printf x
32 #define TAG //printf( "# %s(%d)\n", __FILE__, __LINE__ )
35 #define ALIGN_BITS ( sizeof(void*) >> 1 )
38 #define SLOT_BITS ( sizeof( void*) * 8 ) - ( ALIGN_BITS + BIT_BITS + BYTE_BITS )
39 #define BYTES_PER_SLOT 1 << BYTE_BITS
40 #define TRACKING_SLOTS 8192 // max. 8192 for 4GB/32-bit machine
42 typedef char* TRACKING[ TRACKING_SLOTS ];
45 Checks to see if thing is in the bitstring.
46 Returns true or false, and
47 notes thing in the segmented bitstring.
49 IV check_new( TRACKING *tv, void *p ) {
50 unsigned long slot = (unsigned long)p >> (SLOT_BITS + BIT_BITS + ALIGN_BITS);
51 unsigned int byte = ((unsigned long)p >> (ALIGN_BITS + BIT_BITS)) & 0x00003fffU;
52 unsigned int bit = ((unsigned long)p >> ALIGN_BITS) & 0x00000007U;
53 unsigned int nop = (unsigned long)p & 0x3U;
55 if (NULL == p || NULL == tv) return FALSE;
61 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
65 "address: %p slot: %p byte: %4x bit: %4x nop:%x\n",
66 p, slot, byte, bit, nop
69 if( slot >= TRACKING_SLOTS ) {
70 die( "Devel::Size: Please rebuild D::S with TRACKING_SLOTS > %u\n", slot );
73 if( (*tv)[ slot ] == NULL ) {
74 Newz( 0xfc0ff, (*tv)[ slot ], BYTES_PER_SLOT, char );
77 if( (*tv)[ slot ][ byte ] & ( 1 << bit ) ) {
81 (*tv)[ slot ][ byte ] |= ( 1 << bit );
86 UV thing_size(const SV *const, TRACKING *);
103 cc_opclass(const OP * const o)
109 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
111 if (o->op_type == OP_SASSIGN)
112 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
115 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
119 if ((o->op_type == OP_TRANS)) {
123 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
148 case OA_PVOP_OR_SVOP: TAG;
150 * Character translations (tr///) are usually a PVOP, keeping a
151 * pointer to a table of shorts used to look up translations.
152 * Under utf8, however, a simple table isn't practical; instead,
153 * the OP is an SVOP, and the SV is a reference to a swash
154 * (i.e., an RV pointing to an HV).
156 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
157 ? OPc_SVOP : OPc_PVOP;
165 case OA_BASEOP_OR_UNOP: TAG;
167 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
168 * whether parens were seen. perly.y uses OPf_SPECIAL to
169 * signal whether a BASEOP had empty parens or none.
170 * Some other UNOPs are created later, though, so the best
171 * test is OPf_KIDS, which is set in newUNOP.
173 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
175 case OA_FILESTATOP: TAG;
177 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
178 * the OPf_REF flag to distinguish between OP types instead of the
179 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
180 * return OPc_UNOP so that walkoptree can find our children. If
181 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
182 * (no argument to the operator) it's an OP; with OPf_REF set it's
183 * an SVOP (and op_sv is the GV for the filehandle argument).
185 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
187 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
189 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
191 case OA_LOOPEXOP: TAG;
193 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
194 * label was omitted (in which case it's a BASEOP) or else a term was
195 * seen. In this last case, all except goto are definitely PVOP but
196 * goto is either a PVOP (with an ordinary constant label), an UNOP
197 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
198 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
201 if (o->op_flags & OPf_STACKED)
203 else if (o->op_flags & OPf_SPECIAL)
208 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
209 PL_op_name[o->op_type]);
220 static int go_yell = 1;
222 /* Figure out how much magic is attached to the SV and return the
224 IV magic_size(const SV * const thing, TRACKING *tv) {
226 MAGIC *magic_pointer;
229 if (!SvMAGIC(thing)) {
234 /* Get the base magic pointer */
235 magic_pointer = SvMAGIC(thing);
237 /* Have we seen the magic pointer? */
238 while (magic_pointer && check_new(tv, magic_pointer)) {
239 total_size += sizeof(MAGIC);
242 /* Have we seen the magic vtable? */
243 if (magic_pointer->mg_virtual &&
244 check_new(tv, magic_pointer->mg_virtual)) {
245 total_size += sizeof(MGVTBL);
248 /* Get the next in the chain */ // ?try
249 magic_pointer = magic_pointer->mg_moremagic;
253 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
259 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
262 total_size += sizeof(REGEXP);
263 #if (PERL_VERSION < 11)
264 /* Note the size of the paren offset thing */
265 total_size += sizeof(I32) * baseregex->nparens * 2;
266 total_size += strlen(baseregex->precomp);
268 total_size += sizeof(struct regexp);
269 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
270 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
272 if (go_yell && !regex_whine) {
273 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
280 UV op_size(const OP * const baseop, TRACKING *tv) {
284 if (check_new(tv, baseop->op_next)) {
285 total_size += op_size(baseop->op_next, tv);
288 switch (cc_opclass(baseop)) {
289 case OPc_BASEOP: TAG;
290 total_size += sizeof(struct op);
293 total_size += sizeof(struct unop);
294 if (check_new(tv, cUNOPx(baseop)->op_first)) {
295 total_size += op_size(cUNOPx(baseop)->op_first, tv);
299 total_size += sizeof(struct binop);
300 if (check_new(tv, cBINOPx(baseop)->op_first)) {
301 total_size += op_size(cBINOPx(baseop)->op_first, tv);
303 if (check_new(tv, cBINOPx(baseop)->op_last)) {
304 total_size += op_size(cBINOPx(baseop)->op_last, tv);
308 total_size += sizeof(struct logop);
309 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
310 total_size += op_size(cBINOPx(baseop)->op_first, tv);
312 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
313 total_size += op_size(cLOGOPx(baseop)->op_other, tv);
316 case OPc_LISTOP: TAG;
317 total_size += sizeof(struct listop);
318 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
319 total_size += op_size(cLISTOPx(baseop)->op_first, tv);
321 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
322 total_size += op_size(cLISTOPx(baseop)->op_last, tv);
326 total_size += sizeof(struct pmop);
327 if (check_new(tv, cPMOPx(baseop)->op_first)) {
328 total_size += op_size(cPMOPx(baseop)->op_first, tv);
330 if (check_new(tv, cPMOPx(baseop)->op_last)) {
331 total_size += op_size(cPMOPx(baseop)->op_last, tv);
333 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
334 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
335 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tv);
337 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
338 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tv);
340 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
341 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tv);
344 /* This is defined away in perl 5.8.x, but it is in there for
347 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
348 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
351 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
352 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
357 total_size += sizeof(struct pmop);
358 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
359 total_size += thing_size(cSVOPx(baseop)->op_sv, tv);
363 total_size += sizeof(struct padop);
366 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
367 total_size += strlen(cPVOPx(baseop)->op_pv);
370 total_size += sizeof(struct loop);
371 if (check_new(tv, cLOOPx(baseop)->op_first)) {
372 total_size += op_size(cLOOPx(baseop)->op_first, tv);
374 if (check_new(tv, cLOOPx(baseop)->op_last)) {
375 total_size += op_size(cLOOPx(baseop)->op_last, tv);
377 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
378 total_size += op_size(cLOOPx(baseop)->op_redoop, tv);
380 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
381 total_size += op_size(cLOOPx(baseop)->op_nextop, tv);
383 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
384 total_size += op_size(cLOOPx(baseop)->op_lastop, tv);
391 basecop = (COP *)baseop;
392 total_size += sizeof(struct cop);
394 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
395 Eliminate cop_label from struct cop by storing a label as the first
396 entry in the hints hash. Most statements don't have labels, so this
397 will save memory. Not sure how much.
398 The check below will be incorrect fail on bleadperls
399 before 5.11 @33656, but later than 5.10, producing slightly too
400 small memory sizes on these Perls. */
401 #if (PERL_VERSION < 11)
402 if (check_new(tv, basecop->cop_label)) {
403 total_size += strlen(basecop->cop_label);
407 if (check_new(tv, basecop->cop_file)) {
408 total_size += strlen(basecop->cop_file);
410 if (check_new(tv, basecop->cop_stashpv)) {
411 total_size += strlen(basecop->cop_stashpv);
414 if (check_new(tv, basecop->cop_stash)) {
415 total_size += thing_size((SV *)basecop->cop_stash, tv);
417 if (check_new(tv, basecop->cop_filegv)) {
418 total_size += thing_size((SV *)basecop->cop_filegv, tv);
430 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
435 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
436 # define NEW_HEAD_LAYOUT
439 UV thing_size(const SV * const orig_thing, TRACKING *tv) {
440 const SV *thing = orig_thing;
441 UV total_size = sizeof(SV);
443 switch (SvTYPE(thing)) {
447 /* Just a plain integer. This will be differently sized depending
448 on whether purify's been compiled in */
450 #ifndef NEW_HEAD_LAYOUT
452 total_size += sizeof(sizeof(XPVIV));
454 total_size += sizeof(IV);
458 /* Is it a float? Like the int, it depends on purify */
461 total_size += sizeof(sizeof(XPVNV));
463 total_size += sizeof(NV);
466 #if (PERL_VERSION < 11)
467 /* Is it a reference? */
469 #ifndef NEW_HEAD_LAYOUT
470 total_size += sizeof(XRV);
474 /* How about a plain string? In which case we need to add in how
475 much has been allocated */
477 total_size += sizeof(XPV);
478 #if (PERL_VERSION < 11)
479 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
481 total_size += SvLEN(thing);
484 /* A string with an integer part? */
486 total_size += sizeof(XPVIV);
487 #if (PERL_VERSION < 11)
488 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
490 total_size += SvLEN(thing);
493 total_size += SvIVX(thing);
496 /* A scalar/string/reference with a float part? */
498 total_size += sizeof(XPVNV);
499 #if (PERL_VERSION < 11)
500 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
502 total_size += SvLEN(thing);
506 total_size += sizeof(XPVMG);
507 #if (PERL_VERSION < 11)
508 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
510 total_size += SvLEN(thing);
512 total_size += magic_size(thing, tv);
514 #if PERL_VERSION <= 8
516 total_size += sizeof(XPVBM);
517 #if (PERL_VERSION < 11)
518 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
520 total_size += SvLEN(thing);
522 total_size += magic_size(thing, tv);
526 total_size += sizeof(XPVLV);
527 #if (PERL_VERSION < 11)
528 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
530 total_size += SvLEN(thing);
532 total_size += magic_size(thing, tv);
534 /* How much space is dedicated to the array? Not counting the
535 elements in the array, mind, just the array itself */
537 total_size += sizeof(XPVAV);
538 /* Is there anything in the array? */
539 if (AvMAX(thing) != -1) {
540 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
541 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
542 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
544 /* Add in the bits on the other side of the beginning */
546 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
547 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
549 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
550 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
551 if (AvALLOC(thing) != 0) {
552 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
554 #if (PERL_VERSION < 9)
555 /* Is there something hanging off the arylen element?
556 Post 5.9.something this is stored in magic, so will be found there,
557 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
558 complain about AvARYLEN() passing thing to it. */
559 if (AvARYLEN(thing)) {
560 if (check_new(tv, AvARYLEN(thing))) {
561 total_size += thing_size(AvARYLEN(thing), tv);
565 total_size += magic_size(thing, tv);
568 /* First the base struct */
569 total_size += sizeof(XPVHV);
570 /* Now the array of buckets */
571 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
572 /* Now walk the bucket chain */
573 if (HvARRAY(thing)) {
576 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
577 cur_entry = *(HvARRAY(thing) + cur_bucket);
579 total_size += sizeof(HE);
580 if (cur_entry->hent_hek) {
581 /* Hash keys can be shared. Have we seen this before? */
582 if (check_new(tv, cur_entry->hent_hek)) {
583 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
586 cur_entry = cur_entry->hent_next;
590 total_size += magic_size(thing, tv);
593 total_size += sizeof(XPVCV);
594 total_size += magic_size(thing, tv);
596 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
597 if (check_new(tv, CvSTASH(thing))) {
598 total_size += thing_size((SV *)CvSTASH(thing), tv);
600 if (check_new(tv, SvSTASH(thing))) {
601 total_size += thing_size( (SV *)SvSTASH(thing), tv);
603 if (check_new(tv, CvGV(thing))) {
604 total_size += thing_size((SV *)CvGV(thing), tv);
606 if (check_new(tv, CvPADLIST(thing))) {
607 total_size += thing_size((SV *)CvPADLIST(thing), tv);
609 if (check_new(tv, CvOUTSIDE(thing))) {
610 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
612 if (check_new(tv, CvSTART(thing))) {
613 total_size += op_size(CvSTART(thing), tv);
615 if (check_new(tv, CvROOT(thing))) {
616 total_size += op_size(CvROOT(thing), tv);
621 total_size += magic_size(thing, tv);
622 total_size += sizeof(XPVGV);
623 total_size += GvNAMELEN(thing);
625 /* Is there a file? */
627 if (check_new(tv, GvFILE(thing))) {
628 total_size += strlen(GvFILE(thing));
632 /* Is there something hanging off the glob? */
634 if (check_new(tv, GvGP(thing))) {
635 total_size += sizeof(GP);
638 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
639 total_size += thing_size(generic_thing, tv);
641 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
642 total_size += thing_size(generic_thing, tv);
644 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
645 total_size += thing_size(generic_thing, tv);
647 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
648 total_size += thing_size(generic_thing, tv);
650 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
651 total_size += thing_size(generic_thing, tv);
653 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
654 total_size += thing_size(generic_thing, tv);
661 total_size += sizeof(XPVFM);
662 total_size += magic_size(thing, tv);
663 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
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);
671 if (go_yell && !fm_whine) {
672 carp("Devel::Size: Calculated sizes for FMs are incomplete");
677 total_size += sizeof(XPVIO);
678 total_size += magic_size(thing, tv);
679 if (check_new(tv, (SvPVX(thing)))) {
680 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
682 /* Some embedded char pointers */
683 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
684 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
686 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
687 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
689 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
690 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
692 /* Throw the GVs on the list to be walked if they're not-null */
693 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
694 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
697 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
698 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
701 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
702 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
706 /* Only go trotting through the IO structures if they're really
707 trottable. If USE_PERLIO is defined we can do this. If
708 not... we can't, so we don't even try */
710 /* Dig into xio_ifp and xio_ofp here */
711 warn("Devel::Size: Can't size up perlio layers yet\n");
715 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
720 MODULE = Devel::Size PACKAGE = Devel::Size
730 SV *thing = orig_thing;
731 /* Hash to track our seen pointers */
732 //HV *tracking_hash = newHV();
735 Newz( 0xfc0ff, tv, 1, TRACKING );
737 /* Check warning status */
742 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
743 dangle_whine = go_yell = SvIV(warn_flag);
745 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
746 dangle_whine = SvIV(warn_flag);
749 /* If they passed us a reference then dereference it. This is the
750 only way we can check the sizes of arrays and hashes */
751 #if (PERL_VERSION < 11)
752 if (SvOK(thing) && SvROK(thing)) {
761 RETVAL = thing_size(thing, tv);
762 /* Clean up after ourselves */
763 //SvREFCNT_dec(tracking_hash);
764 for( i = 0; i < TRACKING_SLOTS; ++i ) {
766 Safefree( (*tv)[ i ] );
775 total_size(orig_thing)
780 SV *thing = orig_thing;
781 /* Hash to track our seen pointers */
784 /* Array with things we still need to do */
789 /* Size starts at zero */
792 /* Check warning status */
797 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
798 dangle_whine = go_yell = SvIV(warn_flag);
800 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
801 dangle_whine = SvIV(warn_flag);
804 /* init these after the go_yell above */
805 //tracking_hash = newHV();
806 Newz( 0xfc0ff, tv, 1, TRACKING );
807 pending_array = newAV();
809 /* We cannot push HV/AV directly, only the RV. So deref it
810 later (see below for "*** dereference later") and adjust here for
812 This is the only way we can check the sizes of arrays and hashes. */
814 RETVAL -= thing_size(thing, NULL);
817 /* Put it on the pending array */
818 av_push(pending_array, thing);
820 /* Now just yank things off the end of the array until it's done */
821 while (av_len(pending_array) >= 0) {
822 thing = av_pop(pending_array);
823 /* Process it if we've not seen it */
824 if (check_new(tv, thing)) {
825 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
828 /* Yes, it is. So let's check the type */
829 switch (SvTYPE(thing)) {
830 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
834 av_push(pending_array, SvRV(thing));
838 /* this is the "*** dereference later" part - see above */
839 #if (PERL_VERSION < 11)
844 dbg_printf(("# Found RV\n"));
846 dbg_printf(("# Found RV\n"));
847 av_push(pending_array, SvRV(thing));
853 AV *tempAV = (AV *)thing;
856 dbg_printf(("# Found type AV\n"));
857 /* Quick alias to cut down on casting */
860 if (av_len(tempAV) != -1) {
862 /* Run through them all */
863 for (index = 0; index <= av_len(tempAV); index++) {
864 /* Did we get something? */
865 if ((tempSV = av_fetch(tempAV, index, 0))) {
867 if (*tempSV != &PL_sv_undef) {
868 /* Apparently not. Save it for later */
869 av_push(pending_array, *tempSV);
878 dbg_printf(("# Found type HV\n"));
879 /* Is there anything in here? */
880 if (hv_iterinit((HV *)thing)) {
882 while ((temp_he = hv_iternext((HV *)thing))) {
883 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
889 dbg_printf(("# Found type GV\n"));
890 /* Run through all the pieces and push the ones with bits */
892 av_push(pending_array, (SV *)GvSV(thing));
895 av_push(pending_array, (SV *)GvFORM(thing));
898 av_push(pending_array, (SV *)GvAV(thing));
901 av_push(pending_array, (SV *)GvHV(thing));
904 av_push(pending_array, (SV *)GvCV(thing));
912 size = thing_size(thing, tv);
915 /* check_new() returned false: */
916 #ifdef DEVEL_SIZE_DEBUGGING
917 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
918 else printf("# Ignore non-sv 0x%x\n", sv);
923 /* Clean up after ourselves */
924 //SvREFCNT_dec(tracking_hash);
925 for( i = 0; i < TRACKING_SLOTS; ++i ) {
927 Safefree( (*tv)[ i ] );
930 SvREFCNT_dec(pending_array);