Bug 796061 - Part 2: Remove mInsertionParentTable from nsBindingManager. r=mrbkap
authorWilliam Chen <wchen@mozilla.com>
Wed, 17 Jul 2013 09:05:06 -0700
changeset 138872 d810dcc0726f6516571dfa26657b7add26fe4659
parent 138871 5e3d564cd1b551eda17fcb7056a91db5dc866306
child 138873 df259aaab707393909d5bc212ef2f160568db44d
push id31159
push userwchen@mozilla.com
push dateWed, 17 Jul 2013 16:05:53 +0000
treeherdermozilla-inbound@d810dcc0726f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs796061
milestone25.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 796061 - Part 2: Remove mInsertionParentTable from nsBindingManager. r=mrbkap
content/base/public/FragmentOrElement.h
content/base/public/nsIContent.h
content/base/src/FragmentOrElement.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericDOMDataNode.h
content/xbl/src/XBLChildrenElement.h
content/xbl/src/nsBindingManager.cpp
content/xbl/src/nsBindingManager.h
content/xbl/src/nsXBLBinding.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/inspector/src/inDOMUtils.cpp
layout/inspector/src/inLayoutUtils.cpp
layout/inspector/src/inLayoutUtils.h
--- a/content/base/public/FragmentOrElement.h
+++ b/content/base/public/FragmentOrElement.h
@@ -213,16 +213,18 @@ public:
   virtual nsresult AppendText(const PRUnichar* aBuffer, uint32_t aLength,
                               bool aNotify) MOZ_OVERRIDE;
   virtual bool TextIsOnlyWhitespace() MOZ_OVERRIDE;
   virtual void AppendTextTo(nsAString& aResult) MOZ_OVERRIDE;
   virtual nsIContent *GetBindingParent() const MOZ_OVERRIDE;
   virtual nsXBLBinding *GetXBLBinding() const MOZ_OVERRIDE;
   virtual void SetXBLBinding(nsXBLBinding* aBinding,
                              nsBindingManager* aOldBindingManager = nullptr) MOZ_OVERRIDE;
+  virtual nsIContent *GetXBLInsertionParent() const;
+  virtual void SetXBLInsertionParent(nsIContent* aContent);
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
 
   virtual void DestroyContent() MOZ_OVERRIDE;
   virtual void SaveSubtreeState() MOZ_OVERRIDE;
 
   virtual const nsAttrValue* DoGetClasses() const MOZ_OVERRIDE;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
 
@@ -362,16 +364,21 @@ public:
      * An object implementing the .classList property for this element.
      */
     nsRefPtr<nsDOMTokenList> mClassList;
 
     /**
      * XBL binding installed on the element.
      */
     nsRefPtr<nsXBLBinding> mXBLBinding;
+
+    /**
+     * XBL binding installed on the lement.
+     */
+    nsCOMPtr<nsIContent> mXBLInsertionParent;
   };
 
 protected:
   // Override from nsINode
   virtual nsINode::nsSlots* CreateSlots() MOZ_OVERRIDE;
 
   nsDOMSlots *DOMSlots()
   {
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -635,16 +635,31 @@ public:
    * @param aOldBindingManager The old binding manager that contains
    *                           this content if this content was adopted
    *                           to another document.
    */
   virtual void SetXBLBinding(nsXBLBinding* aBinding,
                              nsBindingManager* aOldBindingManager = nullptr) = 0;
 
   /**
+   * Gets the insertion parent element of the XBL binding.
+   * The insertion parent is our one true parent in the transformed DOM.
+   *
+   * @return the insertion parent element.
+   */
+  virtual nsIContent *GetXBLInsertionParent() const = 0;
+
+  /**
+   * 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
    */
   nsIContent *GetFlattenedTreeParent() const;
 
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -145,18 +145,17 @@ nsIContent::FindFirstNonChromeOnlyAccess
   }
   return nullptr;
 }
 
 nsIContent*
 nsIContent::GetFlattenedTreeParent() const
 {
   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    nsIContent* parent = OwnerDoc()->BindingManager()->
-      GetInsertionParent(const_cast<nsIContent*>(this));
+    nsIContent* parent = GetXBLInsertionParent();
     if (parent) {
       return parent;
     }
   }
 
   return GetParent();
 }
 
@@ -563,16 +562,19 @@ FragmentOrElement::nsDOMSlots::Traverse(
   if (aIsXUL) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
     cb.NoteXPCOMChild(mControllers);
   }
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLBinding");
   cb.NoteNativeChild(mXBLBinding, NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
 
+  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
+  cb.NoteXPCOMChild(mXBLInsertionParent.get());
+
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
   cb.NoteXPCOMChild(mClassList.get());
 }
 
 void
