aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/js-optimizer.js41
-rw-r--r--tools/test-js-optimizer-asm-regs-harder-output.js28
2 files changed, 26 insertions, 43 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 78676681..abb854c6 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -2460,55 +2460,40 @@ function registerizeHarder(ast) {
buildFlowGraph(node[2]);
break;
case 'switch':
- // This is horrific. It need to capture the default flow-through
- // logic of sequential case bodies, as well as the theoretical
- // sequential evaluation of each case clause.
- // TODO: simplify based on asmjs switch-statement restrictions.
+ // 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.
isInExpr++;
buildFlowGraph(node[1]);
isInExpr--;
var jCheckExit = markJunction();
var jExit = addJunction();
pushActiveLabels(null, jExit);
- // Process all cases as a sequential chain of checks.
- // Process all case bodies as one big flow-through statement.
- // They might break themselves out of it but this implements the
- // default fall-through case logic.
var hasDefault = false;
- var jPrevCaseExit = jCheckExit;
- var jPrevBodyExit = jCheckExit;
for (var i=0; i<node[2].length; i++) {
- // In the general case we'll need a basic block for the case clause.
- // Try to avoid it for common, simple, non-var-using cases.
+ setJunction(jCheckExit);
if (!node[2][i][0]) {
hasDefault = true;
} else {
if (node[2][i][0][0] !== 'num') {
- setJunction(jPrevCaseExit);
- isInExpr++;
- buildFlowGraph(node[2][i][0]);
- isInExpr--;
- jPrevCaseExit = markJunction();
+ if (node[2][i][0][0] !== 'unary-prefix' || node[2][i][0][2][0] !== 'num') {
+ assert(false, 'non-numeric switch case clause');
+ }
}
- }
- // The next case body flows from the exit of the prev one,
- // or may be entered directly from the case statement exit.
- setJunction(jPrevCaseExit);
- if (jPrevBodyExit !== jCheckExit) {
- joinJunction(jPrevBodyExit);
+ 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]);
}
- jPrevBodyExit = markJunction();
+ if (currEntryJunction !== null, 'switch case body did not break');
}
- markJunction(jExit);
// If there was no default case, we also need an empty block
- // linking straight from entry to exit.
- if (!hasDefault && jCheckExit !== jPrevBodyExit) {
+ // linking straight from the test evaluation to the exit.
+ if (!hasDefault) {
setJunction(jCheckExit);
- joinJunction(jExit);
}
+ markJunction(jExit);
popActiveLabels()
break;
case 'return':
diff --git a/tools/test-js-optimizer-asm-regs-harder-output.js b/tools/test-js-optimizer-asm-regs-harder-output.js
index 710018bb..448fb67a 100644
--- a/tools/test-js-optimizer-asm-regs-harder-output.js
+++ b/tools/test-js-optimizer-asm-regs-harder-output.js
@@ -37,31 +37,29 @@ function switchey(d1, i2) {
}
}
function switchey2() {
- var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, d7 = +0, d8 = +0;
+ var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, d6 = +0, d7 = +0;
i2 = STACKTOP;
STACKTOP = STACKTOP + 8 | 0;
- i6 = 1;
- while (1) switch (i6 | 0) {
+ i3 = 1;
+ while (1) switch (i3 | 0) {
case 1:
i1 = i2 | 0;
__ZN6RandomC1Ev(i1);
i4 = 0;
- i3 = 0;
- i6 = 2;
+ i5 = 0;
+ i3 = 2;
break;
case 2:
- d8 = +__ZN6Random3getEf(8, +1);
- d7 = +__ZN6Random3getEf(i1, +1);
- _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d8, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d7, tempInt) | 0);
- i5 = (d8 != d7 & 1) + i3 | 0;
- i6 = i4 + 1 | 0;
- if ((i6 | 0) < 100) {
- i4 = i6;
- i3 = i5;
- i6 = 2;
+ d7 = +__ZN6Random3getEf(8, +1);
+ d6 = +__ZN6Random3getEf(i1, +1);
+ _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d7, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d6, tempInt) | 0);
+ i5 = (d7 != d6 & 1) + i5 | 0;
+ i4 = i4 + 1 | 0;
+ if ((i4 | 0) < 100) {
+ i3 = 2;
break;
} else {
- i6 = 3;
+ i3 = 3;
break;
}
case 3: