In perl.git, the branch yves/hv_h_split has been updated <http://perl5.git.perl.org/perl.git/commitdiff/e2183dd1583911a709201025e7d0020fde8b1862?hp=728e03041b31deae2692138beb96fd7ca6f6519f>
- Log ----------------------------------------------------------------- commit e2183dd1583911a709201025e7d0020fde8b1862 Author: Yves Orton <[email protected]> Date: Tue Feb 19 13:25:53 2013 +0100 semi-Randomize hash insertion order M hv.c commit b33589ebd581733d90cb08d27eab2cf13f44a0d9 Author: Yves Orton <[email protected]> Date: Tue Feb 19 12:14:44 2013 +0100 Ensure that Module::Pluggable returns plugins in a predictable order As of 5.18 hash traversal order will vary per-hash, and indeed more frequently. The likelihood this results in one of the tests in M::P failing becomes very high. In general the test expectations were fragile, but probably almost never failed. With hash traversal randomization they will fail regularly. Note the use a temporary array in part of this patch is because sort in scalar context is undefined. M cpan/Module-Pluggable/lib/Module/Pluggable.pm M cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm M cpan/Module-Pluggable/t/19can_ok_clobber.t commit b23fbb6034fcc892c44527b955be9c682131de88 Author: Yves Orton <[email protected]> Date: Tue Feb 19 12:12:34 2013 +0100 Fix code which modifies a hash while each()ing over it It has never been correct to modify a hash during traversal by each(). In older perls this was unlikely to break the tests. In newer perls it is relatively likely, and in 5.18 it will be almost certain. This includes a version bump. Needs to be merged upstream. M cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm M cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm M cpan/ExtUtils-MakeMaker/t/basic.t ----------------------------------------------------------------------- Summary of changes: cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm | 2 +- cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm | 2 +- cpan/ExtUtils-MakeMaker/t/basic.t | 6 +--- cpan/Module-Pluggable/lib/Module/Pluggable.pm | 2 +- .../lib/Module/Pluggable/Object.pm | 5 ++- cpan/Module-Pluggable/t/19can_ok_clobber.t | 4 +- hv.c | 29 ++++++++++++++++++- 7 files changed, 36 insertions(+), 14 deletions(-) diff --git a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm index 68d19fa..f7c8f22 100644 --- a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm +++ b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MM_Unix.pm @@ -15,7 +15,7 @@ use ExtUtils::MakeMaker qw($Verbose neatvalue); # If we make $VERSION an our variable parse_version() breaks use vars qw($VERSION); -$VERSION = '6.64_01'; +$VERSION = '6.64_02'; $VERSION = eval $VERSION; require ExtUtils::MM_Any; diff --git a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm index fbe854b..5bdd517 100644 --- a/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm +++ b/cpan/ExtUtils-MakeMaker/lib/ExtUtils/MakeMaker.pm @@ -18,7 +18,7 @@ our @Overridable; my @Prepend_parent; my %Recognized_Att_Keys; -our $VERSION = '6.64_01'; +our $VERSION = '6.64_02'; $VERSION = eval $VERSION; # Emulate something resembling CVS $Revision$ diff --git a/cpan/ExtUtils-MakeMaker/t/basic.t b/cpan/ExtUtils-MakeMaker/t/basic.t index fb374c0..cd53c65 100644 --- a/cpan/ExtUtils-MakeMaker/t/basic.t +++ b/cpan/ExtUtils-MakeMaker/t/basic.t @@ -411,9 +411,5 @@ close SAVERR; sub _normalize { my $hash = shift; - - while(my($k,$v) = each %$hash) { - delete $hash->{$k}; - $hash->{lc $k} = $v; - } + %$hash= map { lc($_) => $hash->{$_} } keys %$hash; } diff --git a/cpan/Module-Pluggable/lib/Module/Pluggable.pm b/cpan/Module-Pluggable/lib/Module/Pluggable.pm index a723dbc..9e7962e 100644 --- a/cpan/Module-Pluggable/lib/Module/Pluggable.pm +++ b/cpan/Module-Pluggable/lib/Module/Pluggable.pm @@ -11,7 +11,7 @@ use if $] > 5.017, 'deprecate'; # Peter Gibbons: I wouldn't say I've been missing it, Bob! -$VERSION = '4.6'; # core release only! +$VERSION = '4.7'; $FORCE_SEARCH_ALL_PATHS = 0; sub import { diff --git a/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm b/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm index 3c198a7..c9960d3 100644 --- a/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm +++ b/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm @@ -83,7 +83,7 @@ sub plugins { if (defined $self->{'instantiate'}) { my $method = $self->{'instantiate'}; my @objs = (); - foreach my $package (keys %plugins) { + foreach my $package (sort keys %plugins) { next unless $package->can($method); my $obj = eval { $package->$method(@_) }; $self->{'on_instantiate_error'}->($package, $@) if $@; @@ -92,7 +92,8 @@ sub plugins { return @objs; } else { # no? just return the names - return keys %plugins; + my @objs= sort keys %plugins; + return @objs; } } diff --git a/cpan/Module-Pluggable/t/19can_ok_clobber.t b/cpan/Module-Pluggable/t/19can_ok_clobber.t index 07c598b..8b1466d 100644 --- a/cpan/Module-Pluggable/t/19can_ok_clobber.t +++ b/cpan/Module-Pluggable/t/19can_ok_clobber.t @@ -21,7 +21,7 @@ is_deeply( \@plugins_after, \@plugins, "plugins haven't been clobbered", -); +) or diag Dumper(\@plugins_after,\@plugins); can_ok ($foo, 'frobnitz'); @@ -30,7 +30,7 @@ is_deeply( \@plugins_after, \@plugins, "plugins haven't been clobbered", -) or diag Dumper ; +) or diag Dumper(\@plugins_after,\@plugins); diff --git a/hv.c b/hv.c index 474a79f..fa19c2b 100644 --- a/hv.c +++ b/hv.c @@ -786,8 +786,33 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, else /* gotta do the real thing */ HeKEY_hek(entry) = save_hek_flags(key, klen, hash, flags); HeVAL(entry) = val; - HeNEXT(entry) = *oentry; - *oentry = entry; + if (*oentry) { + /* This logic semi- randomizes the insert order in a bucket. + * Either we insert into the top, or the slot below the top + * + * We rotate the HvRAND(hv) each time we use it, so that each + * insert potentially gets a different result. + */ + if (!HvRAND(hv)) { + HvRAND(hv)= ptr_hash((PTRV)HvARRAY(hv)); + } + if (HvRAND(hv) & 1) { + HeNEXT(entry) = *oentry; + *oentry = entry; + } else { + HeNEXT(entry) = HeNEXT(*oentry); + HeNEXT(*oentry) = entry; + } + HvRAND(hv)= ROTL32(HvRAND(hv),1); + } + else { + *oentry = entry; + /* I am not sure that HeNEXT(entry) will be NULL or not after new_HE(). + * So for now we assume that this is not a safe assumption, and set it explicitly. + * If we can prove that it IS a safe assumption we could remove the next line. + */ + HeNEXT(entry) = NULL; + } if (val == &PL_sv_placeholder) HvPLACEHOLDERS(hv)++; -- Perl5 Master Repository
