From 63fff83ae240cb211307cfb07d5ae0a7fbe7eb56 Mon Sep 17 00:00:00 2001 From: "dp%netscape.com" Date: Thu, 24 Jan 2002 07:00:07 +0000 Subject: [PATCH] bug 118061 Enabling nsRecyclingAllocator r=dveditz sr=sfraser --- modules/libjar/nsJARFactory.cpp | 4 +- modules/libjar/nsZipArchive.cpp | 161 ++----------------- modules/libpr0n/decoders/gif/GIF2.cpp | 151 ++--------------- modules/libpr0n/decoders/gif/nsGIFModule.cpp | 4 +- 4 files changed, 37 insertions(+), 283 deletions(-) diff --git a/modules/libjar/nsJARFactory.cpp b/modules/libjar/nsJARFactory.cpp index 030754fae0f7..c263f3ebd92d 100644 --- a/modules/libjar/nsJARFactory.cpp +++ b/modules/libjar/nsJARFactory.cpp @@ -36,10 +36,10 @@ #include "nsCOMPtr.h" #include "nsIModule.h" #include "nsIGenericFactory.h" - #include "nsJAR.h" #include "nsIJARFactory.h" -#include "nsZlibAllocator.h" +#include "nsRecyclingAllocator.h" +extern nsRecyclingAllocator *gZlibAllocator; // The list of components we register static nsModuleComponentInfo components[] = diff --git a/modules/libjar/nsZipArchive.cpp b/modules/libjar/nsZipArchive.cpp index 59df7ad32010..d9247994e197 100644 --- a/modules/libjar/nsZipArchive.cpp +++ b/modules/libjar/nsZipArchive.cpp @@ -44,14 +44,16 @@ #define READTYPE PRInt32 #include "zlib.h" #include "nsISupportsUtils.h" -#include "nsZlibAllocator.h" +#include "nsRecyclingAllocator.h" /** * Globals * * Global allocator used with zlib. Destroyed in module shutdown. */ -nsZlibAllocator *gZlibAllocator = NULL; +#define NBUCKETS 6 +#define BY4ALLOC_ITEMS 320 +nsRecyclingAllocator *gZlibAllocator = NULL; #else /* STANDALONE */ @@ -382,148 +384,17 @@ void ProcessWindowsMessages() // we startup and disabled after we startup if memory is a concern. //*********************************************************** -void * nsZlibAllocator::zAlloc(PRUint32 items, PRUint32 bytes) -{ - PRUint32 totalsize = items * bytes; - PRInt32 freeAllocatedBucketIndex = -1; - PRUint32 i; - PRUint32 size; - void *ptr; - - for (i = 0; i < NBUCKETS; i++) - { - size = mMemBucket[i].size; - ptr = mMemBucket[i].ptr; - - // Dont look at buckets with no memory allocated or less memory than - // what we need. - // Can we do this check without claiming the bucket? I think we can - // because the next thing we do is try claim this bucket. - if (!ptr || size < totalsize) - continue; - - // Try Claim a bucket. If we cant, skip it. - if (!Claim(i)) - continue; - - if (size == totalsize) - { - // Let go of any freeAllocatedBucket that we claimed - if (freeAllocatedBucketIndex >= 0) - Unclaim(freeAllocatedBucketIndex); - - // zero out memory and return it - memset(ptr, 0, totalsize); - return ptr; - } - // Meanwhile, remember a free allocated bucket. - // At this point we know the bucket is not in use and it has more - // than what we need - if (freeAllocatedBucketIndex < 0) - freeAllocatedBucketIndex = i; - else - { - // See if this bucket is closer to what we need - if (size < mMemBucket[freeAllocatedBucketIndex].size) - { - Unclaim(freeAllocatedBucketIndex); - freeAllocatedBucketIndex = i; - } - else - // Undo our claim as freeAllocatedBucketIndex does better than this one - Unclaim(i); - } - } - - // See if we have an allocated bucket - if (freeAllocatedBucketIndex >= 0) - { - ptr = mMemBucket[freeAllocatedBucketIndex].ptr; - // Clear it, Mark it used and return ptr - // We need to clear only the size that was requested although - // the bucket may be larger - memset(ptr, 0, totalsize); - return ptr; - } - - // We dont have that memory already - // Allocate. Make sure we bump up our allocations of x4 allocations - int realitems = items; - if (bytes == 4 && items < BY4ALLOC_ITEMS) - realitems = BY4ALLOC_ITEMS; - ptr = calloc(realitems, bytes); - - // Take care of no memory situation - if (!ptr) - return ptr; - - // Find a free unallocated bucket and store allocation - for (i = 0; i < NBUCKETS; i++) - { - // If bucket cannot be calimed, continue search. - if (!Claim(i)) - continue; - - if (!mMemBucket[i].ptr) - { - // Found free slot. Store it - mMemBucket[i].ptr = ptr; - mMemBucket[i].size = realitems * bytes; - return ptr; - } - - // This is an already allocated bucket. Cant use this one. - Unclaim(i); - } -#ifdef DEBUG_dp - // Warn if we are failing over to calloc and not storing it - // This says we have a misdesigned memory pool. The intent was - // once the pool was full, we would never fail over to calloc. - printf("zalloc %d [%dx%d] - FAILOVER 0x%p Memory pool has sizes: ", - items*bytes, items, bytes, ptr); - for (i = 0; i < NBUCKETS; i++) - { - printf("%d ", mMemBucket[i].size); - } - printf("\n"); -#endif - - return ptr; -} - -void nsZlibAllocator::zFree(void *ptr) -{ - PRUint32 i; - - for (i = 0; i < NBUCKETS; i++) - { - if (mMemBucket[i].ptr == ptr) - { - // Ah ha. One of the slots we allocated. - // Nothing to do. Mark it unused. - Unclaim(i); - return; - } - } - -#ifdef DEBUG_dp - // Warn if we are failing over to free. - // This says we have a misdesigned memory pool. The intent was - // once the pool was full, we would never fail over to free. - printf("DEBUG: zlib memory pool freeing 0x%p\n", ptr); -#endif - - // Failover to free - free(ptr); - return; -} - PR_STATIC_CALLBACK(void *) zlibAlloc(void *opaque, uInt items, uInt size) { - nsZlibAllocator *zallocator = (nsZlibAllocator *)opaque; - if (zallocator) - return zallocator->zAlloc(items, size); + nsRecyclingAllocator *zallocator = (nsRecyclingAllocator *)opaque; + if (zallocator) { + // Bump up x4 allocations + PRUint32 realitems = items; + if (size == 4 && items < BY4ALLOC_ITEMS) + realitems = BY4ALLOC_ITEMS; + return zallocator->Calloc(realitems, size); + } else return calloc(items, size); } @@ -531,9 +402,9 @@ zlibAlloc(void *opaque, uInt items, uInt size) PR_STATIC_CALLBACK(void) zlibFree(void *opaque, void *ptr) { - nsZlibAllocator *zallocator = (nsZlibAllocator *)opaque; + nsRecyclingAllocator *zallocator = (nsRecyclingAllocator *)opaque; if (zallocator) - zallocator->zFree(ptr); + zallocator->Free(ptr); else free(ptr); return; @@ -1063,7 +934,7 @@ PRInt32 nsZipArchive::BuildFileList() //-- we think we found the central directory, read in the first chunk pos = 0; bufsize = PR_Read( mFd, &buf, sizeof(buf) ); - if (bufsize < sizeof(ZipCentral) + sizeof(ZipEnd)) + if (bufsize < (PRInt32)(sizeof(ZipCentral) + sizeof(ZipEnd))) { // We know we read the end sig and got pointed at the central // directory--there should be at least this much @@ -1404,7 +1275,7 @@ PRInt32 nsZipArchive::InflateItem( const nsZipItem* aItem, PRFileDesc* fOut, #ifndef STANDALONE //-- ensure we have our zlib allocator for better performance if (!gZlibAllocator) { - gZlibAllocator = new nsZlibAllocator(); + gZlibAllocator = new nsRecyclingAllocator(NBUCKETS); } zs.zalloc = zlibAlloc; diff --git a/modules/libpr0n/decoders/gif/GIF2.cpp b/modules/libpr0n/decoders/gif/GIF2.cpp index c14da9d69b99..592a7a15ee52 100644 --- a/modules/libpr0n/decoders/gif/GIF2.cpp +++ b/modules/libpr0n/decoders/gif/GIF2.cpp @@ -76,11 +76,23 @@ mailing address. #include "prlog.h" #include "GIF2.h" #include "nsCRT.h" -#include "nsGifAllocator.h" +#include "nsRecyclingAllocator.h" #include "nsAutoLock.h" -// Global gif allocator -nsGifAllocator *gGifAllocator = nsnull; +/******************************************************************************* + * Gif decoder allocator + * + * For every image that gets loaded, we allocate + * 4097 x 2 : gs->prefix + * 4097 x 1 : gs->suffix + * 4097 x 1 : gs->stack + * for lzw to operate on the data. These are held for a very short interval + * and freed. This allocator tries to keep one set of these around + * and reuses them; automatically fails over to use calloc/free when all + * buckets are full. + */ +const int kGifAllocatorNBucket = 6; +nsRecyclingAllocator *gGifAllocator = nsnull; #define HOWMANY(x, r) (((x) + ((r) - 1)) / (r)) #define ROUNDUP(x, r) (HOWMANY(x, r) * (r)) @@ -452,142 +464,11 @@ PRBool gif_create(gif_struct **gs) return PR_TRUE; } -/******************************************************************************* - * Gif decoder allocator - * - * For every image that gets loaded, we allocate - * 4097 x 2 : gs->prefix - * 4097 x 1 : gs->suffix - * 4097 x 1 : gs->stack - * for lzw to operate on the data. These are held for a very short interval - * and freed. This allocator tries to keep one set of these around - * and reuses them; automatically fails over to use calloc/free when all - * buckets are full. - */ - -void -nsGifAllocator::ClearBuckets() -{ - nsAutoLock autolock(mLock); - - for (PRUint32 i = 0; i < kNumBuckets; i++) - { - if (mMemBucket[i]) - { - // If the bucket is in use, then we will leak that memory. - PR_ASSERT(!IsUsed(i)); - if (!IsUsed(i)) - { - free(mMemBucket[i]); - } - mMemBucket[i] = nsnull; - mSize[i] = 0; - } - } - - // Clear the in use flag of all buckets - mFlag = 0; -} - -void * -nsGifAllocator::Calloc(PRUint32 items, PRUint32 size) -{ - PRUint32 totalsize = items * size; - PRInt32 freeAllocatedBucket = -1; - nsAutoLock autolock(mLock); - PRUint32 i; - - for (i = 0; i < kNumBuckets; i++) { - // if bucket is in use or has no memory, dont touch it. - if (IsUsed(i) || !mMemBucket[i]) - continue; - - // See if we have the memory already allocated. This is the - // most common case. - if (mSize[i] == totalsize) { - // Exact match. zero out memory, increase refcnt and return it - memset(mMemBucket[i], 0, totalsize); - MarkUsed(i); - return mMemBucket[i]; - } - - // Meanwhile, remember a free bucket that has enough memory - if (mSize[i] >= totalsize) - freeAllocatedBucket = i; - } - - // See if we have an allocated bucket - if (freeAllocatedBucket >= 0) { - // Clear it, Mark it used and return ptr - // We need to clear only the size that was requested although - // the bucket may be larger - memset(mMemBucket[freeAllocatedBucket], 0, totalsize); - MarkUsed(freeAllocatedBucket); - return mMemBucket[freeAllocatedBucket]; - } - - // Make sure we are not holding on to a lock - autolock.unlock(); - - void *ptr = calloc(items, size); - - // Reaquire the lock - autolock.lock(); - - // Find a free bucket and store allocation - for (i = 0; i < kNumBuckets; i++) - if (!mMemBucket[i]) { - // Found free slot. Store it - PR_ASSERT(!IsUsed(i)); - mMemBucket[i] = ptr; - mSize[i] = totalsize; - MarkUsed(i); - return ptr; - } -#ifdef DEBUG_dp - // Warn if we are failing over to calloc and not storing it - // This says we have a misdesigned memory pool. The intent was - // once the pool was full, we would never fail over to calloc. - printf("0x%p - Calloc %d [%dx%d] - FAILOVER 0x%p Memory pool has sizes: ", - this, items*size, items, size, ptr); - for (i = 0; i < kNumBuckets; i++) - { - printf("%d ", mSize[i]); - } - printf("\n"); -#endif - - return ptr; -} - -void nsGifAllocator::Free(void *ptr) -{ - nsAutoLock autolock(mLock); - - for (PRUint32 i = 0; i < kNumBuckets; i++) - { - if (mMemBucket[i] == ptr) - { - // Ah ha. One of the slots we allocated. - // Nothing to do. Mark it unused. - ClearUsed(i); - return; - } - } - - // Release lock before calling free - autolock.unlock(); - - // Failover to free - free(ptr); - return; -} - static inline void * gif_calloc(size_t n, size_t s) { if (!gGifAllocator) - gGifAllocator = new nsGifAllocator; + gGifAllocator = new nsRecyclingAllocator(kGifAllocatorNBucket); if (gGifAllocator) return gGifAllocator->Calloc(n, s); else diff --git a/modules/libpr0n/decoders/gif/nsGIFModule.cpp b/modules/libpr0n/decoders/gif/nsGIFModule.cpp index 992da76db3ea..fdeef8595ab5 100644 --- a/modules/libpr0n/decoders/gif/nsGIFModule.cpp +++ b/modules/libpr0n/decoders/gif/nsGIFModule.cpp @@ -41,7 +41,9 @@ #include "nsIGenericFactory.h" #include "nsISupports.h" #include "nsCOMPtr.h" -#include "nsGifAllocator.h" +#include "nsRecyclingAllocator.h" + +extern nsRecyclingAllocator *gGifAllocator; NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIFDecoder2)