mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 958353 - Add finishCC() and ccSlice() methods for testing incremental cycle collection. r=smaug
This commit is contained in:
parent
ab3d274c1e
commit
b89c24ee20
@ -18,13 +18,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
/** Test for Bug **/
|
||||
let Ci = Components.interfaces;
|
||||
var obs = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
.getService(Ci.nsIObserverService);
|
||||
var didCall = false;
|
||||
var observer = {
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsIObserver) ||
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
if (aIID.equals(Ci.nsIObserver) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
@ -35,9 +36,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure that we call the observer even if we're in the middle
|
||||
// of an ICC when we add the observer. See bug 981033.
|
||||
SpecialPowers.finishCC();
|
||||
SpecialPowers.ccSlice(1);
|
||||
|
||||
obs.addObserver(observer, "cycle-collector-begin", false);
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils).cycleCollect();
|
||||
|
||||
SpecialPowers.DOMWindowUtils.cycleCollect();
|
||||
|
||||
ok(didCall, "Observer should have been called!");
|
||||
]]>
|
||||
|
@ -121,7 +121,7 @@ interface ScheduledGCCallback : nsISupports
|
||||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(45b80e00-fb0d-439e-b7bf-54f24af0c4a6)]
|
||||
[scriptable, uuid(c9b6f5a0-cfe8-11e3-9c1a-0800200c9a66)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
@ -260,6 +260,22 @@ interface nsIXPCComponents_Utils : nsISupports
|
||||
*/
|
||||
void forceCC();
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
* If any incremental CC is in progress, finish it. For testing.
|
||||
*/
|
||||
void finishCC();
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
* Do some cycle collector work, with the given work budget.
|
||||
* The cost of calling Traverse() on a single object is set as 1.
|
||||
* For testing.
|
||||
*/
|
||||
void ccSlice(in long long budget);
|
||||
|
||||
/*
|
||||
* To be called from JS only.
|
||||
*
|
||||
|
@ -2786,6 +2786,22 @@ nsXPCComponents_Utils::ForceCC()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void finishCC(); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::FinishCC()
|
||||
{
|
||||
nsCycleCollector_finishAnyCurrentCollection();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void ccSlice(long long budget); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::CcSlice(int64_t budget)
|
||||
{
|
||||
nsCycleCollector_collectSliceWork(budget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void forceShrinkingGC (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceShrinkingGC()
|
||||
|
@ -1317,6 +1317,14 @@ SpecialPowersAPI.prototype = {
|
||||
Cu.forceCC();
|
||||
},
|
||||
|
||||
finishCC: function() {
|
||||
Cu.finishCC();
|
||||
},
|
||||
|
||||
ccSlice: function(budget) {
|
||||
Cu.ccSlice(budget);
|
||||
},
|
||||
|
||||
// Due to various dependencies between JS objects and C++ objects, an ordinary
|
||||
// forceGC doesn't necessarily clear all unused objects, thus the GC and CC
|
||||
// needs to run several times and when no other JS is running.
|
||||
|
@ -1217,6 +1217,7 @@ public:
|
||||
void RemoveObjectFromGraph(void *aPtr);
|
||||
|
||||
void PrepareForGarbageCollection();
|
||||
void FinishAnyCurrentCollection();
|
||||
|
||||
bool Collect(ccType aCCType,
|
||||
SliceBudget &aBudget,
|
||||
@ -3363,8 +3364,18 @@ nsCycleCollector::PrepareForGarbageCollection()
|
||||
return;
|
||||
}
|
||||
|
||||
FinishAnyCurrentCollection();
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::FinishAnyCurrentCollection()
|
||||
{
|
||||
if (mIncrementalPhase == IdlePhase) {
|
||||
return;
|
||||
}
|
||||
|
||||
SliceBudget unlimitedBudget;
|
||||
PrintPhase("PrepareForGarbageCollection");
|
||||
PrintPhase("FinishAnyCurrentCollection");
|
||||
// Use SliceCC because we only want to finish the CC in progress.
|
||||
Collect(SliceCC, unlimitedBudget, nullptr);
|
||||
MOZ_ASSERT(mIncrementalPhase == IdlePhase);
|
||||
@ -3871,10 +3882,25 @@ nsCycleCollector_collectSlice(int64_t aSliceTime)
|
||||
|
||||
PROFILER_LABEL("CC", "nsCycleCollector_collectSlice");
|
||||
SliceBudget budget;
|
||||
if (aSliceTime > 0) {
|
||||
if (aSliceTime >= 0) {
|
||||
budget = SliceBudget::TimeBudget(aSliceTime);
|
||||
} else if (aSliceTime == 0) {
|
||||
budget = SliceBudget::WorkBudget(1);
|
||||
}
|
||||
data->mCollector->Collect(SliceCC, budget, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_collectSliceWork(int64_t aSliceWork)
|
||||
{
|
||||
CollectorData *data = sCollectorData.get();
|
||||
|
||||
// We should have started the cycle collector by now.
|
||||
MOZ_ASSERT(data);
|
||||
MOZ_ASSERT(data->mCollector);
|
||||
|
||||
PROFILER_LABEL("CC", "nsCycleCollector_collectSliceWork");
|
||||
SliceBudget budget;
|
||||
if (aSliceWork >= 0) {
|
||||
budget = SliceBudget::WorkBudget(aSliceWork);
|
||||
}
|
||||
data->mCollector->Collect(SliceCC, budget, nullptr);
|
||||
}
|
||||
@ -3893,6 +3919,20 @@ nsCycleCollector_prepareForGarbageCollection()
|
||||
data->mCollector->PrepareForGarbageCollection();
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_finishAnyCurrentCollection()
|
||||
{
|
||||
CollectorData *data = sCollectorData.get();
|
||||
|
||||
MOZ_ASSERT(data);
|
||||
|
||||
if (!data->mCollector) {
|
||||
return;
|
||||
}
|
||||
|
||||
data->mCollector->FinishAnyCurrentCollection();
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_shutdown()
|
||||
{
|
||||
|
@ -37,16 +37,22 @@ void nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes = false,
|
||||
|
||||
void nsCycleCollector_prepareForGarbageCollection();
|
||||
|
||||
// If an incremental cycle collection is in progress, finish it.
|
||||
void nsCycleCollector_finishAnyCurrentCollection();
|
||||
|
||||
void nsCycleCollector_dispatchDeferredDeletion(bool aContinuation = false);
|
||||
bool nsCycleCollector_doDeferredDeletion();
|
||||
|
||||
void nsCycleCollector_collect(nsICycleCollectorListener *aManualListener);
|
||||
|
||||
// If aSliceTime is negative, the CC will run to completion. If aSliceTime
|
||||
// is 0, only a minimum quantum of work will be done. Otherwise, aSliceTime
|
||||
// will be used as the time budget for the slice, in ms.
|
||||
// If aSliceTime is negative, the CC will run to completion. Otherwise,
|
||||
// aSliceTime will be used as the time budget for the slice, in ms.
|
||||
void nsCycleCollector_collectSlice(int64_t aSliceTime);
|
||||
|
||||
// If aSliceTime is negative, the CC will run to completion. Otherwise,
|
||||
// aSliceTime will be used as the work budget for the slice.
|
||||
void nsCycleCollector_collectSliceWork(int64_t aSliceWork);
|
||||
|
||||
uint32_t nsCycleCollector_suspectedCount();
|
||||
void nsCycleCollector_shutdown();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user