Add a faster method for iterating the nsIContent children of an

nsINode if we know that there will be no DOM mutations of any sort
during the iteration.  Bug 429744, r+sr=jst
This commit is contained in:
Boris Zbarsky 2008-07-11 16:42:19 -04:00
Родитель 8e6047ac2b
Коммит e73857359a
13 изменённых файлов: 79 добавлений и 10 удалений

Просмотреть файл

@ -148,8 +148,9 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument)
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x6f69dd90, 0x318d, 0x40ac, \
{ 0xb8, 0xb8, 0x99, 0xb8, 0xa7, 0xbb, 0x9a, 0x58 } }
{ 0x2593b0d5, 0x9a06, 0x4d6b, \
{ 0x9a, 0x10, 0xb1, 0x39, 0x9f, 0x1b, 0xa0, 0x8e } }
/**
* An internal interface that abstracts some DOMNode-related parts that both
@ -233,6 +234,16 @@ public:
*/
virtual nsIContent* GetChildAt(PRUint32 aIndex) const = 0;
/**
* Get a raw pointer to the child array. This should only be used if you
* plan to walk a bunch of the kids, promise to make sure that nothing ever
* mutates (no attribute changes, not DOM tree changes, no script execution,
* NOTHING), and will never ever peform an out-of-bounds access here. This
* method may return null if there are no children, or it may return a
* garbage pointer..
*/
virtual nsIContent * const * GetChildArray() const = 0;
/**
* Get the index of a child within this content
* @param aPossibleChild the child to get the index of.

Просмотреть файл

@ -145,6 +145,16 @@ nsAttrAndChildArray::GetSafeChildAt(PRUint32 aPos) const
return nsnull;
}
nsIContent * const *
nsAttrAndChildArray::GetChildArray() const
{
if (!mImpl) {
return nsnull;
}
return reinterpret_cast<nsIContent**>(mImpl->mBuffer + AttrSlotsSize());
}
nsresult
nsAttrAndChildArray::InsertChildAt(nsIContent* aChild, PRUint32 aPos)
{

Просмотреть файл

@ -88,6 +88,7 @@ public:
return reinterpret_cast<nsIContent*>(mImpl->mBuffer[AttrSlotsSize() + aPos]);
}
nsIContent* GetSafeChildAt(PRUint32 aPos) const;
nsIContent * const * GetChildArray() const;
nsresult AppendChild(nsIContent* aChild)
{
return InsertChildAt(aChild, ChildCount());

Просмотреть файл

@ -64,7 +64,7 @@ PRBool nsDOMAttribute::sInitialized;
nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
nsINodeInfo *aNodeInfo,
const nsAString &aValue)
: nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue)
: nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue), mChild(nsnull)
{
NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
@ -73,18 +73,23 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
// to drop our reference when it goes away.
}
nsDOMAttribute::~nsDOMAttribute()
{
NS_IF_RELEASE(mChild);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttribute)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttribute)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChild)
NS_IF_RELEASE(tmp->mChild);
NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@ -668,8 +673,14 @@ nsDOMAttribute::GetChildAt(PRUint32 aIndex) const
PRBool hasChild;
EnsureChildState(PR_TRUE, hasChild);
return aIndex == 0 && hasChild ? mChild.get() : nsnull;
return aIndex == 0 && hasChild ? mChild : nsnull;
}
nsIContent * const *
nsDOMAttribute::GetChildArray() const
{
return &mChild;
}
PRInt32
nsDOMAttribute::IndexOf(nsINode* aPossibleChild) const
@ -779,7 +790,7 @@ nsDOMAttribute::EnsureChildState(PRBool aSetText, PRBool &aHasChild) const
mutableThis->GetValue(value);
if (!mChild && !value.IsEmpty()) {
nsresult rv = NS_NewTextNode(getter_AddRefs(mutableThis->mChild),
nsresult rv = NS_NewTextNode(&mutableThis->mChild,
mNodeInfo->NodeInfoManager());
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -66,6 +66,7 @@ class nsDOMAttribute : public nsIAttribute,
public:
nsDOMAttribute(nsDOMAttributeMap* aAttrMap, nsINodeInfo *aNodeInfo,
const nsAString& aValue);
virtual ~nsDOMAttribute();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -90,6 +91,7 @@ public:
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual nsIContent * const * GetChildArray() const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
@ -121,9 +123,10 @@ private:
nsresult EnsureChildState(PRBool aSetText, PRBool &aHasChild) const;
nsString mValue;
// XXX For now, there's only a single child - a text
// element representing the value
nsCOMPtr<nsIContent> mChild;
// XXX For now, there's only a single child - a text element
// representing the value. This is strong ref, but we use a raw
// pointer so we can implement GetChildArray().
nsIContent* mChild;
nsIContent *GetContentInternal() const
{

Просмотреть файл

@ -2682,6 +2682,13 @@ nsDocument::GetChildCount() const
return mChildren.ChildCount();
}
nsIContent * const *
nsDocument::GetChildArray() const
{
return mChildren.GetChildArray();
}
nsresult
nsDocument::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify)

Просмотреть файл

@ -630,6 +630,7 @@ public:
// nsINode
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual nsIContent * const * GetChildArray() const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual PRUint32 GetChildCount() const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,

Просмотреть файл

@ -800,6 +800,12 @@ nsGenericDOMDataNode::GetChildAt(PRUint32 aIndex) const
return nsnull;
}
nsIContent * const *
nsGenericDOMDataNode::GetChildArray() const
{
return nsnull;
}
PRInt32
nsGenericDOMDataNode::IndexOf(nsINode* aPossibleChild) const
{

Просмотреть файл

@ -172,6 +172,7 @@ public:
// nsINode methods
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual nsIContent * const * GetChildArray() const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);

Просмотреть файл

@ -4322,6 +4322,12 @@ nsGenericElement::GetChildAt(PRUint32 aIndex) const
return mAttrsAndChildren.GetSafeChildAt(aIndex);
}
nsIContent * const *
nsGenericElement::GetChildArray() const
{
return mAttrsAndChildren.GetChildArray();
}
PRInt32
nsGenericElement::IndexOf(nsINode* aPossibleChild) const
{

Просмотреть файл

@ -361,6 +361,7 @@ public:
// nsINode interface methods
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual nsIContent * const * GetChildArray() const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);

Просмотреть файл

@ -947,6 +947,16 @@ nsXULElement::GetChildAt(PRUint32 aIndex) const
return mAttrsAndChildren.GetSafeChildAt(aIndex);
}
nsIContent * const *
nsXULElement::GetChildArray() const
{
if (NS_FAILED(EnsureContentsGenerated())) {
return nsnull;
}
return mAttrsAndChildren.GetChildArray();
}
PRInt32
nsXULElement::IndexOf(nsINode* aPossibleChild) const
{

Просмотреть файл

@ -543,6 +543,7 @@ public:
// nsINode
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual nsIContent * const * GetChildArray() const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,