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.

Reply via email to