aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-07-17 16:45:32 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-07-17 16:45:32 -0700
commit59553016250b4208ab28385933076950cf596998 (patch)
treedfeebace043aaa9020a5f86f9e9d1dc1d1142447
parentbb8442890f7e70c5c9fb94257fa6feef2aa8a023 (diff)
do not emit illegal breaks in seqs when outlining
-rw-r--r--tools/js-optimizer.js89
-rw-r--r--tools/test-js-optimizer-asm-outline1-output.js24
-rw-r--r--tools/test-js-optimizer-asm-outline2-output.js38
3 files changed, 92 insertions, 59 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 798fa855..a3b7db53 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -3137,47 +3137,56 @@ function outline(ast) {
// we need to capture all control flow using a top-level labeled one-time loop in the outlined function
var breakCapturers = 0;
var continueCapturers = 0;
- traverse(code, function(node, type) {
+ traverse(['block', code], function(node, type) { // traverse on dummy block, so we get the toplevel statements
// replace all break/continue/returns with code to break out of the main one-time loop, and set the control data
- if (type == 'return') {
- var ret = ['break', 'OL'];
- if (!node[1]) {
- ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', CONTROL_RETURN_VOID]), ret];
- } else {
- var type = detectAsmCoercion(node[1], asmData);
- ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', type == ASM_INT ? CONTROL_RETURN_INT : CONTROL_RETURN_DOUBLE]), ret];
- ret = ['seq', makeAssign(makeStackAccess(type, asmData.controlDataStackPos), node[1]), ret];
- }
- return ret;
- } else if (type == 'break') {
- var label = node[1] || 0;
- if (label == 'OL') return; // this was just added before us, it is new replacement code
- if (!label && breakCapturers > 0) return; // no label, and captured
- if (label && (label in codeInfo.labels)) return; // label, and defined in this code, so captured
- var ret = ['break', 'OL'];
- ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', label ? CONTROL_BREAK_LABEL : CONTROL_BREAK]), ret];
- if (label) {
- assert(label in codeInfo.breaks);
- ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', codeInfo.breaks[label]]), ret];
- }
- return ret;
- } else if (type == 'continue') {
- var label = node[1] || 0;
- if (!label && continueCapturers > 0) return; // no label, and captured
- if (label && (label in codeInfo.labels)) return; // label, and defined in this code, so captured
- var ret = ['break', 'OL'];
- ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', label ? CONTROL_CONTINUE_LABEL : CONTROL_CONTINUE]), ret];
- if (label) {
- assert(label in codeInfo.continues);
- ret = ['seq', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', codeInfo.continues[label]]), ret];
- }
- return ret;
- } else {
- if (type in BREAK_CAPTURERS) {
- breakCapturers++;
- }
- if (type in CONTINUE_CAPTURERS) {
- continueCapturers++;
+ if (type in BREAK_CAPTURERS) {
+ breakCapturers++;
+ }
+ if (type in CONTINUE_CAPTURERS) {
+ continueCapturers++;
+ }
+ var stats = node === code ? node : getStatements(node);
+ if (stats) {
+ for (var i = 0; i < stats.length; i++) {
+ var node = stats[i]; // step all over node and type here, for convenience
+ var type = node[0];
+ var ret = null;
+ if (type == 'return') {
+ ret = [];
+ if (!node[1]) {
+ ret.push(['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', CONTROL_RETURN_VOID])]);
+ } else {
+ var type = detectAsmCoercion(node[1], asmData);
+ ret.push(['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', type == ASM_INT ? CONTROL_RETURN_INT : CONTROL_RETURN_DOUBLE])]);
+ ret.push(['stat', makeAssign(makeStackAccess(type, asmData.controlDataStackPos), node[1])]);
+ }
+ ret.push(['stat', ['break', 'OL']]);
+ } else if (type == 'break') {
+ var label = node[1] || 0;
+ if (label == 'OL') continue; // this was just added before us, it is new replacement code
+ if (!label && breakCapturers > 0) continue; // no label, and captured
+ if (label && (label in codeInfo.labels)) continue; // label, and defined in this code, so captured
+ ret = [['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', label ? CONTROL_BREAK_LABEL : CONTROL_BREAK])]];
+ if (label) {
+ assert(label in codeInfo.breaks);
+ ret.push(['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', codeInfo.breaks[label]])]);
+ }
+ ret.push(['stat', ['break', 'OL']]);
+ } else if (type == 'continue') {
+ var label = node[1] || 0;
+ if (!label && continueCapturers > 0) continue; // no label, and captured
+ if (label && (label in codeInfo.labels)) continue; // label, and defined in this code, so captured
+ ret = [['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', label ? CONTROL_CONTINUE_LABEL : CONTROL_CONTINUE])]];
+ if (label) {
+ assert(label in codeInfo.continues);
+ ret.push(['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', codeInfo.continues[label]])]);
+ }
+ ret.push(['stat', ['break', 'OL']]);
+ }
+ if (ret) {
+ stats.splice.apply(stats, [i, 1].concat(ret));
+ i += ret.length-1;
+ }
}
}
}, function(node, type) {
diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js
index 6f1af8ca..b61dcf25 100644
--- a/tools/test-js-optimizer-asm-outline1-output.js
+++ b/tools/test-js-optimizer-asm-outline1-output.js
@@ -265,7 +265,9 @@ function lin3$0(sp) {
c(18);
c(19);
c(20);
- HEAP32[sp + 8 >> 2] = 10, HEAP32[sp + 0 >> 2] = 6, break OL;
+ HEAP32[sp + 0 >> 2] = 6;
+ HEAP32[sp + 8 >> 2] = 10;
+ break OL;
} while (0);
}
function lin3$1(sp) {
@@ -290,7 +292,8 @@ function lin4$0(sp) {
c(18);
c(19);
c(20);
- HEAP32[sp + 0 >> 2] = 1, break OL;
+ HEAP32[sp + 0 >> 2] = 1;
+ break OL;
} while (0);
}
function lin4$1(sp) {
@@ -315,7 +318,8 @@ function lin5$0(sp) {
c(18);
c(19);
c(20);
- HEAP32[sp + 0 >> 2] = 3, break OL;
+ HEAP32[sp + 0 >> 2] = 3;
+ break OL;
} while (0);
}
function lin5$1(sp) {
@@ -334,9 +338,12 @@ function mix$0(sp) {
OL : do {
c(16);
c(17);
- HEAP32[sp + 8 >> 2] = 2, HEAP32[sp + 0 >> 2] = 2, break OL;
+ HEAP32[sp + 0 >> 2] = 2;
+ HEAP32[sp + 8 >> 2] = 2;
+ break OL;
c(18);
- HEAP32[sp + 0 >> 2] = 1, break OL;
+ HEAP32[sp + 0 >> 2] = 1;
+ break OL;
while (1) {
break;
}
@@ -344,9 +351,12 @@ function mix$0(sp) {
break inner;
}
c(19);
- HEAP32[sp + 0 >> 2] = 3, break OL;
+ HEAP32[sp + 0 >> 2] = 3;
+ break OL;
c(20);
- HEAP32[sp + 8 >> 2] = 3, HEAP32[sp + 0 >> 2] = 4, break OL;
+ HEAP32[sp + 0 >> 2] = 4;
+ HEAP32[sp + 8 >> 2] = 3;
+ break OL;
} while (0);
}
function mix$1(sp) {
diff --git a/tools/test-js-optimizer-asm-outline2-output.js b/tools/test-js-optimizer-asm-outline2-output.js
index 3213ee4b..349246ab 100644
--- a/tools/test-js-optimizer-asm-outline2-output.js
+++ b/tools/test-js-optimizer-asm-outline2-output.js
@@ -400,7 +400,8 @@ function _free$0(sp) {
HEAP32[25] = $p_0;
HEAP32[$p_0 + 4 >> 2] = $220 | 1;
HEAP32[$189 + $220 >> 2] = $220;
- HEAP32[sp + 632 >> 2] = 5, break OL;
+ HEAP32[sp + 632 >> 2] = 5;
+ break OL;
}
$227 = ($194 & -8) + $psize_0 | 0;
L726 : do {
@@ -559,10 +560,12 @@ function _free$0(sp) {
HEAP32[$189 + $227 >> 2] = $227;
if (($p_0 | 0) != (HEAP32[25] | 0)) {
$psize_1 = $227;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
HEAP32[22] = $227;
- HEAP32[sp + 632 >> 2] = 5, break OL;
+ HEAP32[sp + 632 >> 2] = 5;
+ break OL;
} while (0);
HEAP32[sp + 248 >> 2] = $220;
HEAP32[sp + 256 >> 2] = $227;
@@ -620,13 +623,15 @@ function _free$1(sp) {
if ((HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & 3 | 0) != 3) {
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
HEAP32[22] = $26;
HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & -2;
HEAP32[$mem + ((-8 - $21 | 0) + 4) >> 2] = $26 | 1;
HEAP32[($mem + (($10 & -8) - 8) | 0) >> 2] = $26;
- HEAP32[sp + 632 >> 2] = 5, break OL;
+ HEAP32[sp + 632 >> 2] = 5;
+ break OL;
}
if ($21 >>> 0 < 256) {
$37 = HEAP32[$mem + ((-8 - $21 | 0) + 8) >> 2] | 0;
@@ -646,7 +651,8 @@ function _free$1(sp) {
HEAP32[20] = HEAP32[20] & (1 << ($21 >>> 3) ^ -1);
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
do {
if (($40 | 0) == (120 + ($21 >>> 3 << 1 << 2) | 0 | 0)) {
@@ -666,7 +672,8 @@ function _free$1(sp) {
HEAP32[$_pre_phi307 >> 2] = $37;
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
$69 = $mem + (-8 - $21 | 0) | 0;
$72 = HEAP32[$mem + ((-8 - $21 | 0) + 24) >> 2] | 0;
@@ -732,7 +739,8 @@ function _free$1(sp) {
if (($72 | 0) == 0) {
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
$120 = 384 + (HEAP32[($mem + ((-8 - $21 | 0) + 28) | 0) >> 2] << 2) | 0;
do {
@@ -744,7 +752,9 @@ function _free$1(sp) {
HEAP32[21] = HEAP32[21] & (1 << HEAP32[($mem + ((-8 - $21 | 0) + 28) | 0) >> 2] ^ -1);
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 640 >> 2] = 2, HEAP32[sp + 632 >> 2] = 2, break OL;
+ HEAP32[sp + 632 >> 2] = 2;
+ HEAP32[sp + 640 >> 2] = 2;
+ break OL;
} else {
if ($72 >>> 0 < (HEAP32[24] | 0) >>> 0) {
_abort();
@@ -757,7 +767,9 @@ function _free$1(sp) {
if (($R_1 | 0) == 0) {
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 640 >> 2] = 2, HEAP32[sp + 632 >> 2] = 2, break OL;
+ HEAP32[sp + 632 >> 2] = 2;
+ HEAP32[sp + 640 >> 2] = 2;
+ break OL;
}
}
} while (0);
@@ -781,7 +793,8 @@ function _free$1(sp) {
if (($164 | 0) == 0) {
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
if ($164 >>> 0 < (HEAP32[24] | 0) >>> 0) {
_abort();
@@ -790,7 +803,8 @@ function _free$1(sp) {
HEAP32[$164 + 24 >> 2] = $R_1;
$p_0 = $25;
$psize_0 = $26;
- HEAP32[sp + 632 >> 2] = 1, break OL;
+ HEAP32[sp + 632 >> 2] = 1;
+ break OL;
}
} while (0);
HEAP32[sp + 216 >> 2] = $p_0;