5 static int regex_whine;
8 #if 0 && defined(DEBUGGING)
9 #define dbg_printf(x) printf x
15 UV thing_size(SV *, HV *);
38 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
40 if (o->op_type == OP_SASSIGN)
41 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
44 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
48 if ((o->op_type = OP_TRANS)) {
52 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
79 * Character translations (tr///) are usually a PVOP, keeping a
80 * pointer to a table of shorts used to look up translations.
81 * Under utf8, however, a simple table isn't practical; instead,
82 * the OP is an SVOP, and the SV is a reference to a swash
83 * (i.e., an RV pointing to an HV).
85 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
86 ? OPc_SVOP : OPc_PVOP;
94 case OA_BASEOP_OR_UNOP:
96 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
97 * whether parens were seen. perly.y uses OPf_SPECIAL to
98 * signal whether a BASEOP had empty parens or none.
99 * Some other UNOPs are created later, though, so the best
100 * test is OPf_KIDS, which is set in newUNOP.
102 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
106 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
107 * the OPf_REF flag to distinguish between OP types instead of the
108 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
109 * return OPc_UNOP so that walkoptree can find our children. If
110 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
111 * (no argument to the operator) it's an OP; with OPf_REF set it's
112 * an SVOP (and op_sv is the GV for the filehandle argument).
114 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
116 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
118 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
122 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
123 * label was omitted (in which case it's a BASEOP) or else a term was
124 * seen. In this last case, all except goto are definitely PVOP but
125 * goto is either a PVOP (with an ordinary constant label), an UNOP
126 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
127 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
130 if (o->op_flags & OPf_STACKED)
132 else if (o->op_flags & OPf_SPECIAL)
137 warn("can't determine class of operator %s, assuming BASEOP\n",
138 PL_op_name[o->op_type]);
147 static int go_yell = 1;
149 /* Checks to see if thing is in the hash. Returns true or false, and
150 notes thing in the hash.
152 This code does one Evil Thing. Since we're tracking pointers, we
153 tell perl that the string key is the address in the pointer. We do this by
154 passing in the address of the address, along with the size of a
155 pointer as the length. Perl then uses the four (or eight, on
156 64-bit machines) bytes of the address as the string we're using as
158 IV check_new(HV *tracking_hash, const void *thing) {
159 if (NULL == thing || NULL == tracking_hash) {
162 if (hv_exists(tracking_hash, (char *)&thing, sizeof(void *))) {
165 hv_store(tracking_hash, (char *)&thing, sizeof(void *), &PL_sv_yes, 0);
169 /* Figure out how much magic is attached to the SV and return the
171 IV magic_size(SV *thing, HV *tracking_hash) {
173 MAGIC *magic_pointer;
176 if (!SvMAGIC(thing)) {
181 /* Get the base magic pointer */
182 magic_pointer = SvMAGIC(thing);
184 /* Have we seen the magic pointer? */
185 while (magic_pointer && check_new(tracking_hash, magic_pointer)) {
186 total_size += sizeof(MAGIC);
188 /* Have we seen the magic vtable? */
189 if (magic_pointer->mg_virtual &&
190 check_new(tracking_hash, magic_pointer->mg_virtual)) {
191 total_size += sizeof(MGVTBL);
194 /* Get the next in the chain */
195 magic_pointer = magic_pointer->mg_moremagic;
201 UV regex_size(REGEXP *baseregex, HV *tracking_hash) {
204 total_size += sizeof(REGEXP);
205 #if (PERL_VERSION < 11)
206 /* Note the size of the paren offset thing */
207 total_size += sizeof(I32) * baseregex->nparens * 2;
208 total_size += strlen(baseregex->precomp);
210 total_size += sizeof(struct regexp);
211 total_size += sizeof(I32) * SvANY(baseregex)->nparens * 2;
212 /*total_size += strlen(SvANY(baseregex)->subbeg);*/
214 if (go_yell && !regex_whine) {
215 carp("Devel::Size: Calculated sizes for compiled regexes are incompatible, and probably always will be");
222 UV op_size(OP *baseop, HV *tracking_hash) {
225 if (check_new(tracking_hash, baseop->op_next)) {
226 total_size += op_size(baseop->op_next, tracking_hash);
229 switch (cc_opclass(baseop)) {
231 total_size += sizeof(struct op);
234 total_size += sizeof(struct unop);
235 if (check_new(tracking_hash, cUNOPx(baseop)->op_first)) {
236 total_size += op_size(cUNOPx(baseop)->op_first, tracking_hash);
240 total_size += sizeof(struct binop);
241 if (check_new(tracking_hash, cBINOPx(baseop)->op_first)) {
242 total_size += op_size(cBINOPx(baseop)->op_first, tracking_hash);
244 if (check_new(tracking_hash, cBINOPx(baseop)->op_last)) {
245 total_size += op_size(cBINOPx(baseop)->op_last, tracking_hash);
249 total_size += sizeof(struct logop);
250 if (check_new(tracking_hash, cLOGOPx(baseop)->op_first)) {
251 total_size += op_size(cBINOPx(baseop)->op_first, tracking_hash);
253 if (check_new(tracking_hash, cLOGOPx(baseop)->op_other)) {
254 total_size += op_size(cLOGOPx(baseop)->op_other, tracking_hash);
258 total_size += sizeof(struct listop);
259 if (check_new(tracking_hash, cLISTOPx(baseop)->op_first)) {
260 total_size += op_size(cLISTOPx(baseop)->op_first, tracking_hash);
262 if (check_new(tracking_hash, cLISTOPx(baseop)->op_last)) {
263 total_size += op_size(cLISTOPx(baseop)->op_last, tracking_hash);
267 total_size += sizeof(struct pmop);
268 if (check_new(tracking_hash, cPMOPx(baseop)->op_first)) {
269 total_size += op_size(cPMOPx(baseop)->op_first, tracking_hash);
271 if (check_new(tracking_hash, cPMOPx(baseop)->op_last)) {
272 total_size += op_size(cPMOPx(baseop)->op_last, tracking_hash);
274 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
275 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmreplroot)) {
276 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tracking_hash);
278 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmreplstart)) {
279 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tracking_hash);
281 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmnext)) {
282 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tracking_hash);
285 /* This is defined away in perl 5.8.x, but it is in there for
288 if (check_new(tracking_hash, PM_GETRE((cPMOPx(baseop))))) {
289 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tracking_hash);
292 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmregexp)) {
293 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tracking_hash);
298 total_size += sizeof(struct pmop);
299 if (check_new(tracking_hash, cSVOPx(baseop)->op_sv)) {
300 total_size += thing_size(cSVOPx(baseop)->op_sv, tracking_hash);
304 total_size += sizeof(struct padop);
307 if (check_new(tracking_hash, cPVOPx(baseop)->op_pv)) {
308 total_size += strlen(cPVOPx(baseop)->op_pv);
311 total_size += sizeof(struct loop);
312 if (check_new(tracking_hash, cLOOPx(baseop)->op_first)) {
313 total_size += op_size(cLOOPx(baseop)->op_first, tracking_hash);
315 if (check_new(tracking_hash, cLOOPx(baseop)->op_last)) {
316 total_size += op_size(cLOOPx(baseop)->op_last, tracking_hash);
318 if (check_new(tracking_hash, cLOOPx(baseop)->op_redoop)) {
319 total_size += op_size(cLOOPx(baseop)->op_redoop, tracking_hash);
321 if (check_new(tracking_hash, cLOOPx(baseop)->op_nextop)) {
322 total_size += op_size(cLOOPx(baseop)->op_nextop, tracking_hash);
324 /* Not working for some reason, but the code's here for later
326 if (check_new(tracking_hash, cLOOPx(baseop)->op_lastop)) {
327 total_size += op_size(cLOOPx(baseop)->op_lastop, tracking_hash);
334 basecop = (COP *)baseop;
335 total_size += sizeof(struct cop);
337 /* Change 33656 by nicholas@mouse-mill on 2008/04/07 11:29:51
338 Eliminate cop_label from struct cop by storing a label as the first
339 entry in the hints hash. Most statements don't have labels, so this
340 will save memory. Not sure how much.
341 The check below will be incorrect fail on bleadperls
342 before 5.11 @33656, but later than 5.10, producing slightly too
343 small memory sizes on these Perls. */
344 #if (PERL_VERSION < 11)
345 if (check_new(tracking_hash, basecop->cop_label)) {
346 total_size += strlen(basecop->cop_label);
350 if (check_new(tracking_hash, basecop->cop_file)) {
351 total_size += strlen(basecop->cop_file);
353 if (check_new(tracking_hash, basecop->cop_stashpv)) {
354 total_size += strlen(basecop->cop_stashpv);
357 if (check_new(tracking_hash, basecop->cop_stash)) {
358 total_size += thing_size((SV *)basecop->cop_stash, tracking_hash);
360 if (check_new(tracking_hash, basecop->cop_filegv)) {
361 total_size += thing_size((SV *)basecop->cop_filegv, tracking_hash);
373 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
374 # define NEW_HEAD_LAYOUT
377 UV thing_size(SV *orig_thing, HV *tracking_hash) {
378 SV *thing = orig_thing;
379 UV total_size = sizeof(SV);
381 switch (SvTYPE(thing)) {
385 /* Just a plain integer. This will be differently sized depending
386 on whether purify's been compiled in */
388 #ifndef NEW_HEAD_LAYOUT
390 total_size += sizeof(sizeof(XPVIV));
392 total_size += sizeof(IV);
396 /* Is it a float? Like the int, it depends on purify */
399 total_size += sizeof(sizeof(XPVNV));
401 total_size += sizeof(NV);
404 #if (PERL_VERSION < 11)
405 /* Is it a reference? */
407 #ifndef NEW_HEAD_LAYOUT
408 total_size += sizeof(XRV);
412 /* How about a plain string? In which case we need to add in how
413 much has been allocated */
415 total_size += sizeof(XPV);
416 #if (PERL_VERSION < 11)
417 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
419 total_size += SvLEN(thing);
422 /* A string with an integer part? */
424 total_size += sizeof(XPVIV);
425 #if (PERL_VERSION < 11)
426 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
428 total_size += SvLEN(thing);
431 total_size += SvIVX(thing);
434 /* A scalar/string/reference with a float part? */
436 total_size += sizeof(XPVNV);
437 #if (PERL_VERSION < 11)
438 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
440 total_size += SvLEN(thing);
444 total_size += sizeof(XPVMG);
445 #if (PERL_VERSION < 11)
446 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
448 total_size += SvLEN(thing);
450 total_size += magic_size(thing, tracking_hash);
452 #if PERL_VERSION <= 8
454 total_size += sizeof(XPVBM);
455 #if (PERL_VERSION < 11)
456 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
458 total_size += SvLEN(thing);
460 total_size += magic_size(thing, tracking_hash);
464 total_size += sizeof(XPVLV);
465 #if (PERL_VERSION < 11)
466 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
468 total_size += SvLEN(thing);
470 total_size += magic_size(thing, tracking_hash);
472 /* How much space is dedicated to the array? Not counting the
473 elements in the array, mind, just the array itself */
475 total_size += sizeof(XPVAV);
476 /* Is there anything in the array? */
477 if (AvMAX(thing) != -1) {
478 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
479 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
480 dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", total_size, AvMAX(thing), av_len((AV*)thing)));
482 /* Add in the bits on the other side of the beginning */
484 dbg_printf(("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
485 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )));
487 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
488 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
489 if (AvALLOC(thing) != 0) {
490 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
492 /* Is there something hanging off the arylen element? */
493 if (AvARYLEN(thing)) {
494 if (check_new(tracking_hash, AvARYLEN(thing))) {
495 total_size += thing_size(AvARYLEN(thing), tracking_hash);
498 total_size += magic_size(thing, tracking_hash);
501 /* First the base struct */
502 total_size += sizeof(XPVHV);
503 /* Now the array of buckets */
504 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
505 /* Now walk the bucket chain */
506 if (HvARRAY(thing)) {
509 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
510 cur_entry = *(HvARRAY(thing) + cur_bucket);
512 total_size += sizeof(HE);
513 if (cur_entry->hent_hek) {
514 /* Hash keys can be shared. Have we seen this before? */
515 if (check_new(tracking_hash, cur_entry->hent_hek)) {
516 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
519 cur_entry = cur_entry->hent_next;
523 total_size += magic_size(thing, tracking_hash);
526 total_size += sizeof(XPVCV);
527 total_size += magic_size(thing, tracking_hash);
529 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
530 if (check_new(tracking_hash, CvSTASH(thing))) {
531 total_size += thing_size((SV *)CvSTASH(thing), tracking_hash);
533 if (check_new(tracking_hash, SvSTASH(thing))) {
534 total_size += thing_size((SV *)SvSTASH(thing), tracking_hash);
536 if (check_new(tracking_hash, CvGV(thing))) {
537 total_size += thing_size((SV *)CvGV(thing), tracking_hash);
539 if (check_new(tracking_hash, CvPADLIST(thing))) {
540 total_size += thing_size((SV *)CvPADLIST(thing), tracking_hash);
542 if (check_new(tracking_hash, CvOUTSIDE(thing))) {
543 total_size += thing_size((SV *)CvOUTSIDE(thing), tracking_hash);
546 if (check_new(tracking_hash, CvSTART(thing))) {
547 total_size += op_size(CvSTART(thing), tracking_hash);
549 if (check_new(tracking_hash, CvROOT(thing))) {
550 total_size += op_size(CvROOT(thing), tracking_hash);
555 total_size += magic_size(thing, tracking_hash);
556 total_size += sizeof(XPVGV);
557 total_size += GvNAMELEN(thing);
559 /* Is there a file? */
561 if (check_new(tracking_hash, GvFILE(thing))) {
562 total_size += strlen(GvFILE(thing));
566 /* Is there something hanging off the glob? */
568 if (check_new(tracking_hash, GvGP(thing))) {
569 total_size += sizeof(GP);
572 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
573 total_size += thing_size(generic_thing, tracking_hash);
575 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
576 total_size += thing_size(generic_thing, tracking_hash);
578 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
579 total_size += thing_size(generic_thing, tracking_hash);
581 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
582 total_size += thing_size(generic_thing, tracking_hash);
584 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
585 total_size += thing_size(generic_thing, tracking_hash);
587 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
588 total_size += thing_size(generic_thing, tracking_hash);
595 total_size += sizeof(XPVFM);
596 total_size += magic_size(thing, tracking_hash);
597 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
598 if (check_new(tracking_hash, CvPADLIST(thing))) {
599 total_size += thing_size((SV *)CvPADLIST(thing), tracking_hash);
601 if (check_new(tracking_hash, CvOUTSIDE(thing))) {
602 total_size += thing_size((SV *)CvOUTSIDE(thing), tracking_hash);
605 if (go_yell && !fm_whine) {
606 carp("Devel::Size: Calculated sizes for FMs are incomplete");
611 total_size += sizeof(XPVIO);
612 total_size += magic_size(thing, tracking_hash);
613 if (check_new(tracking_hash, (SvPVX(thing)))) {
614 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
616 /* Some embedded char pointers */
617 if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xio_top_name)) {
618 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
620 if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
621 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
623 if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
624 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
626 /* Throw the GVs on the list to be walked if they're not-null */
627 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
628 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
631 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
632 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
635 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
636 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
640 /* Only go trotting through the IO structures if they're really
641 trottable. If USE_PERLIO is defined we can do this. If
642 not... we can't, so we don't even try */
644 /* Dig into xio_ifp and xio_ofp here */
645 croak("Devel::Size: Can't size up perlio layers yet");
649 croak("Devel::Size: Unknown variable type");
654 MODULE = Devel::Size PACKAGE = Devel::Size
663 SV *thing = orig_thing;
664 /* Hash to track our seen pointers */
665 HV *tracking_hash = newHV();
668 /* Check warning status */
673 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
674 go_yell = SvIV(warn_flag);
677 /* If they passed us a reference then dereference it. This is the
678 only way we can check the sizes of arrays and hashes */
679 #if (PERL_VERSION < 11)
680 if (SvOK(thing) && SvROK(thing)) {
689 RETVAL = thing_size(thing, tracking_hash);
690 /* Clean up after ourselves */
691 SvREFCNT_dec(tracking_hash);
698 total_size(orig_thing)
702 SV *thing = orig_thing;
703 /* Hash to track our seen pointers */
705 /* Array with things we still need to do */
710 /* Size starts at zero */
713 /* Check warning status */
718 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
719 go_yell = SvIV(warn_flag);
722 /* init these after the go_yell above */
723 tracking_hash = newHV();
724 pending_array = newAV();
726 /* We cannot push HV/AV directly, only the RV. So deref it
727 later (see below for "*** dereference later") and adjust here for
729 This is the only way we can check the sizes of arrays and hashes. */
731 RETVAL -= thing_size(thing, NULL);
734 /* Put it on the pending array */
735 av_push(pending_array, thing);
737 /* Now just yank things off the end of the array until it's done */
738 while (av_len(pending_array) >= 0) {
739 thing = av_pop(pending_array);
740 /* Process it if we've not seen it */
741 if (check_new(tracking_hash, thing)) {
742 dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
745 /* Yes, it is. So let's check the type */
746 switch (SvTYPE(thing)) {
747 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
751 av_push(pending_array, SvRV(thing));
755 /* this is the "*** dereference later" part - see above */
756 #if (PERL_VERSION < 11)
761 dbg_printf(("# Found RV\n"));
763 dbg_printf(("# Found RV\n"));
764 av_push(pending_array, SvRV(thing));
770 dbg_printf(("# Found type AV\n"));
771 /* Quick alias to cut down on casting */
772 AV *tempAV = (AV *)thing;
776 if (av_len(tempAV) != -1) {
778 /* Run through them all */
779 for (index = 0; index <= av_len(tempAV); index++) {
780 /* Did we get something? */
781 if ((tempSV = av_fetch(tempAV, index, 0))) {
783 if (*tempSV != &PL_sv_undef) {
784 /* Apparently not. Save it for later */
785 av_push(pending_array, *tempSV);
794 dbg_printf(("# Found type HV\n"));
795 /* Is there anything in here? */
796 if (hv_iterinit((HV *)thing)) {
798 while ((temp_he = hv_iternext((HV *)thing))) {
799 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
805 dbg_printf(("# Found type GV\n"));
806 /* Run through all the pieces and push the ones with bits */
808 av_push(pending_array, (SV *)GvSV(thing));
811 av_push(pending_array, (SV *)GvFORM(thing));
814 av_push(pending_array, (SV *)GvAV(thing));
817 av_push(pending_array, (SV *)GvHV(thing));
820 av_push(pending_array, (SV *)GvCV(thing));
829 size = thing_size(thing, tracking_hash);
832 /* check_new() returned false: */
833 #ifdef DEVEL_SIZE_DEBUGGING
834 if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
835 else printf("# Ignore non-sv 0x%x\n", sv);
840 /* Clean up after ourselves */
841 SvREFCNT_dec(tracking_hash);
842 SvREFCNT_dec(pending_array);