X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FStable.c;h=7082cb3380ca0278b63b23b9fd9f565d2e8eab36;hb=92b67d724a648d1a2ddb371c8ecd3333b0a2ba18;hp=56b029b4ca67479e1b9e3cdd33a65684b6358bd8;hpb=a7eae667e4d5bbcf7415a78c71e07b3b1d65ae7b;p=ghc-hetmet.git diff --git a/ghc/rts/Stable.c b/ghc/rts/Stable.c index 56b029b..7082cb3 100644 --- a/ghc/rts/Stable.c +++ b/ghc/rts/Stable.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Stable.c,v 1.12 2000/09/04 15:08:42 simonmar Exp $ + * $Id: Stable.c,v 1.16 2001/08/08 16:03:47 simonmar Exp $ * * (c) The GHC Team, 1998-1999 * @@ -10,7 +10,6 @@ #include "Rts.h" #include "Hash.h" #include "StablePriv.h" -#include "GC.h" #include "RtsUtils.h" #include "Storage.h" #include "RtsAPI.h" @@ -66,7 +65,6 @@ deRefStablePtr# :: StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #) \end{verbatim} - There is also a C procedure @FreeStablePtr@ which frees a stable pointer. There may be additional functions on the C side to allow evaluation, application, etc of a stable pointer. @@ -107,7 +105,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 @@ -134,6 +132,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->sn_obj = NULL; free = p; @@ -183,8 +182,7 @@ lookupStableName(StgPtr p) } /* removing indirections increases the likelihood - * of finding a match in the stable name - * hash table. + * of finding a match in the stable name hash table. */ p = (StgPtr)removeIndirections((StgClosure*)p); @@ -225,7 +223,7 @@ 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); @@ -238,11 +236,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 -= 1 << (weight_2 - 1); - return (StgStablePtr)(sn + (weight_2 << STABLEPTR_WEIGHT_SHIFT)); + stable_ptr_table[sn].weight -= 1 << n; + return (StgStablePtr)(sn + ((n+1) << STABLEPTR_WEIGHT_SHIFT)); } } @@ -252,7 +250,7 @@ enlargeStablePtrTable(void) nat old_SPT_size = SPT_size; if (SPT_size == 0) { - /* 1st time */ + // 1st time SPT_size = INIT_SPT_SIZE; stable_ptr_table = stgMallocWords(SPT_size * sizeof(snEntry), "initStablePtrTable"); @@ -265,7 +263,7 @@ enlargeStablePtrTable(void) addrToStableHash = allocHashTable(); } else { - /* 2nd and subsequent times */ + // 2nd and subsequent times SPT_size *= 2; stable_ptr_table = stgReallocWords(stable_ptr_table, SPT_size * sizeof(snEntry), @@ -283,49 +281,63 @@ enlargeStablePtrTable(void) * -------------------------------------------------------------------------- */ void -markStablePtrTable(rtsBool full) +markStablePtrTable(evac_fn evac) { - snEntry *p, *end_stable_ptr_table; - StgPtr q; - StgClosure *new; - - if (SPT_size == 0) - return; + snEntry *p, *end_stable_ptr_table; + StgPtr q; + + end_stable_ptr_table = &stable_ptr_table[SPT_size]; + + // Mark all the stable *pointers* (not stable names). + // _starting_ at index 1; index 0 is unused. + for (p = stable_ptr_table+1; p < end_stable_ptr_table; p++) { + q = p->addr; + + // Internal pointers are free slots. If q == NULL, it's a + // stable name where the object has been GC'd, but the + // StableName object (sn_obj) is still alive. + if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) { + + // save the current addr away: we need to be able to tell + // whether the objects moved in order to be able to update + // the hash table later. + p->old = p->addr; + + // if the weight is non-zero, treat addr as a root + if (p->weight != 0) { + evac((StgClosure **)&p->addr); + } + } + } +} - if (full) { - freeHashTable(addrToStableHash,NULL); - addrToStableHash = allocHashTable(); - } +/* ----------------------------------------------------------------------------- + * Thread the stable pointer table for compacting GC. + * + * Here we must call the supplied evac function for each pointer into + * the heap from the stable pointer table, because the compacting + * collector may move the object it points to. + * -------------------------------------------------------------------------- */ - end_stable_ptr_table = &stable_ptr_table[SPT_size]; +void +threadStablePtrTable( evac_fn evac ) +{ + snEntry *p, *end_stable_ptr_table; + StgPtr q; + + end_stable_ptr_table = &stable_ptr_table[SPT_size]; + + for (p = stable_ptr_table+1; p < end_stable_ptr_table; p++) { + + if (p->sn_obj != NULL) { + evac((StgClosure **)&p->sn_obj); + } - /* Mark all the stable *pointers* (not stable names). - * _starting_ at index 1; index 0 is unused. - */ - for (p = stable_ptr_table+1; p < end_stable_ptr_table; p++) { - q = p->addr; - /* 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)); - (StgClosure *)p->addr = new; - } else if ((P_)new != q) { - removeHashTable(addrToStableHash, (W_)q, NULL); - if (!lookupHashTable(addrToStableHash, (W_)new)) { - insertHashTable(addrToStableHash, (W_)new, - (void *)(p - stable_ptr_table)); - } - (StgClosure *)p->addr = new; + q = p->addr; + if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) { + evac((StgClosure **)&p->addr); } - IF_DEBUG(stable, fprintf(stderr,"Stable ptr %d still alive at %p, weight %d\n", p - stable_ptr_table, new, p->weight)); - } } - } } /* ----------------------------------------------------------------------------- @@ -340,6 +352,50 @@ markStablePtrTable(rtsBool full) * 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. + * -------------------------------------------------------------------------- */ + +void +gcStablePtrTable( void ) +{ + snEntry *p, *end_stable_ptr_table; + StgPtr q; + + end_stable_ptr_table = &stable_ptr_table[SPT_size]; + + // 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) { + p->sn_obj = isAlive(p->sn_obj); + } + + // Internal pointers are free slots. If q == NULL, it's a + // stable name where the object has been GC'd, but the + // StableName object (sn_obj) is still alive. + q = p->addr; + if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) { + + // StableNames only: + if (p->weight == 0) { + 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)); + continue; + + } 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)); + } + } + } + } +} + +/* ----------------------------------------------------------------------------- + * Update the StablePtr/StableName hash table * * The boolean argument 'full' indicates that a major collection is * being done, so we might as well throw away the hash table and build @@ -348,65 +404,39 @@ markStablePtrTable(rtsBool full) * -------------------------------------------------------------------------- */ void -gcStablePtrTable(rtsBool full) +updateStablePtrTable(rtsBool full) { - snEntry *p, *end_stable_ptr_table; - StgPtr q, new; - - if (SPT_size == 0) { - return; - } - - end_stable_ptr_table = &stable_ptr_table[SPT_size]; - - /* 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) { - p->sn_obj = isAlive(p->sn_obj); + snEntry *p, *end_stable_ptr_table; + + if (full && addrToStableHash != NULL) { + freeHashTable(addrToStableHash,NULL); + addrToStableHash = allocHashTable(); } - - q = p->addr; - if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) { - - /* We're only interested in Stable Names here. The weight != 0 - * case is handled in markStablePtrTable above. - */ - if (p->weight == 0) { + + end_stable_ptr_table = &stable_ptr_table[SPT_size]; + + // NOTE: _starting_ at index 1; index 0 is unused. + for (p = stable_ptr_table + 1; p < end_stable_ptr_table; p++) { - 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)); - - if (new == NULL) { - /* The target has been garbage collected. Remove its - * entry from the hash table. - */ - removeHashTable(addrToStableHash, (W_)q, NULL); - - } else { - /* Target still alive, Re-hash this stable name - */ + if (p->addr == NULL) { + if (p->old != NULL) { + // The target has been garbage collected. Remove its + // entry from the hash table. + removeHashTable(addrToStableHash, (W_)p->old, NULL); + p->old = NULL; + } + } + else if (p->addr < (P_)stable_ptr_table + || p->addr >= (P_)end_stable_ptr_table) { + // Target still alive, 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)); + insertHashTable(addrToStableHash, (W_)p->addr, + (void *)(p - stable_ptr_table)); + } else if (p->addr != p->old) { + removeHashTable(addrToStableHash, (W_)p->old, NULL); + insertHashTable(addrToStableHash, (W_)p->addr, + (void *)(p - stable_ptr_table)); } - } - - /* finally update the address of the target to point to its - * new location. - */ - p->addr = new; } - } } - } }