Bug 860573 - Part 2 - Use spare bits of wrapper cache flags for nsINode r=smaug

This commit is contained in:
Jon Coppeard 2013-06-08 09:54:59 +01:00
parent 72e8eed021
commit d99e2a4f5c
8 changed files with 35 additions and 41 deletions

View File

@ -104,6 +104,9 @@ enum {
#undef ELEMENT_FLAG_BIT
// Make sure we have space for our bits
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
namespace mozilla {
namespace dom {

View File

@ -71,7 +71,7 @@ class Value;
template<typename T> class Handle;
}
#define NODE_FLAG_BIT(n_) (1U << (n_))
#define NODE_FLAG_BIT(n_) (1U << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_)))
enum {
// This bit will be set if the node has a listener manager.
@ -155,29 +155,27 @@ enum {
// Set if the node has the accesskey attribute set.
NODE_HAS_ACCESSKEY = NODE_FLAG_BIT(17),
// Set if the node is handling a click.
NODE_HANDLING_CLICK = NODE_FLAG_BIT(18),
// Set if the node has had :hover selectors matched against it
NODE_HAS_RELEVANT_HOVER_RULES = NODE_FLAG_BIT(19),
// Set if the node has right-to-left directionality
NODE_HAS_DIRECTION_RTL = NODE_FLAG_BIT(20),
NODE_HAS_DIRECTION_RTL = NODE_FLAG_BIT(18),
// Set if the node has left-to-right directionality
NODE_HAS_DIRECTION_LTR = NODE_FLAG_BIT(21),
NODE_HAS_DIRECTION_LTR = NODE_FLAG_BIT(19),
NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR |
NODE_HAS_DIRECTION_RTL,
NODE_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(22),
NODE_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(20),
NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(23),
NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(21),
// Remaining bits are node type specific.
NODE_TYPE_SPECIFIC_BITS_OFFSET = 24
NODE_TYPE_SPECIFIC_BITS_OFFSET = 22
};
// Make sure we have space for our bits
#define ASSERT_NODE_FLAGS_SPACE(n) PR_STATIC_ASSERT(WRAPPER_CACHE_FLAGS_BITS_USED + (n) <= 32)
ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET);
/**
* Class used to detect unexpected mutations. To use the class create an
* nsMutationGuard on the stack before unexpected mutations could occur.
@ -319,7 +317,6 @@ public:
nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
: mNodeInfo(aNodeInfo),
mParent(nullptr),
mFlags(0),
mBoolFlags(0),
mNextSibling(nullptr),
mPreviousSibling(nullptr),
@ -931,16 +928,6 @@ public:
}
#endif
bool HasFlag(uintptr_t aFlag) const
{
return !!(GetFlags() & aFlag);
}
uint32_t GetFlags() const
{
return mFlags;
}
void SetFlags(uint32_t aFlagsToSet)
{
NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS |
@ -952,7 +939,7 @@ public:
NODE_CHROME_ONLY_ACCESS)) ||
IsNodeOfType(eCONTENT),
"Flag only permitted on nsIContent nodes");
mFlags |= aFlagsToSet;
nsWrapperCache::SetFlags(aFlagsToSet);
}
void UnsetFlags(uint32_t aFlagsToUnset)
@ -962,7 +949,7 @@ public:
NODE_IS_IN_ANONYMOUS_SUBTREE |
NODE_IS_NATIVE_ANONYMOUS_ROOT)),
"Trying to unset write-only flags");
mFlags &= ~aFlagsToUnset;
nsWrapperCache::UnsetFlags(aFlagsToUnset);
}
void SetEditableFlag(bool aEditable)
@ -1337,6 +1324,10 @@ private:
ElementIsInStyleScope,
// Set if the element is a scoped style sheet root
ElementIsScopedStyleRoot,
// Set if the node is handling a click.
NodeHandlingClick,
// Set if the node has had :hover selectors matched against it
NodeHasRelevantHoverRules,
// Guard value
BooleanFlagCount
};
@ -1471,6 +1462,8 @@ public:
void SetIsScopedStyleRoot() { SetBoolFlag(ElementIsScopedStyleRoot); }
void ClearIsScopedStyleRoot() { ClearBoolFlag(ElementIsScopedStyleRoot); }
bool IsScopedStyleRoot() { return GetBoolFlag(ElementIsScopedStyleRoot); }
bool HasRelevantHoverRules() const { return GetBoolFlag(NodeHasRelevantHoverRules); }
void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetInDocument() { SetBoolFlag(IsInDocument); }
@ -1490,6 +1483,9 @@ protected:
void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
bool HasLockedStyleStates() const
{ return GetBoolFlag(ElementHasLockedStyleStates); }
bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); }
void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); }
void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
{
@ -1738,8 +1734,6 @@ protected:
nsINode* mParent;
uint32_t mFlags;
private:
// Boolean flags.
uint32_t mBoolFlags;

View File

@ -45,7 +45,7 @@ enum {
};
// Make sure we have enough space for those bits
PR_STATIC_ASSERT(NODE_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 2);
#undef DATA_NODE_FLAG_BIT

View File

@ -31,8 +31,7 @@ enum {
HTML_ANCHOR_DNS_PREFETCH_DEFERRED = ANCHOR_ELEMENT_FLAG_BIT(1)
};
// Make sure we have enough space for those bits
PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
#undef ANCHOR_ELEMENT_FLAG_BIT

View File

@ -2808,7 +2808,7 @@ nsGenericHTMLElement::Focus(ErrorResult& aError)
void
nsGenericHTMLElement::Click()
{
if (HasFlag(NODE_HANDLING_CLICK))
if (HandlingClick())
return;
// Strong in case the event kills it
@ -2823,7 +2823,7 @@ nsGenericHTMLElement::Click()
}
}
SetFlags(NODE_HANDLING_CLICK);
SetHandlingClick();
// Click() is never called from native code, but it may be
// called from chrome JS. Mark this event trusted if Click()
@ -2834,7 +2834,7 @@ nsGenericHTMLElement::Click()
nsEventDispatcher::Dispatch(this, context, &event);
UnsetFlags(NODE_HANDLING_CLICK);
ClearHandlingClick();
}
bool

View File

@ -1063,8 +1063,7 @@ enum {
// same time, so if it becomes an issue we can probably merge them into the
// same bit. --bz
// Make sure we have enough space for those bits
PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
#undef FORM_ELEMENT_FLAG_BIT

View File

@ -344,8 +344,7 @@ enum {
XUL_ELEMENT_HAS_POPUP_LISTENER = XUL_ELEMENT_FLAG_BIT(2)
};
// Make sure we have space for our bits
PR_STATIC_ASSERT((ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2) < 32);
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
#undef XUL_ELEMENT_FLAG_BIT

View File

@ -2101,7 +2101,7 @@ static bool SelectorMatches(Element* aElement,
if (aTreeMatchContext.mForStyling &&
statesToCheck.HasAtLeastOneOfStates(NS_EVENT_STATE_HOVER)) {
// Mark the element as having :hover-dependent style
aElement->SetFlags(NODE_HAS_RELEVANT_HOVER_RULES);
aElement->SetHasRelevantHoverRules();
}
if (aNodeMatchContext.mStateMask.HasAtLeastOneOfStates(statesToCheck)) {
if (aDependence)
@ -2492,14 +2492,14 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData)
states.HasAtLeastOneOfStates(aData->mStateMask) &&
// We can optimize away testing selectors that only involve :hover, a
// namespace, and a tag name against nodes that don't have the
// NODE_HAS_RELEVANT_HOVER_RULES flag: such a selector didn't match
// NodeHasRelevantHoverRules flag: such a selector didn't match
// the tag name or namespace the first time around (since the :hover
// didn't set the NODE_HAS_RELEVANT_HOVER_RULES flag), so it won't
// didn't set the NodeHasRelevantHoverRules flag), so it won't
// match it now. Check for our selector only having :hover states, or
// the element having the hover rules flag, or the selector having
// some sort of non-namespace, non-tagname data in it.
(states != NS_EVENT_STATE_HOVER ||
aData->mElement->HasFlag(NODE_HAS_RELEVANT_HOVER_RULES) ||
aData->mElement->HasRelevantHoverRules() ||
selector->mIDList || selector->mClassList ||
// We generally expect an mPseudoClassList, since we have a :hover.
// The question is whether we have anything else in there.