File Coverage

blib/lib/optimizer.pm
Criterion Covered Total %
statement 29 111 26.1
branch 7 66 10.6
condition 3 45 6.6
subroutine 9 21 42.8
pod 2 6 33.3
total 50 249 20.0


line stmt bran cond sub pod time code
1             package optimizer;
2 2     2   5093 use Carp;
  2         3  
  2         103  
3 2     2   7 use B;
  2         3  
  2         51  
4 2     2   5 { no warnings 'redefine';
  2         10  
  2         71  
5 2     2   861 use B::Generate;
  2         2830  
  2         68  
6             }
7 2     2   42 use 5.007002;
  2         5  
8 2     2   9 use strict;
  2         3  
  2         45  
9 2     2   7 use warnings;
  2         3  
  2         113  
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       18 if ($] > 5.009) {
15 2 0   0   3181 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.06_07';
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 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 0 my $cop = shift; $file = $cop->file; $line = $cop->line;
  0         0  
  0         0  
42             }
43              
44 0     0 0 0 sub die (@) { CORE::die(preparewarn(@_)) }
45 0     0 0 0 sub warn (@) { CORE::warn(preparewarn(@_)) }
46             }
47              
48             sub import {
49 3     3   72 my ($class,$type) = (shift, shift);
50 3 50       10 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     65 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  
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         9 my ($package, $filename, $line) = caller;
68 3         8 $callbacks{$package} = shift;
69 3         130 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      
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 0 0         relocatetopad($op, $op->find_cv()) if $op->name eq "const"; # For thread safety
83              
84 0           $callback->($op);
85 0           $op = $op->next;
86 0 0         last unless $op->can("next"); # Shouldn't get here
87             }
88             }
89              
90             sub peepextend {
91             # Oh boy
92 0     0 1   my ($o, $callback) = @_;
93 0           my $oldop = 0;
94              
95 0 0 0       return if !$$o or $o->seq;
96              
97 0 0         op_seqmax_inc() unless op_seqmax();
98 0           while ($$o) {
99             #warn ("Trying op $o ($$o) -> ".$o->name."\n");
100 0 0 0       if ($o->isa("B::COP")) {
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
    0          
101              
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              
109 0           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)/) {
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             $o->pmreplstart($o->pmreplstart->next)
148 0   0       while ${$o->pmreplstart} and $o->pmreplstart->name eq "null";
  0            
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        
153 0           ${$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__