Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/Class/C3.pm |
Statements | Executed 62 statements in 1.23ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 209µs | 431µs | BEGIN@12 | Class::C3::
5 | 5 | 5 | 41µs | 56µs | import | Class::C3::
1 | 1 | 1 | 11µs | 13µs | BEGIN@4 | Class::C3::
1 | 1 | 1 | 8µs | 24µs | BEGIN@83 | Class::C3::
1 | 1 | 1 | 6µs | 14µs | BEGIN@218 | Class::C3::
1 | 1 | 1 | 6µs | 20µs | BEGIN@172 | Class::C3::
1 | 1 | 1 | 6µs | 13µs | BEGIN@5 | Class::C3::
1 | 1 | 1 | 6µs | 13µs | BEGIN@222 | Class::C3::
1 | 1 | 1 | 6µs | 18µs | BEGIN@133 | Class::C3::
1 | 1 | 1 | 5µs | 13µs | BEGIN@195 | Class::C3::
1 | 1 | 1 | 5µs | 13µs | BEGIN@208 | Class::C3::
0 | 0 | 0 | 0s | 0s | __ANON__[:210] | Class::C3::
0 | 0 | 0 | 0s | 0s | _apply_method_dispatch_table | Class::C3::
0 | 0 | 0 | 0s | 0s | _apply_method_dispatch_tables | Class::C3::
0 | 0 | 0 | 0s | 0s | _calculate_method_dispatch_table | Class::C3::
0 | 0 | 0 | 0s | 0s | _calculate_method_dispatch_tables | Class::C3::
0 | 0 | 0 | 0s | 0s | _core_calculateMRO | Class::C3::
0 | 0 | 0 | 0s | 0s | _dump_MRO_table | Class::C3::
0 | 0 | 0 | 0s | 0s | _remove_method_dispatch_table | Class::C3::
0 | 0 | 0 | 0s | 0s | _remove_method_dispatch_tables | Class::C3::
0 | 0 | 0 | 0s | 0s | calculateMRO | Class::C3::
0 | 0 | 0 | 0s | 0s | initialize | Class::C3::
0 | 0 | 0 | 0s | 0s | reinitialize | Class::C3::
0 | 0 | 0 | 0s | 0s | uninitialize | Class::C3::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | |||||
2 | package Class::C3; | ||||
3 | |||||
4 | 3 | 16µs | 2 | 16µs | # spent 13µs (11+3) within Class::C3::BEGIN@4 which was called:
# once (11µs+3µs) by main::BEGIN@7 at line 4 # spent 13µs making 1 call to Class::C3::BEGIN@4
# spent 3µs making 1 call to strict::import |
5 | 3 | 127µs | 2 | 20µs | # spent 13µs (6+7) within Class::C3::BEGIN@5 which was called:
# once (6µs+7µs) by main::BEGIN@7 at line 5 # spent 13µs making 1 call to Class::C3::BEGIN@5
# spent 7µs making 1 call to warnings::import |
6 | |||||
7 | 1 | 400ns | our $VERSION = '0.24'; | ||
8 | |||||
9 | 1 | 200ns | our $C3_IN_CORE; | ||
10 | 1 | 0s | our $C3_XS; | ||
11 | |||||
12 | # spent 431µs (209+222) within Class::C3::BEGIN@12 which was called:
# once (209µs+222µs) by main::BEGIN@7 at line 39 | ||||
13 | 1 | 7µs | if($] > 5.009_004) { | ||
14 | 1 | 300ns | $C3_IN_CORE = 1; | ||
15 | 1 | 62µs | require mro; | ||
16 | } | ||||
17 | elsif($C3_XS or not defined $C3_XS) { | ||||
18 | my $error = do { | ||||
19 | local $@; | ||||
20 | eval { require Class::C3::XS }; | ||||
21 | $@; | ||||
22 | }; | ||||
23 | |||||
24 | if ($error) { | ||||
25 | die $error if $error !~ /\blocate\b/; | ||||
26 | |||||
27 | if ($C3_XS) { | ||||
28 | require Carp; | ||||
29 | Carp::croak( "XS explicitly requested but Class::C3::XS is not available" ); | ||||
30 | } | ||||
31 | |||||
32 | require Algorithm::C3; | ||||
33 | require Class::C3::next; | ||||
34 | } | ||||
35 | else { | ||||
36 | $C3_XS = 1; | ||||
37 | } | ||||
38 | } | ||||
39 | 1 | 103µs | 1 | 431µs | } # spent 431µs making 1 call to Class::C3::BEGIN@12 |
40 | |||||
41 | # this is our global stash of both | ||||
42 | # MRO's and method dispatch tables | ||||
43 | # the structure basically looks like | ||||
44 | # this: | ||||
45 | # | ||||
46 | # $MRO{$class} = { | ||||
47 | # MRO => [ <class precendence list> ], | ||||
48 | # methods => { | ||||
49 | # orig => <original location of method>, | ||||
50 | # code => \&<ref to original method> | ||||
51 | # }, | ||||
52 | # has_overload_fallback => (1 | 0) | ||||
53 | # } | ||||
54 | # | ||||
55 | 1 | 200ns | our %MRO; | ||
56 | |||||
57 | # use these for debugging ... | ||||
58 | sub _dump_MRO_table { %MRO } | ||||
59 | 1 | 200ns | our $TURN_OFF_C3 = 0; | ||
60 | |||||
61 | # state tracking for initialize()/uninitialize() | ||||
62 | 1 | 300ns | our $_initialized = 0; | ||
63 | |||||
64 | # spent 56µs (41+15) within Class::C3::import which was called 5 times, avg 11µs/call:
# once (12µs+6µs) by Tapper::Model::BEGIN@21 at line 21 of Tapper/Model.pm
# once (11µs+4µs) by Tapper::Schema::TestTools::BEGIN@15 at line 15 of Tapper/Schema/TestTools.pm
# once (11µs+3µs) by Tapper::Schema::ReportsDB::BEGIN@21 at line 21 of Tapper/Schema/ReportsDB.pm
# once (5µs+2µs) by Tapper::Schema::TestrunDB::BEGIN@20 at line 20 of Tapper/Schema/TestrunDB.pm
# once (2µs+0s) by main::BEGIN@7 at line 7 of xt/tapper-mcp-scheduler-with-db-longrun.t | ||||
65 | 5 | 7µs | my $class = caller(); | ||
66 | # skip if the caller is main:: | ||||
67 | # since that is clearly not relevant | ||||
68 | 5 | 6µs | return if $class eq 'main'; | ||
69 | |||||
70 | 4 | 2µs | return if $TURN_OFF_C3; | ||
71 | 4 | 31µs | 4 | 15µs | mro::set_mro($class, 'c3') if $C3_IN_CORE; # spent 15µs making 4 calls to mro::set_mro, avg 4µs/call |
72 | |||||
73 | # make a note to calculate $class | ||||
74 | # during INIT phase | ||||
75 | 4 | 21µs | $MRO{$class} = undef unless exists $MRO{$class}; | ||
76 | } | ||||
77 | |||||
78 | ## initializers | ||||
79 | |||||
80 | # This prevents silly warnings when Class::C3 is | ||||
81 | # used explicitly along with MRO::Compat under 5.9.5+ | ||||
82 | |||||
83 | 4 | 220µs | 2 | 40µs | # spent 24µs (8+16) within Class::C3::BEGIN@83 which was called:
# once (8µs+16µs) by main::BEGIN@7 at line 83 # spent 24µs making 1 call to Class::C3::BEGIN@83
# spent 16µs making 1 call to warnings::unimport |
84 | |||||
85 | sub initialize { | ||||
86 | %next::METHOD_CACHE = (); | ||||
87 | # why bother if we don't have anything ... | ||||
88 | return unless keys %MRO; | ||||
89 | if($C3_IN_CORE) { | ||||
90 | mro::set_mro($_, 'c3') for keys %MRO; | ||||
91 | } | ||||
92 | else { | ||||
93 | if($_initialized) { | ||||
94 | uninitialize(); | ||||
95 | $MRO{$_} = undef foreach keys %MRO; | ||||
96 | } | ||||
97 | _calculate_method_dispatch_tables(); | ||||
98 | _apply_method_dispatch_tables(); | ||||
99 | $_initialized = 1; | ||||
100 | } | ||||
101 | } | ||||
102 | |||||
103 | sub uninitialize { | ||||
104 | # why bother if we don't have anything ... | ||||
105 | %next::METHOD_CACHE = (); | ||||
106 | return unless keys %MRO; | ||||
107 | if($C3_IN_CORE) { | ||||
108 | mro::set_mro($_, 'dfs') for keys %MRO; | ||||
109 | } | ||||
110 | else { | ||||
111 | _remove_method_dispatch_tables(); | ||||
112 | $_initialized = 0; | ||||
113 | } | ||||
114 | } | ||||
115 | |||||
116 | sub reinitialize { goto &initialize } | ||||
117 | |||||
118 | } # end of "no warnings 'redefine'" | ||||
119 | |||||
120 | ## functions for applying C3 to classes | ||||
121 | |||||
122 | sub _calculate_method_dispatch_tables { | ||||
123 | return if $C3_IN_CORE; | ||||
124 | my %merge_cache; | ||||
125 | foreach my $class (keys %MRO) { | ||||
126 | _calculate_method_dispatch_table($class, \%merge_cache); | ||||
127 | } | ||||
128 | } | ||||
129 | |||||
130 | sub _calculate_method_dispatch_table { | ||||
131 | return if $C3_IN_CORE; | ||||
132 | my ($class, $merge_cache) = @_; | ||||
133 | 3 | 210µs | 2 | 31µs | # spent 18µs (6+13) within Class::C3::BEGIN@133 which was called:
# once (6µs+13µs) by main::BEGIN@7 at line 133 # spent 18µs making 1 call to Class::C3::BEGIN@133
# spent 13µs making 1 call to strict::unimport |
134 | my @MRO = calculateMRO($class, $merge_cache); | ||||
135 | $MRO{$class} = { MRO => \@MRO }; | ||||
136 | my $has_overload_fallback; | ||||
137 | my %methods; | ||||
138 | # NOTE: | ||||
139 | # we do @MRO[1 .. $#MRO] here because it | ||||
140 | # makes no sense to interogate the class | ||||
141 | # which you are calculating for. | ||||
142 | foreach my $local (@MRO[1 .. $#MRO]) { | ||||
143 | # if overload has tagged this module to | ||||
144 | # have use "fallback", then we want to | ||||
145 | # grab that value | ||||
146 | $has_overload_fallback = ${"${local}::()"} | ||||
147 | if !defined $has_overload_fallback && defined ${"${local}::()"}; | ||||
148 | foreach my $method (grep { defined &{"${local}::$_"} } keys %{"${local}::"}) { | ||||
149 | # skip if already overriden in local class | ||||
150 | next unless !defined *{"${class}::$method"}{CODE}; | ||||
151 | $methods{$method} = { | ||||
152 | orig => "${local}::$method", | ||||
153 | code => \&{"${local}::$method"} | ||||
154 | } unless exists $methods{$method}; | ||||
155 | } | ||||
156 | } | ||||
157 | # now stash them in our %MRO table | ||||
158 | $MRO{$class}->{methods} = \%methods; | ||||
159 | $MRO{$class}->{has_overload_fallback} = $has_overload_fallback; | ||||
160 | } | ||||
161 | |||||
162 | sub _apply_method_dispatch_tables { | ||||
163 | return if $C3_IN_CORE; | ||||
164 | foreach my $class (keys %MRO) { | ||||
165 | _apply_method_dispatch_table($class); | ||||
166 | } | ||||
167 | } | ||||
168 | |||||
169 | sub _apply_method_dispatch_table { | ||||
170 | return if $C3_IN_CORE; | ||||
171 | my $class = shift; | ||||
172 | 3 | 161µs | 2 | 34µs | # spent 20µs (6+14) within Class::C3::BEGIN@172 which was called:
# once (6µs+14µs) by main::BEGIN@7 at line 172 # spent 20µs making 1 call to Class::C3::BEGIN@172
# spent 14µs making 1 call to strict::unimport |
173 | ${"${class}::()"} = $MRO{$class}->{has_overload_fallback} | ||||
174 | if !defined &{"${class}::()"} | ||||
175 | && defined $MRO{$class}->{has_overload_fallback}; | ||||
176 | foreach my $method (keys %{$MRO{$class}->{methods}}) { | ||||
177 | if ( $method =~ /^\(/ ) { | ||||
178 | my $orig = $MRO{$class}->{methods}->{$method}->{orig}; | ||||
179 | ${"${class}::$method"} = $$orig if defined $$orig; | ||||
180 | } | ||||
181 | *{"${class}::$method"} = $MRO{$class}->{methods}->{$method}->{code}; | ||||
182 | } | ||||
183 | } | ||||
184 | |||||
185 | sub _remove_method_dispatch_tables { | ||||
186 | return if $C3_IN_CORE; | ||||
187 | foreach my $class (keys %MRO) { | ||||
188 | _remove_method_dispatch_table($class); | ||||
189 | } | ||||
190 | } | ||||
191 | |||||
192 | sub _remove_method_dispatch_table { | ||||
193 | return if $C3_IN_CORE; | ||||
194 | my $class = shift; | ||||
195 | 3 | 103µs | 2 | 21µs | # spent 13µs (5+8) within Class::C3::BEGIN@195 which was called:
# once (5µs+8µs) by main::BEGIN@7 at line 195 # spent 13µs making 1 call to Class::C3::BEGIN@195
# spent 8µs making 1 call to strict::unimport |
196 | delete ${"${class}::"}{"()"} if $MRO{$class}->{has_overload_fallback}; | ||||
197 | foreach my $method (keys %{$MRO{$class}->{methods}}) { | ||||
198 | delete ${"${class}::"}{$method} | ||||
199 | if defined *{"${class}::${method}"}{CODE} && | ||||
200 | (*{"${class}::${method}"}{CODE} eq $MRO{$class}->{methods}->{$method}->{code}); | ||||
201 | } | ||||
202 | } | ||||
203 | |||||
204 | sub calculateMRO { | ||||
205 | my ($class, $merge_cache) = @_; | ||||
206 | |||||
207 | return Algorithm::C3::merge($class, sub { | ||||
208 | 3 | 63µs | 2 | 20µs | # spent 13µs (5+8) within Class::C3::BEGIN@208 which was called:
# once (5µs+8µs) by main::BEGIN@7 at line 208 # spent 13µs making 1 call to Class::C3::BEGIN@208
# spent 7µs making 1 call to strict::unimport |
209 | @{$_[0] . '::ISA'}; | ||||
210 | }, $merge_cache); | ||||
211 | } | ||||
212 | |||||
213 | # Method overrides to support 5.9.5+ or Class::C3::XS | ||||
214 | |||||
215 | sub _core_calculateMRO { @{mro::get_linear_isa($_[0], 'c3')} } | ||||
216 | |||||
217 | 1 | 300ns | if($C3_IN_CORE) { | ||
218 | 3 | 30µs | 2 | 21µs | # spent 14µs (6+8) within Class::C3::BEGIN@218 which was called:
# once (6µs+8µs) by main::BEGIN@7 at line 218 # spent 14µs making 1 call to Class::C3::BEGIN@218
# spent 8µs making 1 call to warnings::unimport |
219 | 1 | 7µs | *Class::C3::calculateMRO = \&_core_calculateMRO; | ||
220 | } | ||||
221 | elsif($C3_XS) { | ||||
222 | 3 | 44µs | 2 | 20µs | # spent 13µs (6+7) within Class::C3::BEGIN@222 which was called:
# once (6µs+7µs) by main::BEGIN@7 at line 222 # spent 13µs making 1 call to Class::C3::BEGIN@222
# spent 7µs making 1 call to warnings::unimport |
223 | *Class::C3::calculateMRO = \&Class::C3::XS::calculateMRO; | ||||
224 | *Class::C3::_calculate_method_dispatch_table | ||||
225 | = \&Class::C3::XS::_calculate_method_dispatch_table; | ||||
226 | } | ||||
227 | |||||
228 | 1 | 7µs | 1; | ||
229 | |||||
230 | __END__ |