@@ -582,16 +584,17 @@ FragmentOrElement::nsDOMSlots::Unlink(bo
   mSMILOverrideStyle = nullptr;
   if (mAttributeMap) {
     mAttributeMap->DropReference();
     mAttributeMap = nullptr;
   }
   if (aIsXUL)
     NS_IF_RELEASE(mControllers);
   mXBLBinding = nullptr;
+  mXBLInsertionParent = nullptr;
   mChildrenList = nullptr;
   mUndoManager = nullptr;
   if (mClassList) {
     mClassList->DropReference();
     mClassList = nullptr;
   }
 }
 
@@ -801,18 +804,17 @@ nsIContent::PreHandleEvent(nsEventChainP
     if (content && content->GetBindingParent() == parent) {
       aVisitor.mEventTargetAtParent = parent;
     }
   }
 
   // check for an anonymous parent
   // XXX XBL2/sXBL issue
   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    nsIContent* insertionParent = OwnerDoc()->BindingManager()->
-      GetInsertionParent(this);
+    nsIContent* insertionParent = GetXBLInsertionParent();
     NS_ASSERTION(!(aVisitor.mEventTargetAtParent && insertionParent &&
                    aVisitor.mEventTargetAtParent != insertionParent),
                  "Retargeting and having insertion parent!");
     if (insertionParent) {
       parent = insertionParent;
     }
   }
 
@@ -938,16 +940,39 @@ FragmentOrElement::SetXBLBinding(nsXBLBi
     slots->mXBLBinding = nullptr;
     bindingManager->RemoveBoundContent(this);
     if (oldBinding) {
       oldBinding->SetBoundElement(nullptr);
     }
   }
 }
 
+nsIContent*
+FragmentOrElement::GetXBLInsertionParent() const
+{
+  if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+    nsDOMSlots *slots = GetExistingDOMSlots();
+    if (slots) {
+      return slots->mXBLInsertionParent;
+    }
+  }
+
+  return nullptr;
+}
+
+void
+FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
+{
+  nsDOMSlots *slots = DOMSlots();
+  if (aContent) {
+    SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
+  }
+  slots->mXBLInsertionParent = aContent;
+}
+
 nsresult
 FragmentOrElement::InsertChildAt(nsIContent* aKid,
                                 uint32_t aIndex,
                                 bool aNotify)
 {
   NS_PRECONDITION(aKid, "null ptr");
 
   return doInsertChildAt(aKid, aIndex, aNotify, mAttrsAndChildren);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3562,18 +3562,17 @@ nsContentUtils::HasMutationListeners(nsI
   while (aNode) {
     nsEventListenerManager* manager = aNode->GetListenerManager(false);
     if (manager && manager->HasMutationListeners()) {
       return true;
     }
 
     if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
       nsIContent* content = static_cast<nsIContent*>(aNode);
-      nsIContent* insertionParent =
-        doc->BindingManager()->GetInsertionParent(content);
+      nsIContent* insertionParent = content->GetXBLInsertionParent();
       if (insertionParent) {
         aNode = insertionParent;
         continue;
       }
     }
     aNode = aNode->GetParentNode();
   }
 
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -81,21 +81,31 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   // Always need to traverse script objects, so do that before we check
   // if we're uncollectable.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 
+  nsDataSlots *slots = tmp->GetExistingDataSlots();
+  if (slots) {
+    slots->Traverse(cb);
+  }
+
   tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
   nsINode::Unlink(tmp);
+
+  nsDataSlots *slots = tmp->GetExistingDataSlots();
+  if (slots) {
+    slots->Unlink();
+  }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericDOMDataNode)
   NS_INTERFACE_MAP_ENTRY(nsIContent)
   NS_INTERFACE_MAP_ENTRY(nsINode)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
@@ -644,16 +654,39 @@ nsGenericDOMDataNode::GetXBLBinding() co
 }
 
 void
 nsGenericDOMDataNode::SetXBLBinding(nsXBLBinding* aBinding,
                                     nsBindingManager* aOldBindingManager)
 {
 }
 
+nsIContent *
+nsGenericDOMDataNode::GetXBLInsertionParent() const
+{
+  if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+    nsDataSlots *slots = GetExistingDataSlots();
+    if (slots) {
+      return slots->mXBLInsertionParent;
+    }
+  }
+
+  return nullptr;
+}
+
+void
+nsGenericDOMDataNode::SetXBLInsertionParent(nsIContent* aContent)
+{
+  nsDataSlots *slots = DataSlots();
+  if (aContent) {
+    SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
+  }
+  slots->mXBLInsertionParent = aContent;
+}
+
 bool
 nsGenericDOMDataNode::IsNodeOfType(uint32_t aFlags) const
 {
   return !(aFlags & ~(eCONTENT | eDATA_NODE));
 }
 
 void
 nsGenericDOMDataNode::SaveSubtreeState()
