On Thu Feb 09 18:53:29 2012, RURBAN wrote:
Show quoted text> On Thu Feb 09 18:08:07 2012, RURBAN wrote:
> > I have a patch for that but I do not fully understand why suddenly with
> > 5.15.6 the CV shared 5 pointers less. Nick should now and adjust it.
>
>
> Nope, this version failed on 32bit use64bitint. And the explanation is
> now a bit weirder.
>
> Revised patch attached
Thanks for trying to nail it. I had a long look, and the explanation
seems to be much much stranger than this.
If one changes the order of these three in globs.t:
gv_grew('glipp', 'zok', 'no strict "vars"; $zok = undef; 1', 'SCALAR');
gv_grew('bang', 'boff', 'no strict "vars"; @boff = (); 1', 'ARRAY');
gv_grew('clange', 'sock', 'no strict "vars"; %sock = (); 1', 'HASH');
then it's always the *first* one that fails.
I bisected the blead commit that caused the failure using this shell
script to unpack Devel::Size into the perl tree before building perl:
#!/bin/sh
git clean -dxf
# If you get './makedepend: 1: Syntax error: Unterminated quoted
# string' when bisecting versions of perl older than 5.9.5 this hack
# will work around the bug in makedepend.SH which was fixed in
# version 96a8704c. Make sure to comment out 'git checkout makedepend.SH'
# below too.
git show blead:makedepend.SH > makedepend.SH
(cd ext && tar xfz
/Volumes/Nonsense/cpan/authors/id/N/NW/NWCLARK/Devel-Size-0.77.tar.gz &&
mv Devel-Size-0.77 Devel-Size)
# If you can use ccache, add -Dcc=ccache\ gcc -Dld=gcc to the Configure line
# if Encode is not needed for the test, you can speed up the bisect by
# excluding it from the runs with -Dnoextensions=Encode
./Configure -Dusedevel -Dcc=ccache\ gcc -Dld=gcc -Dnoextensions=Encode -de
test -f config.sh || exit 125
# Correct makefile for newer GNU gcc
perl -ni -we 'print unless /<(?:built-in|command)/' makefile x2p/makefile
# if you just need miniperl, replace test_prep with miniperl
make -j3 test_prep
[ -x ./perl ] || exit 125
./perl -Ilib ext/Devel-Size/t/globs.t
ret=$?
[ $ret -gt 127 ] && ret=127
# git checkout makedepend.SH
git clean -dxf
exit $ret
Turns out that it's this commit
http://perl5.git.perl.org/perl.git/commit/b50b20584a1bbc1a
author Father Chrysostomos <sprout@cpan.org>
Wed, 7 Dec 2011 02:12:14 +0000 (18:12 -0800)
Implement new ‘use 5.xxx' plan
• Version declarations now unload all features before loading the
specified feature bundle.
• Explicit use/no strict overrides any implicit strict-loading done by
version declarations, whether before or after use of strict.pm.
• ‘use 5.01’ or earlier disables any implicitly-enabled strictures.
which really wasn't what I expected.
After a fair amount of grovelling with gdb, the extra 40 bytes turns
out to be sizeof(struct xpvhv_aux), added by line 766:
st->total_size += sizeof(struct xpvhv_aux);
After a lot more head scratching, this is because that commit changes
things so that use strict; will assign to %^H. Before:
$ /Users/nick/Sandpit/snap-v5.15.5-305*/bin/perl5.15.5 -le 'use strict;
BEGIN {print foreach keys %^H}'
After:
$ /Users/nick/Sandpit/snap-v5.15.5-306*/bin/perl5.15.5 -le 'use strict;
BEGIN {print foreach keys %^H}'
strict/subs
strict/refs
strict/vars
This in turn matters, because the eval in gv_grew() in globs.t:
eval $code or die "For $type, can't execute q{$code}: $@";
a: now has a private copy of %^H in the optree
b: now copies that at runtime onto the stack for the eval
and to copy a hash requires a hash iterator, so the *first* time the
hash is copied its size is increased to hold the iterator. Which
happens after this line:
my $cv_was_size = size(do {no strict 'refs'; \&$sub});
This makes a difference because the total size of anything that can
reach \&gv_grew will include this extra size. In this case, this means
that if the code for generate_glob() is within gv_grew() [as it used
to be], then the generated subroutine's CvOUTSIDE points to an anon
sub whose CvOUTSIDE points to gv_grew(). Which means that the
generated subroutine gets "bigger" simply as a side effect of the eval
executing.
The solution is to put the eval that creates the subroutine into a
different scope, so that its outside pointer chain doesn't include
gv_grew(). Hence it's now broken out into generate_glob
I was about to roll up a dev release with a changed t/globs.t, but
I've found that I'm getting an assertion failure from t/magic.t in
5.8.0-5.8.2, which I'm going to see if I can fix too.