[project @ 1999-10-01 08:41:06 by sof]
[ghc-hetmet.git] / ghc / rts / Stable.c
index 206772f..01982b3 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Stable.c,v 1.3 1999/02/26 12:46:48 simonm Exp $
+ * $Id: Stable.c,v 1.8 1999/09/15 13:50:14 sof Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -133,7 +133,9 @@ initFreeList(snEntry *table, nat n, snEntry *free)
   snEntry *p;
 
   for (p = table + n - 1; p >= table; p--) {
-    p->addr = (P_)free;
+    p->addr   = (P_)free;
+    p->weight = 0;
+    p->sn_obj = NULL;
     free = p;
   }
   stable_ptr_free = table;
@@ -185,6 +187,9 @@ static inline void
 freeStableName(snEntry *sn)
 {
   ASSERT(sn->sn_obj == NULL);
+  if (sn->addr != NULL) {
+    removeHashTable(addrToStableHash, (W_)sn->addr, NULL);
+  }
   sn->addr = (P_)stable_ptr_free;
   stable_ptr_free = sn;
 }
@@ -197,7 +202,7 @@ getStablePtr(StgPtr p)
 
   weight = stable_ptr_table[sn].weight;
   if (weight == 0) {
-    weight = 1 << (BITS_IN(StgWord)-1);
+    weight = (StgWord)1 << (BITS_IN(StgWord)-1);
     stable_ptr_table[sn].weight = weight;
     return (StgStablePtr)(sn + ((BITS_IN(StgWord)-1) << STABLEPTR_WEIGHT_SHIFT));
   } 
@@ -226,6 +231,10 @@ enlargeStablePtrTable(void)
     stable_ptr_table = stgMallocWords(SPT_size * sizeof(snEntry), 
                                      "initStablePtrTable");
     
+    /* 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();
   }
@@ -264,9 +273,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 
      */
@@ -321,7 +331,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) {
@@ -345,9 +356,15 @@ gcStablePtrTable(rtsBool full)
          (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;
-         if (new != NULL) {
-           /* Re-hash this stable name */
+         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 (full) {
              insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
            } else if (new != q) {
@@ -355,6 +372,11 @@ gcStablePtrTable(rtsBool full)
              insertHashTable(addrToStableHash, (W_)new, (void *)(p - stable_ptr_table));
            }
          }
+
+         /* finally update the address of the target to point to its
+          * new location.
+          */
+         p->addr = new;
        }
       }
     }