supports-array-use-comarray
author Benjamin Smedberg <benjamin@smedbergs.us>
Sat, 26 Jul 2008 22:49:39 -0400
changeset 167 a4da40849f5436e629c5732f4368c6c48189637f
parent 87 6419604414bca01b0bbfa56c0180fa65672a8335
permissions -rw-r--r--
State as of now

diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp
--- a/xpcom/ds/nsSupportsArray.cpp
+++ b/xpcom/ds/nsSupportsArray.cpp
@@ -45,73 +45,6 @@
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 
-#if DEBUG_SUPPORTSARRAY
-#define MAXSUPPORTS 20
-
-class SupportsStats {
-public:
-  SupportsStats();
-  ~SupportsStats();
-
-};
-
-static int sizesUsed; // number of the elements of the arrays used
-static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations.  sorted
-static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array)
-static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used)
-static int GrowInPlace[MAXSUPPORTS];
-
-// these are per-allocation
-static int MaxElements[3000];
-
-// very evil
-#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
-                                  { \
-                                    if (sizesAlloced[i] == (int)(size)) \
-                                    { ((x)[i])++; break; } \
-                                  } \
-                                  if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \
-                                  { sizesAlloced[sizesUsed] = (size); \
-                                    ((x)[sizesUsed++])++; break; \
-                                  } \
-                                } while (0);
-
-#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
-                                    { \
-                                      if (sizesAlloced[i] == (int)(size)) \
-                                      { ((x)[i])--; break; } \
-                                    } \
-                                  } while (0);
-
-
-SupportsStats::SupportsStats()
-{
-  sizesUsed = 1;
-  sizesAlloced[0] = 0;
-}
-
-SupportsStats::~SupportsStats()
-{
-  int i;
-  for (i = 0; i < sizesUsed; i++)
-  {
-    printf("Size %d:\n",sizesAlloced[i]);
-    printf("\tNumber of SupportsArrays this size (max):     %d\n",NumberOfSize[i]);
-    printf("\tNumber of allocations this size (total):  %d\n",AllocedOfSize[i]);
-    printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
-  }
-  printf("Max Size of SupportsArray:\n");
-  for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
-  {
-    if (MaxElements[i])
-      printf("\t%d: %d\n",i,MaxElements[i]);
-  }
-}
-
-// Just so constructor/destructor get called
-SupportsStats gSupportsStats;
-#endif
-
 void*
 nsQueryElementAt::get(const nsIID &aIID) const
   {
@@ -131,77 +64,10 @@ static const PRInt32 kLinearThreshold = 
 
 nsSupportsArray::nsSupportsArray()
 {
-  mArray = mAutoArray;
-  mArraySize = kAutoArraySize;
-  mCount = 0;
-#if DEBUG_SUPPORTSARRAY
-  mMaxCount = 0;
-  mMaxSize = 0;
-  ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0]));
-  MaxElements[0]++;
-#endif
 }
 
 nsSupportsArray::~nsSupportsArray()
 {
-  DeleteArray();
-}
-
-PRBool nsSupportsArray::GrowArrayBy(PRInt32 aGrowBy)
-{
-  // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller
-  // than kLinearThreshold bytes, or a power of two if we're larger.
-  // This is much more efficient with most memory allocators, especially
-  // if it's very large, or of the allocator is binned.
-  if (aGrowBy < kGrowArrayBy)
-    aGrowBy = kGrowArrayBy;
-
-  PRUint32 newCount = mArraySize + aGrowBy;  // Minimum increase
-  PRUint32 newSize = sizeof(mArray[0]) * newCount;
-
-  if (newSize >= (PRUint32) kLinearThreshold)
-  {
-    // newCount includes enough space for at least kGrowArrayBy new slots.
-    // Select the next power-of-two size in bytes above that if newSize is
-    // not a power of two.
-    if (newSize & (newSize - 1))
-      newSize = PR_BIT(PR_CeilingLog2(newSize));
-
-    newCount = newSize / sizeof(mArray[0]);
-  }
-  // XXX This would be far more efficient in many allocators if we used
-  // XXX PR_Realloc(), etc
-  nsISupports** oldArray = mArray;
-
-  mArray = new nsISupports*[newCount];
-  if (!mArray) {                    // ran out of memory
-    mArray = oldArray;
-    return PR_FALSE;
-  }
-  mArraySize = newCount;
-
-#if DEBUG_SUPPORTSARRAY
-  if (oldArray == mArray) // can't happen without use of realloc
-    ADD_TO_STATS(GrowInPlace,mCount);
-  ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
-  if (mArraySize > mMaxSize)
-  {
-    ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0]));
-    if (oldArray != &(mAutoArray[0]))
-      SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0]));
-    mMaxSize = mArraySize;
-  }
-#endif
-  if (oldArray) {                   // need to move old data
-    if (0 < mCount) {
-      ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
-    }
-    if (oldArray != &(mAutoArray[0])) {
-      delete[] oldArray;
-    }
-  }
-
-  return PR_TRUE;
 }
 
 NS_METHOD
