mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-06 12:43:53 +00:00
Bug 696233. Switch the nth-index cache to having a single hashtable per selector type (from end vs from start and of-type vs not-of-type). Gives somewhat better cache locality on some workloads and makes entry addition much cheaper because we no longer need to initialize all the new memory when the hashtable store is resized; we just initialize the parts of it we need as we need them. r=smaug
This commit is contained in:
parent
63d3c04397
commit
1c68a1582a
@ -56,7 +56,10 @@ nsNthIndexCache::~nsNthIndexCache()
|
||||
void
|
||||
nsNthIndexCache::Reset()
|
||||
{
|
||||
mCache.clear();
|
||||
mCaches[0][0].clear();
|
||||
mCaches[0][1].clear();
|
||||
mCaches[1][0].clear();
|
||||
mCaches[1][1].clear();
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -73,12 +76,13 @@ nsNthIndexCache::IndexDeterminedFromPreviousSibling(nsIContent* aSibling,
|
||||
Element* aChild,
|
||||
bool aIsOfType,
|
||||
bool aIsFromEnd,
|
||||
const Cache& aCache,
|
||||
PRInt32& aResult)
|
||||
{
|
||||
if (SiblingMatchesElement(aSibling, aChild, aIsOfType)) {
|
||||
Cache::Ptr siblingEntry = mCache.lookup(aSibling);
|
||||
Cache::Ptr siblingEntry = aCache.lookup(aSibling);
|
||||
if (siblingEntry) {
|
||||
PRInt32 siblingIndex = siblingEntry->value.mNthIndices[aIsOfType][aIsFromEnd];
|
||||
PRInt32 siblingIndex = siblingEntry->value;
|
||||
NS_ASSERTION(siblingIndex != 0,
|
||||
"How can a non-anonymous node have an anonymous sibling?");
|
||||
if (siblingIndex > 0) {
|
||||
@ -110,19 +114,22 @@ nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mCache.initialized() && !mCache.init()) {
|
||||
Cache &cache = mCaches[aIsOfType][aIsFromEnd];
|
||||
|
||||
if (!cache.initialized() && !cache.init()) {
|
||||
// Give up and just don't match.
|
||||
return 0;
|
||||
}
|
||||
|
||||
Cache::AddPtr entry = mCache.lookupForAdd(aChild);
|
||||
|
||||
if (!entry && !mCache.add(entry, aChild)) {
|
||||
Cache::AddPtr entry = cache.lookupForAdd(aChild);
|
||||
|
||||
// Default the value to -2 when adding
|
||||
if (!entry && !cache.add(entry, aChild, -2)) {
|
||||
// No good; don't match.
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 &slot = entry->value.mNthIndices[aIsOfType][aIsFromEnd];
|
||||
PRInt32 &slot = entry->value;
|
||||
if (slot != -2 && (slot != -1 || aCheckEdgeOnly)) {
|
||||
return slot;
|
||||
}
|
||||
@ -157,7 +164,7 @@ nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
|
||||
cur;
|
||||
cur = cur->GetPreviousSibling()) {
|
||||
if (IndexDeterminedFromPreviousSibling(cur, aChild, aIsOfType,
|
||||
aIsFromEnd, result)) {
|
||||
aIsFromEnd, cache, result)) {
|
||||
slot = result;
|
||||
return result;
|
||||
}
|
||||
|
@ -80,6 +80,23 @@ private:
|
||||
inline bool SiblingMatchesElement(nsIContent* aSibling, Element* aElement,
|
||||
bool aIsOfType);
|
||||
|
||||
// This node's index for this cache.
|
||||
// If -2, needs to be computed.
|
||||
// If -1, needs to be computed but known not to be 1.
|
||||
// If 0, the node is not at any index in its parent.
|
||||
typedef PRInt32 CacheEntry;
|
||||
|
||||
class SystemAllocPolicy {
|
||||
public:
|
||||
void *malloc_(size_t bytes) { return ::malloc(bytes); }
|
||||
void *realloc_(void *p, size_t bytes) { return ::realloc(p, bytes); }
|
||||
void free_(void *p) { ::free(p); }
|
||||
void reportAllocOverflow() const {}
|
||||
};
|
||||
|
||||
typedef js::HashMap<nsIContent*, CacheEntry, js::DefaultHasher<nsIContent*>,
|
||||
SystemAllocPolicy> Cache;
|
||||
|
||||
/**
|
||||
* Returns true if aResult has been set to the correct value for aChild and
|
||||
* no more work needs to be done. Returns false otherwise.
|
||||
@ -95,37 +112,15 @@ private:
|
||||
Element* aChild,
|
||||
bool aIsOfType,
|
||||
bool aIsFromEnd,
|
||||
const Cache& aCache,
|
||||
PRInt32& aResult);
|
||||
|
||||
struct CacheEntry {
|
||||
CacheEntry() {
|
||||
mNthIndices[0][0] = -2;
|
||||
mNthIndices[0][1] = -2;
|
||||
mNthIndices[1][0] = -2;
|
||||
mNthIndices[1][1] = -2;
|
||||
}
|
||||
|
||||
// This node's index for :nth-child(), :nth-last-child(),
|
||||
// :nth-of-type(), :nth-last-of-type(). If -2, needs to be computed.
|
||||
// If -1, needs to be computed but known not to be 1.
|
||||
// If 0, the node is not at any index in its parent.
|
||||
// The first subscript is 0 for -child and 1 for -of-type, the second
|
||||
// subscript is 0 for nth- and 1 for nth-last-.
|
||||
PRInt32 mNthIndices[2][2];
|
||||
};
|
||||
|
||||
class SystemAllocPolicy {
|
||||
public:
|
||||
void *malloc_(size_t bytes) { return ::malloc(bytes); }
|
||||
void *realloc_(void *p, size_t bytes) { return ::realloc(p, bytes); }
|
||||
void free_(void *p) { ::free(p); }
|
||||
void reportAllocOverflow() const {}
|
||||
};
|
||||
|
||||
typedef js::HashMap<nsIContent*, CacheEntry, js::DefaultHasher<nsIContent*>,
|
||||
SystemAllocPolicy> Cache;
|
||||
|
||||
Cache mCache;
|
||||
// Caches of indices for :nth-child(), :nth-last-child(),
|
||||
// :nth-of-type(), :nth-last-of-type(), keyed by Element*.
|
||||
//
|
||||
// The first subscript is 0 for -child and 1 for -of-type, the second
|
||||
// subscript is 0 for nth- and 1 for nth-last-.
|
||||
Cache mCaches[2][2];
|
||||
};
|
||||
|
||||
#endif /* nsContentIndexCache_h__ */
|
||||
|
Loading…
Reference in New Issue
Block a user