From 3a1c8cd8d306c6c3c6f2a272060af95196e09ce1 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 30 Apr 2013 10:41:23 -0700 Subject: [PATCH] Bug 716716 - Add templated way to iterate over purple buffer entries. r=smaug --- xpcom/base/nsCycleCollector.cpp | 155 +++++++++++++++++++------------- 1 file changed, 93 insertions(+), 62 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index f192f60368c..c4fd459881f 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -689,9 +689,18 @@ private: "ill-sized nsPurpleBuffer::Block" ); } - void StaticAsserts(); + + template + void VisitEntries(nsPurpleBuffer &aBuffer, PurpleVisitor &aVisitor) + { + nsPurpleBufferEntry *eEnd = ArrayEnd(mEntries); + for (nsPurpleBufferEntry *e = mEntries; e != eEnd; ++e) { + if (!(uintptr_t(e->mObject) & uintptr_t(1))) { + aVisitor.Visit(aBuffer, e); + } + } + } }; -public: // This class wraps a linked list of the elements in the purple // buffer. @@ -700,6 +709,7 @@ public: Block mFirstBlock; nsPurpleBufferEntry *mFreeList; +public: nsPurpleBuffer(nsCycleCollectorParams ¶ms) : mParams(params) { @@ -711,6 +721,14 @@ public: FreeBlocks(); } + template + void VisitEntries(PurpleVisitor &aVisitor) + { + for (Block *b = &mFirstBlock; b; b = b->mNext) { + b->VisitEntries(*this, aVisitor); + } + } + void InitBlocks() { mCount = 0; @@ -748,25 +766,25 @@ public: mFirstBlock.mNext = nullptr; } - void UnmarkRemainingPurple(Block *b) + struct UnmarkRemainingPurpleVisitor { - for (nsPurpleBufferEntry *e = b->mEntries, - *eEnd = ArrayEnd(b->mEntries); - e != eEnd; ++e) { - if (!(uintptr_t(e->mObject) & uintptr_t(1))) { - // This is a real entry (rather than something on the - // free list). - if (e->mObject) { - void *obj = e->mObject; - nsCycleCollectionParticipant *cp = e->mParticipant; - CanonicalizeParticipant(&obj, &cp); - cp->UnmarkIfPurple(obj); - } - - if (--mCount == 0) - break; + void + Visit(nsPurpleBuffer &aBuffer, nsPurpleBufferEntry *aEntry) + { + if (aEntry->mObject) { + void *obj = aEntry->mObject; + nsCycleCollectionParticipant *cp = aEntry->mParticipant; + CanonicalizeParticipant(&obj, &cp); + cp->UnmarkIfPurple(obj); + --aBuffer.mCount; } } + }; + + void UnmarkRemainingPurple(Block *b) + { + UnmarkRemainingPurpleVisitor visitor; + b->VisitEntries(*this, visitor); } void SelectPointers(GCGraphBuilder &builder); @@ -859,32 +877,38 @@ public: static bool AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp); -void -nsPurpleBuffer::SelectPointers(GCGraphBuilder &aBuilder) +struct SelectPointersVisitor { - // Walk through all the blocks. - for (Block *b = &mFirstBlock; b; b = b->mNext) { - for (nsPurpleBufferEntry *e = b->mEntries, - *eEnd = ArrayEnd(b->mEntries); - e != eEnd; ++e) { - if (!(uintptr_t(e->mObject) & uintptr_t(1))) { - // This is a real entry (rather than something on the - // free list). - if (e->mObject && e->mNotPurple) { - void* o = e->mObject; - nsCycleCollectionParticipant* cp = e->mParticipant; - CanonicalizeParticipant(&o, &cp); - cp->UnmarkIfPurple(o); - Remove(e); - } else if (!e->mObject || AddPurpleRoot(aBuilder, e->mObject, - e->mParticipant)) { - Remove(e); - } - } + SelectPointersVisitor(GCGraphBuilder &aBuilder) + : mBuilder(aBuilder) + {} + + void + Visit(nsPurpleBuffer &aBuffer, nsPurpleBufferEntry *aEntry) + { + if (aEntry->mObject && aEntry->mNotPurple) { + void* o = aEntry->mObject; + nsCycleCollectionParticipant* cp = aEntry->mParticipant; + CanonicalizeParticipant(&o, &cp); + cp->UnmarkIfPurple(o); + aBuffer.Remove(aEntry); + } else if (!aEntry->mObject || + AddPurpleRoot(mBuilder, aEntry->mObject, aEntry->mParticipant)) { + aBuffer.Remove(aEntry); } } - NS_WARN_IF_FALSE(mCount == 0, "AddPurpleRoot failed"); +private: + GCGraphBuilder &mBuilder; +}; + +void +nsPurpleBuffer::SelectPointers(GCGraphBuilder &aBuilder) +{ + SelectPointersVisitor visitor(aBuilder); + VisitEntries(visitor); + + MOZ_ASSERT(mCount == 0, "AddPurpleRoot failed"); if (mCount == 0) { FreeBlocks(); InitBlocks(); @@ -2120,31 +2144,38 @@ MayHaveChild(void *o, nsCycleCollectionParticipant* cp) return cf.MayHaveChild(); } +class RemoveSkippableVisitor +{ +public: + RemoveSkippableVisitor(bool aRemoveChildlessNodes) + : mRemoveChildlessNodes(aRemoveChildlessNodes) + {} + + void + Visit(nsPurpleBuffer &aBuffer, nsPurpleBufferEntry *aEntry) + { + if (aEntry->mObject) { + void *o = aEntry->mObject; + nsCycleCollectionParticipant *cp = aEntry->mParticipant; + CanonicalizeParticipant(&o, &cp); + if (!aEntry->mNotPurple && !cp->CanSkip(o, false) && + (!mRemoveChildlessNodes || MayHaveChild(o, cp))) { + return; + } + cp->UnmarkIfPurple(o); + } + aBuffer.Remove(aEntry); + } + +private: + bool mRemoveChildlessNodes; +}; + void nsPurpleBuffer::RemoveSkippable(bool removeChildlessNodes) { - // Walk through all the blocks. - for (Block *b = &mFirstBlock; b; b = b->mNext) { - for (nsPurpleBufferEntry *e = b->mEntries, - *eEnd = ArrayEnd(b->mEntries); - e != eEnd; ++e) { - if (!(uintptr_t(e->mObject) & uintptr_t(1))) { - // This is a real entry (rather than something on the - // free list). - if (e->mObject) { - void *o = e->mObject; - nsCycleCollectionParticipant *cp = e->mParticipant; - CanonicalizeParticipant(&o, &cp); - if (!e->mNotPurple && !cp->CanSkip(o, false) && - (!removeChildlessNodes || MayHaveChild(o, cp))) { - continue; - } - cp->UnmarkIfPurple(o); - } - Remove(e); - } - } - } + RemoveSkippableVisitor visitor(removeChildlessNodes); + VisitEntries(visitor); } void