diff options
author | Mihai Bazon <mihai@bazon.net> | 2012-11-07 18:57:51 +0200 |
---|---|---|
committer | Mihai Bazon <mihai@bazon.net> | 2012-11-08 11:43:14 +0200 |
commit | 1a5fd3e05294a74900c6265f364f233e3f05eba0 (patch) | |
tree | 44dedf148901474390eb3b34e2a38364575b72a3 /lib | |
parent | 5a7e54cf724d28eab424acd92f097207ee69afbd (diff) | |
download | tracifyjs-1a5fd3e05294a74900c6265f364f233e3f05eba0.tar.gz tracifyjs-1a5fd3e05294a74900c6265f364f233e3f05eba0.zip |
optimization for if/break as first statement in a loop body
for(...; x; ...) if (y) break; → for(...; x&&!y; ...);
similarly for `while` and some combinations (i.e. the `break` appears in the
`else` clause, etc.)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.js | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/lib/compress.js b/lib/compress.js index 59c9128d..1571173c 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1118,11 +1118,57 @@ merge(Compressor.prototype, { return self; }); + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + OPT(AST_While, function(self, compressor) { if (!compressor.option("loops")) return self; self = AST_DWLoop.prototype.optimize.call(self, compressor); if (self instanceof AST_While) { - self = make_node(AST_For, self, self); + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); } return self; }); @@ -1151,6 +1197,7 @@ merge(Compressor.prototype, { } } } + if_break_in_loop(self, compressor); return self; }); |