merge upstream HEAD
[ghc-hetmet.git] / rts / Stable.c
index 813c6c8..c46f8b2 100644 (file)
@@ -6,19 +6,14 @@
  *
  * ---------------------------------------------------------------------------*/
 
-// Make static versions of inline functions in Stable.h:
-#define RTS_STABLE_C
-
 #include "PosixSource.h"
 #include "Rts.h"
+#include "RtsAPI.h"
+
 #include "Hash.h"
 #include "RtsUtils.h"
-#include "OSThreads.h"
-#include "Storage.h"
-#include "RtsAPI.h"
-#include "RtsFlags.h"
-#include "OSThreads.h"
 #include "Trace.h"
+#include "Stable.h"
 
 /* Comment from ADR's implementation in old RTS:
 
@@ -85,6 +80,8 @@ static unsigned int SPT_size = 0;
 static Mutex stable_mutex;
 #endif
 
+static void enlargeStablePtrTable(void);
+
 /* This hash table maps Haskell objects to stable names, so that every
  * call to lookupStableName on a given object will return the same
  * stable name.
@@ -176,6 +173,9 @@ exitStablePtrTable(void)
 
 /*
  * get at the real stuff...remove indirections.
+ * It untags pointers before dereferencing and
+ * retags the real stuff with its tag (if there
+ * is any) when returning.
  *
  * ToDo: move to a better home.
  */
@@ -183,16 +183,18 @@ static
 StgClosure*
 removeIndirections(StgClosure* p)
 {
-  StgClosure* q = p;
+  StgWord tag = GET_CLOSURE_TAG(p);
+  StgClosure* q = UNTAG_CLOSURE(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 ) {
+         get_itbl(q)->type == IND_PERM) {
       q = ((StgInd *)q)->indirectee;
+      tag = GET_CLOSURE_TAG(q);
+      q = UNTAG_CLOSURE(q);
   }
-  return q;
+
+  return TAG_CLOSURE(tag,q);
 }
 
 static StgWord
@@ -210,6 +212,9 @@ lookupStableName_(StgPtr p)
    */
   p = (StgPtr)removeIndirections((StgClosure*)p);
 
+  // register the untagged pointer.  This just makes things simpler.
+  p = (StgPtr)UNTAG_CLOSURE((StgClosure*)p);
+
   sn_tmp = lookupHashTable(addrToStableHash,(W_)p);
   sn = (StgWord)sn_tmp;
   
@@ -292,7 +297,7 @@ freeStablePtr(StgStablePtr sp)
     RELEASE_LOCK(&stable_mutex);
 }
 
-void
+static void
 enlargeStablePtrTable(void)
 {
   nat old_SPT_size = SPT_size;
@@ -308,6 +313,23 @@ enlargeStablePtrTable(void)
 }
 
 /* -----------------------------------------------------------------------------
+ * We must lock the StablePtr table during GC, to prevent simultaneous
+ * calls to freeStablePtr().
+ * -------------------------------------------------------------------------- */
+
+void
+stablePtrPreGC(void)
+{
+    ACQUIRE_LOCK(&stable_mutex);
+}
+
+void
+stablePtrPostGC(void)
+{
+    RELEASE_LOCK(&stable_mutex);
+}
+
+/* -----------------------------------------------------------------------------
  * Treat stable pointers as roots for the garbage collector.
  *
  * A stable pointer is any stable name entry with a ref > 0.  We'll
@@ -315,7 +337,7 @@ enlargeStablePtrTable(void)
  * -------------------------------------------------------------------------- */
 
 void
-markStablePtrTable(evac_fn evac)
+markStablePtrTable(evac_fn evac, void *user)
 {
     snEntry *p, *end_stable_ptr_table;
     StgPtr q;
@@ -339,7 +361,7 @@ markStablePtrTable(evac_fn evac)
 
            // if the ref is non-zero, treat addr as a root
            if (p->ref != 0) {
-               evac((StgClosure **)&p->addr);
+               evac(user, (StgClosure **)&p->addr);
            }
        }
     }
@@ -354,7 +376,7 @@ markStablePtrTable(evac_fn evac)
  * -------------------------------------------------------------------------- */
 
 void
-threadStablePtrTable( evac_fn evac )
+threadStablePtrTable( evac_fn evac, void *user )
 {
     snEntry *p, *end_stable_ptr_table;
     StgPtr q;
@@ -364,12 +386,12 @@ threadStablePtrTable( evac_fn evac )
     for (p = stable_ptr_table+1; p < end_stable_ptr_table; p++) {
        
        if (p->sn_obj != NULL) {
-           evac((StgClosure **)&p->sn_obj);
+           evac(user, (StgClosure **)&p->sn_obj);
        }
 
        q = p->addr;
        if (q && (q < (P_)stable_ptr_table || q >= (P_)end_stable_ptr_table)) {
-           evac((StgClosure **)&p->addr);
+           evac(user, (StgClosure **)&p->addr);
        }
     }
 }