without excessive memory needs. The assumption is that your CPU cache
works :-) (And that we're not going to bust it) */
-#define ALIGN_BITS ( sizeof(void*) >> 1 )
#define BYTE_BITS 3
#define LEAF_BITS (16 - BYTE_BITS)
#define LEAF_MASK 0x1FFF
(and hence hot in the cache) but we can still deal with any unaligned
pointers. */
const size_t cooked_p
- = (raw_p >> ALIGN_BITS) | (raw_p << (bits - BYTE_BITS));
+ = (raw_p >> ALIGN_BITS) | (raw_p << (bits - ALIGN_BITS));
const U8 this_bit = 1 << (cooked_p & 0x7);
U8 **leaf_p;
U8 *leaf;
/* an array with 10 slots has AvMax() set to 9 - te 2007-04-22 */
st->total_size += sizeof(SV *) * (AvMAX(thing) + 1);
dbg_printf(("total_size: %li AvMAX: %li av_len: $i\n", st->total_size, AvMAX(thing), av_len((AV*)thing)));
+
+ if (recurse >= TOTAL_SIZE_RECURSION) {
+ SSize_t i = AvFILLp(thing) + 1;
+
+ while (i--)
+ sv_size(aTHX_ st, AvARRAY(thing)[i], recurse);
+ }
}
/* Add in the bits on the other side of the beginning */
sv_size(aTHX_ st, (SV *)CvSTASH(thing), SOME_RECURSION);
sv_size(aTHX_ st, (SV *)SvSTASH(thing), SOME_RECURSION);
sv_size(aTHX_ st, (SV *)CvGV(thing), SOME_RECURSION);
- sv_size(aTHX_ st, (SV *)CvPADLIST(thing), recurse);
+ sv_size(aTHX_ st, (SV *)CvPADLIST(thing), SOME_RECURSION);
sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
if (CvISXSUB(thing)) {
sv_size(aTHX_ st, cv_const_sv((CV *)thing), recurse);
if(isGV_with_GP(thing)) {
st->total_size += GvNAMELEN(thing);
#ifdef GvFILE
- /* Is there a file? */
+# if !defined(USE_ITHREADS) || (PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION > 8))
+ /* With itreads, before 5.8.9, this can end up pointing to freed memory
+ if the GV was created in an eval, as GvFILE() points to CopFILE(),
+ and the relevant COP has been freed on scope cleanup after the eval.
+ 5.8.9 adds a binary compatible fudge that catches the vast majority
+ of cases. 5.9.something added a proper fix, by converting the GP to
+ use a shared hash key (porperly reference counted), instead of a
+ char * (owned by who knows? possibly no-one now) */
check_new_and_strlen(st, GvFILE(thing));
+# endif
#endif
/* Is there something hanging off the glob? */
if (check_new(st, GvGP(thing))) {
st->total_size += sizeof(XPVFM);
magic_size(thing, st);
st->total_size += ((XPVIO *) SvANY(thing))->xpv_len;
- sv_size(aTHX_ st, (SV *)CvPADLIST(thing), recurse);
+ sv_size(aTHX_ st, (SV *)CvPADLIST(thing), SOME_RECURSION);
sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
if (st->go_yell && !st->fm_whine) {
UV
size(orig_thing)
SV *orig_thing
+ALIAS:
+ total_size = TOTAL_SIZE_RECURSION
CODE:
{
SV *thing = orig_thing;
/* If they passed us a reference then dereference it. This is the
only way we can check the sizes of arrays and hashes */
-#if (PERL_VERSION < 11)
- if (SvOK(thing) && SvROK(thing)) {
- thing = SvRV(thing);
- }
-#else
if (SvROK(thing)) {
thing = SvRV(thing);
}
-#endif
-
- sv_size(aTHX_ st, thing, NO_RECURSION);
- RETVAL = st->total_size;
- free_state(st);
-}
-OUTPUT:
- RETVAL
-
-
-UV
-total_size(orig_thing)
- SV *orig_thing
-CODE:
-{
- SV *thing = orig_thing;
- /* Array with things we still need to do */
- AV *pending_array;
- IV size = 0;
- struct state *st = new_state(aTHX);
-
- /* Size starts at zero */
- RETVAL = 0;
-
- pending_array = newAV();
-
- /* If they passed us a reference then dereference it.
- This is the only way we can check the sizes of arrays and hashes. */
- if (SvROK(thing)) {
- thing = SvRV(thing);
- }
-
- /* Put it on the pending array */
- av_push(pending_array, thing);
-
- /* Now just yank things off the end of the array until it's done */
- while (av_len(pending_array) >= 0) {
- thing = av_pop(pending_array);
- /* Process it if we've not seen it */
- if (sv_size(aTHX_ st, thing, TOTAL_SIZE_RECURSION)) {
- dbg_printf(("# Found type %i at %p\n", SvTYPE(thing), thing));
- switch (SvTYPE(thing)) {
- /* fix for bug #24846 (Does not correctly recurse into references in a PVNV-type scalar) */
- case SVt_PVNV: TAG;
- if (SvROK(thing))
- {
- av_push(pending_array, SvRV(thing));
- }
- TAG;break;
-#if (PERL_VERSION < 11)
- case SVt_RV: TAG;
-#else
- case SVt_IV: TAG;
-#endif
- dbg_printf(("# Found RV\n"));
- if (SvROK(thing)) {
- dbg_printf(("# Found RV\n"));
- av_push(pending_array, SvRV(thing));
- }
- TAG;break;
-
- case SVt_PVAV: TAG;
- {
- AV *tempAV = (AV *)thing;
- SV **tempSV;
-
- dbg_printf(("# Found type AV\n"));
- /* Quick alias to cut down on casting */
-
- /* Any elements? */
- if (av_len(tempAV) != -1) {
- IV index;
- /* Run through them all */
- for (index = 0; index <= av_len(tempAV); index++) {
- /* Did we get something? */
- if ((tempSV = av_fetch(tempAV, index, 0))) {
- /* Was it undef? */
- if (*tempSV != &PL_sv_undef) {
- /* Apparently not. Save it for later */
- av_push(pending_array, *tempSV);
- }
- }
- }
- }
- }
- TAG;break;
-
- case SVt_PVGV: TAG;
- dbg_printf(("# Found type GV\n"));
- if(!isGV_with_GP(thing))
- break;
- /* Run through all the pieces and push the ones with bits */
- if (GvSV(thing)) {
- av_push(pending_array, (SV *)GvSV(thing));
- }
- if (GvFORM(thing)) {
- av_push(pending_array, (SV *)GvFORM(thing));
- }
- if (GvAV(thing)) {
- av_push(pending_array, (SV *)GvAV(thing));
- }
- if (GvHV(thing)) {
- av_push(pending_array, (SV *)GvHV(thing));
- }
- if (GvCV(thing)) {
- av_push(pending_array, (SV *)GvCV(thing));
- }
- TAG;break;
- default:
- TAG;break;
- }
- } else {
- /* check_new() returned false: */
-#ifdef DEVEL_SIZE_DEBUGGING
- if (SvOK(sv)) printf("# Ignore ref copy 0x%x\n", sv);
- else printf("# Ignore non-sv 0x%x\n", sv);
-#endif
- }
- } /* end while */
+ sv_size(aTHX_ st, thing, ix);
RETVAL = st->total_size;
free_state(st);
- SvREFCNT_dec(pending_array);
}
OUTPUT:
RETVAL
-