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 );
90 free_tracking(TRACKING *tv)
93 /* Clean up after ourselves */
94 for( i = 0; i < TRACKING_SLOTS; ++i ) {
96 Safefree( (*tv)[ i ] );
101 UV thing_size(const SV *const, TRACKING *);
118 cc_opclass(const OP * const o)
124 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
126 if (o->op_type == OP_SASSIGN)
127 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
130 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
134 if ((o->op_type == OP_TRANS)) {
138 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
163 case OA_PVOP_OR_SVOP: TAG;
165 * Character translations (tr///) are usually a PVOP, keeping a
166 * pointer to a table of shorts used to look up translations.
167 * Under utf8, however, a simple table isn't practical; instead,
168 * the OP is an SVOP, and the SV is a reference to a swash
169 * (i.e., an RV pointing to an HV).
171 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
172 ? OPc_SVOP : OPc_PVOP;
180 case OA_BASEOP_OR_UNOP: TAG;
182 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
183 * whether parens were seen. perly.y uses OPf_SPECIAL to
184 * signal whether a BASEOP had empty parens or none.
185 * Some other UNOPs are created later, though, so the best
186 * test is OPf_KIDS, which is set in newUNOP.
188 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
190 case OA_FILESTATOP: TAG;
192 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
193 * the OPf_REF flag to distinguish between OP types instead of the
194 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
195 * return OPc_UNOP so that walkoptree can find our children. If
196 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
197 * (no argument to the operator) it's an OP; with OPf_REF set it's
198 * an SVOP (and op_sv is the GV for the filehandle argument).
200 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
202 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
204 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
206 case OA_LOOPEXOP: TAG;
208 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
209 * label was omitted (in which case it's a BASEOP) or else a term was
210 * seen. In this last case, all except goto are definitely PVOP but
211 * goto is either a PVOP (with an ordinary constant label), an UNOP
212 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
213 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
216 if (o->op_flags & OPf_STACKED)
218 else if (o->op_flags & OPf_SPECIAL)
223 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
224 PL_op_name[o->op_type]);
235 static int go_yell = 1;
237 /* Figure out how much magic is attached to the SV and return the
239 IV magic_size(const SV * const thing, TRACKING *tv) {
241 MAGIC *magic_pointer;
244 if (!SvMAGIC(thing)) {
249 /* Get the base magic pointer */
250 magic_pointer = SvMAGIC(thing);
252 /* Have we seen the magic pointer? */
253 while (magic_pointer && check_new(tv, magic_pointer)) {
254 total_size += sizeof(MAGIC);
257 /* Have we seen the magic vtable? */
258 if (magic_pointer->mg_virtual &&
259 check_new(tv, magic_pointer->mg_virtual)) {
260 total_size += sizeof(MGVTBL);
263 /* Get the next in the chain */ // ?try
264 magic_pointer = magic_pointer->mg_moremagic;
268 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
274 UV regex_size(const REGEXP * const baseregex, TRACKING *tv) {
277 total_size += sizeof(REGEXP);
278 #if (PERL_VERSION < 11)
279 /* Note the size of the paren offset thing */
280 total_size += sizeof(I32) * baseregex->nparens * 2;
281 total_size += strlen(baseregex->precomp);
283 total_size += sizeof(struct regexp);
284 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
285 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
287 if (go_yell && !regex_whine) {
288 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
295 UV op_size(const OP * const baseop, TRACKING *tv) {
299 if (check_new(tv, baseop->op_next)) {
300 total_size += op_size(baseop->op_next, tv);
303 switch (cc_opclass(baseop)) {
304 case OPc_BASEOP: TAG;
305 total_size += sizeof(struct op);
308 total_size += sizeof(struct unop);
309 if (check_new(tv, cUNOPx(baseop)->op_first)) {
310 total_size += op_size(cUNOPx(baseop)->op_first, tv);
314 total_size += sizeof(struct binop);
315 if (check_new(tv, cBINOPx(baseop)->op_first)) {
316 total_size += op_size(cBINOPx(baseop)->op_first, tv);
318 if (check_new(tv, cBINOPx(baseop)->op_last)) {
319 total_size += op_size(cBINOPx(baseop)->op_last, tv);
323 total_size += sizeof(struct logop);
324 if (check_new(tv, cLOGOPx(baseop)->op_first)) {
325 total_size += op_size(cBINOPx(baseop)->op_first, tv);
327 if (check_new(tv, cLOGOPx(baseop)->op_other)) {
328 total_size += op_size(cLOGOPx(baseop)->op_other, tv);
331 case OPc_LISTOP: TAG;
332 total_size += sizeof(struct listop);
333 if (check_new(tv, cLISTOPx(baseop)->op_first)) {
334 total_size += op_size(cLISTOPx(baseop)->op_first, tv);
336 if (check_new(tv, cLISTOPx(baseop)->op_last)) {
337 total_size += op_size(cLISTOPx(baseop)->op_last, tv);
341 total_size += sizeof(struct pmop);
342 if (check_new(tv, cPMOPx(baseop)->op_first)) {
343 total_size += op_size(cPMOPx(baseop)->op_first, tv);
345 if (check_new(tv, cPMOPx(baseop)->op_last)) {
346 total_size += op_size(cPMOPx(baseop)->op_last, tv);
348 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
349 if (check_new(tv, cPMOPx(baseop)->op_pmreplroot)) {
350 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tv);
352 if (check_new(tv, cPMOPx(baseop)->op_pmreplstart)) {
353 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tv);
355 if (check_new(tv, cPMOPx(baseop)->op_pmnext)) {
356 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tv);
359 /* This is defined away in perl 5.8.x, but it is in there for
362 if (check_new(tv, PM_GETRE((cPMOPx(baseop))))) {
363 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tv);
366 if (check_new(tv, cPMOPx(baseop)->op_pmregexp)) {
367 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tv);
372 total_size += sizeof(struct pmop);
373 if (check_new(tv, cSVOPx(baseop)->op_sv)) {
374 total_size += thing_size(cSVOPx(baseop)->op_sv, tv);
378 total_size += sizeof(struct padop);
381 if (check_new(tv, cPVOPx(baseop)->op_pv)) {
382 total_size += strlen(cPVOPx(baseop)->op_pv);
385 total_size += sizeof(struct loop);
386 if (check_new(tv, cLOOPx(baseop)->op_first)) {
387 total_size += op_size(cLOOPx(baseop)->op_first, tv);
389 if (check_new(tv, cLOOPx(baseop)->op_last)) {
390 total_size += op_size(cLOOPx(baseop)->op_last, tv);
392 if (check_new(tv, cLOOPx(baseop)->op_redoop)) {
393 total_size += op_size(cLOOPx(baseop)->op_redoop, tv);
395 if (check_new(tv, cLOOPx(baseop)->op_nextop)) {
396 total_size += op_size(cLOOPx(baseop)->op_nextop, tv);
398 if (check_new(tv, cLOOPx(baseop)->op_lastop)) {
399 total_size += op_size(cLOOPx(baseop)->op_lastop, tv);
406 basecop = (COP *)baseop;
407 total_size += sizeof(struct cop);
409 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
410 Eliminate cop_label from struct cop by storing a label as the first
411 entry in the hints hash. Most statements don't have labels, so this
412 will save memory. Not sure how much.
413 The check below will be incorrect fail on bleadperls
414 before 5.11 @33656, but later than 5.10, producing slightly too
415 small memory sizes on these Perls. */
416 #if (PERL_VERSION < 11)
417 if (check_new(tv, basecop->cop_label)) {
418 total_size += strlen(basecop->cop_label);
422 if (check_new(tv, basecop->cop_file)) {
423 total_size += strlen(basecop->cop_file);
425 if (check_new(tv, basecop->cop_stashpv)) {
426 total_size += strlen(basecop->cop_stashpv);
429 if (check_new(tv, basecop->cop_stash)) {
430 total_size += thing_size((SV *)basecop->cop_stash, tv);
432 if (check_new(tv, basecop->cop_filegv)) {
433 total_size += thing_size((SV *)basecop->cop_filegv, tv);
445 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
450 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
451 # define NEW_HEAD_LAYOUT
454 UV thing_size(const SV * const orig_thing, TRACKING *tv) {
455 const SV *thing = orig_thing;
456 UV total_size = sizeof(SV);
458 switch (SvTYPE(thing)) {
462 /* Just a plain integer. This will be differently sized depending
463 on whether purify's been compiled in */
465 #ifndef NEW_HEAD_LAYOUT
467 total_size += sizeof(sizeof(XPVIV));
469 total_size += sizeof(IV);
473 /* Is it a float? Like the int, it depends on purify */
476 total_size += sizeof(sizeof(XPVNV));
478 total_size += sizeof(NV);
481 #if (PERL_VERSION < 11)
482 /* Is it a reference? */
484 #ifndef NEW_HEAD_LAYOUT
485 total_size += sizeof(XRV);
489 /* How about a plain string? In which case we need to add in how
490 much has been allocated */
492 total_size += sizeof(XPV);
493 #if (PERL_VERSION < 11)
494 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
496 total_size += SvLEN(thing);
499 /* A string with an integer part? */
501 total_size += sizeof(XPVIV);
502 #if (PERL_VERSION < 11)
503 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
505 total_size += SvLEN(thing);
508 total_size += SvIVX(thing);
511 /* A scalar/string/reference with a float part? */
513 total_size += sizeof(XPVNV);
514 #if (PERL_VERSION < 11)
515 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
517 total_size += SvLEN(thing);
521 total_size += sizeof(XPVMG);
522 #if (PERL_VERSION < 11)
523 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
525 total_size += SvLEN(thing);
527 total_size += magic_size(thing, tv);
529 #if PERL_VERSION <= 8
531 total_size += sizeof(XPVBM);
532 #if (PERL_VERSION < 11)
533 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
535 total_size += SvLEN(thing);
537 total_size += magic_size(thing, tv);
541 total_size += sizeof(XPVLV);
542 #if (PERL_VERSION < 11)
543 total_size += SvROK(thing) ? thing_size( SvRV(thing), tv) : SvLEN(thing);
545 total_size += SvLEN(thing);
547 total_size += magic_size(thing, tv);
549 /* How much space is dedicated to the array? Not counting the
550 elements in the array, mind, just the array itself */
552 total_size += sizeof(XPVAV);
553 /* Is there anything in the array? */
554 if (AvMAX(thing) != -1) {
555 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
556 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
557 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
559 /* Add in the bits on the other side of the beginning */
561 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
562 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
564 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
565 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
566 if (AvALLOC(thing) != 0) {
567 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
569 #if (PERL_VERSION < 9)
570 /* Is there something hanging off the arylen element?
571 Post 5.9.something this is stored in magic, so will be found there,
572 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
573 complain about AvARYLEN() passing thing to it. */
574 if (AvARYLEN(thing)) {
575 if (check_new(tv, AvARYLEN(thing))) {
576 total_size += thing_size(AvARYLEN(thing), tv);
580 total_size += magic_size(thing, tv);
583 /* First the base struct */
584 total_size += sizeof(XPVHV);
585 /* Now the array of buckets */
586 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
587 /* Now walk the bucket chain */
588 if (HvARRAY(thing)) {
591 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
592 cur_entry = *(HvARRAY(thing) + cur_bucket);
594 total_size += sizeof(HE);
595 if (cur_entry->hent_hek) {
596 /* Hash keys can be shared. Have we seen this before? */
597 if (check_new(tv, cur_entry->hent_hek)) {
598 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
601 cur_entry = cur_entry->hent_next;
605 total_size += magic_size(thing, tv);
608 total_size += sizeof(XPVCV);
609 total_size += magic_size(thing, tv);
611 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
612 if (check_new(tv, CvSTASH(thing))) {
613 total_size += thing_size((SV *)CvSTASH(thing), tv);
615 if (check_new(tv, SvSTASH(thing))) {
616 total_size += thing_size( (SV *)SvSTASH(thing), tv);
618 if (check_new(tv, CvGV(thing))) {
619 total_size += thing_size((SV *)CvGV(thing), tv);
621 if (check_new(tv, CvPADLIST(thing))) {
622 total_size += thing_size((SV *)CvPADLIST(thing), tv);
624 if (check_new(tv, CvOUTSIDE(thing))) {
625 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
627 if (check_new(tv, CvSTART(thing))) {
628 total_size += op_size(CvSTART(thing), tv);
630 if (check_new(tv, CvROOT(thing))) {
631 total_size += op_size(CvROOT(thing), tv);
636 total_size += magic_size(thing, tv);
637 total_size += sizeof(XPVGV);
638 total_size += GvNAMELEN(thing);
640 /* Is there a file? */
642 if (check_new(tv, GvFILE(thing))) {
643 total_size += strlen(GvFILE(thing));
647 /* Is there something hanging off the glob? */
649 if (check_new(tv, GvGP(thing))) {
650 total_size += sizeof(GP);
653 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
654 total_size += thing_size(generic_thing, tv);
656 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
657 total_size += thing_size(generic_thing, tv);
659 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
660 total_size += thing_size(generic_thing, tv);
662 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
663 total_size += thing_size(generic_thing, tv);
665 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
666 total_size += thing_size(generic_thing, tv);
668 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
669 total_size += thing_size(generic_thing, tv);
676 total_size += sizeof(XPVFM);
677 total_size += magic_size(thing, tv);
678 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
679 if (check_new(tv, CvPADLIST(thing))) {
680 total_size += thing_size((SV *)CvPADLIST(thing), tv);
682 if (check_new(tv, CvOUTSIDE(thing))) {
683 total_size += thing_size((SV *)CvOUTSIDE(thing), tv);
686 if (go_yell && !fm_whine) {
687 carp("Devel::Size: Calculated sizes for FMs are incomplete");
692 total_size += sizeof(XPVIO);
693 total_size += magic_size(thing, tv);
694 if (check_new(tv, (SvPVX_const(thing)))) {
695 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
697 /* Some embedded char pointers */
698 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_top_name)) {
699 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
701 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
702 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
704 if (check_new(tv, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
705 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
707 /* Throw the GVs on the list to be walked if they're not-null */
708 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
709 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
712 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
713 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
716 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
717 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
721 /* Only go trotting through the IO structures if they're really
722 trottable. If USE_PERLIO is defined we can do this. If
723 not... we can't, so we don't even try */
725 /* Dig into xio_ifp and xio_ofp here */
726 warn("Devel::Size: Can't size up perlio layers yet\n");
730 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
735 MODULE = Devel::Size PACKAGE = Devel::Size
744 SV *thing = orig_thing;
745 /* Hash to track our seen pointers */
746 //HV *tracking_hash = newHV();
749 Newz( 0xfc0ff, tv, 1, TRACKING );
751 /* Check warning status */
756 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
757 dangle_whine = go_yell = SvIV(warn_flag);
759 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
760 dangle_whine = SvIV(warn_flag);
763 /* If they passed us a reference then dereference it. This is the
764 only way we can check the sizes of arrays and hashes */
765 #if (PERL_VERSION < 11)
766 if (SvOK(thing) && SvROK(thing)) {
775 RETVAL = thing_size(thing, tv);
783 total_size(orig_thing)
787 SV *thing = orig_thing;
788 /* Hash to track our seen pointers */
791 /* Array with things we still need to do */
796 /* Size starts at zero */
799 /* Check warning status */
804 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
805 dangle_whine = go_yell = SvIV(warn_flag);
807 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
808 dangle_whine = SvIV(warn_flag);
811 /* init these after the go_yell above */
812 //tracking_hash = newHV();
813 Newz( 0xfc0ff, tv, 1, TRACKING );
814 pending_array = newAV();
816 /* We cannot push HV/AV directly, only the RV. So deref it
817 later (see below for "*** dereference later") and adjust here for
819 This is the only way we can check the sizes of arrays and hashes. */
821 RETVAL -= thing_size(thing, NULL);
824 /* Put it on the pending array */
825 av_push(pending_array, thing);
827 /* Now just yank things off the end of the array until it's done */
828 while (av_len(pending_array) >= 0) {
829 thing = av_pop(pending_array);
830 /* Process it if we've not seen it */
831 if (check_new(tv, thing)) {
832 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
835 /* Yes, it is. So let's check the type */
836 switch (SvTYPE(thing)) {
837 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
841 av_push(pending_array, SvRV(thing));
845 /* this is the "*** dereference later" part - see above */
846 #if (PERL_VERSION < 11)
851 dbg_printf(("# Found RV\n"));
853 dbg_printf(("# Found RV\n"));
854 av_push(pending_array, SvRV(thing));
860 AV *tempAV = (AV *)thing;
863 dbg_printf(("# Found type AV\n"));
864 /* Quick alias to cut down on casting */
867 if (av_len(tempAV) != -1) {
869 /* Run through them all */
870 for (index = 0; index <= av_len(tempAV); index++) {
871 /* Did we get something? */
872 if ((tempSV = av_fetch(tempAV, index, 0))) {
874 if (*tempSV != &PL_sv_undef) {
875 /* Apparently not. Save it for later */
876 av_push(pending_array, *tempSV);
885 dbg_printf(("# Found type HV\n"));
886 /* Is there anything in here? */
887 if (hv_iterinit((HV *)thing)) {
889 while ((temp_he = hv_iternext((HV *)thing))) {
890 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
896 dbg_printf(("# Found type GV\n"));
897 /* Run through all the pieces and push the ones with bits */
899 av_push(pending_array, (SV *)GvSV(thing));
902 av_push(pending_array, (SV *)GvFORM(thing));
905 av_push(pending_array, (SV *)GvAV(thing));
908 av_push(pending_array, (SV *)GvHV(thing));
911 av_push(pending_array, (SV *)GvCV(thing));
919 size = thing_size(thing, tv);
922 /* check_new() returned false: */
923 #ifdef DEVEL_SIZE_DEBUGGING
924 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
925 else printf("# Ignore non-sv 0x%x\n", sv);
931 SvREFCNT_dec(pending_array);