mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 763984: Add new zeal modes to test incremental GC r=billm
--HG-- extra : rebase_source : 0392bc3985442eb3b378b1f5a47a757f55106fdc
This commit is contained in:
parent
052a9b7ec1
commit
08f94c004a
@ -746,6 +746,7 @@ JSRuntime::JSRuntime()
|
||||
gcZealFrequency(0),
|
||||
gcNextScheduled(0),
|
||||
gcDeterministicOnly(false),
|
||||
gcIncrementalLimit(0),
|
||||
#endif
|
||||
gcCallback(NULL),
|
||||
gcSliceCallback(NULL),
|
||||
@ -6671,7 +6672,10 @@ JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
|
||||
" 4: Verify write barriers between instructions\n"
|
||||
" 5: Verify write barriers between paints\n"
|
||||
" 6: Verify stack rooting (ignoring XML and Reflect)\n"
|
||||
" 7: Verify stack rooting (all roots)\n");
|
||||
" 7: Verify stack rooting (all roots)\n"
|
||||
" 8: Incremental GC in two slices: 1) mark roots 2) finish collection\n"
|
||||
" 9: Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
|
||||
" 10: Incremental GC in multiple slices\n");
|
||||
}
|
||||
const char *p = strchr(env, ',');
|
||||
zeal = atoi(env);
|
||||
|
@ -586,8 +586,9 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
* 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.
|
||||
* At this point, if gcZeal_ is one of the types that trigger periodic
|
||||
* collection, 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)
|
||||
@ -599,12 +600,16 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
*
|
||||
* We use gcZeal_ == 4 to enable write barrier verification. See the comment
|
||||
* in jsgc.cpp for more information about this.
|
||||
*
|
||||
* gcZeal_ values from 8 to 10 periodically run different types of
|
||||
* incremental GC.
|
||||
*/
|
||||
#ifdef JS_GC_ZEAL
|
||||
int gcZeal_;
|
||||
int gcZealFrequency;
|
||||
int gcNextScheduled;
|
||||
bool gcDeterministicOnly;
|
||||
int gcIncrementalLimit;
|
||||
|
||||
js::Vector<JSObject *, 0, js::SystemAllocPolicy> gcSelectedForMarking;
|
||||
|
||||
@ -612,8 +617,12 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
|
||||
bool needZealousGC() {
|
||||
if (gcNextScheduled > 0 && --gcNextScheduled == 0) {
|
||||
if (gcZeal() == js::gc::ZealAllocValue)
|
||||
if (gcZeal() == js::gc::ZealAllocValue ||
|
||||
(gcZeal() >= js::gc::ZealIncrementalRootsThenFinish &&
|
||||
gcZeal() <= js::gc::ZealIncrementalMultipleSlices))
|
||||
{
|
||||
gcNextScheduled = gcZealFrequency;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -3590,12 +3590,23 @@ class AutoCopyFreeListToArenas {
|
||||
};
|
||||
|
||||
static void
|
||||
IncrementalMarkSlice(JSRuntime *rt, int64_t budget, JSGCInvocationKind gckind, bool *shouldSweep)
|
||||
IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, bool *shouldSweep)
|
||||
{
|
||||
AutoGCSlice slice(rt);
|
||||
|
||||
gc::State initialState = rt->gcIncrementalState;
|
||||
|
||||
*shouldSweep = false;
|
||||
|
||||
int zeal = 0;
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (reason == gcreason::DEBUG_GC) {
|
||||
// Do the collection type specified by zeal mode only if the collection
|
||||
// was triggered by RunDebugGC().
|
||||
zeal = rt->gcZeal();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rt->gcIncrementalState == NO_INCREMENTAL) {
|
||||
rt->gcIncrementalState = MARK_ROOTS;
|
||||
rt->gcLastMarkSlice = false;
|
||||
@ -3604,9 +3615,11 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, JSGCInvocationKind gckind, b
|
||||
if (rt->gcIncrementalState == MARK_ROOTS) {
|
||||
BeginMarkPhase(rt);
|
||||
rt->gcIncrementalState = MARK;
|
||||
|
||||
if (zeal == ZealIncrementalRootsThenFinish)
|
||||
return;
|
||||
}
|
||||
|
||||
*shouldSweep = false;
|
||||
if (rt->gcIncrementalState == MARK) {
|
||||
SliceBudget sliceBudget(budget);
|
||||
|
||||
@ -3614,6 +3627,12 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, JSGCInvocationKind gckind, b
|
||||
if (!rt->gcMarker.hasBufferedGrayRoots())
|
||||
sliceBudget.reset();
|
||||
|
||||
if (zeal == ZealIncrementalRootsThenFinish ||
|
||||
zeal == ZealIncrementalMarkAllThenFinish)
|
||||
{
|
||||
sliceBudget.reset();
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (!rt->gcSelectedForMarking.empty()) {
|
||||
for (JSObject **obj = rt->gcSelectedForMarking.begin();
|
||||
@ -3631,7 +3650,12 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, JSGCInvocationKind gckind, b
|
||||
}
|
||||
if (finished) {
|
||||
JS_ASSERT(rt->gcMarker.isDrained());
|
||||
if (initialState == MARK && !rt->gcLastMarkSlice && budget != SliceBudget::Unlimited) {
|
||||
|
||||
if (!rt->gcLastMarkSlice &&
|
||||
((initialState == MARK && budget != SliceBudget::Unlimited) ||
|
||||
zeal == ZealIncrementalMarkAllThenFinish) &&
|
||||
zeal != ZealIncrementalRootsThenFinish)
|
||||
{
|
||||
rt->gcLastMarkSlice = true;
|
||||
} else {
|
||||
EndMarkPhase(rt);
|
||||
@ -3732,7 +3756,7 @@ BudgetIncrementalGC(JSRuntime *rt, int64_t *budget)
|
||||
* the marking implementation.
|
||||
*/
|
||||
static JS_NEVER_INLINE void
|
||||
GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gckind)
|
||||
GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gckind, gcreason::Reason reason)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
@ -3780,7 +3804,7 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
|
||||
NonIncrementalMark(rt, gckind);
|
||||
shouldSweep = true;
|
||||
} else {
|
||||
IncrementalMarkSlice(rt, budget, gckind, &shouldSweep);
|
||||
IncrementalMarkSlice(rt, budget, reason, &shouldSweep);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -3891,7 +3915,7 @@ Collect(JSRuntime *rt, bool incremental, int64_t budget,
|
||||
}
|
||||
|
||||
rt->gcPoke = false;
|
||||
GCCycle(rt, incremental, budget, gckind);
|
||||
GCCycle(rt, incremental, budget, gckind, reason);
|
||||
|
||||
if (rt->gcIncrementalState == NO_INCREMENTAL) {
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_GC_END);
|
||||
@ -4123,8 +4147,32 @@ void
|
||||
RunDebugGC(JSContext *cx)
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
JSRuntime *rt = cx->runtime;
|
||||
PrepareForDebugGC(cx->runtime);
|
||||
RunLastDitchGC(cx, gcreason::DEBUG_GC);
|
||||
|
||||
int type = rt->gcZeal();
|
||||
if (type == ZealIncrementalRootsThenFinish ||
|
||||
type == ZealIncrementalMarkAllThenFinish ||
|
||||
type == ZealIncrementalMultipleSlices)
|
||||
{
|
||||
int64_t budget;
|
||||
if (type == ZealIncrementalMultipleSlices) {
|
||||
// Start with a small slice limit and double it every slice. This ensure that we get
|
||||
// multiple slices, and collection runs to completion.
|
||||
if (rt->gcIncrementalState == NO_INCREMENTAL)
|
||||
rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
|
||||
else
|
||||
rt->gcIncrementalLimit *= 2;
|
||||
budget = SliceBudget::WorkBudget(rt->gcIncrementalLimit);
|
||||
} else {
|
||||
// This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
|
||||
budget = SliceBudget::WorkBudget(1);
|
||||
}
|
||||
Collect(rt, true, budget, GC_NORMAL, gcreason::DEBUG_GC);
|
||||
} else {
|
||||
Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, gcreason::DEBUG_GC);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1069,6 +1069,9 @@ const int ZealVerifierValue = 4;
|
||||
const int ZealFrameVerifierValue = 5;
|
||||
const int ZealStackRootingSafeValue = 6;
|
||||
const int ZealStackRootingValue = 7;
|
||||
const int ZealIncrementalRootsThenFinish = 8;
|
||||
const int ZealIncrementalMarkAllThenFinish = 9;
|
||||
const int ZealIncrementalMultipleSlices = 10;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user