зеркало из https://github.com/mozilla/pjs.git
Bug 742570 - Improve GC testing functions (r=igor)
This commit is contained in:
Родитель
3beb216ed0
Коммит
8a7780be96
|
@ -21,19 +21,30 @@ using namespace JS;
|
||||||
static JSBool
|
static JSBool
|
||||||
GC(JSContext *cx, unsigned argc, jsval *vp)
|
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) {
|
if (argc == 1) {
|
||||||
Value arg = vp[2];
|
Value arg = vp[2];
|
||||||
if (arg.isObject())
|
if (arg.isString()) {
|
||||||
comp = UnwrapObject(&arg.toObject())->compartment();
|
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
|
#ifndef JS_MORE_DETERMINISTIC
|
||||||
size_t preBytes = cx->runtime->gcBytes;
|
size_t preBytes = cx->runtime->gcBytes;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (comp)
|
if (compartment)
|
||||||
PrepareCompartmentForGC(comp);
|
PrepareForDebugGC(cx->runtime);
|
||||||
else
|
else
|
||||||
PrepareForFullGC(cx->runtime);
|
PrepareForFullGC(cx->runtime);
|
||||||
GCForReason(cx, gcreason::API);
|
GCForReason(cx, gcreason::API);
|
||||||
|
@ -177,16 +188,24 @@ GCZeal(JSContext *cx, unsigned argc, jsval *vp)
|
||||||
static JSBool
|
static JSBool
|
||||||
ScheduleGC(JSContext *cx, unsigned argc, jsval *vp)
|
ScheduleGC(JSContext *cx, unsigned argc, jsval *vp)
|
||||||
{
|
{
|
||||||
uint32_t count;
|
|
||||||
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
|
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
|
||||||
return JS_FALSE;
|
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;
|
*vp = JSVAL_VOID;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -473,8 +492,10 @@ Terminate(JSContext *cx, unsigned arg, jsval *vp)
|
||||||
|
|
||||||
static JSFunctionSpecWithHelp TestingFunctions[] = {
|
static JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||||
JS_FN_HELP("gc", ::GC, 0, 0,
|
JS_FN_HELP("gc", ::GC, 0, 0,
|
||||||
"gc([obj])",
|
"gc([obj] | 'compartment')",
|
||||||
" Run the garbage collector. When obj is given, GC only its 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,
|
JS_FN_HELP("gcparam", GCParameter, 2, 0,
|
||||||
"gcparam(name [, value])",
|
"gcparam(name [, value])",
|
||||||
|
@ -511,8 +532,9 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||||
" Period specifies that collection happens every n allocations.\n"),
|
" Period specifies that collection happens every n allocations.\n"),
|
||||||
|
|
||||||
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
|
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
|
||||||
"schedulegc(num)",
|
"schedulegc(num | obj)",
|
||||||
" Schedule a GC to happen after num allocations."),
|
" 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,
|
JS_FN_HELP("verifybarriers", VerifyBarriers, 0, 0,
|
||||||
"verifybarriers()",
|
"verifybarriers()",
|
||||||
|
|
|
@ -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);
|
|
@ -3726,10 +3726,22 @@ GCSlice(JSContext *cx, JSGCInvocationKind gckind, gcreason::Reason reason)
|
||||||
void
|
void
|
||||||
GCDebugSlice(JSContext *cx, int64_t objCount)
|
GCDebugSlice(JSContext *cx, int64_t objCount)
|
||||||
{
|
{
|
||||||
PrepareForFullGC(cx->runtime);
|
PrepareForDebugGC(cx->runtime);
|
||||||
Collect(cx, SliceBudget::WorkBudget(objCount), GC_NORMAL, gcreason::API);
|
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
|
void
|
||||||
ShrinkGCBuffers(JSRuntime *rt)
|
ShrinkGCBuffers(JSRuntime *rt)
|
||||||
{
|
{
|
||||||
|
@ -3919,7 +3931,7 @@ void
|
||||||
RunDebugGC(JSContext *cx)
|
RunDebugGC(JSContext *cx)
|
||||||
{
|
{
|
||||||
#ifdef JS_GC_ZEAL
|
#ifdef JS_GC_ZEAL
|
||||||
PrepareForFullGC(cx->runtime);
|
PrepareForDebugGC(cx->runtime);
|
||||||
RunLastDitchGC(cx, gcreason::DEBUG_GC);
|
RunLastDitchGC(cx, gcreason::DEBUG_GC);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1406,6 +1406,9 @@ GCSlice(JSContext *cx, JSGCInvocationKind gckind, js::gcreason::Reason reason);
|
||||||
extern void
|
extern void
|
||||||
GCDebugSlice(JSContext *cx, int64_t objCount);
|
GCDebugSlice(JSContext *cx, int64_t objCount);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
PrepareForDebugGC(JSRuntime *rt);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче