- Revision
- 105885
- Author
- [email protected]
- Date
- 2012-01-25 09:23:48 -0800 (Wed, 25 Jan 2012)
Log Message
https://bugs.webkit.org/show_bug.cgi?id=65377
Skip the entire node when it is right to do so, instead of stepping
through every character, so we save CPU time on checking every position
unnecessarily.
Patch by Yong Li <[email protected]> on 2012-01-25
Reviewed by Darin Adler.
Source/WebCore:
Test: perf/selection-skip-hidden-node.html
* dom/Position.cpp:
(WebCore::Position::upstream):
(WebCore::Position::downstream):
* dom/PositionIterator.cpp:
(WebCore::PositionIterator::moveToLeafNodeStart):
(WebCore::PositionIterator::moveToLeafNodeEnd):
* dom/PositionIterator.h:
* editing/htmlediting.cpp:
(WebCore::nextCandidate):
(WebCore::nextVisuallyDistinctCandidate):
(WebCore::previousCandidate):
(WebCore::previousVisuallyDistinctCandidate):
LayoutTests:
* perf/selection-skip-hidden-node-expected.txt: Added.
* perf/selection-skip-hidden-node.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (105884 => 105885)
--- trunk/LayoutTests/ChangeLog 2012-01-25 17:21:33 UTC (rev 105884)
+++ trunk/LayoutTests/ChangeLog 2012-01-25 17:23:48 UTC (rev 105885)
@@ -1,3 +1,15 @@
+2012-01-25 Yong Li <[email protected]>
+
+ https://bugs.webkit.org/show_bug.cgi?id=65377
+ Skip the entire node when it is right to do so, instead of stepping
+ through every character, so we save CPU time on checking every position
+ unnecessarily.
+
+ Reviewed by Darin Adler.
+
+ * perf/selection-skip-hidden-node-expected.txt: Added.
+ * perf/selection-skip-hidden-node.html: Added.
+
2012-01-25 NĂ¡ndor Huszka <[email protected]>
[WK2] WebKitTestRunner needs layoutTestController.setPopupBlockingEnabled
Added: trunk/LayoutTests/perf/selection-skip-hidden-node-expected.txt (0 => 105885)
--- trunk/LayoutTests/perf/selection-skip-hidden-node-expected.txt (rev 0)
+++ trunk/LayoutTests/perf/selection-skip-hidden-node-expected.txt 2012-01-25 17:23:48 UTC (rev 105885)
@@ -0,0 +1,3 @@
+Tests that traversing hidden text nodes is constant time.
+PASS
+
Added: trunk/LayoutTests/perf/selection-skip-hidden-node.html (0 => 105885)
--- trunk/LayoutTests/perf/selection-skip-hidden-node.html (rev 0)
+++ trunk/LayoutTests/perf/selection-skip-hidden-node.html 2012-01-25 17:23:48 UTC (rev 105885)
@@ -0,0 +1,34 @@
+<body>
+<script src=""
+<div id="HiddenText"></div><p id="VisibleText">Visible Text</p>
+<script>
+var hiddenDiv = document.getElementById('HiddenText');
+hiddenDiv.style.display = 'none';
+
+var longText = "super long long text";
+while (longText.length < 16)
+ longText = longText + longText;
+
+function setupFunction(magnitude)
+{
+ while (hiddenDiv.hasChildNodes())
+ hiddenDiv.removeChild(hiddenDiv.lastChild);
+
+ var text = longText;
+ for (var i = 0; i < magnitude; ++i)
+ text += longText;
+
+ var textNode = document.createTextNode(text);
+ hiddenDiv.appendChild(textNode);
+}
+
+function test(magnitude)
+{
+ window.getSelection().setPosition(document.body, 0);
+}
+
+Magnitude.description("Tests that traversing hidden text nodes is constant time.");
+Magnitude.run(setupFunction, test, Magnitude.CONSTANT);
+
+</script>
+</body>
Modified: trunk/Source/WebCore/ChangeLog (105884 => 105885)
--- trunk/Source/WebCore/ChangeLog 2012-01-25 17:21:33 UTC (rev 105884)
+++ trunk/Source/WebCore/ChangeLog 2012-01-25 17:23:48 UTC (rev 105885)
@@ -1,3 +1,27 @@
+2012-01-25 Yong Li <[email protected]>
+
+ https://bugs.webkit.org/show_bug.cgi?id=65377
+ Skip the entire node when it is right to do so, instead of stepping
+ through every character, so we save CPU time on checking every position
+ unnecessarily.
+
+ Reviewed by Darin Adler.
+
+ Test: perf/selection-skip-hidden-node.html
+
+ * dom/Position.cpp:
+ (WebCore::Position::upstream):
+ (WebCore::Position::downstream):
+ * dom/PositionIterator.cpp:
+ (WebCore::PositionIterator::moveToLeafNodeStart):
+ (WebCore::PositionIterator::moveToLeafNodeEnd):
+ * dom/PositionIterator.h:
+ * editing/htmlediting.cpp:
+ (WebCore::nextCandidate):
+ (WebCore::nextVisuallyDistinctCandidate):
+ (WebCore::previousCandidate):
+ (WebCore::previousVisuallyDistinctCandidate):
+
2012-01-25 Kaustubh Atrawalkar <[email protected]>
Remove unnecessary member variable from PluginView.
Modified: trunk/Source/WebCore/dom/Position.cpp (105884 => 105885)
--- trunk/Source/WebCore/dom/Position.cpp 2012-01-25 17:21:33 UTC (rev 105884)
+++ trunk/Source/WebCore/dom/Position.cpp 2012-01-25 17:23:48 UTC (rev 105885)
@@ -615,8 +615,10 @@
// skip position in unrendered or invisible node
RenderObject* renderer = currentNode->renderer();
- if (!renderer || renderer->style()->visibility() != VISIBLE)
+ if (!renderer || renderer->style()->visibility() != VISIBLE) {
+ currentPos.moveToLeafNodeStart();
continue;
+ }
if (rule == CanCrossEditingBoundary && boundaryCrossed) {
lastVisible = currentPos;
@@ -636,6 +638,7 @@
if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
if (currentPos.atEndOfNode())
return positionAfterNode(currentNode);
+ currentPos.moveToLeafNodeStart();
continue;
}
@@ -747,8 +750,10 @@
// skip position in unrendered or invisible node
RenderObject* renderer = currentNode->renderer();
- if (!renderer || renderer->style()->visibility() != VISIBLE)
+ if (!renderer || renderer->style()->visibility() != VISIBLE) {
+ currentPos.moveToLeafNodeEnd();
continue;
+ }
if (rule == CanCrossEditingBoundary && boundaryCrossed) {
lastVisible = currentPos;
@@ -763,6 +768,7 @@
if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
+ currentPos.moveToLeafNodeEnd();
continue;
}
Modified: trunk/Source/WebCore/dom/PositionIterator.cpp (105884 => 105885)
--- trunk/Source/WebCore/dom/PositionIterator.cpp 2012-01-25 17:21:33 UTC (rev 105884)
+++ trunk/Source/WebCore/dom/PositionIterator.cpp 2012-01-25 17:23:48 UTC (rev 105885)
@@ -177,4 +177,20 @@
return false;
}
+void PositionIterator::moveToLeafNodeStart()
+{
+ if (!m_anchorNode || m_nodeAfterPositionInAnchor || m_anchorNode->hasChildNodes())
+ return;
+
+ m_offsetInAnchor = 0;
+}
+
+void PositionIterator::moveToLeafNodeEnd()
+{
+ if (!m_anchorNode || m_nodeAfterPositionInAnchor || m_anchorNode->hasChildNodes())
+ return;
+
+ m_offsetInAnchor = lastOffsetForEditing(m_anchorNode);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/PositionIterator.h (105884 => 105885)
--- trunk/Source/WebCore/dom/PositionIterator.h 2012-01-25 17:21:33 UTC (rev 105884)
+++ trunk/Source/WebCore/dom/PositionIterator.h 2012-01-25 17:23:48 UTC (rev 105885)
@@ -64,6 +64,9 @@
bool atEndOfNode() const;
bool isCandidate() const;
+ void moveToLeafNodeStart();
+ void moveToLeafNodeEnd();
+
private:
Node* m_anchorNode;
Node* m_nodeAfterPositionInAnchor; // If this is non-null, m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode;
Modified: trunk/Source/WebCore/editing/htmlediting.cpp (105884 => 105885)
--- trunk/Source/WebCore/editing/htmlediting.cpp 2012-01-25 17:21:33 UTC (rev 105884)
+++ trunk/Source/WebCore/editing/htmlediting.cpp 2012-01-25 17:23:48 UTC (rev 105885)
@@ -209,6 +209,9 @@
p.increment();
if (p.isCandidate())
return p;
+ RenderObject* renderer = p.node() ? p.node()->renderer() : 0;
+ if (!renderer || renderer->style()->visibility() != VISIBLE)
+ p.moveToLeafNodeEnd();
}
return Position();
}
@@ -221,6 +224,9 @@
p = p.next(Character);
if (p.isCandidate() && p.downstream() != downstreamStart)
return p;
+ RenderObject* renderer = p.deprecatedNode() ? p.deprecatedNode()->renderer() : 0;
+ if (!renderer || renderer->style()->visibility() != VISIBLE)
+ p.moveToOffset(lastOffsetForEditing(p.deprecatedNode()));
}
return Position();
}
@@ -232,6 +238,9 @@
p.decrement();
if (p.isCandidate())
return p;
+ RenderObject* renderer = p.node() ? p.node()->renderer() : 0;
+ if (!renderer || renderer->style()->visibility() != VISIBLE)
+ p.moveToLeafNodeStart();
}
return Position();
}
@@ -244,6 +253,9 @@
p = p.previous(Character);
if (p.isCandidate() && p.downstream() != downstreamStart)
return p;
+ RenderObject* renderer = p.deprecatedNode() ? p.deprecatedNode()->renderer() : 0;
+ if (!renderer || renderer->style()->visibility() != VISIBLE)
+ p.moveToOffset(0);
}
return Position();
}