From d463cb5f0374bfc7c62ae5f1c89edd3ca35084e5 Mon Sep 17 00:00:00 2001
From: Olli Pettay <Olli.Pettay@helsinki.fi>
Date: Thu, 24 Sep 2015 03:53:31 +0300
Subject: [PATCH] Bug 1204669 - optimize out hashtable lookups caused by extra
 GetPrototypeBinding call, r=bz,waldo, a=al

--HG--
extra : source : 91657db26f49f885f2338cb8c9302cdf18999f1f
---
 dom/xbl/nsXBLPrototypeBinding.h | 9 +++++++--
 dom/xbl/nsXBLService.cpp        | 6 +++---
 mfbt/WeakPtr.h                  | 8 +++++++-
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/dom/xbl/nsXBLPrototypeBinding.h b/dom/xbl/nsXBLPrototypeBinding.h
index be2cb5a..1aaa07f 100644
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -17,6 +17,7 @@
 #include "nsXBLProtoImplMethod.h"
 #include "nsXBLPrototypeHandler.h"
 #include "nsXBLPrototypeResources.h"
+#include "mozilla/WeakPtr.h"
 
 class nsIAtom;
 class nsIContent;
@@ -35,9 +36,12 @@ class CSSStyleSheet;
 // Instances of this class are owned by the nsXBLDocumentInfo object returned
 // by XBLDocumentInfo().  Consumers who want to refcount things should refcount
 // that.
-class nsXBLPrototypeBinding final
+class nsXBLPrototypeBinding final :
+  public mozilla::SupportsWeakPtr<nsXBLPrototypeBinding>
 {
 public:
+  MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsXBLPrototypeBinding)
+
   nsIContent* GetBindingElement() const { return mBinding; }
   void SetBindingElement(nsIContent* aElement);
 
@@ -289,7 +293,8 @@ protected:
   nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
                                    // the constructor, and the destructor).
 
-  nsXBLPrototypeBinding* mBaseBinding; // Weak.  The docinfo will own our base binding.
+  // Weak.  The docinfo will own our base binding.
+  mozilla::WeakPtr<nsXBLPrototypeBinding> mBaseBinding;
   bool mInheritStyle;
   bool mCheckedBaseProto;
   bool mKeyHandlersRegistered;
diff --git a/dom/xbl/nsXBLService.cpp b/dom/xbl/nsXBLService.cpp
index 2204520..978c6fc 100644
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -732,7 +732,8 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
   if (!docInfo)
     return NS_ERROR_FAILURE;
 
-  nsXBLPrototypeBinding* protoBinding = docInfo->GetPrototypeBinding(ref);
+  WeakPtr<nsXBLPrototypeBinding> protoBinding =
+    docInfo->GetPrototypeBinding(ref);
 
   if (!protoBinding) {
 #ifdef DEBUG
@@ -783,7 +784,7 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> baseBindingURI;
-  nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype();
+  WeakPtr<nsXBLPrototypeBinding> baseProto = protoBinding->GetBasePrototype();
   if (baseProto) {
     baseBindingURI = baseProto->BindingURI();
   }
@@ -828,7 +829,6 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
 
   if (!aPeekOnly) {
     // Make a new binding
-    protoBinding = docInfo->GetPrototypeBinding(ref);
     NS_ENSURE_STATE(protoBinding);
     nsXBLBinding *newBinding = new nsXBLBinding(protoBinding);
 
diff --git a/mfbt/WeakPtr.h b/mfbt/WeakPtr.h
index 6e5de43..22ba20e 100644
--- a/mfbt/WeakPtr.h
+++ b/mfbt/WeakPtr.h
@@ -172,7 +172,13 @@ public:
 
   WeakPtr& operator=(T* aOther)
   {
-    return *this = aOther->SelfReferencingWeakPtr();
+    if (aOther) {
+      *this = aOther->SelfReferencingWeakPtr();
+    } else if (!mRef || mRef->get()) {
+      // Ensure that mRef is dereferenceable in the uninitialized state.
+      mRef = new WeakReference(nullptr);
+    }
+    return *this;
   }
 
   MOZ_IMPLICIT WeakPtr(T* aOther)
-- 
2.5.0

