Make nsCachedStyleData store arrays of nsStyleStruct*, and use style struct IDs for faster access to those arrays. (Bug 639231, patch 3) r=bzbarsky

This commit is contained in:
L. David Baron 2011-03-17 20:14:32 -07:00
parent 52152cb738
commit 8ff298d446
6 changed files with 88 additions and 133 deletions

View File

@ -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); \
} \

View File

@ -61,17 +61,29 @@ struct nsCSSRect;
class nsStyleCoord;
template <nsStyleStructID MinIndex, nsStyleStructID Count>
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<nsStyleStructID_Inherited_Start,
nsStyleStructID_Inherited_Count> 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<nsStyle##name*>(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<nsStyleStructID_Reset_Start,
nsStyleStructID_Reset_Count> 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<nsStyle##name*>(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<char*>(this) + info.mCachedStyleDataOffset;
// Get either mInheritedData or mResetData.
char* resetOrInherit = reinterpret_cast<char*>(*reinterpret_cast<void**>(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<void**>(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<nsStyle##name_*>( \
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<nsStyle##name_*>( \
mResetData->mStyleStructs[eStyleStruct_##name_]) : nsnull; \
}
#include "nsStyleStructList.h"
#undef STYLE_STRUCT_RESET

View File

@ -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<char*>(mCachedResetData) +
nsCachedStyleData::gInfo[aSID].mInheritResetOffset;
cachedData = *reinterpret_cast<void**>(slot);
cachedData = mCachedResetData->mStyleStructs[aSID];
} else {
cachedData = nsnull;
}
} else {
char* slot = reinterpret_cast<char*>(&mCachedInheritedData) +
nsCachedStyleData::gInfo[aSID].mInheritResetOffset;
cachedData = *reinterpret_cast<void**>(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<char*>(mCachedResetData) +
nsCachedStyleData::gInfo[aSID].mInheritResetOffset;
dataSlot = &mCachedResetData->mStyleStructs[aSID];
} else {
dataSlot = reinterpret_cast<char*>(&mCachedInheritedData) +
nsCachedStyleData::gInfo[aSID].mInheritResetOffset;
dataSlot = &mCachedInheritedData.mStyleStructs[aSID];
}
NS_ASSERTION(!*reinterpret_cast<void**>(dataSlot) ||
(mBits & nsCachedStyleData::GetBitForSID(aSID)),
NS_ASSERTION(!*dataSlot || (mBits & nsCachedStyleData::GetBitForSID(aSID)),
"Going to leak style data");
*reinterpret_cast<void**>(dataSlot) = aStruct;
*dataSlot = aStruct;
}
void

View File

@ -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<nsStyle##name_*>( \
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<nsStyle##name_*>( \
mCachedResetData->mStyleStructs[eStyleStruct_##name_]) \
: nsnull; \
if (cachedData) /* Have it cached already, yay */ \
return cachedData; \
/* Have the rulenode deal */ \

View File

@ -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;

View File

@ -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% */