aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-07-21 10:33:44 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-07-21 10:33:44 -0700
commitb11c3d7d5326bdbad7624e75a8bedfd8ade55a27 (patch)
treebe1be99fd039eef443374eeb9cdfa651b5150e97
parent0902d6c3707d3350f40a35ed04a9eb125f36fad5 (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.js41
-rw-r--r--tools/test-js-optimizer-asm-outline1-output.js40
-rw-r--r--tools/test-js-optimizer-asm-outline2-output.js29
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 {