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; }
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; }
nsAutoVoidArray::nsAutoVoidArray() : nsVoidArray() { // Don't need to clear it. Some users just call ReplaceElementAt(), // but we'll clear it at that time if needed to save CPU cycles. #if DEBUG_VOIDARRAY mIsAuto = PR_TRUE; ADD_TO_STATS(MaxAuto,0); #endif ResetToAutoBuffer(); }
nsSupportsArray::SizeTo(int32_t aSize) { #if DEBUG_SUPPORTSARRAY uint32_t oldArraySize = mArraySize; #endif NS_ASSERTION(aSize >= 0, "negative aSize!"); // XXX for aSize < mCount we could resize to mCount if (mArraySize == (uint32_t)aSize || (uint32_t)aSize < mCount) { return true; // nothing to do } // switch back to autoarray if possible nsISupports** oldArray = mArray; if ((uint32_t)aSize <= kAutoArraySize) { mArray = mAutoArray; mArraySize = kAutoArraySize; } else { mArray = new nsISupports*[aSize]; if (!mArray) { mArray = oldArray; return 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; } return true; }
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 }
nsVoidArray::nsVoidArray() : mImpl(nsnull) { MOZ_COUNT_CTOR(nsVoidArray); #if DEBUG_VOIDARRAY mMaxCount = 0; mMaxSize = 0; mIsAuto = PR_FALSE; ADD_TO_STATS(NumberOfSize,0); MaxElements[0]++; #endif }
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; return PR_TRUE; }
// This does all allocation/reallocation of the array. // It also will compact down to N - good for things that might grow a lot // at times, but usually are smaller, like JS deferred GC releases. PRBool nsVoidArray::SizeTo(PRInt32 aSize) { PRUint32 oldsize = GetArraySize(); PRBool isOwner = IsArrayOwner(); PRBool hasAuto = HasAutoBuffer(); if (aSize == (PRInt32) oldsize) return PR_TRUE; // no change if (aSize <= 0) { // free the array if allocated if (mImpl) { if (isOwner) { free(reinterpret_cast<char *>(mImpl)); if (hasAuto) { static_cast<nsAutoVoidArray*>(this)->ResetToAutoBuffer(); } else { mImpl = nsnull; } } else { mImpl->mCount = 0; // nsAutoVoidArray } } return PR_TRUE; } if (mImpl && isOwner) { // We currently own an array impl. Resize it appropriately. if (aSize < mImpl->mCount) { // XXX Note: we could also just resize to mCount return PR_TRUE; // can't make it that small, ignore request } char* bytes = (char *) realloc(mImpl,SIZEOF_IMPL(aSize)); Impl* newImpl = reinterpret_cast<Impl*>(bytes); if (!newImpl) return PR_FALSE; #if DEBUG_VOIDARRAY if (mImpl == newImpl) ADD_TO_STATS(GrowInPlace,oldsize); ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize)); if (aSize > mMaxSize) { ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize)); if (oldsize) SUB_FROM_STATS(NumberOfSize,oldsize); mMaxSize = aSize; if (mIsAuto) { ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize)); SUB_FROM_STATS(MaxAuto,oldsize); } } #endif SetArray(newImpl, aSize, newImpl->mCount, PR_TRUE, hasAuto); return PR_TRUE; } if ((PRUint32) aSize < oldsize) { // No point in allocating if it won't free the current Impl anyway. return PR_TRUE; } // just allocate an array // allocate the exact size requested char* bytes = (char *) malloc(SIZEOF_IMPL(aSize)); Impl* newImpl = reinterpret_cast<Impl*>(bytes); if (!newImpl) return PR_FALSE; #if DEBUG_VOIDARRAY ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize)); if (aSize > mMaxSize) { ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize)); if (oldsize && !mImpl) SUB_FROM_STATS(NumberOfSize,oldsize); mMaxSize = aSize; } #endif if (mImpl) { #if DEBUG_VOIDARRAY ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize)); SUB_FROM_STATS(MaxAuto,0); SUB_FROM_STATS(NumberOfSize,0); mIsAuto = PR_TRUE; #endif // We must be growing an nsAutoVoidArray - copy since we didn't // realloc. memcpy(newImpl->mArray, mImpl->mArray, mImpl->mCount * sizeof(mImpl->mArray[0])); } SetArray(newImpl, aSize, mImpl ? mImpl->mCount : 0, PR_TRUE, hasAuto); // no memset; handled later in ReplaceElementAt if needed return PR_TRUE; }
// This does all allocation/reallocation of the array. // It also will compact down to N - good for things that might grow a lot // at times, but usually are smaller, like JS deferred GC releases. bool nsVoidArray::SizeTo(int32_t aSize) { uint32_t oldsize = GetArraySize(); if (aSize == (int32_t) oldsize) return true; // no change if (aSize <= 0) { // free the array if allocated if (mImpl) { free(reinterpret_cast<char *>(mImpl)); mImpl = nullptr; } return true; } if (mImpl) { // We currently own an array impl. Resize it appropriately. if (aSize < mImpl->mCount) { // XXX Note: we could also just resize to mCount return true; // can't make it that small, ignore request } char* bytes = (char *) realloc(mImpl,SIZEOF_IMPL(aSize)); Impl* newImpl = reinterpret_cast<Impl*>(bytes); if (!newImpl) return false; #if DEBUG_VOIDARRAY if (mImpl == newImpl) ADD_TO_STATS(GrowInPlace,oldsize); ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize)); if (aSize > mMaxSize) { ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize)); if (oldsize) SUB_FROM_STATS(NumberOfSize,oldsize); mMaxSize = aSize; if (mIsAuto) { ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize)); SUB_FROM_STATS(MaxAuto,oldsize); } } #endif SetArray(newImpl, aSize, newImpl->mCount); return true; } if ((uint32_t) aSize < oldsize) { // No point in allocating if it won't free the current Impl anyway. return true; } // just allocate an array // allocate the exact size requested char* bytes = (char *) malloc(SIZEOF_IMPL(aSize)); Impl* newImpl = reinterpret_cast<Impl*>(bytes); if (!newImpl) return false; #if DEBUG_VOIDARRAY ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize)); if (aSize > mMaxSize) { ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize)); if (oldsize && !mImpl) SUB_FROM_STATS(NumberOfSize,oldsize); mMaxSize = aSize; } #endif if (mImpl) { #if DEBUG_VOIDARRAY ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize)); SUB_FROM_STATS(MaxAuto,0); SUB_FROM_STATS(NumberOfSize,0); mIsAuto = true; #endif // We must be growing an nsAutoVoidArray - copy since we didn't // realloc. memcpy(newImpl->mArray, mImpl->mArray, mImpl->mCount * sizeof(mImpl->mArray[0])); } SetArray(newImpl, aSize, mImpl ? mImpl->mCount : 0); // no memset; handled later in ReplaceElementAt if needed return true; }