Loading js/src/builtin/TestingFunctions.cpp +36 −14 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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])", Loading Loading @@ -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()", Loading js/src/jit-test/tests/gc/multi-01.js 0 → 100644 +9 −0 Original line number Diff line number Diff line /* 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); js/src/jsgc.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -3919,7 +3931,7 @@ void RunDebugGC(JSContext *cx) { #ifdef JS_GC_ZEAL PrepareForFullGC(cx->runtime); PrepareForDebugGC(cx->runtime); RunLastDitchGC(cx, gcreason::DEBUG_GC); #endif } Loading js/src/jsgc.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading
js/src/builtin/TestingFunctions.cpp +36 −14 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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])", Loading Loading @@ -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()", Loading
js/src/jit-test/tests/gc/multi-01.js 0 → 100644 +9 −0 Original line number Diff line number Diff line /* 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);
js/src/jsgc.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -3919,7 +3931,7 @@ void RunDebugGC(JSContext *cx) { #ifdef JS_GC_ZEAL PrepareForFullGC(cx->runtime); PrepareForDebugGC(cx->runtime); RunLastDitchGC(cx, gcreason::DEBUG_GC); #endif } Loading
js/src/jsgc.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading