diff options
author | Mihai Bazon <mihai@bazon.net> | 2012-09-12 16:10:03 +0300 |
---|---|---|
committer | Mihai Bazon <mihai@bazon.net> | 2012-09-12 16:10:03 +0300 |
commit | a132841fb920f6815eb6d153f4329242354f1cae (patch) | |
tree | 7e78973f3ff2a365953567ebf528cecbda82304e /lib/compress.js | |
parent | 2b1e4628e0ee3e73d2e9d00635e51067ec36cd52 (diff) | |
download | tracifyjs-a132841fb920f6815eb6d153f4329242354f1cae.tar.gz tracifyjs-a132841fb920f6815eb6d153f4329242354f1cae.zip |
more AST_If optimizations
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 87 |
1 files changed, 74 insertions, 13 deletions
diff --git a/lib/compress.js b/lib/compress.js index 06b133f9..02b9e243 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -122,17 +122,17 @@ function Compressor(options, false_by_default) { }; function SQUEEZE(nodetype, squeeze) { - nodetype.DEFMETHOD("squeeze", function(compressor){ + nodetype.DEFMETHOD("squeeze", function(compressor, block, index){ compressor.push_node(this); - var new_node = squeeze(this, compressor); + var new_node = squeeze(this, compressor, block, index); compressor.pop_node(); return new_node !== undefined ? new_node : this; }); }; function do_list(array, compressor, splice_blocks) { - return MAP(array, function(node){ - node = node.squeeze(compressor); + return MAP(array, function(node, i){ + node = node.squeeze(compressor, array, i); if (splice_blocks) { if (node instanceof AST_BlockStatement) { return MAP.splice(eliminate_spurious_blocks(node.body)); @@ -222,7 +222,8 @@ function Compressor(options, false_by_default) { } else if (i == last && cur instanceof AST_Exit && cur.value - && a.length == 1 && prev instanceof AST_SimpleStatement) { + && a.length > 0 + && prev instanceof AST_SimpleStatement) { // it only makes sense to do this transformation // if the AST gets to a single statement. var seq = make_node(AST_Seq, prev, { @@ -230,7 +231,9 @@ function Compressor(options, false_by_default) { second: cur.value }); cur.value = seq; - return [ cur ]; + a.pop(); + a.push(cur); + return a; } else { a.push(cur); @@ -459,7 +462,9 @@ function Compressor(options, false_by_default) { return basic_negation(this); }); })(function(node, func){ - node.DEFMETHOD("negate", func); + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor).optimize(compressor); + }); }); // determine if expression has side effects @@ -494,6 +499,15 @@ function Compressor(options, false_by_default) { node.DEFMETHOD("has_side_effects", func); }); + // tell me if a statement aborts + (function(def){ + def(AST_StatementBase, function(){ return null }); + def(AST_Jump, function(){ return this }); + def(AST_BlockStatement, function(){ return this.body[this.body.length - 1].aborts() }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + /* -----[ node squeezers ]----- */ SQUEEZE(AST_Debugger, function(self, compressor){ @@ -516,9 +530,13 @@ function Compressor(options, false_by_default) { SQUEEZE(AST_BlockStatement, function(self, compressor){ self = self.clone(); self.body = tighten_body(self.body, compressor); - if (self.body.length == 1) - return self.body[0]; - return self; + return self.optimize(compressor); + }); + + AST_BlockStatement.DEFMETHOD("optimize", function(compressor){ + if (this.body.length == 1) + return this.body[0]; + return this; }); SQUEEZE(AST_Block, function(self, compressor){ @@ -705,16 +723,16 @@ function Compressor(options, false_by_default) { return self; }); - SQUEEZE(AST_If, function(self, compressor){ + SQUEEZE(AST_If, function(self, compressor, block, index){ self = self.clone(); self.condition = self.condition.squeeze(compressor); self.body = self.body.squeeze(compressor); if (self.alternative) self.alternative = self.alternative.squeeze(compressor); - return self.optimize(compressor); + return self.optimize(compressor, block, index); }); - AST_If.DEFMETHOD("optimize", function(compressor){ + AST_If.DEFMETHOD("optimize", function(compressor, block, index){ var self = this; if (!compressor.option("conditionals")) return self; // if condition can be statically determined, warn and drop @@ -809,6 +827,49 @@ function Compressor(options, false_by_default) { }).optimize(compressor) }); } + if (self.body instanceof AST_Return + && !self.body.value + && !self.alternative + && index < block.length - 1) { + if (compressor.parent() instanceof AST_Lambda) { + var rest = tighten_body(block.slice(index + 1), compressor); + var cond = negated_is_best ? negated : self.condition.negate(compressor); + while (rest[0] instanceof AST_If && rest[0].body instanceof AST_Return && !rest[0].alternative) { + cond = make_node(AST_Binary, rest[0], { + operator: "&&", + left: cond, + right: rest[0].condition.negate(compressor) + }); + rest.shift(); + } + return MAP.last(make_node(AST_If, self, { + condition: cond, + body: make_node(AST_BlockStatement, block[index + 1], { + body: rest + }).optimize(compressor) + }).optimize(compressor)); + } + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }); + self.body = self.body.body; + } + var abort = self.body.aborts(); + if (abort) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).optimize(compressor); + } + } return self; }); |