aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2012-10-18 15:14:57 +0300
committerMihai Bazon <mihai@bazon.net>2012-10-18 15:14:57 +0300
commitafb7faa6fadee46a6ab46232eddba2121c77549b (patch)
tree5d472b568192e15812dbf74c63790abf78ce984b /lib
parent6aa56f92fe07edfc677d390a2e26b37c98da0968 (diff)
downloadtracifyjs-afb7faa6fadee46a6ab46232eddba2121c77549b.tar.gz
tracifyjs-afb7faa6fadee46a6ab46232eddba2121c77549b.zip
more optimizations for some break/continue cases
Diffstat (limited to 'lib')
-rw-r--r--lib/ast.js8
-rw-r--r--lib/compress.js45
-rw-r--r--lib/utils.js6
3 files changed, 51 insertions, 8 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 177bd1d7..44cbed12 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -929,10 +929,10 @@ TreeWalker.prototype = {
} else {
for (var i = stack.length; --i >= 0;) {
var x = stack[i];
- if (x instanceof AST_Switch) return x;
- if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
- return (x.body instanceof AST_BlockStatement ? x.body : x);
- }
+ if (x instanceof AST_Switch
+ || x instanceof AST_For
+ || x instanceof AST_ForIn
+ || x instanceof AST_DWLoop) return x;
}
}
}
diff --git a/lib/compress.js b/lib/compress.js
index 1af4a2d6..cde4b6f7 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -186,6 +186,14 @@ merge(Compressor.prototype, {
return false;
};
+ function loop_body(x) {
+ if (x instanceof AST_Switch) return x;
+ if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
+ return (x.body instanceof AST_BlockStatement ? x.body : x);
+ }
+ return x;
+ };
+
function tighten_body(statements, compressor) {
var CHANGED;
do {
@@ -303,8 +311,13 @@ merge(Compressor.prototype, {
}
var ab = aborts(stat.body);
+ var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
- || (ab instanceof AST_Continue && self === compressor.loopcontrol_target(ab.label)))) {
+ || (ab instanceof AST_Continue && self === loop_body(lct))
+ || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
+ if (ab.label) {
+ remove(ab.label.thedef.references, ab.label);
+ }
CHANGED = true;
var body = as_statement_array(stat.body).slice(0, -1);
stat = stat.clone();
@@ -320,8 +333,13 @@ merge(Compressor.prototype, {
}
var ab = aborts(stat.alternative);
+ var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
- || (ab instanceof AST_Continue && self === compressor.loopcontrol_target(ab.label)))) {
+ || (ab instanceof AST_Continue && self === loop_body(lct))
+ || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
+ if (ab.label) {
+ remove(ab.label.thedef.references, ab.label);
+ }
CHANGED = true;
stat = stat.clone();
stat.body = make_node(AST_BlockStatement, stat.body, {
@@ -347,11 +365,26 @@ merge(Compressor.prototype, {
function eliminate_dead_code(statements, compressor) {
var has_quit = false;
var orig = statements.length;
+ var self = compressor.self();
statements = statements.reduce(function(a, stat){
if (has_quit) {
extract_declarations_from_unreachable_code(compressor, stat, a);
} else {
- a.push(stat);
+ if (stat instanceof AST_LoopControl) {
+ var lct = compressor.loopcontrol_target(stat.label);
+ if ((stat instanceof AST_Break
+ && lct instanceof AST_BlockStatement
+ && loop_body(lct) === self) || (stat instanceof AST_Continue
+ && loop_body(lct) === self)) {
+ if (stat.label) {
+ remove(stat.label.thedef.references, stat.label);
+ }
+ } else {
+ a.push(stat);
+ }
+ } else {
+ a.push(stat);
+ }
if (aborts(stat)) has_quit = true;
}
return a;
@@ -795,6 +828,10 @@ merge(Compressor.prototype, {
});
OPT(AST_LabeledStatement, function(self, compressor){
+ if (self.body instanceof AST_Break
+ && compressor.loopcontrol_target(self.body.label) === self.body) {
+ return make_node(AST_EmptyStatement, self);
+ }
return self.label.references.length == 0 ? self.body : self;
});
@@ -1227,7 +1264,7 @@ merge(Compressor.prototype, {
var last_branch = self.body[self.body.length - 1];
if (last_branch) {
var stat = last_branch.body[last_branch.body.length - 1]; // last statement
- if (stat instanceof AST_Break && compressor.loopcontrol_target(stat.label) === self)
+ if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
last_branch.body.pop();
}
return self;
diff --git a/lib/utils.js b/lib/utils.js
index 79039665..4d3d60f6 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -166,6 +166,12 @@ function string_template(text, props) {
});
};
+function remove(array, el) {
+ for (var i = array.length; --i >= 0;) {
+ if (array[i] === el) array.splice(i, 1);
+ }
+};
+
function mergeSort(array, cmp) {
if (array.length < 2) return array.slice();
function merge(a, b) {