Backed out changeset a9715a3b0e13 (bug 937818) for static rooting hazard analysis bustage on a CLOSED TREE

This commit is contained in:
Carsten "Tomcat" Book 2013-12-17 09:20:31 +01:00
parent c0f42c8fcf
commit 94d78eb137

View File

@ -1178,8 +1178,7 @@ private:
void BeginCollection(ccType aCCType, nsICycleCollectorListener *aManualListener);
void MarkRoots(SliceBudget &aBudget);
void ScanRoots(bool aFullySynchGraphBuild);
void ScanIncrementalRoots();
void ScanRoots();
void ScanWeakMaps();
// returns whether anything was collected
@ -2304,16 +2303,6 @@ nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes,
bool aAsyncSnowWhiteFreeing)
{
CheckThreadSafety();
// If we remove things from the purple buffer during graph building, we may
// lose track of an object that was mutated during graph building. This should
// only happen when somebody calls nsJSContext::CycleCollectNow explicitly
// requesting extra forget skippable calls, during an incremental collection.
// See bug 950949 for fixing this so we actually run the forgetSkippable calls.
if (mIncrementalPhase != IdlePhase) {
return;
}
if (mJSRuntime) {
mJSRuntime->PrepareForForgetSkippable();
}
@ -2485,138 +2474,28 @@ nsCycleCollector::ScanWeakMaps()
}
}
// Flood black from any objects in the purple buffer that are in the CC graph.
class PurpleScanBlackVisitor
{
public:
PurpleScanBlackVisitor(GCGraph &aGraph, uint32_t &aCount, bool &aFailed)
: mGraph(aGraph), mCount(aCount), mFailed(aFailed)
{
}
void
Visit(nsPurpleBuffer &aBuffer, nsPurpleBufferEntry *aEntry)
{
MOZ_ASSERT(aEntry->mObject, "Entries with null mObject shouldn't be in the purple buffer.");
MOZ_ASSERT(aEntry->mRefCnt->get() != 0, "Snow-white objects shouldn't be in the purple buffer.");
void *obj = aEntry->mObject;
if (!aEntry->mParticipant) {
obj = CanonicalizeXPCOMParticipant(static_cast<nsISupports*>(obj));
MOZ_ASSERT(obj, "Don't add objects that don't participate in collection!");
}
PtrInfo *pi = mGraph.FindNode(obj);
if (!pi) {
return;
}
MOZ_ASSERT(pi->mParticipant, "No dead objects should be in the purple buffer.");
if (pi->mColor == black) {
return;
}
GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(mCount, mFailed)).Walk(pi);
}
private:
GCGraph &mGraph;
uint32_t &mCount;
bool &mFailed;
};
// Objects that have been stored somewhere since the start of incremental graph building must
// be treated as live for this cycle collection, because we may not have accurate information
// about who holds references to them.
void
nsCycleCollector::ScanIncrementalRoots()
nsCycleCollector::ScanRoots()
{
TimeLog timeLog;
// Reference counted objects:
// We cleared the purple buffer at the start of the current ICC, so if a
// refcounted object is purple, it may have been AddRef'd during the current
// ICC. (It may also have only been released.) If that is the case, we cannot
// be sure that the set of things pointing to the object in the CC graph
// is accurate. Therefore, for safety, we treat any purple objects as being
// live during the current CC. We don't remove anything from the purple
// buffer here, so these objects will be suspected and freed in the next CC
// if they are garbage.
bool failed = false;
PurpleScanBlackVisitor purpleScanBlackVisitor(mGraph, mWhiteNodeCount, failed);
mPurpleBuf.VisitEntries(purpleScanBlackVisitor);
timeLog.Checkpoint("ScanIncrementalRoots::fix purple");
// Garbage collected objects:
// If a GCed object was added to the graph with a refcount of zero, and is
// now marked black by the GC, it was probably gray before and was exposed
// to active JS, so it may have been stored somewhere, so it needs to be
// treated as live.
if (mJSRuntime) {
nsCycleCollectionParticipant *jsParticipant = mJSRuntime->GCThingParticipant();
nsCycleCollectionParticipant *zoneParticipant = mJSRuntime->ZoneParticipant();
NodePool::Enumerator etor(mGraph.mNodes);
while (!etor.IsDone()) {
PtrInfo *pi = etor.GetNext();
if (pi->mRefCount != 0 || pi->mColor == black) {
continue;
}
if (pi->mParticipant == jsParticipant) {
if (xpc_GCThingIsGrayCCThing(pi->mPointer)) {
continue;
}
} else if (pi->mParticipant == zoneParticipant) {
JS::Zone *zone = static_cast<JS::Zone*>(pi->mPointer);
if (js::ZoneGlobalsAreAllGray(zone)) {
continue;
}
} else {
MOZ_ASSERT(false, "Non-JS thing with 0 refcount? Treating as live.");
}
GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(mWhiteNodeCount, failed)).Walk(pi);
}
timeLog.Checkpoint("ScanIncrementalRoots::fix JS");
}
if (failed) {
NS_ASSERTION(false, "Ran out of memory in ScanIncrementalRoots");
CC_TELEMETRY(_OOM, true);
}
}
void
nsCycleCollector::ScanRoots(bool aFullySynchGraphBuild)
{
AutoRestore<bool> ar(mScanInProgress);
MOZ_ASSERT(!mScanInProgress);
mScanInProgress = true;
mWhiteNodeCount = 0;
MOZ_ASSERT(mIncrementalPhase == ScanAndCollectWhitePhase);
if (!aFullySynchGraphBuild) {
ScanIncrementalRoots();
}
TimeLog timeLog;
// On the assumption that most nodes will be black, it's
// probably faster to use a GraphWalker than a
// NodePool::Enumerator.
bool failed = false;
GraphWalker<scanVisitor>(scanVisitor(mWhiteNodeCount, failed)).WalkFromRoots(mGraph);
timeLog.Checkpoint("ScanRoots::WalkFromRoots");
if (failed) {
NS_ASSERTION(false, "Ran out of memory in ScanRoots");
CC_TELEMETRY(_OOM, true);
}
// Scanning weak maps must be done last.
ScanWeakMaps();
timeLog.Checkpoint("ScanRoots::ScanWeakMaps");
if (mListener) {
mListener->BeginResults();
@ -2647,8 +2526,9 @@ nsCycleCollector::ScanRoots(bool aFullySynchGraphBuild)
mListener->End();
mListener = nullptr;
timeLog.Checkpoint("ScanRoots::listener");
}
timeLog.Checkpoint("ScanRoots()");
}
@ -3011,7 +2891,7 @@ nsCycleCollector::Collect(ccType aCCType,
// promoted to a strong reference after ScanRoots has finished.
// See bug 926533.
PrintPhase("ScanRoots");
ScanRoots(startedIdle);
ScanRoots();
PrintPhase("CollectWhite");
collectedAny = CollectWhite();
break;