Bug 1186780: Replace EnumerateRead with new iterators in some DOM code. r=bkelly

This commit is contained in:
Kyle Huey 2015-07-26 19:34:29 -07:00
parent fb0d08a02f
commit f96286d280
4 changed files with 195 additions and 348 deletions

View File

@ -336,86 +336,55 @@ const nsIID nsIStyleRule::COMTypeInfo<css::Rule, void>::kIID = NS_ISTYLE_RULE_II
namespace mozilla {
namespace dom {
static PLDHashOperator
CustomDefinitionsTraverse(CustomElementHashKey* aKey,
CustomElementDefinition* aDefinition,
void* aArg)
{
nsCycleCollectionTraversalCallback* cb =
static_cast<nsCycleCollectionTraversalCallback*>(aArg);
nsAutoPtr<LifecycleCallbacks>& callbacks = aDefinition->mCallbacks;
if (callbacks->mAttributeChangedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttributeChangedCallback.Value());
}
if (callbacks->mCreatedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mCustomDefinitions->mCallbacks->mCreatedCallback");
cb->NoteXPCOMChild(aDefinition->mCallbacks->mCreatedCallback.Value());
}
if (callbacks->mAttachedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mCustomDefinitions->mCallbacks->mAttachedCallback");
cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttachedCallback.Value());
}
if (callbacks->mDetachedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mCustomDefinitions->mCallbacks->mDetachedCallback");
cb->NoteXPCOMChild(aDefinition->mCallbacks->mDetachedCallback.Value());
}
return PL_DHASH_NEXT;
}
static PLDHashOperator
CandidatesTraverse(CustomElementHashKey* aKey,
nsTArray<nsRefPtr<Element>>* aData,
void* aArg)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aArg);
for (size_t i = 0; i < aData->Length(); ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mCandidatesMap->Element");
cb->NoteXPCOMChild(aData->ElementAt(i));
}
return PL_DHASH_NEXT;
}
struct CustomDefinitionTraceArgs
{
const TraceCallbacks& callbacks;
void* closure;
};
static PLDHashOperator
CustomDefinitionTrace(CustomElementHashKey *aKey,
CustomElementDefinition *aData,
void *aArg)
{
CustomDefinitionTraceArgs* traceArgs = static_cast<CustomDefinitionTraceArgs*>(aArg);
MOZ_ASSERT(aData, "Definition must not be null");
traceArgs->callbacks.Trace(&aData->mPrototype, "mCustomDefinitions prototype",
traceArgs->closure);
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(Registry)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Registry)
CustomDefinitionTraceArgs customDefinitionArgs = { aCallbacks, aClosure };
tmp->mCustomDefinitions.EnumerateRead(CustomDefinitionTrace,
&customDefinitionArgs);
for (auto iter = tmp->mCustomDefinitions.ConstIter(); !iter.Done();
iter.Next()) {
aCallbacks.Trace(&iter.UserData()->mPrototype,
"mCustomDefinitions prototype",
aClosure);
}
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Registry)
tmp->mCustomDefinitions.EnumerateRead(CustomDefinitionsTraverse, &cb);
tmp->mCandidatesMap.EnumerateRead(CandidatesTraverse, &cb);
for (auto iter = tmp->mCustomDefinitions.ConstIter(); !iter.Done();
iter.Next()) {
CustomElementDefinition* definition = iter.UserData();
auto callbacks = definition->mCallbacks;
if (callbacks->mAttributeChangedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
}
if (callbacks->mCreatedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mCustomDefinitions->mCallbacks->mCreatedCallback");
cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
}
if (callbacks->mAttachedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mCustomDefinitions->mCallbacks->mAttachedCallback");
cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value());
}
if (callbacks->mDetachedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mCustomDefinitions->mCallbacks->mDetachedCallback");
cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
}
}
for (auto iter = tmp->mCandidatesMap.ConstIter(); !iter.Done(); iter.Next()) {
auto data = iter.UserData();
for (size_t i = 0; i < data->Length(); ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCandidatesMap->Element");
cb.NoteXPCOMChild(data->ElementAt(i));
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -942,99 +911,60 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
return nullptr;
}
struct
nsExternalResourceEnumArgs
{
nsIDocument::nsSubDocEnumFunc callback;
void *data;
};
static PLDHashOperator
ExternalResourceEnumerator(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
nsExternalResourceEnumArgs* args =
static_cast<nsExternalResourceEnumArgs*>(aClosure);
bool next =
aData->mDocument ? args->callback(aData->mDocument, args->data) : true;
return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
}
void
nsExternalResourceMap::EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback,
void* aData)
{
nsExternalResourceEnumArgs args = { aCallback, aData };
mMap.EnumerateRead(ExternalResourceEnumerator, &args);
}
static PLDHashOperator
ExternalResourceTraverser(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mExternalResourceMap.mMap entry"
"->mDocument");
cb->NoteXPCOMChild(aData->mDocument);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mExternalResourceMap.mMap entry"
"->mViewer");
cb->NoteXPCOMChild(aData->mViewer);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mExternalResourceMap.mMap entry"
"->mLoadGroup");
cb->NoteXPCOMChild(aData->mLoadGroup);
return PL_DHASH_NEXT;
for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
auto data = iter.UserData();
if (data->mDocument && !aCallback(data->mDocument, aData)) {
break;
}
}
}
void
nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) const
nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* cb) const
{
// mPendingLoads will get cleared out as the requests complete, so
// no need to worry about those here.
mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
}
for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
auto data = iter.UserData();
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mExternalResourceMap.mMap entry"
"->mDocument");
cb->NoteXPCOMChild(data->mDocument);
static PLDHashOperator
ExternalResourceHider(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
if (aData->mViewer) {
aData->mViewer->Hide();
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mExternalResourceMap.mMap entry"
"->mViewer");
cb->NoteXPCOMChild(data->mViewer);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"mExternalResourceMap.mMap entry"
"->mLoadGroup");
cb->NoteXPCOMChild(data->mLoadGroup);
}
return PL_DHASH_NEXT;
}
void
nsExternalResourceMap::HideViewers()
{
mMap.EnumerateRead(ExternalResourceHider, nullptr);
}
static PLDHashOperator
ExternalResourceShower(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
if (aData->mViewer) {
aData->mViewer->Show();
for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
if (auto viewer = iter.UserData()->mViewer) {
viewer->Hide();
}
}
return PL_DHASH_NEXT;
}
void
nsExternalResourceMap::ShowViewers()
{
mMap.EnumerateRead(ExternalResourceShower, nullptr);
for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
if (auto viewer = iter.UserData()->mViewer) {
viewer->Show();
}
}
}
void
@ -1603,15 +1533,6 @@ nsDocument::nsDocument(const char* aContentType)
}
}
static PLDHashOperator
ClearAllBoxObjects(nsIContent* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
{
if (aBoxObject) {
aBoxObject->Clear();
}
return PL_DHASH_NEXT;
}
nsIDocument::~nsIDocument()
{
MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
@ -1752,10 +1673,7 @@ nsDocument::~nsDocument()
delete mHeaderData;
if (mBoxObjectTable) {
mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nullptr);
delete mBoxObjectTable;
}
MaybeClearBoxObjectTable();
mPendingTitleChangeEvent.Revoke();
@ -1866,18 +1784,6 @@ RadioGroupsTraverser(const nsAString& aKey, nsRadioGroupStruct* aData,
return PL_DHASH_NEXT;
}
static PLDHashOperator
BoxObjectTraverser(nsIContent* key, nsPIBoxObject* boxObject, void* userArg)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(userArg);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mBoxObjectTable entry");
cb->NoteXPCOMChild(boxObject);
return PL_DHASH_NEXT;
}
static const char* kNSURIs[] = {
"([none])",
"(xmlns)",
@ -1959,7 +1865,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
// The boxobject for an element will only exist as long as it's in the
// document, so we'll traverse the table here instead of from the element.
if (tmp->mBoxObjectTable) {
tmp->mBoxObjectTable->EnumerateRead(BoxObjectTraverser, &cb);
for (auto iter = tmp->mBoxObjectTable->ConstIter(); !iter.Done();
iter.Next()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mBoxObjectTable entry");
cb.NoteXPCOMChild(iter.UserData());
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
@ -2078,12 +1988,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPreloadingImages)
if (tmp->mBoxObjectTable) {
tmp->mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nullptr);
delete tmp->mBoxObjectTable;
tmp->mBoxObjectTable = nullptr;
}
tmp->MaybeClearBoxObjectTable();
if (tmp->mListenerManager) {
tmp->mListenerManager->Disconnect();
@ -3851,6 +3756,23 @@ nsDocument::MaybeRescheduleAnimationFrameNotifications()
}
}
void
nsDocument::MaybeClearBoxObjectTable()
{
if (!mBoxObjectTable) {
return;
}
for (auto iter = mBoxObjectTable->ConstIter(); !iter.Done(); iter.Next()) {
if (auto boxObject = iter.UserData()) {
boxObject->Clear();
}
}
delete mBoxObjectTable;
mBoxObjectTable = nullptr;
}
void
nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks)
{
@ -3899,14 +3821,6 @@ nsIDocument::ShouldThrottleFrameRequests()
return false;
}
PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey,
uint32_t aData,
void* userArg)
{
aKey->RequestDiscard();
return PL_DHASH_NEXT;
}
void
nsDocument::DeleteShell()
{
@ -3921,7 +3835,9 @@ nsDocument::DeleteShell()
// When our shell goes away, request that all our images be immediately
// discarded, so we don't carry around decoded image data for a document we
// no longer intend to paint.
mImageTracker.EnumerateRead(RequestDiscardEnumerator, nullptr);
for (auto iter = mImageTracker.ConstIter(); !iter.Done(); iter.Next()) {
iter.Key()->RequestDiscard();
}
// Now that we no longer have a shell, we need to forget about any FontFace
// objects for @font-face rules that came from the style set.
@ -10629,24 +10545,6 @@ nsDocument::NotifyMediaFeatureValuesChanged()
}
}
PLDHashOperator LockEnumerator(imgIRequest* aKey,
uint32_t aData,
void* userArg)
{
aKey->LockImage();
aKey->RequestDecode();
return PL_DHASH_NEXT;
}
PLDHashOperator UnlockEnumerator(imgIRequest* aKey,
uint32_t aData,
void* userArg)
{
aKey->UnlockImage();
return PL_DHASH_NEXT;
}
nsresult
nsDocument::SetImageLockingState(bool aLocked)
{
@ -10660,9 +10558,15 @@ nsDocument::SetImageLockingState(bool aLocked)
return NS_OK;
// Otherwise, iterate over our images and perform the appropriate action.
mImageTracker.EnumerateRead(aLocked ? LockEnumerator
: UnlockEnumerator,
nullptr);
for (auto iter = mImageTracker.ConstIter(); !iter.Done(); iter.Next()) {
imgIRequest* image = iter.Key();
if (aLocked) {
image->LockImage();
image->RequestDecode();
} else {
image->UnlockImage();
}
}
// Update state.
mLockingImages = aLocked;
@ -10670,22 +10574,6 @@ nsDocument::SetImageLockingState(bool aLocked)
return NS_OK;
}
PLDHashOperator IncrementAnimationEnumerator(imgIRequest* aKey,
uint32_t aData,
void* userArg)
{
aKey->IncrementAnimationConsumers();
return PL_DHASH_NEXT;
}
PLDHashOperator DecrementAnimationEnumerator(imgIRequest* aKey,
uint32_t aData,
void* userArg)
{
aKey->DecrementAnimationConsumers();
return PL_DHASH_NEXT;
}
void
nsDocument::SetImagesNeedAnimating(bool aAnimating)
{
@ -10694,9 +10582,14 @@ nsDocument::SetImagesNeedAnimating(bool aAnimating)
return;
// Otherwise, iterate over our images and perform the appropriate action.
mImageTracker.EnumerateRead(aAnimating ? IncrementAnimationEnumerator
: DecrementAnimationEnumerator,
nullptr);
for (auto iter = mImageTracker.ConstIter(); !iter.Done(); iter.Next()) {
imgIRequest* image = iter.Key();
if (aAnimating) {
image->IncrementAnimationConsumers();
} else {
image->DecrementAnimationConsumers();
}
}
// Update state.
mAnimatingImages = aAnimating;

View File

@ -1737,6 +1737,8 @@ private:
// requestAnimationFrame, if it's OK to do so.
void MaybeRescheduleAnimationFrameNotifications();
void MaybeClearBoxObjectTable();
// These are not implemented and not supported.
nsDocument(const nsDocument& aOther);
nsDocument& operator=(const nsDocument& aOther);

View File

@ -120,26 +120,18 @@ nsFrameMessageManager::~nsFrameMessageManager()
}
}
static PLDHashOperator
CycleCollectorTraverseListeners(const nsAString& aKey,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aCb)
{
nsCycleCollectionTraversalCallback* cb =
static_cast<nsCycleCollectionTraversalCallback*> (aCb);
uint32_t count = aListeners->Length();
for (uint32_t i = 0; i < count; ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "listeners[i] mStrongListener");
cb->NoteXPCOMChild(aListeners->ElementAt(i).mStrongListener.get());
}
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
tmp->mListeners.EnumerateRead(CycleCollectorTraverseListeners,
static_cast<void*>(&cb));
for (auto iter = tmp->mListeners.ConstIter(); !iter.Done(); iter.Next()) {
auto listeners = iter.UserData();
const uint32_t count = listeners->Length();
for (uint32_t i = 0; i < count; ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "listeners[i] mStrongListener");
cb.NoteXPCOMChild(listeners->ElementAt(i).mStrongListener.get());
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
@ -415,35 +407,6 @@ nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
return NS_OK;
}
#ifdef DEBUG
typedef struct
{
nsCOMPtr<nsISupports> mCanonical;
nsWeakPtr mWeak;
} CanonicalCheckerParams;
static PLDHashOperator
CanonicalChecker(const nsAString& aKey,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aParams)
{
CanonicalCheckerParams* params =
static_cast<CanonicalCheckerParams*> (aParams);
uint32_t count = aListeners->Length();
for (uint32_t i = 0; i < count; i++) {
if (!aListeners->ElementAt(i).mWeakListener) {
continue;
}
nsCOMPtr<nsISupports> otherCanonical =
do_QueryReferent(aListeners->ElementAt(i).mWeakListener);
MOZ_ASSERT((params->mCanonical == otherCanonical) ==
(params->mWeak == aListeners->ElementAt(i).mWeakListener));
}
return PL_DHASH_NEXT;
}
#endif
NS_IMETHODIMP
nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
nsIMessageListener* aListener)
@ -452,15 +415,24 @@ nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
NS_ENSURE_TRUE(weak, NS_ERROR_NO_INTERFACE);
#ifdef DEBUG
// It's technically possible that one object X could give two different
// nsIWeakReference*'s when you do_GetWeakReference(X). We really don't want
// this to happen; it will break e.g. RemoveWeakMessageListener. So let's
// check that we're not getting ourselves into that situation.
nsCOMPtr<nsISupports> canonical = do_QueryInterface(aListener);
CanonicalCheckerParams params;
params.mCanonical = canonical;
params.mWeak = weak;
mListeners.EnumerateRead(CanonicalChecker, (void*)&params);
{
// It's technically possible that one object X could give two different
// nsIWeakReference*'s when you do_GetWeakReference(X). We really don't
// want this to happen; it will break e.g. RemoveWeakMessageListener. So
// let's check that we're not getting ourselves into that situation.
nsCOMPtr<nsISupports> canonical = do_QueryInterface(aListener);
for (auto iter = mListeners.ConstIter(); !iter.Done(); iter.Next()) {
auto listeners = iter.UserData();
const uint32_t count = listeners->Length();
for (uint32_t i = 0; i < count; i++) {
if (auto listener = listeners->ElementAt(i).mWeakListener) {
nsCOMPtr<nsISupports> otherCanonical = do_QueryReferent(listener);
MOZ_ASSERT((canonical == otherCanonical) == (weak == listener));
}
}
}
}
#endif
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
@ -1472,55 +1444,45 @@ protected:
NS_IMPL_ISUPPORTS(MessageManagerReporter, nsIMemoryReporter)
static PLDHashOperator
CollectMessageListenerData(const nsAString& aKey,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aData)
{
MessageManagerReferentCount* referentCount =
static_cast<MessageManagerReferentCount*>(aData);
uint32_t listenerCount = aListeners->Length();
if (!listenerCount) {
return PL_DHASH_NEXT;
}
nsString key(aKey);
uint32_t oldCount = 0;
referentCount->mMessageCounter.Get(key, &oldCount);
uint32_t currentCount = oldCount + listenerCount;
referentCount->mMessageCounter.Put(key, currentCount);
// Keep track of messages that have a suspiciously large
// number of referents (symptom of leak).
if (currentCount == MessageManagerReporter::kSuspectReferentCount) {
referentCount->mSuspectMessages.AppendElement(key);
}
for (uint32_t i = 0; i < listenerCount; ++i) {
const nsMessageListenerInfo& listenerInfo =
aListeners->ElementAt(i);
if (listenerInfo.mWeakListener) {
nsCOMPtr<nsISupports> referent =
do_QueryReferent(listenerInfo.mWeakListener);
if (referent) {
referentCount->mWeakAlive++;
} else {
referentCount->mWeakDead++;
}
} else {
referentCount->mStrong++;
}
}
return PL_DHASH_NEXT;
}
void
MessageManagerReporter::CountReferents(nsFrameMessageManager* aMessageManager,
MessageManagerReferentCount* aReferentCount)
{
aMessageManager->mListeners.EnumerateRead(CollectMessageListenerData,
aReferentCount);
for (auto iter = aMessageManager->mListeners.ConstIter();
!iter.Done(); iter.Next()) {
auto listeners = iter.UserData();
const uint32_t listenerCount = listeners->Length();
if (!listenerCount) {
continue;
}
nsString key(iter.Key());
uint32_t oldCount = 0;
aReferentCount->mMessageCounter.Get(key, &oldCount);
uint32_t currentCount = oldCount + listenerCount;
aReferentCount->mMessageCounter.Put(key, currentCount);
// Keep track of messages that have a suspiciously large
// number of referents (symptom of leak).
if (currentCount == MessageManagerReporter::kSuspectReferentCount) {
aReferentCount->mSuspectMessages.AppendElement(key);
}
for (uint32_t i = 0; i < listenerCount; ++i) {
const nsMessageListenerInfo& listenerInfo = listeners->ElementAt(i);
if (listenerInfo.mWeakListener) {
nsCOMPtr<nsISupports> referent =
do_QueryReferent(listenerInfo.mWeakListener);
if (referent) {
aReferentCount->mWeakAlive++;
} else {
aReferentCount->mWeakDead++;
}
} else {
aReferentCount->mStrong++;
}
}
}
// Add referent count in child managers because the listeners
// participate in messages dispatched from parent message manager.
@ -2167,24 +2129,19 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
}
static PLDHashOperator
CycleCollectorMarkListeners(const nsAString& aKey,
nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
void* aData)
{
uint32_t count = aListeners->Length();
for (uint32_t i = 0; i < count; i++) {
if (aListeners->ElementAt(i).mStrongListener) {
xpc_TryUnmarkWrappedGrayObject(aListeners->ElementAt(i).mStrongListener);
}
}
return PL_DHASH_NEXT;
}
bool
nsFrameMessageManager::MarkForCC()
{
mListeners.EnumerateRead(CycleCollectorMarkListeners, nullptr);
for (auto iter = mListeners.ConstIter(); !iter.Done(); iter.Next()) {
auto listeners = iter.UserData();
const uint32_t count = listeners->Length();
for (uint32_t i = 0; i < count; i++) {
if (auto listener = listeners->ElementAt(i).mStrongListener) {
xpc_TryUnmarkWrappedGrayObject(listener);
}
}
}
if (mRefCnt.IsPurple()) {
mRefCnt.RemovePurple();

View File

@ -316,18 +316,13 @@ nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)
mFirstBinding = aBinding;
}
static PLDHashOperator
FlushScopedSkinSheets(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
{
aProto->FlushSkinSheets();
return PL_DHASH_NEXT;
}
void
nsXBLDocumentInfo::FlushSkinStylesheets()
{
if (mBindingTable) {
mBindingTable->EnumerateRead(FlushScopedSkinSheets, nullptr);
for (auto iter = mBindingTable->ConstIter(); !iter.Done(); iter.Next()) {
iter.UserData()->FlushSkinSheets();
}
}
}