1 #define PERL_NO_GET_CONTEXT
8 /* Not yet in ppport.h */
10 # define CvISXSUB(cv) (CvXSUB(cv) ? TRUE : FALSE)
13 # define SvRV_const(rv) SvRV(rv)
17 /* "structured exception" handling is a Microsoft extension to C and C++.
18 It's *not* C++ exception handling - C++ exception handling can't capture
19 SEGVs and suchlike, whereas this can. There's no known analagous
20 functionality on other platforms. */
22 # define TRY_TO_CATCH_SEGV __try
23 # define CAUGHT_EXCEPTION __except(EXCEPTION EXCEPTION_EXECUTE_HANDLER)
25 # define TRY_TO_CATCH_SEGV if(1)
26 # define CAUGHT_EXCEPTION else
30 # define __attribute__(x)
33 #if 0 && defined(DEBUGGING)
34 #define dbg_printf(x) printf x
39 #define TAG /* printf( "# %s(%d)\n", __FILE__, __LINE__ ) */
42 /* The idea is to have a tree structure to store 1 bit per possible pointer
43 address. The lowest 16 bits are stored in a block of 8092 bytes.
44 The blocks are in a 256-way tree, indexed by the reset of the pointer.
45 This can cope with 32 and 64 bit pointers, and any address space layout,
46 without excessive memory needs. The assumption is that your CPU cache
47 works :-) (And that we're not going to bust it) */
50 #define LEAF_BITS (16 - BYTE_BITS)
51 #define LEAF_MASK 0x1FFF
59 /* My hunch (not measured) is that for most architectures pointers will
60 start with 0 bits, hence the start of this array will be hot, and the
61 end unused. So put the flags next to the hot end. */
66 Checks to see if thing is in the bitstring.
67 Returns true or false, and
68 notes thing in the segmented bitstring.
71 check_new(struct state *st, const void *const p) {
72 unsigned int bits = 8 * sizeof(void*);
73 const size_t raw_p = PTR2nat(p);
74 /* This effectively rotates the value right by the number of low always-0
75 bits in an aligned pointer. The assmption is that most (if not all)
76 pointers are aligned, and these will be in the same chain of nodes
77 (and hence hot in the cache) but we can still deal with any unaligned
80 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - ALIGN_BITS));
81 const U8 this_bit = 1 << (cooked_p & 0x7);
85 void **tv_p = (void **) (st->tracking);
87 if (NULL == p) return FALSE;
89 const char c = *(const char *)p;
93 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
99 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
101 /* First level is always present. */
103 i = (unsigned int)((cooked_p >> bits) & 0xFF);
105 Newxz(tv_p[i], 256, void *);
106 tv_p = (void **)(tv_p[i]);
108 } while (bits > LEAF_BITS + BYTE_BITS);
109 /* bits now 16 always */
110 #if !defined(MULTIPLICITY) || PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8)
111 /* 5.8.8 and early have an assert() macro that uses Perl_croak, hence needs
112 a my_perl under multiplicity */
115 leaf_p = (U8 **)tv_p;
116 i = (unsigned int)((cooked_p >> bits) & 0xFF);
118 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
123 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
125 if(leaf[i] & this_bit)
133 free_tracking_at(void **tv, int level)
141 free_tracking_at(tv[i], level);
155 free_state(struct state *st)
157 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
158 free_tracking_at((void **)st->tracking, top_level);
162 /* For now, this is somewhat a compatibility bodge until the plan comes
163 together for fine grained recursion control. total_size() would recurse into
164 hash and array members, whereas sv_size() would not. However, sv_size() is
165 called with CvSTASH() of a CV, which means that if it (also) starts to
166 recurse fully, then the size of any CV now becomes the size of the entire
167 symbol table reachable from it, and potentially the entire symbol table, if
168 any subroutine makes a reference to a global (such as %SIG). The historical
169 implementation of total_size() didn't report "everything", and changing the
170 only available size to "everything" doesn't feel at all useful. */
172 #define NO_RECURSION 0
173 #define SOME_RECURSION 1
174 #define TOTAL_SIZE_RECURSION 2
176 static bool sv_size(pTHX_ struct state *, const SV *const, const int recurse);
194 cc_opclass(const OP * const o)
200 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
202 if (o->op_type == OP_SASSIGN)
203 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
206 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
210 if ((o->op_type == OP_TRANS)) {
214 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
239 case OA_PVOP_OR_SVOP: TAG;
241 * Character translations (tr///) are usually a PVOP, keeping a
242 * pointer to a table of shorts used to look up translations.
243 * Under utf8, however, a simple table isn't practical; instead,
244 * the OP is an SVOP, and the SV is a reference to a swash
245 * (i.e., an RV pointing to an HV).
247 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
248 ? OPc_SVOP : OPc_PVOP;
256 case OA_BASEOP_OR_UNOP: TAG;
258 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
259 * whether parens were seen. perly.y uses OPf_SPECIAL to
260 * signal whether a BASEOP had empty parens or none.
261 * Some other UNOPs are created later, though, so the best
262 * test is OPf_KIDS, which is set in newUNOP.
264 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
266 case OA_FILESTATOP: TAG;
268 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
269 * the OPf_REF flag to distinguish between OP types instead of the
270 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
271 * return OPc_UNOP so that walkoptree can find our children. If
272 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
273 * (no argument to the operator) it's an OP; with OPf_REF set it's
274 * an SVOP (and op_sv is the GV for the filehandle argument).
276 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
278 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
280 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
282 case OA_LOOPEXOP: TAG;
284 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
285 * label was omitted (in which case it's a BASEOP) or else a term was
286 * seen. In this last case, all except goto are definitely PVOP but
287 * goto is either a PVOP (with an ordinary constant label), an UNOP
288 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
289 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
292 if (o->op_flags & OPf_STACKED)
294 else if (o->op_flags & OPf_SPECIAL)
299 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
300 PL_op_name[o->op_type]);
311 /* Figure out how much magic is attached to the SV and return the
314 magic_size(pTHX_ const SV * const thing, struct state *st) {
315 MAGIC *magic_pointer;
318 if (!SvMAGIC(thing)) {
323 /* Get the base magic pointer */
324 magic_pointer = SvMAGIC(thing);
326 /* Have we seen the magic pointer? */
327 while (check_new(st, magic_pointer)) {
328 st->total_size += sizeof(MAGIC);
331 /* Have we seen the magic vtable? */
332 if (check_new(st, magic_pointer->mg_virtual)) {
333 st->total_size += sizeof(MGVTBL);
335 sv_size(aTHX_ st, magic_pointer->mg_obj, TOTAL_SIZE_RECURSION);
336 if (magic_pointer->mg_len == HEf_SVKEY) {
337 sv_size(aTHX_ st, (SV *)magic_pointer->mg_ptr, TOTAL_SIZE_RECURSION);
339 #if defined(PERL_MAGIC_utf8) && defined (PERL_MAGIC_UTF8_CACHESIZE)
340 else if (magic_pointer->mg_type == PERL_MAGIC_utf8) {
341 if (check_new(st, magic_pointer->mg_ptr)) {
342 st->total_size += PERL_MAGIC_UTF8_CACHESIZE * 2 * sizeof(STRLEN);
346 else if (magic_pointer->mg_len > 0) {
347 if (check_new(st, magic_pointer->mg_ptr)) {
348 st->total_size += magic_pointer->mg_len;
352 /* Get the next in the chain */
353 magic_pointer = magic_pointer->mg_moremagic;
356 if (st->dangle_whine)
357 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
363 check_new_and_strlen(struct state *st, const char *const p) {
365 st->total_size += 1 + strlen(p);
369 regex_size(const REGEXP * const baseregex, struct state *st) {
370 if(!check_new(st, baseregex))
372 st->total_size += sizeof(REGEXP);
373 #if (PERL_VERSION < 11)
374 /* Note the size of the paren offset thing */
375 st->total_size += sizeof(I32) * baseregex->nparens * 2;
376 st->total_size += strlen(baseregex->precomp);
378 st->total_size += sizeof(struct regexp);
379 st->total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
380 /*st->total_size += strlen(SvANY(baseregex)->subbeg);*/
382 if (st->go_yell && !st->regex_whine) {
383 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
389 op_size(pTHX_ const OP * const baseop, struct state *st)
393 if(!check_new(st, baseop))
396 op_size(aTHX_ baseop->op_next, st);
398 switch (cc_opclass(baseop)) {
399 case OPc_BASEOP: TAG;
400 st->total_size += sizeof(struct op);
403 st->total_size += sizeof(struct unop);
404 op_size(aTHX_ cUNOPx(baseop)->op_first, st);
407 st->total_size += sizeof(struct binop);
408 op_size(aTHX_ cBINOPx(baseop)->op_first, st);
409 op_size(aTHX_ cBINOPx(baseop)->op_last, st);
412 st->total_size += sizeof(struct logop);
413 op_size(aTHX_ cBINOPx(baseop)->op_first, st);
414 op_size(aTHX_ cLOGOPx(baseop)->op_other, st);
416 case OPc_LISTOP: TAG;
417 st->total_size += sizeof(struct listop);
418 op_size(aTHX_ cLISTOPx(baseop)->op_first, st);
419 op_size(aTHX_ cLISTOPx(baseop)->op_last, st);
422 st->total_size += sizeof(struct pmop);
423 op_size(aTHX_ cPMOPx(baseop)->op_first, st);
424 op_size(aTHX_ cPMOPx(baseop)->op_last, st);
425 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
426 op_size(aTHX_ cPMOPx(baseop)->op_pmreplroot, st);
427 op_size(aTHX_ cPMOPx(baseop)->op_pmreplstart, st);
428 op_size(aTHX_ (OP *)cPMOPx(baseop)->op_pmnext, st);
430 /* This is defined away in perl 5.8.x, but it is in there for
433 regex_size(PM_GETRE(cPMOPx(baseop)), st);
435 regex_size(cPMOPx(baseop)->op_pmregexp, st);
439 st->total_size += sizeof(struct pmop);
440 if (!(baseop->op_type == OP_AELEMFAST
441 && baseop->op_flags & OPf_SPECIAL)) {
442 /* not an OP_PADAV replacement */
443 sv_size(aTHX_ st, cSVOPx(baseop)->op_sv, SOME_RECURSION);
447 st->total_size += sizeof(struct padop);
450 check_new_and_strlen(st, cPVOPx(baseop)->op_pv);
453 st->total_size += sizeof(struct loop);
454 op_size(aTHX_ cLOOPx(baseop)->op_first, st);
455 op_size(aTHX_ cLOOPx(baseop)->op_last, st);
456 op_size(aTHX_ cLOOPx(baseop)->op_redoop, st);
457 op_size(aTHX_ cLOOPx(baseop)->op_nextop, st);
458 op_size(aTHX_ cLOOPx(baseop)->op_lastop, st);
463 basecop = (COP *)baseop;
464 st->total_size += sizeof(struct cop);
466 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
467 Eliminate cop_label from struct cop by storing a label as the first
468 entry in the hints hash. Most statements don't have labels, so this
469 will save memory. Not sure how much.
470 The check below will be incorrect fail on bleadperls
471 before 5.11 @33656, but later than 5.10, producing slightly too
472 small memory sizes on these Perls. */
473 #if (PERL_VERSION < 11)
474 check_new_and_strlen(st, basecop->cop_label);
477 check_new_and_strlen(st, basecop->cop_file);
478 check_new_and_strlen(st, basecop->cop_stashpv);
480 sv_size(aTHX_ st, (SV *)basecop->cop_stash, SOME_RECURSION);
481 sv_size(aTHX_ st, (SV *)basecop->cop_filegv, SOME_RECURSION);
491 if (st->dangle_whine)
492 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
496 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
497 # define NEW_HEAD_LAYOUT
501 sv_size(pTHX_ struct state *const st, const SV * const orig_thing,
503 const SV *thing = orig_thing;
505 if(!check_new(st, thing))
508 st->total_size += sizeof(SV);
510 switch (SvTYPE(thing)) {
514 /* Just a plain integer. This will be differently sized depending
515 on whether purify's been compiled in */
517 #ifndef NEW_HEAD_LAYOUT
519 st->total_size += sizeof(sizeof(XPVIV));
521 st->total_size += sizeof(IV);
524 if(recurse && SvROK(thing))
525 sv_size(aTHX_ st, SvRV_const(thing), recurse);
527 /* Is it a float? Like the int, it depends on purify */
530 st->total_size += sizeof(sizeof(XPVNV));
532 st->total_size += sizeof(NV);
535 #if (PERL_VERSION < 11)
536 /* Is it a reference? */
538 #ifndef NEW_HEAD_LAYOUT
539 st->total_size += sizeof(XRV);
541 if(recurse && SvROK(thing))
542 sv_size(aTHX_ st, SvRV_const(thing), recurse);
545 /* How about a plain string? In which case we need to add in how
546 much has been allocated */
548 st->total_size += sizeof(XPV);
549 if(recurse && SvROK(thing))
550 sv_size(aTHX_ st, SvRV_const(thing), recurse);
552 st->total_size += SvLEN(thing);
554 /* A string with an integer part? */
556 st->total_size += sizeof(XPVIV);
557 if(recurse && SvROK(thing))
558 sv_size(aTHX_ st, SvRV_const(thing), recurse);
560 st->total_size += SvLEN(thing);
562 st->total_size += SvIVX(thing);
565 /* A scalar/string/reference with a float part? */
567 st->total_size += sizeof(XPVNV);
568 if(recurse && SvROK(thing))
569 sv_size(aTHX_ st, SvRV_const(thing), recurse);
571 st->total_size += SvLEN(thing);
574 st->total_size += sizeof(XPVMG);
575 if(recurse && SvROK(thing))
576 sv_size(aTHX_ st, SvRV_const(thing), recurse);
578 st->total_size += SvLEN(thing);
579 magic_size(aTHX_ thing, st);
581 #if PERL_VERSION <= 8
583 st->total_size += sizeof(XPVBM);
584 if(recurse && SvROK(thing))
585 sv_size(aTHX_ st, SvRV_const(thing), recurse);
587 st->total_size += SvLEN(thing);
588 magic_size(aTHX_ thing, st);
592 st->total_size += sizeof(XPVLV);
593 if(recurse && SvROK(thing))
594 sv_size(aTHX_ st, SvRV_const(thing), recurse);
596 st->total_size += SvLEN(thing);
597 magic_size(aTHX_ thing, st);
599 /* How much space is dedicated to the array? Not counting the
600 elements in the array, mind, just the array itself */
602 st->total_size += sizeof(XPVAV);
603 /* Is there anything in the array? */
604 if (AvMAX(thing) != -1) {
605 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
606 st->total_size += sizeof(SV *) * (AvMAX(thing) + 1);
607 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", st->total_size, AvMAX(thing), av_len((AV*)thing)));
609 if (recurse >= TOTAL_SIZE_RECURSION) {
610 SSize_t i = AvFILLp(thing) + 1;
613 sv_size(aTHX_ st, AvARRAY(thing)[i], recurse);
616 /* Add in the bits on the other side of the beginning */
618 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
619 st->total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
621 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
622 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
623 if (AvALLOC(thing) != 0) {
624 st->total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
626 #if (PERL_VERSION < 9)
627 /* Is there something hanging off the arylen element?
628 Post 5.9.something this is stored in magic, so will be found there,
629 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
630 complain about AvARYLEN() passing thing to it. */
631 sv_size(aTHX_ st, AvARYLEN(thing), recurse);
633 magic_size(aTHX_ thing, st);
636 /* First the base struct */
637 st->total_size += sizeof(XPVHV);
638 /* Now the array of buckets */
639 st->total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
640 /* Now walk the bucket chain */
641 if (HvARRAY(thing)) {
644 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
645 cur_entry = *(HvARRAY(thing) + cur_bucket);
647 st->total_size += sizeof(HE);
648 if (cur_entry->hent_hek) {
649 /* Hash keys can be shared. Have we seen this before? */
650 if (check_new(st, cur_entry->hent_hek)) {
651 st->total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
654 if (recurse >= TOTAL_SIZE_RECURSION)
655 sv_size(aTHX_ st, HeVAL(cur_entry), recurse);
656 cur_entry = cur_entry->hent_next;
660 magic_size(aTHX_ thing, st);
663 st->total_size += sizeof(XPVCV);
664 magic_size(aTHX_ thing, st);
666 st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
667 sv_size(aTHX_ st, (SV *)CvSTASH(thing), SOME_RECURSION);
668 sv_size(aTHX_ st, (SV *)SvSTASH(thing), SOME_RECURSION);
669 sv_size(aTHX_ st, (SV *)CvGV(thing), SOME_RECURSION);
670 sv_size(aTHX_ st, (SV *)CvPADLIST(thing), SOME_RECURSION);
671 sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
672 if (CvISXSUB(thing)) {
673 sv_size(aTHX_ st, cv_const_sv((CV *)thing), recurse);
675 op_size(aTHX_ CvSTART(thing), st);
676 op_size(aTHX_ CvROOT(thing), st);
681 magic_size(aTHX_ thing, st);
682 st->total_size += sizeof(XPVGV);
683 if(isGV_with_GP(thing)) {
684 st->total_size += GvNAMELEN(thing);
686 # if !defined(USE_ITHREADS) || (PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8))
687 /* With itreads, before 5.8.9, this can end up pointing to freed memory
688 if the GV was created in an eval, as GvFILE() points to CopFILE(),
689 and the relevant COP has been freed on scope cleanup after the eval.
690 5.8.9 adds a binary compatible fudge that catches the vast majority
691 of cases. 5.9.something added a proper fix, by converting the GP to
692 use a shared hash key (porperly reference counted), instead of a
693 char * (owned by who knows? possibly no-one now) */
694 check_new_and_strlen(st, GvFILE(thing));
697 /* Is there something hanging off the glob? */
698 if (check_new(st, GvGP(thing))) {
699 st->total_size += sizeof(GP);
700 sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_sv), recurse);
701 sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_form), recurse);
702 sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_av), recurse);
703 sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_hv), recurse);
704 sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_egv), recurse);
705 sv_size(aTHX_ st, (SV *)(GvGP(thing)->gp_cv), recurse);
710 st->total_size += sizeof(XPVFM);
711 magic_size(aTHX_ thing, st);
712 st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
713 sv_size(aTHX_ st, (SV *)CvPADLIST(thing), SOME_RECURSION);
714 sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
716 if (st->go_yell && !st->fm_whine) {
717 carp("Devel::Size: Calculated sizes for FMs are incomplete");
722 st->total_size += sizeof(XPVIO);
723 magic_size(aTHX_ thing, st);
724 if (check_new(st, (SvPVX_const(thing)))) {
725 st->total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
727 /* Some embedded char pointers */
728 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_top_name);
729 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_fmt_name);
730 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_bottom_name);
731 /* Throw the GVs on the list to be walked if they're not-null */
732 sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_top_gv, recurse);
733 sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv, recurse);
734 sv_size(aTHX_ st, (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv, recurse);
736 /* Only go trotting through the IO structures if they're really
737 trottable. If USE_PERLIO is defined we can do this. If
738 not... we can't, so we don't even try */
740 /* Dig into xio_ifp and xio_ofp here */
741 warn("Devel::Size: Can't size up perlio layers yet\n");
745 warn("Devel::Size: Unknown variable type: %d encountered\n", SvTYPE(thing) );
751 #include "vtables.inc"
755 static struct state *
760 void **vt_p = vtables;
762 Newxz(st, 1, struct state);
764 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
765 st->dangle_whine = st->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
767 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
768 st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
770 check_new(st, &PL_sv_undef);
771 check_new(st, &PL_sv_no);
772 check_new(st, &PL_sv_yes);
774 check_new(st, *vt_p++);
778 MODULE = Devel::Size PACKAGE = Devel::Size
786 total_size = TOTAL_SIZE_RECURSION
789 SV *thing = orig_thing;
790 struct state *st = new_state(aTHX);
792 /* If they passed us a reference then dereference it. This is the
793 only way we can check the sizes of arrays and hashes */
798 sv_size(aTHX_ st, thing, ix);
799 RETVAL = st->total_size;