aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-01-11 21:30:03 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-01-11 21:30:03 -0800
commit08d261d183a6071f8d72ea9af05c59c152f28c95 (patch)
treed0540433fef13941e37c833eecf65d2b7f756a5b
parent5e107c8d5a10b74933f52cffaa27d0c01106dc60 (diff)
do not blow up the stack with lots of varargs
-rw-r--r--src/analyzer.js55
-rw-r--r--src/runtime.js3
-rw-r--r--tests/runner.py20
3 files changed, 61 insertions, 17 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 4aac53a8..6fd7ef66 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -788,26 +788,49 @@ function analyzer(data, sidePass) {
delete item.allocatedSize;
}
func.initialStack = index;
- // We need to note if stack allocations other than initial allocs can happen here
- // (for example, via alloca). If so, we need to rewind the stack when we leave.
func.otherStackAllocations = false;
- var finishedInitial = false;
- for (var i = 0; i < lines.length; i++) {
- var item = lines[i].value;
- if (!item || item.intertype != 'alloca') {
- finishedInitial = true;
- continue;
+ while (func.initialStack == 0) { // one-time loop with possible abort in the middle
+ // If there is no obvious need for stack management, perhaps we don't need it
+ // (we try to optimize that way with SKIP_STACK_IN_SMALL). However,
+ // we need to note if stack allocations other than initial allocs can happen here
+ // If so, we need to rewind the stack when we leave.
+
+ // By-value params are causes of additional allocas (although we could in theory make them normal allocas too)
+ func.params.forEach(function(param) {
+ if (param.byVal) {
+ func.otherStackAllocations = true;
+ }
+ });
+ if (func.otherStackAllocations) break;
+
+ // Allocas
+ var finishedInitial = false;
+ for (var i = 0; i < lines.length; i++) {
+ var item = lines[i].value;
+ if (!item || item.intertype != 'alloca') {
+ finishedInitial = true;
+ continue;
+ }
+ if (item.intertype == 'alloca' && finishedInitial) {
+ func.otherStackAllocations = true;
+ break;
+ }
}
- if (item.intertype == 'alloca' && finishedInitial) {
- func.otherStackAllocations = true;
+ if (func.otherStackAllocations) break;
+
+ // Varargs
+ for (var i = 0; i < lines.length; i++) {
+ var item = lines[i];
+ if (item.value) item = item.value;
+ if (item.intertype == 'call' && isVarArgsFunctionType(item.type)) {
+ func.otherStackAllocations = true;
+ break;
+ }
}
+ if (func.otherStackAllocations) break;
+
+ break;
}
- // by-value params are also causes of additional allocas (although we could in theory make them normal allocas too)
- func.params.forEach(function(param) {
- if (param.byVal) {
- func.otherStackAllocations = true;
- }
- });
});
this.forwardItem(data, 'Relooper');
}
diff --git a/src/runtime.js b/src/runtime.js
index 2b81258d..6439d0ed 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -34,7 +34,8 @@ var RuntimeGenerator = {
stackEnter: function(initial, force) {
if (initial === 0 && SKIP_STACK_IN_SMALL && !force) return '';
- var ret = 'var __stackBase__ = STACKTOP; STACKTOP += ' + initial;
+ var ret = 'var __stackBase__ = STACKTOP';
+ if (initial > 0) ret += '; STACKTOP += ' + initial;
if (USE_TYPED_ARRAYS == 2) {
assert(initial % QUANTUM_SIZE == 0);
if (ASSERTIONS) {
diff --git a/tests/runner.py b/tests/runner.py
index 18ce11af..dd11b950 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -1459,6 +1459,26 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
'''
self.do_run(src, 'sum:9780*')
+ # We should not blow up the stack with numerous varargs
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ void func(int i) {
+ printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i);
+ }
+ int main() {
+ for (int i = 0; i < 1024; i++)
+ func(i);
+ printf("ok!\n");
+ return 0;
+ }
+ '''
+ Settings.TOTAL_STACK = 1024
+ self.do_run(src, 'ok!')
+
def test_array2(self):
src = '''
#include <stdio.h>