Permalink
Browse files

DOM traversal optimizations DOM Core optimizations Prefetch optimizat…

…ion for DOM Tree Traversal

Change-Id: Ifc330c13f58c254d717d555375a584c9b7ca6479
  • Loading branch information...
1 parent 46db31e commit a78859f6a6ea579b6db838d740404014f0eaeda1 Naiem Shaik committed with Whitehawkx Jul 19, 2012
Showing with 877 additions and 379 deletions.
  1. +3 −3 Source/JavaScriptCore/runtime/RopeImpl.h
  2. +1 −1 Source/JavaScriptCore/wtf/RefPtr.h
  3. +1 −1 Source/JavaScriptCore/wtf/text/AtomicString.cpp
  4. +1 −1 Source/JavaScriptCore/wtf/text/AtomicString.h
  5. +7 −3 Source/JavaScriptCore/wtf/text/StringImpl.cpp
  6. +14 −25 Source/JavaScriptCore/wtf/text/StringImpl.h
  7. +34 −21 Source/JavaScriptCore/wtf/text/StringImplBase.h
  8. +1 −1 Source/JavaScriptCore/wtf/text/WTFString.h
  9. +1 −0 Source/WebCore/Android.mk
  10. +2 −2 Source/WebCore/css/CSSStyleSelector.cpp
  11. +2 −0 Source/WebCore/dom/Attr.cpp
  12. +1 −0 Source/WebCore/dom/CharacterData.cpp
  13. +14 −3 Source/WebCore/dom/ChildNodeList.cpp
  14. +5 −3 Source/WebCore/dom/ChildNodeList.h
  15. +39 −8 Source/WebCore/dom/ContainerNode.cpp
  16. +11 −0 Source/WebCore/dom/ContainerNode.h
  17. +5 −4 Source/WebCore/dom/Document.cpp
  18. +3 −0 Source/WebCore/dom/Document.h
  19. +1 −1 Source/WebCore/dom/DocumentOrderedMap.cpp
  20. +40 −6 Source/WebCore/dom/DynamicNodeList.cpp
  21. +8 −0 Source/WebCore/dom/DynamicNodeList.h
  22. +167 −86 Source/WebCore/dom/Node.cpp
  23. +64 −15 Source/WebCore/dom/Node.h
  24. +18 −4 Source/WebCore/dom/NodeRareData.h
  25. +13 −3 Source/WebCore/dom/SelectorNodeList.cpp
  26. +28 −7 Source/WebCore/dom/TagNodeList.cpp
  27. +35 −14 Source/WebCore/dom/TagNodeList.h
  28. +1 −1 Source/WebCore/dom/Text.cpp
  29. +5 −0 Source/WebCore/dom/Text.h
  30. +2 −2 Source/WebCore/dom/TreeScope.cpp
  31. +1 −0 Source/WebCore/html/CollectionCache.cpp
  32. +2 −0 Source/WebCore/html/CollectionCache.h
  33. +39 −4 Source/WebCore/html/HTMLAllCollection.cpp
  34. +4 −2 Source/WebCore/html/HTMLAllCollection.h
  35. +1 −0 Source/WebCore/html/HTMLAreaElement.cpp
  36. +1 −0 Source/WebCore/html/HTMLBRElement.cpp
  37. +1 −0 Source/WebCore/html/HTMLBaseElement.cpp
  38. +5 −0 Source/WebCore/html/HTMLCanvasElement.cpp
  39. +139 −87 Source/WebCore/html/HTMLCollection.cpp
  40. +10 −0 Source/WebCore/html/HTMLCollection.h
  41. +1 −0 Source/WebCore/html/HTMLDataGridCellElement.cpp
  42. +1 −0 Source/WebCore/html/HTMLDataGridColElement.cpp
  43. +0 −45 Source/WebCore/html/HTMLElement.cpp
  44. +0 −2 Source/WebCore/html/HTMLElement.h
  45. +1 −0 Source/WebCore/html/HTMLEmbedElement.cpp
  46. +1 −0 Source/WebCore/html/HTMLFrameElement.cpp
  47. +1 −0 Source/WebCore/html/HTMLHRElement.cpp
  48. +1 −0 Source/WebCore/html/HTMLImageElement.cpp
  49. +1 −0 Source/WebCore/html/HTMLInputElement.cpp
  50. +1 −0 Source/WebCore/html/HTMLLinkElement.cpp
  51. +1 −0 Source/WebCore/html/HTMLMetaElement.cpp
  52. +1 −0 Source/WebCore/html/HTMLParamElement.cpp
  53. +1 −0 Source/WebCore/html/HTMLSourceElement.cpp
  54. +1 −0 Source/WebCore/html/HTMLTableColElement.cpp
  55. +1 −1 Source/WebCore/html/HTMLTagNames.in
  56. +62 −0 Source/WebCore/html/HTMLWbrElement.cpp
  57. +50 −0 Source/WebCore/html/HTMLWbrElement.h
  58. +3 −3 Source/WebCore/rendering/svg/SVGShadowTreeElements.cpp
  59. +1 −3 Source/WebCore/rendering/svg/SVGShadowTreeElements.h
  60. +2 −2 Source/WebCore/svg/SVGElement.cpp
  61. +1 −1 Source/WebCore/svg/SVGElement.h
  62. +2 −2 Source/WebCore/svg/SVGGElement.cpp
  63. +1 −1 Source/WebCore/svg/SVGGElement.h
  64. +2 −2 Source/WebCore/svg/SVGStyledElement.cpp
  65. +1 −1 Source/WebCore/svg/SVGStyledElement.h
  66. +2 −2 Source/WebCore/svg/SVGStyledLocatableElement.cpp
  67. +1 −1 Source/WebCore/svg/SVGStyledLocatableElement.h
  68. +2 −2 Source/WebCore/svg/SVGStyledTransformableElement.cpp
  69. +1 −1 Source/WebCore/svg/SVGStyledTransformableElement.h
  70. +3 −2 Source/WebKit/android/jni/WebViewCore.cpp
@@ -71,8 +71,8 @@ class RopeImpl : public StringImplBase {
ALWAYS_INLINE void deref()
{
- m_refCountAndFlags -= s_refCountIncrement;
- if (!(m_refCountAndFlags & s_refCountMask))
+ --m_refCount;
+ if (!m_refCount)
destructNonRecursive();
}
@@ -86,7 +86,7 @@ class RopeImpl : public StringImplBase {
void destructNonRecursive();
void derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue);
- bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; }
+ bool hasOneRef() { return m_refCount == 1; }
unsigned m_size;
Fiber m_fibers[1];
@@ -57,7 +57,7 @@ namespace WTF {
ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }
- T* get() const { return m_ptr; }
+ ALWAYS_INLINE T* get() const { return m_ptr; }
void clear();
PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
@@ -343,7 +343,7 @@ AtomicString AtomicString::lower() const
{
// Note: This is a hot function in the Dromaeo benchmark.
StringImpl* impl = this->impl();
- if (UNLIKELY(!impl))
+ if (UNLIKELY(!impl) || impl->isLower())
return *this;
RefPtr<StringImpl> newImpl = impl->lower();
if (LIKELY(newImpl == impl))
@@ -58,7 +58,7 @@ class AtomicString {
operator const String&() const { return m_string; }
const String& string() const { return m_string; };
- AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
+ ALWAYS_INLINE AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
const UChar* characters() const { return m_string.characters(); }
unsigned length() const { return m_string.length(); }
@@ -148,7 +148,7 @@ SharedUChar* StringImpl::sharedBuffer()
if (ownership == BufferOwned) {
ASSERT(!m_sharedBuffer);
m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).leakRef();
- m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
+ m_bufferOwnership = BufferShared;
}
ASSERT(bufferOwnership() == BufferShared);
@@ -193,6 +193,8 @@ PassRefPtr<StringImpl> StringImpl::lower()
{
// Note: This is a hot function in the Dromaeo benchmark, specifically the
// no-op code path up through the first 'return' statement.
+ if (isLower())
+ return this;
// First scan the string for uppercase and non-ASCII characters:
UChar ored = 0;
@@ -205,8 +207,10 @@ PassRefPtr<StringImpl> StringImpl::lower()
}
// Nothing to do if the string is all ASCII with no uppercase.
- if (noUpper && !(ored & ~0x7F))
+ if (noUpper && !(ored & ~0x7F)) {
+ setIsLower(true);
return this;
+ }
if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
CRASH();
@@ -1060,7 +1064,7 @@ PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const Stri
data[length] = 0;
terminatedString->m_length--;
terminatedString->m_hash = string.m_hash;
- terminatedString->m_refCountAndFlags |= s_refCountFlagHasTerminatingNullCharacter;
+ terminatedString->m_hasTerminatingNullCharacter = true;
return terminatedString.release();
}
@@ -206,40 +206,29 @@ class StringImpl : public StringImplBase {
if (bufferOwnership() == BufferSubstring)
return m_substringBuffer->cost();
- if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) {
- m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost;
+ if (m_shouldReportCost) {
+ m_shouldReportCost = false;
return m_length;
}
return 0;
}
- bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; }
- void setIsIdentifier(bool isIdentifier)
- {
- ASSERT(!isStatic());
- if (isIdentifier)
- m_refCountAndFlags |= s_refCountFlagIsIdentifier;
- else
- m_refCountAndFlags &= ~s_refCountFlagIsIdentifier;
- }
+ bool isIdentifier() const { return m_identifier; }
+ void setIsIdentifier(bool isIdentifier) { ASSERT(!isStatic()); m_identifier = isIdentifier; }
- bool hasTerminatingNullCharacter() const { return m_refCountAndFlags & s_refCountFlagHasTerminatingNullCharacter; }
+ bool hasTerminatingNullCharacter() const { return m_hasTerminatingNullCharacter; }
- bool isAtomic() const { return m_refCountAndFlags & s_refCountFlagIsAtomic; }
- void setIsAtomic(bool isIdentifier)
- {
- ASSERT(!isStatic());
- if (isIdentifier)
- m_refCountAndFlags |= s_refCountFlagIsAtomic;
- else
- m_refCountAndFlags &= ~s_refCountFlagIsAtomic;
- }
+ bool isAtomic() const { return m_atomic; }
+ void setIsAtomic(bool isAtomic) { ASSERT(!isStatic()); m_atomic = isAtomic; }
+
+ bool isLower() const { return m_lower; }
+ void setIsLower(bool isLower) { m_lower = isLower; }
unsigned hash() const { if (!m_hash) m_hash = StringHasher::computeHash(m_data, m_length); return m_hash; }
unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
- ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }
- ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; }
+ ALWAYS_INLINE void deref() { --m_refCount; if (!m_refCount && !m_static) delete this; }
+ ALWAYS_INLINE bool hasOneRef() const { return (m_refCount == 1 && !m_static); }
static StringImpl* empty();
@@ -328,8 +317,8 @@ class StringImpl : public StringImplBase {
static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length);
- BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); }
- bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; }
+ BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_bufferOwnership); }
+ bool isStatic() const { return m_static; }
const UChar* m_data;
union {
void* m_buffer;
@@ -33,9 +33,9 @@ namespace WTF {
class StringImplBase {
WTF_MAKE_NONCOPYABLE(StringImplBase); WTF_MAKE_FAST_ALLOCATED;
public:
- bool isStringImpl() { return (m_refCountAndFlags & s_refCountInvalidForStringImpl) != s_refCountInvalidForStringImpl; }
+ bool isStringImpl() { return !(m_static && m_shouldReportCost); }
unsigned length() const { return m_length; }
- void ref() { m_refCountAndFlags += s_refCountIncrement; }
+ void ref() { ++m_refCount; }
protected:
enum BufferOwnership {
@@ -49,15 +49,29 @@ class StringImplBase {
StringImplBase() { }
StringImplBase(unsigned length, BufferOwnership ownership)
- : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership)
+ : m_lower(false)
+ , m_hasTerminatingNullCharacter(false)
+ , m_atomic(false)
+ , m_static(false)
+ , m_shouldReportCost(true)
+ , m_identifier(false)
+ , m_bufferOwnership(ownership)
+ , m_refCount(1)
, m_length(length)
{
ASSERT(isStringImpl());
}
enum StaticStringConstructType { ConstructStaticString };
StringImplBase(unsigned length, StaticStringConstructType)
- : m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagIsIdentifier | BufferOwned)
+ : m_lower(false)
+ , m_hasTerminatingNullCharacter(false)
+ , m_atomic(false)
+ , m_static(true)
+ , m_shouldReportCost(false)
+ , m_identifier(true)
+ , m_bufferOwnership(BufferOwned)
+ , m_refCount(0)
, m_length(length)
{
ASSERT(isStringImpl());
@@ -67,29 +81,28 @@ class StringImplBase {
// and sets the flags into a state marking the object as such.
enum NonStringImplConstructType { ConstructNonStringImpl };
StringImplBase(NonStringImplConstructType)
- : m_refCountAndFlags(s_refCountIncrement | s_refCountInvalidForStringImpl)
+ : m_lower(false)
+ , m_hasTerminatingNullCharacter(false)
+ , m_atomic(false)
+ , m_static(true)
+ , m_shouldReportCost(true)
+ , m_identifier(false)
+ , m_bufferOwnership(0)
+ , m_refCount(1)
, m_length(0)
{
ASSERT(!isStringImpl());
}
- // The bottom 7 bits hold flags, the top 25 bits hold the ref count.
- // When dereferencing StringImpls we check for the ref count AND the
- // static bit both being zero - static strings are never deleted.
- static const unsigned s_refCountMask = 0xFFFFFF80;
- static const unsigned s_refCountIncrement = 0x80;
- static const unsigned s_refCountFlagStatic = 0x40;
- static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x20;
- static const unsigned s_refCountFlagIsAtomic = 0x10;
- static const unsigned s_refCountFlagShouldReportedCost = 0x8;
- static const unsigned s_refCountFlagIsIdentifier = 0x4;
- static const unsigned s_refCountMaskBufferOwnership = 0x3;
- // An invalid permutation of flags (static & shouldReportedCost - static strings do not
- // set shouldReportedCost in the constructor, and this bit is only ever cleared, not set).
- // Used by "ConstructNonStringImpl" constructor, above.
- static const unsigned s_refCountInvalidForStringImpl = s_refCountFlagStatic | s_refCountFlagShouldReportedCost;
+ bool m_lower : 1;
+ bool m_hasTerminatingNullCharacter : 1;
+ bool m_atomic : 1;
+ bool m_static : 1;
+ bool m_shouldReportCost : 1;
+ bool m_identifier : 1;
+ unsigned m_bufferOwnership : 2;
+ unsigned m_refCount : 24;
- unsigned m_refCountAndFlags;
unsigned m_length;
};
@@ -123,7 +123,7 @@ class String {
bool isNull() const { return !m_impl; }
bool isEmpty() const { return !m_impl || !m_impl->length(); }
- StringImpl* impl() const { return m_impl.get(); }
+ ALWAYS_INLINE StringImpl* impl() const { return m_impl.get(); }
unsigned length() const
{
@@ -339,6 +339,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
html/HTMLParserErrorCodes.cpp \
html/HTMLTableRowsCollection.cpp \
html/HTMLViewSourceDocument.cpp \
+ html/HTMLWbrElement.cpp \
html/HiddenInputType.cpp \
html/ImageData.cpp \
html/ImageDocument.cpp \
@@ -7037,7 +7037,7 @@ void CSSStyleSelector::SelectorChecker::allVisitedStateChanged()
{
if (m_linksCheckedForVisitedState.isEmpty())
return;
- for (Node* node = m_document; node; node = node->traverseNextNode()) {
+ for (Node* node = m_document; node; node = node->traverseNextNodeFastPath()) {
if (node->isLink())
node->setNeedsStyleRecalc();
}
@@ -7047,7 +7047,7 @@ void CSSStyleSelector::SelectorChecker::visitedStateChanged(LinkHash visitedHash
{
if (!m_linksCheckedForVisitedState.contains(visitedHash))
return;
- for (Node* node = m_document; node; node = node->traverseNextNode()) {
+ for (Node* node = m_document; node; node = node->traverseNextNodeFastPath()) {
const AtomicString* attr = linkAttribute(node);
if (attr && visitedLinkHash(m_document->baseURL(), *attr) == visitedHash)
node->setNeedsStyleRecalc();
@@ -69,6 +69,8 @@ void Attr::createTextChild()
textNode->setParent(this);
setFirstChild(textNode.get());
setLastChild(textNode.get());
+ textNode->updateNextNode();
+ textNode->updatePreviousNode();
}
}
@@ -189,6 +189,7 @@ void CharacterData::updateRenderer(unsigned offsetOfReplacedData, unsigned lengt
void CharacterData::dispatchModifiedEvent(StringImpl* oldData)
{
+ updatePrevNextNodesInSubtree();
if (parentNode())
parentNode()->childrenChanged();
if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER))
@@ -27,19 +27,27 @@
namespace WebCore {
-ChildNodeList::ChildNodeList(PassRefPtr<Node> rootNode, DynamicNodeList::Caches* info)
- : DynamicNodeList(rootNode, info)
+ChildNodeList::ChildNodeList(PassRefPtr<Node> rootNode)
+ : DynamicNodeList(rootNode)
{
}
+ChildNodeList::~ChildNodeList()
+{
+ m_rootNode->removeCachedChildNodeList(this);
+}
+
unsigned ChildNodeList::length() const
{
if (m_caches->isLengthCacheValid)
return m_caches->cachedLength;
unsigned len = 0;
- for (Node* n = m_rootNode->firstChild(); n; n = n->nextSibling())
+ Vector<Node* >& cachedNodes = m_caches->cachedNodes;
+ for (Node* n = m_rootNode->firstChild(); n; n = n->nextSibling()) {
+ cachedNodes.append(n);
len++;
+ }
m_caches->cachedLength = len;
m_caches->isLengthCacheValid = true;
@@ -49,6 +57,9 @@ unsigned ChildNodeList::length() const
Node* ChildNodeList::item(unsigned index) const
{
+ if (m_caches->isLengthCacheValid && index < m_caches->cachedLength)
+ return m_caches->cachedNodes[index];
+
unsigned int pos = 0;
Node* n = m_rootNode->firstChild();
@@ -31,16 +31,18 @@ namespace WebCore {
class ChildNodeList : public DynamicNodeList {
public:
- static PassRefPtr<ChildNodeList> create(PassRefPtr<Node> rootNode, Caches* caches)
+ static PassRefPtr<ChildNodeList> create(PassRefPtr<Node> rootNode)
{
- return adoptRef(new ChildNodeList(rootNode, caches));
+ return adoptRef(new ChildNodeList(rootNode));
}
+ virtual ~ChildNodeList();
+
virtual unsigned length() const;
virtual Node* item(unsigned index) const;
protected:
- ChildNodeList(PassRefPtr<Node> rootNode, Caches*);
+ ChildNodeList(PassRefPtr<Node> rootNode);
virtual bool nodeMatches(Element*) const;
};
Oops, something went wrong.

0 comments on commit a78859f

Please sign in to comment.