mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-11 01:57:00 +00:00
Bug 1114804 - Make ISupports use the standard deferred finalizer code. r=peterv
This commit is contained in:
parent
5406e27070
commit
b1093185b2
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -301,7 +301,6 @@ private:
|
||||
|
||||
nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders;
|
||||
|
||||
nsTArray<nsISupports*> mDeferredSupports;
|
||||
typedef nsDataHashtable<nsFuncPtrHashKey<DeferredFinalizeFunction>, void*>
|
||||
DeferredFinalizerTable;
|
||||
DeferredFinalizerTable mDeferredFinalizerTable;
|
||||
|
Loading…
x
Reference in New Issue
Block a user