Backout a5b21cffeebf (bug 743112) for intermittent but severe leaks; a=whatafunwaytospendtheday on a CLOSED TREE

This commit is contained in:
Ed Morley 2012-07-28 18:46:27 +01:00
Родитель 20d737e7b9
Коммит 4d7bcc30d0
5 изменённых файлов: 20 добавлений и 98 удалений

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

@ -541,9 +541,6 @@ struct JSRuntime : js::RuntimeFriendFields
/* The gcNumber at the time of the most recent GC's first slice. */ /* The gcNumber at the time of the most recent GC's first slice. */
uint64_t gcStartNumber; uint64_t gcStartNumber;
/* Whether the currently running GC can finish in multiple slices. */
int gcIsIncremental;
/* Whether all compartments are being collected in first GC slice. */ /* Whether all compartments are being collected in first GC slice. */
bool gcIsFull; bool gcIsFull;

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

@ -776,12 +776,6 @@ SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
return old; return old;
} }
JS_FRIEND_API(bool)
WasIncrementalGC(JSRuntime *rt)
{
return rt->gcIsIncremental;
}
jschar * jschar *
GCDescription::formatMessage(JSRuntime *rt) const GCDescription::formatMessage(JSRuntime *rt) const
{ {

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

@ -745,10 +745,6 @@ typedef void
extern JS_FRIEND_API(GCSliceCallback) extern JS_FRIEND_API(GCSliceCallback)
SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback); SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback);
/* Was the most recent GC run incrementally? */
extern JS_FRIEND_API(bool)
WasIncrementalGC(JSRuntime *rt);
/* /*
* Signals a good place to do an incremental slice, because the browser is * Signals a good place to do an incremental slice, because the browser is
* drawing a frame. * drawing a frame.

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

@ -3186,7 +3186,7 @@ ShouldPreserveJITCode(JSCompartment *c, int64_t currentTime)
} }
static void static void
BeginMarkPhase(JSRuntime *rt) BeginMarkPhase(JSRuntime *rt, bool isIncremental)
{ {
int64_t currentTime = PRMJ_Now(); int64_t currentTime = PRMJ_Now();
@ -3197,7 +3197,7 @@ BeginMarkPhase(JSRuntime *rt)
* arenas. This purge call ensures that we only mark arenas that have had * arenas. This purge call ensures that we only mark arenas that have had
* allocations after the incremental GC started. * allocations after the incremental GC started.
*/ */
if (rt->gcIsIncremental) { if (isIncremental) {
for (GCCompartmentsIter c(rt); !c.done(); c.next()) for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->arenas.purge(); c->arenas.purge();
} }
@ -3221,7 +3221,7 @@ BeginMarkPhase(JSRuntime *rt)
JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker)); JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker));
/* For non-incremental GC the following sweep discards the jit code. */ /* For non-incremental GC the following sweep discards the jit code. */
if (rt->gcIsIncremental) { if (isIncremental) {
for (GCCompartmentsIter c(rt); !c.done(); c.next()) { for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_DISCARD_CODE); gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_DISCARD_CODE);
c->discardJitCode(rt->defaultFreeOp()); c->discardJitCode(rt->defaultFreeOp());
@ -3314,7 +3314,7 @@ ValidateIncrementalMarking(JSRuntime *rt);
#endif #endif
static void static void
EndMarkPhase(JSRuntime *rt) EndMarkPhase(JSRuntime *rt, bool isIncremental)
{ {
{ {
gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_MARK); gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_MARK);
@ -3324,7 +3324,7 @@ EndMarkPhase(JSRuntime *rt)
JS_ASSERT(rt->gcMarker.isDrained()); JS_ASSERT(rt->gcMarker.isDrained());
#ifdef DEBUG #ifdef DEBUG
if (rt->gcIsIncremental) if (isIncremental)
ValidateIncrementalMarking(rt); ValidateIncrementalMarking(rt);
#endif #endif
@ -3891,7 +3891,7 @@ IncrementalCollectSlice(JSRuntime *rt,
} }
#endif #endif
rt->gcIsIncremental = rt->gcIncrementalState != NO_INCREMENTAL || bool isIncremental = rt->gcIncrementalState != NO_INCREMENTAL ||
budget != SliceBudget::Unlimited || budget != SliceBudget::Unlimited ||
zeal == ZealIncrementalRootsThenFinish || zeal == ZealIncrementalRootsThenFinish ||
zeal == ZealIncrementalMarkAllThenFinish; zeal == ZealIncrementalMarkAllThenFinish;
@ -3904,7 +3904,7 @@ IncrementalCollectSlice(JSRuntime *rt,
switch (rt->gcIncrementalState) { switch (rt->gcIncrementalState) {
case MARK_ROOTS: case MARK_ROOTS:
BeginMarkPhase(rt); BeginMarkPhase(rt, isIncremental);
PushZealSelectedObjects(rt); PushZealSelectedObjects(rt);
rt->gcIncrementalState = MARK; rt->gcIncrementalState = MARK;
@ -3939,7 +3939,7 @@ IncrementalCollectSlice(JSRuntime *rt,
break; break;
} }
EndMarkPhase(rt); EndMarkPhase(rt, isIncremental);
rt->gcIncrementalState = SWEEP; rt->gcIncrementalState = SWEEP;

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

@ -22,7 +22,6 @@
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "nsLayoutStatics.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsCCUncollectableMarker.h" #include "nsCCUncollectableMarker.h"
#include "jsfriendapi.h" #include "jsfriendapi.h"
@ -553,7 +552,7 @@ xpc_UnmarkSkippableJSHolders()
template<class T> static void template<class T> static void
DoDeferredRelease(nsTArray<T> &array) DoDeferredRelease(nsTArray<T> &array)
{ {
while (true) { while (1) {
PRUint32 count = array.Length(); PRUint32 count = array.Length();
if (!count) { if (!count) {
array.Compact(); array.Compact();
@ -565,74 +564,6 @@ DoDeferredRelease(nsTArray<T> &array)
} }
} }
class IncrementalReleaseRunnable : public nsRunnable
{
nsTArray<nsISupports *> items;
static const PRTime SliceMillis = 10; /* ms */
public:
IncrementalReleaseRunnable(nsTArray<nsISupports *> &items);
virtual ~IncrementalReleaseRunnable();
NS_DECL_NSIRUNNABLE
};
IncrementalReleaseRunnable::IncrementalReleaseRunnable(nsTArray<nsISupports *> &items)
{
nsLayoutStatics::AddRef();
this->items.SwapElements(items);
}
IncrementalReleaseRunnable::~IncrementalReleaseRunnable()
{
nsLayoutStatics::Release();
}
NS_IMETHODIMP
IncrementalReleaseRunnable::Run()
{
MOZ_ASSERT(NS_IsMainThread());
TimeDuration sliceTime = TimeDuration::FromMilliseconds(SliceMillis);
TimeStamp started = TimeStamp::Now();
PRUint32 counter = 0;
while (true) {
PRUint32 count = items.Length();
if (!count)
break;
nsISupports *wrapper = items[count - 1];
items.RemoveElementAt(count - 1);
NS_RELEASE(wrapper);
/* We don't want to read the clock too often. */
counter++;
if (counter == 100) {
counter = 0;
if (TimeStamp::Now() - started >= sliceTime)
break;
}
}
if (items.Length()) {
nsresult rv = NS_DispatchToMainThread(this);
if (NS_FAILED(rv))
Run();
}
return NS_OK;
}
static void
ReleaseIncrementally(nsTArray<nsISupports *> &array)
{
nsRefPtr<IncrementalReleaseRunnable> runnable = new IncrementalReleaseRunnable(array);
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv))
runnable->Run();
}
/* static */ void /* static */ void
XPCJSRuntime::GCCallback(JSRuntime *rt, JSGCStatus status) XPCJSRuntime::GCCallback(JSRuntime *rt, JSGCStatus status)
{ {
@ -655,10 +586,14 @@ XPCJSRuntime::GCCallback(JSRuntime *rt, JSGCStatus status)
case JSGC_END: case JSGC_END:
{ {
// Do any deferred releases of native objects. // Do any deferred releases of native objects.
if (js::WasIncrementalGC(rt)) #ifdef XPC_TRACK_DEFERRED_RELEASES
ReleaseIncrementally(self->mNativesToReleaseArray); printf("XPC - Begin deferred Release of %d nsISupports pointers\n",
else self->mNativesToReleaseArray.Length());
#endif
DoDeferredRelease(self->mNativesToReleaseArray); DoDeferredRelease(self->mNativesToReleaseArray);
#ifdef XPC_TRACK_DEFERRED_RELEASES
printf("XPC - End deferred Releases\n");
#endif
self->GetXPConnect()->ClearGCBeforeCC(); self->GetXPConnect()->ClearGCBeforeCC();
break; break;