зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 300f5b7d72e1 (bug 897433) for intermittent Linux dromaeo crashes.
This commit is contained in:
Родитель
5c2c464bdd
Коммит
496513c7cd
|
@ -135,8 +135,6 @@ static PRLogModuleInfo* gJSDiagnostics;
|
|||
// Large value used to specify that a script should run essentially forever
|
||||
#define NS_UNLIMITED_SCRIPT_RUNTIME (0x40000000LL << 32)
|
||||
|
||||
#define NS_MAJOR_FORGET_SKIPPABLE_CALLS 2
|
||||
|
||||
// if you add statics here, add them to the list in nsJSRuntime::Startup
|
||||
|
||||
static nsITimer *sGCTimer;
|
||||
|
@ -2504,9 +2502,7 @@ FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless)
|
|||
{
|
||||
PRTime startTime = PR_Now();
|
||||
FinishAnyIncrementalGC();
|
||||
bool earlyForgetSkippable =
|
||||
sCleanupsSinceLastGC < NS_MAJOR_FORGET_SKIPPABLE_CALLS;
|
||||
nsCycleCollector_forgetSkippable(aRemoveChildless, earlyForgetSkippable);
|
||||
nsCycleCollector_forgetSkippable(aRemoveChildless);
|
||||
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
++sCleanupsSinceLastGC;
|
||||
PRTime delta = PR_Now() - startTime;
|
||||
|
@ -2556,9 +2552,8 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
|
|||
|
||||
// Run forgetSkippable synchronously to reduce the size of the CC graph. This
|
||||
// is particularly useful if we recently finished a GC.
|
||||
if (sCleanupsSinceLastGC < NS_MAJOR_FORGET_SKIPPABLE_CALLS &&
|
||||
aExtraForgetSkippableCalls >= 0) {
|
||||
while (sCleanupsSinceLastGC < NS_MAJOR_FORGET_SKIPPABLE_CALLS) {
|
||||
if (sCleanupsSinceLastGC < 2 && aExtraForgetSkippableCalls >= 0) {
|
||||
while (sCleanupsSinceLastGC < 2) {
|
||||
FireForgetSkippable(nsCycleCollector_suspectedCount(), false);
|
||||
ranSyncForgetSkippable = true;
|
||||
}
|
||||
|
|
|
@ -86,12 +86,6 @@
|
|||
"kind": "flag",
|
||||
"description": "Set if the cycle collector ran out of memory at some point"
|
||||
},
|
||||
"CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING": {
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
"n_buckets": 50,
|
||||
"description": "Time spent on one asynchronous SnowWhite freeing (ms)"
|
||||
},
|
||||
"FORGET_SKIPPABLE_MAX": {
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
|
|
|
@ -775,15 +775,14 @@ public:
|
|||
|
||||
void SelectPointers(GCGraphBuilder &builder);
|
||||
|
||||
// RemoveSkippable removes entries from the purple buffer synchronously
|
||||
// (1) if aAsyncSnowWhiteFreeing is false and nsPurpleBufferEntry::mRefCnt is 0 or
|
||||
// (2) if the object's nsXPCOMCycleCollectionParticipant::CanSkip() returns true or
|
||||
// (3) if nsPurpleBufferEntry::mRefCnt->IsPurple() is false.
|
||||
// (4) If removeChildlessNodes is true, then any nodes in the purple buffer
|
||||
// that will have no children in the cycle collector graph will also be
|
||||
// removed. CanSkip() may be run on these children.
|
||||
// RemoveSkippable removes entries from the purple buffer if
|
||||
// nsPurpleBufferEntry::mRefCnt is 0 or if the object's
|
||||
// nsXPCOMCycleCollectionParticipant::CanSkip() returns true or
|
||||
// if nsPurpleBufferEntry::mRefCnt->IsPurple() is false.
|
||||
// If removeChildlessNodes is true, then any nodes in the purple buffer
|
||||
// that will have no children in the cycle collector graph will also be
|
||||
// removed. CanSkip() may be run on these children.
|
||||
void RemoveSkippable(bool removeChildlessNodes,
|
||||
bool aAsyncSnowWhiteFreeing,
|
||||
CC_ForgetSkippableCallback aCb);
|
||||
|
||||
nsPurpleBufferEntry* NewEntry()
|
||||
|
@ -1038,7 +1037,7 @@ public:
|
|||
void ScanRoots();
|
||||
void ScanWeakMaps();
|
||||
|
||||
void ForgetSkippable(bool aRemoveChildlessNodes, bool aAsyncSnowWhiteFreeing);
|
||||
void ForgetSkippable(bool removeChildlessNodes);
|
||||
|
||||
// returns whether anything was collected
|
||||
bool CollectWhite(nsICycleCollectorListener *aListener);
|
||||
|
@ -1073,12 +1072,11 @@ public:
|
|||
bool BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
|
||||
bool FinishCollection(nsICycleCollectorListener *aListener);
|
||||
|
||||
bool FreeSnowWhite(bool aUntilNoSWInPurpleBuffer);
|
||||
void FreeSnowWhite(bool aUntilNoSWInPurpleBuffer);
|
||||
|
||||
// If there is a cycle collector available in the current thread,
|
||||
// this calls FreeSnowWhite(false). Returns true if some
|
||||
// snow-white objects were found.
|
||||
static bool TryToFreeSnowWhite();
|
||||
// this calls FreeSnowWhite(false).
|
||||
static void TryToFreeSnowWhite();
|
||||
|
||||
uint32_t SuspectedCount();
|
||||
void Shutdown();
|
||||
|
@ -2150,33 +2148,6 @@ MayHaveChild(void *o, nsCycleCollectionParticipant* cp)
|
|||
return cf.MayHaveChild();
|
||||
}
|
||||
|
||||
class AsyncFreeSnowWhite : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
PRTime start = PR_Now();
|
||||
bool hadSnowWhiteObjects = nsCycleCollector::TryToFreeSnowWhite();
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING,
|
||||
uint32_t(PR_Now() - start) / PR_USEC_PER_MSEC);
|
||||
if (hadSnowWhiteObjects && !mContinuation) {
|
||||
mContinuation = true;
|
||||
NS_DispatchToCurrentThread(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void Dispatch(bool aContinuation = false)
|
||||
{
|
||||
nsRefPtr<AsyncFreeSnowWhite> ev = new AsyncFreeSnowWhite(aContinuation);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
}
|
||||
private:
|
||||
AsyncFreeSnowWhite(bool aContinuation) : mContinuation(aContinuation) {}
|
||||
|
||||
bool mContinuation;
|
||||
};
|
||||
|
||||
struct SnowWhiteObject
|
||||
{
|
||||
void* mPointer;
|
||||
|
@ -2238,12 +2209,9 @@ class RemoveSkippableVisitor : public SnowWhiteKiller
|
|||
{
|
||||
public:
|
||||
RemoveSkippableVisitor(uint32_t aMaxCount, bool aRemoveChildlessNodes,
|
||||
bool aAsyncSnowWhiteFreeing,
|
||||
CC_ForgetSkippableCallback aCb)
|
||||
: SnowWhiteKiller(aAsyncSnowWhiteFreeing ? 0 : aMaxCount),
|
||||
: SnowWhiteKiller(aMaxCount),
|
||||
mRemoveChildlessNodes(aRemoveChildlessNodes),
|
||||
mAsyncSnowWhiteFreeing(aAsyncSnowWhiteFreeing),
|
||||
mDispatchedDeferredDeletion(false),
|
||||
mCallback(aCb)
|
||||
{}
|
||||
|
||||
|
@ -2254,10 +2222,6 @@ public:
|
|||
if (mCallback) {
|
||||
mCallback();
|
||||
}
|
||||
if (HasSnowWhiteObjects()) {
|
||||
// Effectively a continuation.
|
||||
AsyncFreeSnowWhite::Dispatch(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2265,12 +2229,7 @@ public:
|
|||
{
|
||||
MOZ_ASSERT(aEntry->mObject, "null mObject in purple buffer");
|
||||
if (!aEntry->mRefCnt->get()) {
|
||||
if (!mAsyncSnowWhiteFreeing) {
|
||||
SnowWhiteKiller::Visit(aBuffer, aEntry);
|
||||
} else if (!mDispatchedDeferredDeletion) {
|
||||
mDispatchedDeferredDeletion = true;
|
||||
nsCycleCollector_dispatchDeferredDeletion();
|
||||
}
|
||||
SnowWhiteKiller::Visit(aBuffer, aEntry);
|
||||
return;
|
||||
}
|
||||
void *o = aEntry->mObject;
|
||||
|
@ -2285,44 +2244,57 @@ public:
|
|||
|
||||
private:
|
||||
bool mRemoveChildlessNodes;
|
||||
bool mAsyncSnowWhiteFreeing;
|
||||
bool mDispatchedDeferredDeletion;
|
||||
CC_ForgetSkippableCallback mCallback;
|
||||
};
|
||||
|
||||
void
|
||||
nsPurpleBuffer::RemoveSkippable(bool aRemoveChildlessNodes,
|
||||
bool aAsyncSnowWhiteFreeing,
|
||||
nsPurpleBuffer::RemoveSkippable(bool removeChildlessNodes,
|
||||
CC_ForgetSkippableCallback aCb)
|
||||
{
|
||||
RemoveSkippableVisitor visitor(Count(), aRemoveChildlessNodes,
|
||||
aAsyncSnowWhiteFreeing, aCb);
|
||||
RemoveSkippableVisitor visitor(Count(), removeChildlessNodes, aCb);
|
||||
VisitEntries(visitor);
|
||||
// If we're about to delete some objects when visitor goes out of scope,
|
||||
// try to delete some more soon.
|
||||
if (visitor.HasSnowWhiteObjects()) {
|
||||
nsCycleCollector_dispatchDeferredDeletion();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
class AsyncFreeSnowWhite : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsCycleCollector::TryToFreeSnowWhite();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void Dispatch()
|
||||
{
|
||||
nsRefPtr<AsyncFreeSnowWhite> ev = new AsyncFreeSnowWhite();
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
nsCycleCollector::FreeSnowWhite(bool aUntilNoSWInPurpleBuffer)
|
||||
{
|
||||
bool hadSnowWhiteObjects = false;
|
||||
do {
|
||||
SnowWhiteKiller visitor(mPurpleBuf.Count());
|
||||
mPurpleBuf.VisitEntries(visitor);
|
||||
hadSnowWhiteObjects = hadSnowWhiteObjects ||
|
||||
visitor.HasSnowWhiteObjects();
|
||||
if (!visitor.HasSnowWhiteObjects()) {
|
||||
break;
|
||||
}
|
||||
} while (aUntilNoSWInPurpleBuffer);
|
||||
return hadSnowWhiteObjects;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
/* static */ void
|
||||
nsCycleCollector::TryToFreeSnowWhite()
|
||||
{
|
||||
CollectorData* data = sCollectorData.get();
|
||||
return data->mCollector ?
|
||||
data->mCollector->FreeSnowWhite(false) :
|
||||
false;
|
||||
if (data->mCollector) {
|
||||
data->mCollector->FreeSnowWhite(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2332,14 +2304,12 @@ nsCycleCollector::SelectPurple(GCGraphBuilder &builder)
|
|||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes,
|
||||
bool aAsyncSnowWhiteFreeing)
|
||||
nsCycleCollector::ForgetSkippable(bool removeChildlessNodes)
|
||||
{
|
||||
if (mJSRuntime) {
|
||||
mJSRuntime->PrepareForForgetSkippable();
|
||||
}
|
||||
mPurpleBuf.RemoveSkippable(aRemoveChildlessNodes, aAsyncSnowWhiteFreeing,
|
||||
mForgetSkippableCB);
|
||||
mPurpleBuf.RemoveSkippable(removeChildlessNodes, mForgetSkippableCB);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE void
|
||||
|
@ -3287,8 +3257,7 @@ nsCycleCollector_setForgetSkippableCallback(CC_ForgetSkippableCallback aCB)
|
|||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes,
|
||||
bool aAsyncSnowWhiteFreeing)
|
||||
nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes)
|
||||
{
|
||||
CollectorData *data = sCollectorData.get();
|
||||
|
||||
|
@ -3298,8 +3267,7 @@ nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes,
|
|||
|
||||
PROFILER_LABEL("CC", "nsCycleCollector_forgetSkippable");
|
||||
TimeLog timeLog;
|
||||
data->mCollector->ForgetSkippable(aRemoveChildlessNodes,
|
||||
aAsyncSnowWhiteFreeing);
|
||||
data->mCollector->ForgetSkippable(aRemoveChildlessNodes);
|
||||
timeLog.Checkpoint("ForgetSkippable()");
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,7 @@ void nsCycleCollector_setBeforeUnlinkCallback(CC_BeforeUnlinkCallback aCB);
|
|||
typedef void (*CC_ForgetSkippableCallback)(void);
|
||||
void nsCycleCollector_setForgetSkippableCallback(CC_ForgetSkippableCallback aCB);
|
||||
|
||||
void nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes = false,
|
||||
bool aAsyncSnowWhiteFreeing = false);
|
||||
void nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes = false);
|
||||
|
||||
void nsCycleCollector_dispatchDeferredDeletion();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче