Bug 377423, MemoryElements not removed from the pool properly, fixes topcrash, r=peterv,sr=sicking
authorenndeakin@sympatico.ca
Thu, 26 Apr 2007 06:03:55 -0700
changeset 835 dfaba0404aed38e5f0f676036da5e7568145b91f
parent 834 d5600d516db0d7283f5fd0e4fe6824a51600bd3d
child 836 a3f72faa922a3b3a115adeacaa67ce0b20f042ce
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, sicking
bugs377423
milestone1.9a4pre
Bug 377423, MemoryElements not removed from the pool properly, fixes topcrash, r=peterv,sr=sicking
content/xul/templates/src/nsRDFConInstanceTestNode.cpp
content/xul/templates/src/nsRDFConInstanceTestNode.h
content/xul/templates/src/nsRDFConMemberTestNode.cpp
content/xul/templates/src/nsRDFConMemberTestNode.h
content/xul/templates/src/nsRDFPropertyTestNode.cpp
content/xul/templates/src/nsRDFPropertyTestNode.h
content/xul/templates/src/nsRuleNetwork.cpp
content/xul/templates/src/nsRuleNetwork.h
content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
--- a/content/xul/templates/src/nsRDFConInstanceTestNode.cpp
+++ b/content/xul/templates/src/nsRDFConInstanceTestNode.cpp
@@ -239,18 +239,17 @@ nsRDFConInstanceTestNode::FilterInstanti
                    ("    container => %s",
                     (container == mContainer) ? "consistent" : "inconsistent"));
 
             if (((mEmpty == empty) && (mContainer == container)) ||
                 ((mEmpty == eDontCare) && (mContainer == container)) ||
                 ((mContainer == eDontCare) && (mEmpty == empty)))
             {
                 Element* element =
-                    nsRDFConInstanceTestNode::Element::Create(mProcessor->GetPool(),
-                                                              valueres, container, empty);
+                    nsRDFConInstanceTestNode::Element::Create(valueres, container, empty);
 
                 if (! element)
                     return NS_ERROR_OUT_OF_MEMORY;
 
                 inst->AddSupportingElement(element);
             }
             else {
                 aInstantiations.Erase(inst--);
--- a/content/xul/templates/src/nsRDFConInstanceTestNode.h
+++ b/content/xul/templates/src/nsRDFConInstanceTestNode.h
@@ -90,25 +90,25 @@ public:
             : mContainer(aContainer),
               mContainerTest(aContainerTest),
               mEmptyTest(aEmptyTest) {
             MOZ_COUNT_CTOR(nsRDFConInstanceTestNode::Element); }
 
         virtual ~Element() { MOZ_COUNT_DTOR(nsRDFConInstanceTestNode::Element); }
 
         static Element*
-        Create(nsFixedSizeAllocator& aPool, nsIRDFResource* aContainer,
+        Create(nsIRDFResource* aContainer,
                Test aContainerTest, Test aEmptyTest) {
-            void* place = aPool.Alloc(sizeof(Element));
+            void* place = MemoryElement::gPool.Alloc(sizeof(Element));
             return place ? ::new (place) Element(aContainer, aContainerTest, aEmptyTest) : nsnull; }
 
-        static void
-        Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
-            aElement->~Element();
-            aPool.Free(aElement, sizeof(*aElement)); }
+        void Destroy() {
+            this->~Element();
+            MemoryElement::gPool.Free(this, sizeof(Element));
+        }
 
         virtual const char* Type() const {
             return "nsRDFConInstanceTestNode::Element"; }
 
         virtual PLHashNumber Hash() const {
             return (PLHashNumber(NS_PTR_TO_INT32(mContainer.get())) >> 4) ^
                 PLHashNumber(mContainerTest) ^
                 (PLHashNumber(mEmptyTest) << 4); }
@@ -117,20 +117,16 @@ public:
             if (aElement.Type() == Type()) {
                 const Element& element = NS_STATIC_CAST(const Element&, aElement);
                 return mContainer == element.mContainer
                     && mContainerTest == element.mContainerTest
                     && mEmptyTest == element.mEmptyTest;
             }
             return PR_FALSE; }
 
-        virtual MemoryElement* Clone(void* aPool) const {
-            return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool),
-                          mContainer, mContainerTest, mEmptyTest); }
-
     protected:
         nsCOMPtr<nsIRDFResource> mContainer;
         Test mContainerTest;
         Test mEmptyTest;
     };
 
 protected:
     nsXULTemplateQueryProcessorRDF* mProcessor;
--- a/content/xul/templates/src/nsRDFConMemberTestNode.cpp
+++ b/content/xul/templates/src/nsRDFConMemberTestNode.cpp
@@ -208,18 +208,17 @@ nsRDFConMemberTestNode::FilterInstantiat
             }
 
             PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
                    ("    consistency check => %s", isconsistent ? "passed" : "failed"));
 
             if (isconsistent) {
                 // Add a memory element to our set-of-support.
                 Element* element =
-                    nsRDFConMemberTestNode::Element::Create(mProcessor->GetPool(),
-                                                            containerRes,
+                    nsRDFConMemberTestNode::Element::Create(containerRes,
                                                             memberValue);
 
                 if (! element)
                     return NS_ERROR_OUT_OF_MEMORY;
 
                 inst->AddSupportingElement(element);
             }
             else {
@@ -264,19 +263,17 @@ nsRDFConMemberTestNode::FilterInstantiat
                            ("    member => %s", NS_ConvertUTF16toUTF8(member).get()));
                 }
 #endif
 
                 Instantiation newinst = *inst;
                 newinst.AddAssignment(mMemberVariable, node);
 
                 Element* element =
-                    nsRDFConMemberTestNode::Element::Create(mProcessor->GetPool(),
-                                                            containerRes,
-                                                            node);
+                    nsRDFConMemberTestNode::Element::Create(containerRes, node);
 
                 if (! element)
                     return NS_ERROR_OUT_OF_MEMORY;
 
                 newinst.AddSupportingElement(element);
                 aInstantiations.Insert(inst, newinst);
             }
         }
@@ -356,18 +353,17 @@ nsRDFConMemberTestNode::FilterInstantiat
                         }
 #endif
 
                         // Add a new instantiation
                         Instantiation newinst = *inst;
                         newinst.AddAssignment(mContainerVariable, source);
 
                         Element* element =
-                            nsRDFConMemberTestNode::Element::Create(mProcessor->GetPool(),
-                                                                    source,
+                            nsRDFConMemberTestNode::Element::Create(source,
                                                                     memberValue);
 
                         if (! element)
                             return NS_ERROR_OUT_OF_MEMORY;
 
                         newinst.AddSupportingElement(element);
 
                         aInstantiations.Insert(inst, newinst);
@@ -453,24 +449,21 @@ nsRDFConMemberTestNode::FilterInstantiat
                     // instantiation set with the new assignment that we've
                     // introduced. Ownership will be transferred to the
                     Instantiation newinst = *inst;
                     newinst.AddAssignment(variable, value);
 
                     Element* element;
                     if (hasContainerBinding) {
                         element =
-                            nsRDFConMemberTestNode::Element::Create(mProcessor->GetPool(),
-                                                                    containerRes,
-                                                                    value);
+                            nsRDFConMemberTestNode::Element::Create(containerRes, value);
                     }
                     else {
                         element =
-                            nsRDFConMemberTestNode::Element::Create(mProcessor->GetPool(),
-                                                                    valueRes, memberValue);
+                            nsRDFConMemberTestNode::Element::Create(valueRes, memberValue);
                     }
 
                     if (! element)
                         return NS_ERROR_OUT_OF_MEMORY;
 
                     newinst.AddSupportingElement(element);
 
                     aInstantiations.Insert(inst, newinst);
--- a/content/xul/templates/src/nsRDFConMemberTestNode.h
+++ b/content/xul/templates/src/nsRDFConMemberTestNode.h
@@ -83,45 +83,39 @@ public:
                 nsIRDFNode* aMember)
             : mContainer(aContainer),
               mMember(aMember) {
             MOZ_COUNT_CTOR(nsRDFConMemberTestNode::Element); }
 
         virtual ~Element() { MOZ_COUNT_DTOR(nsRDFConMemberTestNode::Element); }
 
         static Element*
-        Create(nsFixedSizeAllocator& aPool,
-               nsIRDFResource* aContainer,
-               nsIRDFNode* aMember) {
-            void* place = aPool.Alloc(sizeof(Element));
+        Create(nsIRDFResource* aContainer, nsIRDFNode* aMember) {
+            void* place = MemoryElement::gPool.Alloc(sizeof(Element));
             return place ? ::new (place) Element(aContainer, aMember) : nsnull; }
 
-        static void
-        Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
-            aElement->~Element();
-            aPool.Free(aElement, sizeof(*aElement)); }
+        void Destroy() {
+            this->~Element();
+            MemoryElement::gPool.Free(this, sizeof(Element));
+        }
 
         virtual const char* Type() const {
             return "nsRDFConMemberTestNode::Element"; }
 
         virtual PLHashNumber Hash() const {
             return PLHashNumber(NS_PTR_TO_INT32(mContainer.get())) ^
                 (PLHashNumber(NS_PTR_TO_INT32(mMember.get())) >> 12); }
 
         virtual PRBool Equals(const MemoryElement& aElement) const {
             if (aElement.Type() == Type()) {
                 const Element& element = NS_STATIC_CAST(const Element&, aElement);
                 return mContainer == element.mContainer && mMember == element.mMember;
             }
             return PR_FALSE; }
 
-        virtual MemoryElement* Clone(void* aPool) const {
-            return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool),
-                          mContainer, mMember); }
-
     protected:
         nsCOMPtr<nsIRDFResource> mContainer;
         nsCOMPtr<nsIRDFNode> mMember;
     };
 
 protected:
     nsXULTemplateQueryProcessorRDF* mProcessor;
     nsCOMPtr<nsIAtom> mContainerVariable;
--- a/content/xul/templates/src/nsRDFPropertyTestNode.cpp
+++ b/content/xul/templates/src/nsRDFPropertyTestNode.cpp
@@ -215,18 +215,17 @@ nsRDFPropertyTestNode::FilterInstantiati
 #ifdef PR_LOGGING
             PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
                    ("    consistency check => %s", hasAssertion ? "passed" : "failed"));
 #endif
 
             if (hasAssertion) {
                 // it's consistent.
                 Element* element =
-                    nsRDFPropertyTestNode::Element::Create(mProcessor->GetPool(),
-                                                           sourceRes,
+                    nsRDFPropertyTestNode::Element::Create(sourceRes,
                                                            mProperty,
                                                            targetValue);
 
                 if (! element)
                     return NS_ERROR_OUT_OF_MEMORY;
 
                 inst->AddSupportingElement(element);
             }
@@ -315,18 +314,17 @@ nsRDFPropertyTestNode::FilterInstantiati
 
                 // Copy the original instantiation, and add it to the
                 // instantiation set with the new assignment that we've
                 // introduced. Ownership will be transferred to the
                 Instantiation newinst = *inst;
                 newinst.AddAssignment(variable, value);
 
                 Element* element =
-                    nsRDFPropertyTestNode::Element::Create(mProcessor->GetPool(),
-                                                           sourceRes,
+                    nsRDFPropertyTestNode::Element::Create(sourceRes,
                                                            mProperty,
                                                            targetValue);
 
                 if (! element)
                     return NS_ERROR_OUT_OF_MEMORY;
 
                 newinst.AddSupportingElement(element);
 
--- a/content/xul/templates/src/nsRDFPropertyTestNode.h
+++ b/content/xul/templates/src/nsRDFPropertyTestNode.h
@@ -104,27 +104,26 @@ public:
             : mSource(aSource),
               mProperty(aProperty),
               mTarget(aTarget) {
             MOZ_COUNT_CTOR(nsRDFPropertyTestNode::Element); }
 
         virtual ~Element() { MOZ_COUNT_DTOR(nsRDFPropertyTestNode::Element); }
 
         static Element*
-        Create(nsFixedSizeAllocator& aPool,
-               nsIRDFResource* aSource,
+        Create(nsIRDFResource* aSource,
                nsIRDFResource* aProperty,
                nsIRDFNode* aTarget) {
-            void* place = aPool.Alloc(sizeof(Element));
+            void* place = MemoryElement::gPool.Alloc(sizeof(Element));
             return place ? ::new (place) Element(aSource, aProperty, aTarget) : nsnull; }
 
-        static void
-        Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
-            aElement->~Element();
-            aPool.Free(aElement, sizeof(*aElement)); }
+        void Destroy() {
+            this->~Element();
+            MemoryElement::gPool.Free(this, sizeof(Element));
+        }
 
         virtual const char* Type() const {
             return "nsRDFPropertyTestNode::Element"; }
 
         virtual PLHashNumber Hash() const {
             return PLHashNumber(NS_PTR_TO_INT32(mSource.get())) ^
                 (PLHashNumber(NS_PTR_TO_INT32(mProperty.get())) >> 4) ^
                 (PLHashNumber(NS_PTR_TO_INT32(mTarget.get())) >> 12); }
@@ -133,20 +132,16 @@ public:
             if (aElement.Type() == Type()) {
                 const Element& element = NS_STATIC_CAST(const Element&, aElement);
                 return mSource == element.mSource
                     && mProperty == element.mProperty
                     && mTarget == element.mTarget;
             }
             return PR_FALSE; }
 
-        virtual MemoryElement* Clone(void* aPool) const {
-            return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool),
-                          mSource, mProperty, mTarget); }
-
     protected:
         nsCOMPtr<nsIRDFResource> mSource;
         nsCOMPtr<nsIRDFResource> mProperty;
         nsCOMPtr<nsIRDFNode> mTarget;
     };
 
 protected:
     nsXULTemplateQueryProcessorRDF* mProcessor;
