diff options
-rw-r--r-- | tools/js-optimizer.js | 89 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline1-output.js | 24 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline2-output.js | 38 |
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; |