Commit a59148d1 authored by simonm's avatar simonm

[project @ 1999-02-26 12:46:45 by simonm]

Fix stable pointer bug:

   - the 'keep' flag is now a pointer to the stable name object.

   - makeStableName always returns an existing stable name object
     if one exists.

   - re-use stable name table entries iff the stable name object
     becomes unreachable (takes into account generational GC now),
     and the reference count is 0.
parent 284ed5fb
/* -----------------------------------------------------------------------------
* $Id: Stable.h,v 1.2 1999/02/05 16:02:28 simonm Exp $
* $Id: Stable.h,v 1.3 1999/02/26 12:46:45 simonm Exp $
*
* (c) The GHC Team, 1998-1999
*
......@@ -22,9 +22,9 @@ extern StgStablePtr splitStablePtr(StgStablePtr sp);
extern StgStablePtr getStablePtr(StgPtr p);
typedef struct {
StgPtr addr; /* either Haskell object or free list */
StgPtr addr; /* Haskell object, free list, or NULL */
StgWord weight; /* used for reference counting */
unsigned int keep; /* set by the garbage collector */
StgClosure *sn_obj; /* the StableName object (or NULL) */
} snEntry;
extern snEntry *stable_ptr_table;
......
/* -----------------------------------------------------------------------------
* $Id: GC.c,v 1.42 1999/02/25 17:52:33 simonm Exp $
* $Id: GC.c,v 1.43 1999/02/26 12:46:46 simonm Exp $
*
* (c) The GHC Team 1998-1999
*
......@@ -1099,10 +1099,6 @@ loop:
recordMutable((StgMutClosure *)to);
return to;
case STABLE_NAME:
stable_ptr_table[((StgStableName *)q)->sn].keep = rtsTrue;
return copy(q,sizeofW(StgStableName),step);
case FUN_1_0:
case FUN_0_1:
case CONSTR_1_0:
......@@ -1140,6 +1136,7 @@ loop:
case CAF_ENTERED:
case WEAK:
case FOREIGN:
case STABLE_NAME:
return copy(q,sizeW_fromITBL(info),step);
case CAF_BLACKHOLE:
......
/* -----------------------------------------------------------------------------
* $Id: PrimOps.hc,v 1.16 1999/02/17 15:57:39 simonm Exp $
* $Id: PrimOps.hc,v 1.17 1999/02/26 12:46:48 simonm Exp $
*
* (c) The GHC Team, 1998-1999
*
......@@ -880,9 +880,15 @@ FN_(makeStableNamezh_fast)
index = RET_STGCALL1(StgWord,lookupStableName,R1.p);
sn_obj = (StgStableName *) (Hp - sizeofW(StgStableName) + 1);
sn_obj->header.info = &STABLE_NAME_info;
sn_obj->sn = index;
/* Is there already a StableName for this heap object? */
if (stable_ptr_table[index].sn_obj == NULL) {
sn_obj = (StgStableName *) (Hp - sizeofW(StgStableName) + 1);
sn_obj->header.info = &STABLE_NAME_info;
sn_obj->sn = index;
stable_ptr_table[index].sn_obj = (StgClosure *)sn_obj;
} else {
(StgClosure *)sn_obj = stable_ptr_table[index].sn_obj;
}
TICK_RET_UNBOXED_TUP(1);
RET_P(sn_obj);
......
/* -----------------------------------------------------------------------------
* $Id: Stable.c,v 1.2 1999/02/05 16:02:55 simonm Exp $
* $Id: Stable.c,v 1.3 1999/02/26 12:46:48 simonm Exp $
*
* (c) The GHC Team, 1998-1999
*
......@@ -170,6 +170,7 @@ lookupStableName(StgPtr p)
(P_)stable_ptr_free = stable_ptr_free->addr;
stable_ptr_table[sn].weight = 0;
stable_ptr_table[sn].addr = p;
stable_ptr_table[sn].sn_obj = NULL;
/* IF_DEBUG(stable,fprintf(stderr,"new stable name %d at
%p\n",sn,p)); */
......@@ -183,6 +184,7 @@ lookupStableName(StgPtr p)
static inline void
freeStableName(snEntry *sn)
{
ASSERT(sn->sn_obj == NULL);
sn->addr = (P_)stable_ptr_free;
stable_ptr_free = sn;
}
......@@ -266,26 +268,23 @@ markStablePtrTable(rtsBool full)
*/
for (p = stable_ptr_table; p < end_stable_ptr_table; p++) {
q = p->addr;
/* internal pointers or NULL are free slots */
/* internal pointers or NULL are free slots
*/
if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) {
if (p->weight != 0) {
new = MarkRoot((StgClosure *)q);
/* Update the hash table */
if (full) {
insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
insertHashTable(addrToStableHash, (W_)new,
(void *)(p - stable_ptr_table));
(StgClosure *)p->addr = new;
} else if ((P_)new != q) {
removeHashTable(addrToStableHash, (W_)q, NULL);
insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
insertHashTable(addrToStableHash, (W_)new,
(void *)(p - stable_ptr_table));
(StgClosure *)p->addr = new;
}
/* IF_DEBUG(stable, fprintf(stderr,"Stable ptr %d still alive
at %p, weight %d\n", p - stable_ptr_table, new,
p->weight)); */
}
else {
/* reset the keep flag */
p->keep = rtsFalse;
IF_DEBUG(stable, fprintf(stderr,"Stable ptr %d still alive at %p, weight %d\n", p - stable_ptr_table, new, p->weight));
}
}
}
......@@ -297,10 +296,12 @@ markStablePtrTable(rtsBool full)
* A dead entry has:
*
* - a weight of zero (i.e. 2^32)
* - a false keep flag
* - a dead sn_obj
*
* The keep flag is set by the garbage collector whenever it
* encounters a StableName object on the heap.
* Both of these conditions must be true in order to re-use the stable
* name table entry. We can re-use stable name table entries for live
* heap objects, as long as the program has no StableName objects that
* refer to the entry.
*
* The boolean argument 'full' indicates that a major collection is
* being done, so we might as well throw away the hash table and build
......@@ -321,36 +322,40 @@ gcStablePtrTable(rtsBool full)
end_stable_ptr_table = &stable_ptr_table[SPT_size];
for (p = stable_ptr_table; p < end_stable_ptr_table; p++) {
q = p->addr;
/* Update the pointer to the StableName object, if there is one */
if (p->sn_obj != NULL) {
p->sn_obj = isAlive(p->sn_obj);
}
q = p->addr;
if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) {
/* We're only interested in Stable Names here. */
/* We're only interested in Stable Names here. The weight != 0
* case is handled in markStablePtrTable above.
*/
if (p->weight == 0) {
if (((StgClosure *)new = isAlive((StgClosure *)q))) {
if (p->sn_obj == NULL) {
/* StableName object is dead */
freeStableName(p);
IF_DEBUG(stable, fprintf(stderr,"GC'd Stable name %d\n", p - stable_ptr_table));
}
else {
(StgClosure *)new = isAlive((StgClosure *)q);
IF_DEBUG(stable, fprintf(stderr,"Stable name %d still alive at %p, weight %d\n", p - stable_ptr_table, new, p->weight));
p->addr = new;
/* Re-hash this stable name */
if (full) {
insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
} else if (new != q) {
removeHashTable(addrToStableHash, (W_)q, NULL);
insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
if (new != NULL) {
/* Re-hash this stable name */
if (full) {
insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
} else if (new != q) {
removeHashTable(addrToStableHash, (W_)q, NULL);
insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
}
}
}
else {
/* If there are still StableName objects in the heap
* pointing to this entry (p->keep == rtsTrue), then
* don't free the entry just yet.
*/
if (p->keep)
p->addr = NULL;
else
freeStableName(p);
}
}
}
}
......
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