Bug 931668 - Part 24: Avoid copying RestyleData::mDescendants when modifying an existing entry. r=dbaron

--HG--
extra : rebase_source : 0b9905bdff6f9ceec823b2091aadc39f0ca467bc
This commit is contained in:
Cameron McCormack 2014-09-05 13:48:48 +10:00
parent ba2eea0592
commit 01abd28246
3 changed files with 60 additions and 55 deletions

View File

@ -2420,14 +2420,14 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
// we'll fail to do the restyling we need to do.
(mContent->GetParent() || mContent->GetPrimaryFrame() == mFrame)) {
mContent->OwnerDoc()->FlushPendingLinkUpdates();
RestyleTracker::RestyleData restyleData;
if (mRestyleTracker.GetRestyleData(mContent->AsElement(), &restyleData)) {
if (NS_UpdateHint(mHintsHandled, restyleData.mChangeHint)) {
mChangeList->AppendChange(mFrame, mContent, restyleData.mChangeHint);
nsAutoPtr<RestyleTracker::RestyleData> restyleData;
if (mRestyleTracker.GetRestyleData(mContent->AsElement(), restyleData)) {
if (NS_UpdateHint(mHintsHandled, restyleData->mChangeHint)) {
mChangeList->AppendChange(mFrame, mContent, restyleData->mChangeHint);
}
hintToRestore = restyleData.mRestyleHint;
aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
descendants.SwapElements(restyleData.mDescendants);
hintToRestore = restyleData->mRestyleHint;
aRestyleHint = nsRestyleHint(aRestyleHint | restyleData->mRestyleHint);
descendants.SwapElements(restyleData->mDescendants);
}
}
@ -3138,12 +3138,12 @@ ElementRestyler::RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint)
}
nsRestyleHint thisChildHint = aChildRestyleHint;
RestyleTracker::RestyleData undisplayedRestyleData;
nsAutoPtr<RestyleTracker::RestyleData> undisplayedRestyleData;
Element* element = undisplayed->mContent->AsElement();
if (mRestyleTracker.GetRestyleData(element,
&undisplayedRestyleData)) {
undisplayedRestyleData)) {
thisChildHint =
nsRestyleHint(thisChildHint | undisplayedRestyleData.mRestyleHint);
nsRestyleHint(thisChildHint | undisplayedRestyleData->mRestyleHint);
}
nsRefPtr<nsStyleContext> undisplayedContext;
nsStyleSet* styleSet = mPresContext->StyleSet();

View File

