Bug 742570 - Improve GC testing functions (r=igor)

This commit is contained in:
Bill McCloskey 2012-04-03 14:07:38 -07:00
parent 714dde6b82
commit 6090417a56
4 changed files with 62 additions and 16 deletions

View File

@ -21,19 +21,30 @@ using namespace JS;
static JSBool
GC(JSContext *cx, unsigned argc, jsval *vp)
{
JSCompartment *comp = NULL;
/*
* If the first argument is 'compartment', we collect any compartments
* previously scheduled for GC via schedulegc. If the first argument is an
* object, we collect the object's compartment (any any other compartments
* scheduled for GC). Otherwise, we collect call compartments.
*/
JSBool compartment = false;
if (argc == 1) {
Value arg = vp[2];
if (arg.isObject())
comp = UnwrapObject(&arg.toObject())->compartment();
if (arg.isString()) {
if (!JS_StringEqualsAscii(cx, arg.toString(), "compartment", &compartment))
return false;
} else if (arg.isObject()) {
PrepareCompartmentForGC(UnwrapObject(&arg.toObject())->compartment());
compartment = true;
}
}
#ifndef JS_MORE_DETERMINISTIC
size_t preBytes = cx->runtime->gcBytes;
#endif
if (comp)
PrepareCompartmentForGC(comp);
if (compartment)
PrepareForDebugGC(cx->runtime);
else
PrepareForFullGC(cx->runtime);
GCForReason(cx, gcreason::API);
@ -177,16 +188,24 @@ GCZeal(JSContext *cx, unsigned argc, jsval *vp)
static JSBool
ScheduleGC(JSContext *cx, unsigned argc, jsval *vp)
{
uint32_t count;
if (argc != 1) {
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
return JS_FALSE;
}
if (!JS_ValueToECMAUint32(cx, vp[2], &count))
return JS_FALSE;
JS_ScheduleGC(cx, count);
Value arg(vp[2]);
if (arg.isInt32()) {
/* Schedule a GC to happen after |arg| allocations. */
JS_ScheduleGC(cx, arg.toInt32());
} else if (arg.isObject()) {
/* Ensure that |comp| is collected during the next GC. */
JSCompartment *comp = UnwrapObject(&arg.toObject())->compartment();
PrepareCompartmentForGC(comp);
} else if (arg.isString()) {
/* This allows us to schedule atomsCompartment for GC. */
PrepareCompartmentForGC(arg.toString()->compartment());
}
*vp = JSVAL_VOID;
return JS_TRUE;
}
@ -473,8 +492,10 @@ Terminate(JSContext *cx, unsigned arg, jsval *vp)
static JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj])",
" Run the garbage collector. When obj is given, GC only its compartment."),
"gc([obj] | 'compartment')",
" Run the garbage collector. When obj is given, GC only its compartment.\n"
" If 'compartment' is given, GC any compartments that were scheduled for\n"
" GC via schedulegc."),
JS_FN_HELP("gcparam", GCParameter, 2, 0,
"gcparam(name [, value])",
@ -511,8 +532,9 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
" Period specifies that collection happens every n allocations.\n"),
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
"schedulegc(num)",
" Schedule a GC to happen after num allocations."),
"schedulegc(num | obj)",
" If num is given, schedule a GC after num allocations.\n"
" If obj is given, schedule a GC of obj's compartment."),
JS_FN_HELP("verifybarriers", VerifyBarriers, 0, 0,
"verifybarriers()",

View File

@ -0,0 +1,9 @@
/* Make sure we don't collect the atoms compartment unless every compartment is marked. */
var g = newGlobal('new-compartment');
g.eval("var x = 'some-atom';");
schedulegc(this);
schedulegc('atoms');
gc('compartment');
print(g.x);

View File

@ -3726,10 +3726,22 @@ GCSlice(JSContext *cx, JSGCInvocationKind gckind, gcreason::Reason reason)
void
GCDebugSlice(JSContext *cx, int64_t objCount)
{
PrepareForFullGC(cx->runtime);
PrepareForDebugGC(cx->runtime);
Collect(cx, SliceBudget::WorkBudget(objCount), GC_NORMAL, gcreason::API);
}
/* Schedule a full GC unless a compartment will already be collected. */
void
PrepareForDebugGC(JSRuntime *rt)
{
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (c->isGCScheduled())
return;
}
PrepareForFullGC(rt);
}
void
ShrinkGCBuffers(JSRuntime *rt)
{
@ -3919,7 +3931,7 @@ void
RunDebugGC(JSContext *cx)
{
#ifdef JS_GC_ZEAL
PrepareForFullGC(cx->runtime);
PrepareForDebugGC(cx->runtime);
RunLastDitchGC(cx, gcreason::DEBUG_GC);
#endif
}

View File

@ -1406,6 +1406,9 @@ GCSlice(JSContext *cx, JSGCInvocationKind gckind, js::gcreason::Reason reason);
extern void
GCDebugSlice(JSContext *cx, int64_t objCount);
extern void
PrepareForDebugGC(JSRuntime *rt);
} /* namespace js */
namespace js {