aboutsummaryrefslogtreecommitdiff
path: root/tools/js-optimizer.js
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-01-01 16:34:58 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-01-01 16:34:58 -0800
commit22f0f113c706781fba92ab5fddbd17843091d288 (patch)
treeb5c0d659d5104a6d90b8624e8b709c3b18bbf819 /tools/js-optimizer.js
parent16c68271b2527d87a01dc9330c7030bde0f5803e (diff)
fix bug in loopOptimizer with not removing all unneeded labels
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r--tools/js-optimizer.js33
1 files changed, 24 insertions, 9 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 7b489b33..f9b2cc1c 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -869,7 +869,7 @@ function loopOptimizer(ast) {
node[1] = '+' + node[1];
} else if (type in LOOP) {
stack.push(node);
- } else if (type in LOOP_FLOW && node[1]) { // only care about break/continue with an explicit label
+ } else if (type in LOOP_FLOW) {
// Find topmost loop, and its label if there is one
var lastLabel = null, lastLoop = null, i = stack.length-1;
while (i >= 0 && !lastLoop) {
@@ -882,25 +882,33 @@ function loopOptimizer(ast) {
if (stack[i][0] == 'label') lastLabel = stack[i];
i--;
}
- var ident = node[1];
+ var ident = node[1]; // there may not be a label ident if this is a simple break; or continue;
var plus = '+' + ident;
- if (lastLabel && (ident == lastLabel[1] || plus == lastLabel[1])) {
+ if (lastLabel && ident && (ident == lastLabel[1] || plus == lastLabel[1])) {
// If this is a 'do' loop, this break means we actually need it.
neededDos.push(lastLoop);
// We don't need the control flow command to have a label - it's referring to the current loop
return [node[0]];
} else {
- // Find the label node that needs to stay alive
- stack.forEach(function(label) {
- if (!label) return;
- if (label[1] == plus) label[1] = label[1].substr(1); // Remove '+', marking it as needed
- });
+ if (!ident) {
+ // No label on the break/continue, so keep the last loop alive (no need for its label though)
+ neededDos.push(lastLoop);
+ } else {
+ // Find the label node that needs to stay alive
+ stack.forEach(function(label) {
+ if (!label) return;
+ if (label[1] == plus) label[1] = label[1].substr(1); // Remove '+', marking it as needed
+ });
+ }
}
}
}, null, []);
+ // We return whether another pass is necessary
+ var more = false;
// Remove unneeded labels
traverseGenerated(ast, function(node, type) {
if (type == 'label' && node[1][0] == '+') {
+ more = true;
var ident = node[1].substr(1);
// Remove label from loop flow commands
traverse(node[2], function(node2, type) {
@@ -922,16 +930,23 @@ function loopOptimizer(ast) {
traverseGenerated(ast, function(node, type) {
if (type == 'do' && neededDos.indexOf(node) < 0) {
assert(jsonCompare(node[1], ['num', 0]), 'Trying to remove a one-time do loop that is not one of our generated ones.;');
+ more = true;
return node[2];
}
});
+ return more;
}
// Go
// TODO: pass 1: Removal of unneeded continues, breaks if they get us to where we are already going. That will
// help the next pass.
- passTwo(ast);
+
+ // Multiple pass two runs may be needed, as we remove one-time loops and so forth
+ do {
+ var more = passTwo(ast);
+ vacuum(ast);
+ } while (more);
vacuum(ast);
}