diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 89ac00bbff5..e2e39a262ca 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -166,7 +166,7 @@ public: mIsBeingUsedAsImage(PR_FALSE), mPartID(0) { - mParentPtrBits |= PARENT_BIT_INDOCUMENT; + SetInDocument(); } #endif diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 5b01b4791e9..60c673321cd 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -315,12 +315,12 @@ public: #ifdef MOZILLA_INTERNAL_API nsINode(already_AddRefed aNodeInfo) : mNodeInfo(aNodeInfo), - mParentPtrBits(0), + mParent(nsnull), mFlags(0), + mBoolFlags(0), mNextSibling(nsnull), mPreviousSibling(nsnull), mFirstChild(nsnull), - mNodeHasRenderingObservers(false), mSlots(nsnull) { } @@ -433,9 +433,9 @@ public: * * @return whether this content is in a document tree */ - PRBool IsInDoc() const + bool IsInDoc() const { - return mParentPtrBits & PARENT_BIT_INDOCUMENT; + return GetBoolFlag(IsInDocument); } /** @@ -704,13 +704,11 @@ public: /** * Get the parent nsIContent for this node. * @return the parent, or null if no parent or the parent is not an nsIContent + * Implemented in nsIContent.h */ - nsIContent* GetParent() const - { - return NS_LIKELY(mParentPtrBits & PARENT_BIT_PARENT_IS_CONTENT) ? - reinterpret_cast - (mParentPtrBits & ~kParentBitMask) : - nsnull; + nsIContent* GetParent() const { + return NS_LIKELY(GetBoolFlag(ParentIsContent)) ? + reinterpret_cast(mParent) : nsnull; } /** @@ -720,7 +718,7 @@ public: */ nsINode* GetNodeParent() const { - return reinterpret_cast(mParentPtrBits & ~kParentBitMask); + return mParent; } /** @@ -1136,9 +1134,53 @@ public: NS_NOTREACHED("How did we get here?"); } - bool HasRenderingObservers() { return mNodeHasRenderingObservers; } + /** + * Boolean flags + */ +private: + enum BooleanFlag { + // Set if we're being used from -moz-element + NodeHasRenderingObservers, + // Set if our parent chain (including this node itself) terminates + // in a document + IsInDocument, + // Set if mParent is an nsIContent + ParentIsContent, + BooleanFlagCount + }; + + void SetBoolFlag(BooleanFlag name, bool value) { + PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags)); + mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name); + } + + void SetBoolFlag(BooleanFlag name) { + PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags)); + mBoolFlags |= (1 << name); + } + + void ClearBoolFlag(BooleanFlag name) { + PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags)); + mBoolFlags &= ~(1 << name); + } + + bool GetBoolFlag(BooleanFlag name) const { + PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags)); + return mBoolFlags & (1 << name); + } + +public: + bool HasRenderingObservers() const + { return GetBoolFlag(NodeHasRenderingObservers); } void SetHasRenderingObservers(bool aValue) - { mNodeHasRenderingObservers = aValue; } + { SetBoolFlag(NodeHasRenderingObservers, aValue); } + +protected: + void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); } + void SetInDocument() { SetBoolFlag(IsInDocument); } + void ClearInDocument() { ClearBoolFlag(IsInDocument); } + +public: // Optimized way to get classinfo. virtual nsXPCClassInfo* GetClassInfo() = 0; @@ -1244,20 +1286,19 @@ protected: nsCOMPtr mNodeInfo; - enum { PARENT_BIT_INDOCUMENT = 1 << 0, PARENT_BIT_PARENT_IS_CONTENT = 1 << 1 }; - enum { kParentBitMask = 0x3 }; - - PtrBits mParentPtrBits; + nsINode* mParent; PRUint32 mFlags; +private: + // Boolean flags. + PRUint32 mBoolFlags; + +protected: nsIContent* mNextSibling; nsIContent* mPreviousSibling; nsIContent* mFirstChild; - // More flags - bool mNodeHasRenderingObservers : 1; - // Storage for more members that are usually not needed; allocated lazily. nsSlots* mSlots; }; diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 98452cc4d11..7fdcf6b5c58 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -523,19 +523,19 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // Set parent if (aParent) { - mParentPtrBits = - reinterpret_cast(aParent) | PARENT_BIT_PARENT_IS_CONTENT; + mParent = aParent; } else { - mParentPtrBits = reinterpret_cast(aDocument); + mParent = aDocument; } + SetParentIsContent(aParent); // XXXbz sXBL/XBL2 issue! // Set document if (aDocument) { // XXX See the comment in nsGenericElement::BindToTree - mParentPtrBits |= PARENT_BIT_INDOCUMENT; + SetInDocument(); if (mText.IsBidi()) { aDocument->SetBidiEnabled(); } @@ -570,7 +570,11 @@ nsGenericDOMDataNode::UnbindFromTree(PRBool aDeep, PRBool aNullParent) document->BindingManager()->RemovedFromDocument(this, document); } - mParentPtrBits = aNullParent ? 0 : mParentPtrBits & ~PARENT_BIT_INDOCUMENT; + if (aNullParent) { + mParent = nsnull; + SetParentIsContent(false); + } + ClearInDocument(); nsDataSlots *slots = GetExistingDataSlots(); if (slots) { diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 3d910679101..c6e0ea8e8f7 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2943,15 +2943,16 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // Now set the parent and set the "Force attach xbl" flag if needed. if (aParent) { - mParentPtrBits = reinterpret_cast(aParent) | PARENT_BIT_PARENT_IS_CONTENT; + mParent = aParent; if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) { SetFlags(NODE_FORCE_XBL_BINDINGS); } } else { - mParentPtrBits = reinterpret_cast(aDocument); + mParent = aDocument; } + SetParentIsContent(aParent); // XXXbz sXBL/XBL2 issue! @@ -2967,7 +2968,7 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // aDocument); // Being added to a document. - mParentPtrBits |= PARENT_BIT_INDOCUMENT; + SetInDocument(); // Unset this flag since we now really are in a document. UnsetFlags(NODE_FORCE_XBL_BINDINGS | @@ -3049,7 +3050,11 @@ nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent) nsIDocument *document = HasFlag(NODE_FORCE_XBL_BINDINGS) ? GetOwnerDoc() : GetCurrentDoc(); - mParentPtrBits = aNullParent ? 0 : mParentPtrBits & ~PARENT_BIT_INDOCUMENT; + if (aNullParent) { + mParent = nsnull; + SetParentIsContent(false); + } + ClearInDocument(); if (document) { // Notify XBL- & nsIAnonymousContentCreator-generated diff --git a/content/base/src/nsTextNode.cpp b/content/base/src/nsTextNode.cpp index d915743cf10..c3dc9be6da1 100644 --- a/content/base/src/nsTextNode.cpp +++ b/content/base/src/nsTextNode.cpp @@ -215,7 +215,9 @@ nsTextNode::BindToAttribute(nsIAttribute* aAttr) NS_ASSERTION(!GetNodeParent(), "Unbind before binding!"); NS_ASSERTION(HasSameOwnerDoc(aAttr), "Wrong owner document!"); - mParentPtrBits = reinterpret_cast(aAttr); + mParent = aAttr; + SetParentIsContent(false); + ClearInDocument(); return NS_OK; } @@ -226,7 +228,7 @@ nsTextNode::UnbindFromAttribute() NS_ASSERTION(GetNodeParent() && GetNodeParent()->IsNodeOfType(nsINode::eATTRIBUTE), "Use this method only to unbind from an attribute!"); - mParentPtrBits = 0; + mParent = nsnull; return NS_OK; }