зеркало из https://github.com/mozilla/gecko-dev.git
Bug 613595. Speed up the cache-hit case for getElementsByTagName. r=peterv
This commit is contained in:
Родитель
5c09bffd17
Коммит
4193bc442a
|
@ -203,24 +203,20 @@ ContentListHashtableMatchEntry(PLDHashTable *table,
|
|||
{
|
||||
const ContentListHashEntry *e =
|
||||
static_cast<const ContentListHashEntry *>(entry);
|
||||
const nsContentListKey* list1 = e->mContentList->GetKey();
|
||||
const nsContentListKey* list2 = static_cast<const nsContentListKey *>(key);
|
||||
const nsContentList* list = e->mContentList;
|
||||
const nsContentListKey* ourKey = static_cast<const nsContentListKey *>(key);
|
||||
|
||||
return list1->Equals(*list2);
|
||||
return list->MatchesKey(*ourKey);
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsINode* aRootNode,
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
nsIAtom* aHTMLMatchAtom,
|
||||
nsIAtom* aXMLMatchAtom)
|
||||
const nsAString& aTagname)
|
||||
|
||||
{
|
||||
NS_ASSERTION(aRootNode, "content list has to have a root");
|
||||
|
||||
if(!aXMLMatchAtom)
|
||||
aXMLMatchAtom = aHTMLMatchAtom;
|
||||
|
||||
nsContentList* list = nsnull;
|
||||
|
||||
static PLDHashTableOps hash_table_ops =
|
||||
|
@ -249,15 +245,14 @@ NS_GetContentList(nsINode* aRootNode,
|
|||
ContentListHashEntry *entry = nsnull;
|
||||
// First we look in our hashtable. Then we create a content list if needed
|
||||
if (gContentListHashTable.ops) {
|
||||
nsContentListKey hashKey(aRootNode, aHTMLMatchAtom,
|
||||
aXMLMatchAtom, aMatchNameSpaceId);
|
||||
nsContentListKey hashKey(aRootNode, aMatchNameSpaceId, aTagname);
|
||||
|
||||
// A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
|
||||
// when the entry is already in the hashtable.
|
||||
entry = static_cast<ContentListHashEntry *>
|
||||
(PL_DHashTableOperate(&gContentListHashTable,
|
||||
&hashKey,
|
||||
PL_DHASH_ADD));
|
||||
&hashKey,
|
||||
PL_DHASH_ADD));
|
||||
if (entry)
|
||||
list = entry->mContentList;
|
||||
}
|
||||
|
@ -265,8 +260,17 @@ NS_GetContentList(nsINode* aRootNode,
|
|||
if (!list) {
|
||||
// We need to create a ContentList and add it to our new entry, if
|
||||
// we have an entry
|
||||
nsCOMPtr<nsIAtom> xmlAtom = do_GetAtom(aTagname);
|
||||
nsCOMPtr<nsIAtom> htmlAtom;
|
||||
if (aMatchNameSpaceId == kNameSpaceID_Unknown) {
|
||||
nsAutoString lowercaseName;
|
||||
nsContentUtils::ASCIIToLower(aTagname, lowercaseName);
|
||||
htmlAtom = do_GetAtom(lowercaseName);
|
||||
} else {
|
||||
htmlAtom = xmlAtom;
|
||||
}
|
||||
list = new nsContentList(aRootNode, aMatchNameSpaceId,
|
||||
aHTMLMatchAtom, aXMLMatchAtom);
|
||||
htmlAtom, xmlAtom);
|
||||
if (entry) {
|
||||
entry->mContentList = list;
|
||||
}
|
||||
|
@ -391,7 +395,10 @@ nsContentList::nsContentList(nsINode* aRootNode,
|
|||
nsIAtom* aXMLMatchAtom,
|
||||
PRBool aDeep)
|
||||
: nsBaseContentList(),
|
||||
nsContentListKey(aRootNode, aHTMLMatchAtom, aXMLMatchAtom, aMatchNameSpaceId),
|
||||
mRootNode(aRootNode),
|
||||
mMatchNameSpaceId(aMatchNameSpaceId),
|
||||
mHTMLMatchAtom(aHTMLMatchAtom),
|
||||
mXMLMatchAtom(aXMLMatchAtom),
|
||||
mFunc(nsnull),
|
||||
mDestroyFunc(nsnull),
|
||||
mData(nsnull),
|
||||
|
@ -419,12 +426,15 @@ nsContentList::nsContentList(nsINode* aRootNode,
|
|||
PRInt32 aMatchNameSpaceId,
|
||||
PRBool aFuncMayDependOnAttr)
|
||||
: nsBaseContentList(),
|
||||
nsContentListKey(aRootNode, aMatchAtom, aMatchAtom, aMatchNameSpaceId),
|
||||
mRootNode(aRootNode),
|
||||
mMatchNameSpaceId(aMatchNameSpaceId),
|
||||
mHTMLMatchAtom(aMatchAtom),
|
||||
mXMLMatchAtom(aMatchAtom),
|
||||
mFunc(aFunc),
|
||||
mDestroyFunc(aDestroyFunc),
|
||||
mData(aData),
|
||||
mMatchAll(PR_FALSE),
|
||||
mState(LIST_DIRTY),
|
||||
mMatchAll(PR_FALSE),
|
||||
mDeep(aDeep),
|
||||
mFuncMayDependOnAttr(aFuncMayDependOnAttr)
|
||||
{
|
||||
|
@ -907,8 +917,10 @@ nsContentList::RemoveFromHashtable()
|
|||
if (!gContentListHashTable.ops)
|
||||
return;
|
||||
|
||||
nsDependentAtomString str(mXMLMatchAtom);
|
||||
nsContentListKey key(mRootNode, mMatchNameSpaceId, str);
|
||||
PL_DHashTableOperate(&gContentListHashTable,
|
||||
GetKey(),
|
||||
&key,
|
||||
PL_DHASH_REMOVE);
|
||||
|
||||
if (gContentListHashTable.entryCount == 0) {
|
||||
|
|
|
@ -140,53 +140,35 @@ public:
|
|||
* Class that's used as the key to hash nsContentList implementations
|
||||
* for fast retrieval
|
||||
*/
|
||||
class nsContentListKey
|
||||
struct nsContentListKey
|
||||
{
|
||||
public:
|
||||
nsContentListKey(nsINode* aRootNode,
|
||||
nsIAtom* aHTMLMatchAtom,
|
||||
nsIAtom* aXMLMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId)
|
||||
: mHTMLMatchAtom(aHTMLMatchAtom),
|
||||
mXMLMatchAtom(aXMLMatchAtom),
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
const nsAString& aTagname)
|
||||
: mRootNode(aRootNode),
|
||||
mMatchNameSpaceId(aMatchNameSpaceId),
|
||||
mRootNode(aRootNode)
|
||||
mTagname(aTagname)
|
||||
{
|
||||
NS_ASSERTION(!aXMLMatchAtom == !aHTMLMatchAtom, "Either neither or both atoms should be null");
|
||||
}
|
||||
|
||||
|
||||
nsContentListKey(const nsContentListKey& aContentListKey)
|
||||
: mHTMLMatchAtom(aContentListKey.mHTMLMatchAtom),
|
||||
mXMLMatchAtom(aContentListKey.mXMLMatchAtom),
|
||||
: mRootNode(aContentListKey.mRootNode),
|
||||
mMatchNameSpaceId(aContentListKey.mMatchNameSpaceId),
|
||||
mRootNode(aContentListKey.mRootNode)
|
||||
mTagname(aContentListKey.mTagname)
|
||||
{
|
||||
}
|
||||
|
||||
PRBool Equals(const nsContentListKey& aContentListKey) const
|
||||
{
|
||||
NS_ASSERTION(mHTMLMatchAtom == aContentListKey.mHTMLMatchAtom
|
||||
|| mXMLMatchAtom != aContentListKey.mXMLMatchAtom, "HTML atoms should match if XML atoms match");
|
||||
|
||||
return
|
||||
mXMLMatchAtom == aContentListKey.mXMLMatchAtom &&
|
||||
mMatchNameSpaceId == aContentListKey.mMatchNameSpaceId &&
|
||||
mRootNode == aContentListKey.mRootNode;
|
||||
}
|
||||
|
||||
inline PRUint32 GetHash(void) const
|
||||
{
|
||||
return
|
||||
NS_PTR_TO_INT32(mXMLMatchAtom.get()) ^
|
||||
HashString(mTagname) ^
|
||||
(NS_PTR_TO_INT32(mRootNode) << 12) ^
|
||||
(mMatchNameSpaceId << 24);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIAtom> mHTMLMatchAtom;
|
||||
nsCOMPtr<nsIAtom> mXMLMatchAtom;
|
||||
PRInt32 mMatchNameSpaceId;
|
||||
nsINode* mRootNode; // Weak ref
|
||||
nsINode* const mRootNode; // Weak ref
|
||||
const PRInt32 mMatchNameSpaceId;
|
||||
const nsAString& mTagname;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -214,7 +196,6 @@ protected:
|
|||
* tree based on some criterion.
|
||||
*/
|
||||
class nsContentList : public nsBaseContentList,
|
||||
protected nsContentListKey,
|
||||
public nsIHTMLCollection,
|
||||
public nsStubMutationObserver,
|
||||
public nsWrapperCache
|
||||
|
@ -290,11 +271,6 @@ public:
|
|||
NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
|
||||
NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
|
||||
|
||||
nsContentListKey* GetKey() {
|
||||
return static_cast<nsContentListKey*>(this);
|
||||
}
|
||||
|
||||
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
|
@ -318,6 +294,19 @@ public:
|
|||
return static_cast<nsContentList*>(list);
|
||||
}
|
||||
|
||||
PRBool MatchesKey(const nsContentListKey& aKey) const
|
||||
{
|
||||
// The root node is most commonly the same: the document. And the
|
||||
// most common namespace id is kNameSpaceID_Unknown. So check the
|
||||
// string first.
|
||||
NS_PRECONDITION(mXMLMatchAtom,
|
||||
"How did we get here with a null match atom on our list?");
|
||||
return
|
||||
mXMLMatchAtom->Equals(aKey.mTagname) &&
|
||||
mRootNode == aKey.mRootNode &&
|
||||
mMatchNameSpaceId == aKey.mMatchNameSpaceId;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns whether the element matches our criterion
|
||||
|
@ -388,6 +377,11 @@ protected:
|
|||
RemoveFromHashtable();
|
||||
}
|
||||
|
||||
nsINode* mRootNode; // Weak ref
|
||||
PRInt32 mMatchNameSpaceId;
|
||||
nsCOMPtr<nsIAtom> mHTMLMatchAtom;
|
||||
nsCOMPtr<nsIAtom> mXMLMatchAtom;
|
||||
|
||||
/**
|
||||
* Function to use to determine whether a piece of content matches
|
||||
* our criterion
|
||||
|
@ -494,11 +488,15 @@ protected:
|
|||
nsString mString;
|
||||
};
|
||||
|
||||
// If aMatchNameSpaceId is kNameSpaceID_Unknown, this will return a
|
||||
// content list which matches ASCIIToLower(aTagname) against HTML
|
||||
// elements in HTML documents and aTagname against everything else.
|
||||
// For any other value of aMatchNameSpaceId, the list will match
|
||||
// aTagname against all elements.
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsINode* aRootNode,
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
nsIAtom* aHTMLMatchAtom,
|
||||
nsIAtom* aXMLMatchAtom = nsnull);
|
||||
const nsAString& aTagname);
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetFuncStringContentList(nsINode* aRootNode,
|
||||
|
|
|
@ -4579,17 +4579,6 @@ nsDocument::CreateEntityReference(const nsAString& aName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
nsDocument::GetElementsByTagName(const nsAString& aTagname)
|
||||
{
|
||||
nsAutoString lowercaseName;
|
||||
nsContentUtils::ASCIIToLower(aTagname, lowercaseName);
|
||||
nsCOMPtr<nsIAtom> xmlAtom = do_GetAtom(aTagname);
|
||||
nsCOMPtr<nsIAtom> htmlAtom = do_GetAtom(lowercaseName);
|
||||
|
||||
return NS_GetContentList(this, kNameSpaceID_Unknown, htmlAtom, xmlAtom);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetElementsByTagName(const nsAString& aTagname,
|
||||
nsIDOMNodeList** aReturn)
|
||||
|
@ -4615,9 +4604,9 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
|
||||
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
|
||||
|
||||
return NS_GetContentList(this, nameSpaceId, nameAtom);
|
||||
return NS_GetContentList(this, nameSpaceId, aLocalName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -5184,7 +5173,7 @@ nsDocument::GetTitleContent(PRUint32 aNamespace)
|
|||
return nsnull;
|
||||
|
||||
nsRefPtr<nsContentList> list =
|
||||
NS_GetContentList(this, aNamespace, nsGkAtoms::title);
|
||||
NS_GetContentList(this, aNamespace, NS_LITERAL_STRING("title"));
|
||||
|
||||
return list->Item(0, PR_FALSE);
|
||||
}
|
||||
|
@ -7473,7 +7462,7 @@ nsDocument::OnPageShow(PRBool aPersisted,
|
|||
// Send out notifications that our <link> elements are attached.
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(root,
|
||||
kNameSpaceID_Unknown,
|
||||
nsGkAtoms::link);
|
||||
NS_LITERAL_STRING("link"));
|
||||
|
||||
PRUint32 linkCount = links->Length(PR_TRUE);
|
||||
for (PRUint32 i = 0; i < linkCount; ++i) {
|
||||
|
@ -7525,7 +7514,7 @@ nsDocument::OnPageHide(PRBool aPersisted,
|
|||
if (aPersisted && root) {
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(root,
|
||||
kNameSpaceID_Unknown,
|
||||
nsGkAtoms::link);
|
||||
NS_LITERAL_STRING("link"));
|
||||
|
||||
PRUint32 linkCount = links->Length(PR_TRUE);
|
||||
for (PRUint32 i = 0; i < linkCount; ++i) {
|
||||
|
|
|
@ -978,7 +978,9 @@ public:
|
|||
virtual void SetChangeScrollPosWhenScrollingToRef(PRBool aValue);
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagName(const nsAString& aTagName);
|
||||
GetElementsByTagName(const nsAString& aTagName) {
|
||||
return NS_GetContentList(this, kNameSpaceID_Unknown, aTagName);
|
||||
}
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName);
|
||||
|
|
|
@ -2558,13 +2558,8 @@ nsresult
|
|||
nsGenericElement::GetElementsByTagName(const nsAString& aTagname,
|
||||
nsIDOMNodeList** aReturn)
|
||||
{
|
||||
nsAutoString lowercaseName;
|
||||
nsContentUtils::ASCIIToLower(aTagname, lowercaseName);
|
||||
nsCOMPtr<nsIAtom> XMLAtom = do_GetAtom(aTagname);
|
||||
nsCOMPtr<nsIAtom> HTMLAtom = do_GetAtom(lowercaseName);
|
||||
|
||||
nsContentList *list = NS_GetContentList(this, kNameSpaceID_Unknown,
|
||||
HTMLAtom, XMLAtom).get();
|
||||
aTagname).get();
|
||||
|
||||
// transfer ref to aReturn
|
||||
*aReturn = list;
|
||||
|
@ -2690,9 +2685,9 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
|
||||
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
|
||||
|
||||
nsContentList *list = NS_GetContentList(this, nameSpaceId, nameAtom).get();
|
||||
nsContentList *list = NS_GetContentList(this, nameSpaceId, aLocalName).get();
|
||||
|
||||
// transfer ref to aReturn
|
||||
*aReturn = list;
|
||||
|
|
|
@ -1537,7 +1537,7 @@ nsHTMLDocument::GetBody(nsresult *aResult)
|
|||
// The document is most likely a frameset document so look for the
|
||||
// outer most frameset element
|
||||
nsRefPtr<nsContentList> nodeList =
|
||||
NS_GetContentList(this, kNameSpaceID_XHTML, nsGkAtoms::frameset);
|
||||
NS_GetContentList(this, kNameSpaceID_XHTML, NS_LITERAL_STRING("frameset"));
|
||||
|
||||
return nodeList->GetNodeAt(0);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче