Change 30259 by [EMAIL PROTECTED] on 2007/02/13 16:04:12
Integrate:
[ 26483]
Using a hash reference rather than a hash can save a hash copy.
[ 26484]
Tests for creating constants where prototypes or other symbols of the
same name already exist.
[ 26485]
The value from caller doesn't change, so my $pkg = caller;
should be moved out of the loop.
[ 26487]
Rework constant.pm to take advantage of the space savings of proxy
constant subroutines whenever it can.
[ 26502]
As what we're doing is generating subroutines, which are methods, we
need to invalidate cached methods. For constant.pm we need to create
&Internals::inc_sub_generation
[ 30255]
Change 26487 left some debugging code in, and through the wonders of
autovivification, that code actually introduced a bug, most easily
visible for the for the non-5.9.x case.
Affected files ...
... //depot/maint-5.8/perl/lib/constant.pm#3 integrate
... //depot/maint-5.8/perl/lib/constant.t#6 integrate
... //depot/maint-5.8/perl/universal.c#62 integrate
Differences ...
==== //depot/maint-5.8/perl/lib/constant.pm#3 (text) ====
Index: perl/lib/constant.pm
--- perl/lib/constant.pm#2~23593~ 2004-12-01 11:11:22.000000000 -0800
+++ perl/lib/constant.pm 2007-02-13 08:04:12.000000000 -0800
@@ -5,7 +5,7 @@
use warnings::register;
our($VERSION, %declared);
-$VERSION = '1.05';
+$VERSION = '1.08';
#=======================================================================
@@ -28,25 +28,31 @@
sub import {
my $class = shift;
return unless @_; # Ignore 'use constant;'
- my %constants = ();
+ my $constants;
my $multiple = ref $_[0];
+ my $pkg = caller;
+ my $symtab;
+
+ if ($] > 5.009002) {
+ no strict 'refs';
+ $symtab = \%{$pkg . '::'};
+ };
if ( $multiple ) {
if (ref $_[0] ne 'HASH') {
require Carp;
Carp::croak("Invalid reference type '".ref(shift)."' not 'HASH'");
}
- %constants = %{+shift};
+ $constants = shift;
} else {
- $constants{+shift} = undef;
+ $constants->{+shift} = undef;
}
- foreach my $name ( keys %constants ) {
+ foreach my $name ( keys %$constants ) {
unless (defined $name) {
require Carp;
Carp::croak("Can't use undef as constant name");
}
- my $pkg = caller;
# Normal constant name
if ($name =~ /^_?[^\W_0-9]\w*\z/ and !$forbidden{$name}) {
@@ -94,19 +100,24 @@
no strict 'refs';
my $full_name = "${pkg}::$name";
$declared{$full_name}++;
- if ($multiple) {
- my $scalar = $constants{$name};
- *$full_name = sub () { $scalar };
- } else {
- if (@_ == 1) {
- my $scalar = $_[0];
- *$full_name = sub () { $scalar };
- } elsif (@_) {
- my @list = @_;
- *$full_name = sub () { @list };
+ if ($multiple || @_ == 1) {
+ my $scalar = $multiple ? $constants->{$name} : $_[0];
+ if ($symtab && !exists $symtab->{$name}) {
+ # No typeglob yet, so we can use a reference as space-
+ # efficient proxy for a constant subroutine
+ # The check in Perl_ck_rvconst knows that inlinable
+ # constants from cv_const_sv are read only. So we have to:
+ Internals::SvREADONLY($scalar, 1);
+ $symtab->{$name} = \$scalar;
+ Internals::inc_sub_generation;
} else {
- *$full_name = sub () { };
+ *$full_name = sub () { $scalar };
}
+ } elsif (@_) {
+ my @list = @_;
+ *$full_name = sub () { @list };
+ } else {
+ *$full_name = sub () { };
}
}
}
==== //depot/maint-5.8/perl/lib/constant.t#6 (text) ====
Index: perl/lib/constant.t
--- perl/lib/constant.t#5~23593~ 2004-12-01 11:11:22.000000000 -0800
+++ perl/lib/constant.t 2007-02-13 08:04:12.000000000 -0800
@@ -6,7 +6,7 @@
}
use warnings;
-use vars qw{ @warnings };
+use vars qw{ @warnings $fagwoosh $putt $kloong};
BEGIN { # ...and save 'em for later
$SIG{'__WARN__'} = sub { push @warnings, @_ }
}
@@ -14,7 +14,7 @@
use strict;
-use Test::More tests => 81;
+use Test::More tests => 101;
my $TB = Test::More->builder;
BEGIN { use_ok('constant'); }
@@ -252,3 +252,73 @@
};
ok( $@ eq '' );
}
+
+sub slotch ();
+
+{
+ my @warnings;
+ local $SIG{'__WARN__'} = sub { push @warnings, @_ };
+ eval 'use constant slotch => 3; 1' or die $@;
+
+ is ("@warnings", "", "No warnings if a prototype exists");
+
+ my $value = eval 'slotch';
+ is ($@, '');
+ is ($value, 3);
+}
+
+sub zit;
+
+{
+ my @warnings;
+ local $SIG{'__WARN__'} = sub { push @warnings, @_ };
+ eval 'use constant zit => 4; 1' or die $@;
+
+ is(scalar @warnings, 1, "1 warning");
+ like ($warnings[0], qr/^Prototype mismatch: sub main::zit: none vs \(\)/,
+ "about the prototype mismatch");
+
+ my $value = eval 'zit';
+ is ($@, '');
+ is ($value, 4);
+}
+
+$fagwoosh = 'geronimo';
+$putt = 'leutwein';
+$kloong = 'schlozhauer';
+
+{
+ my @warnings;
+ local $SIG{'__WARN__'} = sub { push @warnings, @_ };
+ eval 'use constant fagwoosh => 5; 1' or die $@;
+
+ is ("@warnings", "", "No warnings if the typeglob exists already");
+
+ my $value = eval 'fagwoosh';
+ is ($@, '');
+ is ($value, 5);
+
+ my @value = eval 'fagwoosh';
+ is ($@, '');
+ is_deeply ([EMAIL PROTECTED], [5]);
+
+ eval 'use constant putt => 6, 7; 1' or die $@;
+
+ is ("@warnings", "", "No warnings if the typeglob exists already");
+
+ @value = eval 'putt';
+ is ($@, '');
+ is_deeply ([EMAIL PROTECTED], [6, 7]);
+
+ eval 'use constant "klong"; 1' or die $@;
+
+ is ("@warnings", "", "No warnings if the typeglob exists already");
+
+ $value = eval 'klong';
+ is ($@, '');
+ is ($value, undef);
+
+ @value = eval 'klong';
+ is ($@, '');
+ is_deeply ([EMAIL PROTECTED], []);
+}
==== //depot/maint-5.8/perl/universal.c#62 (text) ====
Index: perl/universal.c
--- perl/universal.c#61~30006~ 2007-01-26 04:19:35.000000000 -0800
+++ perl/universal.c 2007-02-13 08:04:12.000000000 -0800
@@ -188,6 +188,7 @@
XS(XS_Internals_hash_seed);
XS(XS_Internals_rehash_seed);
XS(XS_Internals_HvREHASH);
+XS(XS_Internals_inc_sub_generation);
void
Perl_boot_core_UNIVERSAL(pTHX)
@@ -215,6 +216,8 @@
newXSproto("Internals::hash_seed",XS_Internals_hash_seed, (char *)file,
"");
newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, (char
*)file, "");
newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, (char *)file,
"\\%");
+ newXSproto("Internals::inc_sub_generation",XS_Internals_inc_sub_generation,
+ file, "");
}
@@ -705,6 +708,17 @@
Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
}
+XS(XS_Internals_inc_sub_generation)
+{
+ /* Using dXSARGS would also have dITEM and dSP,
+ * which define 2 unused local variables. */
+ dAXMARK;
+ PERL_UNUSED_ARG(cv);
+ PERL_UNUSED_VAR(mark);
+ ++PL_sub_generation;
+ XSRETURN_EMPTY;
+}
+
/*
* Local variables:
* c-indentation-style: bsd
End of Patch.