Bug 1380133 - Part 7: Use old ServoComputedValues in Gecko_CalcStyleDifference.
MozReview-Commit-ID: DwxEAAOxQcr
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -357,28 +357,31 @@ Gecko_GetStyleContext(RawGeckoElementBor
CSSPseudoElementType
Gecko_GetImplementedPseudo(RawGeckoElementBorrowed aElement)
{
return aElement->GetPseudoElementType();
}
nsChangeHint
-Gecko_CalcStyleDifference(nsStyleContext* aOldStyleContext,
- RawServoComputedValuesBorrowed aComputedValues,
+Gecko_CalcStyleDifference(nsStyleContext* aOldSource,
+ RawServoComputedValuesBorrowed aOldValues,
+ RawServoComputedValuesBorrowed aNewValues,
bool* aAnyStyleChanged)
{
- MOZ_ASSERT(aOldStyleContext);
- MOZ_ASSERT(aComputedValues);
+ MOZ_ASSERT(aOldValues);
+ MOZ_ASSERT(aNewValues);
uint32_t equalStructs, samePointerStructs;
nsChangeHint result =
- aOldStyleContext->CalcStyleDifference(aComputedValues,
- &equalStructs,
- &samePointerStructs);
+ nsStyleContext::CalcStyleDifference(aOldSource,
+ aOldValues,
+ aNewValues,
+ &equalStructs,
+ &samePointerStructs);
*aAnyStyleChanged = equalStructs != NS_STYLE_INHERIT_MASK;
return result;
}
nsChangeHint
Gecko_HintsHandledForDescendants(nsChangeHint aHint)
{
return aHint & ~NS_HintsNotHandledForDescendantsIn(aHint);
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -353,17 +353,18 @@ void Gecko_UnsetNodeFlags(RawGeckoNodeBo
void Gecko_SetOwnerDocumentNeedsStyleFlush(RawGeckoElementBorrowed element);
// Incremental restyle.
// Also, we might want a ComputedValues to ComputedValues API for animations?
// Not if we do them in Gecko...
nsStyleContext* Gecko_GetStyleContext(RawGeckoElementBorrowed element,
nsIAtom* aPseudoTagOrNull);
mozilla::CSSPseudoElementType Gecko_GetImplementedPseudo(RawGeckoElementBorrowed element);
-nsChangeHint Gecko_CalcStyleDifference(nsStyleContext* oldstyle,
+nsChangeHint Gecko_CalcStyleDifference(nsStyleContext* old_source,
+ RawServoComputedValuesBorrowed old_style,
RawServoComputedValuesBorrowed new_style,
bool* any_style_changed);
nsChangeHint Gecko_HintsHandledForDescendants(nsChangeHint aHint);
// Get an element snapshot for a given element from the table.
const ServoElementSnapshot*
Gecko_GetElementSnapshot(const mozilla::ServoElementSnapshotTable* table,
RawGeckoElementBorrowed element);
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -229,28 +229,28 @@ nsStyleContext::MoveTo(nsStyleContext* a
if (mStyleIfVisited) {
mStyleIfVisited->mParent->RemoveChild(mStyleIfVisited);
mStyleIfVisited->mParent = aNewParent;
mStyleIfVisited->mParent->AddChild(mStyleIfVisited);
}
}
-template<class StyleContextLike>
bool
-nsStyleContext::EqualCustomProperties(StyleContextLike* aOther)
+nsStyleContext::EqualCustomProperties(nsStyleContext* aOther)
{
const nsStyleVariables* thisVariables = PeekStyleVariables();
return !thisVariables ||
thisVariables->mVariables == aOther->StyleVariables()->mVariables;
}
template<class StyleContextLike>
-nsChangeHint
-nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
+/* static */ nsChangeHint
+nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aOldContext,
+ StyleContextLike* aNewContext,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs)
{
AUTO_PROFILER_LABEL("nsStyleContext::CalcStyleDifferenceInternal", CSS);
static_assert(nsStyleStructID_Length <= 32,
"aEqualStructs is not big enough");
@@ -267,44 +267,44 @@ nsStyleContext::CalcStyleDifferenceInter
// we could later get a small change in one of those structs that we
// don't want to miss.
DebugOnly<uint32_t> structsFound = 0;
// FIXME(heycam): We should just do the comparison in
// nsStyleVariables::CalcDifference, returning NeutralChange if there are
// any Variables differences.
- if (EqualCustomProperties(aNewContext)) {
+ if (aOldContext->EqualCustomProperties(aNewContext)) {
*aEqualStructs |= NS_STYLE_INHERIT_BIT(Variables);
}
- if (PeekStyleVariables()) {
+ if (aOldContext->PeekStyleVariables()) {
structsFound |= NS_STYLE_INHERIT_BIT(Variables);
}
DebugOnly<int> styleStructCount = 1; // count Variables already
// Servo's optimization to stop the cascade when there are no style changes
// that children need to be recascade for relies on comparing all of the
// structs, not just those that are returned from PeekStyleData, although
// if PeekStyleData does return null we still don't want to accumulate
// any change hints for those structs.
- bool checkUnrequestedServoStructs = IsServo();
+ bool checkUnrequestedServoStructs = aOldContext->IsServo();
#define EXPAND(...) __VA_ARGS__
#define DO_STRUCT_DIFFERENCE_WITH_ARGS(struct_, extra_args_) \
PR_BEGIN_MACRO \
- const nsStyle##struct_* this##struct_ = PeekStyle##struct_(); \
+ const nsStyle##struct_* this##struct_ = aOldContext->PeekStyle##struct_();\
bool unrequestedStruct; \
if (this##struct_) { \
unrequestedStruct = false; \
structsFound |= NS_STYLE_INHERIT_BIT(struct_); \
} else if (checkUnrequestedServoStructs) { \
this##struct_ = \
- Servo_GetStyle##struct_(AsServo()->ComputedValues()); \
+ aOldContext->PeekStyle##struct_##FromComputedValues(); \
unrequestedStruct = true; \
} else { \
unrequestedStruct = false; \
} \
if (this##struct_) { \
const nsStyle##struct_* other##struct_ = aNewContext->Style##struct_(); \
if (this##struct_ == other##struct_) { \
/* The very same struct, so we know that there will be no */ \
@@ -337,20 +337,20 @@ nsStyleContext::CalcStyleDifferenceInter
DO_STRUCT_DIFFERENCE(Content);
DO_STRUCT_DIFFERENCE(UserInterface);
DO_STRUCT_DIFFERENCE(Visibility);
DO_STRUCT_DIFFERENCE(Outline);
DO_STRUCT_DIFFERENCE(TableBorder);
DO_STRUCT_DIFFERENCE(Table);
DO_STRUCT_DIFFERENCE(UIReset);
DO_STRUCT_DIFFERENCE(Text);
- DO_STRUCT_DIFFERENCE_WITH_ARGS(List, (, PeekStyleDisplay()));
+ DO_STRUCT_DIFFERENCE_WITH_ARGS(List, (, aOldContext->PeekStyleDisplay()));
DO_STRUCT_DIFFERENCE(SVGReset);
DO_STRUCT_DIFFERENCE(SVG);
- DO_STRUCT_DIFFERENCE_WITH_ARGS(Position, (, PeekStyleVisibility()));
+ DO_STRUCT_DIFFERENCE_WITH_ARGS(Position, (, aOldContext->PeekStyleVisibility()));
DO_STRUCT_DIFFERENCE(Font);
DO_STRUCT_DIFFERENCE(Margin);
DO_STRUCT_DIFFERENCE(Padding);
DO_STRUCT_DIFFERENCE(Border);
DO_STRUCT_DIFFERENCE(TextReset);
DO_STRUCT_DIFFERENCE(Effects);
DO_STRUCT_DIFFERENCE(Background);
DO_STRUCT_DIFFERENCE(Color);
@@ -360,17 +360,17 @@ nsStyleContext::CalcStyleDifferenceInter
#undef EXPAND
MOZ_ASSERT(styleStructCount == nsStyleStructID_Length,
"missing a call to DO_STRUCT_DIFFERENCE");
#ifdef DEBUG
#define STYLE_STRUCT(name_, callback_) \
MOZ_ASSERT(!!(structsFound & NS_STYLE_INHERIT_BIT(name_)) == \
- !!PeekStyle##name_(), \
+ !!aOldContext->PeekStyle##name_(), \
"PeekStyleData results must not change in the middle of " \
"difference calculation.");
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#endif
// We check for struct pointer equality here rather than as part of the
// DO_STRUCT_DIFFERENCE calls, since those calls can result in structs
@@ -379,17 +379,17 @@ nsStyleContext::CalcStyleDifferenceInter
// happen when the nsRuleNode::ComputeXXXData method looks up another
// struct.) This is important for callers in RestyleManager that
// need to know the equality or not of the final set of cached struct
// pointers.
*aSamePointerStructs = 0;
#define STYLE_STRUCT(name_, callback_) \
{ \
- const nsStyle##name_* data = PeekStyle##name_(); \
+ const nsStyle##name_* data = aOldContext->PeekStyle##name_(); \
if (!data || data == aNewContext->Style##name_()) { \
*aSamePointerStructs |= NS_STYLE_INHERIT_BIT(name_); \
} \
}
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
// Note that we do not check whether this->RelevantLinkVisited() !=
@@ -403,42 +403,34 @@ nsStyleContext::CalcStyleDifferenceInter
// the page to measure.
// However, we do need to compute the larger of the changes that can
// happen depending on whether the link is visited or unvisited, since
// doing only the one that's currently appropriate would expose which
// links are in history to easy performance measurement. Therefore,
// here, we add nsChangeHint_RepaintFrame hints (the maximum for
// things that can depend on :visited) for the properties on which we
// call GetVisitedDependentColor.
- auto* thisVis = GetStyleIfVisited();
- auto* otherVis = aNewContext->GetStyleIfVisited();
+ StyleContextLike* thisVis = aOldContext->GetStyleIfVisited();
+ StyleContextLike* otherVis = aNewContext->GetStyleIfVisited();
if (!thisVis != !otherVis) {
// One style context has a style-if-visited and the other doesn't.
// Presume a difference.
hint |= nsChangeHint_RepaintFrame;
} else if (thisVis && !NS_IsHintSubset(nsChangeHint_RepaintFrame, hint)) {
- // Bug 1364484: Update comments here and potentially remove the assertion
- // below once we return a non-null visited context in CalcStyleDifference
- // using Servo values. The approach is becoming quite similar to Gecko.
- // We'll handle visited style differently in servo. Assert against being
- // in the parallel traversal to avoid static analysis hazards when calling
- // StyleFoo() below.
- MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
-
// Both style contexts have a style-if-visited.
bool change = false;
- // NB: Calling Peek on |this|, not |thisVis|, since callers may look
- // at a struct on |this| without looking at the same struct on
+ // NB: Calling Peek on |aOldContext|, not |thisVis|, since callers may
+ // look at a struct on |this| without looking at the same struct on
// |thisVis| (including this function if we skip one of these checks
// due to change being true already or due to the old style context
// not having a style-if-visited), but not the other way around.
#define STYLE_FIELD(name_) thisVisStruct->name_ != otherVisStruct->name_
#define STYLE_STRUCT(name_, fields_) \
- if (!change && PeekStyle##name_()) { \
+ if (!change && aOldContext->PeekStyle##name_()) { \
const nsStyle##name_* thisVisStruct = thisVis->Style##name_(); \
const nsStyle##name_* otherVisStruct = otherVis->Style##name_(); \
if (MOZ_FOR_EACH_SEPARATED(STYLE_FIELD, (||), (), fields_)) { \
change = true; \
} \
}
#include "nsCSSVisitedDependentPropList.h"
#undef STYLE_STRUCT
@@ -458,20 +450,22 @@ nsStyleContext::CalcStyleDifferenceInter
// This depends on data in nsStyleDisplay, nsStyleEffects and
// nsStyleSVGReset, so we do it here.
// Note that it's perhaps good for this test to be last because it
// doesn't use Peek* functions to get the structs on the old
// context. But this isn't a big concern because these struct
// getters should be called during frame construction anyway.
- if (ThreadsafeStyleDisplay()->IsAbsPosContainingBlockForAppropriateFrame(this) ==
+ if (aOldContext->ThreadsafeStyleDisplay()->
+ IsAbsPosContainingBlockForAppropriateFrame(aOldContext) ==
aNewContext->ThreadsafeStyleDisplay()->
IsAbsPosContainingBlockForAppropriateFrame(aNewContext) &&
- ThreadsafeStyleDisplay()->IsFixedPosContainingBlockForAppropriateFrame(this) ==
+ aOldContext->ThreadsafeStyleDisplay()->
+ IsFixedPosContainingBlockForAppropriateFrame(aOldContext) ==
aNewContext->ThreadsafeStyleDisplay()->
IsFixedPosContainingBlockForAppropriateFrame(aNewContext)) {
// While some styles that cause the frame to be a containing block
// has changed, the overall result hasn't.
hint &= ~nsChangeHint_UpdateContainingBlock;
}
}
@@ -480,17 +474,17 @@ nsStyleContext::CalcStyleDifferenceInter
return hint & ~nsChangeHint_NeutralChange;
}
nsChangeHint
nsStyleContext::CalcStyleDifference(nsStyleContext* aNewContext,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs)
{
- return CalcStyleDifferenceInternal(aNewContext,
+ return CalcStyleDifferenceInternal(this, aNewContext,
aEqualStructs,
aSamePointerStructs);
}
class MOZ_STACK_CLASS FakeStyleContext
{
public:
FakeStyleContext(RawServoComputedValuesBorrowed aComputedValues,
@@ -523,29 +517,77 @@ public:
#undef STYLE_STRUCT
bool EqualCustomProperties(FakeStyleContext* aOther)
{
return Servo_RawComputedValues_EqualCustomProperties(
mComputedValues, aOther->mComputedValues);
}
+ bool IsServo() const { return true; }
+
private:
RawServoComputedValuesBorrowed MOZ_NON_OWNING_REF mComputedValues;
uint64_t mBits;
FakeStyleContext* MOZ_NON_OWNING_REF mVisitedStyle;
};
-nsChangeHint
-nsStyleContext::CalcStyleDifference(RawServoComputedValuesBorrowed aNewValues,
+/* static */ Maybe<FakeStyleContext>
+nsStyleContext::MakeFakeStyleContext(RawServoComputedValuesBorrowed aValues,
+ nsStyleContext* aSource,
+ FakeStyleContext* aVisitedStyle)
+{
+ if (!aValues) {
+ return Nothing();
+ }
+
+ uint64_t bits = aSource ? aSource->mBits : 0;
+ return Some(FakeStyleContext(aValues, bits, aVisitedStyle));
+}
+
+/* static */ Maybe<FakeStyleContext>
+nsStyleContext::MakeVisitedFakeStyleContext(
+ RawServoComputedValuesBorrowed aValues,
+ nsStyleContext* aSource)
+{
+ if (!aValues) {
+ return Nothing();
+ }
+
+ RawServoComputedValuesBorrowed visitedValues =
+ Servo_RawComputedValues_GetVisitedStyle(aValues);
+ if (!visitedValues) {
+ return Nothing();
+ }
+
+ return MakeFakeStyleContext(visitedValues, aSource, nullptr);
+}
+
+/* static */ nsChangeHint
+nsStyleContext::CalcStyleDifference(nsStyleContext* aSource,
+ RawServoComputedValuesBorrowed aOldValues,
+ RawServoComputedValuesBorrowed aNewValues,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs)
{
- FakeStyleContext newContext(aNewValues, 0, nullptr);
- return CalcStyleDifferenceInternal(&newContext,
+ nsStyleContext* visitedSource =
+ aSource ? aSource->GetStyleIfVisited() : nullptr;
+
+ Maybe<FakeStyleContext> oldVisitedContext =
+ MakeVisitedFakeStyleContext(aOldValues, visitedSource);
+ Maybe<FakeStyleContext> newVisitedContext =
+ MakeVisitedFakeStyleContext(aNewValues, nullptr);
+
+ FakeStyleContext oldContext(aOldValues, aSource ? aSource->mBits : 0,
+ oldVisitedContext.ptrOr(nullptr));
+ FakeStyleContext newContext(aNewValues, 0,
+ newVisitedContext.ptrOr(nullptr));
+
+ return CalcStyleDifferenceInternal(&oldContext,
+ &newContext,
aEqualStructs,
aSamePointerStructs);
}
namespace mozilla {
void
GeckoStyleContext::EnsureSameStructsCached(nsStyleContext* aOldContext)
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -4,23 +4,25 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* the interface (to internal code) for retrieving computed style data */
#ifndef _nsStyleContext_h_
#define _nsStyleContext_h_
#include "mozilla/Assertions.h"
+#include "mozilla/Maybe.h"
#include "mozilla/RestyleLogging.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/ServoUtils.h"
#include "mozilla/StyleComplexColor.h"
#include "nsCSSAnonBoxes.h"
#include "nsStyleSet.h"
+class FakeStyleContext;
class nsIAtom;
class nsPresContext;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
class GeckoStyleContext;
class ServoStyleContext;
} // namespace mozilla
@@ -338,28 +340,41 @@ public:
nsChangeHint CalcStyleDifference(nsStyleContext* aNewContext,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs);
/**
* Like the above, but allows comparing ServoComputedValues instead of needing
* a full-fledged style context.
*/
- nsChangeHint CalcStyleDifference(RawServoComputedValuesBorrowed aNewValues,
- uint32_t* aEqualStructs,
- uint32_t* aSamePointerStructs);
+ static nsChangeHint CalcStyleDifference(
+ nsStyleContext* aOldSource,
+ RawServoComputedValuesBorrowed aOldValues,
+ RawServoComputedValuesBorrowed aNewValues,
+ uint32_t* aEqualStructs,
+ uint32_t* aSamePointerStructs);
private:
template<class StyleContextLike>
- nsChangeHint CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
+ static
+ nsChangeHint CalcStyleDifferenceInternal(StyleContextLike* aOldContext,
+ StyleContextLike* aNewContext,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs);
- template<typename StyleContextLike>
- bool EqualCustomProperties(StyleContextLike* aOther);
+ bool EqualCustomProperties(nsStyleContext* aOther);
+
+ static mozilla::Maybe<FakeStyleContext> MakeFakeStyleContext(
+ RawServoComputedValuesBorrowed aValues,
+ nsStyleContext* aSource,
+ FakeStyleContext* aVisitedStyle);
+
+ static mozilla::Maybe<FakeStyleContext> MakeVisitedFakeStyleContext(
+ RawServoComputedValuesBorrowed aValues,
+ nsStyleContext* aSource);
public:
/**
* Get a color that depends on link-visitedness using this and
* this->GetStyleIfVisited().
*
* @param aField A pointer to a member variable in a style struct.
* The member variable and its style struct must have