Bug 1644393 - Fix test case to work in beta/release builds r=sfink

This changes the test to be much more specific.

It adds a way of making gcslice only trigger a slice during an incremental collection, without which the collection loop can loop forever.

Differential Revision: https://phabricator.services.mozilla.com/D79136
This commit is contained in:
Jon Coppeard 2020-06-11 09:31:07 +00:00
Родитель bc84cbd3de
Коммит 925ac1a2d0
2 изменённых файлов: 49 добавлений и 20 удалений

Просмотреть файл

@ -1526,14 +1526,14 @@ static bool FinishGC(JSContext* cx, unsigned argc, Value* vp) {
static bool GCSlice(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() > 1) {
if (args.length() > 2) {
RootedObject callee(cx, &args.callee());
ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
return false;
}
auto budget = SliceBudget::unlimited();
if (args.length() == 1) {
if (args.length() >= 1) {
uint32_t work = 0;
if (!ToUint32(cx, args[0], &work)) {
return false;
@ -1541,11 +1541,21 @@ static bool GCSlice(JSContext* cx, unsigned argc, Value* vp) {
budget = SliceBudget(WorkBudget(work));
}
bool dontStart = false;
if (args.get(1).isObject()) {
RootedObject options(cx, &args[1].toObject());
RootedValue v(cx);
if (!JS_GetProperty(cx, options, "dontStart", &v)) {
return false;
}
dontStart = ToBoolean(v);
}
JSRuntime* rt = cx->runtime();
if (!rt->gc.isIncrementalGCInProgress()) {
rt->gc.startDebugGC(GC_NORMAL, budget);
} else {
if (rt->gc.isIncrementalGCInProgress()) {
rt->gc.debugGCSlice(budget);
} else if (!dontStart) {
rt->gc.startDebugGC(GC_NORMAL, budget);
}
args.rval().setUndefined();
@ -6156,8 +6166,12 @@ gc::ZealModeHelpText),
" Finish an in-progress incremental GC, if none is running then do nothing."),
JS_FN_HELP("gcslice", GCSlice, 1, 0,
"gcslice([n])",
" Start or continue an an incremental GC, running a slice that processes about n objects."),
"gcslice([n [, options]])",
" Start or continue an an incremental GC, running a slice that processes\n"
" about n objects. Takes an optional options object, which may contain the\n"
" following properties:\n"
" dontStart: do not start a new incremental GC if one is not already\n"
" running"),
JS_FN_HELP("abortgc", AbortGC, 1, 0,
"abortgc()",
@ -6512,7 +6526,7 @@ gc::ZealModeHelpText),
JS_FN_HELP("getBacktrace", GetBacktrace, 1, 0,
"getBacktrace([options])",
" Return the current stack as a string. Takes an optional options object,\n"
" which may contain any or all of the boolean properties\n"
" which may contain any or all of the boolean properties:\n"
" options.args - show arguments to each function\n"
" options.locals - show local variables in each frame\n"
" options.thisprops - show the properties of the 'this' object of each frame\n"),

Просмотреть файл

@ -1,21 +1,36 @@
// |jit-test| --enable-weak-refs; --no-ti
// |jit-test| --enable-weak-refs
for (let i = 70; i > 50; i--) {
gc();
gczeal(10, i);
for (let p of [false, true]) {
f(p);
f(true, false, false);
f(true, false, true);
// Run an incremental GC to completion.
startgc(1);
while (gcstate() !== 'NotActive') {
gcslice(10000, { dontStart: true });
}
}
function ccwToObject() {
return evalcx('({})', newGlobal({newCompartment: true}));
}
function f(x, y, z) {
let registry = new FinalizationRegistry(value => {});
let target = x ? ccwToObject() : {};
let heldValue = y ? ccwToObject() : {};
let token = z ? ccwToObject() : {};
registry.register(target, heldValue, token);
function ccwToRegistry() {
return evalcx('new FinalizationRegistry(value => {})',
newGlobal({newCompartment: true}));
}
function f(p) {
let registry = ccwToRegistry();
let target = ccwToObject();
registry.register(target, undefined);
// Add a CCW from registry to target zone or vice versa to control
// the order the zones are swept in.
if (p) {
registry.ptr = target;
} else {
target.ptr = registry;
}
gc();
}