зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d7c56b8b4f
Коммит
c6c68c0d60
|
@ -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,
|
||||
#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
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче