PERFORCE change 12187 for review
[email protected] (Chris Nandor) Tue, 25 Sep 2001 00:09:48 -0400
| Newsgroups | perl.perl5.changes.mac |
|---|---|
| Message-ID | <p05100311b7d5b40838bf@[10.0.1.177]> |
Change 12187 by pudge@pudge-mobile on 2001/09/25 02:11:13
Make malloc smarter, fix bugs. (Bug #404030)
Affected files ...
... //depot/maint-5.6/macperl/macos/icemalloc.c#2 edit
... //depot/maint-5.6/macperl/macos/icemalloc.h#2 edit
Differences ...
==== //depot/maint-5.6/macperl/macos/icemalloc.c#2 (text) ====
Index: perl/macos/icemalloc.c
--- perl/macos/icemalloc.c.~1~ Mon Sep 24 20:15:05 2001
+++ perl/macos/icemalloc.c Mon Sep 24 20:15:05 2001
@@ -3,6 +3,15 @@
File : icemalloc.c - Memory allocator
$Log: icemalloc.c,v $
+Revision 1.4 2001/09/24 06:03:35 neeri
+Backwards pointers in linked bucket list were not maintained properly (MacPerl Bug#404030)
+
+Revision 1.3 2001/09/18 09:03:46 neeri
+Off by one error in bucket search routine (MacPerl Bug#404030)
+
+Revision 1.2 2001/09/14 08:10:36 neeri
+Make realloc smarter (MacPerl bug $404030)
+
Revision 1.1 2000/08/14 01:48:17 neeri
Checked into Sourceforge
@@ -180,7 +189,6 @@
/* DISPATCH_START */
void free(void * ptr)
{
-
pool_free((char *) ptr);
}
/* DISPATCH_END */
@@ -195,31 +203,48 @@
/* DISPATCH_START */
void * realloc(void * old, u_long size)
{
- void * nu;
+ _mem_pool_ptr pool;
+ char * mem;
+
+ pool = _default_mem_pool;
+ if (pool == (_mem_pool_ptr)0)
+ return (char *)0;
- nu = malloc(size);
-
- if (!old || !nu)
- return nu;
-
- memcpy(nu, old, size);
-
- free(old);
-
- return nu;
+ mem = pool_realloc(pool, old, size);
+
+ return mem;
}
/* DISPATCH_END */
void * pool_realloc(_mem_pool_ptr pool, void * old, u_long size)
{
void * nu;
+ u_long old_size = pool_size(old);
+
+ /*
+ * To prevent excessive reallocations, we impose growth and
+ * shrinkage minima.
+ */
+
+ const int growth_fraction = 5;
+ const int shrink_fraction = 3;
+ if (size > old_size) { /* Growing */
+ if (((size - old_size) << growth_fraction) < old_size) /* Proposed growth too small, increase it */
+ size = old_size + (old_size >> growth_fraction);
+ } else { /* Shrinking */
+ if (old_size < 65 && (size << 1) > old_size) /* Bucket allocation is by power of two, so don't shrink earlier */
+ return old;
+ if (((old_size - size) << shrink_fraction) < old_size) /* Proposed shrinkage too insignificant, omit it */
+ return old;
+ }
+
nu = pool_malloc(pool, size);
if (!old || !nu)
return nu;
- memcpy(nu, old, size);
+ memcpy(nu, old, old_size < size ? old_size : size);
pool_free(old);
@@ -521,7 +546,8 @@
#endif
bucket->prev = (_mem_bucket_ptr) buckets;
- bucket->next = *buckets;
+ if (bucket->next = *buckets)
+ bucket->next->prev = bucket;
*buckets = bucket;
bucket->pool = pool;
bucket->max_count = max;
@@ -635,13 +661,86 @@
#ifdef DOCUMENTATION
+ pool_size() determines the size of an allocated block.
+
+#endif
+
+static u_long _pool_find_ptr_bucket_size(char * ptr);
+static u_long _pool_find_ptr_blk_size(char * ptr);
+
+u_long pool_size(void * ptr)
+{
+ u_long ptr_size;
+
+ if (!ptr)
+ return 0;
+
+ ptr_size = _pool_find_ptr_bucket_size(ptr);
+ if (!ptr_size)
+ ptr_size = _pool_find_ptr_blk_size(ptr);
+
+#ifdef MALLOC_LOG
+ MallocLog("sz %d %d\n", (int) ptr, (int) ptr_size);
+#endif
+
+ return ptr_size;
+}
+
+#ifdef DOCUMENTATION
+
+ _pool_find_ptr_bucket_size() finds size of a pointer allocated in a bucket.
+
+#endif
+
+u_long _pool_find_ptr_bucket_size(char * ptr)
+{
+ _mem_pool_ptr pool;
+ _mem_bucket_ptr bucket;
+
+ /*
+ ** Since the default list is stored at the front of the forest list,
+ ** we inherently search the default forest first. Nice.
+ */
+ pool = _mem_pool_forest;
+
+ while (pool != (_mem_pool_ptr)0) {
+ if (bucket = pool->free_16)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
+ return 16;
+ }
+ if (bucket = pool->free_32)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
+ return 32;
+ }
+ if (bucket = pool->free_64)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
+ return 64;
+ }
+
+ for (bucket = pool->blk_16; bucket; bucket = bucket->next)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
+ return 16;
+ for (bucket = pool->blk_32; bucket; bucket = bucket->next)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
+ return 32;
+ for (bucket = pool->blk_64; bucket; bucket = bucket->next)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
+ return 64;
+
+ pool = pool->next;
+ }
+
+ return 0;
+}
+
+#ifdef DOCUMENTATION
+
pool_free() does the low level work of a free().
#endif
static _mem_bucket_ptr _pool_find_ptr_bucket(char * ptr);
-static int _block_is_freed(_mem_blk_ptr blk);
-static _mem_blk_ptr _pool_find_ptr_blk(char * ptr);
+static _mem_blk_ptr _pool_find_ptr_blk(char * ptr);
int pool_free(void * ptr)
{
@@ -1044,7 +1143,7 @@
#ifdef DOCUMENTATION
- _pool_find_ptr_blk() finds the block containing this pointer in "ptr".
+ _pool_find_ptr_bucket() finds the bucket containing this pointer in "ptr".
#endif
@@ -1061,32 +1160,32 @@
while (pool != (_mem_pool_ptr)0) {
if (bucket = pool->free_16)
- if (ptr > bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
if (bucket->free_count+1 == bucket->max_count)
pool->free_16 = nil;
return bucket;
}
if (bucket = pool->free_32)
- if (ptr > bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
if (bucket->free_count+1 == bucket->max_count)
pool->free_32 = nil;
return bucket;
}
if (bucket = pool->free_64)
- if (ptr > bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size) {
if (bucket->free_count+1 == bucket->max_count)
pool->free_64 = nil;
return bucket;
}
for (bucket = pool->blk_16; bucket; bucket = bucket->next)
- if (ptr > bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
return bucket;
for (bucket = pool->blk_32; bucket; bucket = bucket->next)
- if (ptr > bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
return bucket;
for (bucket = pool->blk_64; bucket; bucket = bucket->next)
- if (ptr > bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
+ if (ptr >= bucket->memory && ptr < bucket->memory + pool->pref_blk_size)
return bucket;
pool = pool->next;
@@ -1123,6 +1222,18 @@
return (_mem_blk_ptr)0;
}
+u_long _pool_find_ptr_blk_size(char * ptr)
+{
+ _mem_blk_ptr blk = _pool_find_ptr_blk(ptr);
+
+ if (!blk) {
+ return 0;
+ } else {
+ _mem_ptr_hdr_ptr hdr = (_mem_ptr_hdr_ptr) ( (u_long)ptr - sizeof(_mem_ptr_hdr) );
+
+ return GET_PTR_SIZE(hdr);
+ }
+}
#ifdef DOCUMENTATION
==== //depot/maint-5.6/macperl/macos/icemalloc.h#2 (text) ====
Index: perl/macos/icemalloc.h
--- perl/macos/icemalloc.h.~1~ Mon Sep 24 20:15:05 2001
+++ perl/macos/icemalloc.h Mon Sep 24 20:15:05 2001
@@ -3,6 +3,9 @@
File : icemalloc.h - Memory allocator
$Log: icemalloc.h,v $
+Revision 1.2 2001/09/14 08:10:36 neeri
+Make realloc smarter (MacPerl bug $404030)
+
Revision 1.1 2000/08/14 01:48:17 neeri
Checked into Sourceforge
@@ -195,6 +198,7 @@
void * pool_malloc(_mem_pool_ptr pool, u_long size);
void * pool_realloc(_mem_pool_ptr pool, void * ptr, u_long size);
int pool_free(void * ptr);
+u_long pool_size(void * ptr);
int free_pool(int id);
int free_pool_memory(int id);
_mem_pool_ptr find_pool(int id);
End of Patch.