Don't count PL_sv_{undef,no,yes} in the size returned
Nicholas Clark [Mon, 18 Apr 2011 10:21:53 +0000 (11:21 +0100)]
PL_sv_{undef,no,yes} are singletons, interpreter wide, so shouldn't count as
part of the size.

CHANGES
Size.xs
t/basic.t
t/recurse.t

diff --git a/CHANGES b/CHANGES
index d1e8b6d..862d384 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
 Revision history for Perl extension Devel::Size.
 
+0.74_51 2011-04-20 nicholas
+ * Don't count PL_sv_{undef,no,yes} in the size returned
+
 0.74_50 2011-04-19 nicholas
  * Ensure that size() doesn't add the referent's size for non SVt_RV references
 
diff --git a/Size.xs b/Size.xs
index b2c777c..c533942 100644 (file)
--- a/Size.xs
+++ b/Size.xs
@@ -749,6 +749,9 @@ new_state(pTHX)
     if (NULL != (warn_flag = perl_get_sv("Devel::Size::dangle", FALSE))) {
        st->dangle_whine = SvIV(warn_flag) ? TRUE : FALSE;
     }
+    check_new(st, &PL_sv_undef);
+    check_new(st, &PL_sv_no);
+    check_new(st, &PL_sv_yes);
     return st;
 }
 
index 8073e01..86c58cd 100644 (file)
--- a/t/basic.t
+++ b/t/basic.t
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 
-use Test::More tests => 15;
+use Test::More tests => 18;
 use strict;
 use Devel::Size qw(size total_size);
 use Scalar::Util qw(weaken);
@@ -100,3 +100,13 @@ cmp_ok (total_size(\&LARGE), '>', 8192,
     is(total_size($a), total_size([]),
        'Any intial reference is dereferenced and discarded');
 }
+
+# Must call direct - avoid all copying:
+foreach(['undef', total_size(undef)],
+       ['no', total_size(1 == 0)],
+       ['yes', total_size(1 == 1)],
+       ) {
+    my ($name, $size) = @$_;
+    is($size, 0,
+       "PL_sv_$name is interpeter wide, so not counted as part of the structure's size");
+}
index 8a9866c..4c67b29 100644 (file)
@@ -40,10 +40,18 @@ $ptr_size /= 4;
 #############################################################################
 # assert hash and hash key size
 
+# Note, undef puts PL_sv_undef on perl's stack. Assigning to a hash or array
+# value is always copying, so { a => undef } has a value which is a fresh
+# (allocated) SVt_NULL. Nowever, total_size(undef) isn't a copy, so total_size()
+# sees PL_sv_undef, which is a singleton, interpreter wide, so isn't counted as
+# part of the size. So we need to use an unassigned scalar to get the correct
+# size for a SVt_NULL:
+my $undef;
+
 my $hash = {};
 $hash->{a} = 1;
 is (total_size($hash),
-    total_size( { a => undef } ) + total_size(1) - total_size(undef),
+    total_size( { a => undef } ) + total_size(1) - total_size($undef),
     'assert hash and hash key size');
 
 #############################################################################
@@ -177,7 +185,7 @@ for my $size (2, 3, 7, 100)
   $array = [ 0..$size, undef, undef ]; pop @$array;
 
   $array_size = total_size($array);
-  my $scalar_size = total_size(1) * (1+$size) + total_size(undef) * 1 + $ptr_size
+  my $scalar_size = total_size(1) * (1+$size) + total_size($undef) * 1 + $ptr_size
     + $ptr_size * ($size + 2) + total_size([]);
   is ($scalar_size, $array_size, "computed right size if full array");