Filename | /usr/local/share/perl/5.18.2/Sub/Quote.pm |
Statements | Executed 281 statements in 10.9ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 2.82ms | 3.59ms | BEGIN@10 | Sub::Quote::
2 | 1 | 1 | 1.66ms | 1.78ms | _clean_eval | Sub::Quote::
1 | 1 | 1 | 999µs | 1.31ms | BEGIN@7 | Sub::Quote::
82 | 9 | 3 | 300µs | 456µs | quotify | Sub::Quote::
2 | 1 | 1 | 163µs | 279µs | capture_unroll | Sub::Quote::
2 | 1 | 1 | 161µs | 252µs | quote_sub | Sub::Quote::
2 | 1 | 1 | 143µs | 2.22ms | unquote_sub | Sub::Quote::
12 | 1 | 1 | 30µs | 30µs | quoted_from_sub | Sub::Quote::
18 | 2 | 1 | 28µs | 28µs | CORE:match (opcode) | Sub::Quote::
1 | 1 | 1 | 15µs | 47µs | BEGIN@5 | Sub::Quote::
2 | 1 | 1 | 12µs | 12µs | CORE:subst (opcode) | Sub::Quote::
1 | 1 | 1 | 11µs | 28µs | BEGIN@162 | Sub::Quote::
1 | 1 | 1 | 10µs | 40µs | BEGIN@8 | Sub::Quote::
1 | 1 | 1 | 9µs | 17µs | BEGIN@9 | Sub::Quote::
1 | 1 | 1 | 7µs | 7µs | BEGIN@11 | Sub::Quote::
0 | 0 | 0 | 0s | 0s | CLONE | Sub::Quote::
0 | 0 | 0 | 0s | 0s | __ANON__[:107] | Sub::Quote::
0 | 0 | 0 | 0s | 0s | inlinify | Sub::Quote::
0 | 0 | 0 | 0s | 0s | qsub | Sub::Quote::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Sub::Quote; | ||||
2 | |||||
3 | 2 | 470µs | # spent 1.78ms (1.66+119µs) within Sub::Quote::_clean_eval which was called 2 times, avg 892µs/call:
# 2 times (1.66ms+119µs) by Sub::Quote::unquote_sub at line 167, avg 892µs/call # spent 985µs executing statements in string eval # includes 234µs spent executing 5 calls to 3 subs defined therein. # spent 448µs executing statements in string eval # includes 78µs spent executing 5 calls to 3 subs defined therein. | ||
4 | |||||
5 | 2 | 36µs | 2 | 78µs | # spent 47µs (15+32) within Sub::Quote::BEGIN@5 which was called:
# once (15µs+32µs) by Method::Generate::Constructor::BEGIN@4 at line 5 # spent 47µs making 1 call to Sub::Quote::BEGIN@5
# spent 32µs making 1 call to Moo::_strictures::import |
6 | |||||
7 | 2 | 117µs | 2 | 1.36ms | # spent 1.31ms (999µs+308µs) within Sub::Quote::BEGIN@7 which was called:
# once (999µs+308µs) by Method::Generate::Constructor::BEGIN@4 at line 7 # spent 1.31ms making 1 call to Sub::Quote::BEGIN@7
# spent 49µs making 1 call to Exporter::import |
8 | 2 | 32µs | 2 | 70µs | # spent 40µs (10+30) within Sub::Quote::BEGIN@8 which was called:
# once (10µs+30µs) by Method::Generate::Constructor::BEGIN@4 at line 8 # spent 40µs making 1 call to Sub::Quote::BEGIN@8
# spent 30µs making 1 call to Exporter::import |
9 | 2 | 26µs | 2 | 24µs | # spent 17µs (9+7) within Sub::Quote::BEGIN@9 which was called:
# once (9µs+7µs) by Method::Generate::Constructor::BEGIN@4 at line 9 # spent 17µs making 1 call to Sub::Quote::BEGIN@9
# spent 7µs making 1 call to Exporter::import |
10 | 2 | 173µs | 1 | 3.59ms | # spent 3.59ms (2.82+770µs) within Sub::Quote::BEGIN@10 which was called:
# once (2.82ms+770µs) by Method::Generate::Constructor::BEGIN@4 at line 10 # spent 3.59ms making 1 call to Sub::Quote::BEGIN@10 |
11 | # spent 7µs within Sub::Quote::BEGIN@11 which was called:
# once (7µs+0s) by Method::Generate::Constructor::BEGIN@4 at line 13 | ||||
12 | 1 | 7µs | *_HAVE_PERLSTRING = defined &B::perlstring ? sub(){1} : sub(){0}; | ||
13 | 1 | 1.24ms | 1 | 7µs | } # spent 7µs making 1 call to Sub::Quote::BEGIN@11 |
14 | |||||
15 | 1 | 800ns | our $VERSION = '2.001000'; | ||
16 | 1 | 21µs | $VERSION = eval $VERSION; # spent 3µs executing statements in string eval | ||
17 | |||||
18 | 1 | 2µs | our @EXPORT = qw(quote_sub unquote_sub quoted_from_sub qsub); | ||
19 | 1 | 800ns | our @EXPORT_OK = qw(quotify capture_unroll inlinify); | ||
20 | |||||
21 | 1 | 300ns | our %QUOTED; | ||
22 | |||||
23 | # spent 456µs (300+157) within Sub::Quote::quotify which was called 82 times, avg 6µs/call:
# 16 times (68µs+29µs) by Sub::Quote::capture_unroll at line 36, avg 6µs/call
# 15 times (58µs+23µs) by Method::Generate::Constructor::_assign_new at line 213 of Method/Generate/Constructor.pm, avg 5µs/call
# 15 times (58µs+21µs) by Method::Generate::Accessor::_generate_simple_set at line 543 of Method/Generate/Accessor.pm, avg 5µs/call
# 15 times (42µs+29µs) by Method::Generate::Accessor::_generate_core_set at line 537 of Method/Generate/Accessor.pm, avg 5µs/call
# 9 times (24µs+9µs) by Method::Generate::Accessor::_wrap_attr_exception at line 421 of Method/Generate/Accessor.pm, avg 4µs/call
# 4 times (15µs+20µs) by Sub::Quote::quote_sub at line 88, avg 9µs/call
# 3 times (10µs+4µs) by Method::Generate::Accessor::_attr_desc at line 384 of Method/Generate/Accessor.pm, avg 5µs/call
# 3 times (8µs+6µs) by Method::Generate::Accessor::_wrap_attr_exception at line 420 of Method/Generate/Accessor.pm, avg 5µs/call
# 2 times (16µs+17µs) by Method::Generate::Constructor::_handle_subconstructor at line 161 of Method/Generate/Constructor.pm, avg 16µs/call | ||||
24 | 82 | 533µs | 82 | 157µs | ! defined $_[0] ? 'undef()' # spent 157µs making 82 calls to B::perlstring, avg 2µs/call |
25 | : _HAVE_PERLSTRING ? B::perlstring($_[0]) | ||||
26 | : qq["\Q$_[0]\E"]; | ||||
27 | } | ||||
28 | |||||
29 | # spent 279µs (163+115) within Sub::Quote::capture_unroll which was called 2 times, avg 139µs/call:
# 2 times (163µs+115µs) by Sub::Quote::unquote_sub at line 143, avg 139µs/call | ||||
30 | 2 | 2µs | my ($from, $captures, $indent) = @_; | ||
31 | 16 | 62µs | 16 | 19µs | join( # spent 19µs making 16 calls to Sub::Quote::CORE:match, avg 1µs/call |
32 | '', | ||||
33 | map { | ||||
34 | 2 | 33µs | /^([\@\%\$])/ | ||
35 | or die "capture key should start with \@, \% or \$: $_"; | ||||
36 | 32 | 85µs | 16 | 97µs | (' ' x $indent).qq{my ${_} = ${1}{${from}->{${\quotify $_}}};\n}; # spent 97µs making 16 calls to Sub::Quote::quotify, avg 6µs/call |
37 | } keys %$captures | ||||
38 | ); | ||||
39 | } | ||||
40 | |||||
41 | sub inlinify { | ||||
42 | my ($code, $args, $extra, $local) = @_; | ||||
43 | my $do = 'do { '.($extra||''); | ||||
44 | if ($code =~ s/^(\s*package\s+([a-zA-Z0-9:]+);)//) { | ||||
45 | $do .= $1; | ||||
46 | } | ||||
47 | if ($code =~ s{ | ||||
48 | \A((?:\#\ BEGIN\ quote_sub\ PRELUDE\n.*?\#\ END\ quote_sub\ PRELUDE\n)?\s*) | ||||
49 | (^\s*) my \s* \(([^)]+)\) \s* = \s* \@_; | ||||
50 | }{}xms) { | ||||
51 | my ($pre, $indent, $code_args) = ($1, $2, $3); | ||||
52 | $do .= $pre; | ||||
53 | if ($code_args ne $args) { | ||||
54 | $do .= $indent . 'my ('.$code_args.') = ('.$args.'); '; | ||||
55 | } | ||||
56 | } | ||||
57 | elsif ($local || $args ne '@_') { | ||||
58 | $do .= ($local ? 'local ' : '').'@_ = ('.$args.'); '; | ||||
59 | } | ||||
60 | $do.$code.' }'; | ||||
61 | } | ||||
62 | |||||
63 | # spent 252µs (161+91) within Sub::Quote::quote_sub which was called 2 times, avg 126µs/call:
# 2 times (161µs+91µs) by Method::Generate::Constructor::generate_method at line 154 of Method/Generate/Constructor.pm, avg 126µs/call | ||||
64 | # HOLY DWIMMERY, BATMAN! | ||||
65 | # $name => $code => \%captures => \%options | ||||
66 | # $name => $code => \%captures | ||||
67 | # $name => $code | ||||
68 | # $code => \%captures => \%options | ||||
69 | # $code | ||||
70 | 2 | 15µs | my $options = | ||
71 | (ref($_[-1]) eq 'HASH' and ref($_[-2]) eq 'HASH') | ||||
72 | ? pop | ||||
73 | : {}; | ||||
74 | 2 | 1µs | my $captures = ref($_[-1]) eq 'HASH' ? pop : undef; | ||
75 | 2 | 3µs | undef($captures) if $captures && !keys %$captures; | ||
76 | 2 | 11µs | my $code = pop; | ||
77 | 2 | 1µs | my $name = $_[0]; | ||
78 | 2 | 2µs | if ($name) { | ||
79 | 2 | 900ns | my $subname = $name; | ||
80 | 2 | 29µs | 2 | 12µs | my $package = $subname =~ s/(.*)::// ? $1 : caller; # spent 12µs making 2 calls to Sub::Quote::CORE:subst, avg 6µs/call |
81 | 2 | 2µs | $name = join '::', $package, $subname; | ||
82 | 2 | 5µs | die "package name $package too long!" | ||
83 | if length $package > 252; | ||||
84 | 2 | 2µs | die "sub name $subname too long!" | ||
85 | if length $subname > 252; | ||||
86 | } | ||||
87 | 2 | 13µs | my ($package, $hints, $bitmask, $hintshash) = (caller(0))[0,8,9,10]; | ||
88 | 2 | 18µs | 4 | 35µs | my $context # spent 35µs making 4 calls to Sub::Quote::quotify, avg 9µs/call |
89 | ="# BEGIN quote_sub PRELUDE\n" | ||||
90 | ."package $package;\n" | ||||
91 | ."BEGIN {\n" | ||||
92 | ." \$^H = ".quotify($hints).";\n" | ||||
93 | ." \${^WARNING_BITS} = ".quotify($bitmask).";\n" | ||||
94 | ." \%^H = (\n" | ||||
95 | . join('', map | ||||
96 | " ".quotify($_)." => ".quotify($hintshash->{$_}).",", | ||||
97 | keys %$hintshash) | ||||
98 | ." );\n" | ||||
99 | ."}\n" | ||||
100 | ."# END quote_sub PRELUDE\n"; | ||||
101 | 2 | 10µs | $code = "$context$code"; | ||
102 | 2 | 400ns | my $quoted_info; | ||
103 | 2 | 500ns | my $unquoted; | ||
104 | my $deferred = defer_sub +($options->{no_install} ? undef : $name) => sub { | ||||
105 | $unquoted if 0; | ||||
106 | unquote_sub($quoted_info->[4]); | ||||
107 | 2 | 16µs | 2 | 38µs | }; # spent 38µs making 2 calls to Sub::Defer::defer_sub, avg 19µs/call |
108 | 2 | 8µs | $quoted_info = [ $name, $code, $captures, \$unquoted, $deferred ]; | ||
109 | 2 | 8µs | 2 | 2µs | weaken($quoted_info->[3]); # spent 2µs making 2 calls to Scalar::Util::weaken, avg 1µs/call |
110 | 2 | 6µs | 2 | 2µs | weaken($quoted_info->[4]); # spent 2µs making 2 calls to Scalar::Util::weaken, avg 850ns/call |
111 | 2 | 7µs | 2 | 2µs | weaken($QUOTED{$deferred} = $quoted_info); # spent 2µs making 2 calls to Scalar::Util::weaken, avg 850ns/call |
112 | 2 | 9µs | return $deferred; | ||
113 | } | ||||
114 | |||||
115 | # spent 30µs within Sub::Quote::quoted_from_sub which was called 12 times, avg 3µs/call:
# 12 times (30µs+0s) by Method::Generate::Accessor::_generate_call_code at line 456 of Method/Generate/Accessor.pm, avg 3µs/call | ||||
116 | 12 | 4µs | my ($sub) = @_; | ||
117 | 12 | 7.46ms | my $quoted_info = $QUOTED{$sub||''} or return undef; | ||
118 | my ($name, $code, $captured, $unquoted, $deferred) = @{$quoted_info}; | ||||
119 | $unquoted &&= $$unquoted; | ||||
120 | if (($deferred && $deferred eq $sub) | ||||
121 | || ($unquoted && $unquoted eq $sub)) { | ||||
122 | return [ $name, $code, $captured, $unquoted, $deferred ]; | ||||
123 | } | ||||
124 | return undef; | ||||
125 | } | ||||
126 | |||||
127 | # spent 2.22ms (143µs+2.08) within Sub::Quote::unquote_sub which was called 2 times, avg 1.11ms/call:
# 2 times (143µs+2.08ms) by Method::Generate::Constructor::__ANON__[/usr/local/share/perl/5.18.2/Method/Generate/Constructor.pm:102] at line 96 of Method/Generate/Constructor.pm, avg 1.11ms/call | ||||
128 | 2 | 1µs | my ($sub) = @_; | ||
129 | 2 | 2µs | my $quoted = $QUOTED{$sub} or return undef; | ||
130 | 2 | 2µs | my $unquoted = $quoted->[3]; | ||
131 | 2 | 2µs | unless ($unquoted && $$unquoted) { | ||
132 | 2 | 9µs | my ($name, $code, $captures) = @$quoted; | ||
133 | 2 | 800ns | my $package; | ||
134 | |||||
135 | 2 | 20µs | 2 | 9µs | ($package, $name) = $name =~ /(.*)::(.*)/ # spent 9µs making 2 calls to Sub::Quote::CORE:match, avg 5µs/call |
136 | if $name; | ||||
137 | |||||
138 | 2 | 10µs | my $make_sub = "{\n"; | ||
139 | |||||
140 | 2 | 8µs | my %captures = $captures ? %$captures : (); | ||
141 | 2 | 2µs | $captures{'$_UNQUOTED'} = \$unquoted; | ||
142 | 2 | 1µs | $captures{'$_QUOTED'} = \$quoted; | ||
143 | 2 | 8µs | 2 | 279µs | $make_sub .= capture_unroll("\$_[1]", \%captures, 2); # spent 279µs making 2 calls to Sub::Quote::capture_unroll, avg 139µs/call |
144 | |||||
145 | 2 | 4µs | $make_sub .= ( | ||
146 | $name | ||||
147 | # disable the 'variable $x will not stay shared' warning since | ||||
148 | # we're not letting it escape from this scope anyway so there's | ||||
149 | # nothing trying to share it | ||||
150 | ? " no warnings 'closure';\n package ${package};\n sub ${name} {\n" | ||||
151 | : " \$\$_UNQUOTED = sub {\n" | ||||
152 | ); | ||||
153 | 2 | 900ns | $make_sub .= " (\$_QUOTED,\$_UNQUOTED) if 0;\n"; | ||
154 | 2 | 20µs | $make_sub .= $code; | ||
155 | 2 | 2µs | $make_sub .= " }".($name ? '' : ';')."\n"; | ||
156 | 2 | 2µs | if ($name) { | ||
157 | $make_sub .= " \$\$_UNQUOTED = \\&${name}\n"; | ||||
158 | } | ||||
159 | 2 | 1µs | $make_sub .= "}\n1;\n"; | ||
160 | 2 | 2µs | $ENV{SUB_QUOTE_DEBUG} && warn $make_sub; | ||
161 | { | ||||
162 | 4 | 293µs | 2 | 46µs | # spent 28µs (11+18) within Sub::Quote::BEGIN@162 which was called:
# once (11µs+18µs) by Method::Generate::Constructor::BEGIN@4 at line 162 # spent 28µs making 1 call to Sub::Quote::BEGIN@162
# spent 18µs making 1 call to strict::unimport |
163 | 2 | 8µs | local *{"${package}::${name}"} if $name; | ||
164 | 2 | 700ns | my ($success, $e); | ||
165 | { | ||||
166 | 4 | 2µs | local $@; | ||
167 | 2 | 6µs | 2 | 1.78ms | $success = _clean_eval($make_sub, \%captures); # spent 1.78ms making 2 calls to Sub::Quote::_clean_eval, avg 892µs/call |
168 | 2 | 2µs | $e = $@; | ||
169 | } | ||||
170 | 2 | 1µs | unless ($success) { | ||
171 | die "Eval went very, very wrong:\n\n${make_sub}\n\n$e"; | ||||
172 | } | ||||
173 | 2 | 18µs | 2 | 4µs | weaken($QUOTED{$$unquoted} = $quoted); # spent 4µs making 2 calls to Scalar::Util::weaken, avg 2µs/call |
174 | } | ||||
175 | } | ||||
176 | 2 | 9µs | $$unquoted; | ||
177 | } | ||||
178 | |||||
179 | sub qsub ($) { | ||||
180 | goto "e_sub; | ||||
181 | } | ||||
182 | |||||
183 | sub CLONE { | ||||
184 | %QUOTED = map { defined $_ ? ( | ||||
185 | $_->[3] && ${$_->[3]} ? (${ $_->[3] } => $_) : (), | ||||
186 | $_->[4] ? ($_->[4] => $_) : (), | ||||
187 | ) : () } values %QUOTED; | ||||
188 | weaken($_) for values %QUOTED; | ||||
189 | } | ||||
190 | |||||
191 | 1 | 4µs | 1; | ||
192 | __END__ | ||||
sub Sub::Quote::CORE:match; # opcode | |||||
# spent 12µs within Sub::Quote::CORE:subst which was called 2 times, avg 6µs/call:
# 2 times (12µs+0s) by Sub::Quote::quote_sub at line 80, avg 6µs/call |