mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1488413 - To improve performance, CycleCollector could use a cache on top of the graph's hashtable, r=mccr8
--HG-- extra : rebase_source : 8f67777644346549a3df3c4e97433378dc70a177
This commit is contained in:
parent
4454f01d19
commit
e8a92b84f1
@ -157,6 +157,7 @@
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/HashTable.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
/* This must occur *after* base/process_util.h to avoid typedefs conflicts. */
|
||||
@ -164,6 +165,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/SegmentedVector.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCycleCollectionNoteRootCallback.h"
|
||||
@ -2092,6 +2094,43 @@ private:
|
||||
nsAutoPtr<NodePool::Enumerator> mCurrNode;
|
||||
uint32_t mNoteChildCount;
|
||||
|
||||
class GraphCache
|
||||
{
|
||||
public:
|
||||
// This either returns a pointer if present, or an index, if it isn't.
|
||||
Variant<PtrInfo*, uint32_t> GetEntryOrIndex(void* aPtr)
|
||||
{
|
||||
uint32_t hash = mozilla::HashGeneric(aPtr);
|
||||
uint32_t index = hash % kCacheSize;
|
||||
PtrInfo* result = mCache[index];
|
||||
if (result && result->mPointer == aPtr) {
|
||||
return AsVariant(result);
|
||||
}
|
||||
|
||||
return AsVariant(index);
|
||||
}
|
||||
|
||||
void Add(uint32_t aIndex, PtrInfo* aPtrInfo)
|
||||
{
|
||||
mCache[aIndex] = aPtrInfo;
|
||||
}
|
||||
|
||||
void Remove(void* aPtr)
|
||||
{
|
||||
uint32_t hash = mozilla::HashGeneric(aPtr);
|
||||
uint32_t index = hash % kCacheSize;
|
||||
PtrInfo* pinfo = mCache[index];
|
||||
if (pinfo && pinfo->mPointer == aPtr) {
|
||||
mCache[index] = nullptr;
|
||||
}
|
||||
}
|
||||
private:
|
||||
const static uint32_t kCacheSize = 491;
|
||||
PtrInfo* mCache[kCacheSize] = {0};
|
||||
};
|
||||
|
||||
GraphCache mGraphCache;
|
||||
|
||||
public:
|
||||
CCGraphBuilder(CCGraph& aGraph,
|
||||
CycleCollectorResults& aResults,
|
||||
@ -2113,6 +2152,10 @@ public:
|
||||
// Do some work traversing nodes in the graph. Returns true if this graph building is finished.
|
||||
bool BuildGraph(SliceBudget& aBudget);
|
||||
|
||||
void RemoveCachedEntry(void* aPtr)
|
||||
{
|
||||
mGraphCache.Remove(aPtr);
|
||||
}
|
||||
private:
|
||||
PtrInfo* AddNode(void* aPtr, nsCycleCollectionParticipant* aParticipant);
|
||||
PtrInfo* AddWeakMapNode(JS::GCCellPtr aThing);
|
||||
@ -2210,6 +2253,10 @@ CCGraphBuilder::CCGraphBuilder(CCGraph& aGraph,
|
||||
, mMergeZones(aMergeZones)
|
||||
, mNoteChildCount(0)
|
||||
{
|
||||
// 4096 is an allocation bucket size.
|
||||
static_assert(sizeof(CCGraphBuilder) <= 4096,
|
||||
"Don't create too large CCGraphBuilder objects");
|
||||
|
||||
if (aCCRuntime) {
|
||||
mJSParticipant = aCCRuntime->GCThingParticipant();
|
||||
mJSZoneParticipant = aCCRuntime->ZoneParticipant();
|
||||
@ -2240,6 +2287,15 @@ CCGraphBuilder::AddNode(void* aPtr, nsCycleCollectionParticipant* aParticipant)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Variant<PtrInfo*, uint32_t> cacheVariant = mGraphCache.GetEntryOrIndex(aPtr);
|
||||
if (cacheVariant.is<PtrInfo*>()) {
|
||||
MOZ_ASSERT(cacheVariant.as<PtrInfo*>()->mParticipant == aParticipant,
|
||||
"nsCycleCollectionParticipant shouldn't change!");
|
||||
return cacheVariant.as<PtrInfo*>();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(cacheVariant.is<uint32_t>());
|
||||
|
||||
PtrInfo* result;
|
||||
auto p = mGraph.mPtrInfoMap.lookupForAdd(aPtr);
|
||||
if (!p) {
|
||||
@ -2263,6 +2319,8 @@ CCGraphBuilder::AddNode(void* aPtr, nsCycleCollectionParticipant* aParticipant)
|
||||
"nsCycleCollectionParticipant shouldn't change!");
|
||||
}
|
||||
|
||||
mGraphCache.Add(cacheVariant.as<uint32_t>(), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -4044,6 +4102,9 @@ nsCycleCollector::RemoveObjectFromGraph(void* aObj)
|
||||
}
|
||||
|
||||
mGraph.RemoveObjectFromMap(aObj);
|
||||
if (mBuilder) {
|
||||
mBuilder->RemoveCachedEntry(aObj);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user