mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
ba2eea0592
commit
01abd28246
@ -2420,14 +2420,14 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
|
|||||||
// we'll fail to do the restyling we need to do.
|
// we'll fail to do the restyling we need to do.
|
||||||
(mContent->GetParent() || mContent->GetPrimaryFrame() == mFrame)) {
|
(mContent->GetParent() || mContent->GetPrimaryFrame() == mFrame)) {
|
||||||
mContent->OwnerDoc()->FlushPendingLinkUpdates();
|
mContent->OwnerDoc()->FlushPendingLinkUpdates();
|
||||||
RestyleTracker::RestyleData restyleData;
|
nsAutoPtr<RestyleTracker::RestyleData> restyleData;
|
||||||
if (mRestyleTracker.GetRestyleData(mContent->AsElement(), &restyleData)) {
|
if (mRestyleTracker.GetRestyleData(mContent->AsElement(), restyleData)) {
|
||||||
if (NS_UpdateHint(mHintsHandled, restyleData.mChangeHint)) {
|
if (NS_UpdateHint(mHintsHandled, restyleData->mChangeHint)) {
|
||||||
mChangeList->AppendChange(mFrame, mContent, restyleData.mChangeHint);
|
mChangeList->AppendChange(mFrame, mContent, restyleData->mChangeHint);
|
||||||
}
|
}
|
||||||
hintToRestore = restyleData.mRestyleHint;
|
hintToRestore = restyleData->mRestyleHint;
|
||||||
aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
|
aRestyleHint = nsRestyleHint(aRestyleHint | restyleData->mRestyleHint);
|
||||||
descendants.SwapElements(restyleData.mDescendants);
|
descendants.SwapElements(restyleData->mDescendants);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3138,12 +3138,12 @@ ElementRestyler::RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsRestyleHint thisChildHint = aChildRestyleHint;
|
nsRestyleHint thisChildHint = aChildRestyleHint;
|
||||||
RestyleTracker::RestyleData undisplayedRestyleData;
|
nsAutoPtr<RestyleTracker::RestyleData> undisplayedRestyleData;
|
||||||
Element* element = undisplayed->mContent->AsElement();
|
Element* element = undisplayed->mContent->AsElement();
|
||||||
if (mRestyleTracker.GetRestyleData(element,
|
if (mRestyleTracker.GetRestyleData(element,
|
||||||
&undisplayedRestyleData)) {
|
undisplayedRestyleData)) {
|
||||||
thisChildHint =
|
thisChildHint =
|
||||||
nsRestyleHint(thisChildHint | undisplayedRestyleData.mRestyleHint);
|
nsRestyleHint(thisChildHint | undisplayedRestyleData->mRestyleHint);
|
||||||
}
|
}
|
||||||
nsRefPtr<nsStyleContext> undisplayedContext;
|
nsRefPtr<nsStyleContext> undisplayedContext;
|
||||||
nsStyleSet* styleSet = mPresContext->StyleSet();
|
nsStyleSet* styleSet = mPresContext->StyleSet();
|
||||||
|
@ -29,7 +29,7 @@ struct LaterSiblingCollector {
|
|||||||
|
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
CollectLaterSiblings(nsISupports* aElement,
|
CollectLaterSiblings(nsISupports* aElement,
|
||||||
RestyleTracker::RestyleData& aData,
|
nsAutoPtr<RestyleTracker::RestyleData>& aData,
|
||||||
void* aSiblingCollector)
|
void* aSiblingCollector)
|
||||||
{
|
{
|
||||||
dom::Element* element =
|
dom::Element* element =
|
||||||
@ -42,7 +42,7 @@ CollectLaterSiblings(nsISupports* aElement,
|
|||||||
// document.
|
// document.
|
||||||
if (element->GetCrossShadowCurrentDoc() == collector->tracker->Document() &&
|
if (element->GetCrossShadowCurrentDoc() == collector->tracker->Document() &&
|
||||||
element->HasFlag(collector->tracker->RestyleBit()) &&
|
element->HasFlag(collector->tracker->RestyleBit()) &&
|
||||||
(aData.mRestyleHint & eRestyle_LaterSiblings)) {
|
(aData->mRestyleHint & eRestyle_LaterSiblings)) {
|
||||||
collector->elements->AppendElement(element);
|
collector->elements->AppendElement(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ struct RestyleCollector {
|
|||||||
|
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
CollectRestyles(nsISupports* aElement,
|
CollectRestyles(nsISupports* aElement,
|
||||||
RestyleTracker::RestyleData& aData,
|
nsAutoPtr<RestyleTracker::RestyleData>& aData,
|
||||||
void* aRestyleCollector)
|
void* aRestyleCollector)
|
||||||
{
|
{
|
||||||
dom::Element* element =
|
dom::Element* element =
|
||||||
@ -83,7 +83,7 @@ CollectRestyles(nsISupports* aElement,
|
|||||||
// the bit, since any descendants that didn't get added
|
// the bit, since any descendants that didn't get added
|
||||||
// to the roots list because we had the bits will be
|
// to the roots list because we had the bits will be
|
||||||
// completely restyled in a moment.
|
// completely restyled in a moment.
|
||||||
(aData.mChangeHint & nsChangeHint_ReconstructFrame),
|
(aData->mChangeHint & nsChangeHint_ReconstructFrame),
|
||||||
"Why did this not get handled while processing mRestyleRoots?");
|
"Why did this not get handled while processing mRestyleRoots?");
|
||||||
|
|
||||||
// Unset the restyle bits now, so if they get readded later as we
|
// Unset the restyle bits now, so if they get readded later as we
|
||||||
@ -96,8 +96,8 @@ CollectRestyles(nsISupports* aElement,
|
|||||||
RestyleTracker::RestyleEnumerateData* currentRestyle =
|
RestyleTracker::RestyleEnumerateData* currentRestyle =
|
||||||
*restyleArrayPtr;
|
*restyleArrayPtr;
|
||||||
currentRestyle->mElement = element;
|
currentRestyle->mElement = element;
|
||||||
currentRestyle->mRestyleHint = aData.mRestyleHint;
|
currentRestyle->mRestyleHint = aData->mRestyleHint;
|
||||||
currentRestyle->mChangeHint = aData.mChangeHint;
|
currentRestyle->mChangeHint = aData->mChangeHint;
|
||||||
|
|
||||||
// Increment to the next slot in the array
|
// Increment to the next slot in the array
|
||||||
*restyleArrayPtr = currentRestyle + 1;
|
*restyleArrayPtr = currentRestyle + 1;
|
||||||
@ -164,16 +164,14 @@ RestyleTracker::DoProcessRestyles()
|
|||||||
for (uint32_t i = 0; i < laterSiblingArr.Length(); ++i) {
|
for (uint32_t i = 0; i < laterSiblingArr.Length(); ++i) {
|
||||||
Element* element = laterSiblingArr[i];
|
Element* element = laterSiblingArr[i];
|
||||||
NS_ASSERTION(element->HasFlag(RestyleBit()), "How did that happen?");
|
NS_ASSERTION(element->HasFlag(RestyleBit()), "How did that happen?");
|
||||||
RestyleData data;
|
RestyleData* data;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool found =
|
bool found =
|
||||||
#endif
|
#endif
|
||||||
mPendingRestyles.Get(element, &data);
|
mPendingRestyles.Get(element, &data);
|
||||||
NS_ASSERTION(found, "Where did our entry go?");
|
NS_ASSERTION(found, "Where did our entry go?");
|
||||||
data.mRestyleHint =
|
data->mRestyleHint =
|
||||||
nsRestyleHint(data.mRestyleHint & ~eRestyle_LaterSiblings);
|
nsRestyleHint(data->mRestyleHint & ~eRestyle_LaterSiblings);
|
||||||
|
|
||||||
mPendingRestyles.Put(element, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mHaveLaterSiblingRestyles = false;
|
mHaveLaterSiblingRestyles = false;
|
||||||
@ -197,13 +195,13 @@ RestyleTracker::DoProcessRestyles()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RestyleData data;
|
nsAutoPtr<RestyleData> data;
|
||||||
if (!GetRestyleData(element, &data)) {
|
if (!GetRestyleData(element, data)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint);
|
ProcessOneRestyle(element, data->mRestyleHint, data->mChangeHint);
|
||||||
AddRestyleRootsIfAwaitingRestyle(data.mDescendants);
|
AddRestyleRootsIfAwaitingRestyle(data->mDescendants);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHaveLaterSiblingRestyles) {
|
if (mHaveLaterSiblingRestyles) {
|
||||||
@ -243,7 +241,7 @@ RestyleTracker::DoProcessRestyles()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
|
RestyleTracker::GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(aElement->GetCrossShadowCurrentDoc() == Document(),
|
NS_PRECONDITION(aElement->GetCrossShadowCurrentDoc() == Document(),
|
||||||
"Unexpected document; this will lead to incorrect behavior!");
|
"Unexpected document; this will lead to incorrect behavior!");
|
||||||
@ -253,11 +251,8 @@ RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
mPendingRestyles.RemoveAndForget(aElement, aData);
|
||||||
bool gotData =
|
NS_ASSERTION(aData.get(), "Must have data if restyle bit is set");
|
||||||
#endif
|
|
||||||
mPendingRestyles.Get(aElement, aData);
|
|
||||||
NS_ASSERTION(gotData, "Must have data if restyle bit is set");
|
|
||||||
|
|
||||||
if (aData->mRestyleHint & eRestyle_LaterSiblings) {
|
if (aData->mRestyleHint & eRestyle_LaterSiblings) {
|
||||||
// Someone readded the eRestyle_LaterSiblings hint for this
|
// 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.
|
// since it's no longer a root with the new restyle data.
|
||||||
NS_ASSERTION(aData->mDescendants.IsEmpty(),
|
NS_ASSERTION(aData->mDescendants.IsEmpty(),
|
||||||
"expected descendants to be handled by now");
|
"expected descendants to be handled by now");
|
||||||
RestyleData newData;
|
RestyleData* newData = new RestyleData;
|
||||||
newData.mChangeHint = nsChangeHint(0);
|
newData->mChangeHint = nsChangeHint(0);
|
||||||
newData.mRestyleHint = eRestyle_LaterSiblings;
|
newData->mRestyleHint = eRestyle_LaterSiblings;
|
||||||
mPendingRestyles.Put(aElement, newData);
|
mPendingRestyles.Put(aElement, newData);
|
||||||
aElement->UnsetFlags(RootBit());
|
aElement->UnsetFlags(RootBit());
|
||||||
aData->mRestyleHint =
|
aData->mRestyleHint =
|
||||||
nsRestyleHint(aData->mRestyleHint & ~eRestyle_LaterSiblings);
|
nsRestyleHint(aData->mRestyleHint & ~eRestyle_LaterSiblings);
|
||||||
} else {
|
} else {
|
||||||
mPendingRestyles.Remove(aElement);
|
|
||||||
aElement->UnsetFlags(mRestyleBits);
|
aElement->UnsetFlags(mRestyleBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#define mozilla_RestyleTracker_h
|
#define mozilla_RestyleTracker_h
|
||||||
|
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "nsDataHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsContainerFrame.h"
|
#include "nsContainerFrame.h"
|
||||||
#include "mozilla/SplayTree.h"
|
#include "mozilla/SplayTree.h"
|
||||||
|
|
||||||
@ -286,8 +286,18 @@ public:
|
|||||||
Element::FlagsType RootBit() const {
|
Element::FlagsType RootBit() const {
|
||||||
return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
|
return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RestyleData {
|
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
|
nsRestyleHint mRestyleHint; // What we want to restyle
|
||||||
nsChangeHint mChangeHint; // The minimal change hint for "self"
|
nsChangeHint mChangeHint; // The minimal change hint for "self"
|
||||||
|
|
||||||
@ -306,10 +316,9 @@ public:
|
|||||||
* eRestyle_LaterSiblings hint in it.
|
* eRestyle_LaterSiblings hint in it.
|
||||||
*
|
*
|
||||||
* The return value indicates whether any restyle data was found for
|
* The return value indicates whether any restyle data was found for
|
||||||
* the element. If false is returned, then the state of *aData is
|
* the element. aData is set to nullptr iff false is returned.
|
||||||
* undefined.
|
|
||||||
*/
|
*/
|
||||||
bool GetRestyleData(Element* aElement, RestyleData* aData);
|
bool GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each element in aElements, appends it to mRestyleRoots if it
|
* For each element in aElements, appends it to mRestyleRoots if it
|
||||||
@ -353,14 +362,14 @@ private:
|
|||||||
*/
|
*/
|
||||||
void DoProcessRestyles();
|
void DoProcessRestyles();
|
||||||
|
|
||||||
typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
|
typedef nsClassHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
|
||||||
typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
|
typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
|
||||||
// Our restyle bits. These will be a subset of ELEMENT_ALL_RESTYLE_FLAGS, and
|
// 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
|
// will include one flag from ELEMENT_PENDING_RESTYLE_FLAGS and one flag
|
||||||
// that's not in ELEMENT_PENDING_RESTYLE_FLAGS.
|
// that's not in ELEMENT_PENDING_RESTYLE_FLAGS.
|
||||||
Element::FlagsType mRestyleBits;
|
Element::FlagsType mRestyleBits;
|
||||||
RestyleManager* mRestyleManager; // Owns us
|
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
|
// values only make sense if the element's current document is our
|
||||||
// document and it has our RestyleBit() flag set. In particular,
|
// document and it has our RestyleBit() flag set. In particular,
|
||||||
// said bit might not be set if the element had a restyle posted and
|
// said bit might not be set if the element had a restyle posted and
|
||||||
@ -384,9 +393,7 @@ RestyleTracker::AddPendingRestyleToTable(Element* aElement,
|
|||||||
nsRestyleHint aRestyleHint,
|
nsRestyleHint aRestyleHint,
|
||||||
nsChangeHint aMinChangeHint)
|
nsChangeHint aMinChangeHint)
|
||||||
{
|
{
|
||||||
RestyleData existingData;
|
RestyleData* existingData;
|
||||||
existingData.mRestyleHint = nsRestyleHint(0);
|
|
||||||
existingData.mChangeHint = NS_STYLE_HINT_NONE;
|
|
||||||
|
|
||||||
// Check the RestyleBit() flag before doing the hashtable Get, since
|
// Check the RestyleBit() flag before doing the hashtable Get, since
|
||||||
// it's possible that the data in the hashtable isn't actually
|
// it's possible that the data in the hashtable isn't actually
|
||||||
@ -395,15 +402,20 @@ RestyleTracker::AddPendingRestyleToTable(Element* aElement,
|
|||||||
mPendingRestyles.Get(aElement, &existingData);
|
mPendingRestyles.Get(aElement, &existingData);
|
||||||
} else {
|
} else {
|
||||||
aElement->SetFlags(RestyleBit());
|
aElement->SetFlags(RestyleBit());
|
||||||
|
existingData = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingData) {
|
||||||
|
mPendingRestyles.Put(aElement,
|
||||||
|
new RestyleData(aRestyleHint, aMinChangeHint));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hadRestyleLaterSiblings =
|
bool hadRestyleLaterSiblings =
|
||||||
(existingData.mRestyleHint & eRestyle_LaterSiblings) != 0;
|
(existingData->mRestyleHint & eRestyle_LaterSiblings) != 0;
|
||||||
existingData.mRestyleHint =
|
existingData->mRestyleHint =
|
||||||
nsRestyleHint(existingData.mRestyleHint | aRestyleHint);
|
nsRestyleHint(existingData->mRestyleHint | aRestyleHint);
|
||||||
NS_UpdateHint(existingData.mChangeHint, aMinChangeHint);
|
NS_UpdateHint(existingData->mChangeHint, aMinChangeHint);
|
||||||
|
|
||||||
mPendingRestyles.Put(aElement, existingData);
|
|
||||||
|
|
||||||
return hadRestyleLaterSiblings;
|
return hadRestyleLaterSiblings;
|
||||||
}
|
}
|
||||||
@ -459,11 +471,10 @@ RestyleTracker::AddPendingRestyle(Element* aElement,
|
|||||||
// invariant that if two elements appear in the array and one
|
// invariant that if two elements appear in the array and one
|
||||||
// is an ancestor of the other, that the ancestor appears after
|
// is an ancestor of the other, that the ancestor appears after
|
||||||
// the descendant.
|
// the descendant.
|
||||||
RestyleData curData;
|
RestyleData* curData;
|
||||||
// XXX We should avoid copying RestyleData::mDescendants around.
|
|
||||||
mPendingRestyles.Get(cur, &curData);
|
mPendingRestyles.Get(cur, &curData);
|
||||||
curData.mDescendants.AppendElement(aElement);
|
NS_ASSERTION(curData, "expected to find a RestyleData for cur");
|
||||||
mPendingRestyles.Put(cur, curData);
|
curData->mDescendants.AppendElement(aElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user