Filename | /Users/edenc/perl5/lib/perl5/KiokuDB/TypeMap/Entry/Closure.pm |
Statements | Executed 15 statements in 1.03ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 18µs | 4.31ms | BEGIN@2 | KiokuDB::TypeMap::Entry::Closure::
1 | 1 | 1 | 11µs | 46µs | BEGIN@4 | KiokuDB::TypeMap::Entry::Closure::
1 | 1 | 1 | 10µs | 25µs | BEGIN@122 | KiokuDB::TypeMap::Entry::Closure::
1 | 1 | 1 | 10µs | 305µs | BEGIN@9 | KiokuDB::TypeMap::Entry::Closure::
1 | 1 | 1 | 8µs | 30µs | BEGIN@5 | KiokuDB::TypeMap::Entry::Closure::
1 | 1 | 1 | 8µs | 23µs | BEGIN@7 | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | __ANON__[:142] | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | __ANON__[:150] | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | __ANON__[:172] | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | __ANON__[:90] | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | _deparse | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | _eval_body | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | compile_collapse_body | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | compile_expand | KiokuDB::TypeMap::Entry::Closure::
0 | 0 | 0 | 0s | 0s | compile_refresh | KiokuDB::TypeMap::Entry::Closure::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package KiokuDB::TypeMap::Entry::Closure; | ||||
2 | 2 | 49µs | 2 | 8.60ms | # spent 4.31ms (18µs+4.29) within KiokuDB::TypeMap::Entry::Closure::BEGIN@2 which was called:
# once (18µs+4.29ms) by Module::Runtime::require_module at line 2 # spent 4.31ms making 1 call to KiokuDB::TypeMap::Entry::Closure::BEGIN@2
# spent 4.29ms making 1 call to Moose::Exporter::__ANON__[Moose/Exporter.pm:492] |
3 | |||||
4 | 2 | 29µs | 2 | 80µs | # spent 46µs (11+34) within KiokuDB::TypeMap::Entry::Closure::BEGIN@4 which was called:
# once (11µs+34µs) by Module::Runtime::require_module at line 4 # spent 46µs making 1 call to KiokuDB::TypeMap::Entry::Closure::BEGIN@4
# spent 34µs making 1 call to Exporter::import |
5 | 2 | 27µs | 2 | 51µs | # spent 30µs (8+21) within KiokuDB::TypeMap::Entry::Closure::BEGIN@5 which was called:
# once (8µs+21µs) by Module::Runtime::require_module at line 5 # spent 30µs making 1 call to KiokuDB::TypeMap::Entry::Closure::BEGIN@5
# spent 21µs making 1 call to Exporter::import |
6 | |||||
7 | 2 | 29µs | 2 | 38µs | # spent 23µs (8+15) within KiokuDB::TypeMap::Entry::Closure::BEGIN@7 which was called:
# once (8µs+15µs) by Module::Runtime::require_module at line 7 # spent 23µs making 1 call to KiokuDB::TypeMap::Entry::Closure::BEGIN@7
# spent 15µs making 1 call to warnings::unimport |
8 | |||||
9 | 2 | 535µs | 2 | 600µs | # spent 305µs (10+295) within KiokuDB::TypeMap::Entry::Closure::BEGIN@9 which was called:
# once (10µs+295µs) by Module::Runtime::require_module at line 9 # spent 305µs making 1 call to KiokuDB::TypeMap::Entry::Closure::BEGIN@9
# spent 295µs making 1 call to namespace::clean::import |
10 | |||||
11 | 1 | 3µs | 1 | 4.56ms | with qw(KiokuDB::TypeMap::Entry::Std); # spent 4.56ms making 1 call to Moose::with |
12 | |||||
13 | sub compile_collapse_body { | ||||
14 | my $self = shift; | ||||
15 | |||||
16 | require B; | ||||
17 | require B::Deparse; | ||||
18 | require PadWalker; | ||||
19 | |||||
20 | return sub { | ||||
21 | my ( $collapser, %args ) = @_; | ||||
22 | |||||
23 | my $sub = $args{object}; | ||||
24 | |||||
25 | my ( $pkg, $name ) = Class::MOP::get_code_info($sub); | ||||
26 | |||||
27 | my %data; | ||||
28 | |||||
29 | # FIXME make this customizable on a per sub and per typemap level | ||||
30 | if ( $name eq '__ANON__' ) { | ||||
31 | my $pad = PadWalker::closed_over($sub); | ||||
32 | |||||
33 | if ( keys %$pad ) { | ||||
34 | my $collapsed_pad = $collapser->visit($pad); | ||||
35 | |||||
36 | $data{pad} = $collapsed_pad; | ||||
37 | |||||
38 | my $buffer = $collapser->_buffer; | ||||
39 | my $pad_entry_data = blessed $collapsed_pad ? $buffer->id_to_entry( $collapsed_pad->id )->data : $collapsed_pad; | ||||
40 | |||||
41 | $buffer->first_class->insert(map { $_->id } values %$pad_entry_data ); # maybe only if entry($_->id)->object's refcount is > 1 (only shared closure vars) ? | ||||
42 | } | ||||
43 | |||||
44 | # FIXME find all GVs in the optree and insert refs to them? | ||||
45 | # i suppose they should be handled like named... | ||||
46 | $data{body} = $self->_deparse($sub); | ||||
47 | } else { | ||||
48 | ( my $pkg_file = "${pkg}.pm" ) =~ s{::}{/}g; | ||||
49 | |||||
50 | my $file; | ||||
51 | |||||
52 | if ( my $meta = Class::MOP::get_metaclass_by_name($pkg) ) { | ||||
53 | if ( my $method = $meta->get_method($name) ) { | ||||
54 | if ( refaddr($method->body) == refaddr($sub) | ||||
55 | and | ||||
56 | $method->isa("Class::MOP::Method::Generated") | ||||
57 | and | ||||
58 | $method->can("definition_context") | ||||
59 | ) { | ||||
60 | $file = $method->definition_context->{file}; | ||||
61 | } | ||||
62 | } | ||||
63 | } | ||||
64 | |||||
65 | unless ( defined $file ) { | ||||
66 | my $cv = B::svref_2object($sub); | ||||
67 | $file = $cv->FILE unless $cv->XSUB; # Can't really tell who called newXS or even bootstrap, so we assume the package .pm did | ||||
68 | } | ||||
69 | |||||
70 | my $inc_key; | ||||
71 | |||||
72 | if ( defined $file ) { | ||||
73 | my %rev_inc = reverse %INC; | ||||
74 | $inc_key = $rev_inc{$file}; | ||||
75 | $inc_key = $file unless defined $inc_key; | ||||
76 | } | ||||
77 | |||||
78 | if ( defined($inc_key) and $pkg_file ne $inc_key ) { | ||||
79 | $data{file} = $inc_key; | ||||
80 | } | ||||
81 | |||||
82 | @data{qw(package name)} = ( $pkg, $name ); | ||||
83 | } | ||||
84 | |||||
85 | return $collapser->make_entry( | ||||
86 | %args, | ||||
87 | object => $sub, | ||||
88 | data => \%data, | ||||
89 | ); | ||||
90 | }; | ||||
91 | } | ||||
92 | |||||
93 | sub _deparse { | ||||
94 | my ( $self, $cv ) = @_; | ||||
95 | |||||
96 | B::Deparse->new->coderef2text($cv); | ||||
97 | } | ||||
98 | |||||
99 | sub compile_expand { | ||||
100 | my $self = shift; | ||||
101 | |||||
102 | require PadWalker; | ||||
103 | |||||
104 | return sub { | ||||
105 | my ( $linker, $entry ) = @_; | ||||
106 | |||||
107 | my $data = $entry->data; | ||||
108 | |||||
109 | if ( exists $data->{body} ) { | ||||
110 | my ( $body, $pad ) = @{ $data }{qw(body pad)}; | ||||
111 | |||||
112 | my $inflated_pad; | ||||
113 | $linker->inflate_data( $pad, \$inflated_pad ); | ||||
114 | |||||
115 | my $sub = $self->_eval_body( $linker, $body, $inflated_pad ); | ||||
116 | |||||
117 | $linker->register_object( $entry => $sub ); | ||||
118 | |||||
119 | return $sub; | ||||
120 | } else { | ||||
121 | my $fq = join("::", @{ $data }{qw(package name)}); | ||||
122 | 2 | 334µs | 2 | 40µs | # spent 25µs (10+15) within KiokuDB::TypeMap::Entry::Closure::BEGIN@122 which was called:
# once (10µs+15µs) by Module::Runtime::require_module at line 122 # spent 25µs making 1 call to KiokuDB::TypeMap::Entry::Closure::BEGIN@122
# spent 15µs making 1 call to strict::unimport |
123 | |||||
124 | unless ( defined(*{$glob}{CODE}) ) { | ||||
125 | if ( defined(my $file = $data->{file}) ) { | ||||
126 | require $file unless exists $INC{$file}; | ||||
127 | } else { | ||||
128 | Class::MOP::load_class($data->{package}); | ||||
129 | } | ||||
130 | |||||
131 | unless ( defined(*{$glob}{CODE}) ) { | ||||
132 | croak "The subroutine &$data->{name} is no longer defined, but is referred to in the database"; | ||||
133 | } | ||||
134 | } | ||||
135 | |||||
136 | my $sub = *{$glob}{CODE}; | ||||
137 | |||||
138 | $linker->register_object( $entry => $sub ); | ||||
139 | |||||
140 | return $sub; | ||||
141 | } | ||||
142 | }; | ||||
143 | } | ||||
144 | |||||
145 | sub compile_refresh { | ||||
146 | my $self = shift; | ||||
147 | |||||
148 | return sub { | ||||
149 | croak "refreshing of closures is not yet supported"; | ||||
150 | }; | ||||
151 | } | ||||
152 | |||||
153 | sub _eval_body { | ||||
154 | my ( $self, $linker, $body, $pad ) = @_; | ||||
155 | |||||
156 | my ( $sub, $e ) = do { | ||||
157 | local $@; | ||||
158 | |||||
159 | if ( my @vars = keys %$pad ) { | ||||
160 | my $vars = join ", ", @vars; | ||||
161 | |||||
162 | # FIXME Parse::Perl | ||||
163 | my $sub = eval " | ||||
164 | my ( $vars ); | ||||
165 | sub $body; | ||||
166 | "; | ||||
167 | |||||
168 | my $e = $@; | ||||
169 | |||||
170 | $linker->queue_finalizer(sub { | ||||
171 | PadWalker::set_closed_over($sub, $pad); | ||||
172 | }) if $sub; | ||||
173 | |||||
174 | ( $sub, $e ); | ||||
175 | } else { | ||||
176 | eval "sub $body", $@; | ||||
177 | } | ||||
178 | }; | ||||
179 | |||||
180 | die $e unless $sub; | ||||
181 | |||||
182 | return $sub; | ||||
183 | } | ||||
184 | |||||
185 | |||||
186 | 1 | 4µs | 2 | 2.87ms | __PACKAGE__->meta->make_immutable; # spent 2.85ms making 1 call to Class::MOP::Class::make_immutable
# spent 15µs making 1 call to KiokuDB::TypeMap::Entry::Closure::meta |
187 | |||||
188 | 1 | 10µs | __PACKAGE__ | ||
189 | |||||
190 | 1 | 10µs | 1 | 995µs | __END__ # spent 995µs making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26] |