diff options
author | Ryan Kelly <ryan@rfk.id.au> | 2014-01-28 20:20:28 +1100 |
---|---|---|
committer | Ryan Kelly <ryan@rfk.id.au> | 2014-02-02 08:49:42 +1100 |
commit | 47288a40ac04bc7f4fe9734a3b6160735b58f1b2 (patch) | |
tree | 17ee178b6d4713e346a12f130c72ad884ebb068e /tools | |
parent | b175281cb1d1e1a27339bddedfa6ff4fc0822fca (diff) |
Handle non-breaking case bodies in switch statement.
These don't actually flow through to the next case, but we have to
make sure they're properly closed in order to keep our invariants
in order.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/js-optimizer.js | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d12f4f4d..a3ed24d3 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2490,8 +2490,8 @@ function registerizeHarder(ast) { case 'switch': // Emscripten generates switch statements of a very limited // form: all case clauses are numeric literals, and all - // case bodies end with a break. So it's basically equivalent - // to a multi-way 'if' statement. + // case bodies end with a (maybe implicit) break. So it's + // basically equivalent to a multi-way 'if' statement. isInExpr++; buildFlowGraph(node[1]); isInExpr--; @@ -2501,20 +2501,22 @@ function registerizeHarder(ast) { var hasDefault = false; for (var i=0; i<node[2].length; i++) { setJunction(jCheckExit); + // All case clauses are either 'default' or a numeric literal. if (!node[2][i][0]) { hasDefault = true; - } else { - if (node[2][i][0][0] !== 'num') { - if (node[2][i][0][0] !== 'unary-prefix' || node[2][i][0][2][0] !== 'num') { - assert(false, 'non-numeric switch case clause'); - } - } - addPreCondTrue(['binary', '==', node[1], node[2][i][0]]); } for (var j = 0; j < node[2][i][1].length; j++) { buildFlowGraph(node[2][i][1][j]); } - assert(currEntryJunction === null, 'switch case body did not break'); + // Control flow will never actually reach the end of the case body. + // If there's live code here, assume it jumps to case exit. + if (currEntryJunction !== null && nextBasicBlock.nodes.length > 0) { + if (node[2][i][0]) { + markNonLocalJump('return'); + } else { + joinJunction(jExit); + } + } } // If there was no default case, we also need an empty block // linking straight from the test evaluation to the exit. |