mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 12:35:58 +00:00
Bug 650978 - Add gczeal setting to GC on every allocation (r=gwagner)
This commit is contained in:
parent
9a7e3e93e0
commit
ebcdca5a0d
@ -1013,7 +1013,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
||||
#ifdef JS_GC_ZEAL
|
||||
PRInt32 zeal = nsContentUtils::GetIntPref(js_zeal_option_str, -1);
|
||||
if (zeal >= 0)
|
||||
::JS_SetGCZeal(context->mContext, (PRUint8)zeal);
|
||||
::JS_SetGCZeal(context->mContext, (PRUint8)zeal, JS_DEFAULT_ZEAL_FREQ, JS_FALSE);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -437,7 +437,7 @@ GCZeal(JSContext *cx,
|
||||
if (!JS_ValueToECMAUint32(cx, argv[0], &zeal))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SetGCZeal(cx, PRUint8(zeal));
|
||||
JS_SetGCZeal(cx, PRUint8(zeal), JS_DEFAULT_ZEAL_FREQ, JS_FALSE);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
@ -574,7 +574,7 @@ JetpackChild::GCZeal(JSContext* cx, uintN argc, jsval *vp)
|
||||
if (!JS_ValueToECMAUint32(cx, argv[0], &zeal))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SetGCZeal(cx, PRUint8(zeal));
|
||||
JS_SetGCZeal(cx, PRUint8(zeal), JS_DEFAULT_ZEAL_FREQ, JS_FALSE);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
@ -2591,14 +2591,24 @@ JS_IsGCMarkingTracer(JSTracer *trc)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx)
|
||||
JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
|
||||
{
|
||||
/* We cannot GC the atoms compartment alone; use a full GC instead. */
|
||||
JS_ASSERT(comp != cx->runtime->atomsCompartment);
|
||||
|
||||
LeaveTrace(cx);
|
||||
|
||||
/* Don't nuke active arenas if executing or compiling. */
|
||||
if (cx->tempPool.current == &cx->tempPool.first)
|
||||
JS_FinishArenaPool(&cx->tempPool);
|
||||
js_GC(cx, NULL, GC_NORMAL);
|
||||
|
||||
js_GC(cx, comp, GC_NORMAL);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx)
|
||||
{
|
||||
JS_CompartmentGC(cx, NULL);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
@ -6122,9 +6132,19 @@ JS_ClearContextThread(JSContext *cx)
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetGCZeal(JSContext *cx, uint8 zeal)
|
||||
JS_SetGCZeal(JSContext *cx, uint8 zeal, uint32 frequency, JSBool compartment)
|
||||
{
|
||||
cx->runtime->gcZeal = zeal;
|
||||
cx->runtime->gcZeal_ = zeal;
|
||||
cx->runtime->gcZealFrequency = frequency;
|
||||
cx->runtime->gcNextScheduled = frequency;
|
||||
cx->runtime->gcDebugCompartmentGC = !!compartment;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ScheduleGC(JSContext *cx, uint32 count, JSBool compartment)
|
||||
{
|
||||
cx->runtime->gcNextScheduled = count;
|
||||
cx->runtime->gcDebugCompartmentGC = !!compartment;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1766,6 +1766,9 @@ JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_GC(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CompartmentGC(JSContext *cx, JSCompartment *comp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_MaybeGC(JSContext *cx);
|
||||
|
||||
@ -3864,8 +3867,13 @@ JS_NewObjectForConstructor(JSContext *cx, const jsval *vp);
|
||||
#endif
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
#define JS_DEFAULT_ZEAL_FREQ 100
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetGCZeal(JSContext *cx, uint8 zeal);
|
||||
JS_SetGCZeal(JSContext *cx, uint8 zeal, uint32 frequency, JSBool compartment);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ScheduleGC(JSContext *cx, uint32 count, JSBool compartment);
|
||||
#endif
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
@ -451,8 +451,43 @@ struct JSRuntime {
|
||||
bool gcRunning;
|
||||
bool gcRegenShapes;
|
||||
|
||||
/*
|
||||
* These options control the zealousness of the GC. The fundamental values
|
||||
* are gcNextScheduled and gcDebugCompartmentGC. At every allocation,
|
||||
* gcNextScheduled is decremented. When it reaches zero, we do either a
|
||||
* full or a compartmental GC, based on gcDebugCompartmentGC.
|
||||
*
|
||||
* At this point, if gcZeal_ >= 2 then gcNextScheduled is reset to the
|
||||
* value of gcZealFrequency. Otherwise, no additional GCs take place.
|
||||
*
|
||||
* You can control these values in several ways:
|
||||
* - Pass the -Z flag to the shell (see the usage info for details)
|
||||
* - Call gczeal() or schedulegc() from inside shell-executed JS code
|
||||
* (see the help for details)
|
||||
*
|
||||
* Additionally, if gzZeal_ == 1 then we perform GCs in select places
|
||||
* (during MaybeGC and whenever a GC poke happens). This option is mainly
|
||||
* useful to embedders.
|
||||
*/
|
||||
#ifdef JS_GC_ZEAL
|
||||
jsrefcount gcZeal;
|
||||
int gcZeal_;
|
||||
int gcZealFrequency;
|
||||
int gcNextScheduled;
|
||||
bool gcDebugCompartmentGC;
|
||||
|
||||
int gcZeal() { return gcZeal_; }
|
||||
|
||||
bool needZealousGC() {
|
||||
if (gcNextScheduled > 0 && --gcNextScheduled == 0) {
|
||||
if (gcZeal() >= 2)
|
||||
gcNextScheduled = gcZealFrequency;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
int gcZeal() { return 0; }
|
||||
bool needZealousGC() { return false; }
|
||||
#endif
|
||||
|
||||
JSGCCallback gcCallback;
|
||||
|
@ -1230,7 +1230,7 @@ SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
else
|
||||
argp = &obj->callObjArg(i);
|
||||
|
||||
GC_POKE(cx, *argp);
|
||||
GCPoke(cx, *argp);
|
||||
*argp = *vp;
|
||||
return true;
|
||||
}
|
||||
@ -1253,7 +1253,7 @@ SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
|
||||
Value *up = &obj->getCallObjCallee()->getFlatClosureUpvar(i);
|
||||
|
||||
GC_POKE(cx, *up);
|
||||
GCPoke(cx, *up);
|
||||
*up = *vp;
|
||||
return true;
|
||||
}
|
||||
@ -1310,7 +1310,7 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
else
|
||||
varp = &obj->callObjVar(i);
|
||||
|
||||
GC_POKE(cx, *varp);
|
||||
GCPoke(cx, *varp);
|
||||
*varp = *vp;
|
||||
return true;
|
||||
}
|
||||
|
@ -1325,10 +1325,6 @@ inline bool
|
||||
NeedLastDitchGC(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->gcZeal >= 1)
|
||||
return true;
|
||||
#endif
|
||||
return rt->gcIsNeeded;
|
||||
}
|
||||
|
||||
@ -1358,6 +1354,12 @@ RunLastDitchGC(JSContext *cx)
|
||||
return rt->gcBytes < rt->gcMaxBytes;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsGCAllowed(JSContext *cx)
|
||||
{
|
||||
return !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Cell *
|
||||
RefillTypedFreeList(JSContext *cx, unsigned thingKind)
|
||||
@ -1374,7 +1376,7 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind)
|
||||
JSCompartment *compartment = cx->compartment;
|
||||
JS_ASSERT(!compartment->freeLists.finalizables[thingKind]);
|
||||
|
||||
bool canGC = !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota;
|
||||
bool canGC = IsGCAllowed(cx);
|
||||
bool runGC = canGC && JS_UNLIKELY(NeedLastDitchGC(cx));
|
||||
for (;;) {
|
||||
if (runGC) {
|
||||
@ -1918,12 +1920,10 @@ TriggerCompartmentGC(JSCompartment *comp)
|
||||
JSRuntime *rt = comp->rt;
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->gcZeal >= 1) {
|
||||
if (rt->gcZeal()) {
|
||||
TriggerGC(rt);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rt->gcMode != JSGC_MODE_COMPARTMENT || comp == rt->atomsCompartment) {
|
||||
/* We can't do a compartmental GC of the default compartment. */
|
||||
@ -1958,12 +1958,10 @@ MaybeGC(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->gcZeal > 0) {
|
||||
if (rt->gcZeal()) {
|
||||
js_GC(cx, NULL, GC_NORMAL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSCompartment *comp = cx->compartment;
|
||||
if (rt->gcIsNeeded) {
|
||||
@ -2271,11 +2269,7 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
||||
* Same for the protoHazardShape proxy-shape standing in for all object
|
||||
* prototypes having readonly or setter properties.
|
||||
*/
|
||||
if (rt->shapeGen & SHAPE_OVERFLOW_BIT
|
||||
#ifdef JS_GC_ZEAL
|
||||
|| rt->gcZeal >= 1
|
||||
#endif
|
||||
) {
|
||||
if (rt->shapeGen & SHAPE_OVERFLOW_BIT || (rt->gcZeal() && !rt->gcCurrentCompartment)) {
|
||||
rt->gcRegenShapes = true;
|
||||
rt->shapeGen = 0;
|
||||
rt->protoHazardShape = 0;
|
||||
@ -2943,6 +2937,26 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
RunDebugGC(JSContext *cx)
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (IsGCAllowed(cx)) {
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
/*
|
||||
* If rt->gcDebugCompartmentGC is true, only GC the current
|
||||
* compartment. But don't GC the atoms compartment.
|
||||
*/
|
||||
rt->gcTriggerCompartment = rt->gcDebugCompartmentGC ? cx->compartment : NULL;
|
||||
if (rt->gcTriggerCompartment == rt->atomsCompartment)
|
||||
rt->gcTriggerCompartment = NULL;
|
||||
|
||||
RunLastDitchGC(cx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -869,17 +869,6 @@ CheckAllocation(JSContext *cx);
|
||||
extern JS_FRIEND_API(uint32)
|
||||
js_GetGCThingTraceKind(void *thing);
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
|
||||
* loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
|
||||
* ignored", etc.
|
||||
*/
|
||||
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
|
||||
#else
|
||||
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
|
||||
#endif
|
||||
|
||||
extern JSBool
|
||||
js_InitGC(JSRuntime *rt, uint32 maxbytes);
|
||||
|
||||
@ -1317,6 +1306,10 @@ namespace gc {
|
||||
JSCompartment *
|
||||
NewCompartment(JSContext *cx, JSPrincipals *principals);
|
||||
|
||||
/* Tries to run a GC no matter what (used for GC zeal). */
|
||||
void
|
||||
RunDebugGC(JSContext *cx);
|
||||
|
||||
} /* namespace js */
|
||||
} /* namespace gc */
|
||||
|
||||
|
@ -161,6 +161,27 @@ GetGCKindSlots(FinalizeKind thingKind)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
GCPoke(JSContext *cx, Value oldval)
|
||||
{
|
||||
/*
|
||||
* Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
|
||||
* loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
|
||||
* ignored", etc.
|
||||
*/
|
||||
#if 1
|
||||
cx->runtime->gcPoke = JS_TRUE;
|
||||
#else
|
||||
cx->runtime->gcPoke = oldval.isGCThing();
|
||||
#endif
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
/* Schedule a GC to happen "soon" after a GC poke. */
|
||||
if (cx->runtime->gcZeal())
|
||||
cx->runtime->gcNextScheduled = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
@ -183,6 +204,11 @@ NewFinalizableGCThing(JSContext *cx, unsigned thingKind)
|
||||
#endif
|
||||
JS_ASSERT(!cx->runtime->gcRunning);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (cx->runtime->needZealousGC())
|
||||
js::gc::RunDebugGC(cx);
|
||||
#endif
|
||||
|
||||
METER(cx->compartment->arenas[thingKind].stats.alloc++);
|
||||
js::gc::Cell *cell = cx->compartment->freeLists.getNext(thingKind);
|
||||
return static_cast<T *>(cell ? cell : js::gc::RefillFinalizableFreeList(cx, thingKind));
|
||||
|
@ -5847,7 +5847,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str
|
||||
|
||||
if (obj->containsSlot(shape->slot)) {
|
||||
const Value &v = obj->nativeGetSlot(shape->slot);
|
||||
GC_POKE(cx, v);
|
||||
GCPoke(cx, v);
|
||||
|
||||
/*
|
||||
* Delete is rare enough that we can take the hit of checking for an
|
||||
@ -6527,7 +6527,7 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 slot, const Value &v)
|
||||
}
|
||||
|
||||
obj->setSlot(slot, v);
|
||||
GC_POKE(cx, JS_NULL);
|
||||
GCPoke(cx, NullValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,12 @@ usage(void)
|
||||
fprintf(gErrFile, " -g <n> Sleep for <n> seconds before starting (default: 0)\n");
|
||||
#endif
|
||||
#ifdef JS_GC_ZEAL
|
||||
fprintf(gErrFile, " -Z <n> Toggle GC zeal: low if <n> is 0 (default), high if non-zero\n");
|
||||
fprintf(gErrFile, " -Z <n>[,<f>[,<c>]] Set GC zeal to <n>.\n"
|
||||
" Possible values for <n>:\n"
|
||||
" 0: no additional GCs\n"
|
||||
" 1: additional GCs at common danger points\n"
|
||||
" 2: GC every <f> allocations (<f> defaults to 100)\n"
|
||||
" If <c> = 1, do compartment GCs. Otherwise full.\n");
|
||||
#endif
|
||||
#ifdef MOZ_TRACEVIS
|
||||
fprintf(gErrFile, " -T Start TraceVis\n");
|
||||
@ -702,6 +707,25 @@ namespace js {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
static void
|
||||
ParseZealArg(JSContext *cx, const char *arg)
|
||||
{
|
||||
int zeal, freq = 1, compartment = 0;
|
||||
const char *p = strchr(arg, ',');
|
||||
|
||||
zeal = atoi(arg);
|
||||
if (p) {
|
||||
freq = atoi(p + 1);
|
||||
p = strchr(p + 1, ',');
|
||||
if (p)
|
||||
compartment = atoi(p + 1);
|
||||
}
|
||||
|
||||
JS_SetGCZeal(cx, zeal, freq, !!compartment);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
|
||||
{
|
||||
@ -785,7 +809,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
|
||||
case 'Z':
|
||||
if (++i == argc)
|
||||
return usage();
|
||||
JS_SetGCZeal(cx, !!(atoi(argv[i])));
|
||||
ParseZealArg(cx, argv[i]);
|
||||
break;
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
@ -1468,8 +1492,15 @@ AssertJit(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
GC(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSCompartment *comp = NULL;
|
||||
if (argc == 1) {
|
||||
Value arg = Valueify(vp[2]);
|
||||
if (arg.isObject())
|
||||
comp = arg.toObject().unwrap()->compartment();
|
||||
}
|
||||
|
||||
size_t preBytes = cx->runtime->gcBytes;
|
||||
JS_GC(cx);
|
||||
JS_CompartmentGC(cx, comp);
|
||||
|
||||
char buf[256];
|
||||
JS_snprintf(buf, sizeof(buf), "before %lu, after %lu, break %08lx\n",
|
||||
@ -1565,11 +1596,46 @@ GCParameter(JSContext *cx, uintN argc, jsval *vp)
|
||||
static JSBool
|
||||
GCZeal(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
uint32 zeal;
|
||||
uint32 zeal, frequency = JS_DEFAULT_ZEAL_FREQ;
|
||||
JSBool compartment = JS_FALSE;
|
||||
|
||||
if (!JS_ValueToECMAUint32(cx, argc == 0 ? JSVAL_VOID : vp[2], &zeal))
|
||||
if (argc > 3) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TOO_MANY_ARGS, "gczeal");
|
||||
return JS_FALSE;
|
||||
JS_SetGCZeal(cx, (uint8)zeal);
|
||||
}
|
||||
if (!JS_ValueToECMAUint32(cx, argc < 1 ? JSVAL_VOID : vp[2], &zeal))
|
||||
return JS_FALSE;
|
||||
if (argc >= 2)
|
||||
if (!JS_ValueToECMAUint32(cx, vp[3], &frequency))
|
||||
return JS_FALSE;
|
||||
if (argc >= 3)
|
||||
compartment = js_ValueToBoolean(Valueify(vp[3]));
|
||||
|
||||
JS_SetGCZeal(cx, (uint8)zeal, frequency, compartment);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ScheduleGC(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
uint32 count;
|
||||
bool compartment = false;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
|
||||
(argc < 1)
|
||||
? JSSMSG_NOT_ENOUGH_ARGS
|
||||
: JSSMSG_TOO_MANY_ARGS,
|
||||
"schedulegc");
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!JS_ValueToECMAUint32(cx, vp[2], &count))
|
||||
return JS_FALSE;
|
||||
if (argc == 2)
|
||||
compartment = js_ValueToBoolean(Valueify(vp[3]));
|
||||
|
||||
JS_ScheduleGC(cx, count, compartment);
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -4734,7 +4800,8 @@ static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("makeFinalizeObserver", MakeFinalizeObserver, 0,0),
|
||||
JS_FN("finalizeCount", FinalizeCount, 0,0),
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_FN("gczeal", GCZeal, 1,0),
|
||||
JS_FN("gczeal", GCZeal, 2,0),
|
||||
JS_FN("schedulegc", ScheduleGC, 1,0),
|
||||
#endif
|
||||
JS_FN("setDebug", SetDebug, 1,0),
|
||||
JS_FN("setDebuggerHandler", SetDebuggerHandler, 1,0),
|
||||
@ -4837,7 +4904,8 @@ static const char *const shell_help_messages[] = {
|
||||
" Throw if the first two arguments are not the same (both +0 or both -0,\n"
|
||||
" both NaN, or non-zero and ===)",
|
||||
"assertJit() Throw if the calling function failed to JIT",
|
||||
"gc() Run the garbage collector",
|
||||
"gc([obj]) Run the garbage collector\n"
|
||||
" When obj is given, GC only the compartment it's in",
|
||||
#ifdef JS_GCMETER
|
||||
"gcstats() Print garbage collector statistics",
|
||||
#endif
|
||||
@ -4856,7 +4924,10 @@ static const char *const shell_help_messages[] = {
|
||||
" return the current value of the finalization counter that is incremented\n"
|
||||
" each time an object returned by the makeFinalizeObserver is finalized",
|
||||
#ifdef JS_GC_ZEAL
|
||||
"gczeal(level) How zealous the garbage collector should be",
|
||||
"gczeal(level, [freq], [compartmentGC?])\n"
|
||||
" How zealous the garbage collector should be",
|
||||
"schedulegc(num, [compartmentGC?])\n"
|
||||
" Schedule a GC to happen after num allocations",
|
||||
#endif
|
||||
"setDebug(debug) Set debug mode",
|
||||
"setDebuggerHandler(f) Set handler for debugger keyword to f",
|
||||
@ -6046,6 +6117,7 @@ main(int argc, char **argv, char **envp)
|
||||
return 1;
|
||||
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ANONFUNFIX);
|
||||
JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_COMPARTMENT);
|
||||
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024);
|
||||
|
||||
result = Shell(cx, argc, argv, envp);
|
||||
|
@ -571,7 +571,7 @@ GCZeal(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (!JS_ValueToECMAUint32(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID, &zeal))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SetGCZeal(cx, (PRUint8)zeal);
|
||||
JS_SetGCZeal(cx, (PRUint8)zeal, JS_DEFAULT_ZEAL_FREQ, JS_FALSE);
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user