mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 19:25:43 +00:00
Bug 1212469 - Make oomTest() into a shell function r=nbp
This commit is contained in:
parent
daef6b660b
commit
0bba2d39d5
@ -53,6 +53,25 @@ static bool fuzzingSafe = false;
|
||||
// OOM conditions.
|
||||
static bool disableOOMFunctions = false;
|
||||
|
||||
static bool
|
||||
EnvVarIsDefined(const char* name)
|
||||
{
|
||||
const char* value = getenv(name);
|
||||
return value && *value;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||
static bool
|
||||
EnvVarAsInt(const char* name, int* valueOut)
|
||||
{
|
||||
if (!EnvVarIsDefined(name))
|
||||
return false;
|
||||
|
||||
*valueOut = atoi(getenv(name));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
@ -1072,6 +1091,93 @@ ResetOOMFailure(JSContext* cx, unsigned argc, Value* vp)
|
||||
OOM_maxAllocations = UINT32_MAX;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
OOMTest(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (args.length() != 1 || !args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
|
||||
JS_ReportError(cx, "oomTest() takes a single function argument.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (disableOOMFunctions) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedFunction function(cx, &args[0].toObject().as<JSFunction>());
|
||||
|
||||
bool verbose = EnvVarIsDefined("OOM_VERBOSE");
|
||||
|
||||
unsigned threadStart = oom::THREAD_TYPE_MAIN;
|
||||
unsigned threadEnd = oom::THREAD_TYPE_MAX;
|
||||
|
||||
// Test a single thread type if specified by the OOM_THREAD environment variable.
|
||||
int threadOption = 0;
|
||||
if (EnvVarAsInt("OOM_THREAD", &threadOption)) {
|
||||
if (threadOption < oom::THREAD_TYPE_MAIN || threadOption > oom::THREAD_TYPE_MAX) {
|
||||
JS_ReportError(cx, "OOM_THREAD value out of range.");
|
||||
return false;
|
||||
}
|
||||
|
||||
threadStart = threadOption;
|
||||
threadEnd = threadOption + 1;
|
||||
}
|
||||
|
||||
JS_SetGCZeal(cx, 0, JS_DEFAULT_ZEAL_FREQ);
|
||||
|
||||
for (unsigned thread = threadStart; thread < threadEnd; thread++) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "thread %d\n", thread);
|
||||
|
||||
HelperThreadState().waitForAllThreads();
|
||||
js::oom::targetThread = thread;
|
||||
|
||||
unsigned allocation = 1;
|
||||
bool handledOOM;
|
||||
do {
|
||||
if (verbose)
|
||||
fprintf(stderr, " allocation %d\n", allocation);
|
||||
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
MOZ_ASSERT(!cx->runtime()->hadOutOfMemory);
|
||||
|
||||
OOM_maxAllocations = OOM_counter + allocation;
|
||||
OOM_failAlways = false;
|
||||
|
||||
RootedValue result(cx);
|
||||
bool ok = JS_CallFunction(cx, cx->global(), function,
|
||||
HandleValueArray::empty(), &result);
|
||||
|
||||
handledOOM = OOM_counter >= OOM_maxAllocations;
|
||||
OOM_maxAllocations = UINT32_MAX;
|
||||
|
||||
MOZ_ASSERT_IF(ok, !cx->isExceptionPending());
|
||||
MOZ_ASSERT_IF(!ok, cx->isExceptionPending());
|
||||
|
||||
// Note that it is possible that the function throws an exception
|
||||
// unconnected to OOM, in which case we ignore it. More correct
|
||||
// would be to have the caller pass some kind of exception
|
||||
// specification and to check the exception against it.
|
||||
|
||||
cx->clearPendingException();
|
||||
cx->runtime()->hadOutOfMemory = false;
|
||||
|
||||
allocation++;
|
||||
} while (handledOOM);
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, " finished after %d allocations\n", allocation - 2);
|
||||
}
|
||||
}
|
||||
|
||||
js::oom::targetThread = js::oom::THREAD_TYPE_NONE;
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const js::Class FakePromiseClass = {
|
||||
@ -3062,6 +3168,12 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
"resetOOMFailure()",
|
||||
" Remove the allocation failure scheduled by either oomAfterAllocations() or\n"
|
||||
" oomAtAllocation() and return whether any allocation had been caused to fail."),
|
||||
|
||||
JS_FN_HELP("oomTest", OOMTest, 0, 0,
|
||||
"oomTest(function)",
|
||||
" Test that the passed function behaves correctly under OOM conditions by\n"
|
||||
" repeatedly executing it and simulating allocation failure at successive\n"
|
||||
" allocations until the function completes without seeing a failure."),
|
||||
#endif
|
||||
|
||||
JS_FN_HELP("makeFakePromise", MakeFakePromise, 0, 0,
|
||||
@ -3464,7 +3576,7 @@ js::DefineTestingFunctions(JSContext* cx, HandleObject obj, bool fuzzingSafe_,
|
||||
bool disableOOMFunctions_)
|
||||
{
|
||||
fuzzingSafe = fuzzingSafe_;
|
||||
if (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0')
|
||||
if (EnvVarIsDefined("MOZ_FUZZING_SAFE"))
|
||||
fuzzingSafe = true;
|
||||
|
||||
disableOOMFunctions = disableOOMFunctions_;
|
||||
|
@ -1,39 +0,0 @@
|
||||
// Function to test OOM handling by repeatedly calling a function and failing
|
||||
// successive allocations.
|
||||
|
||||
if (!("oomAtAllocation" in this && "resetOOMFailure" in this && "oomThreadTypes" in this))
|
||||
quit();
|
||||
|
||||
if ("gczeal" in this)
|
||||
gczeal(0);
|
||||
|
||||
const verbose = ("os" in this) && os.getenv("OOM_VERBOSE");
|
||||
|
||||
// Test out of memory handing by calling a function f() while causing successive
|
||||
// memory allocations to fail. Repeat until f() finishes without reaching the
|
||||
// failing allocation.
|
||||
function oomTest(f) {
|
||||
for (let thread = 1; thread < oomThreadTypes(); thread++) {
|
||||
if (verbose)
|
||||
print("testing thread " + thread);
|
||||
|
||||
var i = 1;
|
||||
var more;
|
||||
do {
|
||||
if (verbose)
|
||||
print("fail at " + i);
|
||||
try {
|
||||
oomAtAllocation(i, thread);
|
||||
f();
|
||||
more = resetOOMFailure();
|
||||
} catch (e) {
|
||||
// Ignore exceptions.
|
||||
more = resetOOMFailure();
|
||||
}
|
||||
i++;
|
||||
} while(more);
|
||||
|
||||
if (verbose)
|
||||
print("finished after " + (i - 2) + " failures");
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
// |jit-test| --no-ion
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
var g = newGlobal();
|
||||
oomTest(function() {
|
||||
Debugger(g);
|
||||
|
@ -1,2 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest((function(x) { assertEq(x + y + ex, 25); }));
|
||||
|
@ -1,6 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
|
||||
if (helperThreadCount() === 0)
|
||||
if (!('oomTest' in this) || helperThreadCount() === 0)
|
||||
quit(0);
|
||||
|
||||
var lfGlobal = newGlobal();
|
||||
|
@ -1,2 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => getBacktrace({args: oomTest[load+1], locals: true, thisprops: true}));
|
||||
|
@ -1,2 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => parseModule('import v from "mod";'));
|
||||
|
@ -1,4 +1,5 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => {
|
||||
try {
|
||||
|
@ -1,4 +1,5 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
function arrayProtoOutOfRange() {
|
||||
function f(obj) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
var g = newGlobal();
|
||||
oomTest(() => Debugger(g));
|
||||
|
@ -1,4 +1,5 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => {
|
||||
let x = 0;
|
||||
|
@ -1,2 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => getBacktrace({args: true, locals: true, thisprops: true}));
|
||||
|
@ -1,3 +1,5 @@
|
||||
// |jit-test| allow-oom; allow-unhandlable-oom; --no-threads
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => getBacktrace({thisprops: gc() && delete addDebuggee.enabled}));
|
||||
|
@ -1,2 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(newGlobal);
|
||||
|
@ -1,4 +1,6 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
function parseAsmJS() {
|
||||
eval(`function m(stdlib)
|
||||
{
|
||||
|
@ -1,2 +1,4 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => eval("function f() {}"));
|
||||
|
@ -1,3 +1,5 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(() => assertEq("foobar\xff5baz\u1200".search(/bar\u0178\d/i), 3));
|
||||
oomTest(() => assertEq((/(?!(?!(?!6)[\Wc]))/i).test(), false));
|
||||
|
@ -1,4 +1,6 @@
|
||||
load(libdir + 'oomTest.js');
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
oomTest(function () {
|
||||
eval(`var wm = new WeakMap();
|
||||
wm.set({}, 'FOO').get(false);`);
|
||||
|
@ -1,5 +1,6 @@
|
||||
// |jit-test| slow;
|
||||
load(libdir + "oomTest.js");
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
enableSPSProfiling();
|
||||
var lfGlobal = newGlobal();
|
||||
|
Loading…
Reference in New Issue
Block a user