X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FStable.c;h=5b2635b4ab8053057b5da3e04e0cd8c08177de73;hb=f9232b8d6071f163796663ca04d65ec168f739dc;hp=a429920f2c02085dbafa84367ec52a907448dfdd;hpb=b2eced5b4910ded034935d4e60083c15c2f367ed;p=ghc-hetmet.git diff --git a/ghc/rts/Stable.c b/ghc/rts/Stable.c index a429920..5b2635b 100644 --- a/ghc/rts/Stable.c +++ b/ghc/rts/Stable.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Stable.c,v 1.6 1999/08/04 10:04:31 simonmar Exp $ + * $Id: Stable.c,v 1.13 2000/09/04 15:17:03 simonmar Exp $ * * (c) The GHC Team, 1998-1999 * @@ -107,7 +107,7 @@ unsigned int SPT_size; * * A stable pointer has a weighted reference count N attached to it * (actually in its upper 5 bits), which represents the weight - * 2^N. The stable name entry keeps a 32-bit reference count, which + * 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 @@ -152,6 +152,27 @@ initStablePtrTable(void) SPT_size = 0; } +/* + * get at the real stuff...remove indirections. + * + * ToDo: move to a better home. + */ +static +StgClosure* +removeIndirections(StgClosure* p) +{ + StgClosure* q = p; + + while (get_itbl(q)->type == IND || + get_itbl(q)->type == IND_STATIC || + get_itbl(q)->type == IND_OLDGEN || + get_itbl(q)->type == IND_PERM || + get_itbl(q)->type == IND_OLDGEN_PERM ) { + q = ((StgInd *)q)->indirectee; + } + return q; +} + StgWord lookupStableName(StgPtr p) { @@ -160,7 +181,13 @@ lookupStableName(StgPtr p) if (stable_ptr_free == NULL) { enlargeStablePtrTable(); } - + + /* removing indirections increases the likelihood + * of finding a match in the stable name + * hash table. + */ + p = (StgPtr)removeIndirections((StgClosure*)p); + (void *)sn = lookupHashTable(addrToStableHash,(W_)p); if (sn != 0) { @@ -198,13 +225,12 @@ StgStablePtr getStablePtr(StgPtr p) { StgWord sn = lookupStableName(p); - StgWord weight, weight_2; - + 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)-1) << STABLEPTR_WEIGHT_SHIFT)); + return (StgStablePtr)(sn + (BITS_IN(StgWord) << STABLEPTR_WEIGHT_SHIFT)); } else if (weight == 1) { barf("getStablePtr: too light"); @@ -212,11 +238,11 @@ getStablePtr(StgPtr p) else { weight /= 2; /* find log2(weight) */ - for (weight_2 = 1; weight != 1; weight_2++) { + for (n = 0; weight != 1; n++) { weight >>= 1; } - stable_ptr_table[sn].weight -= 2^weight_2; - return (StgStablePtr)(sn + (weight_2 << STABLEPTR_WEIGHT_SHIFT)); + stable_ptr_table[sn].weight -= 1 << n; + return (StgStablePtr)(sn + ((n+1) << STABLEPTR_WEIGHT_SHIFT)); } } @@ -231,7 +257,11 @@ enlargeStablePtrTable(void) stable_ptr_table = stgMallocWords(SPT_size * sizeof(snEntry), "initStablePtrTable"); - initFreeList(stable_ptr_table,INIT_SPT_SIZE,NULL); + /* we don't use index 0 in the stable name table, because that + * would conflict with the hash table lookup operations which + * return NULL if an entry isn't found in the hash table. + */ + initFreeList(stable_ptr_table+1,INIT_SPT_SIZE-1,NULL); addrToStableHash = allocHashTable(); } else { @@ -269,9 +299,10 @@ markStablePtrTable(rtsBool full) end_stable_ptr_table = &stable_ptr_table[SPT_size]; - /* Mark all the stable *pointers* (not stable names) + /* Mark all the stable *pointers* (not stable names). + * _starting_ at index 1; index 0 is unused. */ - for (p = stable_ptr_table; p < end_stable_ptr_table; p++) { + for (p = stable_ptr_table+1; p < end_stable_ptr_table; p++) { q = p->addr; /* internal pointers or NULL are free slots */ @@ -285,11 +316,13 @@ markStablePtrTable(rtsBool full) (StgClosure *)p->addr = new; } else if ((P_)new != q) { removeHashTable(addrToStableHash, (W_)q, NULL); - insertHashTable(addrToStableHash, (W_)new, - (void *)(p - stable_ptr_table)); + if (!lookupHashTable(addrToStableHash, (W_)new)) { + 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)); + IF_DEBUG(stable, fprintf(stderr,"Stable ptr %d still alive at %p, weight %u\n", p - stable_ptr_table, new, p->weight)); } } } @@ -326,7 +359,8 @@ gcStablePtrTable(rtsBool full) end_stable_ptr_table = &stable_ptr_table[SPT_size]; - for (p = stable_ptr_table; p < end_stable_ptr_table; p++) { + /* NOTE: _starting_ at index 1; index 0 is unused. */ + for (p = stable_ptr_table + 1; p < end_stable_ptr_table; p++) { /* Update the pointer to the StableName object, if there is one */ if (p->sn_obj != NULL) {