mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 716716 - Add templated way to iterate over purple buffer entries. r=smaug
This commit is contained in:
parent
fd769e05e8
commit
3a1c8cd8d3
@ -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 ¶ms)
|
||||
: 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
|
||||
|
Loading…
Reference in New Issue
Block a user