diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-01-06 17:55:44 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-01-06 17:55:44 -0800 |
commit | 27adc83bb2454fc71149b3efdae93d9c323d3bac (patch) | |
tree | 70c993a70ca3fa7ef1fbd6a12d177cf772c09463 /src | |
parent | 638532d89fc586adc739eb535625971bd29c8a74 (diff) |
prevent stack from being exhausted due to allocas and byval arguments
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 20 | ||||
-rw-r--r-- | src/jsifier.js | 5 | ||||
-rw-r--r-- | src/runtime.js | 8 |
3 files changed, 27 insertions, 6 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 4ff5d2d9..7d99ab69 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -785,6 +785,26 @@ 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; + } + if (item.intertype == 'alloca' && finishedInitial) { + func.otherStackAllocations = true; + } + } + // 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/jsifier.js b/src/jsifier.js index a750f805..8a75e49f 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -505,7 +505,8 @@ function JSify(data, functionsOnly, givenFunctions) { + '}\n'; } - func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack) + ';\n'; + // Prepare the stack, if we need one. If we have other stack allocations, force the stack to be set up. + func.JS += ' ' + RuntimeGenerator.stackEnter(func.initialStack, func.otherStackAllocations) + ';\n'; // Make copies of by-value params // XXX It is not clear we actually need this. While without this we fail, it does look like @@ -907,7 +908,7 @@ function JSify(data, functionsOnly, givenFunctions) { return ret; }); makeFuncLineActor('return', function(item) { - var ret = RuntimeGenerator.stackExit(item.funcData.initialStack) + ';\n'; + var ret = RuntimeGenerator.stackExit(item.funcData.initialStack, item.funcData.otherStackAllocations) + ';\n'; if (PROFILE) { ret += 'if (PROFILING) { ' + 'PROFILING_NODE.time += Date.now() - __profilingStartTime__; ' diff --git a/src/runtime.js b/src/runtime.js index 76b01089..605de749 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -29,8 +29,8 @@ var RuntimeGenerator = { return ret; }, - stackEnter: function(initial) { - if (initial === 0 && SKIP_STACK_IN_SMALL) return ''; + stackEnter: function(initial, force) { + if (initial === 0 && SKIP_STACK_IN_SMALL && !force) return ''; if (USE_TYPED_ARRAYS === 2) initial = Runtime.forceAlign(initial); var ret = 'var __stackBase__ = STACKTOP; STACKTOP += ' + initial; if (ASSERTIONS) { @@ -42,8 +42,8 @@ var RuntimeGenerator = { return ret; }, - stackExit: function(initial) { - if (initial === 0 && SKIP_STACK_IN_SMALL) return ''; + stackExit: function(initial, force) { + if (initial === 0 && SKIP_STACK_IN_SMALL && !force) return ''; var ret = ''; if (SAFE_HEAP) { ret += 'for (var i = __stackBase__; i < STACKTOP; i++) SAFE_HEAP_CLEAR(i);'; |