From 8ff298d4463e3903a6b04ddf8d1af159c0812fef Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 17 Mar 2011 20:14:32 -0700 Subject: [PATCH] Make nsCachedStyleData store arrays of nsStyleStruct*, and use style struct IDs for faster access to those arrays. (Bug 639231, patch 3) r=bzbarsky --- layout/style/nsRuleNode.cpp | 12 ++- layout/style/nsRuleNode.h | 144 ++++++++++++++------------------ layout/style/nsStyleContext.cpp | 24 ++---- layout/style/nsStyleContext.h | 15 ++-- layout/style/nsStyleSet.cpp | 2 +- layout/style/nsStyleUtil.cpp | 24 ------ 6 files changed, 88 insertions(+), 133 deletions(-) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index f4fee7f9ab25..160e3e034766 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -2294,9 +2294,11 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext, return nsnull; \ } \ } \ - NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData->m##type_##Data, \ + NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData-> \ + mStyleStructs[eStyleStruct_##type_], \ "Going to leak style data"); \ - aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \ + aHighestNode->mStyleData.mInheritedData-> \ + mStyleStructs[eStyleStruct_##type_] = data_; \ /* Propagate the bit down. */ \ PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \ /* Tell the style context that it doesn't own the data */ \ @@ -2336,9 +2338,11 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext, return nsnull; \ } \ } \ - NS_ASSERTION(!aHighestNode->mStyleData.mResetData->m##type_##Data, \ + NS_ASSERTION(!aHighestNode->mStyleData.mResetData-> \ + mStyleStructs[eStyleStruct_##type_], \ "Going to leak style data"); \ - aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \ + aHighestNode->mStyleData.mResetData-> \ + mStyleStructs[eStyleStruct_##type_] = data_; \ /* Propagate the bit down. */ \ PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \ } \ diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index 887a1a77106d..181ee06ac2e3 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -61,17 +61,29 @@ struct nsCSSRect; class nsStyleCoord; +template +class FixedStyleStructArray +{ +private: + void* mArray[Count]; +public: + void*& operator[](nsStyleStructID aIndex) { + NS_ABORT_IF_FALSE(MinIndex <= aIndex && aIndex < (MinIndex + Count), + "out of range"); + return mArray[aIndex - MinIndex]; + } + + const void* operator[](nsStyleStructID aIndex) const { + NS_ABORT_IF_FALSE(MinIndex <= aIndex && aIndex < (MinIndex + Count), + "out of range"); + return mArray[aIndex - MinIndex]; + } +}; + struct nsInheritedStyleData { - -#define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \ - nsStyle##name * m##name##Data; -#define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) - -#include "nsStyleStructList.h" - -#undef STYLE_STRUCT_INHERITED -#undef STYLE_STRUCT_RESET + FixedStyleStructArray mStyleStructs; void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { return aContext->AllocateFromShell(sz); @@ -79,8 +91,9 @@ struct nsInheritedStyleData void DestroyStructs(PRUint32 aBits, nsPresContext* aContext) { #define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \ - if (m##name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \ - m##name##Data->Destroy(aContext); + void *name##Data = mStyleStructs[eStyleStruct_##name]; \ + if (name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \ + static_cast(name##Data)->Destroy(aContext); #define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) #include "nsStyleStructList.h" @@ -95,30 +108,26 @@ struct nsInheritedStyleData } nsInheritedStyleData() { -#define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \ - m##name##Data = nsnull; -#define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) - -#include "nsStyleStructList.h" - -#undef STYLE_STRUCT_INHERITED -#undef STYLE_STRUCT_RESET - + for (nsStyleStructID i = nsStyleStructID_Inherited_Start; + i < nsStyleStructID_Inherited_Start + nsStyleStructID_Inherited_Count; + i = nsStyleStructID(i + 1)) { + mStyleStructs[i] = nsnull; + } } }; struct nsResetStyleData { + FixedStyleStructArray mStyleStructs; + nsResetStyleData() { -#define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \ - m##name##Data = nsnull; -#define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) - -#include "nsStyleStructList.h" - -#undef STYLE_STRUCT_RESET -#undef STYLE_STRUCT_INHERITED + for (nsStyleStructID i = nsStyleStructID_Reset_Start; + i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count; + i = nsStyleStructID(i + 1)) { + mStyleStructs[i] = nsnull; + } } void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { @@ -127,8 +136,9 @@ struct nsResetStyleData void Destroy(PRUint32 aBits, nsPresContext* aContext) { #define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \ - if (m##name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \ - m##name##Data->Destroy(aContext); + void *name##Data = mStyleStructs[eStyleStruct_##name]; \ + if (name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \ + static_cast(name##Data)->Destroy(aContext); #define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) #include "nsStyleStructList.h" @@ -138,78 +148,46 @@ struct nsResetStyleData aContext->FreeToShell(sizeof(nsResetStyleData), this); } - -#define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \ - nsStyle##name * m##name##Data; -#define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) - -#include "nsStyleStructList.h" - -#undef STYLE_STRUCT_RESET -#undef STYLE_STRUCT_INHERITED - }; struct nsCachedStyleData { - struct StyleStructInfo { - ptrdiff_t mCachedStyleDataOffset; - ptrdiff_t mInheritResetOffset; - PRBool mIsReset; - }; - - static StyleStructInfo gInfo[]; - nsInheritedStyleData* mInheritedData; nsResetStyleData* mResetData; - static PRBool IsReset(const nsStyleStructID& aSID) { - return gInfo[aSID].mIsReset; + static PRBool IsReset(const nsStyleStructID aSID) { + NS_ABORT_IF_FALSE(0 <= aSID && aSID < nsStyleStructID_Length, + "must be an inherited or reset SID"); + return nsStyleStructID_Reset_Start <= aSID; } - static PRUint32 GetBitForSID(const nsStyleStructID& aSID) { + static PRUint32 GetBitForSID(const nsStyleStructID aSID) { return 1 << aSID; } - void* NS_FASTCALL GetStyleData(const nsStyleStructID& aSID) { - // Each struct is stored at this.m##type##Data->m##name##Data where - // |type| is either Inherit or Reset, and |name| is the name of the - // style struct. The |gInfo| stores the offset of the appropriate - // m##type##Data for the struct within nsCachedStyleData (|this|) - // and the offset of the appropriate m##name##Data within the - // m##type##Data. Note that if we don't have any reset structs, - // then mResetData is null, and likewise for mInheritedData. This - // saves us from having to go through the long if-else cascade into - // which most compilers will turn a case statement. - - // NOTE: nsStyleContext::SetStyle works roughly the same way. - - const StyleStructInfo& info = gInfo[aSID]; - - // Get either &mInheritedData or &mResetData. - char* resetOrInheritSlot = reinterpret_cast(this) + info.mCachedStyleDataOffset; - - // Get either mInheritedData or mResetData. - char* resetOrInherit = reinterpret_cast(*reinterpret_cast(resetOrInheritSlot)); - - void* data = nsnull; - if (resetOrInherit) { - // If we have the mInheritedData or mResetData, then we might have - // the struct, so get it. - char* dataSlot = resetOrInherit + info.mInheritResetOffset; - data = *reinterpret_cast(dataSlot); + void* NS_FASTCALL GetStyleData(const nsStyleStructID aSID) { + if (IsReset(aSID)) { + if (mResetData) { + return mResetData->mStyleStructs[aSID]; + } + } else { + if (mInheritedData) { + return mInheritedData->mStyleStructs[aSID]; + } } - return data; + return nsnull; } // Typesafe and faster versions of the above #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_, ctor_args_) \ - nsStyle##name_ * NS_FASTCALL GetStyle##name_ () { \ - return mInheritedData ? mInheritedData->m##name_##Data : nsnull; \ + nsStyle##name_ * NS_FASTCALL GetStyle##name_ () { \ + return mInheritedData ? static_cast( \ + mInheritedData->mStyleStructs[eStyleStruct_##name_]) : nsnull; \ } #define STYLE_STRUCT_RESET(name_, checkdata_cb_, ctor_args_) \ - nsStyle##name_ * NS_FASTCALL GetStyle##name_ () { \ - return mResetData ? mResetData->m##name_##Data : nsnull; \ + nsStyle##name_ * NS_FASTCALL GetStyle##name_ () { \ + return mResetData ? static_cast( \ + mResetData->mStyleStructs[eStyleStruct_##name_]) : nsnull; \ } #include "nsStyleStructList.h" #undef STYLE_STRUCT_RESET diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 47fd8fff50ff..f5415751790f 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -226,19 +226,14 @@ nsStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag, const void* nsStyleContext::GetCachedStyleData(nsStyleStructID aSID) { const void* cachedData; - PRBool isReset = nsCachedStyleData::IsReset(aSID); - if (isReset) { + if (nsCachedStyleData::IsReset(aSID)) { if (mCachedResetData) { - char* slot = reinterpret_cast(mCachedResetData) + - nsCachedStyleData::gInfo[aSID].mInheritResetOffset; - cachedData = *reinterpret_cast(slot); + cachedData = mCachedResetData->mStyleStructs[aSID]; } else { cachedData = nsnull; } } else { - char* slot = reinterpret_cast(&mCachedInheritedData) + - nsCachedStyleData::gInfo[aSID].mInheritResetOffset; - cachedData = *reinterpret_cast(slot); + cachedData = mCachedInheritedData.mStyleStructs[aSID]; } return cachedData; } @@ -314,22 +309,19 @@ nsStyleContext::SetStyle(nsStyleStructID aSID, void* aStruct) // See the comments there (in nsRuleNode.h) for more details about // what this is doing and why. - char* dataSlot; + void** dataSlot; if (nsCachedStyleData::IsReset(aSID)) { if (!mCachedResetData) { mCachedResetData = new (mRuleNode->GetPresContext()) nsResetStyleData; // XXXbz And if that fails? } - dataSlot = reinterpret_cast(mCachedResetData) + - nsCachedStyleData::gInfo[aSID].mInheritResetOffset; + dataSlot = &mCachedResetData->mStyleStructs[aSID]; } else { - dataSlot = reinterpret_cast(&mCachedInheritedData) + - nsCachedStyleData::gInfo[aSID].mInheritResetOffset; + dataSlot = &mCachedInheritedData.mStyleStructs[aSID]; } - NS_ASSERTION(!*reinterpret_cast(dataSlot) || - (mBits & nsCachedStyleData::GetBitForSID(aSID)), + NS_ASSERTION(!*dataSlot || (mBits & nsCachedStyleData::GetBitForSID(aSID)), "Going to leak style data"); - *reinterpret_cast(dataSlot) = aStruct; + *dataSlot = aStruct; } void diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index ea7a70345606..c81eb07066a3 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -208,11 +208,13 @@ public: // Setters for inherit structs only, since rulenode only sets those eagerly. #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_, ctor_args_) \ void SetStyle##name_ (nsStyle##name_ * aStruct) { \ - NS_ASSERTION(!mCachedInheritedData.m##name_##Data || \ + void *& slot = \ + mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]; \ + NS_ASSERTION(!slot || \ (mBits & \ nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)), \ "Going to leak styledata"); \ - mCachedInheritedData.m##name_##Data = aStruct; \ + slot = aStruct; \ } #define STYLE_STRUCT_RESET(name_, checkdata_cb_, ctor_args_) /* nothing */ #include "nsStyleStructList.h" @@ -350,7 +352,8 @@ protected: #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_, ctor_args_) \ const nsStyle##name_ * DoGetStyle##name_(PRBool aComputeData) { \ const nsStyle##name_ * cachedData = \ - mCachedInheritedData.m##name_##Data; \ + static_cast( \ + mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]); \ if (cachedData) /* Have it cached already, yay */ \ return cachedData; \ /* Have the rulenode deal */ \ @@ -358,8 +361,10 @@ protected: } #define STYLE_STRUCT_RESET(name_, checkdata_cb_, ctor_args_) \ const nsStyle##name_ * DoGetStyle##name_(PRBool aComputeData) { \ - const nsStyle##name_ * cachedData = \ - mCachedResetData ? mCachedResetData->m##name_##Data : nsnull; \ + const nsStyle##name_ * cachedData = mCachedResetData \ + ? static_cast( \ + mCachedResetData->mStyleStructs[eStyleStruct_##name_]) \ + : nsnull; \ if (cachedData) /* Have it cached already, yay */ \ return cachedData; \ /* Have the rulenode deal */ \ diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index ba2c5a8d90da..6e56bc96f8f5 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -740,7 +740,7 @@ PRBool nsStyleSet::BuildDefaultStyleData(nsPresContext* aPresContext) #define SSARG_PRESCONTEXT aPresContext #define CREATE_DATA(name, type, args) \ - if (!(mDefaultStyleData.m##type##Data->m##name##Data = \ + if (!(mDefaultStyleData.m##type##Data->mStyleStructs[eStyleStruct_##name] = \ new (aPresContext) nsStyle##name args)) \ return PR_FALSE; diff --git a/layout/style/nsStyleUtil.cpp b/layout/style/nsStyleUtil.cpp index ae499a6420bb..001d27aebac8 100644 --- a/layout/style/nsStyleUtil.cpp +++ b/layout/style/nsStyleUtil.cpp @@ -51,30 +51,6 @@ #include "nsTextFormatter.h" #include "nsCSSProps.h" -// XXX This is here because nsCachedStyleData is accessed outside of -// the content module; e.g., by nsCSSFrameConstructor. -#include "nsRuleNode.h" - -nsCachedStyleData::StyleStructInfo -nsCachedStyleData::gInfo[] = { - -#define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \ - { offsetof(nsCachedStyleData, mInheritedData), \ - offsetof(nsInheritedStyleData, m##name##Data), \ - PR_FALSE }, -#define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \ - { offsetof(nsCachedStyleData, mResetData), \ - offsetof(nsResetStyleData, m##name##Data), \ - PR_TRUE }, - -#include "nsStyleStructList.h" - -#undef STYLE_STRUCT_INHERITED -#undef STYLE_STRUCT_RESET - - { 0, 0, 0 } -}; - #define POSITIVE_SCALE_FACTOR 1.10 /* 10% */ #define NEGATIVE_SCALE_FACTOR .90 /* 10% */