Bug 1114804 - Make ISupports use the standard deferred finalizer code. r=peterv

This commit is contained in:
Andrew McCreight 2015-03-10 08:35:47 -07:00
parent 5406e27070
commit b1093185b2
3 changed files with 33 additions and 70 deletions

View File

@ -2865,14 +2865,24 @@ private:
typename Conditional<IsRefcounted<T>::value, nsRefPtr<T>, OwnedNative>::Type mNative;
};
template<class T,
bool isISupports=IsBaseOf<nsISupports, T>::value>
class DeferredFinalizer
template<class T>
struct DeferredFinalizerImpl
{
typedef typename Conditional<IsRefcounted<T>::value,
nsRefPtr<T>, nsAutoPtr<T>>::Type SmartPtr;
typedef typename Conditional<IsSame<T, nsISupports>::value,
nsCOMPtr<T>,
typename Conditional<IsRefcounted<T>::value,
nsRefPtr<T>,
nsAutoPtr<T>>::Type>::Type SmartPtr;
typedef nsTArray<SmartPtr> SmartPtrArray;
static_assert(IsSame<T, nsISupports>::value || !IsBaseOf<nsISupports, T>::value,
"nsISupports classes should all use the nsISupports instantiation");
static inline void
AppendAndTake(nsTArray<nsCOMPtr<nsISupports>>& smartPtrArray, nsISupports* ptr)
{
smartPtrArray.AppendElement(dont_AddRef(ptr));
}
template<class U>
static inline void
AppendAndTake(nsTArray<nsRefPtr<U>>& smartPtrArray, U* ptr)
@ -2913,20 +2923,24 @@ class DeferredFinalizer
}
return false;
}
};
public:
template<class T,
bool isISupports=IsBaseOf<nsISupports, T>::value>
struct DeferredFinalizer
{
static void
AddForDeferredFinalization(T* aObject)
{
cyclecollector::DeferredFinalize(AppendDeferredFinalizePointer,
DeferredFinalize, aObject);
typedef DeferredFinalizerImpl<T> Impl;
cyclecollector::DeferredFinalize(Impl::AppendDeferredFinalizePointer,
Impl::DeferredFinalize, aObject);
}
};
template<class T>
class DeferredFinalizer<T, true>
struct DeferredFinalizer<T, true>
{
public:
static void
AddForDeferredFinalization(T* aObject)
{

View File

@ -94,7 +94,6 @@ class IncrementalFinalizeRunnable : public nsRunnable
typedef CycleCollectedJSRuntime::DeferredFinalizerTable DeferredFinalizerTable;
CycleCollectedJSRuntime* mRuntime;
nsTArray<nsISupports*> mSupports;
DeferredFinalizeArray mDeferredFinalizeFunctions;
uint32_t mFinalizeFunctionToRun;
bool mReleasing;
@ -108,7 +107,6 @@ class IncrementalFinalizeRunnable : public nsRunnable
public:
IncrementalFinalizeRunnable(CycleCollectedJSRuntime* aRt,
nsTArray<nsISupports*>& aMSupports,
DeferredFinalizerTable& aFinalizerTable);
virtual ~IncrementalFinalizeRunnable();
@ -508,7 +506,6 @@ CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
{
MOZ_ASSERT(mJSRuntime);
MOZ_ASSERT(!mDeferredFinalizerTable.Count());
MOZ_ASSERT(!mDeferredSupports.Length());
// Clear mPendingException first, since it might be cycle collected.
mPendingException = nullptr;
@ -1045,30 +1042,9 @@ CycleCollectedJSRuntime::DeferredFinalize(DeferredFinalizeAppendFunction aAppend
void
CycleCollectedJSRuntime::DeferredFinalize(nsISupports* aSupports)
{
#ifdef MOZ_CRASHREPORTER
// Bug 997908's crashes (in ReleaseSliceNow()) might be caused by
// intermittent failures here in nsTArray::AppendElement(). So if we see
// any failures, deliberately crash and include diagnostic information in
// the crash report.
size_t oldLength = mDeferredSupports.Length();
nsISupports** itemPtr = mDeferredSupports.AppendElement(aSupports);
size_t newLength = mDeferredSupports.Length();
nsISupports* item = mDeferredSupports.ElementAt(newLength - 1);
if ((newLength - oldLength != 1) || !itemPtr ||
(*itemPtr != aSupports) || (item != aSupports)) {
nsAutoCString debugInfo;
debugInfo.AppendPrintf("\noldLength [%u], newLength [%u], aSupports [%p], item [%p], itemPtr [%p], *itemPtr [%p]",
oldLength, newLength, aSupports, item, itemPtr, itemPtr ? *itemPtr : NULL);
#define CRASH_MESSAGE "nsTArray::AppendElement() failed!"
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("\nBug 997908: ") +
NS_LITERAL_CSTRING(CRASH_MESSAGE));
CrashReporter::AppendAppNotesToCrashReport(debugInfo);
MOZ_CRASH(CRASH_MESSAGE);
#undef CRASH_MESSAGE
}
#else
mDeferredSupports.AppendElement(aSupports);
#endif
typedef DeferredFinalizerImpl<nsISupports> Impl;
DeferredFinalize(Impl::AppendDeferredFinalizePointer, Impl::DeferredFinalize,
aSupports);
}
void
@ -1078,26 +1054,6 @@ CycleCollectedJSRuntime::DumpJSHeap(FILE* aFile)
}
bool
ReleaseSliceNow(uint32_t aSlice, void* aData)
{
MOZ_ASSERT(aSlice > 0, "nonsensical/useless call with slice == 0");
nsTArray<nsISupports*>* items = static_cast<nsTArray<nsISupports*>*>(aData);
uint32_t length = items->Length();
aSlice = std::min(aSlice, length);
for (uint32_t i = length; i > length - aSlice; --i) {
// Remove (and NS_RELEASE) the last entry in "items":
uint32_t lastItemIdx = i - 1;
nsISupports* wrapper = items->ElementAt(lastItemIdx);
items->RemoveElementAt(lastItemIdx);
NS_IF_RELEASE(wrapper);
}
return items->IsEmpty();
}
/* static */ PLDHashOperator
IncrementalFinalizeRunnable::DeferredFinalizerEnumerator(DeferredFinalizeFunction& aFunction,
void*& aData,
@ -1113,19 +1069,11 @@ IncrementalFinalizeRunnable::DeferredFinalizerEnumerator(DeferredFinalizeFunctio
}
IncrementalFinalizeRunnable::IncrementalFinalizeRunnable(CycleCollectedJSRuntime* aRt,
nsTArray<nsISupports*>& aSupports,
DeferredFinalizerTable& aFinalizers)
: mRuntime(aRt)
, mFinalizeFunctionToRun(0)
, mReleasing(false)
{
this->mSupports.SwapElements(aSupports);
DeferredFinalizeFunctionHolder* function =
mDeferredFinalizeFunctions.AppendElement();
function->run = ReleaseSliceNow;
function->data = &this->mSupports;
// Enumerate the hashtable into our array.
aFinalizers.Enumerate(DeferredFinalizerEnumerator, &mDeferredFinalizeFunctions);
}
@ -1191,7 +1139,6 @@ IncrementalFinalizeRunnable::Run()
{
if (mRuntime->mFinalizeRunnable != this) {
/* These items were already processed synchronously in JSGC_END. */
MOZ_ASSERT(!mSupports.Length());
MOZ_ASSERT(!mDeferredFinalizeFunctions.Length());
return NS_OK;
}
@ -1226,13 +1173,16 @@ CycleCollectedJSRuntime::FinalizeDeferredThings(DeferredFinalizeType aType)
return;
}
}
if (mDeferredFinalizerTable.Count() == 0) {
return;
}
mFinalizeRunnable = new IncrementalFinalizeRunnable(this,
mDeferredSupports,
mDeferredFinalizerTable);
// Everything should be gone now.
MOZ_ASSERT(!mDeferredSupports.Length());
MOZ_ASSERT(!mDeferredFinalizerTable.Count());
MOZ_ASSERT(mDeferredFinalizerTable.Count() == 0);
if (aType == FinalizeIncrementally) {
NS_DispatchToCurrentThread(mFinalizeRunnable);

View File

@ -301,7 +301,6 @@ private:
nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders;
nsTArray<nsISupports*> mDeferredSupports;
typedef nsDataHashtable<nsFuncPtrHashKey<DeferredFinalizeFunction>, void*>
DeferredFinalizerTable;
DeferredFinalizerTable mDeferredFinalizerTable;