Use the existing linked list structure while sorting rules instead of using temporary arrays. b=408295 r+sr=sicking a=dsicore

This commit is contained in:
dbaron@dbaron.org 2007-12-14 14:59:20 -08:00
Родитель acd02c39f3
Коммит f66731bfd1
4 изменённых файлов: 104 добавлений и 62 удалений

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

@ -1925,20 +1925,19 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
return PR_FALSE;
}
PR_STATIC_CALLBACK(PRBool)
AddRule(void* aRuleInfo, void* aCascade)
static PRBool
AddRule(RuleValue* aRuleInfo, void* aCascade)
{
RuleValue* ruleInfo = static_cast<RuleValue*>(aRuleInfo);
RuleCascadeData *cascade = static_cast<RuleCascadeData*>(aCascade);
// Build the rule hash.
cascade->mRuleHash.PrependRule(ruleInfo);
cascade->mRuleHash.PrependRule(aRuleInfo);
nsVoidArray* stateArray = &cascade->mStateSelectors;
nsVoidArray* classArray = &cascade->mClassSelectors;
nsVoidArray* idArray = &cascade->mIDSelectors;
for (nsCSSSelector* selector = ruleInfo->mSelector;
for (nsCSSSelector* selector = aRuleInfo->mSelector;
selector; selector = selector->mNext) {
// It's worth noting that this loop over negations isn't quite
// optimal for two reasons. One, we could add something to one of
@ -1978,23 +1977,60 @@ AddRule(void* aRuleInfo, void* aCascade)
return PR_TRUE;
}
PR_STATIC_CALLBACK(PRIntn)
RuleArraysDestroy(nsHashKey *aKey, void *aData, void *aClosure)
struct PerWeightData {
PRInt32 mWeight;
RuleValue* mRules; // linked list (reverse order)
};
struct RuleByWeightEntry : public PLDHashEntryHdr {
PerWeightData data; // mWeight is key, mRules are value
};
PR_STATIC_CALLBACK(PLDHashNumber)
HashIntKey(PLDHashTable *table, const void *key)
{
delete static_cast<nsAutoVoidArray*>(aData);
return PR_TRUE;
return PLDHashNumber(NS_PTR_TO_INT32(key));
}
PR_STATIC_CALLBACK(PRBool)
MatchWeightEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
const void *key)
{
const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr;
return entry->data.mWeight == NS_PTR_TO_INT32(key);
}
static PLDHashTableOps gRulesByWeightOps = {
PL_DHashAllocTable,
PL_DHashFreeTable,
HashIntKey,
MatchWeightEntry,
PL_DHashMoveEntryStub,
PL_DHashClearEntryStub,
PL_DHashFinalizeStub,
NULL
};
struct CascadeEnumData {
CascadeEnumData(nsPresContext* aPresContext, PLArenaPool& aArena)
: mPresContext(aPresContext),
mRuleArrays(nsnull, nsnull, RuleArraysDestroy, nsnull, 64),
mArena(aArena)
{
if (!PL_DHashTableInit(&mRulesByWeight, &gRulesByWeightOps, nsnull,
sizeof(RuleByWeightEntry), 64))
mRulesByWeight.ops = nsnull;
}
~CascadeEnumData()
{
if (mRulesByWeight.ops)
PL_DHashTableFinish(&mRulesByWeight);
}
nsPresContext* mPresContext;
nsObjectHashtable mRuleArrays; // of nsAutoVoidArray
// 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 (?)
PLArenaPool& mArena;
};
@ -2011,24 +2047,25 @@ InsertRuleByWeight(nsICSSRule* aRule, void* aData)
for (nsCSSSelectorList *sel = styleRule->Selector();
sel; sel = sel->mNext) {
PRInt32 weight = sel->mWeight;
nsPRUint32Key key(weight);
nsAutoVoidArray *rules =
static_cast<nsAutoVoidArray*>(data->mRuleArrays.Get(&key));
if (!rules) {
rules = new nsAutoVoidArray();
if (!rules) return PR_FALSE; // out of memory
data->mRuleArrays.Put(&key, rules);
}
RuleByWeightEntry *entry = static_cast<RuleByWeightEntry*>(
PL_DHashTableOperate(&data->mRulesByWeight, NS_INT32_TO_PTR(weight),
PL_DHASH_ADD));
if (!entry)
return PR_FALSE;
entry->data.mWeight = weight;
RuleValue *info =
new (data->mArena) RuleValue(styleRule, sel->mSelectors);
rules->AppendElement(info);
// entry->data.mRules must be in backwards order.
info->mNext = entry->data.mRules;
entry->data.mRules = info;
}
}
else if (nsICSSRule::MEDIA_RULE == type ||
nsICSSRule::DOCUMENT_RULE == type) {
nsICSSGroupRule* groupRule = (nsICSSGroupRule*)aRule;
if (groupRule->UseForPresentation(data->mPresContext))
groupRule->EnumerateRulesForwards(InsertRuleByWeight, aData);
if (!groupRule->EnumerateRulesForwards(InsertRuleByWeight, aData))
return PR_FALSE;
}
return PR_TRUE;
}
@ -2050,48 +2087,43 @@ CascadeSheetRulesInto(nsICSSStyleSheet* aSheet, void* aData)
}
if (sheet->mInner) {
sheet->mInner->mOrderedRules.EnumerateForwards(InsertRuleByWeight, data);
if (!sheet->mInner->mOrderedRules.EnumerateForwards(InsertRuleByWeight, data))
return PR_FALSE;
}
}
return PR_TRUE;
}
struct RuleArrayData {
PRInt32 mWeight;
nsVoidArray* mRuleArray;
};
PR_STATIC_CALLBACK(int) CompareArrayData(const void* aArg1, const void* aArg2,
PR_STATIC_CALLBACK(int) CompareWeightData(const void* aArg1, const void* aArg2,
void* closure)
{
const RuleArrayData* arg1 = static_cast<const RuleArrayData*>(aArg1);
const RuleArrayData* arg2 = static_cast<const RuleArrayData*>(aArg2);
const PerWeightData* arg1 = static_cast<const PerWeightData*>(aArg1);
const PerWeightData* arg2 = static_cast<const PerWeightData*>(aArg2);
return arg1->mWeight - arg2->mWeight; // put lower weight first
}
struct FillArrayData {
FillArrayData(RuleArrayData* aArrayData) :
struct FillWeightArrayData {
FillWeightArrayData(PerWeightData* aArrayData) :
mIndex(0),
mArrayData(aArrayData)
mWeightArray(aArrayData)
{
}
PRInt32 mIndex;
RuleArrayData* mArrayData;
PerWeightData* mWeightArray;
};
PR_STATIC_CALLBACK(PRBool)
FillArray(nsHashKey* aKey, void* aData, void* aClosure)
PR_STATIC_CALLBACK(PLDHashOperator)
FillWeightArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
PRUint32 number, void *arg)
{
nsPRUint32Key* key = static_cast<nsPRUint32Key*>(aKey);
nsVoidArray* weightArray = static_cast<nsVoidArray*>(aData);
FillArrayData* data = static_cast<FillArrayData*>(aClosure);
FillWeightArrayData* data = static_cast<FillWeightArrayData*>(arg);
const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr;
RuleArrayData& ruleData = data->mArrayData[data->mIndex++];
ruleData.mRuleArray = weightArray;
ruleData.mWeight = key->GetValue();
data->mWeightArray[data->mIndex++] = entry->data;
return PR_TRUE;
return PL_DHASH_NEXT;
}
RuleCascadeData*
@ -2118,24 +2150,34 @@ nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
eCompatibility_NavQuirks == aPresContext->CompatibilityMode()));
if (newCascade) {
CascadeEnumData data(aPresContext, newCascade->mRuleHash.Arena());
mSheets.EnumerateForwards(CascadeSheetRulesInto, &data);
if (!data.mRulesByWeight.ops)
return nsnull;
if (!mSheets.EnumerateForwards(CascadeSheetRulesInto, &data))
return nsnull;
// Take the hashtable of arrays (keyed by weight, in order sort) and
// sort by weight and secondary sort by order.
PRInt32 arrayCount = data.mRuleArrays.Count();
nsAutoArrayPtr<RuleArrayData> arrayData(new RuleArrayData[arrayCount]);
FillArrayData faData(arrayData);
data.mRuleArrays.Enumerate(FillArray, &faData);
NS_QuickSort(arrayData, arrayCount, sizeof(RuleArrayData),
CompareArrayData, nsnull);
// Sort the hash table of per-weight linked lists by weight.
PRUint32 weightCount = data.mRulesByWeight.entryCount;
nsAutoArrayPtr<PerWeightData> weightArray(new PerWeightData[weightCount]);
FillWeightArrayData fwData(weightArray);
PL_DHashTableEnumerate(&data.mRulesByWeight, FillWeightArray, &fwData);
NS_QuickSort(weightArray, weightCount, sizeof(PerWeightData),
CompareWeightData, nsnull);
// Put things into the rule hash backwards because it's easier to
// build a singly linked list lowest-first that way.
for (PRInt32 i = arrayCount - 1; i >= 0; --i) {
if (!arrayData[i].mRuleArray->EnumerateBackwards(AddRule,
newCascade)) {
return nsnull;
}
// The primary sort is by weight...
PRUint32 i = weightCount;
while (i > 0) {
--i;
// and the secondary sort is by order. mRules are already backwards.
RuleValue *ruleValue = weightArray[i].mRules;
do {
// Calling |AddRule| reuses mNext!
RuleValue *next = ruleValue->mNext;
if (!AddRule(ruleValue, newCascade))
return nsnull;
ruleValue = next;
} while (ruleValue);
}
*cascadep = newCascade;

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

@ -728,11 +728,11 @@ nsCSSGroupRule::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const
return NS_OK;
}
NS_IMETHODIMP
NS_IMETHODIMP_(PRBool)
nsCSSGroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
{
const_cast<nsCSSGroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
return NS_OK;
return
const_cast<nsCSSGroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
}
/*

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

@ -84,7 +84,7 @@ public:
NS_IMETHOD AppendStyleRule(nsICSSRule* aRule);
NS_IMETHOD StyleRuleCount(PRInt32& aCount) const;
NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const;
NS_IMETHOD EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const;
NS_IMETHOD_(PRBool) EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const;
NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex);
NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex,
nsCOMArray<nsICSSRule>& aRules);

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

@ -63,7 +63,7 @@ public:
NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0;
typedef nsCOMArray<nsICSSRule>::nsCOMArrayEnumFunc RuleEnumFunc;
NS_IMETHOD EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const = 0;
NS_IMETHOD_(PRBool) EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const = 0;
/*
* The next three methods should never be called unless you have first