diff options
author | Simon Marlow <marlowsd@gmail.com> | 2013-02-14 08:58:03 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2013-02-14 10:57:10 +0000 |
commit | 88b4578bc82795de48876a250c2b6d7cce380628 (patch) | |
tree | 77b9dd7bee66ad7c1ae542814ccba70c29393c88 /rts/Stable.c | |
parent | 7e7a4e4d7e9e84b2c57d3d55e372e738b5f8dbf5 (diff) | |
download | haskell-88b4578bc82795de48876a250c2b6d7cce380628.tar.gz |
small tidyups and refactorings
Diffstat (limited to 'rts/Stable.c')
-rw-r--r-- | rts/Stable.c | 238 |
1 files changed, 106 insertions, 132 deletions
diff --git a/rts/Stable.c b/rts/Stable.c index ff3843ecd7..e1807faa72 100644 --- a/rts/Stable.c +++ b/rts/Stable.c @@ -103,41 +103,36 @@ Mutex stable_mutex; static void enlargeStableNameTable(void); static void enlargeStablePtrTable(void); -/* This hash table maps Haskell objects to stable names, so that every +/* + * This hash table maps Haskell objects to stable names, so that every * call to lookupStableName on a given object will return the same * stable name. - * - * OLD COMMENTS about reference counting follow. The reference count - * in a stable name entry is now just a counter. - * - * Reference counting - * ------------------ - * A plain stable name entry has a zero reference count, which means - * the entry will dissappear when the object it points to is - * unreachable. For stable pointers, we need an entry that sticks - * around and keeps the object it points to alive, so each stable name - * entry has an associated reference count. - * - * A stable pointer has a weighted reference count N attached to it - * (actually in its upper 5 bits), which represents the weight - * 2^(N-1). The stable name entry keeps a 32-bit reference count, which - * represents any weight between 1 and 2^32 (represented as zero). - * When the weight is 2^32, the stable name table owns "all" of the - * stable pointers to this object, and the entry can be garbage - * collected if the object isn't reachable. - * - * A new stable pointer is given the weight log2(W/2), where W is the - * weight stored in the table entry. The new weight in the table is W - * - 2^log2(W/2). - * - * A stable pointer can be "split" into two stable pointers, by - * dividing the weight by 2 and giving each pointer half. - * When freeing a stable pointer, the weight of the pointer is added - * to the weight stored in the table entry. - * */ + */ static HashTable *addrToStableHash = NULL; +/* ----------------------------------------------------------------------------- + * We must lock the StablePtr table during GC, to prevent simultaneous + * calls to freeStablePtr(). + * -------------------------------------------------------------------------- */ + +void +stableLock(void) +{ + initStableTables(); + ACQUIRE_LOCK(&stable_mutex); +} + +void +stableUnlock(void) +{ + RELEASE_LOCK(&stable_mutex); +} + +/* ----------------------------------------------------------------------------- + * Initialising the tables + * -------------------------------------------------------------------------- */ + STATIC_INLINE void initSnEntryFreeList(snEntry *table, nat n, snEntry *free) { @@ -187,6 +182,44 @@ initStableTables(void) #endif } +/* ----------------------------------------------------------------------------- + * Enlarging the tables + * -------------------------------------------------------------------------- */ + +static void +enlargeStableNameTable(void) +{ + nat old_SNT_size = SNT_size; + + // 2nd and subsequent times + SNT_size *= 2; + stable_name_table = + stgReallocBytes(stable_name_table, + SNT_size * sizeof *stable_name_table, + "enlargeStableNameTable"); + + initSnEntryFreeList(stable_name_table + old_SNT_size, old_SNT_size, NULL); +} + +static void +enlargeStablePtrTable(void) +{ + nat old_SPT_size = SPT_size; + + // 2nd and subsequent times + SPT_size *= 2; + stable_ptr_table = + stgReallocBytes(stable_ptr_table, + SPT_size * sizeof *stable_ptr_table, + "enlargeStablePtrTable"); + + initSpEntryFreeList(stable_ptr_table + old_SPT_size, old_SPT_size, NULL); +} + +/* ----------------------------------------------------------------------------- + * Freeing entries and tables + * -------------------------------------------------------------------------- */ + void exitStableTables(void) { @@ -209,6 +242,40 @@ exitStableTables(void) #endif } +STATIC_INLINE void +freeSnEntry(snEntry *sn) +{ + ASSERT(sn->sn_obj == NULL); + sn->addr = (P_)stable_name_free; + stable_name_free = sn; +} + +STATIC_INLINE void +freeSpEntry(spEntry *sp) +{ + sp->addr = (P_)stable_ptr_free; + stable_ptr_free = sp; +} + +void +freeStablePtrUnsafe(StgStablePtr sp) +{ + ASSERT((StgWord)sp < SPT_size); + freeSpEntry(&stable_ptr_table[(StgWord)sp]); +} + +void +freeStablePtr(StgStablePtr sp) +{ + stableLock(); + freeStablePtrUnsafe(sp); + stableUnlock(); +} + +/* ----------------------------------------------------------------------------- + * Looking up + * -------------------------------------------------------------------------- */ + /* * get at the real stuff...remove indirections. * It untags pointers before dereferencing and @@ -235,12 +302,14 @@ removeIndirections(StgClosure* p) return TAG_CLOSURE(tag,q); } -static StgWord -lookupStableName_(StgPtr p) +StgWord +lookupStableName (StgPtr p) { StgWord sn; void* sn_tmp; + stableLock(); + if (stable_name_free == NULL) { enlargeStableNameTable(); } @@ -259,6 +328,7 @@ lookupStableName_(StgPtr p) if (sn != 0) { ASSERT(stable_name_table[sn].addr == p); debugTrace(DEBUG_stable, "cached stable name %ld at %p",sn,p); + stableUnlock(); return sn; } @@ -271,40 +341,9 @@ lookupStableName_(StgPtr p) /* add the new stable name to the hash table */ insertHashTable(addrToStableHash, (W_)p, (void *)sn); - return sn; -} - -StgWord -lookupStableName(StgPtr p) -{ - StgWord res; - - initStableTables(); - ACQUIRE_LOCK(&stable_mutex); - res = lookupStableName_(p); - RELEASE_LOCK(&stable_mutex); - return res; -} - -STATIC_INLINE void -freeSnEntry(snEntry *sn) -{ - ASSERT(sn->sn_obj == NULL); - if(sn->addr != NULL) { - /* StableName object may die before pointee, in which case we - * need to remove from hash table, or after pointee, in which - * case addr==NULL and we already removed it. */ - removeHashTable(addrToStableHash, (W_)sn->addr, NULL); - } - sn->addr = (P_)stable_name_free; - stable_name_free = sn; -} + stableUnlock(); -STATIC_INLINE void -freeSpEntry(spEntry *sp) -{ - sp->addr = (P_)stable_ptr_free; - stable_ptr_free = sp; + return sn; } StgStablePtr @@ -312,80 +351,15 @@ getStablePtr(StgPtr p) { StgWord sp; - initStableTables(); - ACQUIRE_LOCK(&stable_mutex); + stableLock(); if (!stable_ptr_free) enlargeStablePtrTable(); sp = stable_ptr_free - stable_ptr_table; stable_ptr_free = (spEntry*)(stable_ptr_free->addr); stable_ptr_table[sp].addr = p; - RELEASE_LOCK(&stable_mutex); + stableUnlock(); return (StgStablePtr)(sp); } -void -freeStablePtrUnsafe(StgStablePtr sp) -{ - ASSERT((StgWord)sp < SPT_size); - freeSpEntry(&stable_ptr_table[(StgWord)sp]); -} - -void -freeStablePtr(StgStablePtr sp) -{ - initStableTables(); - ACQUIRE_LOCK(&stable_mutex); - freeStablePtrUnsafe(sp); - RELEASE_LOCK(&stable_mutex); -} - -static void -enlargeStableNameTable(void) -{ - nat old_SNT_size = SNT_size; - - // 2nd and subsequent times - SNT_size *= 2; - stable_name_table = - stgReallocBytes(stable_name_table, - SNT_size * sizeof *stable_name_table, - "enlargeStableNameTable"); - - initSnEntryFreeList(stable_name_table + old_SNT_size, old_SNT_size, NULL); -} - -static void -enlargeStablePtrTable(void) -{ - nat old_SPT_size = SPT_size; - - // 2nd and subsequent times - SPT_size *= 2; - stable_ptr_table = - stgReallocBytes(stable_ptr_table, - SPT_size * sizeof *stable_ptr_table, - "enlargeStablePtrTable"); - - initSpEntryFreeList(stable_ptr_table + old_SPT_size, old_SPT_size, NULL); -} - -/* ----------------------------------------------------------------------------- - * We must lock the StablePtr table during GC, to prevent simultaneous - * calls to freeStablePtr(). - * -------------------------------------------------------------------------- */ - -void -stableLock(void) -{ - initStableTables(); - ACQUIRE_LOCK(&stable_mutex); -} - -void -stableUnlock(void) -{ - RELEASE_LOCK(&stable_mutex); -} - /* ----------------------------------------------------------------------------- * Treat stable pointers as roots for the garbage collector. * -------------------------------------------------------------------------- */ |