aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/js-optimizer.js54
-rw-r--r--tools/test-js-optimizer-asm-outline1-output.js46
2 files changed, 91 insertions, 9 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index edaaf28f..78439d61 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -3302,8 +3302,54 @@ function outline(ast) {
if (size >= sizeToOutline) {
aggressiveVariableElimination(func, asmData);
analyzeFunction(func, asmData);
- var ret = outlineStatements(func, asmData, getStatements(func), 0.5*size);
- if (ret && ret.length > 0) newFuncs.push.apply(newFuncs, ret);
+ var stats = getStatements(func);
+ var ret = outlineStatements(func, asmData, stats, 0.5*size);
+ if (ret && ret.length > 0) {
+ newFuncs.push.apply(newFuncs, ret);
+ // We have outlined. Add stack support
+ var extraSpace = asmData.stackSize;
+ if ('sp' in asmData.vars) {
+ // find stack bump (STACKTOP = STACKTOP + X | 0) and add the extra space
+ traverse(stats, function(node, type) {
+ if (type === 'assign' && node[2][0] === 'name' && node[2][1] === 'STACKTOP') {
+ var value = node[3];
+ assert(value[0] == 'binary' && value[1] == '|' && value[2][0] == 'name' && value[2][1] == 'STACKTOP' && value[3][0] == 'num');
+ value[3][1] += extraSpace;
+ return true;
+ }
+ });
+ } else {
+ // add sp variable and stack bump
+ var index = getFirstIndexInNormalized(func, asmData);
+ stats.splice(index, 0,
+ ['stat', makeAssign(['name', 'sp'], ['name', 'STACKTOP'])],
+ ['stat', makeAssign(['name', 'STACKTOP'], ['binary', '|', ['binary', '+', ['name', 'STACKTOP'], ['num', extraSpace]], ['num', 0]])]
+ );
+ asmData.vars.sp = ASM_INT; // no need to add to vars, we are about to denormalize anyhow
+ }
+ // pop the stack in returns
+ function makePop() {
+ return ['stat', makeAssign(['name', 'STACKTOP'], ['name', 'sp'])];
+ }
+ traverse(func, function(node, type) {
+ var stats = getStatements(node);
+ if (!stats) return;
+ for (var i = 0; i < stats.length; i++) {
+ var subNode = stats[i];
+ if (subNode[0] === 'stat') subNode = subNode[1];
+ if (subNode[0] == 'return') {
+ stats.splice(i, 0, makePop());
+ i++;
+ }
+ }
+ });
+ // pop the stack at the end if there is not a return
+ var last = stats[stats.length-1];
+ if (last[0] === 'stat') last = last[1];
+ if (last[0] !== 'return') {
+ stats.push(makePop());
+ }
+ }
}
denormalizeAsm(func, asmData);
});
@@ -3314,10 +3360,6 @@ function outline(ast) {
// after setting a state variable, etc.
if (newFuncs.length > 0) {
- // We have outlined. Add stack support: header in which we allocate enough stack space TODO
- // If sp was not present before, add it and before each return, pop the stack. also a final pop if not ending with a return TODO
- // (none of this should be done in inner functions, of course, just the original)
-
// add new functions to the toplevel, or create a toplevel if there isn't one
ast[1].push.apply(ast[1], newFuncs);
diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js
index 12607902..d279a045 100644
--- a/tools/test-js-optimizer-asm-outline1-output.js
+++ b/tools/test-js-optimizer-asm-outline1-output.js
@@ -1,12 +1,19 @@
function lin() {
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
c(1);
c(2);
c(3);
c(4);
lin$1(sp);
lin$0(sp);
+ STACKTOP = sp;
}
function lin2() {
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
while (1) {
c(1);
c(2);
@@ -15,8 +22,12 @@ function lin2() {
lin2$1(sp);
lin2$0(sp);
}
+ STACKTOP = sp;
}
function lin3() {
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
while (1) {
c(1);
c(2);
@@ -26,18 +37,25 @@ function lin3() {
lin3$1(sp);
lin3$0(sp);
if (HEAP32[sp + 0 >> 2] == 5) {
+ STACKTOP = sp;
return;
}
if (HEAP32[sp + 0 >> 2] == 6) {
+ STACKTOP = sp;
return HEAP32[sp + 8 >> 2];
}
if (HEAP32[sp + 0 >> 2] == 7) {
+ STACKTOP = sp;
return HEAPF32[sp + 8 >> 2];
}
}
+ STACKTOP = sp;
return 20;
}
function lin4() {
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
while (1) {
c(1);
c(2);
@@ -49,9 +67,13 @@ function lin4() {
break;
}
}
+ STACKTOP = sp;
return 20;
}
function lin5() {
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
while (1) {
c(1);
c(2);
@@ -63,9 +85,13 @@ function lin5() {
continue;
}
}
+ STACKTOP = sp;
return 20;
}
function mix() {
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
main : while (1) {
c(1);
c(2);
@@ -95,22 +121,29 @@ function mix() {
}
}
}
+ STACKTOP = sp;
return 20;
}
function vars(x, y) {
x = x | 0;
y = +y;
+ var sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
HEAP32[sp + 0 >> 2] = x;
HEAPF32[sp + 8 >> 2] = y;
vars$1(sp);
HEAP32[sp + 0 >> 2] = x;
HEAPF32[sp + 8 >> 2] = y;
vars$0(sp);
+ STACKTOP = sp;
}
function vars2(x, y) {
x = x | 0;
y = +y;
- var a = 0, b = +0;
+ var a = 0, b = +0, sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
a = x + y;
b = y * x;
a = c(1 + a);
@@ -120,11 +153,14 @@ function vars2(x, y) {
vars2$0(sp);
a = HEAP32[sp + 16 >> 2];
b = HEAPF32[sp + 24 >> 2];
+ STACKTOP = sp;
}
function vars3(x, y) {
x = x | 0;
y = +y;
- var a = 0;
+ var a = 0, sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
HEAP32[sp + 16 >> 2] = a;
HEAP32[sp + 0 >> 2] = x;
HEAPF32[sp + 8 >> 2] = y;
@@ -135,11 +171,14 @@ function vars3(x, y) {
HEAP32[sp + 0 >> 2] = x;
vars3$0(sp);
a = HEAP32[sp + 16 >> 2];
+ STACKTOP = sp;
}
function vars4(x, y) {
x = x | 0;
y = +y;
- var a = 0, b = +0;
+ var a = 0, b = +0, sp = 0;
+ sp = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
a = x + y;
HEAPF32[sp + 8 >> 2] = y;
HEAP32[sp + 0 >> 2] = x;
@@ -152,6 +191,7 @@ function vars4(x, y) {
vars4$0(sp);
a = HEAP32[sp + 16 >> 2];
b = HEAPF32[sp + 24 >> 2];
+ STACKTOP = sp;
}
function lin$0(sp) {
sp = sp | 0;