[project @ 2000-05-11 19:37:30 by rrt]
[ghc-hetmet.git] / ghc / rts / Stable.c
index 01982b3..bf5e6aa 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Stable.c,v 1.8 1999/09/15 13:50:14 sof Exp $
+ * $Id: Stable.c,v 1.11 2000/04/24 22:05:08 panne Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -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) {
@@ -199,7 +226,6 @@ getStablePtr(StgPtr p)
 {
   StgWord sn = lookupStableName(p);
   StgWord weight, weight_2;
-
   weight = stable_ptr_table[sn].weight;
   if (weight == 0) {
     weight = (StgWord)1 << (BITS_IN(StgWord)-1);
@@ -290,8 +316,10 @@ 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));