@@ -210,7 +76,7 @@ nsSupportsArray::Create(nsISupports *aOu
   if (aOuter)
     return NS_ERROR_NO_AGGREGATION;
 
-  nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
+  nsISupportsArray* it = new nsSupportsArray();
   if (!it)
     return NS_ERROR_OUT_OF_MEMORY;
 
@@ -222,42 +88,18 @@ nsSupportsArray::Read(nsIObjectInputStre
 {
   nsresult rv;
 
-  PRUint32 newArraySize;
-  rv = aStream->Read32(&newArraySize);
-
-  if (newArraySize <= kAutoArraySize) {
-    if (mArray != mAutoArray) {
-      delete[] mArray;
-      mArray = mAutoArray;
-    }
-    newArraySize = kAutoArraySize;
-  }
-  else {
-    if (newArraySize <= mArraySize) {
-      // Keep non-default-size mArray, it's more than big enough.
-      newArraySize = mArraySize;
-    }
-    else {
-      nsISupports** array = new nsISupports*[newArraySize];
-      if (!array)
-        return NS_ERROR_OUT_OF_MEMORY;
-      if (mArray != mAutoArray)
-        delete[] mArray;
-      mArray = array;
-    }
-  }
-  mArraySize = newArraySize;
-
-  rv = aStream->Read32(&mCount);
+  PRUint32 count;
+  rv = aStream->Read32(&count);
   if (NS_FAILED(rv)) return rv;
 
-  NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!");
-  if (mCount > mArraySize)
-    mCount = mArraySize;
+  mArray.SetCapacity(count);
 
-  for (PRUint32 i = 0; i < mCount; i++) {
-    rv = aStream->ReadObject(PR_TRUE, &mArray[i]);
+  for (PRUint32 i = 0; i < count; i++) {
+    nsISupports* object;
+    rv = aStream->ReadObject(PR_TRUE, &object);
     if (NS_FAILED(rv)) return rv;
+
+    mArray.AppendObject(object);
   }
 
   return NS_OK;
@@ -268,30 +110,18 @@ nsSupportsArray::Write(nsIObjectOutputSt
 {
   nsresult rv;
 
-  rv = aStream->Write32(mArraySize);
+  PRUint32 count = mArray.Count();
+
+  rv = aStream->Write32(count);
   if (NS_FAILED(rv)) return rv;
 
-  rv = aStream->Write32(mCount);
-  if (NS_FAILED(rv)) return rv;
-
-  for (PRUint32 i = 0; i < mCount; i++) {
+  for (PRUint32 i = 0; i < count; i++) {
     rv = aStream->WriteObject(mArray[i], PR_TRUE);
     if (NS_FAILED(rv)) return rv;
   }
 
   return NS_OK;
 }
-
-void nsSupportsArray::DeleteArray(void)
-{
-  Clear();
-  if (mArray != &(mAutoArray[0])) {
-    delete[] mArray;
-    mArray = mAutoArray;
-    mArraySize = kAutoArraySize;
-  }
-}
-
 
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::Equals(const nsISupportsArray* aOther)
@@ -303,11 +133,11 @@ nsSupportsArray::Equals(const nsISupport
     if (NS_FAILED( rv ))
       return PR_FALSE;
 
-    if (mCount == countOther) {
-      PRUint32 index = mCount;
-      nsCOMPtr<nsISupports> otherElem;
+    if ((PRUint32) mArray.Count() == countOther) {
+      PRUint32 index = mArray.Count();
+      nsISupports* otherElem = nsnull;
       while (index--) {
-        if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem))))
+        if (NS_FAILED(other->GetElementAt(index, &otherElem)))
           return PR_FALSE;
         if (mArray[index] != otherElem)
           return PR_FALSE;
@@ -321,12 +151,7 @@ NS_IMETHODIMP_(nsISupports*)
 NS_IMETHODIMP_(nsISupports*)
 nsSupportsArray::ElementAt(PRUint32 aIndex)
 {
-  if (aIndex < mCount) {
-    nsISupports*  element = mArray[aIndex];
-    NS_IF_ADDREF(element);
-    return element;
-  }
-  return 0;
+  return mArray.SafeObjectAt(aIndex);
 }
 
 NS_IMETHODIMP_(PRInt32)
@@ -339,31 +164,20 @@ nsSupportsArray::IndexOfStartingAt(const
 nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement,
                                    PRUint32 aStartIndex)
 {
-  if (aStartIndex < mCount) {
-    const nsISupports** start = (const nsISupports**)mArray;  // work around goofy compiler behavior
-    const nsISupports** ep = (start + aStartIndex);
-    const nsISupports** end = (start + mCount);
-    while (ep < end) {
-      if (aPossibleElement == *ep) {
-        return (ep - start);
-      }
-      ep++;
-    }
+  for (; aStartIndex < (PRUint32) mArray.Count(); ++aStartIndex) {
+    if (mArray[aStartIndex] == aPossibleElement)
+      return aStartIndex;
   }
+
   return -1;
 }
 
 NS_IMETHODIMP_(PRInt32)
 nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement)
 {
-  if (0 < mCount) {
-    const nsISupports** start = (const nsISupports**)mArray;  // work around goofy compiler behavior
-    const nsISupports** ep = (start + mCount);
-    while (start <= --ep) {
-      if (aPossibleElement == *ep) {
-        return (ep - start);
-      }
-    }
+  for (PRInt32 i = mArray.Count() - 1; i >= 0; --i) {
+    if (mArray[i] == aPossibleElement)
+      return i;
   }
   return -1;
 }
@@ -371,110 +185,48 @@ NS_IMETHODIMP_(PRBool)
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex)
 {
-  if (aIndex <= mCount) {
-    if (mArraySize < (mCount + 1)) {
-      // need to grow the array
-      if (!GrowArrayBy(1))
-        return PR_FALSE;
-    }
-
-    // Could be slightly more efficient if GrowArrayBy knew about the
-    // split, but the difference is trivial.
-    PRUint32 slide = (mCount - aIndex);
-    if (0 < slide) {
-      ::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*));
-    }
-
-    mArray[aIndex] = aElement;
-    NS_IF_ADDREF(aElement);
-    mCount++;
-
-#if DEBUG_SUPPORTSARRAY
-    if (mCount > mMaxCount &&
-        mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
-    {
-      MaxElements[mCount]++;
-      MaxElements[mMaxCount]--;
-      mMaxCount = mCount;
-    }
-#endif
-    return PR_TRUE;
-  }
-  return PR_FALSE;
+  return mArray.InsertObjectAt(aElement, aIndex);
 }
 
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, PRUint32 aIndex)
 {
-  if (!aElements) {
-    return PR_FALSE;
-  }
+  NS_ASSERTION(aElements, "Null badness");
+
   PRUint32 countElements;
   if (NS_FAILED( aElements->Count( &countElements ) ))
     return PR_FALSE;
 
-  if (aIndex <= mCount) {
-    if (mArraySize < (mCount + countElements)) {
-      // need to grow the array
-      if (!GrowArrayBy(countElements))
-        return PR_FALSE;
-    }
+  mArray.SetCapacity(mArray.Count() + countElements);
 
-    // Could be slightly more efficient if GrowArrayBy knew about the
-    // split, but the difference is trivial.
-    PRUint32 slide = (mCount - aIndex);
-    if (0 < slide) {
-      ::memmove(mArray + aIndex + countElements, mArray + aIndex,
-                slide * sizeof(nsISupports*));
-    }
-
-    for (PRUint32 i = 0; i < countElements; ++i, ++mCount) {
-      // use GetElementAt to copy and do AddRef for us
-      if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) ))
-        return PR_FALSE;
-    }
-
-#if DEBUG_SUPPORTSARRAY
-    if (mCount > mMaxCount &&
-        mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
-    {
-      MaxElements[mCount]++;
-      MaxElements[mMaxCount]--;
-      mMaxCount = mCount;
-    }
-#endif
-    return PR_TRUE;
+  // Count backwards and always insert at aIndex... inefficient but I don't care
+  for (; countElements; --countElements) {
+    nsISupports* el;
+    aElements->GetElementAt(countElements - 1, &el);
+    mArray.InsertObjectAt(el, aIndex);
   }
-  return PR_FALSE;
+  return PR_TRUE;
 }
 
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex)
 {
-  if (aIndex < mCount) {
-    NS_IF_ADDREF(aElement);  // addref first in case it's the same object!
-    NS_IF_RELEASE(mArray[aIndex]);
-    mArray[aIndex] = aElement;
-    return PR_TRUE;
-  }
-  return PR_FALSE;
+  if (aIndex >= (PRUint32) mArray.Count())
+    return PR_FALSE;
+
+  return mArray.ReplaceObjectAt(aElement, aIndex);
 }
 
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount)
 {
-  if (aIndex + aCount <= mCount) {
-    for (PRUint32 i = 0; i < aCount; i++)
-      NS_IF_RELEASE(mArray[aIndex+i]);
-    mCount -= aCount;
-    PRInt32 slide = (mCount - aIndex);
-    if (0 < slide) {
-      ::memmove(mArray + aIndex, mArray + aIndex + aCount,
-                slide * sizeof(nsISupports*));
-    }
-    return PR_TRUE;
+  if (aIndex + aCount > (PRUint32) mArray.Count())
+    return PR_FALSE;
+
+  while (aCount--) {
+    mArray.RemoveObjectAt(aIndex);
   }
-  return PR_FALSE;
+  return PR_TRUE;
 }
 
 NS_IMETHODIMP_(PRBool)
@@ -500,119 +252,27 @@ NS_IMETHODIMP_(PRBool)
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
 {
-  nsISupports *tempElement;
-
-  if (aTo == aFrom)
-    return PR_TRUE;
-
-  if (aTo < 0 || aFrom < 0 ||
-      (PRUint32) aTo >= mCount || (PRUint32) aFrom >= mCount)
-  {
-    // can't extend the array when moving an element.  Also catches mImpl = null
-    return PR_FALSE;
-  }
-  tempElement = mArray[aFrom];
-
-  if (aTo < aFrom)
-  {
-    // Moving one element closer to the head; the elements inbetween move down
-    ::memmove(mArray + aTo + 1, mArray + aTo,
-              (aFrom-aTo) * sizeof(mArray[0]));
-    mArray[aTo] = tempElement;
-  }
-  else // already handled aFrom == aTo
-  {
-    // Moving one element closer to the tail; the elements inbetween move up
-    ::memmove(mArray + aFrom, mArray + aFrom + 1,
-              (aTo-aFrom) * sizeof(mArray[0]));
-    mArray[aTo] = tempElement;
-  }
-
-  return PR_TRUE;
+  NS_NOTREACHED("This method sucks!");
+  return PR_FALSE;
 }
 
 NS_IMETHODIMP
 nsSupportsArray::Clear(void)
 {
-  if (0 < mCount) {
-    do {
-      --mCount;
-      NS_IF_RELEASE(mArray[mCount]);
-    } while (0 != mCount);
-  }
+  mArray.Clear();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSupportsArray::Compact(void)
 {
-#if DEBUG_SUPPORTSARRAY
-  PRUint32 oldArraySize = mArraySize;
-#endif
-  if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) {
-    nsISupports** oldArray = mArray;
-    if (mCount <= kAutoArraySize) {
-      mArray = mAutoArray;
-      mArraySize = kAutoArraySize;
-    }
-    else {
-      mArray = new nsISupports*[mCount];
-      if (!mArray) {
-        mArray = oldArray;
-        return NS_OK;
-      }
-      mArraySize = mCount;
-    }
-#if DEBUG_SUPPORTSARRAY
-    if (oldArray == mArray &&
-        oldArray != &(mAutoArray[0])) // can't happen without use of realloc
-      ADD_TO_STATS(GrowInPlace,oldArraySize);
-    if (oldArray != &(mAutoArray[0]))
-      ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
-#endif
-    ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
-    delete[] oldArray;
-  }
   return NS_OK;
 }
 
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::SizeTo(PRInt32 aSize)
 {
-#if DEBUG_SUPPORTSARRAY
-  PRUint32 oldArraySize = mArraySize;
-#endif
-  NS_ASSERTION(aSize >= 0, "negative aSize!");
-
-  // XXX for aSize < mCount we could resize to mCount
-  if (mArraySize == (PRUint32) aSize || (PRUint32) aSize < mCount)
-    return PR_TRUE;     // nothing to do
-
-  // switch back to autoarray if possible
-  nsISupports** oldArray = mArray;
-  if ((PRUint32) aSize <= kAutoArraySize) {
-    mArray = mAutoArray;
-    mArraySize = kAutoArraySize;
-  }
-  else {
-    mArray = new nsISupports*[aSize];
-    if (!mArray) {
-      mArray = oldArray;
-      return PR_FALSE;
-    }
-    mArraySize = aSize;
-  }
-#if DEBUG_SUPPORTSARRAY
-  if (oldArray == mArray &&
-      oldArray != &(mAutoArray[0])) // can't happen without use of realloc
-    ADD_TO_STATS(GrowInPlace,oldArraySize);
-  if (oldArray != &(mAutoArray[0]))
-    ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
-#endif
-  ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
-  if (oldArray != mAutoArray)
-    delete[] oldArray;
-
+  mArray.SetCapacity(aSize);
   return PR_TRUE;
 }
 
@@ -622,7 +282,7 @@ nsSupportsArray::EnumerateForwards(nsISu
   PRInt32 aIndex = -1;
   PRBool  running = PR_TRUE;
 
-  while (running && (++aIndex < (PRInt32)mCount)) {
+  while (running && (++aIndex < mArray.Count())) {
     running = (*aFunc)(mArray[aIndex], aData);
   }
   return running;
@@ -631,10 +291,10 @@ NS_IMETHODIMP_(PRBool)
 NS_IMETHODIMP_(PRBool)
 nsSupportsArray::EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData)
 {
-  PRUint32 aIndex = mCount;
+  PRUint32 aIndex = mArray.Count();
   PRBool  running = PR_TRUE;
 
-  while (running && (0 < aIndex--)) {
+  while (running && aIndex--) {
     running = (*aFunc)(mArray[aIndex], aData);
   }
   return running;
@@ -647,7 +307,6 @@ nsSupportsArray::Enumerate(nsIEnumerator
   if (!e)
     return NS_ERROR_OUT_OF_MEMORY;
   *result = e;
-  NS_ADDREF(e);
   return NS_OK;
 }
 
@@ -685,7 +344,6 @@ nsArrayEnumerator::nsArrayEnumerator(nsI
     : mValueArray(aValueArray),
       mIndex(0)
 {
-    NS_IF_ADDREF(mValueArray);
 }
 
 nsArrayEnumerator::~nsArrayEnumerator(void)
@@ -742,6 +400,5 @@ NS_NewArrayEnumerator(nsISimpleEnumerato
     if (enumer == nsnull)
         return NS_ERROR_OUT_OF_MEMORY;
     *result = enumer; 
-    NS_ADDREF(*result);
     return NS_OK;
 }
diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h
--- a/xpcom/ds/nsSupportsArray.h
+++ b/xpcom/ds/nsSupportsArray.h
@@ -41,15 +41,14 @@
 //#define DEBUG_SUPPORTSARRAY 1
 
 #include "nsISupportsArray.h"
-
-static const PRUint32 kAutoArraySize = 8;
+#include "nsCOMArray.h"
 
 // Set IMETHOD_VISIBILITY to empty so that the class-level NS_COM declaration
 // controls member method visibility.
 #undef  IMETHOD_VISIBILITY
 #define IMETHOD_VISIBILITY
 
-class NS_COM nsSupportsArray : public nsISupportsArray {
+class NS_COM nsSupportsArray : public XPCOMGCFinalizedObject, public nsISupportsArray {
 public:
   nsSupportsArray(void);
   ~nsSupportsArray(void); // nonvirtual since we're not subclassed
@@ -62,13 +61,13 @@ public:
   NS_DECL_NSISERIALIZABLE
 
   // nsICollection methods:
-  NS_IMETHOD Count(PRUint32 *result) { *result = mCount; return NS_OK; }
+  NS_IMETHOD Count(PRUint32 *result) { *result = mArray.Count(); return NS_OK; }
   NS_IMETHOD GetElementAt(PRUint32 aIndex, nsISupports* *result) {
     *result = ElementAt(aIndex);
     return NS_OK;
   }
   NS_IMETHOD QueryElementAt(PRUint32 aIndex, const nsIID & aIID, void * *aResult) {
-    if (aIndex < mCount) {
+    if (aIndex < (PRUint32) mArray.Count()) {
       nsISupports* element = mArray[aIndex];
       if (nsnull != element)
         return element->QueryInterface(aIID, aResult);
@@ -79,7 +78,7 @@ public:
     return ReplaceElementAt(value, aIndex) ? NS_OK : NS_ERROR_FAILURE;
   }
   NS_IMETHOD AppendElement(nsISupports *aElement) {
-    return InsertElementAt(aElement, mCount)/* ? NS_OK : NS_ERROR_FAILURE*/;
+    return InsertElementAt(aElement, mArray.Count())/* ? NS_OK : NS_ERROR_FAILURE*/;
   }
   // XXX this is badly named - should be RemoveFirstElement
   NS_IMETHOD RemoveElement(nsISupports *aElement) {
@@ -134,7 +133,7 @@ public:
   }
   
   NS_IMETHOD_(PRBool) AppendElements(nsISupportsArray* aElements) {
-    return InsertElementsAt(aElements,mCount);
+    return InsertElementsAt(aElements, mArray.Count());
   }
   
   NS_IMETHOD Compact(void);
@@ -150,18 +149,7 @@ public:
 
   NS_IMETHOD_(PRBool) SizeTo(PRInt32 aSize);
 protected:
-  void DeleteArray(void);
-
-  NS_IMETHOD_(PRBool) GrowArrayBy(PRInt32 aGrowBy);
-
-  nsISupports** mArray;
-  PRUint32 mArraySize;
-  PRUint32 mCount;
-  nsISupports*  mAutoArray[kAutoArraySize];
-#if DEBUG_SUPPORTSARRAY
-  PRUint32 mMaxCount;
-  PRUint32 mMaxSize;
-#endif
+  nsCOMArray<nsISupports> mArray;
 
 private:
   // Copy constructors are not allowed