Commit 88b4578b authored by Simon Marlow's avatar Simon Marlow

small tidyups and refactorings

parent 7e7a4e4d
......@@ -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.
* -------------------------------------------------------------------------- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment