summaryrefslogtreecommitdiff
path: root/ghc/rts/Hash.c
diff options
context:
space:
mode:
authorsimonmar <unknown>2001-11-26 13:06:49 +0000
committersimonmar <unknown>2001-11-26 13:06:49 +0000
commit18ea22a1d98fc9d5a12c69ed140053300fc887d5 (patch)
treecc6c9ae168c17a94d89d81e5d8669262e4d81b01 /ghc/rts/Hash.c
parentd6181fe1c1584b4e5f12e4dd58b26cfd5b68c560 (diff)
downloadhaskell-18ea22a1d98fc9d5a12c69ed140053300fc887d5.tar.gz
[project @ 2001-11-26 13:06:49 by simonmar]
Use an arena internally to allocate hash bucket cells instead of the current home-brewed combination of malloc/free and a free list. We still allocate hash table segments using malloc/free because these are large (4k by default) and might interact badly with the blockish nature of the arena allocator.
Diffstat (limited to 'ghc/rts/Hash.c')
-rw-r--r--ghc/rts/Hash.c60
1 files changed, 16 insertions, 44 deletions
diff --git a/ghc/rts/Hash.c b/ghc/rts/Hash.c
index 9b9e98a3df..ba0746f408 100644
--- a/ghc/rts/Hash.c
+++ b/ghc/rts/Hash.c
@@ -1,5 +1,5 @@
/*-----------------------------------------------------------------------------
- * $Id: Hash.c,v 1.6 2001/08/14 13:40:09 sewardj Exp $
+ * $Id: Hash.c,v 1.7 2001/11/26 13:06:49 simonmar Exp $
*
* (c) The AQUA Project, Glasgow University, 1995-1998
* (c) The GHC Team, 1999
@@ -13,6 +13,7 @@
#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 */
@@ -46,6 +47,7 @@ struct hashtable {
HashList **dir[HDIRSIZE]; /* Directory of segments */
HashFunction *hash; /* hash function */
CompareFunction *compare; /* key comparison function */
+ Arena *arena;
};
/* -----------------------------------------------------------------------------
@@ -119,7 +121,6 @@ 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
@@ -202,39 +203,6 @@ 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)
{
@@ -254,7 +222,7 @@ insertHashTable(HashTable *table, StgWord key, void *data)
segment = bucket / HSEGSIZE;
index = bucket % HSEGSIZE;
- hl = allocHashList();
+ hl = arenaAlloc(table->arena, sizeof(struct hashlist));
hl->key = key;
hl->data = data;
@@ -300,7 +268,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;
@@ -310,21 +278,23 @@ 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) {
- while (index >= 0) {
- for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
- next = hl->next;
- if (freeDataFun != NULL)
+ if (freeDataFun != NULL) {
+ while (index >= 0) {
+ for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
+ next = hl->next;
(*freeDataFun)(hl->data);
- freeHashList(hl);
+ }
+ index--;
}
- index--;
}
free(table->dir[segment]);
segment--;
index = HSEGSIZE - 1;
}
+
+ arenaFree(table->arena);
free(table);
}
@@ -341,6 +311,8 @@ 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++)