Bug 731094 - Expose a testing function that permits only deterministic GCs (r=igor)

This commit is contained in:
Bill McCloskey 2012-03-06 11:39:31 -08:00
Родитель 61365656cd
Коммит 38627da91d
6 изменённых файлов: 56 добавлений и 5 удалений

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

@ -8,6 +8,7 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsfriendapi.h"
#include "jsgc.h"
#include "jsobj.h"
#include "jsprf.h"
#include "jswrapper.h"
@ -221,6 +222,19 @@ GCSlice(JSContext *cx, unsigned argc, jsval *vp)
*vp = JSVAL_VOID;
return JS_TRUE;
}
static JSBool
DeterministicGC(JSContext *cx, unsigned argc, jsval *vp)
{
if (argc != 1) {
ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
return JS_FALSE;
}
gc::SetDeterministicGC(cx, js_ValueToBoolean(vp[2]));
*vp = JSVAL_VOID;
return JS_TRUE;
}
#endif /* JS_GC_ZEAL */
typedef struct JSCountHeapNode JSCountHeapNode;
@ -516,6 +530,10 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gcslice", GCSlice, 1, 0,
"gcslice(n)",
" Run an incremental GC slice that marks about n objects."),
JS_FN_HELP("deterministicgc", DeterministicGC, 1, 0,
"deterministicgc(true|false)",
" If true, only allow determinstic GCs to run."),
#endif
JS_FN_HELP("internalConst", InternalConst, 1, 0,

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

@ -753,6 +753,7 @@ JSRuntime::JSRuntime()
gcZealFrequency(0),
gcNextScheduled(0),
gcDebugCompartmentGC(false),
gcDeterministicOnly(false),
#endif
gcCallback(NULL),
gcSliceCallback(NULL),

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

@ -419,6 +419,7 @@ struct JSRuntime : js::RuntimeFriendFields
int gcZealFrequency;
int gcNextScheduled;
bool gcDebugCompartmentGC;
bool gcDeterministicOnly;
int gcZeal() { return gcZeal_; }

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

@ -673,7 +673,7 @@ SizeOfJSContext();
D(LAST_DITCH) \
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
D(UNUSED1) /* was CHUNK */ \
D(DEBUG_GC) \
D(UNUSED2) /* was SHAPE */ \
D(UNUSED3) /* was REFILL */ \
\

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

@ -1708,13 +1708,13 @@ ArenaLists::finalizeScripts(JSContext *cx)
}
static void
RunLastDitchGC(JSContext *cx)
RunLastDitchGC(JSContext *cx, gcreason::Reason reason)
{
JSRuntime *rt = cx->runtime;
/* The last ditch GC preserves all atoms. */
AutoKeepAtoms keep(rt);
GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcreason::LAST_DITCH);
GC(cx, rt->gcTriggerCompartment, GC_NORMAL, reason);
}
/* static */ void *
@ -1729,7 +1729,7 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
bool runGC = rt->gcIncrementalState != NO_INCREMENTAL && comp->gcBytes > comp->gcTriggerBytes;
for (;;) {
if (JS_UNLIKELY(runGC)) {
RunLastDitchGC(cx);
RunLastDitchGC(cx, gcreason::LAST_DITCH);
/*
* The JSGC_END callback can legitimately allocate new GC
@ -3662,6 +3662,20 @@ GCCycle(JSContext *cx, JSCompartment *comp, int64_t budget, JSGCInvocationKind g
#endif
}
#ifdef JS_GC_ZEAL
static bool
IsDeterministicGCReason(gcreason::Reason reason)
{
if (reason > gcreason::DEBUG_GC && reason != gcreason::CC_FORCED)
return false;
if (reason == gcreason::MAYBEGC)
return false;
return true;
}
#endif
static void
Collect(JSContext *cx, JSCompartment *comp, int64_t budget,
JSGCInvocationKind gckind, gcreason::Reason reason)
@ -3669,6 +3683,11 @@ Collect(JSContext *cx, JSCompartment *comp, int64_t budget,
JSRuntime *rt = cx->runtime;
JS_AbortIfWrongThread(rt);
#ifdef JS_GC_ZEAL
if (rt->gcDeterministicOnly && !IsDeterministicGCReason(reason))
return;
#endif
JS_ASSERT_IF(budget != SliceBudget::Unlimited, JSGC_INCREMENTAL);
#ifdef JS_GC_ZEAL
@ -3947,7 +3966,16 @@ RunDebugGC(JSContext *cx)
if (rt->gcTriggerCompartment == rt->atomsCompartment)
rt->gcTriggerCompartment = NULL;
RunLastDitchGC(cx);
RunLastDitchGC(cx, gcreason::DEBUG_GC);
#endif
}
void
SetDeterministicGC(JSContext *cx, bool enabled)
{
#ifdef JS_GC_ZEAL
JSRuntime *rt = cx->runtime;
rt->gcDeterministicOnly = enabled;
#endif
}

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

@ -1968,6 +1968,9 @@ NewCompartment(JSContext *cx, JSPrincipals *principals);
void
RunDebugGC(JSContext *cx);
void
SetDeterministicGC(JSContext *cx, bool enabled);
#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG) && !defined(JS_THREADSAFE)
/* Overwrites stack references to GC things which have not been rooted. */
void CheckStackRoots(JSContext *cx);