Bug 403830, arena for content, r=sicking, sr=jst

This commit is contained in:
Olli.Pettay@helsinki.fi 2007-12-15 01:45:33 -08:00
parent a2ae010008
commit 489154b8b5
40 changed files with 433 additions and 161 deletions

View File

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

View File

@ -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<Impl*>(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<Impl*>
(mImpl ? PR_Realloc(mImpl, size * sizeof(void*)) :
PR_Malloc(size * sizeof(void*)));
Impl* newImpl = static_cast<Impl*>(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);
}

View File

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

View File

@ -88,7 +88,7 @@ NS_NewCommentNode(nsIContent** aInstancePtrResult,
nsCOMPtr<nsINodeInfo> 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;
}

View File

@ -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<nsDOMAttribute*>(this)->GetValue(value);
*aResult = new nsDOMAttribute(nsnull, aNodeInfo, value);
*aResult = new (aNodeInfo) nsDOMAttribute(nsnull, aNodeInfo, value);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}

View File

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

View File

@ -179,8 +179,8 @@ nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo,
// the attribute node.
mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
}
nsCOMPtr<nsIDOMNode> newAttr = new nsDOMAttribute(aRemove ? nsnull : this,
aNodeInfo, value);
nsCOMPtr<nsIDOMNode> newAttr =
new (aNodeInfo) nsDOMAttribute(aRemove ? nsnull : this, aNodeInfo, value);
if (!newAttr) {
return NS_ERROR_OUT_OF_MEMORY;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<size_t*>(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<size_t*>(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

View File

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

View File

@ -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<unsigned int>((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<unsigned int>(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",

View File

@ -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<nsDOMNodeAllocator> mNodeAllocator;
static PRUint32 gNodeManagerCount;
};

View File

@ -188,6 +188,7 @@ void
nsNodeUtils::LastRelease(nsINode* aNode)
{
nsINode::nsSlots* slots = aNode->GetExistingSlots();
nsRefPtr<nsDOMNodeAllocator> 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<size_t*>(slots);
slotsAllocator->Free(*sz, static_cast<void*>(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<size_t*>(aNode);
allocator->Free(*sz, static_cast<void*>(aNode));
NS_RELEASE(allocator);
}
}
static nsresult

View File

@ -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<PRUnichar*>
(nsMemory::Clone(aOther.m2b, aOther.mState.mLength *
(aOther.mState.mIs2b ? sizeof(PRUnichar) : sizeof(char))));
m2b =
static_cast<PRUnichar*>
(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<char*>(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<char*>(m1b));
}
mState.mInHeap = PR_TRUE;
m1b = buff;
mState.mLength += aLength;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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