[project @ 2002-04-09 12:55:11 by simonmar]
authorsimonmar <unknown>
Tue, 9 Apr 2002 12:55:11 +0000 (12:55 +0000)
committersimonmar <unknown>
Tue, 9 Apr 2002 12:55:11 +0000 (12:55 +0000)
- Revert rev. 1.7, i.e. go back to using malloc/free and a free list
  to manage hash list cells, because the arena method doesn't recycle
  used cells, resulting in memory leaks.

- Add a freeHashList() call which was missing in removeHashTable().

ghc/rts/Hash.c

index ba0746f..05f2b19 100644 (file)
@@ -1,5 +1,5 @@
 /*-----------------------------------------------------------------------------
- * $Id: Hash.c,v 1.7 2001/11/26 13:06:49 simonmar Exp $
+ * $Id: Hash.c,v 1.8 2002/04/09 12:55:11 simonmar Exp $
  *
  * (c) The AQUA Project, Glasgow University, 1995-1998
  * (c) The GHC Team, 1999
@@ -13,7 +13,6 @@
 #include "Rts.h"
 #include "Hash.h"
 #include "RtsUtils.h"
-#include "Arena.h"
 
 #define HSEGSIZE    1024    /* Size of a single hash table segment */
                            /* Also the minimum size of a hash table */
@@ -47,7 +46,6 @@ struct hashtable {
     HashList **dir[HDIRSIZE];  /* Directory of segments */
     HashFunction *hash;                /* hash function */
     CompareFunction *compare;   /* key comparison function */
-    Arena *arena;
 };
 
 /* -----------------------------------------------------------------------------
@@ -121,6 +119,7 @@ allocSegment(HashTable *table, int segment)
                                         "allocSegment");
 }
 
+
 /* -----------------------------------------------------------------------------
  * Expand the larger hash table by one bucket, and split one bucket
  * from the smaller table into two parts.  Only the bucket referenced
@@ -203,6 +202,39 @@ lookupHashTable(HashTable *table, StgWord key)
     return NULL;
 }
 
+/* -----------------------------------------------------------------------------
+ * We allocate the hashlist cells in large chunks to cut down on malloc
+ * overhead.  Although we keep a free list of hashlist cells, we make
+ * no effort to actually return the space to the malloc arena.
+ * -------------------------------------------------------------------------- */
+
+static HashList *freeList = NULL;
+
+static HashList *
+allocHashList(void)
+{
+    HashList *hl, *p;
+
+    if ((hl = freeList) != NULL) {
+       freeList = hl->next;
+    } else {
+        hl = stgMallocBytes(HCHUNK * sizeof(HashList), "allocHashList");
+
+       freeList = hl + 1;
+       for (p = freeList; p < hl + HCHUNK - 1; p++)
+           p->next = p + 1;
+       p->next = NULL;
+    }
+    return hl;
+}
+
+static void
+freeHashList(HashList *hl)
+{
+    hl->next = freeList;
+    freeList = hl;
+}
+
 void
 insertHashTable(HashTable *table, StgWord key, void *data)
 {
@@ -222,7 +254,7 @@ insertHashTable(HashTable *table, StgWord key, void *data)
     segment = bucket / HSEGSIZE;
     index = bucket % HSEGSIZE;
 
-    hl = arenaAlloc(table->arena, sizeof(struct hashlist));
+    hl = allocHashList();
 
     hl->key = key;
     hl->data = data;
@@ -250,6 +282,7 @@ removeHashTable(HashTable *table, StgWord key, void *data)
                table->dir[segment][index] = hl->next;
            else
                prev->next = hl->next;
+           freeHashList(hl);
            table->kcount--;
            return hl->data;
        }
@@ -268,7 +301,7 @@ removeHashTable(HashTable *table, StgWord key, void *data)
  * -------------------------------------------------------------------------- */
 
 void
-freeHashTable( HashTable *table, void (*freeDataFun)(void *) )
+freeHashTable(HashTable *table, void (*freeDataFun)(void *) )
 {
     long segment;
     long index;
@@ -278,23 +311,21 @@ freeHashTable( HashTable *table, void (*freeDataFun)(void *) )
     /* The last bucket with something in it is table->max + table->split - 1 */
     segment = (table->max + table->split - 1) / HSEGSIZE;
     index = (table->max + table->split - 1) % HSEGSIZE;
-    
+
     while (segment >= 0) {
-       if (freeDataFun != NULL) {
-           while (index >= 0) {
-               for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
-                   next = hl->next;
+       while (index >= 0) {
+           for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
+               next = hl->next;
+               if (freeDataFun != NULL)
                    (*freeDataFun)(hl->data);
-               }
-               index--;
+               freeHashList(hl);
            }
+           index--;
        }
        free(table->dir[segment]);
        segment--;
        index = HSEGSIZE - 1;
     }
-
-    arenaFree(table->arena);
     free(table);
 }
 
@@ -311,8 +342,6 @@ allocHashTable_(HashFunction *hash, CompareFunction *compare)
 
     table = stgMallocBytes(sizeof(HashTable),"allocHashTable");
 
-    table->arena = newArena();
-
     allocSegment(table, 0);
 
     for (hb = table->dir[0]; hb < table->dir[0] + HSEGSIZE; hb++)