diff --git a/ghc/includes/Stable.h b/ghc/includes/Stable.h index 4552439e8779fe7dfa0d6f5bb8fc420450ff9ed0..70c467429046b45e306eb2bc870d65f2d2a49cce 100644 --- a/ghc/includes/Stable.h +++ b/ghc/includes/Stable.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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; diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index fad50be014f10ccfd16852ed62c63b3bfeb5b021..d823c44d1eaeb1e416fda4869981a53ef46e4535 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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: diff --git a/ghc/rts/PrimOps.hc b/ghc/rts/PrimOps.hc index f711d9bb74682291fb9076c99c69b5f5b7ef5b05..33e2d2332d750d2a8585669790f28d27ef216d2c 100644 --- a/ghc/rts/PrimOps.hc +++ b/ghc/rts/PrimOps.hc @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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); diff --git a/ghc/rts/Stable.c b/ghc/rts/Stable.c index 9f1414efd4f4345611ac055b735935459e63a87f..206772f3346b04f97f2f8129fb60fe423cf99193 100644 --- a/ghc/rts/Stable.c +++ b/ghc/rts/Stable.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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); - } } } }