Bug 1373018 - Part 9: stylo: Make more things on nsStyleContext inlined; r?bholley
MozReview-Commit-ID: FYiOtmSK2oC
--- a/layout/generic/WritingModes.h
+++ b/layout/generic/WritingModes.h
@@ -3,16 +3,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef WritingModes_h_
#define WritingModes_h_
#include "nsRect.h"
#include "nsStyleContext.h"
+#include "nsStyleContextInlines.h"
#include "nsBidiUtils.h"
// It is the caller's responsibility to operate on logical-coordinate objects
// with matched writing modes. Failure to do so will be a runtime bug; the
// compiler can't catch it, but in debug mode, we'll throw an assertion.
// NOTE that in non-debug builds, a writing mode mismatch error will NOT be
// detected, yet the results will be nonsense (and may lead to further layout
// failures). Therefore, it is important to test (and fuzz-test) writing-mode
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -36,16 +36,17 @@
#include "nsITheme.h"
#include "nsLayoutUtils.h"
#include "nsQueryFrame.h"
#include "nsStringGlue.h"
#include "nsStyleContext.h"
#include "nsStyleStruct.h"
#include "Visibility.h"
#include "nsChangeHint.h"
+#include "nsStyleContextInlines.h"
#ifdef ACCESSIBILITY
#include "mozilla/a11y/AccTypes.h"
#endif
/**
* New rules of reflow:
* 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -689,34 +689,16 @@ void nsStyleContext::List(FILE* out, int
#endif
NonOwningStyleContextSource
nsStyleContext::StyleSource() const
{
MOZ_STYLO_FORWARD(StyleSource, ())
}
-#define STYLE_STRUCT(name_, checkdata_cb_) \
-const nsStyle##name_ * \
-nsStyleContext::Style##name_() { \
- return DoGetStyle##name_<true>(); \
-} \
-const nsStyle##name_ * \
-nsStyleContext::ThreadsafeStyle##name_() { \
- if (mozilla::ServoStyleSet::IsInServoTraversal()) { \
- return Servo_GetStyle##name_(AsServo()->ComputedValues()); \
- } \
- return Style##name_(); \
-} \
-const nsStyle##name_ * nsStyleContext::PeekStyle##name_() { \
- return DoGetStyle##name_<false>(); \
-}
-#include "nsStyleStructList.h"
-#undef STYLE_STRUCT
-
// Overridden to prevent the global delete from being called, since the memory
// came out of an nsIArena instead of the global delete operator's heap.
void
nsStyleContext::Destroy()
{
if (IsGecko()) {
// Get the pres context.
RefPtr<nsPresContext> presContext = PresContext();
@@ -1010,26 +992,8 @@ nsStyleContext::LogStyleContextTree(bool
/* static */ void
nsStyleContext::Initialize()
{
Preferences::AddBoolVarCache(
&sExpensiveStyleStructAssertionsEnabled,
"layout.css.expensive-style-struct-assertions.enabled");
}
#endif
-
-nsPresContext*
-nsStyleContext::PresContext() const
-{
- MOZ_STYLO_FORWARD(PresContext, ())
-}
-
-GeckoStyleContext*
-nsStyleContext::GetParent() const
-{
- MOZ_ASSERT(IsGecko(),
- "This should be used only in Gecko-backed style system!");
- if (mParent) {
- return mParent->AsGecko();
- } else {
- return nullptr;
- }
-}
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -123,19 +123,19 @@ public:
bool HasSingleReference() const {
NS_ASSERTION(mRefCnt != 0,
"do not call HasSingleReference on a newly created "
"nsStyleContext with no references yet");
return mRefCnt == 1;
}
- nsPresContext* PresContext() const;
+ inline nsPresContext* PresContext() const;
- mozilla::GeckoStyleContext* GetParent() const;
+ inline mozilla::GeckoStyleContext* GetParent() const;
nsStyleContext* GetParentAllowServo() const {
return mParent;
}
nsIAtom* GetPseudo() const { return mPseudoTag; }
mozilla::CSSPseudoElementType GetPseudoType() const {
return static_cast<mozilla::CSSPseudoElementType>(
@@ -188,20 +188,17 @@ public:
// Is the only link whose visitedness is allowed to influence the
// style of the node this style context is for (which is that element
// or its nearest ancestor that is a link) visited?
bool RelevantLinkVisited() const
{ return !!(mBits & NS_STYLE_RELEVANT_LINK_VISITED); }
// Is this a style context for a link?
- bool IsLinkContext() const {
- return
- GetStyleIfVisited() && GetStyleIfVisited()->GetParent() == GetParent();
- }
+ inline bool IsLinkContext() const;
// Is this style context the GetStyleIfVisited() for some other style
// context?
bool IsStyleIfVisited() const
{ return !!(mBits & NS_STYLE_IS_STYLE_IF_VISITED); }
// Tells this style context that it should return true from
// IsStyleIfVisited.
@@ -279,42 +276,42 @@ public:
/**
* Define typesafe getter functions for each style struct by
* preprocessing the list of style structs. These functions are the
* preferred way to get style data. The macro creates functions like:
* const nsStyleBorder* StyleBorder();
* const nsStyleColor* StyleColor();
*/
#define STYLE_STRUCT(name_, checkdata_cb_) \
- const nsStyle##name_ * Style##name_() MOZ_NONNULL_RETURN;
+ inline const nsStyle##name_ * Style##name_() MOZ_NONNULL_RETURN;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/**
* Equivalent to StyleFoo(), except that we skip the cache write during the
* servo traversal. This can cause incorrect behavior if used improperly,
* since we won't record that layout potentially depends on the values in
* this style struct. Use with care.
*/
#define STYLE_STRUCT(name_, checkdata_cb_) \
- const nsStyle##name_ * ThreadsafeStyle##name_();
+ inline const nsStyle##name_ * ThreadsafeStyle##name_();
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/**
* PeekStyle* is like Style* but doesn't trigger style
* computation if the data is not cached on either the style context
* or the rule node.
*
* Perhaps this shouldn't be a public nsStyleContext API.
*/
#define STYLE_STRUCT(name_, checkdata_cb_) \
- const nsStyle##name_ * PeekStyle##name_();
+ inline const nsStyle##name_ * PeekStyle##name_();
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/**
* Compute the style changes needed during restyling when this style
* context is being replaced by aNewContext. (This is nonsymmetric since
* we optimize by skipping comparison for styles that have never been
* requested.)
@@ -371,20 +368,17 @@ public:
* be used based on aLinkIsVisited with the A component of aColors[0].
*/
static nscolor CombineVisitedColors(nscolor *aColors,
bool aLinkIsVisited);
/**
* Start the background image loads for this style context.
*/
- void StartBackgroundImageLoads() {
- // Just get our background struct; that should do the trick
- StyleBackground();
- }
+ inline void StartBackgroundImageLoads();
/**
* Moves this style context to a new parent.
*
* This function violates style context tree immutability, and
* is a very low-level function and should only be used after verifying
* many conditions that make it safe to call.
*/
@@ -508,115 +502,21 @@ protected:
AutoCheckDependency checkNesting_(this, sid_)
#else
#define AUTO_CHECK_DEPENDENCY(sid_)
#endif
// Helper functions for GetStyle* and PeekStyle*
#define STYLE_STRUCT_INHERITED(name_, checkdata_cb_) \
template<bool aComputeData> \
- const nsStyle##name_ * DoGetStyle##name_() { \
- if (IsGecko()) { \
- const nsStyle##name_ * cachedData = \
- static_cast<nsStyle##name_*>( \
- mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]); \
- if (cachedData) /* Have it cached already, yay */ \
- return cachedData; \
- if (!aComputeData) { \
- /* We always cache inherited structs on the context when we */\
- /* compute them. */ \
- return nullptr; \
- } \
- /* Have the rulenode deal */ \
- AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
- const nsStyle##name_ * newData = \
- StyleSource().AsGeckoRuleNode()-> \
- GetStyle##name_<aComputeData>(this->AsGecko(), mBits); \
- /* always cache inherited data on the style context; the rule */\
- /* node set the bit in mBits for us if needed. */ \
- mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] = \
- const_cast<nsStyle##name_ *>(newData); \
- return newData; \
- } \
- /** \
- * Also (conservatively) set the owning bit in the parent style \
- * context if we're a text node. \
- * \
- * This causes the parent element's style context to cache any \
- * inherited structs we request for a text node, which means we \
- * don't have to compute change hints for the text node, as \
- * handling the change on the parent element is sufficient. \
- * \
- * Note, however, that we still need to request the style struct \
- * of the text node itself, since we may run some fixups on it, \
- * like for text-combine. \
- * \
- * This model is sound because for the fixed-up values to change, \
- * other properties on the parent need to change too, and we'll \
- * handle those change hints correctly. \
- * \
- * TODO(emilio): Perhaps we should remove those fixups and handle \
- * those in layout instead. Those fixups are kind of expensive \
- * for style sharing, and computed style of text nodes is not \
- * observable. If we do that, we could assert here that the \
- * inherited structs of both are the same. \
- */ \
- if (mPseudoTag == nsCSSAnonBoxes::mozText && aComputeData) { \
- MOZ_ASSERT(mParent); \
- mParent->AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
- } \
- \
- const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
- if (!aComputeData && needToCompute) { \
- return nullptr; \
- } \
- \
- const nsStyle##name_* data = \
- Servo_GetStyle##name_(StyleSource().AsServoComputedValues()); \
- /* perform any remaining main thread work on the struct */ \
- if (needToCompute) { \
- MOZ_ASSERT(NS_IsMainThread()); \
- MOZ_ASSERT(!mozilla::ServoStyleSet::IsInServoTraversal()); \
- const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext()); \
- /* the Servo-backed StyleContextSource owns the struct */ \
- AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
- } \
- return data; \
- }
-
+ const nsStyle##name_ * DoGetStyle##name_();
#define STYLE_STRUCT_RESET(name_, checkdata_cb_) \
template<bool aComputeData> \
- const nsStyle##name_ * DoGetStyle##name_() { \
- if (IsGecko()) { \
- if (mCachedResetData) { \
- const nsStyle##name_ * cachedData = \
- static_cast<nsStyle##name_*>( \
- mCachedResetData->mStyleStructs[eStyleStruct_##name_]); \
- if (cachedData) /* Have it cached already, yay */ \
- return cachedData; \
- } \
- /* Have the rulenode deal */ \
- AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
- return StyleSource().AsGeckoRuleNode()-> \
- GetStyle##name_<aComputeData>(this->AsGecko()); \
- } \
- const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
- if (!aComputeData && needToCompute) { \
- return nullptr; \
- } \
- const nsStyle##name_* data = \
- Servo_GetStyle##name_(StyleSource().AsServoComputedValues()); \
- /* perform any remaining main thread work on the struct */ \
- if (needToCompute) { \
- const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext()); \
- /* the Servo-backed StyleContextSource owns the struct */ \
- AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
- } \
- return data; \
- }
+ const nsStyle##name_ * DoGetStyle##name_();
+
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_RESET
#undef STYLE_STRUCT_INHERITED
#ifdef DEBUG
void AssertStructsNotUsedElsewhere(nsStyleContext* aDestroyingContext,
int32_t aLevels) const;
#endif
--- a/layout/style/nsStyleContextInlines.h
+++ b/layout/style/nsStyleContextInlines.h
@@ -14,20 +14,176 @@
#ifndef nsStyleContextInlines_h
#define nsStyleContextInlines_h
#include "nsStyleContext.h"
#include "mozilla/ServoStyleContext.h"
#include "mozilla/GeckoStyleContext.h"
#include "mozilla/ServoUtils.h"
-using namespace mozilla;
-
-MOZ_DEFINE_STYLO_METHODS(nsStyleContext, GeckoStyleContext, ServoStyleContext);
+MOZ_DEFINE_STYLO_METHODS(nsStyleContext,
+ mozilla::GeckoStyleContext,
+ mozilla::ServoStyleContext);
nsRuleNode*
nsStyleContext::RuleNode()
{
MOZ_RELEASE_ASSERT(IsGecko());
return AsGecko()->RuleNode();
}
+#define STYLE_STRUCT(name_, checkdata_cb_) \
+const nsStyle##name_ * \
+nsStyleContext::Style##name_() { \
+ return DoGetStyle##name_<true>(); \
+} \
+const nsStyle##name_ * \
+nsStyleContext::ThreadsafeStyle##name_() { \
+ if (mozilla::ServoStyleSet::IsInServoTraversal()) { \
+ return Servo_GetStyle##name_(AsServo()->ComputedValues()); \
+ } \
+ return Style##name_(); \
+} \
+const nsStyle##name_ * nsStyleContext::PeekStyle##name_() { \
+ return DoGetStyle##name_<false>(); \
+}
+#include "nsStyleStructList.h"
+#undef STYLE_STRUCT
+
+// Helper functions for GetStyle* and PeekStyle*
+#define STYLE_STRUCT_INHERITED(name_, checkdata_cb_) \
+template<bool aComputeData> \
+const nsStyle##name_ * nsStyleContext::DoGetStyle##name_() { \
+ if (IsGecko()) { \
+ const nsStyle##name_ * cachedData = \
+ static_cast<nsStyle##name_*>( \
+ mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]); \
+ if (cachedData) /* Have it cached already, yay */ \
+ return cachedData; \
+ if (!aComputeData) { \
+ /* We always cache inherited structs on the context when we */\
+ /* compute them. */ \
+ return nullptr; \
+ } \
+ /* Have the rulenode deal */ \
+ AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
+ const nsStyle##name_ * newData = \
+ StyleSource().AsGeckoRuleNode()-> \
+ GetStyle##name_<aComputeData>(this->AsGecko(), mBits); \
+ /* always cache inherited data on the style context; the rule */\
+ /* node set the bit in mBits for us if needed. */ \
+ mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] = \
+ const_cast<nsStyle##name_ *>(newData); \
+ return newData; \
+ } \
+ /** \
+ * Also (conservatively) set the owning bit in the parent style \
+ * context if we're a text node. \
+ * \
+ * This causes the parent element's style context to cache any \
+ * inherited structs we request for a text node, which means we \
+ * don't have to compute change hints for the text node, as \
+ * handling the change on the parent element is sufficient. \
+ * \
+ * Note, however, that we still need to request the style struct \
+ * of the text node itself, since we may run some fixups on it, \
+ * like for text-combine. \
+ * \
+ * This model is sound because for the fixed-up values to change, \
+ * other properties on the parent need to change too, and we'll \
+ * handle those change hints correctly. \
+ * \
+ * TODO(emilio): Perhaps we should remove those fixups and handle \
+ * those in layout instead. Those fixups are kind of expensive \
+ * for style sharing, and computed style of text nodes is not \
+ * observable. If we do that, we could assert here that the \
+ * inherited structs of both are the same. \
+ */ \
+ if (mPseudoTag == nsCSSAnonBoxes::mozText && aComputeData) { \
+ MOZ_ASSERT(mParent); \
+ mParent->AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
+ } \
+ \
+ const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
+ if (!aComputeData && needToCompute) { \
+ return nullptr; \
+ } \
+ \
+ const nsStyle##name_* data = \
+ Servo_GetStyle##name_(StyleSource().AsServoComputedValues()); \
+ /* perform any remaining main thread work on the struct */ \
+ if (needToCompute) { \
+ MOZ_ASSERT(NS_IsMainThread()); \
+ MOZ_ASSERT(!mozilla::ServoStyleSet::IsInServoTraversal()); \
+ const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext()); \
+ /* the Servo-backed StyleContextSource owns the struct */ \
+ AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
+ } \
+ return data; \
+}
+
+#define STYLE_STRUCT_RESET(name_, checkdata_cb_) \
+template<bool aComputeData> \
+const nsStyle##name_ * nsStyleContext::DoGetStyle##name_() { \
+ if (IsGecko()) { \
+ if (mCachedResetData) { \
+ const nsStyle##name_ * cachedData = \
+ static_cast<nsStyle##name_*>( \
+ mCachedResetData->mStyleStructs[eStyleStruct_##name_]); \
+ if (cachedData) /* Have it cached already, yay */ \
+ return cachedData; \
+ } \
+ /* Have the rulenode deal */ \
+ AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
+ return StyleSource().AsGeckoRuleNode()-> \
+ GetStyle##name_<aComputeData>(this->AsGecko()); \
+ } \
+ const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
+ if (!aComputeData && needToCompute) { \
+ return nullptr; \
+ } \
+ const nsStyle##name_* data = \
+ Servo_GetStyle##name_(StyleSource().AsServoComputedValues()); \
+ /* perform any remaining main thread work on the struct */ \
+ if (needToCompute) { \
+ const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext()); \
+ /* the Servo-backed StyleContextSource owns the struct */ \
+ AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
+ } \
+ return data; \
+}
+#include "nsStyleStructList.h"
+#undef STYLE_STRUCT_RESET
+#undef STYLE_STRUCT_INHERITED
+
+
+nsPresContext*
+nsStyleContext::PresContext() const
+{
+ MOZ_STYLO_FORWARD(PresContext, ())
+}
+
+mozilla::GeckoStyleContext*
+nsStyleContext::GetParent() const
+{
+ MOZ_ASSERT(IsGecko(),
+ "This should be used only in Gecko-backed style system!");
+ if (mParent) {
+ return mParent->AsGecko();
+ } else {
+ return nullptr;
+ }
+}
+
+bool
+nsStyleContext::IsLinkContext() const
+{
+ return GetStyleIfVisited() && GetStyleIfVisited()->GetParent() == GetParent();
+}
+
+void
+nsStyleContext::StartBackgroundImageLoads()
+{
+ // Just get our background struct; that should do the trick
+ StyleBackground();
+}
+
#endif // nsStyleContextInlines_h