aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2012-09-12 16:10:03 +0300
committerMihai Bazon <mihai@bazon.net>2012-09-12 16:10:03 +0300
commita132841fb920f6815eb6d153f4329242354f1cae (patch)
tree7e78973f3ff2a365953567ebf528cecbda82304e /lib/compress.js
parent2b1e4628e0ee3e73d2e9d00635e51067ec36cd52 (diff)
downloadtracifyjs-a132841fb920f6815eb6d153f4329242354f1cae.tar.gz
tracifyjs-a132841fb920f6815eb6d153f4329242354f1cae.zip
more AST_If optimizations
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js87
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;
});