@ -29,7 +29,7 @@ struct LaterSiblingCollector {
static PLDHashOperator
CollectLaterSiblings(nsISupports* aElement,
RestyleTracker::RestyleData& aData,
nsAutoPtr<RestyleTracker::RestyleData>& aData,
void* aSiblingCollector)
{
dom::Element* element =
@ -42,7 +42,7 @@ CollectLaterSiblings(nsISupports* aElement,
// document.
if (element->GetCrossShadowCurrentDoc() == collector->tracker->Document() &&
element->HasFlag(collector->tracker->RestyleBit()) &&
(aData.mRestyleHint & eRestyle_LaterSiblings)) {
(aData->mRestyleHint & eRestyle_LaterSiblings)) {
collector->elements->AppendElement(element);
}
@ -56,7 +56,7 @@ struct RestyleCollector {
static PLDHashOperator
CollectRestyles(nsISupports* aElement,
RestyleTracker::RestyleData& aData,
nsAutoPtr<RestyleTracker::RestyleData>& aData,
void* aRestyleCollector)
{
dom::Element* element =
@ -83,7 +83,7 @@ CollectRestyles(nsISupports* aElement,
// the bit, since any descendants that didn't get added
// to the roots list because we had the bits will be
// completely restyled in a moment.
(aData.mChangeHint & nsChangeHint_ReconstructFrame),
(aData->mChangeHint & nsChangeHint_ReconstructFrame),
"Why did this not get handled while processing mRestyleRoots?");
// Unset the restyle bits now, so if they get readded later as we
@ -96,8 +96,8 @@ CollectRestyles(nsISupports* aElement,
RestyleTracker::RestyleEnumerateData* currentRestyle =
*restyleArrayPtr;
currentRestyle->mElement = element;
currentRestyle->mRestyleHint = aData.mRestyleHint;
currentRestyle->mChangeHint = aData.mChangeHint;
currentRestyle->mRestyleHint = aData->mRestyleHint;
currentRestyle->mChangeHint = aData->mChangeHint;
// Increment to the next slot in the array
*restyleArrayPtr = currentRestyle + 1;
@ -164,16 +164,14 @@ RestyleTracker::DoProcessRestyles()
for (uint32_t i = 0; i < laterSiblingArr.Length(); ++i) {
Element* element = laterSiblingArr[i];
NS_ASSERTION(element->HasFlag(RestyleBit()), "How did that happen?");
RestyleData data;
RestyleData* data;
#ifdef DEBUG
bool found =
#endif
mPendingRestyles.Get(element, &data);
NS_ASSERTION(found, "Where did our entry go?");
data.mRestyleHint =
nsRestyleHint(data.mRestyleHint & ~eRestyle_LaterSiblings);
mPendingRestyles.Put(element, data);
data->mRestyleHint =
nsRestyleHint(data->mRestyleHint & ~eRestyle_LaterSiblings);
}
mHaveLaterSiblingRestyles = false;
@ -197,13 +195,13 @@ RestyleTracker::DoProcessRestyles()
continue;
}
RestyleData data;
if (!GetRestyleData(element, &data)) {
nsAutoPtr<RestyleData> data;
if (!GetRestyleData(element, data)) {
continue;
}
ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint);
AddRestyleRootsIfAwaitingRestyle(data.mDescendants);
ProcessOneRestyle(element, data->mRestyleHint, data->mChangeHint);
AddRestyleRootsIfAwaitingRestyle(data->mDescendants);
}
if (mHaveLaterSiblingRestyles) {
@ -243,7 +241,7 @@ RestyleTracker::DoProcessRestyles()
}
bool
RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
RestyleTracker::GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData)
{
NS_PRECONDITION(aElement->GetCrossShadowCurrentDoc() == Document(),
"Unexpected document; this will lead to incorrect behavior!");
@ -253,11 +251,8 @@ RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
return false;
}
#ifdef DEBUG
bool gotData =
#endif
mPendingRestyles.Get(aElement, aData);
NS_ASSERTION(gotData, "Must have data if restyle bit is set");
mPendingRestyles.RemoveAndForget(aElement, aData);
NS_ASSERTION(aData.get(), "Must have data if restyle bit is set");
if (aData->mRestyleHint & eRestyle_LaterSiblings) {
// Someone readded the eRestyle_LaterSiblings hint for this
@ -266,15 +261,14 @@ RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
// since it's no longer a root with the new restyle data.
NS_ASSERTION(aData->mDescendants.IsEmpty(),
"expected descendants to be handled by now");
RestyleData newData;
newData.mChangeHint = nsChangeHint(0);
newData.mRestyleHint = eRestyle_LaterSiblings;
RestyleData* newData = new RestyleData;
newData->mChangeHint = nsChangeHint(0);
newData->mRestyleHint = eRestyle_LaterSiblings;
mPendingRestyles.Put(aElement, newData);
aElement->UnsetFlags(RootBit());
aData->mRestyleHint =
nsRestyleHint(aData->mRestyleHint & ~eRestyle_LaterSiblings);
} else {
mPendingRestyles.Remove(aElement);
aElement->UnsetFlags(mRestyleBits);
}

View File

@ -12,7 +12,7 @@
#define mozilla_RestyleTracker_h
#include "mozilla/dom/Element.h"
#include "nsDataHashtable.h"
#include "nsClassHashtable.h"
#include "nsContainerFrame.h"
#include "mozilla/SplayTree.h"
@ -286,8 +286,18 @@ public:
Element::FlagsType RootBit() const {
return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
}
struct RestyleData {
RestyleData() {
mRestyleHint = nsRestyleHint(0);
mChangeHint = NS_STYLE_HINT_NONE;
}
RestyleData(nsRestyleHint aRestyleHint, nsChangeHint aChangeHint) {
mRestyleHint = aRestyleHint;
mChangeHint = aChangeHint;
}
nsRestyleHint mRestyleHint; // What we want to restyle
nsChangeHint mChangeHint; // The minimal change hint for "self"
@ -306,10 +316,9 @@ public:
* eRestyle_LaterSiblings hint in it.
*
* The return value indicates whether any restyle data was found for
* the element. If false is returned, then the state of *aData is
* undefined.
* the element. aData is set to nullptr iff false is returned.
*/
bool GetRestyleData(Element* aElement, RestyleData* aData);
bool GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData);
/**
* For each element in aElements, appends it to mRestyleRoots if it
@ -353,14 +362,14 @@ private:
*/
void DoProcessRestyles();
typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
typedef nsClassHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
// Our restyle bits. These will be a subset of ELEMENT_ALL_RESTYLE_FLAGS, and
// will include one flag from ELEMENT_PENDING_RESTYLE_FLAGS and one flag
// that's not in ELEMENT_PENDING_RESTYLE_FLAGS.
Element::FlagsType mRestyleBits;
RestyleManager* mRestyleManager; // Owns us
// A hashtable that maps elements to RestyleData structs. The
// A hashtable that maps elements to pointers to RestyleData structs. The
// values only make sense if the element's current document is our
// document and it has our RestyleBit() flag set. In particular,
// said bit might not be set if the element had a restyle posted and
@ -384,9 +393,7 @@ RestyleTracker::AddPendingRestyleToTable(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
RestyleData existingData;
existingData.mRestyleHint = nsRestyleHint(0);
existingData.mChangeHint = NS_STYLE_HINT_NONE;
RestyleData* existingData;
// Check the RestyleBit() flag before doing the hashtable Get, since
// it's possible that the data in the hashtable isn't actually
@ -395,15 +402,20 @@ RestyleTracker::AddPendingRestyleToTable(Element* aElement,
mPendingRestyles.Get(aElement, &existingData);
} else {
aElement->SetFlags(RestyleBit());
existingData = nullptr;
}
if (!existingData) {
mPendingRestyles.Put(aElement,
new RestyleData(aRestyleHint, aMinChangeHint));
return false;
}
bool hadRestyleLaterSiblings =
(existingData.mRestyleHint & eRestyle_LaterSiblings) != 0;
existingData.mRestyleHint =
nsRestyleHint(existingData.mRestyleHint | aRestyleHint);
NS_UpdateHint(existingData.mChangeHint, aMinChangeHint);
mPendingRestyles.Put(aElement, existingData);
(existingData->mRestyleHint & eRestyle_LaterSiblings) != 0;
existingData->mRestyleHint =
nsRestyleHint(existingData->mRestyleHint | aRestyleHint);
NS_UpdateHint(existingData->mChangeHint, aMinChangeHint);
return hadRestyleLaterSiblings;
}
@ -459,11 +471,10 @@ RestyleTracker::AddPendingRestyle(Element* aElement,
// invariant that if two elements appear in the array and one
// is an ancestor of the other, that the ancestor appears after
// the descendant.
RestyleData curData;
// XXX We should avoid copying RestyleData::mDescendants around.
RestyleData* curData;
mPendingRestyles.Get(cur, &curData);
curData.mDescendants.AppendElement(aElement);
mPendingRestyles.Put(cur, curData);
NS_ASSERTION(curData, "expected to find a RestyleData for cur");
curData->mDescendants.AppendElement(aElement);
}
}