зеркало из https://github.com/mozilla/pjs.git
Bug 514773. Don't trigger rulenode gc unless we have rulenodes to gc. r=dbaron
This commit is contained in:
Родитель
b0feb8e6ff
Коммит
751e9657f6
|
@ -876,7 +876,8 @@ nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
|
|||
mRule(aRule),
|
||||
mDependentBits((PRUint32(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) |
|
||||
(aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)),
|
||||
mNoneBits(0)
|
||||
mNoneBits(0),
|
||||
mRefCnt(0)
|
||||
{
|
||||
mChildren.asVoid = nsnull;
|
||||
MOZ_COUNT_CTOR(nsRuleNode);
|
||||
|
@ -884,6 +885,13 @@ nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
|
|||
|
||||
NS_ASSERTION(IsRoot() || GetLevel() == aLevel, "not enough bits");
|
||||
NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant, "yikes");
|
||||
/* If IsRoot(), then aContext->StyleSet() is typically null at this
|
||||
point. In any case, we don't want to treat the root rulenode as
|
||||
unused. */
|
||||
if (!IsRoot()) {
|
||||
mParent->AddRef();
|
||||
aContext->StyleSet()->RuleNodeUnused();
|
||||
}
|
||||
}
|
||||
|
||||
nsRuleNode::~nsRuleNode()
|
||||
|
@ -6192,22 +6200,32 @@ nsRuleNode::Sweep()
|
|||
// Call sweep on the children, since some may not be marked, and
|
||||
// remove any deleted children from the child lists.
|
||||
if (HaveChildren()) {
|
||||
PRUint32 childrenDestroyed;
|
||||
if (ChildrenAreHashed()) {
|
||||
PLDHashTable *children = ChildrenHash();
|
||||
PRUint32 oldChildCount = children->entryCount;
|
||||
PL_DHashTableEnumerate(children, SweepRuleNodeChildren, nsnull);
|
||||
childrenDestroyed = children->entryCount - oldChildCount;
|
||||
} else {
|
||||
childrenDestroyed = 0;
|
||||
for (nsRuleNode **children = ChildrenListPtr(); *children; ) {
|
||||
nsRuleNode *next = (*children)->mNextSibling;
|
||||
if ((*children)->Sweep()) {
|
||||
// This rule node was destroyed, so implicitly advance by
|
||||
// making *children point to the next entry.
|
||||
*children = next;
|
||||
++childrenDestroyed;
|
||||
} else {
|
||||
// Advance.
|
||||
children = &(*children)->mNextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
mRefCnt -= childrenDestroyed;
|
||||
NS_POSTCONDITION(IsRoot() || mRefCnt > 0,
|
||||
"We didn't get swept, so we'd better have style contexts "
|
||||
"pointing to us or to one of our descendants, which means "
|
||||
"we'd better have a nonzero mRefCnt here!");
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
|
|
@ -451,6 +451,11 @@ private:
|
|||
// Compute*Data functions don't initialize from
|
||||
// inherited data.
|
||||
|
||||
// Reference count. This just counts the style contexts that
|
||||
// reference this rulenode. When this goes to 0 or stops being 0,
|
||||
// we notify the style set.
|
||||
PRUint32 mRefCnt;
|
||||
|
||||
public:
|
||||
// Overloaded new operator. Initializes the memory to 0 and relies on an arena
|
||||
// (which comes from the presShell) to perform the allocation.
|
||||
|
@ -458,6 +463,12 @@ public:
|
|||
NS_HIDDEN_(void) Destroy() { DestroyInternal(nsnull); }
|
||||
static NS_HIDDEN_(nsILanguageAtomService*) gLangService;
|
||||
|
||||
// Implemented in nsStyleSet.h, since it needs to know about nsStyleSet.
|
||||
inline NS_HIDDEN_(void) AddRef();
|
||||
|
||||
// Implemented in nsStyleSet.h, since it needs to know about nsStyleSet.
|
||||
inline NS_HIDDEN_(void) Release();
|
||||
|
||||
protected:
|
||||
NS_HIDDEN_(void) DestroyInternal(nsRuleNode ***aDestroyQueueTail);
|
||||
NS_HIDDEN_(void) PropagateDependentBit(PRUint32 aBit,
|
||||
|
|
|
@ -91,6 +91,8 @@ nsStyleContext::nsStyleContext(nsStyleContext* aParent,
|
|||
NS_ASSERTION(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
|
||||
"NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
|
||||
#undef eStyleStruct_LastItem
|
||||
|
||||
mRuleNode->AddRef();
|
||||
}
|
||||
|
||||
nsStyleContext::~nsStyleContext()
|
||||
|
@ -99,6 +101,8 @@ nsStyleContext::~nsStyleContext()
|
|||
|
||||
nsPresContext *presContext = mRuleNode->GetPresContext();
|
||||
|
||||
mRuleNode->Release();
|
||||
|
||||
presContext->PresShell()->StyleSet()->
|
||||
NotifyStyleContextDestroyed(presContext, this);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ static const nsStyleSet::sheetType gCSSSheetTypes[] = {
|
|||
nsStyleSet::nsStyleSet()
|
||||
: mRuleTree(nsnull),
|
||||
mRuleWalker(nsnull),
|
||||
mDestroyedCount(0),
|
||||
mUnusedRuleNodeCount(0),
|
||||
mBatching(0),
|
||||
mInShutdown(PR_FALSE),
|
||||
mAuthorStyleDisabled(PR_FALSE),
|
||||
|
@ -905,7 +905,7 @@ nsStyleSet::Shutdown(nsPresContext* aPresContext)
|
|||
mDefaultStyleData.Destroy(0, aPresContext);
|
||||
}
|
||||
|
||||
static const PRInt32 kGCInterval = 1000;
|
||||
static const PRInt32 kGCInterval = 300;
|
||||
|
||||
void
|
||||
nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext,
|
||||
|
@ -925,7 +925,7 @@ nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext,
|
|||
if (mInReconstruct)
|
||||
return;
|
||||
|
||||
if (++mDestroyedCount == kGCInterval) {
|
||||
if (mUnusedRuleNodeCount == kGCInterval) {
|
||||
GCRuleTrees();
|
||||
}
|
||||
}
|
||||
|
@ -933,7 +933,7 @@ nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext,
|
|||
void
|
||||
nsStyleSet::GCRuleTrees()
|
||||
{
|
||||
mDestroyedCount = 0;
|
||||
mUnusedRuleNodeCount = 0;
|
||||
|
||||
// Mark the style context tree by marking all style contexts which
|
||||
// have no parent, which will mark all descendants. This will reach
|
||||
|
|
|
@ -248,6 +248,17 @@ class nsStyleSet
|
|||
PRBool HasCachedStyleData() const {
|
||||
return (mRuleTree && mRuleTree->TreeHasCachedData()) || !mRoots.IsEmpty();
|
||||
}
|
||||
|
||||
// Notify the style set that a rulenode is no longer in use, or was
|
||||
// just created and is not in use yet.
|
||||
void RuleNodeUnused() {
|
||||
++mUnusedRuleNodeCount;
|
||||
}
|
||||
|
||||
// Notify the style set that a rulenode that wasn't in use now is
|
||||
void RuleNodeInUse() {
|
||||
--mUnusedRuleNodeCount;
|
||||
}
|
||||
|
||||
private:
|
||||
// Not to be implemented
|
||||
|
@ -322,7 +333,7 @@ class nsStyleSet
|
|||
nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can
|
||||
// be used to navigate through our tree.
|
||||
|
||||
PRInt32 mDestroyedCount; // used to batch style context GC
|
||||
PRUint32 mUnusedRuleNodeCount; // used to batch rule node GC
|
||||
nsTArray<nsStyleContext*> mRoots; // style contexts with no parent
|
||||
|
||||
// Empty style rules to force things that restrict which properties
|
||||
|
@ -343,4 +354,19 @@ class nsStyleSet
|
|||
|
||||
};
|
||||
|
||||
inline
|
||||
NS_HIDDEN_(void) nsRuleNode::AddRef()
|
||||
{
|
||||
if (mRefCnt++ == 0 && !IsRoot()) {
|
||||
mPresContext->StyleSet()->RuleNodeInUse();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
NS_HIDDEN_(void) nsRuleNode::Release()
|
||||
{
|
||||
if (--mRefCnt == 0 && !IsRoot()) {
|
||||
mPresContext->StyleSet()->RuleNodeUnused();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче