mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-30 19:17:31 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
02a8a3cf55
3 changed files with 163 additions and 167 deletions
|
|
@ -4640,8 +4640,8 @@ struct LengthPercentNumberCalcOps : public css::NumbersAlreadyNormalizedOps
|
||||||
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
|
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
|
||||||
result_type aValue1, float aValue2)
|
result_type aValue1, float aValue2)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_TimesR ||
|
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_R ||
|
||||||
aCalcFunction == eCSSUnit_Divided,
|
aCalcFunction == eCSSUnit_Calc_Divided,
|
||||||
"unexpected unit");
|
"unexpected unit");
|
||||||
result_type result;
|
result_type result;
|
||||||
if (aCalcFunction == eCSSUnit_Calc_Divided) {
|
if (aCalcFunction == eCSSUnit_Calc_Divided) {
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,9 @@ class SegmentedVector : private AllocPolicy
|
||||||
? (IdealSegmentSize - kSingleElementSegmentSize) / sizeof(T) + 1
|
? (IdealSegmentSize - kSingleElementSegmentSize) / sizeof(T) + 1
|
||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
|
public:
|
||||||
typedef SegmentImpl<kSegmentCapacity> Segment;
|
typedef SegmentImpl<kSegmentCapacity> Segment;
|
||||||
|
|
||||||
public:
|
|
||||||
// The |aIdealSegmentSize| is only for sanity checking. If it's specified, we
|
// The |aIdealSegmentSize| is only for sanity checking. If it's specified, we
|
||||||
// check that the actual segment size is as close as possible to it. This
|
// check that the actual segment size is as close as possible to it. This
|
||||||
// serves as a sanity check for SegmentedVectorCapacity's capacity
|
// serves as a sanity check for SegmentedVectorCapacity's capacity
|
||||||
|
|
@ -259,7 +259,6 @@ public:
|
||||||
// than we want to pop.
|
// than we want to pop.
|
||||||
MOZ_ASSERT(last);
|
MOZ_ASSERT(last);
|
||||||
MOZ_ASSERT(last == mSegments.getLast());
|
MOZ_ASSERT(last == mSegments.getLast());
|
||||||
MOZ_ASSERT(aNumElements != 0);
|
|
||||||
MOZ_ASSERT(aNumElements < last->Length());
|
MOZ_ASSERT(aNumElements < last->Length());
|
||||||
for (uint32_t i = 0; i < aNumElements; ++i) {
|
for (uint32_t i = 0; i < aNumElements; ++i) {
|
||||||
last->PopLast();
|
last->PopLast();
|
||||||
|
|
@ -274,6 +273,10 @@ public:
|
||||||
// f(elem);
|
// f(elem);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
// Note, adding new entries to the SegmentedVector while using iterators
|
||||||
|
// is supported, but removing is not!
|
||||||
|
// If an iterator has entered Done() state, adding more entries to the
|
||||||
|
// vector doesn't affect it.
|
||||||
class IterImpl
|
class IterImpl
|
||||||
{
|
{
|
||||||
friend class SegmentedVector;
|
friend class SegmentedVector;
|
||||||
|
|
@ -281,10 +284,14 @@ public:
|
||||||
Segment* mSegment;
|
Segment* mSegment;
|
||||||
size_t mIndex;
|
size_t mIndex;
|
||||||
|
|
||||||
explicit IterImpl(SegmentedVector* aVector)
|
explicit IterImpl(SegmentedVector* aVector, bool aFromFirst)
|
||||||
: mSegment(aVector->mSegments.getFirst())
|
: mSegment(aFromFirst ? aVector->mSegments.getFirst() :
|
||||||
, mIndex(0)
|
aVector->mSegments.getLast())
|
||||||
{}
|
, mIndex(aFromFirst ? 0 :
|
||||||
|
(mSegment ? mSegment->Length() - 1 : 0))
|
||||||
|
{
|
||||||
|
MOZ_ASSERT_IF(mSegment, mSegment->Length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Done() const { return !mSegment; }
|
bool Done() const { return !mSegment; }
|
||||||
|
|
@ -310,10 +317,23 @@ public:
|
||||||
mIndex = 0;
|
mIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Prev()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!Done());
|
||||||
|
if (mIndex == 0) {
|
||||||
|
mSegment = mSegment->getPrevious();
|
||||||
|
if (mSegment) {
|
||||||
|
mIndex = mSegment->Length() - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
--mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IterImpl Iter() { return IterImpl(this); }
|
IterImpl Iter() { return IterImpl(this, true); }
|
||||||
|
IterImpl IterFromLast() { return IterImpl(this, false); }
|
||||||
// Measure the memory consumption of the vector excluding |this|. Note that
|
// Measure the memory consumption of the vector excluding |this|. Note that
|
||||||
// it only measures the vector itself. If the vector elements contain
|
// it only measures the vector itself. If the vector elements contain
|
||||||
// pointers to other memory blocks, those blocks must be measured separately
|
// pointers to other memory blocks, those blocks must be measured separately
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,7 @@
|
||||||
/* This must occur *after* base/process_util.h to avoid typedefs conflicts. */
|
/* This must occur *after* base/process_util.h to avoid typedefs conflicts. */
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
|
#include "mozilla/Move.h"
|
||||||
#include "mozilla/SegmentedVector.h"
|
#include "mozilla/SegmentedVector.h"
|
||||||
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
|
@ -961,14 +962,43 @@ CanonicalizeParticipant(void** aParti, nsCycleCollectionParticipant** aCp)
|
||||||
|
|
||||||
struct nsPurpleBufferEntry
|
struct nsPurpleBufferEntry
|
||||||
{
|
{
|
||||||
union
|
nsPurpleBufferEntry(void* aObject, nsCycleCollectingAutoRefCnt* aRefCnt,
|
||||||
|
nsCycleCollectionParticipant* aParticipant)
|
||||||
|
: mObject(aObject)
|
||||||
|
, mRefCnt(aRefCnt)
|
||||||
|
, mParticipant(aParticipant)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsPurpleBufferEntry(nsPurpleBufferEntry&& aOther)
|
||||||
|
: mObject(nullptr)
|
||||||
|
, mRefCnt(nullptr)
|
||||||
|
, mParticipant(nullptr)
|
||||||
{
|
{
|
||||||
void* mObject; // when low bit unset
|
Swap(aOther);
|
||||||
nsPurpleBufferEntry* mNextInFreeList; // when low bit set
|
}
|
||||||
};
|
|
||||||
|
void Swap(nsPurpleBufferEntry& aOther) {
|
||||||
|
std::swap(mObject, aOther.mObject);
|
||||||
|
std::swap(mRefCnt, aOther.mRefCnt);
|
||||||
|
std::swap(mParticipant, aOther.mParticipant);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
mRefCnt->RemoveFromPurpleBuffer();
|
||||||
|
mRefCnt = nullptr;
|
||||||
|
mObject = nullptr;
|
||||||
|
mParticipant = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
~nsPurpleBufferEntry() {
|
||||||
|
if (mRefCnt) {
|
||||||
|
mRefCnt->RemoveFromPurpleBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mObject;
|
||||||
|
|
||||||
nsCycleCollectingAutoRefCnt* mRefCnt;
|
nsCycleCollectingAutoRefCnt* mRefCnt;
|
||||||
|
|
||||||
nsCycleCollectionParticipant* mParticipant; // nullptr for nsISupports
|
nsCycleCollectionParticipant* mParticipant; // nullptr for nsISupports
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -977,118 +1007,113 @@ class nsCycleCollector;
|
||||||
struct nsPurpleBuffer
|
struct nsPurpleBuffer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct PurpleBlock
|
|
||||||
{
|
|
||||||
PurpleBlock* mNext;
|
|
||||||
// Try to match the size of a jemalloc bucket, to minimize slop bytes.
|
|
||||||
// - On 32-bit platforms sizeof(nsPurpleBufferEntry) is 12, so mEntries
|
|
||||||
// is 16,380 bytes, which leaves 4 bytes for mNext.
|
|
||||||
// - On 64-bit platforms sizeof(nsPurpleBufferEntry) is 24, so mEntries
|
|
||||||
// is 32,544 bytes, which leaves 8 bytes for mNext.
|
|
||||||
nsPurpleBufferEntry mEntries[1365];
|
|
||||||
|
|
||||||
PurpleBlock() : mNext(nullptr)
|
|
||||||
{
|
|
||||||
// Ensure PurpleBlock is the right size (see above).
|
|
||||||
static_assert(
|
|
||||||
sizeof(PurpleBlock) == 16384 || // 32-bit
|
|
||||||
sizeof(PurpleBlock) == 32768, // 64-bit
|
|
||||||
"ill-sized nsPurpleBuffer::PurpleBlock"
|
|
||||||
);
|
|
||||||
|
|
||||||
InitNextPointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put all the entries in the block on the free list.
|
|
||||||
void InitNextPointers()
|
|
||||||
{
|
|
||||||
for (uint32_t i = 1; i < ArrayLength(mEntries); ++i) {
|
|
||||||
mEntries[i - 1].mNextInFreeList =
|
|
||||||
(nsPurpleBufferEntry*)(uintptr_t(mEntries + i) | 1);
|
|
||||||
}
|
|
||||||
mEntries[ArrayLength(mEntries) - 1].mNextInFreeList =
|
|
||||||
(nsPurpleBufferEntry*)1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class PurpleVisitor>
|
|
||||||
void VisitEntries(nsPurpleBuffer& aBuffer, PurpleVisitor& aVisitor)
|
|
||||||
{
|
|
||||||
nsPurpleBufferEntry* eEnd = ArrayEnd(mEntries);
|
|
||||||
for (nsPurpleBufferEntry* e = mEntries; e != eEnd; ++e) {
|
|
||||||
MOZ_ASSERT(e->mObject, "There should be no null mObject when we iterate over the purple buffer");
|
|
||||||
if (!(uintptr_t(e->mObject) & uintptr_t(1)) && e->mObject) {
|
|
||||||
aVisitor.Visit(aBuffer, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// This class wraps a linked list of the elements in the purple
|
|
||||||
// buffer.
|
|
||||||
|
|
||||||
uint32_t mCount;
|
uint32_t mCount;
|
||||||
PurpleBlock mFirstBlock;
|
|
||||||
nsPurpleBufferEntry* mFreeList;
|
|
||||||
|
|
||||||
|
// Try to match the size of a jemalloc bucket, to minimize slop bytes.
|
||||||
|
// - On 32-bit platforms sizeof(nsPurpleBufferEntry) is 12, so mEntries'
|
||||||
|
// Segment is 16,372 bytes.
|
||||||
|
// - On 64-bit platforms sizeof(nsPurpleBufferEntry) is 24, so mEntries'
|
||||||
|
// Segment is 32,760 bytes.
|
||||||
|
static const uint32_t kEntriesPerSegment = 1365;
|
||||||
|
static const size_t kSegmentSize =
|
||||||
|
sizeof(nsPurpleBufferEntry) * kEntriesPerSegment;
|
||||||
|
typedef
|
||||||
|
SegmentedVector<nsPurpleBufferEntry, kSegmentSize, InfallibleAllocPolicy>
|
||||||
|
PurpleBufferVector;
|
||||||
|
PurpleBufferVector mEntries;
|
||||||
public:
|
public:
|
||||||
nsPurpleBuffer()
|
nsPurpleBuffer()
|
||||||
|
: mCount(0)
|
||||||
{
|
{
|
||||||
InitBlocks();
|
static_assert(
|
||||||
|
sizeof(PurpleBufferVector::Segment) == 16372 || // 32-bit
|
||||||
|
sizeof(PurpleBufferVector::Segment) == 32760 || // 64-bit
|
||||||
|
sizeof(PurpleBufferVector::Segment) == 32744, // 64-bit Windows
|
||||||
|
"ill-sized nsPurpleBuffer::mEntries");
|
||||||
}
|
}
|
||||||
|
|
||||||
~nsPurpleBuffer()
|
~nsPurpleBuffer()
|
||||||
{
|
{}
|
||||||
FreeBlocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// This method compacts mEntries.
|
||||||
template<class PurpleVisitor>
|
template<class PurpleVisitor>
|
||||||
void VisitEntries(PurpleVisitor& aVisitor)
|
void VisitEntries(PurpleVisitor& aVisitor) {
|
||||||
{
|
if (mEntries.IsEmpty()) {
|
||||||
for (PurpleBlock* b = &mFirstBlock; b; b = b->mNext) {
|
return;
|
||||||
b->VisitEntries(*this, aVisitor);
|
}
|
||||||
|
|
||||||
|
uint32_t oldLength = mEntries.Length();
|
||||||
|
uint32_t newLength = 0;
|
||||||
|
auto revIter = mEntries.IterFromLast();
|
||||||
|
auto iter = mEntries.Iter();
|
||||||
|
// After iteration this points to the first empty entry.
|
||||||
|
auto firstEmptyIter = mEntries.Iter();
|
||||||
|
auto iterFromLastEntry = mEntries.IterFromLast();
|
||||||
|
for (; !iter.Done(); iter.Next()) {
|
||||||
|
nsPurpleBufferEntry& e = iter.Get();
|
||||||
|
if (e.mObject) {
|
||||||
|
aVisitor.Visit(*this, &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visit call above may have cleared the entry, or the entry was empty
|
||||||
|
// already.
|
||||||
|
if (!e.mObject) {
|
||||||
|
// Try to find a non-empty entry from the end of the vector.
|
||||||
|
for (; !revIter.Done(); revIter.Prev()) {
|
||||||
|
nsPurpleBufferEntry& otherEntry = revIter.Get();
|
||||||
|
if (&e == &otherEntry) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (otherEntry.mObject) {
|
||||||
|
aVisitor.Visit(*this, &otherEntry);
|
||||||
|
// Visit may have cleared otherEntry.
|
||||||
|
if (otherEntry.mObject) {
|
||||||
|
e.Swap(otherEntry);
|
||||||
|
revIter.Prev(); // We've swapped this now empty entry.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitBlocks()
|
// Entry is non-empty even after the Visit call, ensure it is kept
|
||||||
{
|
// in mEntries.
|
||||||
|
if (e.mObject) {
|
||||||
|
firstEmptyIter.Next();
|
||||||
|
++newLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&e == &revIter.Get()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// There were some empty entries.
|
||||||
|
if (oldLength != newLength) {
|
||||||
|
|
||||||
|
// While visiting entries, some new ones were possibly added. This can
|
||||||
|
// happen during CanSkip. Move all such new entries to be after other
|
||||||
|
// entries. Note, we don't call Visit on newly added entries!
|
||||||
|
if (&iterFromLastEntry.Get() != &mEntries.GetLast()) {
|
||||||
|
iterFromLastEntry.Next(); // Now pointing to the first added entry.
|
||||||
|
auto& iterForNewEntries = iterFromLastEntry;
|
||||||
|
while (!iterForNewEntries.Done()) {
|
||||||
|
MOZ_ASSERT(!firstEmptyIter.Done());
|
||||||
|
MOZ_ASSERT(!firstEmptyIter.Get().mObject);
|
||||||
|
firstEmptyIter.Get().Swap(iterForNewEntries.Get());
|
||||||
|
firstEmptyIter.Next();
|
||||||
|
iterForNewEntries.Next();
|
||||||
|
++newLength; // We keep all the new entries.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mEntries.PopLastN(oldLength - newLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeBlocks() {
|
||||||
mCount = 0;
|
mCount = 0;
|
||||||
mFreeList = mFirstBlock.mEntries;
|
mEntries.Clear();
|
||||||
}
|
|
||||||
|
|
||||||
void FreeBlocks()
|
|
||||||
{
|
|
||||||
if (mCount > 0) {
|
|
||||||
UnmarkRemainingPurple(&mFirstBlock);
|
|
||||||
}
|
|
||||||
PurpleBlock* b = mFirstBlock.mNext;
|
|
||||||
while (b) {
|
|
||||||
if (mCount > 0) {
|
|
||||||
UnmarkRemainingPurple(b);
|
|
||||||
}
|
|
||||||
PurpleBlock* next = b->mNext;
|
|
||||||
delete b;
|
|
||||||
b = next;
|
|
||||||
}
|
|
||||||
mFirstBlock.mNext = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UnmarkRemainingPurpleVisitor
|
|
||||||
{
|
|
||||||
void
|
|
||||||
Visit(nsPurpleBuffer& aBuffer, nsPurpleBufferEntry* aEntry)
|
|
||||||
{
|
|
||||||
if (aEntry->mRefCnt) {
|
|
||||||
aEntry->mRefCnt->RemoveFromPurpleBuffer();
|
|
||||||
aEntry->mRefCnt = nullptr;
|
|
||||||
}
|
|
||||||
aEntry->mObject = nullptr;
|
|
||||||
--aBuffer.mCount;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void UnmarkRemainingPurple(PurpleBlock* aBlock)
|
|
||||||
{
|
|
||||||
UnmarkRemainingPurpleVisitor visitor;
|
|
||||||
aBlock->VisitEntries(*this, visitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectPointers(CCGraphBuilder& aBuilder);
|
void SelectPointers(CCGraphBuilder& aBuilder);
|
||||||
|
|
@ -1105,73 +1130,27 @@ public:
|
||||||
bool aAsyncSnowWhiteFreeing,
|
bool aAsyncSnowWhiteFreeing,
|
||||||
CC_ForgetSkippableCallback aCb);
|
CC_ForgetSkippableCallback aCb);
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE nsPurpleBufferEntry* NewEntry()
|
|
||||||
{
|
|
||||||
if (MOZ_UNLIKELY(!mFreeList)) {
|
|
||||||
PurpleBlock* b = new PurpleBlock;
|
|
||||||
mFreeList = b->mEntries;
|
|
||||||
|
|
||||||
// Add the new block as the second block in the list.
|
|
||||||
b->mNext = mFirstBlock.mNext;
|
|
||||||
mFirstBlock.mNext = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsPurpleBufferEntry* e = mFreeList;
|
|
||||||
mFreeList = (nsPurpleBufferEntry*)
|
|
||||||
(uintptr_t(mFreeList->mNextInFreeList) & ~uintptr_t(1));
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE void Put(void* aObject, nsCycleCollectionParticipant* aCp,
|
MOZ_ALWAYS_INLINE void Put(void* aObject, nsCycleCollectionParticipant* aCp,
|
||||||
nsCycleCollectingAutoRefCnt* aRefCnt)
|
nsCycleCollectingAutoRefCnt* aRefCnt) {
|
||||||
{
|
nsPurpleBufferEntry entry(aObject, aRefCnt, aCp);
|
||||||
nsPurpleBufferEntry* e = NewEntry();
|
Unused << mEntries.Append(Move(entry));
|
||||||
|
MOZ_ASSERT(!entry.mRefCnt, "CC: PurpleBufferEntry:Put() Move failed!");
|
||||||
|
|
||||||
++mCount;
|
++mCount;
|
||||||
|
|
||||||
e->mObject = aObject;
|
|
||||||
e->mRefCnt = aRefCnt;
|
|
||||||
e->mParticipant = aCp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Remove(nsPurpleBufferEntry* aEntry)
|
void Remove(nsPurpleBufferEntry* aEntry) {
|
||||||
{
|
|
||||||
MOZ_ASSERT(mCount != 0, "must have entries");
|
MOZ_ASSERT(mCount != 0, "must have entries");
|
||||||
|
|
||||||
if (aEntry->mRefCnt) {
|
|
||||||
aEntry->mRefCnt->RemoveFromPurpleBuffer();
|
|
||||||
aEntry->mRefCnt = nullptr;
|
|
||||||
}
|
|
||||||
aEntry->mNextInFreeList =
|
|
||||||
(nsPurpleBufferEntry*)(uintptr_t(mFreeList) | uintptr_t(1));
|
|
||||||
mFreeList = aEntry;
|
|
||||||
|
|
||||||
--mCount;
|
--mCount;
|
||||||
|
aEntry->Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Count() const
|
uint32_t Count() const {
|
||||||
{
|
|
||||||
return mCount;
|
return mCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||||
{
|
return mEntries.SizeOfExcludingThis(aMallocSizeOf);
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
// Don't measure mFirstBlock because it's within |this|.
|
|
||||||
const PurpleBlock* block = mFirstBlock.mNext;
|
|
||||||
while (block) {
|
|
||||||
n += aMallocSizeOf(block);
|
|
||||||
block = block->mNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mFreeList is deliberately not measured because it points into
|
|
||||||
// the purple buffer, which is within mFirstBlock and thus within |this|.
|
|
||||||
//
|
|
||||||
// We also don't measure the things pointed to by mEntries[] because
|
|
||||||
// those pointers are non-owning.
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1203,16 +1182,13 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPurpleBuffer::SelectPointers(CCGraphBuilder& aBuilder)
|
nsPurpleBuffer::SelectPointers(CCGraphBuilder& aBuilder) {
|
||||||
{
|
|
||||||
SelectPointersVisitor visitor(aBuilder);
|
SelectPointersVisitor visitor(aBuilder);
|
||||||
VisitEntries(visitor);
|
VisitEntries(visitor);
|
||||||
|
|
||||||
NS_ASSERTION(mCount == 0, "AddPurpleRoot failed");
|
NS_ASSERTION(mCount == 0, "AddPurpleRoot failed");
|
||||||
if (mCount == 0) {
|
if (mCount == 0) {
|
||||||
FreeBlocks();
|
FreeBlocks();
|
||||||
InitBlocks();
|
|
||||||
mFirstBlock.InitNextPointers();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue