blob: 8c8bc85899342869237780a1d09fce17d0fb8b60 [file] [log] [blame]
//@ skip
description("Regression test for https://webkit.org/b/141098. Make sure eval() properly handles running out of stack space. This test should run without crashing.");
// The tiering up to test higher levels of optimization will only test the DFG
// if run in run-jsc-stress-tests with the eager settings.
// countStart, countIncrement, and numberOfFramesToBackoffFromStackOverflowPoint were
// empirically determined to be the values that will cause StackOverflowErrors to be
// thrown where the tests expects them. If stack frame layouts change sufficiently (e.g.
// due to JIT changes) such that this test starts failing (due to text output
// differences), then these values will need to be rebased.
// Under no circumstance should this test ever crash.
let countStart = 2;
let countIncrement = 8;
let numberOfFramesToBackoffFromStackOverflowPoint = 10;
// backoffEverything is chosen to be -1 because a negative number will never be
// decremented to 0, and hence, will cause probeAndRecurse() to return out of every
// frame instead of retrying the eval test.
let backoffEverything = -1;
var lastEvalString = "";
function testEval(maxIterations)
{
var result;
var count = countStart;
if (!maxIterations)
var result = eval(lastEvalString);
else {
for (var iter = 0; iter < maxIterations; count *= countIncrement, iter++) {
var evalString = "\"dummy\".valueOf(";
for (var i = 0; i < count; i++) {
if (i > 0)
evalString += ", ";
evalString += i;
}
evalString += ");";
if (maxIterations > 1)
lastEvalString = evalString;
result = eval(evalString);
}
}
return result;
}
function probeAndRecurse(reuseEvalString)
{
var framesToBackOffFromStackOverflowPoint;
// Probe stack depth
try {
remainingFramesToBackOff = probeAndRecurse(reuseEvalString);
if (!remainingFramesToBackOff) {
// We've backed off a number of frames. Now retry the eval test to see if we
// still overflow.
try {
testEval(1);
} catch (e) {
// Yikes. We still overflow. Back off some more.
return numberOfFramesToBackoffFromStackOverflowPoint;
}
} else
return remainingFramesToBackOff - 1
} catch (e) {
// We exceeded stack space, now return up the stack until we can execute a simple eval.
// Then run an eval test to exceed stack.
return numberOfFramesToBackoffFromStackOverflowPoint;
}
try {
testEval(reuseEvalString ? 0 : 20);
} catch (e) {
testPassed("Exception: " + e);
}
return backoffEverything;
}
// Because this test intentionally exhausts the stack, we call testPassed() to ensure
// everything we need in that path has been compiled and is available. Otherwise we
// might properly handle an out of stack, but run out of stack calling testPassed().
testPassed("Initial setup");
debug("Starting 1st probeAndRecurse");
probeAndRecurse(false);
// Tier up the eval'ed code.
// When run with run-jsc-stress-tests and it's agressive options, this low of a count will
// allow us to get up to the DFG.
for (var i = 0; i < 200; i++)
testEval(0);
debug("Starting 2nd probeAndRecurse");
probeAndRecurse(true);