Bug 716716 - Add templated way to iterate over purple buffer entries. r=smaug

This commit is contained in:
Andrew McCreight 2013-04-30 10:41:23 -07:00
parent fd769e05e8
commit 3a1c8cd8d3

View File

@ -689,9 +689,18 @@ private:
"ill-sized nsPurpleBuffer::Block"
);
}
void StaticAsserts();
template <class PurpleVisitor>
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 &params)
: mParams(params)
{
@ -711,6 +721,14 @@ public:
FreeBlocks();
}
template <class PurpleVisitor>
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