From: Shawn M Moore Date: Wed, 3 Dec 2008 02:59:11 +0000 (+0000) Subject: When we memoize methods, get their results lazily to remove some compile-time cost X-Git-Tag: 0.71_01~26 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9ec62360fdfabb90c9ca3d3088ed521990d476bc;p=gitmo%2FClass-MOP.git When we memoize methods, get their results lazily to remove some compile-time cost --- diff --git a/Changes b/Changes index 4897d07..1e772d7 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ Revision history for Perl extension Class-MOP. - Add an "execute" method to invoke the body so we can avoid using the coderef overload (Sartak) * Class::MOP::Immutable + - When we memoize methods, get their results lazily + to remove some compile-time cost (Sartak) - Small speedup from eliminating several method calls (Sartak) diff --git a/lib/Class/MOP/Immutable.pm b/lib/Class/MOP/Immutable.pm index 58e10c1..3037a1a 100644 --- a/lib/Class/MOP/Immutable.pm +++ b/lib/Class/MOP/Immutable.pm @@ -174,16 +174,6 @@ sub make_metaclass_immutable { ($metaclass->can($method_name)) || confess "Could not find the method '$method_name' in " . $metaclass->name; - - if ($type eq 'ARRAY') { - $metaclass->{'___' . $method_name} = [ $metaclass->$method_name ]; - } - elsif ($type eq 'HASH') { - $metaclass->{'___' . $method_name} = { $metaclass->$method_name }; - } - elsif ($type eq 'SCALAR') { - $metaclass->{'___' . $method_name} = $metaclass->$method_name; - } } $metaclass->{'___original_class'} = blessed($metaclass); @@ -267,14 +257,29 @@ sub create_methods_for_immutable_metaclass { my $memoized_methods = $self->options->{memoize}; foreach my $method_name (keys %{$memoized_methods}) { my $type = $memoized_methods->{$method_name}; + my $key = '___' . $method_name; + my $method = $meta->find_method_by_name($method_name); + if ($type eq 'ARRAY') { - $methods{$method_name} = sub { @{$_[0]->{'___' . $method_name}} }; + $methods{$method_name} = sub { + @{$_[0]->{$key}} = $method->execute($_[0]) + if !exists $_[0]->{$key}; + return @{$_[0]->{$key}}; + }; } elsif ($type eq 'HASH') { - $methods{$method_name} = sub { %{$_[0]->{'___' . $method_name}} }; + $methods{$method_name} = sub { + %{$_[0]->{$key}} = $method->execute($_[0]) + if !exists $_[0]->{$key}; + return %{$_[0]->{$key}}; + }; } elsif ($type eq 'SCALAR') { - $methods{$method_name} = sub { $_[0]->{'___' . $method_name} }; + $methods{$method_name} = sub { + $_[0]->{$key} = $method->execute($_[0]) + if !exists $_[0]->{$key}; + return $_[0]->{$key}; + }; } }