Bug 1296509 - Optimize GetFlattenedTreeParent. r=smaug
authorBobby Holley <bobbyholley@gmail.com>
Thu, 18 Aug 2016 17:03:49 -0700
changeset 310471 4687780af322afe048863d5f0f943ec1ca4d7f9f
parent 310470 6c95e0617d78214306f30395f37b02d6577efa8f
child 310472 fe333162679eb3d446e3a17bd87c6b1b1557ffac
push id30585
push userryanvm@gmail.com
push dateMon, 22 Aug 2016 13:41:00 +0000
treeherdermozilla-central@194fe275b4e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1296509
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1296509 - Optimize GetFlattenedTreeParent. r=smaug We need to call it on some hot paths in stylo, and this allows us to do quick inline check before delegating to the slow path.
accessible/generic/Accessible.h
dom/base/FragmentOrElement.cpp
dom/base/nsContentUtils.cpp
dom/base/nsIContent.h
dom/base/nsIContentInlines.h
dom/base/nsINode.h
dom/events/EventStateManager.cpp
dom/html/HTMLLinkElement.cpp
dom/svg/SVGAnimationElement.cpp
dom/svg/SVGSVGElement.h
layout/base/RestyleTracker.h
layout/generic/nsFrame.cpp
layout/generic/nsPlaceholderFrame.cpp
layout/inspector/inDOMUtils.cpp
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -9,16 +9,17 @@
 #include "mozilla/a11y/AccTypes.h"
 #include "mozilla/a11y/RelationType.h"
 #include "mozilla/a11y/Role.h"
 #include "mozilla/a11y/States.h"
 
 #include "mozilla/UniquePtr.h"
 
 #include "nsIContent.h"
+#include "nsIContentInlines.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 #include "nsRect.h"
 
 struct nsRoleMapEntry;
 
 struct nsRect;
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -146,20 +146,25 @@ nsIContent::FindFirstNonChromeOnlyAccess
       // Oops, this function signature allows casting const to
       // non-const.  (Then again, so does GetChildAt(0)->GetParent().)
       return const_cast<nsIContent*>(content);
     }
   }
   return nullptr;
 }
 
