aboutsummaryrefslogtreecommitdiff
path: root/tools/js-optimizer.js
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-01-06 13:19:48 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-01-06 13:19:48 -0800
commit36d076140f80d9ba8e3010955fb2144a8c619663 (patch)
tree3de9064c5cf7fd3570f9bfe9ceccf29dcc8c9532 /tools/js-optimizer.js
parentb97c0cc2585a6617b8f170c2d8583e4c69f3f50d (diff)
also hoist loops in inner functions
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r--tools/js-optimizer.js122
1 files changed, 59 insertions, 63 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index c5d3a79f..7ac2195f 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -101,7 +101,7 @@ function traverse(node, pre, post, stack) {
// Only walk through the generated functions
function traverseGenerated(ast, pre, post, stack) {
- ast[1].forEach(function(node, i) {
+ traverse(ast, function(node) {
if (node[0] == 'defun' && isGenerated(node[1])) {
traverse(node, pre, post, stack);
}
@@ -109,7 +109,7 @@ function traverseGenerated(ast, pre, post, stack) {
}
function traverseGeneratedFunctions(ast, callback) {
- ast[1].forEach(function(node, i) {
+ traverse(ast, function(node) {
if (node[0] == 'defun' && isGenerated(node[1])) {
callback(node);
}
@@ -717,72 +717,69 @@ function vacuum(ast) {
var more = true;
while (more) {
more = false;
- ast[1].forEach(function(node, i) {
- function simplifyList(node, i) {
- var changed = false;
- var pre = node[i].length;
- node[i] = node[i].filter(function(node) { return !isEmpty(node) });
- if (node[i].length < pre) changed = true;
- // Also, seek blocks with single items we can simplify
- node[i] = node[i].map(function(subNode) {
- if (subNode[0] == 'block' && typeof subNode[1] == 'object' && subNode[1].length == 1 && subNode[1][0][0] == 'if') {
- return subNode[1][0];
- }
- return subNode;
- });
- if (changed) {
- more = true;
- return node;
+ function simplifyList(node, i) {
+ var changed = false;
+ var pre = node[i].length;
+ node[i] = node[i].filter(function(node) { return !isEmpty(node) });
+ if (node[i].length < pre) changed = true;
+ // Also, seek blocks with single items we can simplify
+ node[i] = node[i].map(function(subNode) {
+ if (subNode[0] == 'block' && typeof subNode[1] == 'object' && subNode[1].length == 1 && subNode[1][0][0] == 'if') {
+ return subNode[1][0];
}
+ return subNode;
+ });
+ if (changed) {
+ more = true;
+ return node;
}
- var type = node[0];
- if (type == 'defun' && isGenerated(node[1])) {
- simplifyNotComps(node);
- traverse(node, function(node, type) {
- if (type == 'block' && node[1] && node[1].length == 1 && node[1][0][0] == 'block') {
- more = true;
- return node[1][0];
- } else if (type == 'stat' && node[1][0] == 'block') {
- more = true;
- return node[1];
- } else if (type == 'block' && typeof node[1] == 'object') {
- ret = simplifyList(node, 1);
- if (ret) return ret;
- } else if (type == 'defun' && node[3].length == 1 && node[3][0][0] == 'block') {
+ }
+ traverseGeneratedFunctions(ast, function(node) {
+ simplifyNotComps(node);
+ traverse(node, function(node, type) {
+ if (type == 'block' && node[1] && node[1].length == 1 && node[1][0][0] == 'block') {
+ more = true;
+ return node[1][0];
+ } else if (type == 'stat' && node[1][0] == 'block') {
+ more = true;
+ return node[1];
+ } else if (type == 'block' && typeof node[1] == 'object') {
+ ret = simplifyList(node, 1);
+ if (ret) return ret;
+ } else if (type == 'defun' && node[3].length == 1 && node[3][0][0] == 'block') {
+ more = true;
+ node[3] = node[3][0][1];
+ return node;
+ } else if (type == 'defun') {
+ ret = simplifyList(node, 3);
+ if (ret) return ret;
+ } else if (type == 'do' && node[1][0] == 'num' && jsonCompare(node[2], emptyNode())) {
+ more = true;
+ return emptyNode();
+ } else if (type == 'label' && jsonCompare(node[2], emptyNode())) {
+ more = true;
+ return emptyNode();
+ } else if (type == 'if') {
+ var empty2 = isEmpty(node[2]), empty3 = isEmpty(node[3]), has3 = node.length == 4;
+ if (!empty2 && empty3 && has3) { // empty else clauses
more = true;
- node[3] = node[3][0][1];
- return node;
- } else if (type == 'defun') {
- ret = simplifyList(node, 3);
- if (ret) return ret;
- } else if (type == 'do' && node[1][0] == 'num' && jsonCompare(node[2], emptyNode())) {
+ return node.slice(0, 3);
+ } else if (empty2 && !empty3) { // empty if blocks
more = true;
- return emptyNode();
- } else if (type == 'label' && jsonCompare(node[2], emptyNode())) {
+ return ['if', ['unary-prefix', '!', node[1]], node[3]];
+ } else if (empty2 && empty3) {
more = true;
- return emptyNode();
- } else if (type == 'if') {
- var empty2 = isEmpty(node[2]), empty3 = isEmpty(node[3]), has3 = node.length == 4;
- if (!empty2 && empty3 && has3) { // empty else clauses
- more = true;
- return node.slice(0, 3);
- } else if (empty2 && !empty3) { // empty if blocks
- more = true;
- return ['if', ['unary-prefix', '!', node[1]], node[3]];
- } else if (empty2 && empty3) {
- more = true;
- if (hasSideEffects(node[1])) {
- return ['stat', node[1]];
- } else {
- return emptyNode();
- }
+ if (hasSideEffects(node[1])) {
+ return ['stat', node[1]];
+ } else {
+ return emptyNode();
}
- } else if (type == 'do' && isEmpty(node[2]) && !hasSideEffects(node[1])) {
- more = true;
- return emptyNode();
}
- });
- }
+ } else if (type == 'do' && isEmpty(node[2]) && !hasSideEffects(node[1])) {
+ more = true;
+ return emptyNode();
+ }
+ });
});
}
}
@@ -803,8 +800,7 @@ function getStatements(node) {
// if (condition) { __label__ == x } else ..
// We can hoist the multiple block into the condition, thus removing code and one 'if' check
function hoistMultiples(ast) {
- ast[1].forEach(function(node, i) {
- if (!(node[0] == 'defun' && isGenerated(node[1]))) return;
+ traverseGeneratedFunctions(ast, function(node) {
traverse(node, function(node, type) {
var statements = getStatements(node);
if (!statements) return;