diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 7c5fa009d29..83a042e9ef5 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -59,6 +59,7 @@ class nsIMutationObserver; class nsChildContentList; class nsNodeWeakReference; class nsNodeSupportsWeakRefTearoff; +class nsDOMNodeAllocator; enum { // This bit will be set if the node doesn't have nsSlots @@ -126,8 +127,8 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument) // IID for the nsINode interface #define NS_INODE_IID \ -{ 0x8cef8b4e, 0x4b7f, 0x4f86, \ - { 0xba, 0x64, 0x75, 0xdf, 0xed, 0x0d, 0xa2, 0x3e } } +{ 0x42f3a894, 0xe5d4, 0x44b1, \ + { 0x96, 0x34, 0x73, 0x8f, 0xf8, 0xbe, 0x5d, 0x9b } } // hack to make egcs / gcc 2.95.2 happy class nsINode_base : public nsPIDOMEventTarget { @@ -578,6 +579,11 @@ public: * Weak reference to this node */ nsNodeWeakReference* mWeakReference; + + void* operator new(size_t aSize, nsDOMNodeAllocator* aAllocator); + void operator delete(void* aPtr, size_t aSize); +private: + void* operator new(size_t aSize) CPP_THROW_NEW; }; /** @@ -636,6 +642,13 @@ public: #endif } + // Returns nsnull only when called on an nsIDocument object. + virtual nsDOMNodeAllocator* GetAllocator() = 0; + + void* operator new(size_t aSize, nsINodeInfo* aNodeInfo); + void operator delete(void* aPtr, size_t aSize); +private: + void* operator new(size_t aSize) CPP_THROW_NEW; protected: // Override this function to create a custom slots class. diff --git a/content/base/src/nsAttrAndChildArray.cpp b/content/base/src/nsAttrAndChildArray.cpp index 58e0c5211ab..eec36581a61 100644 --- a/content/base/src/nsAttrAndChildArray.cpp +++ b/content/base/src/nsAttrAndChildArray.cpp @@ -119,20 +119,28 @@ GetIndexFromCache(const nsAttrAndChildArray* aArray) #define NS_IMPL_EXTRA_SIZE \ ((sizeof(Impl) - sizeof(mImpl->mBuffer)) / sizeof(void*)) -nsAttrAndChildArray::nsAttrAndChildArray() - : mImpl(nsnull) +nsAttrAndChildArray::nsAttrAndChildArray(nsDOMNodeAllocator* aAllocator) + : mImpl(nsnull), mAllocator(aAllocator) { + NS_IF_ADDREF(mAllocator); } nsAttrAndChildArray::~nsAttrAndChildArray() { - if (!mImpl) { - return; + if (mImpl) { + Clear(); + mAllocator->Free((mImpl->mBufferSize + NS_IMPL_EXTRA_SIZE) * sizeof(void*), + mImpl); } - Clear(); + NS_IF_RELEASE(mAllocator); +} - PR_Free(mImpl); +void +nsAttrAndChildArray::SetAllocator(nsDOMNodeAllocator* aAllocator) +{ + NS_ASSERTION(!mAllocator, "Allocator already set!"); + NS_ADDREF(mAllocator = aAllocator); } nsIContent* @@ -593,39 +601,6 @@ nsAttrAndChildArray::WalkMappedAttributeStyleRules(nsRuleWalker* aRuleWalker) } } -void -nsAttrAndChildArray::Compact() -{ - if (!mImpl) { - return; - } - - // First compress away empty attrslots - PRUint32 slotCount = AttrSlotCount(); - PRUint32 attrCount = NonMappedAttrCount(); - PRUint32 childCount = ChildCount(); - - if (attrCount < slotCount) { - memmove(mImpl->mBuffer + attrCount * ATTRSIZE, - mImpl->mBuffer + slotCount * ATTRSIZE, - childCount * sizeof(nsIContent*)); - SetAttrSlotCount(attrCount); - } - - // Then resize or free buffer - PRUint32 newSize = attrCount * ATTRSIZE + childCount; - if (!newSize && !mImpl->mMappedAttrs) { - PR_Free(mImpl); - mImpl = nsnull; - } - else if (newSize < mImpl->mBufferSize) { - mImpl = static_cast(PR_Realloc(mImpl, (newSize + NS_IMPL_EXTRA_SIZE) * sizeof(nsIContent*))); - NS_ASSERTION(mImpl, "failed to reallocate to smaller buffer"); - - mImpl->mBufferSize = newSize; - } -} - void nsAttrAndChildArray::Clear() { @@ -755,16 +730,17 @@ nsAttrAndChildArray::GrowBy(PRUint32 aGrowSize) size = PR_BIT(PR_CeilingLog2(minSize)); } - Impl* newImpl = static_cast - (mImpl ? PR_Realloc(mImpl, size * sizeof(void*)) : - PR_Malloc(size * sizeof(void*))); + Impl* newImpl = static_cast(mAllocator->Alloc(size * sizeof(void*))); NS_ENSURE_TRUE(newImpl, PR_FALSE); - Impl* oldImpl = mImpl; mImpl = newImpl; - - // Set initial counts if we didn't have a buffer before - if (!oldImpl) { + if (oldImpl) { + PRUint32 oldSize = + (oldImpl->mBufferSize + NS_IMPL_EXTRA_SIZE) * sizeof(void*); + memcpy(newImpl, oldImpl, oldSize); + mAllocator->Free(oldSize, oldImpl); + } else { + // Set initial counts if we didn't have a buffer before mImpl->mMappedAttrs = nsnull; SetAttrSlotAndChildCount(0, 0); } diff --git a/content/base/src/nsAttrAndChildArray.h b/content/base/src/nsAttrAndChildArray.h index 5f475a8bad9..5d0c1cee8ac 100644 --- a/content/base/src/nsAttrAndChildArray.h +++ b/content/base/src/nsAttrAndChildArray.h @@ -75,8 +75,10 @@ class nsGenericHTMLElement; class nsAttrAndChildArray { public: - nsAttrAndChildArray(); + nsAttrAndChildArray(nsDOMNodeAllocator* aAllocator); ~nsAttrAndChildArray(); + void SetAllocator(nsDOMNodeAllocator* aAllocator); + nsDOMNodeAllocator* Allocator() { return mAllocator; } PRUint32 ChildCount() const { @@ -123,8 +125,6 @@ public: nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet); void WalkMappedAttributeStyleRules(nsRuleWalker* aRuleWalker); - void Compact(); - private: nsAttrAndChildArray(const nsAttrAndChildArray& aOther); // Not to be implemented nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther); // Not to be implemented @@ -186,7 +186,8 @@ private: void* mBuffer[1]; }; - Impl* mImpl; + Impl* mImpl; + nsDOMNodeAllocator* mAllocator; }; #endif diff --git a/content/base/src/nsCommentNode.cpp b/content/base/src/nsCommentNode.cpp index 65060ef586f..0c0bba499e9 100644 --- a/content/base/src/nsCommentNode.cpp +++ b/content/base/src/nsCommentNode.cpp @@ -88,7 +88,7 @@ NS_NewCommentNode(nsIContent** aInstancePtrResult, nsCOMPtr ni = aNodeInfoManager->GetCommentNodeInfo(); NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY); - nsCommentNode *instance = new nsCommentNode(ni); + nsCommentNode *instance = new (ni) nsCommentNode(ni); if (!instance) { return NS_ERROR_OUT_OF_MEMORY; } @@ -163,7 +163,7 @@ nsCommentNode::GetNodeType(PRUint16* aNodeType) nsGenericDOMDataNode* nsCommentNode::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const { - nsCommentNode *it = new nsCommentNode(aNodeInfo); + nsCommentNode *it = new (aNodeInfo) nsCommentNode(aNodeInfo); if (it && aCloneText) { it->mText = mText; } diff --git a/content/base/src/nsDOMAttribute.cpp b/content/base/src/nsDOMAttribute.cpp index 2a2e889d9b1..ce739403558 100644 --- a/content/base/src/nsDOMAttribute.cpp +++ b/content/base/src/nsDOMAttribute.cpp @@ -64,7 +64,9 @@ PRBool nsDOMAttribute::sInitialized; nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap, nsINodeInfo *aNodeInfo, const nsAString &aValue) - : nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue) + : nsIAttribute(aAttrMap, aNodeInfo), + mAllocator(aNodeInfo->NodeInfoManager()->NodeAllocator()), + mValue(aValue) { NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!"); @@ -372,7 +374,7 @@ nsDOMAttribute::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const nsAutoString value; const_cast(this)->GetValue(value); - *aResult = new nsDOMAttribute(nsnull, aNodeInfo, value); + *aResult = new (aNodeInfo) nsDOMAttribute(nsnull, aNodeInfo, value); if (!*aResult) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/base/src/nsDOMAttribute.h b/content/base/src/nsDOMAttribute.h index 619ca8a2dfd..415673a2371 100644 --- a/content/base/src/nsDOMAttribute.h +++ b/content/base/src/nsDOMAttribute.h @@ -59,9 +59,9 @@ class nsDOMAttribute; // Attribute helper class used to wrap up an attribute with a dom // object that implements nsIDOMAttr, nsIDOM3Attr, nsIDOMNode, nsIDOM3Node -class nsDOMAttribute : public nsIDOMAttr, - public nsIDOM3Attr, - public nsIAttribute +class nsDOMAttribute : public nsIAttribute, + public nsIDOMAttr, + public nsIDOM3Attr { public: nsDOMAttribute(nsDOMAttributeMap* aAttrMap, nsINodeInfo *aNodeInfo, @@ -108,6 +108,7 @@ public: const nsIID& aIID); virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup); virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + virtual nsDOMNodeAllocator* GetAllocator() { return mAllocator; } static void Initialize(); static void Shutdown(); @@ -120,6 +121,7 @@ protected: private: nsresult EnsureChildState(PRBool aSetText, PRBool &aHasChild) const; + nsDOMNodeAllocator* mAllocator; nsString mValue; // XXX For now, there's only a single child - a text // element representing the value diff --git a/content/base/src/nsDOMAttributeMap.cpp b/content/base/src/nsDOMAttributeMap.cpp index 53f6fdffa7d..6f77b5216b4 100644 --- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -179,8 +179,8 @@ nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo, // the attribute node. mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value); } - nsCOMPtr newAttr = new nsDOMAttribute(aRemove ? nsnull : this, - aNodeInfo, value); + nsCOMPtr newAttr = + new (aNodeInfo) nsDOMAttribute(aRemove ? nsnull : this, aNodeInfo, value); if (!newAttr) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/base/src/nsDOMDocumentType.cpp b/content/base/src/nsDOMDocumentType.cpp index f221894b522..95bcbd64d29 100644 --- a/content/base/src/nsDOMDocumentType.cpp +++ b/content/base/src/nsDOMDocumentType.cpp @@ -89,8 +89,8 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType, kNameSpaceID_None, getter_AddRefs(ni)); NS_ENSURE_SUCCESS(rv, rv); - *aDocType = new nsDOMDocumentType(ni, aName, aEntities, aNotations, - aPublicId, aSystemId, aInternalSubset); + *aDocType = new (ni) nsDOMDocumentType(ni, aName, aEntities, aNotations, + aPublicId, aSystemId, aInternalSubset); if (!*aDocType) { return NS_ERROR_OUT_OF_MEMORY; } @@ -235,8 +235,9 @@ nsDOMDocumentType::GetNodeType(PRUint16* aNodeType) nsGenericDOMDataNode* nsDOMDocumentType::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const { - return new nsDOMDocumentType(aNodeInfo, mName, mEntities, mNotations, - mPublicId, mSystemId, mInternalSubset); + return new (aNodeInfo) nsDOMDocumentType(aNodeInfo, mName, mEntities, + mNotations, mPublicId, mSystemId, + mInternalSubset); } nsresult diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 9b0d65b3e38..4005e04b936 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -769,6 +769,7 @@ nsDOMImplementation::Init(nsIURI* aDocumentURI, nsIURI* aBaseURI, nsDocument::nsDocument(const char* aContentType) : nsIDocument(), + mChildren(nsnull), mVisible(PR_TRUE) { nsLayoutStatics::AddRef(); @@ -1105,6 +1106,19 @@ nsDocument::Init() NS_ENSURE_TRUE(bindingManager, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(mBindingManager = bindingManager); + mNodeInfoManager = new nsNodeInfoManager(); + NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(mNodeInfoManager); + + nsresult rv = mNodeInfoManager->Init(this); + NS_ENSURE_SUCCESS(rv, rv); + + mChildren.SetAllocator(mNodeInfoManager->NodeAllocator()); + + mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo(); + NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY); + nsINode::nsSlots* slots = GetSlots(); NS_ENSURE_TRUE(slots,NS_ERROR_OUT_OF_MEMORY); @@ -1125,17 +1139,6 @@ nsDocument::Init() mCSSLoader->SetCaseSensitive(PR_TRUE); mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards); - mNodeInfoManager = new nsNodeInfoManager(); - NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY); - - NS_ADDREF(mNodeInfoManager); - - nsresult rv = mNodeInfoManager->Init(this); - NS_ENSURE_SUCCESS(rv, rv); - - mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo(); - NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY); - NS_ASSERTION(GetOwnerDoc() == this, "Our nodeinfo is busted!"); mScriptLoader = new nsScriptLoader(this); @@ -1144,6 +1147,13 @@ nsDocument::Init() return NS_OK; } +nsINode::nsSlots* +nsDocument::CreateSlots() +{ + return + new (mNodeInfo->NodeInfoManager()->NodeAllocator()) nsSlots(mFlagsOrSlots); +} + nsresult nsDocument::AddXMLEventsContent(nsIContent *aXMLEventsElement) { @@ -3124,7 +3134,7 @@ nsDocument::CreateAttribute(const nsAString& aName, getter_AddRefs(nodeInfo)); NS_ENSURE_SUCCESS(rv, rv); - attribute = new nsDOMAttribute(nsnull, nodeInfo, value); + attribute = new (nodeInfo) nsDOMAttribute(nsnull, nodeInfo, value); NS_ENSURE_TRUE(attribute, NS_ERROR_OUT_OF_MEMORY); return CallQueryInterface(attribute, aReturn); @@ -3146,7 +3156,8 @@ nsDocument::CreateAttributeNS(const nsAString & aNamespaceURI, NS_ENSURE_SUCCESS(rv, rv); nsAutoString value; - nsDOMAttribute* attribute = new nsDOMAttribute(nsnull, nodeInfo, value); + nsDOMAttribute* attribute = + new (nodeInfo) nsDOMAttribute(nsnull, nodeInfo, value); NS_ENSURE_TRUE(attribute, NS_ERROR_OUT_OF_MEMORY); return CallQueryInterface(attribute, aResult); diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 9ef5c2d8832..2fb15774275 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -536,6 +536,7 @@ public: { return NS_ERROR_NOT_IMPLEMENTED; } + virtual nsDOMNodeAllocator* GetAllocator() { return nsnull; } // nsIRadioGroupContainer NS_IMETHOD WalkRadioGroup(const nsAString& aName, @@ -658,6 +659,7 @@ public: const nsAString& aClasses, nsIDOMNodeList** aReturn); protected: + virtual nsINode::nsSlots* CreateSlots(); /** * Check that aId is not empty and log a message to the console diff --git a/content/base/src/nsDocumentFragment.cpp b/content/base/src/nsDocumentFragment.cpp index e229acd8c11..582c6b7c7dd 100644 --- a/content/base/src/nsDocumentFragment.cpp +++ b/content/base/src/nsDocumentFragment.cpp @@ -171,7 +171,7 @@ NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult, getter_AddRefs(nodeInfo)); NS_ENSURE_SUCCESS(rv, rv); - nsDocumentFragment *it = new nsDocumentFragment(nodeInfo); + nsDocumentFragment *it = new (nodeInfo) nsDocumentFragment(nodeInfo); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/base/src/nsGenConImageContent.cpp b/content/base/src/nsGenConImageContent.cpp index 0880203d8e8..e2430a64ee1 100644 --- a/content/base/src/nsGenConImageContent.cpp +++ b/content/base/src/nsGenConImageContent.cpp @@ -81,7 +81,7 @@ NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo, imgIRequest* aImageRequest) { NS_PRECONDITION(aImageRequest, "Must have request!"); - nsGenConImageContent *it = new nsGenConImageContent(aNodeInfo); + nsGenConImageContent *it = new (aNodeInfo) nsGenConImageContent(aNodeInfo); if (!it) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*aResult = it); diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 171d22daf1c..36c842186ea 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -66,7 +66,7 @@ #include "prprf.h" nsGenericDOMDataNode::nsGenericDOMDataNode(nsINodeInfo *aNodeInfo) - : nsIContent(aNodeInfo) + : nsIContent(aNodeInfo), mText(aNodeInfo->NodeInfoManager()->NodeAllocator()) { } @@ -864,7 +864,7 @@ nsGenericDOMDataNode::IsLink(nsIURI** aURI) const nsINode::nsSlots* nsGenericDOMDataNode::CreateSlots() { - return new nsDataSlots(mFlagsOrSlots); + return new (GetAllocator()) nsDataSlots(mFlagsOrSlots); } //---------------------------------------------------------------------- diff --git a/content/base/src/nsGenericDOMDataNode.h b/content/base/src/nsGenericDOMDataNode.h index efeb7fc9cfb..2c50f6bb229 100644 --- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -187,6 +187,7 @@ public: virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID); virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup); + virtual nsDOMNodeAllocator* GetAllocator() { return mText.Allocator(); } // Implementation for nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index d587cc2aadf..7d9e2c44f12 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -171,8 +171,44 @@ nsINode::nsSlots::~nsSlots() } } +void* +nsINode::nsSlots::operator new(size_t aSize, nsDOMNodeAllocator* aAllocator) +{ + void* result = aAllocator->Alloc(aSize); + if (result) { + NS_ADDREF(aAllocator); + } + return result; +} + +void +nsINode::nsSlots::operator delete(void* aPtr, size_t aSize) +{ + size_t* szPtr = static_cast(aPtr); + *szPtr = aSize; +} + //---------------------------------------------------------------------- +void* +nsINode::operator new(size_t aSize, nsINodeInfo* aNodeInfo) +{ + nsDOMNodeAllocator* allocator = + aNodeInfo->NodeInfoManager()->NodeAllocator(); + void* result = allocator->Alloc(aSize); + if (result) { + NS_ADDREF(allocator); + } + return result; +} + +void +nsINode::operator delete(void* aPtr, size_t aSize) +{ + size_t* szPtr = static_cast(aPtr); + *szPtr = aSize; +} + nsINode::~nsINode() { NS_ASSERTION(!HasSlots(), "nsNodeUtils::LastRelease was not called?"); @@ -276,7 +312,7 @@ nsGenericElement::GetSystemEventGroup(nsIDOMEventGroup** aGroup) nsINode::nsSlots* nsINode::CreateSlots() { - return new nsSlots(mFlagsOrSlots); + return new (GetAllocator()) nsSlots(mFlagsOrSlots); } void @@ -1094,7 +1130,8 @@ nsGenericElement::nsDOMSlots::~nsDOMSlots() } nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo) - : nsIContent(aNodeInfo) + : nsIContent(aNodeInfo), + mAttrsAndChildren(aNodeInfo->NodeInfoManager()->NodeAllocator()) { // Set the default scriptID to JS - but skip SetScriptTypeID as it // does extra work we know isn't necessary here... @@ -4170,7 +4207,7 @@ nsGenericElement::IndexOf(nsINode* aPossibleChild) const nsINode::nsSlots* nsGenericElement::CreateSlots() { - return new nsDOMSlots(mFlagsOrSlots); + return new (GetAllocator()) nsDOMSlots(mFlagsOrSlots); } PRBool diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index c14c39d2160..8edf7ca27a5 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -376,6 +376,10 @@ public: virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID); virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup); + virtual nsDOMNodeAllocator* GetAllocator() + { + return mAttrsAndChildren.Allocator(); + } // nsIContent interface methods virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, @@ -1010,7 +1014,7 @@ _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const \ { \ *aResult = nsnull; \ \ - _elementName *it = new _elementName(aNodeInfo); \ + _elementName *it = new (aNodeInfo) _elementName(aNodeInfo); \ if (!it) { \ return NS_ERROR_OUT_OF_MEMORY; \ } \ @@ -1030,7 +1034,7 @@ _elementName::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const \ { \ *aResult = nsnull; \ \ - _elementName *it = new _elementName(aNodeInfo); \ + _elementName *it = new (aNodeInfo) _elementName(aNodeInfo); \ if (!it) { \ return NS_ERROR_OUT_OF_MEMORY; \ } \ diff --git a/content/base/src/nsNodeInfoManager.cpp b/content/base/src/nsNodeInfoManager.cpp index 83e956e8643..dd545b5542f 100644 --- a/content/base/src/nsNodeInfoManager.cpp +++ b/content/base/src/nsNodeInfoManager.cpp @@ -51,6 +51,146 @@ #include "nsReadableUtils.h" #include "nsGkAtoms.h" #include "nsComponentManagerUtils.h" +#include "prbit.h" +#include "plarena.h" +#include "nsMemory.h" + +#define NS_MAX_NODE_RECYCLE_SIZE \ + (NS_NODE_RECYCLER_SIZE * sizeof(void*)) + +#ifdef DEBUG +static PRUint32 gDOMNodeAllocators = 0; +// Counts the number of non-freed allocations. +static size_t gDOMNodeAllocations = 0; +static PRUint32 gDOMNodeRecyclerCounters[NS_NODE_RECYCLER_SIZE]; +static PRUint32 gDOMNodeNormalAllocations = 0; +class nsDOMNodeAllocatorTester +{ +public: + nsDOMNodeAllocatorTester() + { + memset(gDOMNodeRecyclerCounters, 0, sizeof(gDOMNodeRecyclerCounters)); + } + ~nsDOMNodeAllocatorTester() + { +#ifdef DEBUG_smaug + for (PRInt32 i = 0 ; i < NS_NODE_RECYCLER_SIZE; ++i) { + if (gDOMNodeRecyclerCounters[i]) { + printf("DOMNodeAllocator, arena allocation: %u bytes %u times\n", + static_cast((i + 1) * sizeof(void*)), + gDOMNodeRecyclerCounters[i]); + } + } + if (gDOMNodeNormalAllocations) { + printf("DOMNodeAllocator, normal allocations: %i times \n", + gDOMNodeNormalAllocations); + } +#endif + if (gDOMNodeAllocations != 0) { + printf("nsDOMNodeAllocator leaked %u bytes \n", + static_cast(gDOMNodeAllocations)); + } + } +}; +nsDOMNodeAllocatorTester gDOMAllocatorTester; +#endif + +nsDOMNodeAllocator::~nsDOMNodeAllocator() +{ + if (mPool) { + PL_FinishArenaPool(mPool); + delete mPool; + } +#ifdef DEBUG + --gDOMNodeAllocators; +#endif +} + +nsresult +nsDOMNodeAllocator::Init() +{ +#ifdef DEBUG + ++gDOMNodeAllocators; +#endif + mPool = new PLArenaPool(); + NS_ENSURE_TRUE(mPool, NS_ERROR_OUT_OF_MEMORY); + PL_InitArenaPool(mPool, "nsDOMNodeAllocator", 4096 * (sizeof(void*)/2), 0); + memset(mRecyclers, 0, sizeof(mRecyclers)); + return NS_OK; +} + +nsrefcnt +nsDOMNodeAllocator::Release() +{ + NS_PRECONDITION(0 != mRefCnt, "dup release"); + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsDOMNodeAllocator"); + if (mRefCnt == 0) { + mRefCnt = 1; /* stabilize */ + delete this; + return 0; + } + return mRefCnt; +} + +void* +nsDOMNodeAllocator::Alloc(size_t aSize) +{ + void* result = nsnull; + + // Ensure we have correct alignment for pointers. + aSize = aSize ? PR_ROUNDUP(aSize, sizeof(void*)) : sizeof(void*); + // Check recyclers first + if (aSize <= NS_MAX_NODE_RECYCLE_SIZE) { + const PRInt32 index = (aSize / sizeof(void*)) - 1; + result = mRecyclers[index]; + if (result) { + // Need to move to the next object + void* next = *((void**)result); + mRecyclers[index] = next; + } + if (!result) { + // Allocate a new chunk from the arena + PL_ARENA_ALLOCATE(result, mPool, aSize); + } +#ifdef DEBUG + ++gDOMNodeRecyclerCounters[index]; +#endif + } else { + result = nsMemory::Alloc(aSize); +#ifdef DEBUG + ++gDOMNodeNormalAllocations; +#endif + } + +#ifdef DEBUG + gDOMNodeAllocations += aSize; +#endif + return result; +} + +void +nsDOMNodeAllocator::Free(size_t aSize, void* aPtr) +{ + if (!aPtr) { + return; + } + // Ensure we have correct alignment for pointers. + aSize = aSize ? PR_ROUNDUP(aSize, sizeof(void*)) : sizeof(void*); + // See if it's a size that we recycle + if (aSize <= NS_MAX_NODE_RECYCLE_SIZE) { + const PRInt32 index = (aSize / sizeof(void*)) - 1; + void* currentTop = mRecyclers[index]; + mRecyclers[index] = aPtr; + *((void**)aPtr) = currentTop; + } else { + nsMemory::Free(aPtr); + } + +#ifdef DEBUG + gDOMNodeAllocations -= aSize; +#endif +} PRUint32 nsNodeInfoManager::gNodeManagerCount; @@ -154,6 +294,10 @@ nsNodeInfoManager::Init(nsIDocument *aDocument) { NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY); + mNodeAllocator = new nsDOMNodeAllocator(); + NS_ENSURE_TRUE(mNodeAllocator && NS_SUCCEEDED(mNodeAllocator->Init()), + NS_ERROR_OUT_OF_MEMORY); + NS_PRECONDITION(!mPrincipal, "Being inited when we already have a principal?"); nsresult rv = CallCreateInstance("@mozilla.org/nullprincipal;1", diff --git a/content/base/src/nsNodeInfoManager.h b/content/base/src/nsNodeInfoManager.h index 64c464a3806..cd433b9e67a 100644 --- a/content/base/src/nsNodeInfoManager.h +++ b/content/base/src/nsNodeInfoManager.h @@ -44,6 +44,8 @@ #include "nsCOMPtr.h" // for already_AddRefed #include "plhash.h" +#include "prlog.h" +#include "nsAutoPtr.h" class nsIAtom; class nsIDocument; @@ -57,6 +59,39 @@ class nsIDOMDocument; class nsAString; class nsIDOMNamedNodeMap; class nsXULPrototypeDocument; +class nsNodeInfoManager; +struct PLArenaPool; + +// The size of mRecyclers array. The max size of recycled memory is +// sizeof(void*) * NS_NODE_RECYCLER_SIZE. +#define NS_NODE_RECYCLER_SIZE 64 + +class nsDOMNodeAllocator +{ +public: + nsDOMNodeAllocator() : mPool(nsnull) {} + ~nsDOMNodeAllocator(); + + nsrefcnt AddRef() + { + NS_ASSERTION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsDOMNodeAllocator", sizeof(*this)); + return mRefCnt; + } + nsrefcnt Release(); + + void* Alloc(size_t aSize); + void Free(size_t aSize, void* aPtr); +protected: + friend class nsNodeInfoManager; + nsresult Init(); + nsAutoRefCnt mRefCnt; + PLArenaPool* mPool; + // The recycler array points to recycled memory, where the size of + // block is index*sizeof(void*), i.e., 0, 4, 8, 12, 16, ... or 0, 8, 16, ... + void* mRecyclers[NS_NODE_RECYCLER_SIZE]; +}; class nsNodeInfoManager { @@ -123,6 +158,7 @@ public: void RemoveNodeInfo(nsNodeInfo *aNodeInfo); + nsDOMNodeAllocator* NodeAllocator() { return mNodeAllocator; } protected: friend class nsDocument; friend class nsXULPrototypeDocument; @@ -159,6 +195,8 @@ private: nsINodeInfo *mCommentNodeInfo; // WEAK to avoid circular ownership nsINodeInfo *mDocumentNodeInfo; // WEAK to avoid circular ownership + nsRefPtr mNodeAllocator; + static PRUint32 gNodeManagerCount; }; diff --git a/content/base/src/nsNodeUtils.cpp b/content/base/src/nsNodeUtils.cpp index 445e25d1184..cf3dc8dd64b 100755 --- a/content/base/src/nsNodeUtils.cpp +++ b/content/base/src/nsNodeUtils.cpp @@ -188,6 +188,7 @@ void nsNodeUtils::LastRelease(nsINode* aNode) { nsINode::nsSlots* slots = aNode->GetExistingSlots(); + nsRefPtr allocator = aNode->GetAllocator(); if (slots) { if (!slots->mMutationObservers.IsEmpty()) { NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(slots->mMutationObservers, @@ -196,7 +197,14 @@ nsNodeUtils::LastRelease(nsINode* aNode) } PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS; - delete slots; + delete slots; // Calls destructor and sets size to *slots. + NS_ASSERTION(allocator || aNode->IsNodeOfType(nsINode::eDOCUMENT), + "Should have allocator or document!"); + nsDOMNodeAllocator* slotsAllocator = allocator ? + allocator.get() : aNode->mNodeInfo->NodeInfoManager()->NodeAllocator(); + size_t* sz = reinterpret_cast(slots); + slotsAllocator->Free(*sz, static_cast(slots)); + NS_RELEASE(slotsAllocator); aNode->mFlagsOrSlots = flags; } @@ -235,7 +243,15 @@ nsNodeUtils::LastRelease(nsINode* aNode) aNode->UnsetFlags(NODE_HAS_LISTENERMANAGER); } - delete aNode; + if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) { + delete aNode; + } else { + NS_ASSERTION(allocator, "Should have allocator here!"); + delete aNode; // Calls destructor and sets size to *aNode. + size_t* sz = reinterpret_cast(aNode); + allocator->Free(*sz, static_cast(aNode)); + NS_RELEASE(allocator); + } } static nsresult diff --git a/content/base/src/nsTextFragment.cpp b/content/base/src/nsTextFragment.cpp index a09f40d121f..7fdca8fa685 100644 --- a/content/base/src/nsTextFragment.cpp +++ b/content/base/src/nsTextFragment.cpp @@ -45,9 +45,9 @@ #include "nsString.h" #include "nsCRT.h" #include "nsReadableUtils.h" -#include "nsMemory.h" #include "nsBidiUtils.h" #include "nsUnicharUtils.h" +#include "nsNodeInfoManager.h" #define TEXTFRAG_WHITE_AFTER_NEWLINE 50 #define TEXTFRAG_MAX_NEWLINES 7 @@ -102,16 +102,27 @@ nsTextFragment::Shutdown() } } +nsTextFragment::nsTextFragment(nsDOMNodeAllocator* aAllocator) + : m1b(nsnull), mAllBits(0), mAllocator(aAllocator) +{ + NS_ADDREF(mAllocator); + NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!"); +} + nsTextFragment::~nsTextFragment() { ReleaseText(); + NS_RELEASE(mAllocator); } void nsTextFragment::ReleaseText() { if (mState.mLength && m1b && mState.mInHeap) { - nsMemory::Free(m2b); // m1b == m2b as far as nsMemory is concerned + // m1b == m2b as far as memory is concerned + mAllocator->Free(mState.mLength * + (mState.mIs2b ? sizeof(PRUnichar) : sizeof(char)), + m2b); } m1b = nsnull; @@ -120,6 +131,16 @@ nsTextFragment::ReleaseText() mAllBits = 0; } +void* +nsTextFragment::CloneMemory(const void* aPtr, PRSize aSize) +{ + void* newPtr = mAllocator->Alloc(aSize); + if (newPtr) { + memcpy(newPtr, aPtr, aSize); + } + return newPtr; +} + nsTextFragment& nsTextFragment::operator=(const nsTextFragment& aOther) { @@ -130,9 +151,11 @@ nsTextFragment::operator=(const nsTextFragment& aOther) m1b = aOther.m1b; // This will work even if aOther is using m2b } else { - m2b = static_cast - (nsMemory::Clone(aOther.m2b, aOther.mState.mLength * - (aOther.mState.mIs2b ? sizeof(PRUnichar) : sizeof(char)))); + m2b = + static_cast + (CloneMemory(aOther.m2b, aOther.mState.mLength * + (aOther.mState.mIs2b ? + sizeof(PRUnichar) : sizeof(char)))); } if (m1b) { @@ -213,14 +236,13 @@ nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength) if (need2) { // Use ucs2 storage because we have to - m2b = (PRUnichar *)nsMemory::Clone(aBuffer, - aLength * sizeof(PRUnichar)); + m2b = (PRUnichar *)CloneMemory(aBuffer, aLength * sizeof(PRUnichar)); if (!m2b) { return; } } else { // Use 1 byte storage because we can - char* buff = (char *)nsMemory::Alloc(aLength * sizeof(char)); + char* buff = (char *)mAllocator->Alloc(aLength * sizeof(char)); if (!buff) { return; } @@ -301,15 +323,20 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength) if (mState.mIs2b) { // Already a 2-byte string so the result will be too - PRUnichar* buff = (PRUnichar*)nsMemory::Realloc(m2b, (mState.mLength + aLength) * sizeof(PRUnichar)); + PRUnichar* buff = + (PRUnichar*)mAllocator->Alloc((mState.mLength + aLength) * + sizeof(PRUnichar)); if (!buff) { return; } - + memcpy(buff, m2b, mState.mLength * sizeof(PRUnichar)); memcpy(buff + mState.mLength, aBuffer, aLength * sizeof(PRUnichar)); + if (mState.mInHeap) { + mAllocator->Free(mState.mLength * sizeof(PRUnichar), m2b); + } mState.mLength += aLength; m2b = buff; - + mState.mInHeap = PR_TRUE; return; } @@ -329,8 +356,8 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength) if (need2) { // The old data was 1-byte, but the new is not so we have to expand it // all to 2-byte - PRUnichar* buff = (PRUnichar*)nsMemory::Alloc((mState.mLength + aLength) * - sizeof(PRUnichar)); + PRUnichar* buff = (PRUnichar*)mAllocator->Alloc((mState.mLength + aLength) * + sizeof(PRUnichar)); if (!buff) { return; } @@ -342,42 +369,34 @@ nsTextFragment::Append(const PRUnichar* aBuffer, PRUint32 aLength) memcpy(buff + mState.mLength, aBuffer, aLength * sizeof(PRUnichar)); + if (mState.mInHeap) { + mAllocator->Free(mState.mLength * sizeof(char), m2b); + } mState.mLength += aLength; mState.mIs2b = PR_TRUE; - - if (mState.mInHeap) { - nsMemory::Free(m2b); - } m2b = buff; - mState.mInHeap = PR_TRUE; return; } // The new and the old data is all 1-byte - char* buff; - if (mState.mInHeap) { - buff = (char*)nsMemory::Realloc(const_cast(m1b), - (mState.mLength + aLength) * sizeof(char)); - if (!buff) { - return; - } + char* buff = + (char*)mAllocator->Alloc((mState.mLength + aLength) * sizeof(char)); + if (!buff) { + return; } - else { - buff = (char*)nsMemory::Alloc((mState.mLength + aLength) * sizeof(char)); - if (!buff) { - return; - } - memcpy(buff, m1b, mState.mLength); - mState.mInHeap = PR_TRUE; - } - + memcpy(buff, m1b, mState.mLength); + for (PRUint32 i = 0; i < aLength; ++i) { buff[mState.mLength + i] = (char)aBuffer[i]; } + if (mState.mInHeap) { + mAllocator->Free(mState.mLength * sizeof(char), const_cast(m1b)); + } + mState.mInHeap = PR_TRUE; m1b = buff; mState.mLength += aLength; diff --git a/content/base/src/nsTextFragment.h b/content/base/src/nsTextFragment.h index 6c65e147f9f..91fd1ece596 100644 --- a/content/base/src/nsTextFragment.h +++ b/content/base/src/nsTextFragment.h @@ -47,6 +47,7 @@ #include "nsAString.h" class nsString; class nsCString; +class nsDOMNodeAllocator; // XXX should this normalize the code to keep a \u0000 at the end? @@ -85,14 +86,12 @@ public: /** * Default constructor. Initialize the fragment to be empty. */ - nsTextFragment() - : m1b(nsnull), mAllBits(0) - { - NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!"); - } + nsTextFragment(nsDOMNodeAllocator* aAllocator); ~nsTextFragment(); + nsDOMNodeAllocator* Allocator() { return mAllocator; } + /** * Change the contents of this fragment to be a copy of the * the argument fragment. @@ -205,6 +204,7 @@ public: private: void ReleaseText(); + void* CloneMemory(const void* aPtr, PRSize aSize); union { PRUnichar *m2b; @@ -215,6 +215,7 @@ private: PRUint32 mAllBits; FragmentBits mState; }; + nsDOMNodeAllocator* mAllocator; }; #endif /* nsTextFragment_h___ */ diff --git a/content/base/src/nsTextNode.cpp b/content/base/src/nsTextNode.cpp index 4f30768a338..6d155aa6d9d 100644 --- a/content/base/src/nsTextNode.cpp +++ b/content/base/src/nsTextNode.cpp @@ -114,9 +114,9 @@ public: virtual nsGenericDOMDataNode *CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const { - nsAttributeTextNode *it = new nsAttributeTextNode(aNodeInfo, - mNameSpaceID, - mAttrName); + nsAttributeTextNode *it = new (aNodeInfo) nsAttributeTextNode(aNodeInfo, + mNameSpaceID, + mAttrName); if (it && aCloneText) { it->mText = mText; } @@ -154,7 +154,7 @@ NS_NewTextNode(nsIContent** aInstancePtrResult, return NS_ERROR_OUT_OF_MEMORY; } - nsIContent *instance = new nsTextNode(ni); + nsIContent *instance = new (ni) nsTextNode(ni); if (!instance) { return NS_ERROR_OUT_OF_MEMORY; } @@ -220,7 +220,7 @@ nsTextNode::IsNodeOfType(PRUint32 aFlags) const nsGenericDOMDataNode* nsTextNode::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const { - nsTextNode *it = new nsTextNode(aNodeInfo); + nsTextNode *it = new (aNodeInfo) nsTextNode(aNodeInfo); if (it && aCloneText) { it->mText = mText; } @@ -280,8 +280,8 @@ NS_NewAttributeContent(nsNodeInfoManager *aNodeInfoManager, return NS_ERROR_OUT_OF_MEMORY; } - nsAttributeTextNode* textNode = new nsAttributeTextNode(ni, aNameSpaceID, - aAttrName); + nsAttributeTextNode* textNode = new (ni) nsAttributeTextNode(ni, aNameSpaceID, + aAttrName); if (!textNode) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/events/src/nsXMLEventsElement.cpp b/content/events/src/nsXMLEventsElement.cpp index 37c07a419d7..30deb24165f 100644 --- a/content/events/src/nsXMLEventsElement.cpp +++ b/content/events/src/nsXMLEventsElement.cpp @@ -87,7 +87,7 @@ NS_IMPL_ELEMENT_CLONE(nsXMLEventsElement) nsresult NS_NewXMLEventsElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo) { - nsXMLEventsElement* it = new nsXMLEventsElement(aNodeInfo); + nsXMLEventsElement* it = new (aNodeInfo) nsXMLEventsElement(aNodeInfo); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index aea26825e2b..8d0cad61016 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -235,7 +235,6 @@ public: nsresult GetHrefURIForAnchors(nsIURI** aURI) const; // HTML element methods - void Compact() { mAttrsAndChildren.Compact(); } const nsAttrValue* GetParsedAttr(nsIAtom* aAttr) const { return mAttrsAndChildren.GetAttr(aAttr); @@ -960,14 +959,15 @@ protected: nsGenericHTMLElement* \ NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo, PRBool aFromParser)\ { \ - return new nsHTML##_elementName##Element(aNodeInfo); \ + return new (aNodeInfo) nsHTML##_elementName##Element(aNodeInfo); \ } #define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \ nsGenericHTMLElement* \ NS_NewHTML##_elementName##Element(nsINodeInfo *aNodeInfo, PRBool aFromParser)\ { \ - return new nsHTML##_elementName##Element(aNodeInfo, aFromParser); \ + return \ + new (aNodeInfo) nsHTML##_elementName##Element(aNodeInfo, aFromParser); \ } diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp index ef55ba49466..5d833cea83c 100644 --- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -135,7 +135,7 @@ public: nsGenericHTMLElement* NS_NewHTMLCanvasElement(nsINodeInfo *aNodeInfo, PRBool aFromParser) { - return new nsHTMLCanvasElement(aNodeInfo); + return new (aNodeInfo) nsHTMLCanvasElement(aNodeInfo); } nsHTMLCanvasElement::nsHTMLCanvasElement(nsINodeInfo *aNodeInfo) diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index 9f812e119e7..94be9f11ce0 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -461,7 +461,7 @@ ShouldBeInElements(nsIFormControl* aFormControl) nsGenericHTMLElement* NS_NewHTMLFormElement(nsINodeInfo *aNodeInfo, PRBool aFromParser) { - nsHTMLFormElement* it = new nsHTMLFormElement(aNodeInfo); + nsHTMLFormElement* it = new (aNodeInfo) nsHTMLFormElement(aNodeInfo); if (!it) { return nsnull; } diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index 265cd1342c7..91e87bdefbe 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -172,7 +172,7 @@ NS_NewHTMLImageElement(nsINodeInfo *aNodeInfo, PRBool aFromParser) NS_ENSURE_SUCCESS(rv, nsnull); } - return new nsHTMLImageElement(nodeInfo); + return new (nodeInfo) nsHTMLImageElement(nodeInfo); } nsHTMLImageElement::nsHTMLImageElement(nsINodeInfo *aNodeInfo) diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index a711f5d586c..14e1944dbc2 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -430,7 +430,8 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { *aResult = nsnull; - nsHTMLInputElement *it = new nsHTMLInputElement(aNodeInfo, PR_FALSE); + nsHTMLInputElement *it = + new (aNodeInfo) nsHTMLInputElement(aNodeInfo, PR_FALSE); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/html/content/src/nsHTMLOptionElement.cpp b/content/html/content/src/nsHTMLOptionElement.cpp index e6c89aea9b1..3eb7160cb78 100644 --- a/content/html/content/src/nsHTMLOptionElement.cpp +++ b/content/html/content/src/nsHTMLOptionElement.cpp @@ -157,7 +157,7 @@ NS_NewHTMLOptionElement(nsINodeInfo *aNodeInfo, PRBool aFromParser) NS_ENSURE_SUCCESS(rv, nsnull); } - return new nsHTMLOptionElement(nodeInfo); + return new (nodeInfo) nsHTMLOptionElement(nodeInfo); } nsHTMLOptionElement::nsHTMLOptionElement(nsINodeInfo *aNodeInfo) diff --git a/content/html/content/src/nsHTMLScriptElement.cpp b/content/html/content/src/nsHTMLScriptElement.cpp index 64c3b888c13..541621078ec 100644 --- a/content/html/content/src/nsHTMLScriptElement.cpp +++ b/content/html/content/src/nsHTMLScriptElement.cpp @@ -420,7 +420,8 @@ nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { *aResult = nsnull; - nsHTMLScriptElement* it = new nsHTMLScriptElement(aNodeInfo, PR_FALSE); + nsHTMLScriptElement* it = + new (aNodeInfo) nsHTMLScriptElement(aNodeInfo, PR_FALSE); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 335e9d24477..4bb1a6a221d 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -931,7 +931,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag, PRBool aMalformed) nsGenericHTMLElement* content = mStack[mStackPos].mContent; - content->Compact(); // If we're in a state where we do append notifications as // we go up the tree, and we're at the level where the next diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index 742ea465552..916b903628e 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -97,7 +97,9 @@ nsSVGEnumMapping nsSVGElement::sSVGUnitTypesMap[] = { }; nsSVGElement::nsSVGElement(nsINodeInfo *aNodeInfo) - : nsSVGElementBase(aNodeInfo), mSuppressNotification(PR_FALSE) + : nsSVGElementBase(aNodeInfo), + mMappedAttributes(aNodeInfo->NodeInfoManager()->NodeAllocator()), + mSuppressNotification(PR_FALSE) { } diff --git a/content/svg/content/src/nsSVGElement.h b/content/svg/content/src/nsSVGElement.h index d44b0bee505..2d890e7a91b 100644 --- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -313,7 +313,7 @@ NS_NewSVG##_elementName##Element(nsIContent **aResult, \ nsINodeInfo *aNodeInfo) \ { \ nsSVG##_elementName##Element *it = \ - new nsSVG##_elementName##Element(aNodeInfo); \ + new (aNodeInfo) nsSVG##_elementName##Element(aNodeInfo); \ if (!it) \ return NS_ERROR_OUT_OF_MEMORY; \ \ diff --git a/content/svg/content/src/nsSVGUseElement.cpp b/content/svg/content/src/nsSVGUseElement.cpp index 36103ac671a..e481928b5f9 100644 --- a/content/svg/content/src/nsSVGUseElement.cpp +++ b/content/svg/content/src/nsSVGUseElement.cpp @@ -133,7 +133,7 @@ nsSVGUseElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { *aResult = nsnull; - nsSVGUseElement *it = new nsSVGUseElement(aNodeInfo); + nsSVGUseElement *it = new (aNodeInfo) nsSVGUseElement(aNodeInfo); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/xml/content/src/nsXMLCDATASection.cpp b/content/xml/content/src/nsXMLCDATASection.cpp index 8a4eb89fdbd..d0663b06b59 100644 --- a/content/xml/content/src/nsXMLCDATASection.cpp +++ b/content/xml/content/src/nsXMLCDATASection.cpp @@ -86,7 +86,7 @@ NS_NewXMLCDATASection(nsIContent** aInstancePtrResult, getter_AddRefs(ni)); NS_ENSURE_SUCCESS(rv, rv); - nsXMLCDATASection *instance = new nsXMLCDATASection(ni); + nsXMLCDATASection *instance = new (ni) nsXMLCDATASection(ni); if (!instance) { return NS_ERROR_OUT_OF_MEMORY; } @@ -154,7 +154,7 @@ nsXMLCDATASection::GetNodeType(PRUint16* aNodeType) nsGenericDOMDataNode* nsXMLCDATASection::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const { - nsXMLCDATASection *it = new nsXMLCDATASection(aNodeInfo); + nsXMLCDATASection *it = new (aNodeInfo) nsXMLCDATASection(aNodeInfo); if (it && aCloneText) { it->mText = mText; } diff --git a/content/xml/content/src/nsXMLElement.cpp b/content/xml/content/src/nsXMLElement.cpp index 5fb4f6765dd..10c10f149f0 100644 --- a/content/xml/content/src/nsXMLElement.cpp +++ b/content/xml/content/src/nsXMLElement.cpp @@ -47,7 +47,7 @@ nsresult NS_NewXMLElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo) { - nsXMLElement* it = new nsXMLElement(aNodeInfo); + nsXMLElement* it = new (aNodeInfo) nsXMLElement(aNodeInfo); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/xml/content/src/nsXMLProcessingInstruction.cpp b/content/xml/content/src/nsXMLProcessingInstruction.cpp index 04a7ac7489f..29575941dbc 100644 --- a/content/xml/content/src/nsXMLProcessingInstruction.cpp +++ b/content/xml/content/src/nsXMLProcessingInstruction.cpp @@ -65,7 +65,7 @@ NS_NewXMLProcessingInstruction(nsIContent** aInstancePtrResult, NS_ENSURE_SUCCESS(rv, rv); nsXMLProcessingInstruction *instance = - new nsXMLProcessingInstruction(ni, aTarget, aData); + new (ni) nsXMLProcessingInstruction(ni, aTarget, aData); if (!instance) { return NS_ERROR_OUT_OF_MEMORY; } @@ -176,7 +176,7 @@ nsXMLProcessingInstruction::CloneDataNode(nsINodeInfo *aNodeInfo, nsAutoString data; nsGenericDOMDataNode::GetData(data); - return new nsXMLProcessingInstruction(aNodeInfo, mTarget, data); + return new (aNodeInfo) nsXMLProcessingInstruction(aNodeInfo, mTarget, data); } #ifdef DEBUG diff --git a/content/xml/content/src/nsXMLStylesheetPI.cpp b/content/xml/content/src/nsXMLStylesheetPI.cpp index e9bcd263908..cf61ca08bd5 100644 --- a/content/xml/content/src/nsXMLStylesheetPI.cpp +++ b/content/xml/content/src/nsXMLStylesheetPI.cpp @@ -246,7 +246,7 @@ nsXMLStylesheetPI::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) cons nsAutoString data; nsGenericDOMDataNode::GetData(data); - return new nsXMLStylesheetPI(aNodeInfo, data); + return new (aNodeInfo) nsXMLStylesheetPI(aNodeInfo, data); } nsresult @@ -265,7 +265,7 @@ NS_NewXMLStylesheetProcessingInstruction(nsIContent** aInstancePtrResult, getter_AddRefs(ni)); NS_ENSURE_SUCCESS(rv, rv); - nsXMLStylesheetPI *instance = new nsXMLStylesheetPI(ni, aData); + nsXMLStylesheetPI *instance = new (ni) nsXMLStylesheetPI(ni, aData); if (!instance) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/xtf/src/nsXTFElementWrapper.cpp b/content/xtf/src/nsXTFElementWrapper.cpp index 3c0dc1d2a38..2c7d5ab4cf2 100644 --- a/content/xtf/src/nsXTFElementWrapper.cpp +++ b/content/xtf/src/nsXTFElementWrapper.cpp @@ -1003,7 +1003,8 @@ NS_NewXTFElementWrapper(nsIXTFElement* aXTFElement, *aResult = nsnull; NS_ENSURE_ARG(aXTFElement); - nsXTFElementWrapper* result = new nsXTFElementWrapper(aNodeInfo, aXTFElement); + nsXTFElementWrapper* result = + new (aNodeInfo) nsXTFElementWrapper(aNodeInfo, aXTFElement); if (!result) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 72bf118a5a9..1045976f58b 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -262,7 +262,7 @@ nsXULElement::nsXULSlots::~nsXULSlots() nsINode::nsSlots* nsXULElement::CreateSlots() { - return new nsXULSlots(mFlagsOrSlots); + return new (GetAllocator()) nsXULSlots(mFlagsOrSlots); } /* static */ @@ -270,7 +270,7 @@ already_AddRefed nsXULElement::Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo, PRBool aIsScriptable) { - nsXULElement *element = new nsXULElement(aNodeInfo); + nsXULElement *element = new (aNodeInfo) nsXULElement(aNodeInfo); if (element) { NS_ADDREF(element); @@ -351,7 +351,7 @@ NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) *aResult = nsnull; // Create an nsXULElement with the specified namespace and tag. - nsXULElement* element = new nsXULElement(aNodeInfo); + nsXULElement* element = new (aNodeInfo) nsXULElement(aNodeInfo); NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aResult = element); @@ -431,7 +431,7 @@ nsXULElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const "Didn't get the default language from proto?"); } else { - element = new nsXULElement(aNodeInfo); + element = new (aNodeInfo) nsXULElement(aNodeInfo); if (element) { // If created from a prototype, we will already have the script // language specified by the proto - otherwise copy it directly