mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1094564 - Used SegmentedArray in SnowWhiteKiller. r=smaug.
This patch generalizes SegmentedArray a little, and then uses it instead of nsTArray in SnowWhiteKiller. This avoids some large (sometimes 1 MiB or more) allocations which were usually mostly unused.
This commit is contained in:
parent
b5fe55c53e
commit
f64f8ba285
@ -2465,16 +2465,18 @@ MayHaveChild(void* aObj, nsCycleCollectionParticipant* aCp)
|
|||||||
return cf.MayHaveChild();
|
return cf.MayHaveChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T, size_t N>
|
||||||
class SegmentedArrayElement
|
class SegmentedArrayElement
|
||||||
: public LinkedListElement<SegmentedArrayElement<T>>
|
: public LinkedListElement<SegmentedArrayElement<T, N>>
|
||||||
, public AutoFallibleTArray<T, 60>
|
, public AutoFallibleTArray<T, N>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T, size_t N>
|
||||||
class SegmentedArray
|
class SegmentedArray
|
||||||
{
|
{
|
||||||
|
typedef SegmentedArrayElement<T, N> Segment;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~SegmentedArray()
|
~SegmentedArray()
|
||||||
{
|
{
|
||||||
@ -2483,9 +2485,9 @@ public:
|
|||||||
|
|
||||||
void AppendElement(T& aElement)
|
void AppendElement(T& aElement)
|
||||||
{
|
{
|
||||||
SegmentedArrayElement<T>* last = mSegments.getLast();
|
Segment* last = mSegments.getLast();
|
||||||
if (!last || last->Length() == last->Capacity()) {
|
if (!last || last->Length() == last->Capacity()) {
|
||||||
last = new SegmentedArrayElement<T>();
|
last = new Segment();
|
||||||
mSegments.insertBack(last);
|
mSegments.insertBack(last);
|
||||||
}
|
}
|
||||||
last->AppendElement(aElement);
|
last->AppendElement(aElement);
|
||||||
@ -2493,24 +2495,29 @@ public:
|
|||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
SegmentedArrayElement<T>* first;
|
Segment* first;
|
||||||
while ((first = mSegments.popFirst())) {
|
while ((first = mSegments.popFirst())) {
|
||||||
delete first;
|
delete first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SegmentedArrayElement<T>* GetFirstSegment()
|
Segment* GetFirstSegment()
|
||||||
{
|
{
|
||||||
return mSegments.getFirst();
|
return mSegments.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty()
|
const Segment* GetFirstSegment() const
|
||||||
|
{
|
||||||
|
return mSegments.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const
|
||||||
{
|
{
|
||||||
return !GetFirstSegment();
|
return !GetFirstSegment();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mozilla::LinkedList<SegmentedArrayElement<T>> mSegments;
|
mozilla::LinkedList<Segment> mSegments;
|
||||||
};
|
};
|
||||||
|
|
||||||
// JSPurpleBuffer keeps references to GCThings which might affect the
|
// JSPurpleBuffer keeps references to GCThings which might affect the
|
||||||
@ -2553,8 +2560,8 @@ public:
|
|||||||
// pointers which may point into the nursery. The purple buffer never contains
|
// pointers which may point into the nursery. The purple buffer never contains
|
||||||
// pointers to the nursery because nursery gcthings can never be gray and only
|
// pointers to the nursery because nursery gcthings can never be gray and only
|
||||||
// gray things can be inserted into the purple buffer.
|
// gray things can be inserted into the purple buffer.
|
||||||
SegmentedArray<JS::Value> mValues;
|
SegmentedArray<JS::Value, 60> mValues;
|
||||||
SegmentedArray<JSObject*> mObjects;
|
SegmentedArray<JSObject*, 60> mObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(JSPurpleBuffer)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(JSPurpleBuffer)
|
||||||
@ -2588,42 +2595,58 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|||||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(JSPurpleBuffer, AddRef)
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(JSPurpleBuffer, AddRef)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(JSPurpleBuffer, Release)
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(JSPurpleBuffer, Release)
|
||||||
|
|
||||||
struct SnowWhiteObject
|
|
||||||
{
|
|
||||||
void* mPointer;
|
|
||||||
nsCycleCollectionParticipant* mParticipant;
|
|
||||||
nsCycleCollectingAutoRefCnt* mRefCnt;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SnowWhiteKiller : public TraceCallbacks
|
class SnowWhiteKiller : public TraceCallbacks
|
||||||
{
|
{
|
||||||
|
struct SnowWhiteObject
|
||||||
|
{
|
||||||
|
void* mPointer;
|
||||||
|
nsCycleCollectionParticipant* mParticipant;
|
||||||
|
nsCycleCollectingAutoRefCnt* mRefCnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Segments are 4 KiB on 32-bit and 8 KiB on 64-bit.
|
||||||
|
static const size_t kIdealSegmentSize = sizeof(void*) * 1024;
|
||||||
|
static const size_t kSingleElemSegmentSize =
|
||||||
|
sizeof(SegmentedArrayElement<SnowWhiteObject, 1>);
|
||||||
|
static const size_t kSegmentCapacity =
|
||||||
|
(kIdealSegmentSize - kSingleElemSegmentSize) / sizeof(SnowWhiteObject) + 1;
|
||||||
|
|
||||||
|
static const size_t kActualSegmentSize =
|
||||||
|
sizeof(SegmentedArrayElement<SnowWhiteObject, kSegmentCapacity>);
|
||||||
|
|
||||||
|
typedef SegmentedArray<SnowWhiteObject, kSegmentCapacity> ObjectsArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SnowWhiteKiller(nsCycleCollector* aCollector, uint32_t aMaxCount)
|
SnowWhiteKiller(nsCycleCollector* aCollector, uint32_t aMaxCount)
|
||||||
: mCollector(aCollector)
|
: mCollector(aCollector)
|
||||||
|
, mObjects()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mCollector, "Calling SnowWhiteKiller after nsCC went away");
|
MOZ_ASSERT(mCollector, "Calling SnowWhiteKiller after nsCC went away");
|
||||||
while (true) {
|
|
||||||
if (mObjects.SetCapacity(aMaxCount)) {
|
// The segment capacity should be such that the actual segment size is as
|
||||||
break;
|
// close as possible to the ideal segment size.
|
||||||
}
|
static_assert(
|
||||||
if (aMaxCount == 1) {
|
kIdealSegmentSize - kActualSegmentSize <= sizeof(SnowWhiteObject),
|
||||||
NS_RUNTIMEABORT("Not enough memory to even delete objects!");
|
"ill-sized SnowWhiteKiller segments"
|
||||||
}
|
);
|
||||||
aMaxCount /= 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~SnowWhiteKiller()
|
~SnowWhiteKiller()
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < mObjects.Length(); ++i) {
|
auto segment = mObjects.GetFirstSegment();
|
||||||
SnowWhiteObject& o = mObjects[i];
|
while (segment) {
|
||||||
if (!o.mRefCnt->get() && !o.mRefCnt->IsInPurpleBuffer()) {
|
for (uint32_t i = 0; i < segment->Length(); i++) {
|
||||||
mCollector->RemoveObjectFromGraph(o.mPointer);
|
SnowWhiteObject& o = segment->ElementAt(i);
|
||||||
o.mRefCnt->stabilizeForDeletion();
|
if (!o.mRefCnt->get() && !o.mRefCnt->IsInPurpleBuffer()) {
|
||||||
o.mParticipant->Trace(o.mPointer, *this, nullptr);
|
mCollector->RemoveObjectFromGraph(o.mPointer);
|
||||||
o.mParticipant->DeleteCycleCollectable(o.mPointer);
|
o.mRefCnt->stabilizeForDeletion();
|
||||||
|
o.mParticipant->Trace(o.mPointer, *this, nullptr);
|
||||||
|
o.mParticipant->DeleteCycleCollectable(o.mPointer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
segment = segment->getNext();
|
||||||
}
|
}
|
||||||
|
mObjects.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2635,15 +2658,14 @@ public:
|
|||||||
nsCycleCollectionParticipant* cp = aEntry->mParticipant;
|
nsCycleCollectionParticipant* cp = aEntry->mParticipant;
|
||||||
CanonicalizeParticipant(&o, &cp);
|
CanonicalizeParticipant(&o, &cp);
|
||||||
SnowWhiteObject swo = { o, cp, aEntry->mRefCnt };
|
SnowWhiteObject swo = { o, cp, aEntry->mRefCnt };
|
||||||
if (mObjects.AppendElement(swo)) {
|
mObjects.AppendElement(swo);
|
||||||
aBuffer.Remove(aEntry);
|
aBuffer.Remove(aEntry);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasSnowWhiteObjects() const
|
bool HasSnowWhiteObjects() const
|
||||||
{
|
{
|
||||||
return mObjects.Length() > 0;
|
return !mObjects.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Trace(JS::Heap<JS::Value>* aValue, const char* aName,
|
virtual void Trace(JS::Heap<JS::Value>* aValue, const char* aName,
|
||||||
@ -2701,7 +2723,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
nsCycleCollector* mCollector;
|
nsCycleCollector* mCollector;
|
||||||
FallibleTArray<SnowWhiteObject> mObjects;
|
ObjectsArray mObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoveSkippableVisitor : public SnowWhiteKiller
|
class RemoveSkippableVisitor : public SnowWhiteKiller
|
||||||
|
Loading…
Reference in New Issue
Block a user