-nsIContent*
-nsIContent::GetFlattenedTreeParent() const
+nsINode*
+nsIContent::GetFlattenedTreeParentNodeInternal() const
 {
-  nsIContent* parent = GetParent();
+  nsINode* parentNode = GetParentNode();
+  if (!parentNode || !parentNode->IsContent()) {
+    MOZ_ASSERT(!parentNode || parentNode == OwnerDoc());
+    return parentNode;
+  }
+  nsIContent* parent = parentNode->AsContent();
 
   if (parent && nsContentUtils::HasDistributedChildren(parent) &&
       nsContentUtils::IsInSameAnonymousTree(parent, this)) {
     // This node is distributed to insertion points, thus we
     // need to consult the destination insertion points list to
     // figure out where this node was inserted in the flattened tree.
     // It may be the case that |parent| distributes its children
     // but the child does not match any insertion points, thus
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -102,16 +102,17 @@
 #include "nsIAddonPolicyService.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsICategoryManager.h"
 #include "nsIChannelEventSink.h"
 #include "nsICharsetDetectionObserver.h"
 #include "nsIChromeRegistry.h"
 #include "nsIConsoleService.h"
 #include "nsIContent.h"
+#include "nsIContentInlines.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIContentSink.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMDocument.h"
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -714,23 +714,25 @@ public:
   /**
    * Sets the insertion parent element of the XBL binding.
    *
    * @param aContent The insertion parent element.
    */
   virtual void SetXBLInsertionParent(nsIContent* aContent) = 0;
 
   /**
-   * Returns the content node that is the parent of this node in the flattened
-   * tree. For nodes that are not filtered into an insertion point, this
-   * simply returns their DOM parent in the original DOM tree.
-   *
-   * @return the flattened tree parent
+   * Same as GetFlattenedTreeParentNode, but returns null if the parent is
+   * non-nsIContent.
    */
-  nsIContent *GetFlattenedTreeParent() const;
+  inline nsIContent *GetFlattenedTreeParent() const;
+
+  /**
+   * Helper method, which we leave public so that it's accessible from nsINode.
+   */
+  nsINode *GetFlattenedTreeParentNodeInternal() const;
 
   /**
    * Gets the custom element data used by web components custom element.
    * Custom element data is created at the first attempt to enqueue a callback.
    *
    * @return The custom element data or null if none.
    */
   virtual mozilla::dom::CustomElementData *GetCustomElementData() const = 0;
--- a/dom/base/nsIContentInlines.h
+++ b/dom/base/nsIContentInlines.h
@@ -28,10 +28,44 @@ inline mozilla::dom::ShadowRoot* nsICont
 {
   if (!IsElement()) {
     return nullptr;
   }
 
   return AsElement()->FastGetShadowRoot();
 }
 
+inline nsINode* nsINode::GetFlattenedTreeParentNode() const
+{
+  nsINode* parent = GetParentNode();
+
+  // Try to short-circuit past the complicated and not-exactly-fast logic for
+  // computing the flattened parent.
+  //
+  // There are three cases where we need might something other than parentNode:
+  //   (1) The node is an explicit child of an XBL-bound element, re-bound
+  //       to an XBL insertion point.
+  //   (2) The node is a top-level element in a shadow tree, whose flattened
+  //       parent is the host element (as opposed to the actual parent which
+  //       is the shadow root).
+  //   (3) The node is an explicit child of an element with a shadow root,
+  //       re-bound to an insertion point.
+  bool needSlowCall = HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
+                      IsInShadowTree() ||
+                      (parent && parent->IsContent() &&
+                       parent->AsContent()->GetShadowRoot());
+  if (MOZ_UNLIKELY(needSlowCall)) {
+    MOZ_ASSERT(IsContent());
+    return AsContent()->GetFlattenedTreeParentNodeInternal();
+  }
+
+  return parent;
+}
+
+inline nsIContent*
+nsIContent::GetFlattenedTreeParent() const
+{
+  nsINode* parent = GetFlattenedTreeParentNode();
+  return (parent && parent->IsContent()) ? parent->AsContent() : nullptr;
+}
+
 
 #endif // nsIContentInlines_h
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -924,16 +924,26 @@ public:
    * @return the parent node
    */
   nsINode* GetParentNode() const
   {
     return mParent;
   }
 
   /**
+   * Returns the node that is the parent of this node in the flattened
+   * tree. This differs from the normal parent if the node is filtered
+   * into an insertion point, or if the node is a direct child of a
+   * shadow root.
+   *
+   * @return the flattened tree parent
+   */
+  inline nsINode* GetFlattenedTreeParentNode() const;
+
+  /**
    * Get the parent nsINode for this node if it is an Element.
    * @return the parent node
    */
   mozilla::dom::Element* GetParentElement() const
   {
     return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
   }
 
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -24,16 +24,17 @@
 
 #include "ContentEventHandler.h"
 #include "IMEContentObserver.h"
 #include "WheelHandlingHelper.h"
 
 #include "nsCOMPtr.h"
 #include "nsFocusManager.h"
 #include "nsIContent.h"
+#include "nsIContentInlines.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsIWidget.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsGkAtoms.h"
 #include "nsIFormControl.h"
 #include "nsIComboboxControlFrame.h"
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/HTMLLinkElementBinding.h"
 #include "nsContentUtils.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsDOMTokenList.h"
+#include "nsIContentInlines.h"
 #include "nsIDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsINode.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIURL.h"
 #include "nsPIDOMWindow.h"
 #include "nsReadableUtils.h"
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGAnimationElement.h"
 #include "mozilla/dom/SVGSVGElement.h"
 #include "nsSMILTimeContainer.h"
 #include "nsSMILAnimationController.h"
 #include "nsSMILAnimationFunction.h"
 #include "nsContentUtils.h"
+#include "nsIContentInlines.h"
 #include "nsIURI.h"
 #include "prtime.h"
 
 namespace mozilla {
 namespace dom {
 
 //----------------------------------------------------------------------
 // nsISupports methods
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGSVGElement_h
 #define mozilla_dom_SVGSVGElement_h
 
 #include "mozilla/dom/FromParser.h"
 #include "nsAutoPtr.h"
+#include "nsIContentInlines.h"
 #include "nsISVGPoint.h"
 #include "nsSVGEnum.h"
 #include "nsSVGLength2.h"
 #include "SVGGraphicsElement.h"
 #include "SVGImageContext.h"
 #include "nsSVGViewBox.h"
 #include "SVGPreserveAspectRatio.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -11,16 +11,17 @@
 #ifndef mozilla_RestyleTracker_h
 #define mozilla_RestyleTracker_h
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/OverflowChangedTracker.h"
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
 #include "nsContainerFrame.h"
+#include "nsIContentInlines.h"
 #include "mozilla/SplayTree.h"
 #include "mozilla/RestyleLogging.h"
 #include "GeckoProfiler.h"
 #include "mozilla/Maybe.h"
 
 #if defined(MOZ_ENABLE_PROFILER_SPS)
 #include "ProfilerBacktrace.h"
 #endif
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/Sprintf.h"
 
 #include "nsCOMPtr.h"
 #include "nsFrameList.h"
 #include "nsPlaceholderFrame.h"
 #include "nsIContent.h"
+#include "nsIContentInlines.h"
 #include "nsContentUtils.h"
 #include "nsCSSPseudoElements.h"
 #include "nsIAtom.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsStyleContext.h"
 #include "nsTableWrapperFrame.h"
 #include "nsView.h"
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -13,16 +13,17 @@
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "nsDisplayList.h"
 #include "nsFrameManager.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
 #include "nsIFrameInlines.h"
+#include "nsIContentInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 nsIFrame*
 NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
                        nsFrameState aTypeBit)
 {
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -9,16 +9,17 @@
 #include "inDOMUtils.h"
 #include "inLayoutUtils.h"
 
 #include "nsAutoPtr.h"
 #include "nsIServiceManager.h"
 #include "nsISupportsArray.h"
 #include "nsString.h"
 #include "nsIStyleSheetLinkingElement.h"
+#include "nsIContentInlines.h"
 #include "nsIDOMElement.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMCharacterData.h"
 #include "nsRuleNode.h"
 #include "nsIStyleRule.h"
 #include "mozilla/css/StyleRule.h"