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.
|
// OOM conditions.
|
||||||
static bool disableOOMFunctions = false;
|
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
|
static bool
|
||||||
GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
|
GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
@ -1072,6 +1091,93 @@ ResetOOMFailure(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
OOM_maxAllocations = UINT32_MAX;
|
OOM_maxAllocations = UINT32_MAX;
|
||||||
return true;
|
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
|
#endif
|
||||||
|
|
||||||
static const js::Class FakePromiseClass = {
|
static const js::Class FakePromiseClass = {
|
||||||
@ -3062,6 +3168,12 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
|||||||
"resetOOMFailure()",
|
"resetOOMFailure()",
|
||||||
" Remove the allocation failure scheduled by either oomAfterAllocations() or\n"
|
" Remove the allocation failure scheduled by either oomAfterAllocations() or\n"
|
||||||
" oomAtAllocation() and return whether any allocation had been caused to fail."),
|
" 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
|
#endif
|
||||||
|
|
||||||
JS_FN_HELP("makeFakePromise", MakeFakePromise, 0, 0,
|
JS_FN_HELP("makeFakePromise", MakeFakePromise, 0, 0,
|
||||||
@ -3464,7 +3576,7 @@ js::DefineTestingFunctions(JSContext* cx, HandleObject obj, bool fuzzingSafe_,
|
|||||||
bool disableOOMFunctions_)
|
bool disableOOMFunctions_)
|
||||||
{
|
{
|
||||||
fuzzingSafe = fuzzingSafe_;
|
fuzzingSafe = fuzzingSafe_;
|
||||||
if (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0')
|
if (EnvVarIsDefined("MOZ_FUZZING_SAFE"))
|
||||||
fuzzingSafe = true;
|
fuzzingSafe = true;
|
||||||
|
|
||||||
disableOOMFunctions = disableOOMFunctions_;
|
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
|
// |jit-test| --no-ion
|
||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
var g = newGlobal();
|
var g = newGlobal();
|
||||||
oomTest(function() {
|
oomTest(function() {
|
||||||
Debugger(g);
|
Debugger(g);
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest((function(x) { assertEq(x + y + ex, 25); }));
|
oomTest((function(x) { assertEq(x + y + ex, 25); }));
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this) || helperThreadCount() === 0)
|
||||||
|
|
||||||
if (helperThreadCount() === 0)
|
|
||||||
quit(0);
|
quit(0);
|
||||||
|
|
||||||
var lfGlobal = newGlobal();
|
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}));
|
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";'));
|
oomTest(() => parseModule('import v from "mod";'));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest(() => {
|
oomTest(() => {
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
function arrayProtoOutOfRange() {
|
function arrayProtoOutOfRange() {
|
||||||
function f(obj) {
|
function f(obj) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
var g = newGlobal();
|
var g = newGlobal();
|
||||||
oomTest(() => Debugger(g));
|
oomTest(() => Debugger(g));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest(() => {
|
oomTest(() => {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest(() => getBacktrace({args: true, locals: true, thisprops: true}));
|
oomTest(() => getBacktrace({args: true, locals: true, thisprops: true}));
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
// |jit-test| allow-oom; allow-unhandlable-oom; --no-threads
|
// |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}));
|
oomTest(() => getBacktrace({thisprops: gc() && delete addDebuggee.enabled}));
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest(newGlobal);
|
oomTest(newGlobal);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
function parseAsmJS() {
|
function parseAsmJS() {
|
||||||
eval(`function m(stdlib)
|
eval(`function m(stdlib)
|
||||||
{
|
{
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest(() => eval("function f() {}"));
|
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("foobar\xff5baz\u1200".search(/bar\u0178\d/i), 3));
|
||||||
oomTest(() => assertEq((/(?!(?!(?!6)[\Wc]))/i).test(), false));
|
oomTest(() => assertEq((/(?!(?!(?!6)[\Wc]))/i).test(), false));
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
load(libdir + 'oomTest.js');
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
oomTest(function () {
|
oomTest(function () {
|
||||||
eval(`var wm = new WeakMap();
|
eval(`var wm = new WeakMap();
|
||||||
wm.set({}, 'FOO').get(false);`);
|
wm.set({}, 'FOO').get(false);`);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// |jit-test| slow;
|
// |jit-test| slow;
|
||||||
load(libdir + "oomTest.js");
|
if (!('oomTest' in this))
|
||||||
|
quit();
|
||||||
|
|
||||||
enableSPSProfiling();
|
enableSPSProfiling();
|
||||||
var lfGlobal = newGlobal();
|
var lfGlobal = newGlobal();
|
||||||
|
Loading…
Reference in New Issue
Block a user