5 static int regex_whine;
10 UV thing_size(SV *, HV *);
33 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
35 if (o->op_type == OP_SASSIGN)
36 return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
39 if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)
43 if ((o->op_type = OP_TRANS)) {
47 switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
74 * Character translations (tr///) are usually a PVOP, keeping a
75 * pointer to a table of shorts used to look up translations.
76 * Under utf8, however, a simple table isn't practical; instead,
77 * the OP is an SVOP, and the SV is a reference to a swash
78 * (i.e., an RV pointing to an HV).
80 return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
81 ? OPc_SVOP : OPc_PVOP;
89 case OA_BASEOP_OR_UNOP:
91 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
92 * whether parens were seen. perly.y uses OPf_SPECIAL to
93 * signal whether a BASEOP had empty parens or none.
94 * Some other UNOPs are created later, though, so the best
95 * test is OPf_KIDS, which is set in newUNOP.
97 return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
101 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
102 * the OPf_REF flag to distinguish between OP types instead of the
103 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
104 * return OPc_UNOP so that walkoptree can find our children. If
105 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
106 * (no argument to the operator) it's an OP; with OPf_REF set it's
107 * an SVOP (and op_sv is the GV for the filehandle argument).
109 return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
111 (o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
113 (o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
117 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
118 * label was omitted (in which case it's a BASEOP) or else a term was
119 * seen. In this last case, all except goto are definitely PVOP but
120 * goto is either a PVOP (with an ordinary constant label), an UNOP
121 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
122 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
125 if (o->op_flags & OPf_STACKED)
127 else if (o->op_flags & OPf_SPECIAL)
132 warn("can't determine class of operator %s, assuming BASEOP\n",
133 PL_op_name[o->op_type]);
142 static int go_yell = 1;
144 /* Checks to see if thing is in the hash. Returns true or false, and
145 notes thing in the hash.
147 This code does one Evil Thing. Since we're tracking pointers, we
148 tell perl that the string key is the address in the pointer. We do this by
149 passing in the address of the address, along with the size of a
150 pointer as the length. Perl then uses the four (or eight, on
151 64-bit machines) bytes of the address as the string we're using as
153 IV check_new(HV *tracking_hash, const void *thing) {
157 if (hv_exists(tracking_hash, (char *)&thing, sizeof(void *))) {
160 hv_store(tracking_hash, (char *)&thing, sizeof(void *), &PL_sv_yes, 0);
165 /* Figure out how much magic is attached to the SV and return the
167 IV magic_size(SV *thing, HV *tracking_hash) {
169 MAGIC *magic_pointer;
172 if (!SvMAGIC(thing)) {
177 /* Get the base magic pointer */
178 magic_pointer = SvMAGIC(thing);
180 /* Have we seen the magic pointer? */
181 while (magic_pointer && check_new(tracking_hash, magic_pointer)) {
182 total_size += sizeof(MAGIC);
184 /* Have we seen the magic vtable? */
185 if (magic_pointer->mg_virtual &&
186 check_new(tracking_hash, magic_pointer->mg_virtual)) {
187 total_size += sizeof(MGVTBL);
190 /* Get the next in the chain */
191 magic_pointer = magic_pointer->mg_moremagic;
197 UV regex_size(REGEXP *baseregex, HV *tracking_hash) {
200 total_size += sizeof(REGEXP);
201 /* Note hte size of the paren offset thing */
202 total_size += sizeof(I32) * baseregex->nparens * 2;
203 total_size += strlen(baseregex->precomp);
205 if (go_yell && !regex_whine) {
206 carp("Devel::Size: Calculated sizes for compiled regexes are incomple, and probably always will be");
213 UV op_size(OP *baseop, HV *tracking_hash) {
216 if (check_new(tracking_hash, baseop->op_next)) {
217 total_size += op_size(baseop->op_next, tracking_hash);
220 switch (cc_opclass(baseop)) {
222 total_size += sizeof(struct op);
225 total_size += sizeof(struct unop);
226 if (check_new(tracking_hash, cUNOPx(baseop)->op_first)) {
227 total_size += op_size(cUNOPx(baseop)->op_first, tracking_hash);
231 total_size += sizeof(struct binop);
232 if (check_new(tracking_hash, cBINOPx(baseop)->op_first)) {
233 total_size += op_size(cBINOPx(baseop)->op_first, tracking_hash);
235 if (check_new(tracking_hash, cBINOPx(baseop)->op_last)) {
236 total_size += op_size(cBINOPx(baseop)->op_last, tracking_hash);
240 total_size += sizeof(struct logop);
241 if (check_new(tracking_hash, cLOGOPx(baseop)->op_first)) {
242 total_size += op_size(cBINOPx(baseop)->op_first, tracking_hash);
244 if (check_new(tracking_hash, cLOGOPx(baseop)->op_other)) {
245 total_size += op_size(cLOGOPx(baseop)->op_other, tracking_hash);
249 total_size += sizeof(struct listop);
250 if (check_new(tracking_hash, cLISTOPx(baseop)->op_first)) {
251 total_size += op_size(cLISTOPx(baseop)->op_first, tracking_hash);
253 if (check_new(tracking_hash, cLISTOPx(baseop)->op_last)) {
254 total_size += op_size(cLISTOPx(baseop)->op_last, tracking_hash);
258 total_size += sizeof(struct pmop);
259 if (check_new(tracking_hash, cPMOPx(baseop)->op_first)) {
260 total_size += op_size(cPMOPx(baseop)->op_first, tracking_hash);
262 if (check_new(tracking_hash, cPMOPx(baseop)->op_last)) {
263 total_size += op_size(cPMOPx(baseop)->op_last, tracking_hash);
265 #if PERL_VERSION < 9 || (PERL_VERSION == 9 && PERL_SUBVERSION < 5)
266 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmreplroot)) {
267 total_size += op_size(cPMOPx(baseop)->op_pmreplroot, tracking_hash);
269 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmreplstart)) {
270 total_size += op_size(cPMOPx(baseop)->op_pmreplstart, tracking_hash);
272 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmnext)) {
273 total_size += op_size((OP *)cPMOPx(baseop)->op_pmnext, tracking_hash);
276 /* This is defined away in perl 5.8.x, but it is in there for
279 if (check_new(tracking_hash, PM_GETRE((cPMOPx(baseop))))) {
280 total_size += regex_size(PM_GETRE(cPMOPx(baseop)), tracking_hash);
283 if (check_new(tracking_hash, cPMOPx(baseop)->op_pmregexp)) {
284 total_size += regex_size(cPMOPx(baseop)->op_pmregexp, tracking_hash);
289 total_size += sizeof(struct pmop);
290 if (check_new(tracking_hash, cSVOPx(baseop)->op_sv)) {
291 total_size += thing_size(cSVOPx(baseop)->op_sv, tracking_hash);
295 total_size += sizeof(struct padop);
298 if (check_new(tracking_hash, cPVOPx(baseop)->op_pv)) {
299 total_size += strlen(cPVOPx(baseop)->op_pv);
302 total_size += sizeof(struct loop);
303 if (check_new(tracking_hash, cLOOPx(baseop)->op_first)) {
304 total_size += op_size(cLOOPx(baseop)->op_first, tracking_hash);
306 if (check_new(tracking_hash, cLOOPx(baseop)->op_last)) {
307 total_size += op_size(cLOOPx(baseop)->op_last, tracking_hash);
309 if (check_new(tracking_hash, cLOOPx(baseop)->op_redoop)) {
310 total_size += op_size(cLOOPx(baseop)->op_redoop, tracking_hash);
312 if (check_new(tracking_hash, cLOOPx(baseop)->op_nextop)) {
313 total_size += op_size(cLOOPx(baseop)->op_nextop, tracking_hash);
315 /* Not working for some reason, but the code's here for later
317 if (check_new(tracking_hash, cLOOPx(baseop)->op_lastop)) {
318 total_size += op_size(cLOOPx(baseop)->op_lastop, tracking_hash);
325 basecop = (COP *)baseop;
326 total_size += sizeof(struct cop);
328 if (check_new(tracking_hash, basecop->cop_label)) {
329 total_size += strlen(basecop->cop_label);
332 if (check_new(tracking_hash, basecop->cop_file)) {
333 total_size += strlen(basecop->cop_file);
335 if (check_new(tracking_hash, basecop->cop_stashpv)) {
336 total_size += strlen(basecop->cop_stashpv);
339 if (check_new(tracking_hash, basecop->cop_stash)) {
340 total_size += thing_size((SV *)basecop->cop_stash, tracking_hash);
342 if (check_new(tracking_hash, basecop->cop_filegv)) {
343 total_size += thing_size((SV *)basecop->cop_filegv, tracking_hash);
355 #if PERL_VERSION > 9 || (PERL_VERSION == 9 && PERL_SUBVERSION > 2)
356 # define NEW_HEAD_LAYOUT
359 UV thing_size(SV *orig_thing, HV *tracking_hash) {
360 SV *thing = orig_thing;
361 UV total_size = sizeof(SV);
363 switch (SvTYPE(thing)) {
367 /* Just a plain integer. This will be differently sized depending
368 on whether purify's been compiled in */
370 #ifndef NEW_HEAD_LAYOUT
372 total_size += sizeof(sizeof(XPVIV));
374 total_size += sizeof(IV);
378 /* Is it a float? Like the int, it depends on purify */
381 total_size += sizeof(sizeof(XPVNV));
383 total_size += sizeof(NV);
386 /* Is it a reference? */
388 #ifndef NEW_HEAD_LAYOUT
389 total_size += sizeof(XRV);
392 /* How about a plain string? In which case we need to add in how
393 much has been allocated */
395 total_size += sizeof(XPV);
396 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
398 /* A string with an integer part? */
400 total_size += sizeof(XPVIV);
401 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
403 total_size += SvIVX(thing);
406 /* A scalar/string/reference with a float part? */
408 total_size += sizeof(XPVNV);
409 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
412 total_size += sizeof(XPVMG);
413 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
414 total_size += magic_size(thing, tracking_hash);
416 #if PERL_VERSION <= 8
418 total_size += sizeof(XPVBM);
419 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
420 total_size += magic_size(thing, tracking_hash);
424 total_size += sizeof(XPVLV);
425 total_size += SvROK(thing) ? thing_size( SvRV(thing), tracking_hash) : SvLEN(thing);
426 total_size += magic_size(thing, tracking_hash);
428 /* How much space is dedicated to the array? Not counting the
429 elements in the array, mind, just the array itself */
431 total_size += sizeof(XPVAV);
432 /* Is there anything in the array? */
433 if (AvMAX(thing) != -1) {
434 /* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
435 total_size += sizeof(SV *) * (AvMAX(thing) + 1);
436 /* printf ("total_size: %li AvMAX: %li av_len: %i\n", total_size, AvMAX(thing), av_len(thing)); */
438 /* Add in the bits on the other side of the beginning */
440 /* printf ("total_size %li, sizeof(SV *) %li, AvARRAY(thing) %li, AvALLOC(thing)%li , sizeof(ptr) %li \n",
441 total_size, sizeof(SV*), AvARRAY(thing), AvALLOC(thing), sizeof( thing )); */
443 /* under Perl 5.8.8 64bit threading, AvARRAY(thing) was a pointer while AvALLOC was 0,
444 resulting in grossly overstated sized for arrays. Technically, this shouldn't happen... */
445 if (AvALLOC(thing) != 0) {
446 total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
448 /* Is there something hanging off the arylen element? */
449 if (AvARYLEN(thing)) {
450 if (check_new(tracking_hash, AvARYLEN(thing))) {
451 total_size += thing_size(AvARYLEN(thing), tracking_hash);
454 total_size += magic_size(thing, tracking_hash);
457 /* First the base struct */
458 total_size += sizeof(XPVHV);
459 /* Now the array of buckets */
460 total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
461 /* Now walk the bucket chain */
462 if (HvARRAY(thing)) {
465 for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) {
466 cur_entry = *(HvARRAY(thing) + cur_bucket);
468 total_size += sizeof(HE);
469 if (cur_entry->hent_hek) {
470 /* Hash keys can be shared. Have we seen this before? */
471 if (check_new(tracking_hash, cur_entry->hent_hek)) {
472 total_size += HEK_BASESIZE + cur_entry->hent_hek->hek_len + 2;
475 cur_entry = cur_entry->hent_next;
479 total_size += magic_size(thing, tracking_hash);
482 total_size += sizeof(XPVCV);
483 total_size += magic_size(thing, tracking_hash);
485 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
486 if (check_new(tracking_hash, CvSTASH(thing))) {
487 total_size += thing_size((SV *)CvSTASH(thing), tracking_hash);
489 if (check_new(tracking_hash, SvSTASH(thing))) {
490 total_size += thing_size((SV *)SvSTASH(thing), tracking_hash);
492 if (check_new(tracking_hash, CvGV(thing))) {
493 total_size += thing_size((SV *)CvGV(thing), tracking_hash);
495 if (check_new(tracking_hash, CvPADLIST(thing))) {
496 total_size += thing_size((SV *)CvPADLIST(thing), tracking_hash);
498 if (check_new(tracking_hash, CvOUTSIDE(thing))) {
499 total_size += thing_size((SV *)CvOUTSIDE(thing), tracking_hash);
502 if (check_new(tracking_hash, CvSTART(thing))) {
503 total_size += op_size(CvSTART(thing), tracking_hash);
505 if (check_new(tracking_hash, CvROOT(thing))) {
506 total_size += op_size(CvROOT(thing), tracking_hash);
511 total_size += magic_size(thing, tracking_hash);
512 total_size += sizeof(XPVGV);
513 total_size += GvNAMELEN(thing);
515 /* Is there a file? */
517 if (check_new(tracking_hash, GvFILE(thing))) {
518 total_size += strlen(GvFILE(thing));
522 /* Is there something hanging off the glob? */
524 if (check_new(tracking_hash, GvGP(thing))) {
525 total_size += sizeof(GP);
528 if ((generic_thing = (SV *)(GvGP(thing)->gp_sv))) {
529 total_size += thing_size(generic_thing, tracking_hash);
531 if ((generic_thing = (SV *)(GvGP(thing)->gp_form))) {
532 total_size += thing_size(generic_thing, tracking_hash);
534 if ((generic_thing = (SV *)(GvGP(thing)->gp_av))) {
535 total_size += thing_size(generic_thing, tracking_hash);
537 if ((generic_thing = (SV *)(GvGP(thing)->gp_hv))) {
538 total_size += thing_size(generic_thing, tracking_hash);
540 if ((generic_thing = (SV *)(GvGP(thing)->gp_egv))) {
541 total_size += thing_size(generic_thing, tracking_hash);
543 if ((generic_thing = (SV *)(GvGP(thing)->gp_cv))) {
544 total_size += thing_size(generic_thing, tracking_hash);
551 total_size += sizeof(XPVFM);
552 total_size += magic_size(thing, tracking_hash);
553 total_size += ((XPVIO *) SvANY(thing))->xpv_len;
554 if (check_new(tracking_hash, CvPADLIST(thing))) {
555 total_size += thing_size((SV *)CvPADLIST(thing), tracking_hash);
557 if (check_new(tracking_hash, CvOUTSIDE(thing))) {
558 total_size += thing_size((SV *)CvOUTSIDE(thing), tracking_hash);
561 if (go_yell && !fm_whine) {
562 carp("Devel::Size: Calculated sizes for FMs are incomplete");
567 total_size += sizeof(XPVIO);
568 total_size += magic_size(thing, tracking_hash);
569 if (check_new(tracking_hash, (SvPVX(thing)))) {
570 total_size += ((XPVIO *) SvANY(thing))->xpv_cur;
572 /* Some embedded char pointers */
573 if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xio_top_name)) {
574 total_size += strlen(((XPVIO *) SvANY(thing))->xio_top_name);
576 if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xio_fmt_name)) {
577 total_size += strlen(((XPVIO *) SvANY(thing))->xio_fmt_name);
579 if (check_new(tracking_hash, ((XPVIO *) SvANY(thing))->xio_bottom_name)) {
580 total_size += strlen(((XPVIO *) SvANY(thing))->xio_bottom_name);
582 /* Throw the GVs on the list to be walked if they're not-null */
583 if (((XPVIO *) SvANY(thing))->xio_top_gv) {
584 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_top_gv,
587 if (((XPVIO *) SvANY(thing))->xio_bottom_gv) {
588 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_bottom_gv,
591 if (((XPVIO *) SvANY(thing))->xio_fmt_gv) {
592 total_size += thing_size((SV *)((XPVIO *) SvANY(thing))->xio_fmt_gv,
596 /* Only go trotting through the IO structures if they're really
597 trottable. If USE_PERLIO is defined we can do this. If
598 not... we can't, so we don't even try */
600 /* Dig into xio_ifp and xio_ofp here */
601 croak("Devel::Size: Can't size up perlio layers yet");
605 croak("Devel::Size: Unknown variable type");
610 MODULE = Devel::Size PACKAGE = Devel::Size
619 SV *thing = orig_thing;
620 /* Hash to track our seen pointers */
621 HV *tracking_hash = newHV();
624 /* Check warning status */
629 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
630 go_yell = SvIV(warn_flag);
634 /* If they passed us a reference then dereference it. This is the
635 only way we can check the sizes of arrays and hashes */
636 if (SvOK(thing) && SvROK(thing)) {
640 RETVAL = thing_size(thing, tracking_hash);
641 /* Clean up after ourselves */
642 SvREFCNT_dec(tracking_hash);
649 total_size(orig_thing)
653 SV *thing = orig_thing;
654 /* Hash to track our seen pointers */
655 HV *tracking_hash = newHV();
656 AV *pending_array = newAV();
660 /* Size starts at zero */
663 /* Check warning status */
668 if (NULL != (warn_flag = perl_get_sv("Devel::Size::warn", FALSE))) {
669 go_yell = SvIV(warn_flag);
673 /* If they passed us a reference then dereference it. This is the
674 only way we can check the sizes of arrays and hashes */
675 if (SvOK(thing) && SvROK(thing)) {
679 /* Put it on the pending array */
680 av_push(pending_array, thing);
682 /* Now just yank things off the end of the array until it's done */
683 while (av_len(pending_array) >= 0) {
684 thing = av_pop(pending_array);
685 /* Process it if we've not seen it */
686 if (check_new(tracking_hash, thing)) {
689 /* printf ("Found type %i at %p\n", SvTYPE(thing), thing); */
691 /* Yes, it is. So let's check the type */
692 switch (SvTYPE(thing)) {
694 av_push(pending_array, SvRV(thing));
697 /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
701 av_push(pending_array, SvRV(thing));
707 /* Quick alias to cut down on casting */
708 AV *tempAV = (AV *)thing;
712 if (av_len(tempAV) != -1) {
714 /* Run through them all */
715 for (index = 0; index <= av_len(tempAV); index++) {
716 /* Did we get something? */
717 if ((tempSV = av_fetch(tempAV, index, 0))) {
719 if (*tempSV != &PL_sv_undef) {
720 /* Apparently not. Save it for later */
721 av_push(pending_array, *tempSV);
730 /* Is there anything in here? */
731 if (hv_iterinit((HV *)thing)) {
733 while ((temp_he = hv_iternext((HV *)thing))) {
734 av_push(pending_array, hv_iterval((HV *)thing, temp_he));
740 /* Run through all the pieces and push the ones with bits */
742 av_push(pending_array, (SV *)GvSV(thing));
745 av_push(pending_array, (SV *)GvFORM(thing));
748 av_push(pending_array, (SV *)GvAV(thing));
751 av_push(pending_array, (SV *)GvHV(thing));
754 av_push(pending_array, (SV *)GvCV(thing));
763 size = thing_size(thing, tracking_hash);
768 /* Clean up after ourselves */
769 SvREFCNT_dec(tracking_hash);
770 SvREFCNT_dec(pending_array);