Commit 560bf0f6 authored by simonmar's avatar simonmar

[project @ 2001-11-21 10:09:15 by simonmar]

Turn the weighted reference count in a StablePtr into a simple counter
in the stable ptr table.  We never made use of the weighted count, and
it caused problems when making many StablePtrs to the same object.

In the future we could remove the reference counting altogether and
just make a new StablePtr each time, rather than attempting to use an
existing one.  This would save on the hash table lookup at creation
time.
parent 1222b052
/* -----------------------------------------------------------------------------
* $Id: Stable.h,v 1.9 2001/10/23 11:28:02 simonmar Exp $
* $Id: Stable.h,v 1.10 2001/11/21 10:09:15 simonmar Exp $
*
* (c) The GHC Team, 1998-2000
*
......@@ -14,9 +14,6 @@
*
* ----------------------------------------------------------------------------*/
#define STABLEPTR_WEIGHT_MASK ((StgWord)0xff << ((sizeof(StgWord)-1) * BITS_PER_BYTE))
#define STABLEPTR_WEIGHT_SHIFT (BITS_IN(StgWord) - 8)
/* -----------------------------------------------------------------------------
External C Interface
-------------------------------------------------------------------------- */
......@@ -33,7 +30,7 @@ extern StgStablePtr getStablePtr(StgPtr p);
typedef struct {
StgPtr addr; /* Haskell object, free list, or NULL */
StgPtr old; /* old Haskell object, used during GC */
StgWord weight; /* used for reference counting */
StgWord ref; /* used for reference counting */
StgClosure *sn_obj; /* the StableName object (or NULL) */
} snEntry;
......@@ -45,29 +42,27 @@ extern DLL_IMPORT_RTS unsigned int SPT_size;
extern inline StgPtr
deRefStablePtr(StgStablePtr sp)
{
ASSERT(stable_ptr_table[stgCast(StgWord,sp) & ~STABLEPTR_WEIGHT_MASK].weight > 0);
return stable_ptr_table[stgCast(StgWord,sp) & ~STABLEPTR_WEIGHT_MASK].addr;
ASSERT(stable_ptr_table[(StgWord)sp].ref > 0);
return stable_ptr_table[(StgWord)sp].addr;
}
extern inline void
freeStablePtr(StgStablePtr sp)
{
StgWord sn = stgCast(StgWord,sp) & ~STABLEPTR_WEIGHT_MASK;
ASSERT(sn < SPT_size
&& stable_ptr_table[sn].addr != NULL
&& stable_ptr_table[sn].weight > 0);
stable_ptr_table[sn].weight +=
1 << ((((StgWord)sp & STABLEPTR_WEIGHT_MASK) >> STABLEPTR_WEIGHT_SHIFT) - 1);
StgWord sn = (StgWord)sp;
ASSERT(sn < SPT_size
&& stable_ptr_table[sn].addr != NULL
&& stable_ptr_table[sn].ref > 0);
stable_ptr_table[sn].ref --;
}
extern inline StgStablePtr
splitStablePtr(StgStablePtr sp)
{
/* doesn't need access to the stable pointer table */
StgWord weight = (stgCast(StgWord,sp) & STABLEPTR_WEIGHT_MASK) / 2;
return stgCast(StgStablePtr,(stgCast(StgWord,sp) & ~STABLEPTR_WEIGHT_MASK) + weight);
stable_ptr_table[(StgWord)sp].ref ++;
return sp;
}
/* No deRefStableName, because the existence of a stable name doesn't
......
/* -----------------------------------------------------------------------------
* $Id: Stable.c,v 1.17 2001/08/14 13:40:09 sewardj Exp $
* $Id: Stable.c,v 1.18 2001/11/21 10:09:16 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
......@@ -96,6 +96,9 @@ unsigned int SPT_size;
* 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
......@@ -134,7 +137,7 @@ initFreeList(snEntry *table, nat n, snEntry *free)
for (p = table + n - 1; p >= table; p--) {
p->addr = (P_)free;
p->old = NULL;
p->weight = 0;
p->ref = 0;
p->sn_obj = NULL;
free = p;
}
......@@ -196,7 +199,7 @@ lookupStableName(StgPtr p)
} else {
sn = stable_ptr_free - stable_ptr_table;
(P_)stable_ptr_free = stable_ptr_free->addr;
stable_ptr_table[sn].weight = 0;
stable_ptr_table[sn].ref = 0;
stable_ptr_table[sn].addr = p;
stable_ptr_table[sn].sn_obj = NULL;
/* IF_DEBUG(stable,fprintf(stderr,"new stable name %d at
......@@ -214,7 +217,7 @@ freeStableName(snEntry *sn)
{
ASSERT(sn->sn_obj == NULL);
if (sn->addr != NULL) {
removeHashTable(addrToStableHash, (W_)sn->addr, NULL);
removeHashTable(addrToStableHash, (W_)sn->addr, NULL);
}
sn->addr = (P_)stable_ptr_free;
stable_ptr_free = sn;
......@@ -223,26 +226,11 @@ freeStableName(snEntry *sn)
StgStablePtr
getStablePtr(StgPtr p)
{
StgWord sn = lookupStableName(p);
StgWord weight, n;
weight = stable_ptr_table[sn].weight;
if (weight == 0) {
weight = (StgWord)1 << (BITS_IN(StgWord)-1);
stable_ptr_table[sn].weight = weight;
return (StgStablePtr)(sn + (BITS_IN(StgWord) << STABLEPTR_WEIGHT_SHIFT));
}
else if (weight == 1) {
barf("getStablePtr: too light");
}
else {
weight /= 2;
/* find log2(weight) */
for (n = 0; weight != 1; n++) {
weight >>= 1;
}
stable_ptr_table[sn].weight -= 1 << n;
return (StgStablePtr)(sn + ((n+1) << STABLEPTR_WEIGHT_SHIFT));
}
StgWord sn;
sn = lookupStableName(p);
stable_ptr_table[sn].ref++;
return (StgStablePtr)(sn);
}
void
......@@ -277,7 +265,7 @@ enlargeStablePtrTable(void)
/* -----------------------------------------------------------------------------
* Treat stable pointers as roots for the garbage collector.
*
* A stable pointer is any stable name entry with a weight > 0. We'll
* A stable pointer is any stable name entry with a ref > 0. We'll
* take the opportunity to zero the "keep" flags at the same time.
* -------------------------------------------------------------------------- */
......@@ -304,8 +292,8 @@ markStablePtrTable(evac_fn evac)
// the hash table later.
p->old = p->addr;
// if the weight is non-zero, treat addr as a root
if (p->weight != 0) {
// if the ref is non-zero, treat addr as a root
if (p->ref != 0) {
evac((StgClosure **)&p->addr);
}
}
......@@ -346,7 +334,7 @@ threadStablePtrTable( evac_fn evac )
*
* A dead entry has:
*
* - a weight of zero (i.e. 2^32)
* - a zero reference count
* - a dead sn_obj
*
* Both of these conditions must be true in order to re-use the stable
......@@ -378,7 +366,7 @@ gcStablePtrTable( void )
if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) {
// StableNames only:
if (p->weight == 0) {
if (p->ref == 0) {
if (p->sn_obj == NULL) {
// StableName object is dead
freeStableName(p);
......@@ -388,7 +376,7 @@ gcStablePtrTable( void )
} else {
(StgClosure *)p->addr = isAlive((StgClosure *)p->addr);
IF_DEBUG(stable, fprintf(stderr,"Stable name %d still alive at %p, weight %d\n", p - stable_ptr_table, p->addr, p->weight));
IF_DEBUG(stable, fprintf(stderr,"Stable name %d still alive at %p, ref %d\n", p - stable_ptr_table, p->addr, p->ref));
}
}
}
......
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