diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-07-21 10:33:44 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-07-21 10:33:44 -0700 |
commit | b11c3d7d5326bdbad7624e75a8bedfd8ade55a27 (patch) | |
tree | be1be99fd039eef443374eeb9cdfa651b5150e97 | |
parent | 0902d6c3707d3350f40a35ed04a9eb125f36fad5 (diff) |
fix semantics of control variable handling in outlining: zero out when calling outlined funcitons, and right after using the value, so that we can handle nested outlined calls
-rw-r--r-- | tools/js-optimizer.js | 41 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline1-output.js | 40 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-outline2-output.js | 29 |
3 files changed, 81 insertions, 29 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 87851b1b..055cf7e8 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -3012,6 +3012,8 @@ function outline(ast) { asmData.stackPos[stack[i]] = stackSize + i*8; } // Reserve an extra two spots: one for control flow var, the other for control flow data + // The control variables are zeroed out when calling an outlined function, and after using + // the value after they return. asmData.extraStackSize = (stack.length + 2)*8; asmData.controlStackPos = stackSize + asmData.extraStackSize - 16; asmData.controlDataStackPos = stackSize + asmData.extraStackSize - 8; @@ -3217,34 +3219,49 @@ function outline(ast) { } }); code = [['label', 'OL', ['do', ['num', 0], ['block', code]]]]; // do this after processing, to not confuse breakCapturers etc. - // read the control data at the callsite to the outlined function + // read the control data at the callsite to the outlined function, and clear the control values + reps.push(['stat', makeAssign( + ['name', 'tempValue'], + makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT) + )]); + reps.push(['stat', makeAssign( + ['name', 'tempInt'], + makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ASM_INT) + )]); + reps.push(['stat', makeAssign( + ['name', 'tempDouble'], + makeAsmCoercion(makeStackAccess(ASM_DOUBLE, asmData.controlDataStackPos), ASM_DOUBLE) + )]); + reps.push(['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlStackPos), ['num', 0])]); + reps.push(['stat', makeAssign(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ['num', 0])]); // XXX not really needed + // use the control data information if (codeInfo.hasReturn) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_RETURN_VOID]), + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_RETURN_VOID]), [['stat', ['return']]] )); } if (codeInfo.hasReturnInt) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_RETURN_INT]), - [['stat', ['return', makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ASM_INT)]]] + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_RETURN_INT]), + [['stat', ['return', makeAsmCoercion(['name', 'tempInt'], ASM_INT)]]] )); } if (codeInfo.hasReturnDouble) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_RETURN_DOUBLE]), - [['stat', ['return', makeAsmCoercion(makeStackAccess(ASM_DOUBLE, asmData.controlDataStackPos), ASM_DOUBLE)]]] + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_RETURN_DOUBLE]), + [['stat', ['return', makeAsmCoercion(['name', 'tempDouble'], ASM_DOUBLE)]]] )); } if (codeInfo.hasBreak) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_BREAK]), + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_BREAK]), [['stat', ['break']]] )); if (keys(codeInfo.breaks).length > 0) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_BREAK_LABEL]), - [makeSwitch(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ASM_INT), keys(codeInfo.breaks).map(function(key) { + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_BREAK_LABEL]), + [makeSwitch(makeAsmCoercion(['name', 'tempInt'], ASM_INT), keys(codeInfo.breaks).map(function(key) { var id = codeInfo.breaks[key]; return [['num', id], [['block', [['stat', ['break', key]]]]]]; }))] @@ -3253,13 +3270,13 @@ function outline(ast) { } if (codeInfo.hasContinue) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_CONTINUE]), + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_CONTINUE]), [['stat', ['continue']]] )); if (keys(codeInfo.continues).length > 0) { reps.push(makeIf( - makeComparison(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlStackPos), ASM_INT), '==', ['num', CONTROL_CONTINUE_LABEL]), - [makeSwitch(makeAsmCoercion(makeStackAccess(ASM_INT, asmData.controlDataStackPos), ASM_INT), keys(codeInfo.continues).map(function(key) { + makeComparison(makeAsmCoercion(['name', 'tempValue'], ASM_INT), '==', ['num', CONTROL_CONTINUE_LABEL]), + [makeSwitch(makeAsmCoercion(['name', 'tempInt'], ASM_INT), keys(codeInfo.continues).map(function(key) { var id = codeInfo.continues[key]; return [['num', id], [['block', [['stat', ['continue', key]]]]]]; }))] diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js index 9f4790de..6ef32f54 100644 --- a/tools/test-js-optimizer-asm-outline1-output.js +++ b/tools/test-js-optimizer-asm-outline1-output.js @@ -48,9 +48,14 @@ function lin3() { HEAP32[sp + 0 >> 2] = 0; HEAP32[sp + 8 >> 2] = 0; sp = lin3$0(sp) | 0; - if ((HEAP32[sp + 0 >> 2] | 0) == 6) { + tempValue = HEAP32[sp + 0 >> 2] | 0; + tempInt = HEAP32[sp + 8 >> 2] | 0; + tempDouble = +HEAPF32[sp + 8 >> 2]; + HEAP32[sp + 0 >> 2] = 0; + HEAP32[sp + 8 >> 2] = 0; + if ((tempValue | 0) == 6) { STACKTOP = sp; - return HEAP32[sp + 8 >> 2] | 0; + return tempInt | 0; } } STACKTOP = sp; @@ -71,7 +76,12 @@ function lin4() { HEAP32[sp + 0 >> 2] = 0; HEAP32[sp + 8 >> 2] = 0; sp = lin4$0(sp) | 0; - if ((HEAP32[sp + 0 >> 2] | 0) == 1) { + tempValue = HEAP32[sp + 0 >> 2] | 0; + tempInt = HEAP32[sp + 8 >> 2] | 0; + tempDouble = +HEAPF32[sp + 8 >> 2]; + HEAP32[sp + 0 >> 2] = 0; + HEAP32[sp + 8 >> 2] = 0; + if ((tempValue | 0) == 1) { break; } } @@ -93,7 +103,12 @@ function lin5() { HEAP32[sp + 0 >> 2] = 0; HEAP32[sp + 8 >> 2] = 0; sp = lin5$0(sp) | 0; - if ((HEAP32[sp + 0 >> 2] | 0) == 3) { + tempValue = HEAP32[sp + 0 >> 2] | 0; + tempInt = HEAP32[sp + 8 >> 2] | 0; + tempDouble = +HEAPF32[sp + 8 >> 2]; + HEAP32[sp + 0 >> 2] = 0; + HEAP32[sp + 8 >> 2] = 0; + if ((tempValue | 0) == 3) { continue; } } @@ -118,22 +133,27 @@ function mix() { HEAP32[sp + 0 >> 2] = 0; HEAP32[sp + 8 >> 2] = 0; sp = mix$0(sp) | 0; - if ((HEAP32[sp + 0 >> 2] | 0) == 1) { + tempValue = HEAP32[sp + 0 >> 2] | 0; + tempInt = HEAP32[sp + 8 >> 2] | 0; + tempDouble = +HEAPF32[sp + 8 >> 2]; + HEAP32[sp + 0 >> 2] = 0; + HEAP32[sp + 8 >> 2] = 0; + if ((tempValue | 0) == 1) { break; } - if ((HEAP32[sp + 0 >> 2] | 0) == 2) { - switch (HEAP32[sp + 8 >> 2] | 0) { + if ((tempValue | 0) == 2) { + switch (tempInt | 0) { case 2: { break main; } } } - if ((HEAP32[sp + 0 >> 2] | 0) == 3) { + if ((tempValue | 0) == 3) { continue; } - if ((HEAP32[sp + 0 >> 2] | 0) == 4) { - switch (HEAP32[sp + 8 >> 2] | 0) { + if ((tempValue | 0) == 4) { + switch (tempInt | 0) { case 3: { continue main; diff --git a/tools/test-js-optimizer-asm-outline2-output.js b/tools/test-js-optimizer-asm-outline2-output.js index 72e219ad..4b7bb6e2 100644 --- a/tools/test-js-optimizer-asm-outline2-output.js +++ b/tools/test-js-optimizer-asm-outline2-output.js @@ -60,14 +60,19 @@ function _free($mem) { sp = _free$1(sp) | 0; $p_0 = HEAP32[sp + 216 >> 2] | 0; $psize_0 = HEAP32[sp + 208 >> 2] | 0; - if ((HEAP32[sp + 632 >> 2] | 0) == 5) { + tempValue = HEAP32[sp + 632 >> 2] | 0; + tempInt = HEAP32[sp + 640 >> 2] | 0; + tempDouble = +HEAPF32[sp + 640 >> 2]; + HEAP32[sp + 632 >> 2] = 0; + HEAP32[sp + 640 >> 2] = 0; + if ((tempValue | 0) == 5) { return; } - if ((HEAP32[sp + 632 >> 2] | 0) == 1) { + if ((tempValue | 0) == 1) { break; } - if ((HEAP32[sp + 632 >> 2] | 0) == 2) { - switch (HEAP32[sp + 640 >> 2] | 0) { + if ((tempValue | 0) == 2) { + switch (tempInt | 0) { case 2: { break L621; @@ -97,7 +102,12 @@ function _free($mem) { HEAP32[sp + 0 >> 2] = $mem; HEAP32[sp + 16 >> 2] = $10; sp = _free$2(sp) | 0; - if ((HEAP32[sp + 632 >> 2] | 0) == 5) { + tempValue = HEAP32[sp + 632 >> 2] | 0; + tempInt = HEAP32[sp + 640 >> 2] | 0; + tempDouble = +HEAPF32[sp + 640 >> 2]; + HEAP32[sp + 632 >> 2] = 0; + HEAP32[sp + 640 >> 2] = 0; + if ((tempValue | 0) == 5) { return; } } @@ -569,11 +579,16 @@ function _free$2(sp) { HEAP32[sp + 416 >> 2] = $psize_1; sp = _free$0(sp) | 0; $psize_1 = HEAP32[sp + 416 >> 2] | 0; - if ((HEAP32[sp + 632 >> 2] | 0) == 5) { + tempValue = HEAP32[sp + 632 >> 2] | 0; + tempInt = HEAP32[sp + 640 >> 2] | 0; + tempDouble = +HEAPF32[sp + 640 >> 2]; + HEAP32[sp + 632 >> 2] = 0; + HEAP32[sp + 640 >> 2] = 0; + if ((tempValue | 0) == 5) { HEAP32[sp + 632 >> 2] = 5; break OL; } - if ((HEAP32[sp + 632 >> 2] | 0) == 1) { + if ((tempValue | 0) == 1) { break; } } else { |