diff options
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 9efca25f..161ed59c 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -271,6 +271,16 @@ function isEmptyNode(node) { return node.length === 2 && node[0] === 'toplevel' && node[1].length === 0; } +function clearEmptyNodes(list) { + for (var i = 0; i < list.length;) { + if (isEmptyNode(list[i]) || (list[i][0] === 'stat' && isEmptyNode(list[i][1]))) { + list.splice(i, 1); + } else { + i++; + } + } +} + // Passes // Dump the AST. Useful for debugging. For example, @@ -2134,14 +2144,11 @@ function registerize(ast) { // In memSafe mode, we are more careful and assume functions can replace HEAP and FUNCTION_TABLE, which // can happen in ALLOW_MEMORY_GROWTH mode -var ELIMINATION_SAFE_NODES = set('var', 'assign', 'call', 'if', 'toplevel', 'do', 'return', 'label', 'switch'); // do is checked carefully, however +var ELIMINATION_SAFE_NODES = set('var', 'assign', 'call', 'if', 'toplevel', 'do', 'return', 'label', 'switch', 'binary', 'unary-prefix'); // do is checked carefully, however var IGNORABLE_ELIMINATOR_SCAN_NODES = set('num', 'toplevel', 'string', 'break', 'continue', 'dot'); // dot can only be STRING_TABLE.* var ABORTING_ELIMINATOR_SCAN_NODES = set('new', 'object', 'function', 'defun', 'for', 'while', 'array', 'throw'); // we could handle some of these, TODO, but nontrivial (e.g. for while, the condition is hit multiple times after the body) function isTempDoublePtrAccess(node) { // these are used in bitcasts; they are not really affecting memory, and should cause no invalidation - // XXX note that we assume they have no effect. this is only true due to the compiler emitting (write, read) - // using the comma operator, so they are not split up. Otherwise, we would need to invalidate - // tempDoublePtr when it is used, so write; read; write; read; would not become write; write; read; read; assert(node[0] === 'sub'); return (node[2][0] === 'name' && node[2][1] === 'tempDoublePtr') || (node[2][0] === 'binary' && ((node[2][2][0] === 'name' && node[2][2][1] === 'tempDoublePtr') || @@ -2427,7 +2434,12 @@ function eliminate(ast, memSafe) { if (allowTracking) track(name, node[3], node); } } else if (target[0] === 'sub') { - if (!isTempDoublePtrAccess(target) && !memoryInvalidated) { + if (isTempDoublePtrAccess(target)) { + if (!globalsInvalidated) { + invalidateGlobals(); + globalsInvalidated = true; + } + } else if (!memoryInvalidated) { invalidateMemory(); memoryInvalidated = true; } @@ -2687,6 +2699,7 @@ function eliminate(ast, memSafe) { } if (ifTrue[1][0] && ifTrue[1][0][0] === 'break') { var assigns = ifFalse[1]; + clearEmptyNodes(assigns); var loopers = [], helpers = []; for (var i = 0; i < assigns.length; i++) { if (assigns[i][0] === 'stat' && assigns[i][1][0] === 'assign') { @@ -3112,6 +3125,17 @@ function outline(ast) { parts = []; var curr = node; while (1) { + if (!curr[3]) { + // we normally expect ..if (cond) { .. } else [if (nextCond) {] (in [] is what we hope to see) + // but are now seeing ..if (cond) { .. } with no else. This might be + // ..if (cond) if (nextCond) { + // which vacuum can generate from if (cond) {} else if (nextCond), making it + // if (!cond) if (nextCond) + // so we undo that, in hopes of making it more flattenable + curr[3] = curr[2]; + curr[2] = ['block', []]; + curr[1] = simplifyNotCompsDirect(['unary-prefix', '!', curr[1]]); + } parts.push({ condition: curr[1], body: curr[2] }); curr = curr[3]; if (!curr) break; |