Filename | /opt/perl-5.18.1/lib/site_perl/5.18.1/Moo/HandleMoose.pm |
Statements | Executed 51 statements in 2.20ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
3 | 1 | 1 | 307µs | 2.89ms | inject_fake_metaclass_for | Moo::HandleMoose::
1 | 1 | 1 | 27µs | 84µs | BEGIN@3 | Moo::HandleMoose::
1 | 1 | 1 | 20µs | 20µs | inject_all | Moo::HandleMoose::
1 | 1 | 1 | 12µs | 24µs | BEGIN@202 | Moo::HandleMoose::
1 | 1 | 1 | 12µs | 79µs | BEGIN@4 | Moo::HandleMoose::
1 | 1 | 1 | 11µs | 22µs | BEGIN@16 | Moo::HandleMoose::
1 | 1 | 1 | 9µs | 36µs | BEGIN@5 | Moo::HandleMoose::
1 | 1 | 1 | 9µs | 28µs | import | Moo::HandleMoose::
2 | 1 | 1 | 5µs | 5µs | maybe_reinject_fake_metaclass_for | Moo::HandleMoose::
0 | 0 | 0 | 0s | 0s | _uninlined_body | Moo::HandleMoose::FakeConstructor::
0 | 0 | 0 | 0s | 0s | __ANON__[:131] | Moo::HandleMoose::
0 | 0 | 0 | 0s | 0s | __ANON__[:143] | Moo::HandleMoose::
0 | 0 | 0 | 0s | 0s | __ANON__[:146] | Moo::HandleMoose::
0 | 0 | 0 | 0s | 0s | inject_real_metaclass_for | Moo::HandleMoose::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Moo::HandleMoose; | ||||
2 | |||||
3 | 3 | 40µs | 3 | 142µs | # spent 84µs (27+57) within Moo::HandleMoose::BEGIN@3 which was called:
# once (27µs+57µs) by Foo::Moo::BEGIN@116 at line 3 # spent 84µs making 1 call to Moo::HandleMoose::BEGIN@3
# spent 41µs making 1 call to strictures::import
# spent 16µs making 1 call to strictures::VERSION |
4 | 2 | 35µs | 2 | 147µs | # spent 79µs (12+68) within Moo::HandleMoose::BEGIN@4 which was called:
# once (12µs+68µs) by Foo::Moo::BEGIN@116 at line 4 # spent 79µs making 1 call to Moo::HandleMoose::BEGIN@4
# spent 68µs making 1 call to Exporter::import |
5 | 2 | 125µs | 2 | 62µs | # spent 36µs (9+27) within Moo::HandleMoose::BEGIN@5 which was called:
# once (9µs+27µs) by Foo::Moo::BEGIN@116 at line 5 # spent 36µs making 1 call to Moo::HandleMoose::BEGIN@5
# spent 27µs making 1 call to Exporter::import |
6 | |||||
7 | 1 | 200ns | our %TYPE_MAP; | ||
8 | |||||
9 | 1 | 100ns | our $SETUP_DONE; | ||
10 | |||||
11 | 3 | 5µs | 1 | 20µs | # spent 28µs (9+20) within Moo::HandleMoose::import which was called:
# once (9µs+20µs) by Foo::Moo::BEGIN@116 at line 17 of Moo/sification.pm # spent 20µs making 1 call to Moo::HandleMoose::inject_all |
12 | |||||
13 | # spent 20µs within Moo::HandleMoose::inject_all which was called:
# once (20µs+0s) by Moo::HandleMoose::import at line 11 | ||||
14 | 1 | 500ns | require Class::MOP; | ||
15 | inject_fake_metaclass_for($_) | ||||
16 | 4 | 1.50ms | 2 | 34µs | # spent 22µs (11+11) within Moo::HandleMoose::BEGIN@16 which was called:
# once (11µs+11µs) by Foo::Moo::BEGIN@116 at line 16 # spent 22µs making 1 call to Moo::HandleMoose::BEGIN@16
# spent 12µs making 1 call to warnings::unimport |
17 | 1 | 1µs | inject_fake_metaclass_for($_) for keys %Moo::Role::INFO; | ||
18 | 1 | 300ns | require Moose::Meta::Method::Constructor; | ||
19 | 1 | 20µs | @Moo::HandleMoose::FakeConstructor::ISA = 'Moose::Meta::Method::Constructor'; | ||
20 | } | ||||
21 | |||||
22 | # spent 5µs within Moo::HandleMoose::maybe_reinject_fake_metaclass_for which was called 2 times, avg 2µs/call:
# 2 times (5µs+0s) by Moo::_maybe_reset_handlemoose at line 113 of Moo.pm, avg 2µs/call | ||||
23 | 2 | 600ns | my ($name) = @_; | ||
24 | 2 | 400ns | our %DID_INJECT; | ||
25 | 2 | 7µs | if (delete $DID_INJECT{$name}) { | ||
26 | unless ($Moo::Role::INFO{$name}) { | ||||
27 | Moo->_constructor_maker_for($name)->install_delayed; | ||||
28 | } | ||||
29 | inject_fake_metaclass_for($name); | ||||
30 | } | ||||
31 | } | ||||
32 | |||||
33 | # spent 2.89ms (307µs+2.58) within Moo::HandleMoose::inject_fake_metaclass_for which was called 3 times, avg 964µs/call:
# 3 times (307µs+2.58ms) by Moo::import at line 75 of Moo.pm, avg 964µs/call | ||||
34 | 3 | 1µs | my ($name) = @_; | ||
35 | 3 | 1µs | require Class::MOP; | ||
36 | 3 | 260µs | require Moo::HandleMoose::FakeMetaClass; | ||
37 | 3 | 12µs | 3 | 7µs | Class::MOP::store_metaclass_by_name( # spent 7µs making 3 calls to Class::MOP::store_metaclass_by_name, avg 2µs/call |
38 | $name, bless({ name => $name }, 'Moo::HandleMoose::FakeMetaClass') | ||||
39 | ); | ||||
40 | 3 | 2µs | require Moose::Util::TypeConstraints; | ||
41 | 3 | 10µs | if ($Moo::Role::INFO{$name}) { | ||
42 | Moose::Util::TypeConstraints::find_or_create_does_type_constraint($name); | ||||
43 | } else { | ||||
44 | 3 | 6µs | 3 | 2.58ms | Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($name); # spent 2.58ms making 3 calls to Moose::Util::TypeConstraints::find_or_create_isa_type_constraint, avg 859µs/call |
45 | } | ||||
46 | } | ||||
47 | |||||
48 | { | ||||
49 | 1 | 500ns | package Moo::HandleMoose::FakeConstructor; | ||
50 | |||||
51 | sub _uninlined_body { \&Moose::Object::new } | ||||
52 | } | ||||
53 | |||||
54 | |||||
55 | sub inject_real_metaclass_for { | ||||
56 | my ($name) = @_; | ||||
57 | our %DID_INJECT; | ||||
58 | return Class::MOP::get_metaclass_by_name($name) if $DID_INJECT{$name}; | ||||
59 | require Moose; require Moo; require Moo::Role; require Scalar::Util; | ||||
60 | Class::MOP::remove_metaclass_by_name($name); | ||||
61 | my ($am_role, $meta, $attr_specs, $attr_order) = do { | ||||
62 | if (my $info = $Moo::Role::INFO{$name}) { | ||||
63 | my @attr_info = @{$info->{attributes}||[]}; | ||||
64 | (1, Moose::Meta::Role->initialize($name), | ||||
65 | { @attr_info }, | ||||
66 | [ @attr_info[grep !($_ % 2), 0..$#attr_info] ] | ||||
67 | ) | ||||
68 | } elsif ( my $cmaker = Moo->_constructor_maker_for($name) ) { | ||||
69 | my $specs = $cmaker->all_attribute_specs; | ||||
70 | (0, Moose::Meta::Class->initialize($name), $specs, | ||||
71 | [ sort { $specs->{$a}{index} <=> $specs->{$b}{index} } keys %$specs ] | ||||
72 | ); | ||||
73 | } else { | ||||
74 | # This codepath is used if $name does not exist in $Moo::MAKERS | ||||
75 | (0, Moose::Meta::Class->initialize($name), {}, [] ) | ||||
76 | } | ||||
77 | }; | ||||
78 | |||||
79 | for my $spec (values %$attr_specs) { | ||||
80 | if (my $inflators = delete $spec->{moosify}) { | ||||
81 | $_->($spec) for @$inflators; | ||||
82 | } | ||||
83 | } | ||||
84 | |||||
85 | my %methods = %{Role::Tiny->_concrete_methods_of($name)}; | ||||
86 | |||||
87 | # if stuff gets added afterwards, _maybe_reset_handlemoose should | ||||
88 | # trigger the recreation of the metaclass but we need to ensure the | ||||
89 | # Role::Tiny cache is cleared so we don't confuse Moo itself. | ||||
90 | if (my $info = $Role::Tiny::INFO{$name}) { | ||||
91 | delete $info->{methods}; | ||||
92 | } | ||||
93 | |||||
94 | # needed to ensure the method body is stable and get things named | ||||
95 | Sub::Defer::undefer_sub($_) for grep defined, values %methods; | ||||
96 | my @attrs; | ||||
97 | { | ||||
98 | # This local is completely not required for roles but harmless | ||||
99 | local @{_getstash($name)}{keys %methods}; | ||||
100 | my %seen_name; | ||||
101 | foreach my $name (@$attr_order) { | ||||
102 | $seen_name{$name} = 1; | ||||
103 | my %spec = %{$attr_specs->{$name}}; | ||||
104 | my %spec_map = ( | ||||
105 | map { $_->name => $_->init_arg||$_->name } | ||||
106 | ( | ||||
107 | (grep { $_->has_init_arg } | ||||
108 | $meta->attribute_metaclass->meta->get_all_attributes), | ||||
109 | grep { exists($_->{init_arg}) ? defined($_->init_arg) : 1 } | ||||
110 | map { | ||||
111 | my $meta = Moose::Util::resolve_metatrait_alias('Attribute', $_) | ||||
112 | ->meta; | ||||
113 | map $meta->get_attribute($_), $meta->get_attribute_list | ||||
114 | } @{$spec{traits}||[]} | ||||
115 | ) | ||||
116 | ); | ||||
117 | # have to hard code this because Moose's role meta-model is lacking | ||||
118 | $spec_map{traits} ||= 'traits'; | ||||
119 | |||||
120 | $spec{is} = 'ro' if $spec{is} eq 'lazy' or $spec{is} eq 'rwp'; | ||||
121 | my $coerce = $spec{coerce}; | ||||
122 | if (my $isa = $spec{isa}) { | ||||
123 | my $tc = $spec{isa} = do { | ||||
124 | if (my $mapped = $TYPE_MAP{$isa}) { | ||||
125 | my $type = $mapped->(); | ||||
126 | Scalar::Util::blessed($type) && $type->isa("Moose::Meta::TypeConstraint") | ||||
127 | or die "error inflating attribute '$name' for package '$_[0]': \$TYPE_MAP{$isa} did not return a valid type constraint'"; | ||||
128 | $coerce ? $type->create_child_type(name => $type->name) : $type; | ||||
129 | } else { | ||||
130 | Moose::Meta::TypeConstraint->new( | ||||
131 | constraint => sub { eval { &$isa; 1 } } | ||||
132 | ); | ||||
133 | } | ||||
134 | }; | ||||
135 | if ($coerce) { | ||||
136 | $tc->coercion(Moose::Meta::TypeCoercion->new) | ||||
137 | ->_compiled_type_coercion($coerce); | ||||
138 | $spec{coerce} = 1; | ||||
139 | } | ||||
140 | } elsif ($coerce) { | ||||
141 | my $attr = perlstring($name); | ||||
142 | my $tc = Moose::Meta::TypeConstraint->new( | ||||
143 | constraint => sub { die "This is not going to work" }, | ||||
144 | inlined => sub { | ||||
145 | 'my $r = $_[42]{'.$attr.'}; $_[42]{'.$attr.'} = 1; $r' | ||||
146 | }, | ||||
147 | ); | ||||
148 | $tc->coercion(Moose::Meta::TypeCoercion->new) | ||||
149 | ->_compiled_type_coercion($coerce); | ||||
150 | $spec{isa} = $tc; | ||||
151 | $spec{coerce} = 1; | ||||
152 | } | ||||
153 | %spec = | ||||
154 | map { $spec_map{$_} => $spec{$_} } | ||||
155 | grep { exists $spec_map{$_} } | ||||
156 | keys %spec; | ||||
157 | push @attrs, $meta->add_attribute($name => %spec); | ||||
158 | } | ||||
159 | foreach my $mouse (do { our %MOUSE; @{$MOUSE{$name}||[]} }) { | ||||
160 | foreach my $attr ($mouse->get_all_attributes) { | ||||
161 | my %spec = %{$attr}; | ||||
162 | delete @spec{qw( | ||||
163 | associated_class associated_methods __METACLASS__ | ||||
164 | provides curries | ||||
165 | )}; | ||||
166 | my $name = delete $spec{name}; | ||||
167 | next if $seen_name{$name}++; | ||||
168 | push @attrs, $meta->add_attribute($name => %spec); | ||||
169 | } | ||||
170 | } | ||||
171 | } | ||||
172 | for my $meth_name (keys %methods) { | ||||
173 | my $meth_code = $methods{$meth_name}; | ||||
174 | $meta->add_method($meth_name, $meth_code) if $meth_code; | ||||
175 | } | ||||
176 | |||||
177 | if ($am_role) { | ||||
178 | my $info = $Moo::Role::INFO{$name}; | ||||
179 | $meta->add_required_methods(@{$info->{requires}}); | ||||
180 | foreach my $modifier (@{$info->{modifiers}}) { | ||||
181 | my ($type, @args) = @$modifier; | ||||
182 | my $code = pop @args; | ||||
183 | $meta->${\"add_${type}_method_modifier"}($_, $code) for @args; | ||||
184 | } | ||||
185 | } else { | ||||
186 | foreach my $attr (@attrs) { | ||||
187 | foreach my $method (@{$attr->associated_methods}) { | ||||
188 | $method->{body} = $name->can($method->name); | ||||
189 | } | ||||
190 | } | ||||
191 | bless( | ||||
192 | $meta->find_method_by_name('new'), | ||||
193 | 'Moo::HandleMoose::FakeConstructor', | ||||
194 | ); | ||||
195 | # a combination of Moo and Moose may bypass a Moo constructor but still | ||||
196 | # use a Moo DEMOLISHALL. We need to make sure this is loaded before | ||||
197 | # global destruction. | ||||
198 | require Method::Generate::DemolishAll; | ||||
199 | } | ||||
200 | $meta->add_role(Class::MOP::class_of($_)) | ||||
201 | for grep !/\|/ && $_ ne $name, # reject Foo|Bar and same-role-as-self | ||||
202 | 2 | 169µs | 2 | 35µs | # spent 24µs (12+12) within Moo::HandleMoose::BEGIN@202 which was called:
# once (12µs+12µs) by Foo::Moo::BEGIN@116 at line 202 # spent 24µs making 1 call to Moo::HandleMoose::BEGIN@202
# spent 12µs making 1 call to warnings::unimport |
203 | $DID_INJECT{$name} = 1; | ||||
204 | $meta; | ||||
205 | } | ||||
206 | |||||
207 | 1 | 4µs | 1; |