line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package optimizer; |
2
|
2
|
|
|
2
|
|
7214
|
use Carp; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
153
|
|
3
|
2
|
|
|
2
|
|
10
|
use B; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
69
|
|
4
|
2
|
|
|
2
|
|
10
|
{ no warnings 'redefine'; |
|
2
|
|
|
|
|
14
|
|
|
2
|
|
|
|
|
76
|
|
5
|
2
|
|
|
2
|
|
1911
|
use B::Generate; |
|
2
|
|
|
|
|
4913
|
|
|
2
|
|
|
|
|
84
|
|
6
|
|
|
|
|
|
|
} |
7
|
2
|
|
|
2
|
|
46
|
use 5.007002; |
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
73
|
|
8
|
2
|
|
|
2
|
|
11
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
60
|
|
9
|
2
|
|
|
2
|
|
9
|
use warnings; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
103
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
BEGIN { |
12
|
|
|
|
|
|
|
# op_seq workaround for 5.10, store it as package global. |
13
|
2
|
|
|
2
|
|
5
|
my $seq = 0; |
14
|
2
|
50
|
|
|
|
14
|
if ($] > 5.009) { |
15
|
2
|
0
|
|
0
|
|
3567
|
eval q( |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
16
|
|
|
|
|
|
|
package B::OP; |
17
|
|
|
|
|
|
|
sub seq { |
18
|
|
|
|
|
|
|
shift; |
19
|
|
|
|
|
|
|
@_ ? $optimizer::seq = shift : $optimizer::seq; |
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
); |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
require DynaLoader; |
26
|
|
|
|
|
|
|
our $VERSION = '0.08'; |
27
|
|
|
|
|
|
|
our @ISA = q(DynaLoader); |
28
|
|
|
|
|
|
|
our %callbacks; |
29
|
|
|
|
|
|
|
bootstrap optimizer $VERSION; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my ($file, $line) = ("unknown", "unknown"); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
{ |
34
|
|
|
|
|
|
|
sub _preparewarn { |
35
|
0
|
|
|
0
|
|
0
|
my $args = join '', @_; |
36
|
0
|
0
|
|
|
|
0
|
$args = "Something's wrong " unless $args; |
37
|
0
|
0
|
|
|
|
0
|
$args .= " at $file line $line.\n" unless substr($args, length($args) -1) eq "\n"; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub _update { |
41
|
0
|
|
|
0
|
|
0
|
my $cop = shift; $file = $cop->file; $line = $cop->line; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
0
|
|
|
0
|
|
0
|
sub _die (@) { CORE::die(preparewarn(@_)) } |
45
|
0
|
|
|
0
|
|
0
|
sub _warn (@) { CORE::warn(preparewarn(@_)) } |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub import { |
49
|
3
|
|
|
3
|
|
79
|
my ($class,$type) = (shift, shift); |
50
|
3
|
50
|
|
|
|
12
|
if (!defined $type) { |
51
|
0
|
|
|
|
|
0
|
CORE::warn("Must pass an action to ${class}'s importer"); |
52
|
|
|
|
|
|
|
return |
53
|
0
|
|
|
|
|
0
|
} |
54
|
3
|
50
|
33
|
|
|
64
|
if ($type eq 'C' or $type eq 'c') { |
|
|
50
|
33
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
55
|
0
|
|
|
|
|
0
|
optimizer::uninstall(); |
56
|
|
|
|
|
|
|
} elsif ($type =~ /^Perl$/i) { |
57
|
0
|
|
|
0
|
|
0
|
optimizer::install( sub { optimizer::peepextend($_[0], sub {}) }); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
58
|
|
|
|
|
|
|
} elsif ($type eq "callback" or $type eq "extend" or $type eq "mine") { |
59
|
0
|
|
|
|
|
0
|
my $subref = shift; |
60
|
0
|
0
|
|
|
|
0
|
croak "Supplied callback was not a subref" unless ref $subref eq "CODE"; |
61
|
0
|
0
|
|
0
|
|
0
|
optimizer::install( sub { callbackoptimizer($_[0], $subref) }) if $type eq "callback"; |
|
0
|
|
|
|
|
0
|
|
62
|
0
|
0
|
|
0
|
|
0
|
optimizer::install( sub { optimizer::peepextend($_[0], $subref) }) if $type eq "extend"; |
|
0
|
|
|
|
|
0
|
|
63
|
0
|
0
|
|
|
|
0
|
optimizer::install( $subref ) if $type eq "mine"; |
64
|
|
|
|
|
|
|
} elsif ($type eq 'extend-c') { |
65
|
0
|
|
|
|
|
0
|
optimizer::c_extend_install(shift); |
66
|
|
|
|
|
|
|
} elsif ($type eq 'sub-detect') { |
67
|
3
|
|
|
|
|
11
|
my ($package, $filename, $line) = caller; |
68
|
3
|
|
|
|
|
7
|
$callbacks{$package} = shift; |
69
|
3
|
|
|
|
|
141
|
optimizer::c_sub_detect_install(); |
70
|
0
|
|
|
|
|
|
} else { croak "Unknown optimizer option '$type'"; } |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub unimport { |
74
|
0
|
|
|
0
|
|
|
optimizer::install(sub {callbackoptimizer($_[0], sub{})}); |
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub callbackoptimizer { |
78
|
0
|
|
|
0
|
1
|
|
my ($op, $callback) = @_; |
79
|
0
|
|
|
|
|
|
while ($$op) { |
80
|
0
|
|
|
|
|
|
$op->seq(optimizer::op_seqmax_inc()); |
81
|
0
|
0
|
|
|
|
|
_update($op) if $op->isa("B::COP"); |
82
|
|
|
|
|
|
|
# crashes: wrong op_sv, strange cv |
83
|
|
|
|
|
|
|
#_relocatetopad($op, $op->find_cv()) if $op->name eq "const"; # For thread safety |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
$callback->($op); |
86
|
0
|
|
|
|
|
|
$op = $op->next; |
87
|
0
|
0
|
|
|
|
|
last unless $op->can("next"); # Shouldn't get here |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub peepextend { |
92
|
|
|
|
|
|
|
# Oh boy |
93
|
0
|
|
|
0
|
1
|
|
my ($o, $callback) = @_; |
94
|
0
|
|
|
|
|
|
my $oldop = 0; |
95
|
|
|
|
|
|
|
|
96
|
0
|
0
|
0
|
|
|
|
return if !$$o or $o->seq; |
97
|
|
|
|
|
|
|
|
98
|
0
|
0
|
|
|
|
|
op_seqmax_inc() unless op_seqmax(); |
99
|
0
|
|
|
|
|
|
while ($$o) { |
100
|
|
|
|
|
|
|
#warn ("Trying op $o ($$o) -> ".$o->name."\n"); |
101
|
0
|
0
|
0
|
|
|
|
if ($o->isa("B::COP")) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
103
|
0
|
|
|
|
|
|
_update($o); # For warnings |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
} elsif ($o->name eq "const") { |
106
|
0
|
0
|
|
|
|
|
optimizer::_die("Bareword ",$o->sv->sv, " not allowed while \"strict subs\" in use") |
107
|
|
|
|
|
|
|
if ($o->private & 8); |
108
|
|
|
|
|
|
|
# crashes: wrong op_sv, strange cv |
109
|
|
|
|
|
|
|
#_relocatetopad($o, $o->find_cv()); |
110
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
111
|
|
|
|
|
|
|
} elsif ($o->name eq "concat") { |
112
|
0
|
0
|
0
|
|
|
|
if ($o->next && $o->next->name eq "stringify" and !($o->flags &64)) { |
|
|
|
0
|
|
|
|
|
113
|
0
|
0
|
|
|
|
|
if ($o->next->private & 16) { |
114
|
0
|
|
|
|
|
|
$o->targ($o->next->targ); |
115
|
0
|
|
|
|
|
|
$o->next->targ(0); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
#$o->null; |
118
|
|
|
|
|
|
|
} |
119
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
120
|
|
|
|
|
|
|
#} elsif ($o->name eq "stub") { |
121
|
|
|
|
|
|
|
# CORE::die "Eep."; |
122
|
|
|
|
|
|
|
#} elsif ($o->name eq "null") { |
123
|
|
|
|
|
|
|
# CORE::die "Eep."; |
124
|
|
|
|
|
|
|
} elsif ($o->name eq "scalar" or $o->name eq "lineseq" or $o->name eq "scope") { |
125
|
0
|
0
|
0
|
|
|
|
if ($$oldop and ${$o->next}) { |
|
0
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
$oldop->next($o->next); |
127
|
0
|
|
|
|
|
|
$o=$o->next; |
128
|
0
|
|
|
|
|
|
next; |
129
|
|
|
|
|
|
|
} |
130
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
131
|
|
|
|
|
|
|
#} elsif ($o->name eq "gv") { |
132
|
|
|
|
|
|
|
# CORE::die "Eep."; |
133
|
|
|
|
|
|
|
} elsif ($o->name =~ /^((map|grep)while|(and|or)(assign)?|cond_expr|range)$/) { |
134
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
135
|
0
|
|
|
|
|
|
$o->other($o->other->next) while $o->other->name eq "null"; |
136
|
0
|
|
|
|
|
|
peepextend($o->other, $callback); # Weee. |
137
|
|
|
|
|
|
|
} elsif ($o->name =~ /^enter(loop|iter|given|when)/) { |
138
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
139
|
0
|
|
|
|
|
|
$o->redoop($o->redoop->next) while $o->redoop->name eq "null"; |
140
|
0
|
|
|
|
|
|
peepextend($o->redoop, $callback); |
141
|
0
|
|
|
|
|
|
$o->nextop($o->nextop->next) while $o->nextop->name eq "null"; |
142
|
0
|
|
|
|
|
|
peepextend($o->nextop, $callback); |
143
|
0
|
|
|
|
|
|
$o->lastop($o->lastop->next) while $o->lastop->name eq "null"; |
144
|
0
|
|
|
|
|
|
peepextend($o->lastop, $callback); |
145
|
|
|
|
|
|
|
} elsif ($o->name eq "qr" or $o->name eq "match" or $o->name eq "subst") { |
146
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
147
|
0
|
|
|
|
|
|
$o->pmreplstart($o->pmreplstart->next) |
148
|
0
|
|
0
|
|
|
|
while ${$o->pmreplstart} and $o->pmreplstart->name eq "null"; |
149
|
0
|
|
|
|
|
|
peepextend($o->pmreplstart, $callback); |
150
|
|
|
|
|
|
|
} elsif ($o->name eq "exec") { |
151
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
152
|
0
|
0
|
0
|
|
|
|
if (${$o->next} and $o->next->name eq "nextstate" and |
|
0
|
|
0
|
|
|
|
|
|
0
|
|
0
|
|
|
|
|
153
|
|
|
|
|
|
|
${$o->next->sibling} and $o->next->sibling->type !~ /exit|warn|die/) { |
154
|
0
|
|
|
|
|
|
optimizer::_warn("Statement unlikely to be reached"); |
155
|
0
|
|
|
|
|
|
optimizer::_warn("\t(Maybe you meant system() when you said exec()?)\n"); |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
} else { |
158
|
|
|
|
|
|
|
# Screw pseudohashes. |
159
|
0
|
|
|
|
|
|
$o->seq(optimizer::op_seqmax_inc()); |
160
|
|
|
|
|
|
|
} |
161
|
0
|
|
|
|
|
|
my $plop = $o; |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
$callback->($o); |
164
|
0
|
|
|
|
|
|
$oldop = $o; |
165
|
0
|
|
|
|
|
|
$o = $o->next; |
166
|
0
|
0
|
|
|
|
|
last unless $o->can("next"); # Shouldn't get here |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
1; |
171
|
|
|
|
|
|
|
__END__ |