--- a/content/xul/templates/src/nsRuleNetwork.cpp
+++ b/content/xul/templates/src/nsRuleNetwork.cpp
@@ -65,31 +65,56 @@ extern PRLogModuleInfo* gXULTemplateLog;
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsXULContentUtils.h"
 
 #endif
 
 #include "nsRuleNetwork.h"
 #include "nsXULTemplateResultSetRDF.h"
+#include "nsRDFConMemberTestNode.h"
+#include "nsRDFPropertyTestNode.h"
+
+PRBool MemoryElement::gPoolInited;
+nsFixedSizeAllocator MemoryElement::gPool;
+
+// static
+PRBool
+MemoryElement::Init()
+{
+    if (!gPoolInited) {
+        const size_t bucketsizes[] = {
+            sizeof (nsRDFConMemberTestNode::Element),
+            sizeof (nsRDFPropertyTestNode::Element)
+        };
+
+        if (NS_FAILED(gPool.Init("MemoryElement", bucketsizes,
+                                 NS_ARRAY_LENGTH(bucketsizes), 256)))
+            return PR_FALSE;
+
+        gPoolInited = PR_TRUE;
+    }
+
+    return PR_TRUE;
+}
 
 //----------------------------------------------------------------------
 //
 // nsRuleNetwork
 //
 
 nsresult
 MemoryElementSet::Add(MemoryElement* aElement)
 {
     for (ConstIterator element = First(); element != Last(); ++element) {
         if (*element == *aElement) {
             // We've already got this element covered. Since Add()
             // assumes ownership, and we aren't going to need this,
             // just nuke it.
-            delete aElement;
+            aElement->Destroy();
             return NS_OK;
         }
     }
 
     List* list = new List;
     if (! list)
         return NS_ERROR_OUT_OF_MEMORY;
 
--- a/content/xul/templates/src/nsRuleNetwork.h
+++ b/content/xul/templates/src/nsRuleNetwork.h
@@ -59,16 +59,17 @@
 
  */
 
 #ifndef nsRuleNetwork_h__
 #define nsRuleNetwork_h__
 
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
+#include "nsFixedSizeAllocator.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsIDOMNode.h"
 #include "plhash.h"
 #include "pldhash.h"
 #include "nsCRT.h"
 #include "nsIRDFNode.h"
 
@@ -82,24 +83,30 @@ class nsXULTemplateQueryProcessorRDF;
  * A memory element that supports an instantiation. A memory element holds a
  * set of nodes involved in an RDF test such as <member> or <triple> test. A
  * memory element is created when a specific test matches. The query processor
  * maintains a map between the memory elements and the results they eventually
  * matched. When an assertion is removed from the graph, this map is consulted
  * to determine which results will no longer match.
  */
 class MemoryElement {
-public:
+protected:
     MemoryElement() { MOZ_COUNT_CTOR(MemoryElement); }
     virtual ~MemoryElement() { MOZ_COUNT_DTOR(MemoryElement); }
+public:
 
+    static PRBool Init();
+
+    static PRBool gPoolInited;
+    static nsFixedSizeAllocator gPool;
+
+    virtual void Destroy() = 0;
     virtual const char* Type() const = 0;
     virtual PLHashNumber Hash() const = 0;
     virtual PRBool Equals(const MemoryElement& aElement) const = 0;
-    virtual MemoryElement* Clone(void* aPool) const = 0;
 
     PRBool operator==(const MemoryElement& aMemoryElement) const {
         return Equals(aMemoryElement);
     }
 
     PRBool operator!=(const MemoryElement& aMemoryElement) const {
         return !Equals(aMemoryElement);
     }
@@ -117,17 +124,17 @@ public:
 
 protected:
     class List {
     public:
         List() { MOZ_COUNT_CTOR(MemoryElementSet::List); }
 
         ~List() {
             MOZ_COUNT_DTOR(MemoryElementSet::List);
-            delete mElement;
+            mElement->Destroy();
             NS_IF_RELEASE(mNext); }
 
         PRInt32 AddRef() { return ++mRefCnt; }
 
         PRInt32 Release() {
             PRInt32 refcnt = --mRefCnt;
             if (refcnt == 0) delete this;
             return refcnt; }
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
@@ -202,17 +202,17 @@ nsXULTemplateQueryProcessorRDF::InitGlob
     }
 
     if (!kRDF_type) {
         gRDFService->GetResource(
           NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
                              &kRDF_type);
     }
 
-    return NS_OK;
+    return MemoryElement::Init() ? NS_OK : NS_ERROR_FAILURE;
 }
 
 //----------------------------------------------------------------------
 //
 // nsIXULTemplateQueryProcessor interface
 //
 
 
@@ -231,25 +231,16 @@ nsXULTemplateQueryProcessorRDF::Initiali
             return NS_ERROR_OUT_OF_MEMORY;
         if (!mBindingDependencies.IsInitialized() &&
             !mBindingDependencies.Init())
             return NS_ERROR_OUT_OF_MEMORY;
         if (!mRuleToBindingsMap.IsInitialized() &&
             !mRuleToBindingsMap.Init())
             return NS_ERROR_OUT_OF_MEMORY;
 
-        const size_t bucketsizes[] = {
-            sizeof (nsRDFConMemberTestNode::Element),
-            sizeof (nsRDFPropertyTestNode::Element)
-        };
-
-        rv = mPool.Init("nsXULTemplateQueryProcessorRDF", bucketsizes, 2, 256);
-        if (NS_FAILED(rv))
-            return rv;
-
         mQueryProcessorRDFInited = PR_TRUE;
     }
 
     // don't do anything if generation has already been done
     if (mGenerationStarted)
         return NS_ERROR_UNEXPECTED;
 
     mDB = do_QueryInterface(aDatasource);
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.h
@@ -333,19 +333,16 @@ protected:
 
     // containment properties that are checked to determine if a resource is
     // a container
     nsResourceSet mContainmentProperties;
 
     // the end node of the default simple node hierarchy
     TestNode* mSimpleRuleMemberTest;
 
-    // fixed size allocator used to allocate rule network structures
-    nsFixedSizeAllocator mPool;
-
     // the reference variable
     nsCOMPtr<nsIAtom> mRefVariable;
 
     // the last ref that was calculated, used for simple rules
     nsCOMPtr<nsIXULTemplateResult> mLastRef;
 
     /**
      * A map between nsIRDFNodes that form the left-hand side (the subject) of
@@ -390,13 +387,11 @@ protected:
     // pseudo-constants
     static nsrefcnt gRefCnt;
 
 public:
     static nsIRDFService*            gRDFService;
     static nsIRDFContainerUtils*     gRDFContainerUtils;
     static nsIRDFResource*           kNC_BookmarkSeparator;
     static nsIRDFResource*           kRDF_type;
-
-    nsFixedSizeAllocator& GetPool() { return mPool; }
 };
 
 #endif // nsXULTemplateQueryProcessorRDF_h__