Bug 1122781 part 4 - Add runtime dependency check of style structs. r=dbaron

This patch adds a mechanism to check struct computation against a known set of non-cyclic dependencies.

The checks are only done when we get a struct on a context during computation of a struct on the same context.
This commit is contained in:
Xidorn Quan 2015-02-07 13:25:21 +11:00
parent d48e44036b
commit a889d0f6ae
3 changed files with 38 additions and 0 deletions

View File

@ -75,6 +75,9 @@ nsStyleContext::nsStyleContext(nsStyleContext* aParent,
, mCachedResetData(nullptr)
, mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT)
, mRefCnt(0)
#ifdef DEBUG
, mComputingStruct(nsStyleStructID_None)
#endif
{
// This check has to be done "backward", because if it were written the
// more natural way it wouldn't fail even when it needed to.

View File

@ -9,6 +9,7 @@
#define _nsStyleContext_h_
#include "mozilla/RestyleLogging.h"
#include "mozilla/Assertions.h"
#include "nsRuleNode.h"
#include "nsCSSPseudoElements.h"
@ -430,6 +431,35 @@ private:
// returns the structs we cache ourselves; never consults the ruletree.
inline const void* GetCachedStyleData(nsStyleStructID aSID);
#ifdef DEBUG
struct AutoCheckDependency {
nsStyleContext* mStyleContext;
nsStyleStructID mOuterSID;
AutoCheckDependency(nsStyleContext* aContext, nsStyleStructID aInnerSID)
: mStyleContext(aContext)
{
mOuterSID = aContext->mComputingStruct;
MOZ_ASSERT(mOuterSID == nsStyleStructID_None ||
DependencyAllowed(mOuterSID, aInnerSID),
"Undeclared dependency, see generate-stylestructlist.py");
aContext->mComputingStruct = aInnerSID;
}
~AutoCheckDependency()
{
mStyleContext->mComputingStruct = mOuterSID;
}
};
#define AUTO_CHECK_DEPENDENCY(sid_) \
AutoCheckDependency checkNesting_(this, sid_)
#else
#define AUTO_CHECK_DEPENDENCY(sid_)
#endif
// Helper functions for GetStyle* and PeekStyle*
#define STYLE_STRUCT_INHERITED(name_, checkdata_cb_) \
const nsStyle##name_ * DoGetStyle##name_(bool aComputeData) { \
@ -439,6 +469,7 @@ private:
if (cachedData) /* Have it cached already, yay */ \
return cachedData; \
/* Have the rulenode deal */ \
AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
return mRuleNode->GetStyle##name_(this, aComputeData); \
}
#define STYLE_STRUCT_RESET(name_, checkdata_cb_) \
@ -450,6 +481,7 @@ private:
if (cachedData) /* Have it cached already, yay */ \
return cachedData; \
/* Have the rulenode deal */ \
AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
return mRuleNode->GetStyle##name_(this, aComputeData); \
}
#include "nsStyleStructList.h"
@ -519,6 +551,8 @@ private:
uint32_t mRefCnt;
#ifdef DEBUG
nsStyleStructID mComputingStruct;
static bool DependencyAllowed(nsStyleStructID aOuterSID,
nsStyleStructID aInnerSID)
{

View File

@ -23,6 +23,7 @@ enum nsStyleStructID {
* one type or the other.
*/
nsStyleStructID_None = -1,
nsStyleStructID_Inherited_Start = 0,
// a dummy value so the value after it is the same as ..._Inherited_Start
nsStyleStructID_DUMMY1 = nsStyleStructID_Inherited_Start - 1,