mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Bug 689443. Switch PerWeightData back to using linked lists instead of arrays for the actual per-weight rule data, so as to reduce fragmentation. r=dbaron
This incidentally fixes a bug where we were copying the per-weight data very inefficiently.
This commit is contained in:
parent
ce77544e56
commit
5da1a0cc40
@ -51,7 +51,8 @@
|
||||
#include "nsRuleProcessorData.h"
|
||||
|
||||
#define PL_ARENA_CONST_ALIGN_MASK 7
|
||||
#define NS_RULEHASH_ARENA_BLOCK_SIZE (256)
|
||||
// We want page-sized arenas so there's no fragmentation involved.
|
||||
#define NS_CASCADEENUMDATA_ARENA_BLOCK_SIZE (4096)
|
||||
#include "plarena.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
@ -117,6 +118,8 @@ PRUint8 nsCSSRuleProcessor::sWinThemeId = LookAndFeel::eWindowsTheme_Generic;
|
||||
struct RuleSelectorPair {
|
||||
RuleSelectorPair(css::StyleRule* aRule, nsCSSSelector* aSelector)
|
||||
: mRule(aRule), mSelector(aSelector) {}
|
||||
// If this class ever grows a destructor, deal with
|
||||
// PerWeightDataListItem appropriately.
|
||||
|
||||
css::StyleRule* mRule;
|
||||
nsCSSSelector* mSelector; // which of |mRule|'s selectors
|
||||
@ -421,7 +424,6 @@ public:
|
||||
void AppendRule(const RuleSelectorPair &aRuleInfo);
|
||||
void EnumerateAllRules(Element* aElement, RuleProcessorData* aData,
|
||||
NodeMatchContext& aNodeMatchContext);
|
||||
PLArenaPool& Arena() { return mArena; }
|
||||
|
||||
PRInt64 SizeOf() const;
|
||||
|
||||
@ -450,8 +452,6 @@ protected:
|
||||
return data;
|
||||
}
|
||||
|
||||
PLArenaPool mArena;
|
||||
|
||||
#ifdef RULE_HASH_STATS
|
||||
PRUint32 mUniversalSelectors;
|
||||
PRUint32 mNameSpaceSelectors;
|
||||
@ -489,8 +489,6 @@ RuleHash::RuleHash(bool aQuirksMode)
|
||||
#endif
|
||||
{
|
||||
MOZ_COUNT_CTOR(RuleHash);
|
||||
// Initialize our arena
|
||||
PL_INIT_ARENA_POOL(&mArena, "RuleHashArena", NS_RULEHASH_ARENA_BLOCK_SIZE);
|
||||
|
||||
PL_DHashTableInit(&mTagTable, &RuleHash_TagTable_Ops, nsnull,
|
||||
sizeof(RuleHashTagTableEntry), 64);
|
||||
@ -552,7 +550,6 @@ RuleHash::~RuleHash()
|
||||
PL_DHashTableFinish(&mClassTable);
|
||||
PL_DHashTableFinish(&mTagTable);
|
||||
PL_DHashTableFinish(&mNameSpaceTable);
|
||||
PL_FinishArenaPool(&mArena);
|
||||
}
|
||||
|
||||
void RuleHash::AppendRuleToTable(PLDHashTable* aTable, const void* aKey,
|
||||
@ -766,12 +763,6 @@ RuleHash::SizeOf() const
|
||||
|
||||
n += mUniversalRules.SizeOf();
|
||||
|
||||
const PLArena* current = &mArena.first;
|
||||
while (current) {
|
||||
n += current->limit - current->base;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -2833,13 +2824,37 @@ AddRule(RuleSelectorPair* aRuleInfo, RuleCascadeData* aCascade)
|
||||
return true;
|
||||
}
|
||||
|
||||
struct PerWeightDataListItem : public RuleSelectorPair {
|
||||
PerWeightDataListItem(css::StyleRule* aRule, nsCSSSelector* aSelector)
|
||||
: RuleSelectorPair(aRule, aSelector)
|
||||
, mNext(nsnull)
|
||||
{}
|
||||
// No destructor; these are arena-allocated
|
||||
|
||||
|
||||
// Placement new to arena allocate the PerWeightDataListItem
|
||||
void *operator new(size_t aSize, PLArenaPool &aArena) CPP_THROW_NEW {
|
||||
void *mem;
|
||||
PL_ARENA_ALLOCATE(mem, &aArena, aSize);
|
||||
return mem;
|
||||
}
|
||||
|
||||
PerWeightDataListItem *mNext;
|
||||
};
|
||||
|
||||
struct PerWeightData {
|
||||
PerWeightData()
|
||||
: mRuleSelectorPairs(nsnull)
|
||||
, mTail(&mRuleSelectorPairs)
|
||||
{}
|
||||
|
||||
PRInt32 mWeight;
|
||||
nsTArray<RuleSelectorPair> mRules; // forward order
|
||||
PerWeightDataListItem *mRuleSelectorPairs;
|
||||
PerWeightDataListItem **mTail;
|
||||
};
|
||||
|
||||
struct RuleByWeightEntry : public PLDHashEntryHdr {
|
||||
PerWeightData data; // mWeight is key, mRules are value
|
||||
PerWeightData data; // mWeight is key, mRuleSelectorPairs are value
|
||||
};
|
||||
|
||||
static PLDHashNumber
|
||||
@ -2865,20 +2880,13 @@ InitWeightEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ClearWeightEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleByWeightEntry* entry = static_cast<RuleByWeightEntry*>(hdr);
|
||||
entry->~RuleByWeightEntry();
|
||||
}
|
||||
|
||||
static PLDHashTableOps gRulesByWeightOps = {
|
||||
PL_DHashAllocTable,
|
||||
PL_DHashFreeTable,
|
||||
HashIntKey,
|
||||
MatchWeightEntry,
|
||||
PL_DHashMoveEntryStub,
|
||||
ClearWeightEntry,
|
||||
PL_DHashClearEntryStub,
|
||||
PL_DHashFinalizeStub,
|
||||
InitWeightEntry
|
||||
};
|
||||
@ -2888,34 +2896,37 @@ struct CascadeEnumData {
|
||||
nsTArray<nsFontFaceRuleContainer>& aFontFaceRules,
|
||||
nsTArray<nsCSSKeyframesRule*>& aKeyframesRules,
|
||||
nsMediaQueryResultCacheKey& aKey,
|
||||
PLArenaPool& aArena,
|
||||
PRUint8 aSheetType)
|
||||
: mPresContext(aPresContext),
|
||||
mFontFaceRules(aFontFaceRules),
|
||||
mKeyframesRules(aKeyframesRules),
|
||||
mCacheKey(aKey),
|
||||
mArena(aArena),
|
||||
mSheetType(aSheetType)
|
||||
{
|
||||
if (!PL_DHashTableInit(&mRulesByWeight, &gRulesByWeightOps, nsnull,
|
||||
sizeof(RuleByWeightEntry), 64))
|
||||
mRulesByWeight.ops = nsnull;
|
||||
|
||||
// Initialize our arena
|
||||
PL_INIT_ARENA_POOL(&mArena, "CascadeEnumDataArena",
|
||||
NS_CASCADEENUMDATA_ARENA_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
~CascadeEnumData()
|
||||
{
|
||||
if (mRulesByWeight.ops)
|
||||
PL_DHashTableFinish(&mRulesByWeight);
|
||||
PL_FinishArenaPool(&mArena);
|
||||
}
|
||||
|
||||
nsPresContext* mPresContext;
|
||||
nsTArray<nsFontFaceRuleContainer>& mFontFaceRules;
|
||||
nsTArray<nsCSSKeyframesRule*>& mKeyframesRules;
|
||||
nsMediaQueryResultCacheKey& mCacheKey;
|
||||
PLArenaPool& mArena;
|
||||
PLArenaPool mArena;
|
||||
// Hooray, a manual PLDHashTable since nsClassHashtable doesn't
|
||||
// provide a getter that gives me a *reference* to the value.
|
||||
PLDHashTable mRulesByWeight; // of RuleValue* linked lists (?)
|
||||
PLDHashTable mRulesByWeight; // of PerWeightDataListItem linked lists
|
||||
PRUint8 mSheetType;
|
||||
};
|
||||
|
||||
@ -2946,9 +2957,14 @@ CascadeRuleEnumFunc(css::Rule* aRule, void* aData)
|
||||
if (!entry)
|
||||
return false;
|
||||
entry->data.mWeight = weight;
|
||||
// entry->data.mRules must be in forward order.
|
||||
entry->data.mRules.AppendElement(RuleSelectorPair(styleRule,
|
||||
sel->mSelectors));
|
||||
// entry->data.mRuleSelectorPairs should be linked in forward order;
|
||||
// entry->data.mTail is the slot to write to.
|
||||
PerWeightDataListItem *newItem =
|
||||
new (data->mArena) PerWeightDataListItem(styleRule, sel->mSelectors);
|
||||
if (newItem) {
|
||||
*(entry->data.mTail) = newItem;
|
||||
entry->data.mTail = &newItem->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (css::Rule::MEDIA_RULE == type ||
|
||||
@ -3075,7 +3091,6 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
||||
CascadeEnumData data(aPresContext, newCascade->mFontFaceRules,
|
||||
newCascade->mKeyframesRules,
|
||||
newCascade->mCacheKey,
|
||||
newCascade->mRuleHash.Arena(),
|
||||
mSheetType);
|
||||
if (!data.mRulesByWeight.ops)
|
||||
return; /* out of memory */
|
||||
@ -3096,12 +3111,11 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
||||
// Put things into the rule hash.
|
||||
// The primary sort is by weight...
|
||||
for (PRUint32 i = 0; i < weightCount; ++i) {
|
||||
// and the secondary sort is by order. mRules are already in
|
||||
// and the secondary sort is by order. mRuleSelectorPairs is already in
|
||||
// the right order..
|
||||
nsTArray<RuleSelectorPair>& arr = weightArray[i].mRules;
|
||||
for (RuleSelectorPair *cur = arr.Elements(),
|
||||
*end = cur + arr.Length();
|
||||
cur != end; ++cur) {
|
||||
for (PerWeightDataListItem *cur = weightArray[i].mRuleSelectorPairs;
|
||||
cur;
|
||||
cur = cur->mNext) {
|
||||
if (!AddRule(cur, newCascade))
|
||||
return; /* out of memory */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user