Bug 1843477, add a nursery purple buffer for each cycle collector, r=mccr8

Depends on D187146

Differential Revision: https://phabricator.services.mozilla.com/D187147
This commit is contained in:
Olli Pettay 2023-09-08 14:51:48 +00:00
Родитель d7c56b8b4f
Коммит c6c68c0d60
2 изменённых файлов: 59 добавлений и 88 удалений

Просмотреть файл

@ -198,33 +198,6 @@
using namespace mozilla;
struct NurseryPurpleBufferEntry {
void* mPtr;
nsCycleCollectionParticipant* mParticipant;
nsCycleCollectingAutoRefCnt* mRefCnt;
};
#define NURSERY_PURPLE_BUFFER_SIZE 2048
bool gNurseryPurpleBufferEnabled = true;
NurseryPurpleBufferEntry gNurseryPurpleBufferEntry[NURSERY_PURPLE_BUFFER_SIZE];
uint32_t gNurseryPurpleBufferEntryCount = 0;
void ClearNurseryPurpleBuffer();
static void SuspectUsingNurseryPurpleBuffer(
void* aPtr, nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt) {
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(gNurseryPurpleBufferEnabled);
if (gNurseryPurpleBufferEntryCount == NURSERY_PURPLE_BUFFER_SIZE) {
ClearNurseryPurpleBuffer();
}
gNurseryPurpleBufferEntry[gNurseryPurpleBufferEntryCount] = {aPtr, aCp,
aRefCnt};
++gNurseryPurpleBufferEntryCount;
}
// #define COLLECT_TIME_DEBUG
// Enable assertions that are useful for diagnosing errors in graph
@ -878,13 +851,26 @@ static nsISupports* CanonicalizeXPCOMParticipant(nsISupports* aIn) {
return out;
}
struct nsPurpleBufferEntry {
nsPurpleBufferEntry(void* aObject, nsCycleCollectingAutoRefCnt* aRefCnt,
nsCycleCollectionParticipant* aParticipant)
#define NURSERY_PURPLE_BUFFER_SIZE 2048
struct NurseryPurpleBufferEntry {
NurseryPurpleBufferEntry() = default;
NurseryPurpleBufferEntry(void* aObject, nsCycleCollectingAutoRefCnt* aRefCnt,
nsCycleCollectionParticipant* aParticipant)
: mObject(aObject), mRefCnt(aRefCnt), mParticipant(aParticipant) {}
void* mObject;
nsCycleCollectingAutoRefCnt* mRefCnt;
nsCycleCollectionParticipant* mParticipant; // nullptr for nsISupports
};
struct nsPurpleBufferEntry : public NurseryPurpleBufferEntry {
nsPurpleBufferEntry(void* aObject, nsCycleCollectingAutoRefCnt* aRefCnt,
nsCycleCollectionParticipant* aParticipant)
: NurseryPurpleBufferEntry(aObject, aRefCnt, aParticipant) {}
nsPurpleBufferEntry(nsPurpleBufferEntry&& aOther)
: mObject(nullptr), mRefCnt(nullptr), mParticipant(nullptr) {
: NurseryPurpleBufferEntry(nullptr, nullptr, nullptr) {
Swap(aOther);
}
@ -906,17 +892,13 @@ struct nsPurpleBufferEntry {
mRefCnt->RemoveFromPurpleBuffer();
}
}
void* mObject;
nsCycleCollectingAutoRefCnt* mRefCnt;
nsCycleCollectionParticipant* mParticipant; // nullptr for nsISupports
};
class nsCycleCollector;
struct nsPurpleBuffer {
private:
uint32_t mCount;
uint32_t mCount = 0;
// Try to match the size of a jemalloc bucket, to minimize slop bytes.
// - On 32-bit platforms sizeof(nsPurpleBufferEntry) is 12, so mEntries'
@ -931,8 +913,14 @@ struct nsPurpleBuffer {
PurpleBufferVector;
PurpleBufferVector mEntries;
NurseryPurpleBufferEntry
mNurseryPurpleBufferEntry[NURSERY_PURPLE_BUFFER_SIZE];
uint32_t mNurseryPurpleBufferEntryCount = 0;
bool mNurseryPurpleBufferEnabled = true;
public:
nsPurpleBuffer() : mCount(0) {
explicit nsPurpleBuffer() {
static_assert(
sizeof(PurpleBufferVector::Segment) == 16372 || // 32-bit
sizeof(PurpleBufferVector::Segment) == 32760 || // 64-bit
@ -942,15 +930,14 @@ struct nsPurpleBuffer {
~nsPurpleBuffer() = default;
void DisableNurseryPurpleBuffer() { mNurseryPurpleBufferEnabled = false; }
// This method compacts mEntries.
template <class PurpleVisitor>
void VisitEntries(PurpleVisitor& aVisitor) {
Maybe<AutoRestore<bool>> ar;
if (NS_IsMainThread()) {
ar.emplace(gNurseryPurpleBufferEnabled);
gNurseryPurpleBufferEnabled = false;
ClearNurseryPurpleBuffer();
}
AutoRestore<bool> ar(mNurseryPurpleBufferEnabled);
mNurseryPurpleBufferEnabled = false;
SuspectNurseryEntries();
if (mEntries.IsEmpty()) {
return;
@ -1047,19 +1034,46 @@ struct nsPurpleBuffer {
MOZ_ALWAYS_INLINE void Put(void* aObject, nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt) {
if (mNurseryPurpleBufferEnabled) {
if (mNurseryPurpleBufferEntryCount == NURSERY_PURPLE_BUFFER_SIZE) {
SuspectNurseryEntries();
}
mNurseryPurpleBufferEntry[mNurseryPurpleBufferEntryCount] = {
aObject, aRefCnt, aCp};
++mNurseryPurpleBufferEntryCount;
return;
}
PutToMainBuffer(aObject, aCp, aRefCnt);
}
private:
MOZ_ALWAYS_INLINE void PutToMainBuffer(void* aObject,
nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt) {
nsPurpleBufferEntry entry(aObject, aRefCnt, aCp);
Unused << mEntries.Append(std::move(entry));
MOZ_ASSERT(!entry.mRefCnt, "Move didn't work!");
++mCount;
}
void SuspectNurseryEntries() {
while (mNurseryPurpleBufferEntryCount) {
NurseryPurpleBufferEntry& entry =
mNurseryPurpleBufferEntry[--mNurseryPurpleBufferEntryCount];
PutToMainBuffer(entry.mObject, entry.mParticipant, entry.mRefCnt);
}
}
public:
void Remove(nsPurpleBufferEntry* aEntry) {
MOZ_ASSERT(mCount != 0, "must have entries");
--mCount;
aEntry->Clear();
}
uint32_t Count() const { return mCount; }
uint32_t Count() const { return mCount + mNurseryPurpleBufferEntryCount; }
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
return mEntries.SizeOfExcludingThis(aMallocSizeOf);
@ -1176,7 +1190,6 @@ class nsCycleCollector : public nsIMemoryReporter {
void Suspect(void* aPtr, nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt);
void SuspectNurseryEntries();
uint32_t SuspectedCount();
void ForgetSkippable(js::SliceBudget& aBudget, bool aRemoveChildlessNodes,
bool aAsyncSnowWhiteFreeing);
@ -3286,15 +3299,6 @@ MOZ_ALWAYS_INLINE void nsCycleCollector::Suspect(
mPurpleBuf.Put(aPtr, aParti, aRefCnt);
}
void nsCycleCollector::SuspectNurseryEntries() {
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
while (gNurseryPurpleBufferEntryCount) {
NurseryPurpleBufferEntry& entry =
gNurseryPurpleBufferEntry[--gNurseryPurpleBufferEntryCount];
mPurpleBuf.Put(entry.mPtr, entry.mParticipant, entry.mRefCnt);
}
}
void nsCycleCollector::CheckThreadSafety() {
#ifdef DEBUG
MOZ_ASSERT(mEventTarget->IsOnCurrentThread());
@ -3701,19 +3705,13 @@ void nsCycleCollector::BeginCollection(
uint32_t nsCycleCollector::SuspectedCount() {
CheckThreadSafety();
if (NS_IsMainThread()) {
return gNurseryPurpleBufferEntryCount + mPurpleBuf.Count();
}
return mPurpleBuf.Count();
}
void nsCycleCollector::Shutdown(bool aDoCollect) {
CheckThreadSafety();
if (NS_IsMainThread()) {
gNurseryPurpleBufferEnabled = false;
}
mPurpleBuf.DisableNurseryPurpleBuffer();
// Always delete snow white objects.
FreeSnowWhite(true);
@ -3852,27 +3850,6 @@ void NS_CycleCollectorSuspect3(void* aPtr, nsCycleCollectionParticipant* aCp,
SuspectAfterShutdown(aPtr, aCp, aRefCnt, aShouldDelete);
}
void ClearNurseryPurpleBuffer() {
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
CollectorData* data = sCollectorData.get();
MOZ_ASSERT(data);
MOZ_ASSERT(data->mCollector);
data->mCollector->SuspectNurseryEntries();
}
void NS_CycleCollectorSuspectUsingNursery(void* aPtr,
nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt,
bool* aShouldDelete) {
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
if (!gNurseryPurpleBufferEnabled) {
NS_CycleCollectorSuspect3(aPtr, aCp, aRefCnt, aShouldDelete);
return;
}
SuspectUsingNurseryPurpleBuffer(aPtr, aCp, aRefCnt);
}
uint32_t nsCycleCollector_suspectedCount() {
CollectorData* data = sCollectorData.get();

Просмотреть файл

@ -297,12 +297,6 @@ NS_CycleCollectorSuspect3(void* aPtr, nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt,
bool* aShouldDelete);
XPCOM_API(void)
NS_CycleCollectorSuspectUsingNursery(void* aPtr,
nsCycleCollectionParticipant* aCp,
nsCycleCollectingAutoRefCnt* aRefCnt,
bool* aShouldDelete);
#endif
/**