Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(503)

Unified Diff: third_party/WebKit/Source/core/input/PointerEventManager.cpp

Issue 1904453003: Change finding common ancestor from O(n^2) to O(n) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Applying the comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/input/PointerEventManager.cpp
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
index 9f8556979c8d409b9338455f071d73f776cfc2b2..12bea1e551c5859df2148eff59bdf2ce4df9760a 100644
--- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
@@ -79,6 +79,42 @@ PlatformMouseEvent mouseEventWithRegion(Node* node, const PlatformMouseEvent& mo
return newMouseEvent;
}
+void buildAncestorChainsAndFindCommonAncestors(
+ EventTarget* exitedTarget, EventTarget* enteredTarget,
bokan 2016/04/21 21:38:29 Seems like these can't be null? If that's true, ma
Navid Zolghadr 2016/04/21 23:40:14 No. They can be null. The isInDocument checks for
bokan 2016/04/22 00:52:54 Got it, ok, fine as they are (if possible though,
Navid Zolghadr 2016/04/22 17:04:12 This turned out to be harder than I thought. Marki
bokan 2016/04/22 17:30:52 Nah, if it's more trouble lgtm as-is. Our code is
+ HeapVector<Member<Node>, 20> &exitedAncestors,
+ HeapVector<Member<Node>, 20> &enteredAncestors,
+ size_t& exitedAncestorsCommonParentIndex,
+ size_t& enteredAncestorsCommonParentIndex)
bokan 2016/04/21 21:38:28 Output parameters should be passed by pointer.
Navid Zolghadr 2016/04/21 23:40:14 You mean like size_t* and HeapVector<Member<Node>
bokan 2016/04/22 00:52:54 Yup, see the bit about output params here: https:/
Navid Zolghadr 2016/04/22 17:04:12 Done.
+{
+ // Index 0 element in the ancestors arrays will be the corresponding
+ // target. So the root of their document will be their last element.
+
bokan 2016/04/21 21:38:29 I see you check if exitedTarget == enteredTarget b
Navid Zolghadr 2016/04/21 23:40:14 I don't think that is needed. This function doesn'
bokan 2016/04/22 00:52:54 Whoops, yah, you're right. That's fine.
+ if (isInDocument(exitedTarget)) {
+ Node* exitedNode = exitedTarget->toNode();
bokan 2016/04/21 21:38:28 Either DCHECK that exitedNode != nullptr (if indee
Navid Zolghadr 2016/04/21 23:40:14 Neither the DCHECK nor the behavior of handling wh
bokan 2016/04/22 00:52:54 Acknowledged.
Navid Zolghadr 2016/04/22 17:04:12 Done.
+ exitedNode->updateDistribution();
+ for (Node* node = exitedNode; node; node = FlatTreeTraversal::parent(*node))
+ exitedAncestors.append(node);
+ }
+
+ if (isInDocument(enteredTarget)) {
+ Node* enteredNode = enteredTarget->toNode();
+ enteredNode->updateDistribution();
bokan 2016/04/21 21:38:29 Question: what does updateDistribution do?
Navid Zolghadr 2016/04/21 23:40:14 To be honest with you, I'm not sure myself. From t
bokan 2016/04/22 00:52:54 Hmm, I've never seen it before. But I can see it w
+ for (Node* node = enteredNode; node; node = FlatTreeTraversal::parent(*node))
+ enteredAncestors.append(node);
+ }
+
+ exitedAncestorsCommonParentIndex = exitedAncestors.size();
+ enteredAncestorsCommonParentIndex = enteredAncestors.size();
bokan 2016/04/21 21:38:29 One more suggested DCHECK here :), exitedAncestors
Navid Zolghadr 2016/04/21 23:40:14 That's not right. They might be from different doc
bokan 2016/04/22 00:52:54 That's what I'm getting at, you have no way of dis
Navid Zolghadr 2016/04/22 01:46:13 No. That is not the case. Here is an example if we
bokan 2016/04/22 01:50:47 Bah, I'm not having a good day...you're totally ri
+ while (exitedAncestorsCommonParentIndex > 0
+ && enteredAncestorsCommonParentIndex > 0) {
+ if (exitedAncestors[exitedAncestorsCommonParentIndex-1]
+ != enteredAncestors[enteredAncestorsCommonParentIndex-1])
+ break;
+ exitedAncestorsCommonParentIndex--;
+ enteredAncestorsCommonParentIndex--;
+ }
+}
+
} // namespace
WebInputEventResult PointerEventManager::dispatchPointerEvent(
@@ -180,21 +216,12 @@ void PointerEventManager::sendNodeTransitionEvents(
}
// Create lists of all exited/entered ancestors, locate the common ancestor
- HeapVector<Member<Node>, 32> exitedAncestors;
- HeapVector<Member<Node>, 32> enteredAncestors;
- if (isInDocument(exitedTarget)) {
- Node* exitedNode = exitedTarget->toNode();
- exitedNode->updateDistribution();
- for (Node* node = exitedNode; node; node = FlatTreeTraversal::parent(*node))
- exitedAncestors.append(node);
- }
-
- if (isInDocument(enteredTarget)) {
- Node* enteredNode = enteredTarget->toNode();
- enteredNode->updateDistribution();
- for (Node* node = enteredNode; node; node = FlatTreeTraversal::parent(*node))
- enteredAncestors.append(node);
- }
+ // Based on httparchive, in more than 97% cases the depth of DOM is less
bokan 2016/04/21 21:38:29 Doesn't this mean that in 3% of cases we'll incur
Navid Zolghadr 2016/04/21 23:40:14 I don't have a strong answer here. I had it at 32.
bokan 2016/04/22 00:52:54 Heap allocations can be fairly expensive and unpre
+ // than 20.
+ HeapVector<Member<Node>, 20> exitedAncestors;
+ HeapVector<Member<Node>, 20> enteredAncestors;
+ size_t exitedAncestorsCommonParentIndex = 0;
+ size_t enteredAncestorsCommonParentIndex = 0;
// A note on mouseenter and mouseleave: These are non-bubbling events, and they are dispatched if there
// is a capturing event handler on an ancestor or a normal event handler on the element itself. This special
@@ -210,22 +237,10 @@ void PointerEventManager::sendNodeTransitionEvents(
//
// TODO(mustaq): Confirm spec conformance, double-check with other browsers.
- size_t numExitedAncestors = exitedAncestors.size();
- size_t numEnteredAncestors = enteredAncestors.size();
-
- size_t exitedAncestorIndex = numExitedAncestors;
- size_t enteredAncestorIndex = numEnteredAncestors;
- for (size_t i = 0; i < numExitedAncestors; i++) {
- for (size_t j = 0; j < numEnteredAncestors; j++) {
- if (exitedAncestors[i] == enteredAncestors[j]) {
- exitedAncestorIndex = i;
- enteredAncestorIndex = j;
- break;
- }
- }
- if (exitedAncestorIndex < exitedAncestors.size())
- break;
- }
+ buildAncestorChainsAndFindCommonAncestors(
+ exitedTarget, enteredTarget,
+ exitedAncestors, enteredAncestors,
+ exitedAncestorsCommonParentIndex, enteredAncestorsCommonParentIndex);
bool exitedNodeHasCapturingAncestor = false;
for (size_t j = 0; j < exitedAncestors.size(); j++) {
@@ -236,7 +251,7 @@ void PointerEventManager::sendNodeTransitionEvents(
}
// Dispatch pointerleave/mouseleave events, in child-to-parent order.
- for (size_t j = 0; j < exitedAncestorIndex; j++) {
+ for (size_t j = 0; j < exitedAncestorsCommonParentIndex; j++) {
if (!sendMouseEvent) {
dispatchPointerEvent(exitedAncestors[j].get(),
m_pointerEventFactory.createPointerTransitionEvent(
@@ -272,7 +287,7 @@ void PointerEventManager::sendNodeTransitionEvents(
}
// Dispatch pointerenter/mouseenter events, in parent-to-child order.
- for (size_t i = enteredAncestorIndex; i > 0; i--) {
+ for (size_t i = enteredAncestorsCommonParentIndex; i > 0; i--) {
if (!sendMouseEvent) {
dispatchPointerEvent(enteredAncestors[i-1].get(),
m_pointerEventFactory.createPointerTransitionEvent(
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698