Commit dfff1021 authored by ch.dumez@samsung.com's avatar ch.dumez@samsung.com

Move HTMLCollection's id / name cache to a new NamedItemCache class

Move HTMLCollection's id / name cache to a new class. HTML's collection
m_hasValidIdNameCache, m_idCache and m_nameCache members were replaced by a
single OwnPtr that holds an instance of NamedItemCache when populated.

Most HTMLCollections do not have a valid namedItemCache so we end up saving
some memory. This also makes the code a bit clearer.

This patch is based on the following WebKit revision by rniwa@webkit.org:
http://trac.webkit.org/changeset/164772

R=

Review URL: https://codereview.chromium.org/215073003

git-svn-id: svn://svn.chromium.org/blink/trunk@170592 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 5a57c0d7
...@@ -50,15 +50,16 @@ Element* HTMLAllCollection::namedItemWithIndex(const AtomicString& name, unsigne ...@@ -50,15 +50,16 @@ Element* HTMLAllCollection::namedItemWithIndex(const AtomicString& name, unsigne
{ {
updateIdNameCache(); updateIdNameCache();
if (Vector<Element*>* cache = idCache(name)) { const NamedItemCache& cache = namedItemCache();
if (index < cache->size()) if (Vector<Element*>* elements = cache.getElementsById(name)) {
return cache->at(index); if (index < elements->size())
index -= cache->size(); return elements->at(index);
index -= elements->size();
} }
if (Vector<Element*>* cache = nameCache(name)) { if (Vector<Element*>* elements = cache.getElementsByName(name)) {
if (index < cache->size()) if (index < elements->size())
return cache->at(index); return elements->at(index);
} }
return 0; return 0;
......
...@@ -162,7 +162,6 @@ HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, It ...@@ -162,7 +162,6 @@ HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, It
: LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type), type) : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type), type)
, m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter) , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter)
, m_shouldOnlyIncludeDirectChildren(shouldTypeOnlyIncludeDirectChildren(type)) , m_shouldOnlyIncludeDirectChildren(shouldTypeOnlyIncludeDirectChildren(type))
, m_hasValidIdNameCache(false)
{ {
ScriptWrappable::init(this); ScriptWrappable::init(this);
} }
...@@ -387,11 +386,12 @@ Element* HTMLCollection::namedItem(const AtomicString& name) const ...@@ -387,11 +386,12 @@ Element* HTMLCollection::namedItem(const AtomicString& name) const
// that are allowed a name attribute. // that are allowed a name attribute.
updateIdNameCache(); updateIdNameCache();
Vector<Element*>* idResults = idCache(name); const NamedItemCache& cache = namedItemCache();
Vector<Element*>* idResults = cache.getElementsById(name);
if (idResults && !idResults->isEmpty()) if (idResults && !idResults->isEmpty())
return idResults->first(); return idResults->first();
Vector<Element*>* nameResults = nameCache(name); Vector<Element*>* nameResults = cache.getElementsByName(name);
if (nameResults && !nameResults->isEmpty()) if (nameResults && !nameResults->isEmpty())
return nameResults->first(); return nameResults->first();
...@@ -443,19 +443,18 @@ void HTMLCollection::updateIdNameCache() const ...@@ -443,19 +443,18 @@ void HTMLCollection::updateIdNameCache() const
if (hasValidIdNameCache()) if (hasValidIdNameCache())
return; return;
NamedItemCache& cache = createNamedItemCache();
ContainerNode& root = rootNode(); ContainerNode& root = rootNode();
for (Element* element = traverseToFirstElement(root); element; element = traverseNextElement(*element, root)) { for (Element* element = traverseToFirstElement(root); element; element = traverseNextElement(*element, root)) {
const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& idAttrVal = element->getIdAttribute();
if (!idAttrVal.isEmpty()) if (!idAttrVal.isEmpty())
appendIdCache(idAttrVal, element); cache.addElementWithId(idAttrVal, element);
if (!element->isHTMLElement()) if (!element->isHTMLElement())
continue; continue;
const AtomicString& nameAttrVal = element->getNameAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute();
if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != DocAll || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != DocAll || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element))))
appendNameCache(nameAttrVal, element); cache.addElementWithName(nameAttrVal, element);
} }
setHasValidIdNameCache();
} }
void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Element> >& result) const void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Element> >& result) const
...@@ -466,8 +465,9 @@ void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Element> ...@@ -466,8 +465,9 @@ void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Element>
updateIdNameCache(); updateIdNameCache();
Vector<Element*>* idResults = idCache(name); const NamedItemCache& cache = namedItemCache();
Vector<Element*>* nameResults = nameCache(name); Vector<Element*>* idResults = cache.getElementsById(name);
Vector<Element*>* nameResults = cache.getElementsByName(name);
for (unsigned i = 0; idResults && i < idResults->size(); ++i) for (unsigned i = 0; idResults && i < idResults->size(); ++i)
result.append(idResults->at(i)); result.append(idResults->at(i));
...@@ -476,12 +476,4 @@ void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Element> ...@@ -476,12 +476,4 @@ void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Element>
result.append(nameResults->at(i)); result.append(nameResults->at(i));
} }
void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element)
{
OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).storedValue->value;
if (!vector)
vector = adoptPtr(new Vector<Element*>);
vector->append(element);
}
} // namespace WebCore } // namespace WebCore
...@@ -65,33 +65,54 @@ public: ...@@ -65,33 +65,54 @@ public:
protected: protected:
HTMLCollection(ContainerNode& base, CollectionType, ItemAfterOverrideType); HTMLCollection(ContainerNode& base, CollectionType, ItemAfterOverrideType);
class NamedItemCache {
public:
Vector<Element*>* getElementsById(const AtomicString& id) const { return m_idCache.get(id.impl()); }
Vector<Element*>* getElementsByName(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
void addElementWithId(const AtomicString& id, Element* element) { addElementToMap(m_idCache, id, element); }
void addElementWithName(const AtomicString& name, Element* element) { addElementToMap(m_nameCache, name, element); }
private:
typedef HashMap<StringImpl*, OwnPtr<Vector<Element*> > > StringToElementsMap;
static void addElementToMap(StringToElementsMap& map, const AtomicString& key, Element* element)
{
OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).storedValue->value;
if (!vector)
vector = adoptPtr(new Vector<Element*>);
vector->append(element);
}
StringToElementsMap m_idCache;
StringToElementsMap m_nameCache;
};
bool overridesItemAfter() const { return m_overridesItemAfter; } bool overridesItemAfter() const { return m_overridesItemAfter; }
virtual Element* virtualItemAfter(Element*) const; virtual Element* virtualItemAfter(Element*) const;
bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; } bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; }
virtual void supportedPropertyNames(Vector<String>& names); virtual void supportedPropertyNames(Vector<String>& names);
virtual void updateIdNameCache() const; virtual void updateIdNameCache() const;
bool hasValidIdNameCache() const { return m_hasValidIdNameCache; } bool hasValidIdNameCache() const { return m_namedItemCache; }
void setHasValidIdNameCache() const
NamedItemCache& createNamedItemCache() const
{ {
ASSERT(!m_hasValidIdNameCache); ASSERT(!m_namedItemCache);
m_hasValidIdNameCache = true;
document().incrementNodeListWithIdNameCacheCount(); document().incrementNodeListWithIdNameCacheCount();
m_namedItemCache = adoptPtr(new NamedItemCache);
return *m_namedItemCache;
}
NamedItemCache& namedItemCache() const
{
ASSERT(m_namedItemCache);
return *m_namedItemCache;
} }
typedef HashMap<StringImpl*, OwnPtr<Vector<Element*> > > NodeCacheMap;
Vector<Element*>* idCache(const AtomicString& name) const { return m_idCache.get(name.impl()); }
Vector<Element*>* nameCache(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
void appendIdCache(const AtomicString& name, Element* element) const { append(m_idCache, name, element); }
void appendNameCache(const AtomicString& name, Element* element) const { append(m_nameCache, name, element); }
private: private:
Element* traverseNextElement(Element& previous, const ContainerNode& root) const; Element* traverseNextElement(Element& previous, const ContainerNode& root) const;
static void append(NodeCacheMap&, const AtomicString&, Element*);
void invalidateIdNameCacheMaps(Document* oldDocument = 0) const void invalidateIdNameCacheMaps(Document* oldDocument = 0) const
{ {
if (!m_hasValidIdNameCache) if (!hasValidIdNameCache())
return; return;
// Make sure we decrement the NodeListWithIdNameCache count from // Make sure we decrement the NodeListWithIdNameCache count from
...@@ -99,22 +120,18 @@ private: ...@@ -99,22 +120,18 @@ private:
// is moved to a new document. // is moved to a new document.
unregisterIdNameCacheFromDocument(oldDocument ? *oldDocument : document()); unregisterIdNameCacheFromDocument(oldDocument ? *oldDocument : document());
m_idCache.clear(); m_namedItemCache.clear();
m_nameCache.clear();
m_hasValidIdNameCache = false;
} }
void unregisterIdNameCacheFromDocument(Document& document) const void unregisterIdNameCacheFromDocument(Document& document) const
{ {
ASSERT(m_hasValidIdNameCache); ASSERT(hasValidIdNameCache());
document.decrementNodeListWithIdNameCacheCount(); document.decrementNodeListWithIdNameCacheCount();
} }
const unsigned m_overridesItemAfter : 1; const unsigned m_overridesItemAfter : 1;
const unsigned m_shouldOnlyIncludeDirectChildren : 1; const unsigned m_shouldOnlyIncludeDirectChildren : 1;
mutable unsigned m_hasValidIdNameCache : 1; mutable OwnPtr<NamedItemCache> m_namedItemCache;
mutable NodeCacheMap m_idCache;
mutable NodeCacheMap m_nameCache;
mutable CollectionIndexCache<HTMLCollection, Element> m_collectionIndexCache; mutable CollectionIndexCache<HTMLCollection, Element> m_collectionIndexCache;
friend class LiveNodeListBase; friend class LiveNodeListBase;
......
...@@ -153,6 +153,7 @@ void HTMLFormControlsCollection::updateIdNameCache() const ...@@ -153,6 +153,7 @@ void HTMLFormControlsCollection::updateIdNameCache() const
if (hasValidIdNameCache()) if (hasValidIdNameCache())
return; return;
NamedItemCache& cache = createNamedItemCache();
HashSet<StringImpl*> foundInputElements; HashSet<StringImpl*> foundInputElements;
const Vector<FormAssociatedElement*>& elementsArray = formControlElements(); const Vector<FormAssociatedElement*>& elementsArray = formControlElements();
...@@ -164,11 +165,11 @@ void HTMLFormControlsCollection::updateIdNameCache() const ...@@ -164,11 +165,11 @@ void HTMLFormControlsCollection::updateIdNameCache() const
const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& idAttrVal = element->getIdAttribute();
const AtomicString& nameAttrVal = element->getNameAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute();
if (!idAttrVal.isEmpty()) { if (!idAttrVal.isEmpty()) {
appendIdCache(idAttrVal, element); cache.addElementWithId(idAttrVal, element);
foundInputElements.add(idAttrVal.impl()); foundInputElements.add(idAttrVal.impl());
} }
if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) {
appendNameCache(nameAttrVal, element); cache.addElementWithName(nameAttrVal, element);
foundInputElements.add(nameAttrVal.impl()); foundInputElements.add(nameAttrVal.impl());
} }
} }
...@@ -181,13 +182,11 @@ void HTMLFormControlsCollection::updateIdNameCache() const ...@@ -181,13 +182,11 @@ void HTMLFormControlsCollection::updateIdNameCache() const
const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& idAttrVal = element->getIdAttribute();
const AtomicString& nameAttrVal = element->getNameAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute();
if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl()))
appendIdCache(idAttrVal, element); cache.addElementWithId(idAttrVal, element);
if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl()))
appendNameCache(nameAttrVal, element); cache.addElementWithName(nameAttrVal, element);
} }
} }
setHasValidIdNameCache();
} }
void HTMLFormControlsCollection::namedGetter(const AtomicString& name, bool& radioNodeListEnabled, RefPtr<RadioNodeList>& radioNodeList, bool& elementEnabled, RefPtr<Element>& element) void HTMLFormControlsCollection::namedGetter(const AtomicString& name, bool& radioNodeListEnabled, RefPtr<RadioNodeList>& radioNodeList, bool& elementEnabled, RefPtr<Element>& element)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment