Commit 6e5aa3f8 authored by dsmith@webkit.org's avatar dsmith@webkit.org
Browse files

WebCore:

2008-06-26  David Smith  <catfish.man@gmail.com>

        Reviewed by Sam Weinig.
        
        https://bugs.webkit.org/show_bug.cgi?id=19002
        
        Optimize simple id selectors in querySelector/querySelectorAll. 
        ~4.4x speedup on the 4 subtests of http://webkit.org/perf/slickspeed/ that it applies to.

        * dom/Document.h:
        (WebCore::Document::containsMultipleElementsWithId): Added to allow optimizing the common case of no duplicates
        * dom/Node.cpp:
        (WebCore::Node::querySelector): Uses getElementById instead of DOM traversal where possible now
        * dom/SelectorNodeList.cpp:
        (WebCore::createSelectorNodeList): Uses getElementById instead of DOM traversal where possible now

LayoutTests:

2008-06-26  David Smith  <catfish.man@gmail.com>

        Reviewed by Sam Weinig.
        
        https://bugs.webkit.org/show_bug.cgi?id=19002
        
        Optimize simple id selectors in querySelector/querySelectorAll. 
        ~4.4x speedup on the 4 subtests of http://webkit.org/perf/slickspeed/ that it applies to.

        * fast/dom/SelectorAPI/dumpNodeList-expected.txt:
        * fast/dom/SelectorAPI/dumpNodeList.html: Add tests for finding ids not in the document, and finding duplicate ids



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@34823 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c13cd254
2008-06-26 David Smith <catfish.man@gmail.com>
Reviewed by Sam Weinig.
https://bugs.webkit.org/show_bug.cgi?id=19002
Optimize simple id selectors in querySelector/querySelectorAll.
~4.4x speedup on the 4 subtests of http://webkit.org/perf/slickspeed/ that it applies to.
* fast/dom/SelectorAPI/dumpNodeList-expected.txt:
* fast/dom/SelectorAPI/dumpNodeList.html: Add tests for finding ids not in the document, and finding duplicate ids
2008-06-26 Dan Bernstein <mitz@apple.com>
 
Reviewed by Darin Adler.
......@@ -6,6 +6,8 @@ line 4
line 5
[object HTMLDivElement], length: 1
length: 0
[object HTMLDivElement], [object HTMLDivElement], length: 2
[object HTMLDivElement], [object HTMLDivElement], [object HTMLDivElement], [object HTMLParagraphElement], length: 4
[object HTMLDivElement], [object HTMLDivElement], [object HTMLDivElement], [object HTMLDivElement], [object HTMLParagraphElement], length: 5
Error: SYNTAX_ERR: DOM Exception 12
......@@ -13,8 +15,11 @@ Error: SYNTAX_ERR: DOM Exception 12
Error: SYNTAX_ERR: DOM Exception 12
Error: SYNTAX_ERR: DOM Exception 12
Error: SYNTAX_ERR: DOM Exception 12
[object HTMLDivElement], [object HTMLDivElement], [object HTMLDivElement], length: 3
length: 0
[object HTMLDivElement], length: 1
length: 0
[object HTMLDivElement], [object HTMLDivElement], length: 2
[object HTMLDivElement], [object HTMLParagraphElement], length: 2
[object HTMLDivElement], [object HTMLParagraphElement], length: 2
Error: SYNTAX_ERR: DOM Exception 12
......@@ -23,6 +28,8 @@ Error: SYNTAX_ERR: DOM Exception 12
Error: SYNTAX_ERR: DOM Exception 12
Error: SYNTAX_ERR: DOM Exception 12
[object HTMLDivElement]
TypeError: Null value
[object HTMLDivElement]
[object HTMLDivElement]
[object HTMLDivElement]
Error: SYNTAX_ERR: DOM Exception 12
......@@ -32,6 +39,8 @@ Error: SYNTAX_ERR: DOM Exception 12
Error: SYNTAX_ERR: DOM Exception 12
TypeError: Null value
[object HTMLDivElement]
TypeError: Null value
[object HTMLDivElement]
[object HTMLDivElement]
[object HTMLDivElement]
Error: SYNTAX_ERR: DOM Exception 12
......
<html>
<body>
<div class="one">Line 1<div class="two">Line 2</div><p>Line <i>3</i></p></div>
<div id="test" class="one two"><div id="test2" class="one two">line 4</div><p class="two">line 5</p></div>
<div id="test" class="one two"><div id="dupe"></div><div id="dupe"></div>
<div id="test2" class="one two">line 4</div><p class="two">line 5</p></div>
<p><ol id="console"></ol></p>
<script type="text/javascript">
if (window.layoutTestController)
......@@ -22,10 +23,10 @@
NodeList.prototype.dump = function()
{
var result = "";
var i = 0;
for (; i < this.length; i++)
var length = this.length;
for (var i = 0; i < length; i++)
result += this[i] + ", ";
result += "length: " + i;
result += "length: " + length;
return result;
}
......@@ -33,6 +34,8 @@
var elm = document.getElementById("test");
try { log(document.querySelectorAll("#test").dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll("#notthere").dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll("#dupe").dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll(".two").dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll(".one, .two").dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll("@font-face").dump()); } catch (e) { log(e) }
......@@ -40,9 +43,12 @@
try { log(document.querySelectorAll().dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll(null).dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll(undefined).dump()); } catch (e) { log(e) }
try { log(document.querySelectorAll("#test>div").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll("#test").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll("#test2").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll("#test2").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll("#notthere").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll("#dupe").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll(".two").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll(".one, .two").dump()); } catch (e) { log(e) }
try { log(elm.querySelectorAll("@font-face").dump()); } catch (e) { log(e) }
......@@ -52,6 +58,8 @@
try { log(elm.querySelectorAll(undefined).dump()); } catch (e) { log(e) }
try { log(document.querySelector("#test").dump()); } catch (e) { log(e) }
try { log(document.querySelector("#notthere").dump()); } catch (e) { log(e) }
try { log(document.querySelector("#dupe").dump()); } catch (e) { log(e) }
try { log(document.querySelector(".two").dump()); } catch (e) { log(e) }
try { log(document.querySelector(".one, .two").dump()); } catch (e) { log(e) }
try { log(document.querySelector("@font-face").dump()); } catch (e) { log(e) }
......@@ -62,6 +70,8 @@
try { log(elm.querySelector("#test").dump()); } catch (e) { log(e) }
try { log(elm.querySelector("#test2").dump()); } catch (e) { log(e) }
try { log(elm.querySelector("#notthere").dump()); } catch (e) { log(e) }
try { log(elm.querySelector("#dupe").dump()); } catch (e) { log(e) }
try { log(elm.querySelector(".two").dump()); } catch (e) { log(e) }
try { log(elm.querySelector(".one, .two").dump()); } catch (e) { log(e) }
try { log(elm.querySelector("@font-face").dump()); } catch (e) { log(e) }
......
2008-06-26 David Smith <catfish.man@gmail.com>
Reviewed by Sam Weinig.
https://bugs.webkit.org/show_bug.cgi?id=19002
Optimize simple id selectors in querySelector/querySelectorAll.
~4.4x speedup on the 4 subtests of http://webkit.org/perf/slickspeed/ that it applies to.
* dom/Document.h:
(WebCore::Document::containsMultipleElementsWithId): Added to allow optimizing the common case of no duplicates
* dom/Node.cpp:
(WebCore::Node::querySelector): Uses getElementById instead of DOM traversal where possible now
* dom/SelectorNodeList.cpp:
(WebCore::createSelectorNodeList): Uses getElementById instead of DOM traversal where possible now
2008-06-26 Dan Bernstein <mitz@apple.com>
 
Reviewed by Darin Adler.
......@@ -223,6 +223,7 @@ public:
PassRefPtr<Element> createElement(const QualifiedName&, bool createdByParser, ExceptionCode& ec);
Element* getElementById(const AtomicString&) const;
bool hasElementWithId(AtomicStringImpl* id) const;
bool containsMultipleElementsWithId(const AtomicString& elementId) { return m_duplicateIds.contains(elementId.impl()); }
Element* elementFromPoint(int x, int y) const;
String readyState() const;
......@@ -753,7 +754,7 @@ public:
// Extension for manipulating canvas drawing contexts for use in CSS
CanvasRenderingContext2D* getCSSCanvasContext(const String& type, const String& name, int width, int height);
HTMLCanvasElement* getCSSCanvasElement(const String& name);
protected:
Document(Frame*, bool isXHTML);
......
......@@ -1234,6 +1234,13 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode&
CSSStyleSelector::SelectorChecker selectorChecker(document(), !document()->inCompatMode());
CSSSelector* querySelector = static_cast<CSSStyleRule*>(rule.get())->selector();
if (!querySelector->next() && querySelector->m_match == CSSSelector::Id) {
Element* element = document()->getElementById(querySelector->m_value);
if (element && (isDocumentNode() || element->isDescendantOf(this)))
return element;
return 0;
}
// FIXME: We can speed this up by implementing caching similar to the one use by getElementById
for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
if (n->isElementNode()) {
......
......@@ -40,18 +40,28 @@ PassRefPtr<StaticNodeList> createSelectorNodeList(PassRefPtr<Node> rootNode, CSS
{
Vector<RefPtr<Node> > nodes;
Document* document = rootNode->document();
CSSStyleSelector::SelectorChecker selectorChecker(document, !document->inCompatMode());
for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode.get())) {
if (n->isElementNode()) {
Element* element = static_cast<Element*>(n);
for (CSSSelector* selector = querySelector; selector; selector = selector->next()) {
if (selectorChecker.checkSelector(selector, element)) {
nodes.append(n);
break;
AtomicString selectorValue = querySelector->m_value;
if (!querySelector->next() && querySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(selectorValue)) {
Element* element = document->getElementById(selectorValue);
if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode.get())))
nodes.append(element);
} else {
CSSStyleSelector::SelectorChecker selectorChecker(document, !document->inCompatMode());
for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode.get())) {
if (n->isElementNode()) {
Element* element = static_cast<Element*>(n);
for (CSSSelector* selector = querySelector; selector; selector = selector->next()) {
if (selectorChecker.checkSelector(selector, element)) {
nodes.append(n);
break;
}
}
}
}
}
return StaticNodeList::adopt(nodes);
}
......
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