3 #undef NDEBUG /* XXX */
6 #define PERL_NO_GET_CONTEXT
13 /* Not yet in ppport.h */
15 # define CvISXSUB(cv) (CvXSUB(cv) ? TRUE : FALSE)
18 # define SvRV_const(rv) SvRV(rv)
21 # define SvOOK_offset(sv, len) STMT_START { len = SvIVX(sv); } STMT_END
24 # define SvIsCOW(sv) ((SvFLAGS(sv) & (SVf_FAKE | SVf_READONLY)) == \
25 (SVf_FAKE | SVf_READONLY))
27 #ifndef SvIsCOW_shared_hash
28 # define SvIsCOW_shared_hash(sv) (SvIsCOW(sv) && SvLEN(sv) == 0)
30 #ifndef SvSHARED_HEK_FROM_PV
31 # define SvSHARED_HEK_FROM_PV(pvx) \
32 ((struct hek*)(pvx - STRUCT_OFFSET(struct hek, hek_key)))
36 # define PL_opargs opargs
37 # define PL_op_name op_name
41 /* "structured exception" handling is a Microsoft extension to C and C++.
42 It's *not* C++ exception handling - C++ exception handling can't capture
43 SEGVs and suchlike, whereas this can. There's no known analagous
44 functionality on other platforms. */
46 # define TRY_TO_CATCH_SEGV __try
47 # define CAUGHT_EXCEPTION __except(EXCEPTION_EXECUTE_HANDLER)
49 # define TRY_TO_CATCH_SEGV if(1)
50 # define CAUGHT_EXCEPTION else
54 # define __attribute__(x)
57 #if 0 && defined(DEBUGGING)
58 #define dbg_printf(x) printf x
63 #define TAG /* printf( "# %s(%d)\n", __FILE__, __LINE__ ) */
66 /* The idea is to have a tree structure to store 1 bit per possible pointer
67 address. The lowest 16 bits are stored in a block of 8092 bytes.
68 The blocks are in a 256-way tree, indexed by the reset of the pointer.
69 This can cope with 32 and 64 bit pointers, and any address space layout,
70 without excessive memory needs. The assumption is that your CPU cache
71 works :-) (And that we're not going to bust it) */
74 #define LEAF_BITS (16 - BYTE_BITS)
75 #define LEAF_MASK 0x1FFF
77 typedef struct npath_node_st npath_node_t;
78 struct npath_node_st {
93 /* My hunch (not measured) is that for most architectures pointers will
94 start with 0 bits, hence the start of this array will be hot, and the
95 end unused. So put the flags next to the hot end. */
97 /* callback hooks and data */
98 int (*add_attr_cb)(struct state *st, npath_node_t *npath_node, UV attr_type, const char *name, UV value);
99 void (*free_state_cb)(struct state *st);
101 void *state_cb_data; /* free'd by free_state() after free_state_cb() call */
104 #define ADD_SIZE(st, leafname, bytes) (NPathAddSizeCb(st, leafname, bytes) (st)->total_size += (bytes))
106 #define PATH_TRACKING
109 #define NPathAddSizeCb(st, name, bytes) (st->add_attr_cb && st->add_attr_cb(st, NP-1, 0, (name), (bytes))),
110 #define pPATH npath_node_t *NPathArg
112 /* A subtle point here is that each dNPathSetNode leaves NP pointing to
113 * the next unused slot (though with prev already filled in)
114 * whereas NPathLink leaves NP unchanged, it just fills in the slot NP points
115 * to and passes that NP value to the function being called.
117 #define dNPathNodes(nodes, prev_np) \
118 npath_node_t name_path_nodes[nodes+1]; /* +1 for NPathLink */ \
119 npath_node_t *NP = &name_path_nodes[0]; \
122 NP->id = "?0?"; /* DEBUG */ \
124 #define dNPathSetNode(nodeid, nodetype) \
126 NP->type = nodetype; \
127 if(0)fprintf(stderr,"dNPathSetNode (%p <-) %p <- [%d %s]\n", NP->prev, NP, nodetype,(char*)nodeid);\
129 NP->id="?+?"; /* DEBUG */ \
133 /* dNPathUseParent points NP directly the the parents' name_path_nodes array
134 * So the function can only safely call ADD_*() but not NPathLink, unless the
135 * caller has spare nodes in its name_path_nodes.
137 #define dNPathUseParent(prev_np) npath_node_t *NP = (((prev_np+1)->prev = prev_np), prev_np+1)
139 #define NPtype_NAME 0x01
140 #define NPtype_LINK 0x02
141 #define NPtype_SV 0x03
142 #define NPtype_MAGIC 0x04
143 #define NPtype_OP 0x05
145 #define NPathLink(nodeid, nodetype) ((NP->id = nodeid), (NP->type = nodetype), (NP->seqn = 0), NP)
146 #define NPathOpLink (NPathArg)
147 #define ADD_ATTR(st, attr_type, attr_name, attr_value) (st->add_attr_cb && st->add_attr_cb(st, NP-1, attr_type, attr_name, attr_value))
151 #define NPathAddSizeCb(st, name, bytes)
152 #define pPATH void *npath_dummy /* XXX ideally remove */
153 #define dNPathNodes(nodes, prev_np) dNOOP
154 #define NPathLink(nodeid, nodetype) NULL
155 #define NPathOpLink NULL
156 #define ADD_ATTR(st, attr_type, attr_name, attr_value) NOOP
158 #endif /* PATH_TRACKING */
165 static const char *svtypenames[SVt_LAST] = {
167 "NULL", "IV", "NV", "RV", "PV", "PVIV", "PVNV", "PVMG", "PVBM", "PVLV", "PVAV", "PVHV", "PVCV", "PVGV", "PVFM", "PVIO",
168 #elif PERL_VERSION == 10 && PERL_SUBVERSION == 0
169 "NULL", "BIND", "IV", "NV", "RV", "PV", "PVIV", "PVNV", "PVMG", "PVGV", "PVLV", "PVAV", "PVHV", "PVCV", "PVFM", "PVIO",
170 #elif PERL_VERSION == 10 && PERL_SUBVERSION == 1
171 "NULL", "BIND", "IV", "NV", "RV", "PV", "PVIV", "PVNV", "PVMG", "PVGV", "PVLV", "PVAV", "PVHV", "PVCV", "PVFM", "PVIO",
172 #elif PERL_VERSION < 13
173 "NULL", "BIND", "IV", "NV", "PV", "PVIV", "PVNV", "PVMG", "REGEXP", "PVGV", "PVLV", "PVAV", "PVHV", "PVCV", "PVFM", "PVIO",
175 "NULL", "BIND", "IV", "NV", "PV", "PVIV", "PVNV", "PVMG", "REGEXP", "PVGV", "PVLV", "PVAV", "PVHV", "PVCV", "PVFM", "PVIO",
180 print_node_name(npath_node_t *npath_node)
182 char buf[1024]; /* XXX */
184 switch (npath_node->type) {
185 case NPtype_SV: { /* id is pointer to the SV sv_size was called on */
186 const SV *sv = (SV*)npath_node->id;
187 int type = SvTYPE(sv);
188 char *typename = (type == SVt_IV && SvROK(sv)) ? "RV" : svtypenames[type];
189 fprintf(stderr, "SV(%s)", typename);
190 switch(type) { /* add some useful details */
191 case SVt_PVAV: fprintf(stderr, " fill=%d/%ld", av_len((AV*)sv), AvMAX((AV*)sv)); break;
192 case SVt_PVHV: fprintf(stderr, " fill=%ld/%ld", HvFILL((HV*)sv), HvMAX((HV*)sv)); break;
196 case NPtype_OP: { /* id is pointer to the OP op_size was called on */
197 const OP *op = (OP*)npath_node->id;
198 fprintf(stderr, "OP(%s)", OP_NAME(op));
201 case NPtype_MAGIC: { /* id is pointer to the MAGIC struct */
202 MAGIC *magic_pointer = (MAGIC*)npath_node->id;
203 /* XXX it would be nice if we could reuse mg_names.c [sigh] */
204 fprintf(stderr, "MAGIC(%c)", magic_pointer->mg_type ? magic_pointer->mg_type : '0');
208 fprintf(stderr, "%s->", npath_node->id);
211 fprintf(stderr, "%s", npath_node->id);
213 default: /* assume id is a string pointer */
214 fprintf(stderr, "UNKNOWN(%d,%p)", npath_node->type, npath_node->id);
221 print_indent(int depth) {
223 fprintf(stderr, ": ");
227 print_formatted_node(struct state *st, npath_node_t *npath_node) {
228 print_indent(npath_node->depth);
229 print_node_name(npath_node);
230 fprintf(stderr, "\t\t[#%ld @%u] ", npath_node->seqn, npath_node->depth);
231 fprintf(stderr, "\n");
236 walk_new_nodes(struct state *st, npath_node_t *npath_node, int (*cb)(struct state *st, npath_node_t *npath_node))
238 if (npath_node->seqn) /* node already output */
241 if (npath_node->prev) {
242 walk_new_nodes(st, npath_node->prev, cb); /* recurse */
243 npath_node->depth = npath_node->prev->depth + 1;
245 else npath_node->depth = 0;
246 npath_node->seqn = ++st->seqn;
255 dump_path(struct state *st, npath_node_t *npath_node, UV attr_type, const char *attr_name, UV attr_value)
257 if (!attr_type && !attr_value)
259 walk_new_nodes(st, npath_node, print_formatted_node);
260 print_indent(npath_node->depth+1);
262 fprintf(stderr, "~NAMED('%s') %lu", attr_name, attr_value);
265 fprintf(stderr, "+%ld ", attr_value);
266 fprintf(stderr, "%s ", attr_name);
267 fprintf(stderr, "=%ld ", attr_value+st->total_size);
269 fprintf(stderr, "\n");
273 #endif /* PATH_TRACKING */
277 Checks to see if thing is in the bitstring.
278 Returns true or false, and
279 notes thing in the segmented bitstring.
282 check_new(struct state *st, const void *const p) {
283 unsigned int bits = 8 * sizeof(void*);
284 const size_t raw_p = PTR2nat(p);
285 /* This effectively rotates the value right by the number of low always-0
286 bits in an aligned pointer. The assmption is that most (if not all)
287 pointers are aligned, and these will be in the same chain of nodes
288 (and hence hot in the cache) but we can still deal with any unaligned
290 const size_t cooked_p
291 = (raw_p >> ALIGN_BITS) | (raw_p << (bits - ALIGN_BITS));
292 const U8 this_bit = 1 << (cooked_p & 0x7);
296 void **tv_p = (void **) (st->tracking);
298 if (NULL == p) return FALSE;
300 const char c = *(const char *)p;
303 if (st->dangle_whine)
304 warn( "Devel::Size: Encountered invalid pointer: %p\n", p );
310 /* bits now 24 (32 bit pointers) or 56 (64 bit pointers) */
312 /* First level is always present. */
314 i = (unsigned int)((cooked_p >> bits) & 0xFF);
316 Newxz(tv_p[i], 256, void *);
317 tv_p = (void **)(tv_p[i]);
319 } while (bits > LEAF_BITS + BYTE_BITS);
320 /* bits now 16 always */
321 #if !defined(MULTIPLICITY) || PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8)
322 /* 5.8.8 and early have an assert() macro that uses Perl_croak, hence needs
323 a my_perl under multiplicity */
326 leaf_p = (U8 **)tv_p;
327 i = (unsigned int)((cooked_p >> bits) & 0xFF);
329 Newxz(leaf_p[i], 1 << LEAF_BITS, U8);
334 i = (unsigned int)((cooked_p >> BYTE_BITS) & LEAF_MASK);
336 if(leaf[i] & this_bit)
344 free_tracking_at(void **tv, int level)
352 free_tracking_at((void **) tv[i], level);
366 free_state(struct state *st)
368 const int top_level = (sizeof(void *) * 8 - LEAF_BITS - BYTE_BITS) / 8;
369 if (st->free_state_cb)
370 st->free_state_cb(st);
371 if (st->state_cb_data)
372 Safefree(st->state_cb_data);
373 free_tracking_at((void **)st->tracking, top_level);
377 /* For now, this is somewhat a compatibility bodge until the plan comes
378 together for fine grained recursion control. total_size() would recurse into
379 hash and array members, whereas sv_size() would not. However, sv_size() is
380 called with CvSTASH() of a CV, which means that if it (also) starts to
381 recurse fully, then the size of any CV now becomes the size of the entire
382 symbol table reachable from it, and potentially the entire symbol table, if
383 any subroutine makes a reference to a global (such as %SIG). The historical
384 implementation of total_size() didn't report "everything", and changing the
385 only available size to "everything" doesn't feel at all useful. */
387 #define NO_RECURSION 0
388 #define SOME_RECURSION 1
389 #define TOTAL_SIZE_RECURSION 2
391 static void sv_size(pTHX_ struct state *, pPATH, const SV *const, const int recurse);
407 , OPc_CONDOP /* 12 */
416 cc_opclass(const OP * const o)
422 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
424 if (o->op_type == OP_SASSIGN)
425 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
428 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
432 if ((o->op_type == OP_TRANS)) {
436 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
468 #ifdef OA_PVOP_OR_SVOP
469 case OA_PVOP_OR_SVOP: TAG;
471 * Character translations (tr///) are usually a PVOP, keeping a
472 * pointer to a table of shorts used to look up translations.
473 * Under utf8, however, a simple table isn't practical; instead,
474 * the OP is an SVOP, and the SV is a reference to a swash
475 * (i.e., an RV pointing to an HV).
477 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
478 ? OPc_SVOP : OPc_PVOP;
487 case OA_BASEOP_OR_UNOP: TAG;
489 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
490 * whether parens were seen. perly.y uses OPf_SPECIAL to
491 * signal whether a BASEOP had empty parens or none.
492 * Some other UNOPs are created later, though, so the best
493 * test is OPf_KIDS, which is set in newUNOP.
495 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
497 case OA_FILESTATOP: TAG;
499 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
500 * the OPf_REF flag to distinguish between OP types instead of the
501 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
502 * return OPc_UNOP so that walkoptree can find our children. If
503 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
504 * (no argument to the operator) it's an OP; with OPf_REF set it's
505 * an SVOP (and op_sv is the GV for the filehandle argument).
507 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
509 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
511 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
513 case OA_LOOPEXOP: TAG;
515 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
516 * label was omitted (in which case it's a BASEOP) or else a term was
517 * seen. In this last case, all except goto are definitely PVOP but
518 * goto is either a PVOP (with an ordinary constant label), an UNOP
519 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
520 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
523 if (o->op_flags & OPf_STACKED)
525 else if (o->op_flags & OPf_SPECIAL)
535 warn("Devel::Size: Can't determine class of operator %s, assuming BASEOP\n",
536 PL_op_name[o->op_type]);
542 /* Figure out how much magic is attached to the SV and return the
545 magic_size(pTHX_ const SV * const thing, struct state *st, pPATH) {
546 dNPathNodes(1, NPathArg);
547 MAGIC *magic_pointer = SvMAGIC(thing);
549 /* Have we seen the magic pointer? (NULL has always been seen before) */
550 while (check_new(st, magic_pointer)) {
552 dNPathSetNode(magic_pointer, NPtype_MAGIC);
554 ADD_SIZE(st, "mg", sizeof(MAGIC));
555 /* magic vtables aren't freed when magic is freed, so don't count them.
556 (They are static structures. Anything that assumes otherwise is buggy.)
561 sv_size(aTHX_ st, NPathLink("mg_obj", NPtype_LINK), magic_pointer->mg_obj, TOTAL_SIZE_RECURSION);
562 if (magic_pointer->mg_len == HEf_SVKEY) {
563 sv_size(aTHX_ st, NPathLink("mg_ptr", NPtype_LINK), (SV *)magic_pointer->mg_ptr, TOTAL_SIZE_RECURSION);
565 #if defined(PERL_MAGIC_utf8) && defined (PERL_MAGIC_UTF8_CACHESIZE)
566 else if (magic_pointer->mg_type == PERL_MAGIC_utf8) {
567 if (check_new(st, magic_pointer->mg_ptr)) {
568 ADD_SIZE(st, "PERL_MAGIC_utf8", PERL_MAGIC_UTF8_CACHESIZE * 2 * sizeof(STRLEN));
572 else if (magic_pointer->mg_len > 0) {
573 if (check_new(st, magic_pointer->mg_ptr)) {
574 ADD_SIZE(st, "mg_len", magic_pointer->mg_len);
578 /* Get the next in the chain */
579 magic_pointer = magic_pointer->mg_moremagic;
582 if (st->dangle_whine)
583 warn( "Devel::Size: Encountered bad magic at: %p\n", magic_pointer );
589 check_new_and_strlen(struct state *st, const char *const p, pPATH) {
590 dNPathNodes(1, NPathArg->prev);
591 if(check_new(st, p)) {
592 dNPathSetNode(NPathArg->id, NPtype_NAME);
593 ADD_SIZE(st, NPathArg->id, 1 + strlen(p));
598 regex_size(const REGEXP * const baseregex, struct state *st, pPATH) {
599 dNPathNodes(1, NPathArg);
600 if(!check_new(st, baseregex))
602 dNPathSetNode("regex_size", NPtype_NAME);
603 ADD_SIZE(st, "REGEXP", sizeof(REGEXP));
604 #if (PERL_VERSION < 11)
605 /* Note the size of the paren offset thing */
606 ADD_SIZE(st, "nparens", sizeof(I32) * baseregex->nparens * 2);
607 ADD_SIZE(st, "precomp", strlen(baseregex->precomp));
609 ADD_SIZE(st, "regexp", sizeof(struct regexp));
610 ADD_SIZE(st, "nparens", sizeof(I32) * SvANY(baseregex)->nparens * 2);
611 /*ADD_SIZE(st, strlen(SvANY(baseregex)->subbeg));*/
613 if (st->go_yell && !st->regex_whine) {
614 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
620 op_size(pTHX_ const OP * const baseop, struct state *st, pPATH)
622 /* op_size recurses to follow the chain of opcodes.
623 * For the 'path' we don't want the chain to be 'nested' in the path so we
624 * use ->prev in dNPathNodes.
626 dNPathUseParent(NPathArg);
630 if(!check_new(st, baseop))
633 op_size(aTHX_ baseop->op_next, st, NPathOpLink);
635 switch (cc_opclass(baseop)) {
636 case OPc_BASEOP: TAG;
637 ADD_SIZE(st, "op", sizeof(struct op));
640 ADD_SIZE(st, "unop", sizeof(struct unop));
641 op_size(aTHX_ ((UNOP *)baseop)->op_first, st, NPathOpLink);
644 ADD_SIZE(st, "binop", sizeof(struct binop));
645 op_size(aTHX_ ((BINOP *)baseop)->op_first, st, NPathOpLink);
646 op_size(aTHX_ ((BINOP *)baseop)->op_last, st, NPathOpLink);
649 ADD_SIZE(st, "logop", sizeof(struct logop));
650 op_size(aTHX_ ((BINOP *)baseop)->op_first, st, NPathOpLink);
651 op_size(aTHX_ ((LOGOP *)baseop)->op_other, st, NPathOpLink);
654 case OPc_CONDOP: TAG;
655 ADD_SIZE(st, "condop", sizeof(struct condop));
656 op_size(aTHX_ ((BINOP *)baseop)->op_first, st, NPathOpLink);
657 op_size(aTHX_ ((CONDOP *)baseop)->op_true, st, NPathOpLink);
658 op_size(aTHX_ ((CONDOP *)baseop)->op_false, st, NPathOpLink);
661 case OPc_LISTOP: TAG;
662 ADD_SIZE(st, "listop", sizeof(struct listop));
663 op_size(aTHX_ ((LISTOP *)baseop)->op_first, st, NPathOpLink);
664 op_size(aTHX_ ((LISTOP *)baseop)->op_last, st, NPathOpLink);
667 ADD_SIZE(st, "pmop", sizeof(struct pmop));
668 op_size(aTHX_ ((PMOP *)baseop)->op_first, st, NPathOpLink);
669 op_size(aTHX_ ((PMOP *)baseop)->op_last, st, NPathOpLink);
670 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
671 op_size(aTHX_ ((PMOP *)baseop)->op_pmreplroot, st, NPathOpLink);
672 op_size(aTHX_ ((PMOP *)baseop)->op_pmreplstart, st, NPathOpLink);
674 /* This is defined away in perl 5.8.x, but it is in there for
677 regex_size(PM_GETRE((PMOP *)baseop), st, NPathLink("PM_GETRE", NPtype_LINK));
679 regex_size(((PMOP *)baseop)->op_pmregexp, st, NPathLink("op_pmregexp", NPtype_LINK));
683 ADD_SIZE(st, "svop", sizeof(struct svop));
684 if (!(baseop->op_type == OP_AELEMFAST
685 && baseop->op_flags & OPf_SPECIAL)) {
686 /* not an OP_PADAV replacement */
687 sv_size(aTHX_ st, NPathLink("SVOP", NPtype_LINK), ((SVOP *)baseop)->op_sv, SOME_RECURSION);
692 ADD_SIZE(st, "padop", sizeof(struct padop));
697 ADD_SIZE(st, "gvop", sizeof(struct gvop));
698 sv_size(aTHX_ st, NPathLink("GVOP", NPtype_LINK), ((GVOP *)baseop)->op_gv, SOME_RECURSION);
702 check_new_and_strlen(st, ((PVOP *)baseop)->op_pv, NPathLink("op_pv", NPtype_LINK));
705 ADD_SIZE(st, "loop", sizeof(struct loop));
706 op_size(aTHX_ ((LOOP *)baseop)->op_first, st, NPathOpLink);
707 op_size(aTHX_ ((LOOP *)baseop)->op_last, st, NPathOpLink);
708 op_size(aTHX_ ((LOOP *)baseop)->op_redoop, st, NPathOpLink);
709 op_size(aTHX_ ((LOOP *)baseop)->op_nextop, st, NPathOpLink);
710 op_size(aTHX_ ((LOOP *)baseop)->op_lastop, st, NPathOpLink);
715 basecop = (COP *)baseop;
716 ADD_SIZE(st, "cop", sizeof(struct cop));
718 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
719 Eliminate cop_label from struct cop by storing a label as the first
720 entry in the hints hash. Most statements don't have labels, so this
721 will save memory. Not sure how much.
722 The check below will be incorrect fail on bleadperls
723 before 5.11 @33656, but later than 5.10, producing slightly too
724 small memory sizes on these Perls. */
725 #if (PERL_VERSION < 11)
726 check_new_and_strlen(st, basecop->cop_label, NPathLink("cop_label", NPtype_LINK));
729 check_new_and_strlen(st, basecop->cop_file, NPathLink("cop_file", NPtype_LINK));
730 check_new_and_strlen(st, basecop->cop_stashpv, NPathLink("cop_stashpv", NPtype_LINK));
732 sv_size(aTHX_ st, NPathLink("cop_stash", NPtype_LINK), (SV *)basecop->cop_stash, SOME_RECURSION);
733 sv_size(aTHX_ st, NPathLink("cop_filegv", NPtype_LINK), (SV *)basecop->cop_filegv, SOME_RECURSION);
743 if (st->dangle_whine)
744 warn( "Devel::Size: Encountered dangling pointer in opcode at: %p\n", baseop );
749 hek_size(pTHX_ struct state *st, HEK *hek, U32 shared, pPATH)
751 dNPathUseParent(NPathArg);
752 /* Hash keys can be shared. Have we seen this before? */
753 if (!check_new(st, hek))
755 ADD_SIZE(st, "hek_len", HEK_BASESIZE + hek->hek_len
757 + 1 /* No hash key flags prior to 5.8.0 */
763 #if PERL_VERSION < 10
764 ADD_SIZE(st, "he", sizeof(struct he));
766 ADD_SIZE(st, "shared_he", STRUCT_OFFSET(struct shared_he, shared_he_hek));
772 #if PERL_VERSION < 8 || PERL_SUBVERSION < 9
777 # define MAYBE_PURIFY(normal, pure) (pure)
778 # define MAYBE_OFFSET(struct_name, member) 0
780 # define MAYBE_PURIFY(normal, pure) (normal)
781 # define MAYBE_OFFSET(struct_name, member) STRUCT_OFFSET(struct_name, member)
784 const U8 body_sizes[SVt_LAST] = {
787 MAYBE_PURIFY(sizeof(IV), sizeof(XPVIV)), /* SVt_IV */
788 MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */
789 sizeof(XRV), /* SVt_RV */
790 sizeof(XPV), /* SVt_PV */
791 sizeof(XPVIV), /* SVt_PVIV */
792 sizeof(XPVNV), /* SVt_PVNV */
793 sizeof(XPVMG), /* SVt_PVMG */
794 sizeof(XPVBM), /* SVt_PVBM */
795 sizeof(XPVLV), /* SVt_PVLV */
796 sizeof(XPVAV), /* SVt_PVAV */
797 sizeof(XPVHV), /* SVt_PVHV */
798 sizeof(XPVCV), /* SVt_PVCV */
799 sizeof(XPVGV), /* SVt_PVGV */
800 sizeof(XPVFM), /* SVt_PVFM */
801 sizeof(XPVIO) /* SVt_PVIO */
802 #elif PERL_VERSION == 10 && PERL_SUBVERSION == 0
806 MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */
808 MAYBE_PURIFY(sizeof(xpv_allocated), sizeof(XPV)), /* SVt_PV */
809 MAYBE_PURIFY(sizeof(xpviv_allocated), sizeof(XPVIV)),/* SVt_PVIV */
810 sizeof(XPVNV), /* SVt_PVNV */
811 sizeof(XPVMG), /* SVt_PVMG */
812 sizeof(XPVGV), /* SVt_PVGV */
813 sizeof(XPVLV), /* SVt_PVLV */
814 MAYBE_PURIFY(sizeof(xpvav_allocated), sizeof(XPVAV)),/* SVt_PVAV */
815 MAYBE_PURIFY(sizeof(xpvhv_allocated), sizeof(XPVHV)),/* SVt_PVHV */
816 MAYBE_PURIFY(sizeof(xpvcv_allocated), sizeof(XPVCV)),/* SVt_PVCV */
817 MAYBE_PURIFY(sizeof(xpvfm_allocated), sizeof(XPVFM)),/* SVt_PVFM */
818 sizeof(XPVIO), /* SVt_PVIO */
819 #elif PERL_VERSION == 10 && PERL_SUBVERSION == 1
823 MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */
825 sizeof(XPV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PV */
826 sizeof(XPVIV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVIV */
827 sizeof(XPVNV), /* SVt_PVNV */
828 sizeof(XPVMG), /* SVt_PVMG */
829 sizeof(XPVGV), /* SVt_PVGV */
830 sizeof(XPVLV), /* SVt_PVLV */
831 sizeof(XPVAV) - MAYBE_OFFSET(XPVAV, xav_fill), /* SVt_PVAV */
832 sizeof(XPVHV) - MAYBE_OFFSET(XPVHV, xhv_fill), /* SVt_PVHV */
833 sizeof(XPVCV) - MAYBE_OFFSET(XPVCV, xpv_cur), /* SVt_PVCV */
834 sizeof(XPVFM) - MAYBE_OFFSET(XPVFM, xpv_cur), /* SVt_PVFM */
835 sizeof(XPVIO) /* SVt_PVIO */
836 #elif PERL_VERSION < 13
840 MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */
841 sizeof(XPV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PV */
842 sizeof(XPVIV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVIV */
843 sizeof(XPVNV), /* SVt_PVNV */
844 sizeof(XPVMG), /* SVt_PVMG */
845 sizeof(regexp) - MAYBE_OFFSET(regexp, xpv_cur), /* SVt_REGEXP */
846 sizeof(XPVGV), /* SVt_PVGV */
847 sizeof(XPVLV), /* SVt_PVLV */
848 sizeof(XPVAV) - MAYBE_OFFSET(XPVAV, xav_fill), /* SVt_PVAV */
849 sizeof(XPVHV) - MAYBE_OFFSET(XPVHV, xhv_fill), /* SVt_PVHV */
850 sizeof(XPVCV) - MAYBE_OFFSET(XPVCV, xpv_cur), /* SVt_PVCV */
851 sizeof(XPVFM) - MAYBE_OFFSET(XPVFM, xpv_cur), /* SVt_PVFM */
852 sizeof(XPVIO) /* SVt_PVIO */
857 MAYBE_PURIFY(sizeof(NV), sizeof(XPVNV)), /* SVt_NV */
858 sizeof(XPV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PV */
859 sizeof(XPVIV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVIV */
860 sizeof(XPVNV) - MAYBE_OFFSET(XPV, xpv_cur), /* SVt_PVNV */
861 sizeof(XPVMG), /* SVt_PVMG */
862 sizeof(regexp), /* SVt_REGEXP */
863 sizeof(XPVGV), /* SVt_PVGV */
864 sizeof(XPVLV), /* SVt_PVLV */
865 sizeof(XPVAV), /* SVt_PVAV */
866 sizeof(XPVHV), /* SVt_PVHV */
867 sizeof(XPVCV), /* SVt_PVCV */
868 sizeof(XPVFM), /* SVt_PVFM */
869 sizeof(XPVIO) /* SVt_PVIO */
875 padlist_size(pTHX_ struct state *const st, pPATH, PADLIST *padlist,
878 dNPathUseParent(NPathArg);
879 /* based on Perl_do_dump_pad() */
887 pad_name = MUTABLE_AV(*av_fetch(MUTABLE_AV(padlist), 0, FALSE));
888 pname = AvARRAY(pad_name);
890 for (ix = 1; ix <= AvFILLp(pad_name); ix++) {
891 const SV *namesv = pname[ix];
892 if (namesv && namesv == &PL_sv_undef) {
897 ADD_ATTR(st, 1, SvPVX_const(namesv), ix);
899 ADD_ATTR(st, 1, SvPVX_const(namesv), ix);
902 ADD_ATTR(st, 1, "SVs_PADTMP", ix);
906 sv_size(aTHX_ st, NPathArg, (SV*)padlist, recurse);
911 sv_size(pTHX_ struct state *const st, pPATH, const SV * const orig_thing,
913 const SV *thing = orig_thing;
914 dNPathNodes(3, NPathArg);
917 if(!check_new(st, orig_thing))
920 type = SvTYPE(thing);
921 if (type > SVt_LAST) {
922 warn("Devel::Size: Unknown variable type: %d encountered\n", type);
925 dNPathSetNode(thing, NPtype_SV);
926 ADD_SIZE(st, "sv", sizeof(SV) + body_sizes[type]);
928 if (type >= SVt_PVMG) {
929 magic_size(aTHX_ thing, st, NPathLink(NULL, 0));
933 #if (PERL_VERSION < 11)
934 /* Is it a reference? */
939 if(recurse && SvROK(thing))
940 sv_size(aTHX_ st, NPathLink("RV", NPtype_LINK), SvRV_const(thing), recurse);
944 /* Is there anything in the array? */
945 if (AvMAX(thing) != -1) {
946 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
947 ADD_SIZE(st, "av_max", sizeof(SV *) * (AvMAX(thing) + 1));
948 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", st->total_size, AvMAX(thing), av_len((AV*)thing)));
950 if (recurse >= TOTAL_SIZE_RECURSION) {
951 SSize_t i = AvFILLp(thing) + 1;
954 sv_size(aTHX_ st, NPathLink("AVelem", NPtype_LINK), AvARRAY(thing)[i], recurse);
957 /* Add in the bits on the other side of the beginning */
959 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
960 st->total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
962 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
963 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
964 if (AvALLOC(thing) != 0) {
965 ADD_SIZE(st, "AvALLOC", (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing))));
967 #if (PERL_VERSION < 9)
968 /* Is there something hanging off the arylen element?
969 Post 5.9.something this is stored in magic, so will be found there,
970 and Perl_av_arylen_p() takes a non-const AV*, hence compilers rightly
971 complain about AvARYLEN() passing thing to it. */
972 sv_size(aTHX_ st, NPathLink("ARYLEN", NPtype_LINK), AvARYLEN(thing), recurse);
976 /* Now the array of buckets */
977 ADD_SIZE(st, "hv_max", (sizeof(HE *) * (HvMAX(thing) + 1)));
978 if (HvENAME(thing)) {
979 ADD_ATTR(st, 1, HvENAME(thing), 0);
981 /* Now walk the bucket chain */
982 if (HvARRAY(thing)) {
985 dNPathSetNode("HvARRAY", NPtype_LINK);
986 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
987 cur_entry = *(HvARRAY(thing) + cur_bucket);
989 ADD_SIZE(st, "he", sizeof(HE));
990 hek_size(aTHX_ st, cur_entry->hent_hek, HvSHAREKEYS(thing), NPathLink("hent_hek", NPtype_LINK));
991 if (recurse >= TOTAL_SIZE_RECURSION)
992 sv_size(aTHX_ st, NPathLink("HeVAL", NPtype_LINK), HeVAL(cur_entry), recurse);
993 cur_entry = cur_entry->hent_next;
999 /* This direct access is arguably "naughty": */
1000 struct mro_meta *meta = HvAUX(thing)->xhv_mro_meta;
1001 #if PERL_VERSION > 13 || PERL_SUBVERSION > 8
1003 I32 count = HvAUX(thing)->xhv_name_count;
1006 HEK **names = HvAUX(thing)->xhv_name_u.xhvnameu_names;
1010 hek_size(aTHX_ st, names[count], 1, NPathLink("HvAUXelem", NPtype_LINK));
1015 hek_size(aTHX_ st, HvNAME_HEK(thing), 1, NPathLink("HvNAME_HEK", NPtype_LINK));
1018 ADD_SIZE(st, "xpvhv_aux", sizeof(struct xpvhv_aux));
1020 ADD_SIZE(st, "mro_meta", sizeof(struct mro_meta));
1021 sv_size(aTHX_ st, NPathLink("mro_nextmethod", NPtype_LINK), (SV *)meta->mro_nextmethod, TOTAL_SIZE_RECURSION);
1022 #if PERL_VERSION > 10 || (PERL_VERSION == 10 && PERL_SUBVERSION > 0)
1023 sv_size(aTHX_ st, NPathLink("isa", NPtype_LINK), (SV *)meta->isa, TOTAL_SIZE_RECURSION);
1025 #if PERL_VERSION > 10
1026 sv_size(aTHX_ st, NPathLink("mro_linear_all", NPtype_LINK), (SV *)meta->mro_linear_all, TOTAL_SIZE_RECURSION);
1027 sv_size(aTHX_ st, NPathLink("mro_linear_current", NPtype_LINK), meta->mro_linear_current, TOTAL_SIZE_RECURSION);
1029 sv_size(aTHX_ st, NPathLink("mro_linear_dfs", NPtype_LINK), (SV *)meta->mro_linear_dfs, TOTAL_SIZE_RECURSION);
1030 sv_size(aTHX_ st, NPathLink("mro_linear_c3", NPtype_LINK), (SV *)meta->mro_linear_c3, TOTAL_SIZE_RECURSION);
1035 check_new_and_strlen(st, HvNAME_get(thing), NPathLink("HvNAME", NPtype_LINK));
1041 padlist_size(aTHX_ st, NPathLink("CvPADLIST", NPtype_LINK), CvPADLIST(thing), SOME_RECURSION);
1042 sv_size(aTHX_ st, NPathLink("CvOUTSIDE", NPtype_LINK), (SV *)CvOUTSIDE(thing), recurse);
1044 if (st->go_yell && !st->fm_whine) {
1045 carp("Devel::Size: Calculated sizes for FMs are incomplete");
1051 sv_size(aTHX_ st, NPathLink("CvSTASH", NPtype_LINK), (SV *)CvSTASH(thing), SOME_RECURSION);
1052 sv_size(aTHX_ st, NPathLink("SvSTASH", NPtype_LINK), (SV *)SvSTASH(thing), SOME_RECURSION);
1053 sv_size(aTHX_ st, NPathLink("CvGV", NPtype_LINK), (SV *)CvGV(thing), SOME_RECURSION);
1054 padlist_size(aTHX_ st, NPathLink("CvPADLIST", NPtype_LINK), CvPADLIST(thing), SOME_RECURSION);
1055 sv_size(aTHX_ st, NPathLink("CvOUTSIDE", NPtype_LINK), (SV *)CvOUTSIDE(thing), recurse);
1056 if (CvISXSUB(thing)) {
1057 sv_size(aTHX_ st, NPathLink("cv_const_sv", NPtype_LINK), cv_const_sv((CV *)thing), recurse);
1059 op_size(aTHX_ CvSTART(thing), st, NPathLink("CvSTART", NPtype_LINK));
1060 op_size(aTHX_ CvROOT(thing), st, NPathLink("CvROOT", NPtype_LINK));
1065 /* Some embedded char pointers */
1066 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_top_name, NPathLink("xio_top_name", NPtype_LINK));
1067 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_fmt_name, NPathLink("xio_fmt_name", NPtype_LINK));
1068 check_new_and_strlen(st, ((XPVIO *) SvANY(thing))->xio_bottom_name, NPathLink("xio_bottom_name", NPtype_LINK));
1069 /* Throw the GVs on the list to be walked if they're not-null */
1070 sv_size(aTHX_ st, NPathLink("xio_top_gv", NPtype_LINK), (SV *)((XPVIO *) SvANY(thing))->xio_top_gv, recurse);
1071 sv_size(aTHX_ st, NPathLink("xio_bottom_gv", NPtype_LINK), (SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv, recurse);
1072 sv_size(aTHX_ st, NPathLink("xio_fmt_gv", NPtype_LINK), (SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv, recurse);
1074 /* Only go trotting through the IO structures if they're really
1075 trottable. If USE_PERLIO is defined we can do this. If
1076 not... we can't, so we don't even try */
1078 /* Dig into xio_ifp and xio_ofp here */
1079 warn("Devel::Size: Can't size up perlio layers yet\n");
1084 #if (PERL_VERSION < 9)
1089 if(isGV_with_GP(thing)) {
1091 hek_size(aTHX_ st, GvNAME_HEK(thing), 1, NPathLink("GvNAME_HEK", NPtype_LINK));
1093 ADD_SIZE(st, "GvNAMELEN", GvNAMELEN(thing));
1095 ADD_ATTR(st, 1, GvNAME_get(thing), 0);
1097 hek_size(aTHX_ st, GvFILE_HEK(thing), 1, NPathLink("GvFILE_HEK", NPtype_LINK));
1098 #elif defined(GvFILE)
1099 # if !defined(USE_ITHREADS) || (PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8))
1100 /* With itreads, before 5.8.9, this can end up pointing to freed memory
1101 if the GV was created in an eval, as GvFILE() points to CopFILE(),
1102 and the relevant COP has been freed on scope cleanup after the eval.
1103 5.8.9 adds a binary compatible fudge that catches the vast majority
1104 of cases. 5.9.something added a proper fix, by converting the GP to
1105 use a shared hash key (porperly reference counted), instead of a
1106 char * (owned by who knows? possibly no-one now) */
1107 check_new_and_strlen(st, GvFILE(thing), NPathLink("GvFILE", NPtype_LINK));
1110 /* Is there something hanging off the glob? */
1111 if (check_new(st, GvGP(thing))) {
1112 ADD_SIZE(st, "GP", sizeof(GP));
1113 sv_size(aTHX_ st, NPathLink("gp_sv", NPtype_LINK), (SV *)(GvGP(thing)->gp_sv), recurse);
1114 sv_size(aTHX_ st, NPathLink("gp_form", NPtype_LINK), (SV *)(GvGP(thing)->gp_form), recurse);
1115 sv_size(aTHX_ st, NPathLink("gp_av", NPtype_LINK), (SV *)(GvGP(thing)->gp_av), recurse);
1116 sv_size(aTHX_ st, NPathLink("gp_hv", NPtype_LINK), (SV *)(GvGP(thing)->gp_hv), recurse);
1117 sv_size(aTHX_ st, NPathLink("gp_egv", NPtype_LINK), (SV *)(GvGP(thing)->gp_egv), recurse);
1118 sv_size(aTHX_ st, NPathLink("gp_cv", NPtype_LINK), (SV *)(GvGP(thing)->gp_cv), recurse);
1120 #if (PERL_VERSION >= 9)
1124 #if PERL_VERSION <= 8
1132 if(recurse && SvROK(thing))
1133 sv_size(aTHX_ st, NPathLink("RV", NPtype_LINK), SvRV_const(thing), recurse);
1134 else if (SvIsCOW_shared_hash(thing))
1135 hek_size(aTHX_ st, SvSHARED_HEK_FROM_PV(SvPVX(thing)), 1, NPathLink("SvSHARED_HEK_FROM_PV", NPtype_LINK));
1137 ADD_SIZE(st, "SvLEN", SvLEN(thing));
1141 SvOOK_offset(thing, len);
1142 ADD_SIZE(st, "SvOOK", len);
1150 static struct state *
1156 Newxz(st, 1, struct state);
1158 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
1159 st->dangle_whine = st->go_yell = SvIV(warn_flag) ? TRUE : FALSE;
1161 if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
1162 st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
1164 check_new(st, &PL_sv_undef);
1165 check_new(st, &PL_sv_no);
1166 check_new(st, &PL_sv_yes);
1167 #if PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 0)
1168 check_new(st, &PL_sv_placeholder);
1170 #ifdef PATH_TRACKING
1171 st->add_attr_cb = dump_path;
1176 MODULE = Devel::Size PACKAGE = Devel::Size
1184 total_size = TOTAL_SIZE_RECURSION
1187 SV *thing = orig_thing;
1188 struct state *st = new_state(aTHX);
1190 /* If they passed us a reference then dereference it. This is the
1191 only way we can check the sizes of arrays and hashes */
1193 thing = SvRV(thing);
1196 sv_size(aTHX_ st, NULL, thing, ix);
1197 RETVAL = st->total_size;
1207 dNPathNodes(1, NULL);
1208 struct state *st = new_state(aTHX);
1210 /* start with PL_defstash to get everything reachable from \%main::
1211 * this seems to include PL_defgv, PL_incgv etc but I've listed them anyway
1213 sv_size(aTHX_ st, NPathLink("PL_defstash", NPtype_LINK), (SV*)PL_defstash, TOTAL_SIZE_RECURSION);
1214 sv_size(aTHX_ st, NPathLink("PL_defgv", NPtype_LINK), (SV*)PL_defgv, TOTAL_SIZE_RECURSION);
1215 sv_size(aTHX_ st, NPathLink("PL_incgv", NPtype_LINK), (SV*)PL_incgv, TOTAL_SIZE_RECURSION);
1216 sv_size(aTHX_ st, NPathLink("PL_rs", NPtype_LINK), (SV*)PL_rs, TOTAL_SIZE_RECURSION);
1217 sv_size(aTHX_ st, NPathLink("PL_fdpid", NPtype_LINK), (SV*)PL_fdpid, TOTAL_SIZE_RECURSION);
1218 sv_size(aTHX_ st, NPathLink("PL_modglobal", NPtype_LINK), (SV*)PL_modglobal, TOTAL_SIZE_RECURSION);
1219 sv_size(aTHX_ st, NPathLink("PL_errors", NPtype_LINK), (SV*)PL_errors, TOTAL_SIZE_RECURSION);
1220 sv_size(aTHX_ st, NPathLink("PL_stashcache", NPtype_LINK), (SV*)PL_stashcache, TOTAL_SIZE_RECURSION);
1221 sv_size(aTHX_ st, NPathLink("PL_patchlevel", NPtype_LINK), (SV*)PL_patchlevel, TOTAL_SIZE_RECURSION);
1222 sv_size(aTHX_ st, NPathLink("PL_apiversion", NPtype_LINK), (SV*)PL_apiversion, TOTAL_SIZE_RECURSION);
1223 sv_size(aTHX_ st, NPathLink("PL_registered_mros", NPtype_LINK), (SV*)PL_registered_mros, TOTAL_SIZE_RECURSION);
1225 sv_size(aTHX_ st, NPathLink("PL_regex_padav", NPtype_LINK), (SV*)PL_regex_padav, TOTAL_SIZE_RECURSION);
1227 /* TODO PL_pidstatus */
1228 /* TODO PL_stashpad */
1230 /* in theory we shouldn't have any elements in PL_strtab that haven't been seen yet */
1231 sv_size(aTHX_ st, NPathLink("PL_strtab", NPtype_LINK), (SV*)PL_strtab, TOTAL_SIZE_RECURSION);
1233 /* TODO stacks: cur, main, tmps, mark, scope, save */
1234 /* TODO unused space in arenas */
1235 /* TODO unused space in malloc, for whichever mallocs support it */
1236 /* TODO anything missed? */
1238 RETVAL = st->total_size;