@@ -689,16 +722,29 @@ nsGenericDOMDataNode::IsLink(nsIURI** aU
 }
 
 nsINode::nsSlots*
 nsGenericDOMDataNode::CreateSlots()
 {
   return new nsDataSlots();
 }
 
+void
+nsGenericDOMDataNode::nsDataSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
+{
+  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
+  cb.NoteXPCOMChild(mXBLInsertionParent.get());
+}
+
+void
+nsGenericDOMDataNode::nsDataSlots::Unlink()
+{
+  mXBLInsertionParent = nullptr;
+}
+
 //----------------------------------------------------------------------
 
 // Implementation of the nsIDOMText interface
 
 nsresult
 nsGenericDOMDataNode::SplitData(uint32_t aOffset, nsIContent** aReturn,
                                 bool aCloneAfterOriginal)
 {
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -139,16 +139,18 @@ public:
   virtual void List(FILE* out, int32_t aIndent) const MOZ_OVERRIDE;
   virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const MOZ_OVERRIDE;
 #endif
 
   virtual nsIContent *GetBindingParent() const MOZ_OVERRIDE;
   virtual nsXBLBinding *GetXBLBinding() const MOZ_OVERRIDE;
   virtual void SetXBLBinding(nsXBLBinding* aBinding,
                              nsBindingManager* aOldBindingManager = nullptr) MOZ_OVERRIDE;
+  virtual nsIContent *GetXBLInsertionParent() const;
+  virtual void SetXBLInsertionParent(nsIContent* aContent);
   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
   virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE;
 
   virtual nsIAtom* DoGetID() const MOZ_OVERRIDE;
   virtual const nsAttrValue* DoGetClasses() const MOZ_OVERRIDE;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
@@ -226,21 +228,29 @@ protected:
   {
   public:
     nsDataSlots()
       : nsINode::nsSlots(),
         mBindingParent(nullptr)
     {
     }
 
+    void Traverse(nsCycleCollectionTraversalCallback &cb);
+    void Unlink();
+
     /**
      * The nearest enclosing content node with a binding that created us.
      * @see nsIContent::GetBindingParent
      */
     nsIContent* mBindingParent;  // [Weak]
+
+    /**
+     * @see nsIContent::GetXBLInsertionParent
+     */
+    nsCOMPtr<nsIContent> mXBLInsertionParent;
   };
 
   // Override from nsINode
   virtual nsINode::nsSlots* CreateSlots() MOZ_OVERRIDE;
 
   nsDataSlots* DataSlots()
   {
     return static_cast<nsDataSlots*>(Slots());
--- a/content/xbl/src/XBLChildrenElement.h
+++ b/content/xbl/src/XBLChildrenElement.h
@@ -45,71 +45,68 @@ public:
   virtual nsIAtom* DoGetID() const;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult);
 
-  void AppendInsertedChild(nsIContent* aChild,
-                           nsBindingManager* aBindingManager)
+  void AppendInsertedChild(nsIContent* aChild)
   {
     mInsertedChildren.AppendElement(aChild);
-    aBindingManager->SetInsertionParent(aChild, GetParent());
+    aChild->SetXBLInsertionParent(GetParent());
   }
 
-  void InsertInsertedChildAt(nsIContent* aChild,
-                             uint32_t aIndex,
-                             nsBindingManager* aBindingManager)
+  void InsertInsertedChildAt(nsIContent* aChild, uint32_t aIndex)
   {
     mInsertedChildren.InsertElementAt(aIndex, aChild);
-    aBindingManager->SetInsertionParent(aChild, GetParent());
+    aChild->SetXBLInsertionParent(GetParent());
   }
 
   void RemoveInsertedChild(nsIContent* aChild)
   {
     // Can't use this assertion as we cheat for dynamic insertions and
     // only insert in the innermost insertion point.
     //NS_ASSERTION(mInsertedChildren.Contains(aChild),
     //             "Removing child that's not there");
     mInsertedChildren.RemoveElement(aChild);
   }
 
   void ClearInsertedChildren()
   {
     mInsertedChildren.Clear();
   }
 
-  void ClearInsertedChildrenAndInsertionParents(nsBindingManager* aBindingManager)
+  void ClearInsertedChildrenAndInsertionParents()
   {
     for (uint32_t c = 0; c < mInsertedChildren.Length(); ++c) {
-      aBindingManager->SetInsertionParent(mInsertedChildren[c], nullptr);
+      mInsertedChildren[c]->SetXBLInsertionParent(nullptr);
     }
     mInsertedChildren.Clear();
   }
 
-  void MaybeSetupDefaultContent(nsBindingManager* aBindingManager)
+  void MaybeSetupDefaultContent()
   {
     if (!HasInsertedChildren()) {
       for (nsIContent* child = static_cast<nsINode*>(this)->GetFirstChild();
            child;
            child = child->GetNextSibling()) {
-        aBindingManager->SetInsertionParent(child, GetParent());
+        child->SetXBLInsertionParent(GetParent());
       }
     }
   }
 
-  void MaybeRemoveDefaultContent(nsBindingManager* aBindingManager)
+  void MaybeRemoveDefaultContent()
   {
     if (!HasInsertedChildren()) {
       for (nsIContent* child = static_cast<nsINode*>(this)->GetFirstChild();
            child;
            child = child->GetNextSibling()) {
-        aBindingManager->SetInsertionParent(child, nullptr);
+        child->SetXBLInsertionParent(nullptr);
       }
     }
   }
 
   uint32_t InsertedChildrenLength()
   {
     return mInsertedChildren.Length();
   }
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -192,20 +192,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     tmp->mBoundContentSet.Clear();
 
   if (tmp->mDocumentTable.IsInitialized())
     tmp->mDocumentTable.Clear();
 
   if (tmp->mLoadingDocTable.IsInitialized())
     tmp->mLoadingDocTable.Clear();
 
-  if (tmp->mInsertionParentTable.ops)
-    PL_DHashTableFinish(&(tmp->mInsertionParentTable));
-  tmp->mInsertionParentTable.ops = nullptr;
-
   if (tmp->mWrapperTable.ops)
     PL_DHashTableFinish(&(tmp->mWrapperTable));
   tmp->mWrapperTable.ops = nullptr;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttachedStack)
 
   if (tmp->mProcessAttachedQueueEvent) {
     tmp->mProcessAttachedQueueEvent->Revoke();
@@ -258,28 +254,23 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBindi
 
 // Constructors/Destructors
 nsBindingManager::nsBindingManager(nsIDocument* aDocument)
   : mProcessingAttachedStack(false),
     mDestroyed(false),
     mAttachedStackSizeOnOutermost(0),
     mDocument(aDocument)
 {
-  mInsertionParentTable.ops = nullptr;
   mWrapperTable.ops = nullptr;
 }
 
 nsBindingManager::~nsBindingManager(void)
 {
   mDestroyed = true;
 
-  NS_ASSERTION(!mInsertionParentTable.ops || !mInsertionParentTable.entryCount,
-               "Insertion parent table isn't empty!");
-  if (mInsertionParentTable.ops)
-    PL_DHashTableFinish(&mInsertionParentTable);
   if (mWrapperTable.ops)
     PL_DHashTableFinish(&mWrapperTable);
 }
 
 nsXBLBinding*
 nsBindingManager::GetBindingWithContent(nsIContent* aContent)
 {
   nsXBLBinding* binding = aContent ? aContent->GetXBLBinding() : nullptr;
@@ -302,37 +293,16 @@ nsBindingManager::RemoveBoundContent(nsI
   if (mBoundContentSet.IsInitialized()) {
     mBoundContentSet.RemoveEntry(aContent);
   }
 
   // The death of the bindings means the death of the JS wrapper.
   SetWrappedJS(aContent, nullptr);
 }
 
-nsIContent*
-nsBindingManager::GetInsertionParent(nsIContent* aContent)
-{ 
-  if (mInsertionParentTable.ops) {
-    return static_cast<nsIContent*>
-                      (LookupObject(mInsertionParentTable, aContent));
-  }
-
-  return nullptr;
-}
-
-nsresult
-nsBindingManager::SetInsertionParent(nsIContent* aContent, nsIContent* aParent)
-{
-  if (mDestroyed) {
-    return NS_OK;
-  }
-
-  return SetOrRemoveObject(mInsertionParentTable, aContent, aParent);
-}
-
 nsIXPConnectWrappedJS*
 nsBindingManager::GetWrappedJS(nsIContent* aContent)
 { 
   if (mWrapperTable.ops) {
     return static_cast<nsIXPConnectWrappedJS*>(LookupObject(mWrapperTable, aContent));
   }
 
   return nullptr;
@@ -360,17 +330,17 @@ nsBindingManager::RemovedFromDocumentInt
   nsRefPtr<nsXBLBinding> binding = aContent->GetXBLBinding();
   if (binding) {
     binding->PrototypeBinding()->BindingDetached(binding->GetBoundElement());
     binding->ChangeDocument(aOldDocument, nullptr);
     aContent->SetXBLBinding(nullptr, this);
   }
 
   // Clear out insertion parents and content lists.
-  SetInsertionParent(aContent, nullptr);
+  aContent->SetXBLInsertionParent(nullptr);
 }
 
 nsIAtom*
 nsBindingManager::ResolveTag(nsIContent* aContent, int32_t* aNameSpaceID)
 {
   nsXBLBinding *binding = aContent->GetXBLBinding();
 
   if (binding) {
@@ -950,18 +920,17 @@ void
 nsBindingManager::AppendAllSheets(nsTArray<nsCSSStyleSheet*>& aArray)
 {
   if (mBoundContentSet.IsInitialized()) {
     mBoundContentSet.EnumerateEntries(EnumAppendAllSheets, &aArray);
   }
 }
 
 static void
-InsertAppendedContent(nsBindingManager* aManager,
-                      XBLChildrenElement* aPoint,
+InsertAppendedContent(XBLChildrenElement* aPoint,
                       nsIContent* aFirstNewContent)
 {
   uint32_t insertionIndex;
   if (nsIContent* prevSibling = aFirstNewContent->GetPreviousSibling()) {
     // If we have a previous sibling, then it must already be in aPoint. Find
     // it and insert after it.
     insertionIndex = aPoint->IndexOfInsertedChild(prevSibling);
     MOZ_ASSERT(insertionIndex != aPoint->NoIndex);
@@ -974,17 +943,17 @@ InsertAppendedContent(nsBindingManager* 
     // keep track of the right index to insert into.
     insertionIndex = aPoint->mInsertedChildren.Length();
   }
 
   // Do the inserting.
   for (nsIContent* currentChild = aFirstNewContent;
        currentChild;
        currentChild = currentChild->GetNextSibling()) {
-    aPoint->InsertInsertedChildAt(currentChild, insertionIndex++, aManager);
+    aPoint->InsertInsertedChildAt(currentChild, insertionIndex++);
   }
 }
 
 void
 nsBindingManager::ContentAppended(nsIDocument* aDocument,
                                   nsIContent* aContainer,
                                   nsIContent* aFirstNewContent,
                                   int32_t     aNewIndexInContainer)
@@ -1026,20 +995,20 @@ nsBindingManager::ContentAppended(nsIDoc
 
     // Even though we're in ContentAppended, nested insertion points force us
     // to deal with this append as an insertion except in the outermost
     // binding.
     if (first) {
       first = false;
       for (nsIContent* child = aFirstNewContent; child;
            child = child->GetNextSibling()) {
-        point->AppendInsertedChild(child, this);
+        point->AppendInsertedChild(child);
       }
     } else {
-      InsertAppendedContent(this, point, aFirstNewContent);
+      InsertAppendedContent(point, aFirstNewContent);
     }
 
     nsIContent* newParent = point->GetParent();
     if (newParent == parent) {
       break;
     }
     parent = newParent;
   } while (parent);
@@ -1060,17 +1029,17 @@ nsBindingManager::ContentInserted(nsIDoc
 
 void
 nsBindingManager::ContentRemoved(nsIDocument* aDocument,
                                  nsIContent* aContainer,
                                  nsIContent* aChild,
                                  int32_t aIndexInContainer,
                                  nsIContent* aPreviousSibling)
 {
-  SetInsertionParent(aChild, nullptr);
+  aChild->SetXBLInsertionParent(nullptr);
 
   XBLChildrenElement* point = nullptr;
   nsIContent* parent = aContainer;
   do {
     nsXBLBinding* binding = GetBindingWithContent(parent);
     if (!binding) {
       // If aChild is XBL content, it might have <xbl:children> elements
       // somewhere under it. We need to inform those elements that they're no
@@ -1099,17 +1068,17 @@ nsBindingManager::ContentRemoved(nsIDocu
     parent = newParent;
   } while (parent);
 }
 
 void
 nsBindingManager::ClearInsertionPointsRecursively(nsIContent* aContent)
 {
   if (aContent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
-    static_cast<XBLChildrenElement*>(aContent)->ClearInsertedChildrenAndInsertionParents(this);
+    static_cast<XBLChildrenElement*>(aContent)->ClearInsertedChildrenAndInsertionParents();
   }
 
   uint32_t childCount = aContent->GetChildCount();
   for (uint32_t c = 0; c < childCount; c++) {
     ClearInsertionPointsRecursively(aContent->GetChildAt(c));
   }
 }
 
@@ -1119,53 +1088,43 @@ nsBindingManager::DropDocumentReference(
   mDestroyed = true;
 
   // Make sure to not run any more XBL constructors
   mProcessingAttachedStack = true;
   if (mProcessAttachedQueueEvent) {
     mProcessAttachedQueueEvent->Revoke();
   }
 
-  if (mInsertionParentTable.ops)
-    PL_DHashTableFinish(&(mInsertionParentTable));
-  mInsertionParentTable.ops = nullptr;
-
   if (mBoundContentSet.IsInitialized()) {
     mBoundContentSet.Clear();
   }
 
   mDocument = nullptr;
 }
 
 void
 nsBindingManager::Traverse(nsIContent *aContent,
                            nsCycleCollectionTraversalCallback &cb)
 {
-  if (!aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
-    return;
-  }
-
-  nsISupports *value;
-  if (mInsertionParentTable.ops &&
-      (value = LookupObject(mInsertionParentTable, aContent))) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mInsertionParentTable key");
-    cb.NoteXPCOMChild(aContent);
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mInsertionParentTable value");
-    cb.NoteXPCOMChild(value);
-  }
-
-  // XXXbz how exactly would NODE_MAY_BE_IN_BINDING_MNGR end up on non-elements?
-  if (!aContent->IsElement()) {
+  if (!aContent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
+      !aContent->IsElement()) {
+    // Don't traverse if content is not in this binding manager.
+    // We also don't traverse non-elements because there should not
+    // be bindings (checking the flag alone is not sufficient because
+    // the flag is also set on children of insertion points that may be
+    // non-elements).
     return;
   }
 
   if (mBoundContentSet.Contains(aContent)) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mBoundContentSet entry");
     cb.NoteXPCOMChild(aContent);
   }
+
+  nsISupports *value;
   if (mWrapperTable.ops &&
       (value = LookupObject(mWrapperTable, aContent))) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mWrapperTable key");
     cb.NoteXPCOMChild(aContent);
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mWrapperTable value");
     cb.NoteXPCOMChild(value);
   }
 }
@@ -1222,17 +1181,17 @@ nsBindingManager::HandleChildInsertion(n
       // based on whether we're appending or inserting.
       uint32_t pointIndex = point->IndexOfInsertedChild(currentSibling);
       if (pointIndex != point->NoIndex) {
         index = pointIndex + 1;
         break;
       }
     }
 
-    point->InsertInsertedChildAt(aChild, index, this);
+    point->InsertInsertedChildAt(aChild, index);
 
     nsIContent* newParent = point->GetParent();
     if (newParent == parent) {
       break;
     }
 
     parent = newParent;
   }
--- a/content/xbl/src/nsBindingManager.h
+++ b/content/xbl/src/nsBindingManager.h
@@ -43,19 +43,16 @@ public:
   nsBindingManager(nsIDocument* aDocument);
   ~nsBindingManager();
 
   nsXBLBinding* GetBindingWithContent(nsIContent* aContent);
 
   void AddBoundContent(nsIContent* aContent);
   void RemoveBoundContent(nsIContent* aContent);
 
-  nsIContent* GetInsertionParent(nsIContent* aContent);
-  nsresult SetInsertionParent(nsIContent* aContent, nsIContent* aResult);
-
   /**
    * Notify the binding manager that an element
    * has been removed from its document,
    * so that it can update any bindings or
    * nsIAnonymousContentCreator-created anonymous
    * content that may depend on the document.
    * @param aContent the element that's being moved
    * @param aOldDocument the old document in which the
@@ -160,21 +157,16 @@ protected:
   // Post an event to process the attached queue.
   void PostProcessAttachedQueueEvent();
 
 // MEMBER VARIABLES
 protected: 
   // A set of nsIContent that currently have a binding installed.
   nsTHashtable<nsRefPtrHashKey<nsIContent> > mBoundContentSet;
 
-  // A mapping from nsIContent* to nsIContent*.  The insertion parent
-  // is our one true parent in the transformed DOM.  This gives us a
-  // more-or-less O(1) way of obtaining our transformed parent.
-  PLDHashTable mInsertionParentTable;
-
   // A mapping from nsIContent* to nsIXPWrappedJS* (an XPConnect
   // wrapper for JS objects).  For XBL bindings that implement XPIDL
   // interfaces, and that get referred to from C++, this table caches
   // the XPConnect wrapper for the binding.  By caching it, I control
   // its lifetime, and I prevent a re-wrap of the same script object
   // (in the case where multiple bindings in an XBL inheritance chain
   // both implement an XPIDL interface).
   PLDHashTable mWrapperTable;
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -318,18 +318,16 @@ nsXBLBinding::GenerateAnonymousContent()
   // Find out if we're really building kids or if we're just
   // using the attribute-setting shorthand hack.
   uint32_t contentCount = content->GetChildCount();
 
   // Plan to build the content by default.
   bool hasContent = (contentCount > 0);
   if (hasContent) {
     nsIDocument* doc = mBoundElement->OwnerDoc();
-    
-    nsBindingManager *bindingManager = doc->BindingManager();
 
     nsCOMPtr<nsINode> clonedNode;
     nsCOMArray<nsINode> nodesWithProperties;
     nsNodeUtils::Clone(content, true, doc->NodeInfoManager(),
                        nodesWithProperties, getter_AddRefs(clonedNode));
     mContent = clonedNode->AsElement();
 
     // Search for <xbl:children> elements in the XBL content. In the presence
@@ -350,27 +348,27 @@ nsXBLBinding::GenerateAnonymousContent()
     // pointer which would make the GetNextNode call above fail
     InstallAnonymousContent(mContent, mBoundElement,
                             mPrototypeBinding->ChromeOnlyContent());
 
     // Insert explicit children into insertion points
     if (mDefaultInsertionPoint && mInsertionPoints.IsEmpty()) {
       ExplicitChildIterator iter(mBoundElement);
       for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
-        mDefaultInsertionPoint->AppendInsertedChild(child, bindingManager);
+        mDefaultInsertionPoint->AppendInsertedChild(child);
       }
     } else {
       // It is odd to come into this code if mInsertionPoints is not empty, but
       // we need to make sure to do the compatibility hack below if the bound
       // node has any non <xul:template> or <xul:observer> children.
       ExplicitChildIterator iter(mBoundElement);
       for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
         XBLChildrenElement* point = FindInsertionPointForInternal(child);
         if (point) {
-          point->AppendInsertedChild(child, bindingManager);
+          point->AppendInsertedChild(child);
         } else {
           nsINodeInfo *ni = child->NodeInfo();
           if (ni->NamespaceID() != kNameSpaceID_XUL ||
               (!ni->Equals(nsGkAtoms::_template) &&
                !ni->Equals(nsGkAtoms::observer))) {
             // Compatibility hack. For some reason the original XBL
             // implementation dropped the content of a binding if any child of
             // the bound element didn't match any of the <children> in the
@@ -387,20 +385,20 @@ nsXBLBinding::GenerateAnonymousContent()
             return;
           }
         }
       }
     }
 
     // Set binding parent on default content if need
     if (mDefaultInsertionPoint) {
-      mDefaultInsertionPoint->MaybeSetupDefaultContent(bindingManager);
+      mDefaultInsertionPoint->MaybeSetupDefaultContent();
     }
     for (uint32_t i = 0; i < mInsertionPoints.Length(); ++i) {
-      mInsertionPoints[i]->MaybeSetupDefaultContent(bindingManager);
+      mInsertionPoints[i]->MaybeSetupDefaultContent();
     }
 
     mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
   }
 
   // Always check the content element for potential attributes.
   // This shorthand hack always happens, even when we didn't
   // build anonymous content.
@@ -697,18 +695,17 @@ nsXBLBinding::UnhookEventHandlers()
       }
 
       manager->RemoveEventListenerByType(handler, type, flags);
     }
   }
 }
 
 static void
-UpdateInsertionParent(nsBindingManager* aBindingManager,
-                      XBLChildrenElement* aPoint,
+UpdateInsertionParent(XBLChildrenElement* aPoint,
                       nsIContent* aOldBoundElement)
 {
   if (aPoint->IsDefaultInsertion()) {
     return;
   }
 
   for (size_t i = 0; i < aPoint->InsertedChildrenLength(); ++i) {
     nsIContent* child = aPoint->mInsertedChildren[i];
@@ -718,19 +715,19 @@ UpdateInsertionParent(nsBindingManager* 
     // Here, we're iterating children that we inserted. There are two cases:
     // either |child| is an explicit child of |aOldBoundElement| and is no
     // longer inserted anywhere or it's a child of a <children> element
     // parented to |aOldBoundElement|. In the former case, the child is no
     // longer inserted anywhere, so we set its insertion parent to null. In the
     // latter case, the child is now inserted into |aOldBoundElement| from some
     // binding above us, so we set its insertion parent to aOldBoundElement.
     if (child->GetParentNode() == aOldBoundElement) {
-      aBindingManager->SetInsertionParent(child, nullptr);
+      child->SetXBLInsertionParent(nullptr);
     } else {
-      aBindingManager->SetInsertionParent(child, aOldBoundElement);
+      child->SetXBLInsertionParent(aOldBoundElement);
     }
   }
 }
 
 void
 nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument)
 {
   if (aOldDocument == aNewDocument)
@@ -832,29 +829,25 @@ nsXBLBinding::ChangeDocument(nsIDocument
     }
 
     // Update the anonymous content.
     // XXXbz why not only for style bindings?
     if (mContent) {
       nsXBLBinding::UninstallAnonymousContent(aOldDocument, mContent);
     }
 
-    nsBindingManager* bindingManager = aOldDocument->BindingManager();
-
     // Now that we've unbound our anonymous content from the tree and updated
     // its binding parent, update the insertion parent for content inserted
     // into our <children> elements.
     if (mDefaultInsertionPoint) {
-      UpdateInsertionParent(bindingManager, mDefaultInsertionPoint,
-                            mBoundElement);
+      UpdateInsertionParent(mDefaultInsertionPoint, mBoundElement);
     }
 
     for (size_t i = 0; i < mInsertionPoints.Length(); ++i) {
-      UpdateInsertionParent(bindingManager, mInsertionPoints[i],
-                            mBoundElement);
+      UpdateInsertionParent(mInsertionPoints[i], mBoundElement);
     }
 
     // Now that our inserted children no longer think they're inserted
     // anywhere, make sure our internal state reflects that as well.
     ClearInsertionPoints();
   }
 }
 
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -6391,18 +6391,17 @@ nsCSSFrameConstructor::GetRangeInsertion
   if (!insertionPoint && !multiple)
     return nullptr; // Don't build the frames.
  
   bool hasInsertion = false;
   if (!multiple) {
     // XXXbz XBL2/sXBL issue
     nsIDocument* document = aStartChild->GetDocument();
     // XXXbz how would |document| be null here?
-    if (document &&
-        document->BindingManager()->GetInsertionParent(aStartChild)) {
+    if (document && aStartChild->GetXBLInsertionParent()) {
       hasInsertion = true;
     }
   }
 
   if (multiple || hasInsertion) {
     // We have an insertion point.  There are some additional tests we need to do
     // in order to ensure that an append is a safe operation.
     uint32_t childCount = 0;
--- a/layout/inspector/src/inDOMUtils.cpp
+++ b/layout/inspector/src/inDOMUtils.cpp
@@ -99,22 +99,17 @@ inDOMUtils::GetParentForNode(nsIDOMNode*
   nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(aNode));
   nsCOMPtr<nsIDOMNode> parent;
 
   if (doc) {
     parent = inLayoutUtils::GetContainerFor(doc);
   } else if (aShowingAnonymousContent) {
     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
     if (content) {
-      nsIContent* bparent = nullptr;
-      nsRefPtr<nsBindingManager> bindingManager = inLayoutUtils::GetBindingManagerFor(aNode);
-      if (bindingManager) {
-        bparent = bindingManager->GetInsertionParent(content);
-      }
-
+      nsIContent* bparent = content->GetXBLInsertionParent();
       parent = do_QueryInterface(bparent);
     }
   }
 
   if (!parent) {
     // Ok, just get the normal DOM parent node
     aNode->GetParentNode(getter_AddRefs(parent));
   }
--- a/layout/inspector/src/inLayoutUtils.cpp
+++ b/layout/inspector/src/inLayoutUtils.cpp
@@ -63,29 +63,16 @@ inLayoutUtils::GetEventStateManagerFor(n
 
   nsIPresShell *shell = doc->GetShell();
   if (!shell)
     return nullptr;
 
   return shell->GetPresContext()->EventStateManager();
 }
 
-nsBindingManager* 
-inLayoutUtils::GetBindingManagerFor(nsIDOMNode* aNode)
-{
-  nsCOMPtr<nsIDOMDocument> domdoc;
-  aNode->GetOwnerDocument(getter_AddRefs(domdoc));
-  if (domdoc) {
-    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
-    return doc->BindingManager();
-  }
-  
-  return nullptr;
-}
-
 nsIDOMDocument*
 inLayoutUtils::GetSubDocumentFor(nsIDOMNode* aNode)
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   if (content) {
     nsCOMPtr<nsIDocument> doc = content->GetDocument();
     if (doc) {
       nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(doc->GetSubDocumentFor(content)));
--- a/layout/inspector/src/inLayoutUtils.h
+++ b/layout/inspector/src/inLayoutUtils.h
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 __inLayoutUtils_h__
 #define __inLayoutUtils_h__
 
-class nsBindingManager;
 class nsIDOMDocument;
 class nsIDOMElement;
 class nsIDOMNode;
 class nsIDOMWindow;
 class nsEventStateManager;
 class nsIFrame;
 class nsIPresShell;
 class nsISupports;
@@ -19,14 +18,13 @@ class nsISupports;
 class inLayoutUtils
 {
 public:
   static nsIDOMWindow* GetWindowFor(nsIDOMNode* aNode);
   static nsIDOMWindow* GetWindowFor(nsIDOMDocument* aDoc);
   static nsIPresShell* GetPresShellFor(nsISupports* aThing);
   static nsIFrame* GetFrameFor(nsIDOMElement* aElement);
   static nsEventStateManager* GetEventStateManagerFor(nsIDOMElement *aElement);
-  static nsBindingManager* GetBindingManagerFor(nsIDOMNode* aNode);
   static nsIDOMDocument* GetSubDocumentFor(nsIDOMNode* aNode);
   static nsIDOMNode* GetContainerFor(nsIDOMDocument* aDoc);
 };
 
 #endif // __inLayoutUtils_h__