STM invariants
[ghc-hetmet.git] / rts / Linker.c
index 92d0106..b6e8249 100644 (file)
@@ -27,6 +27,7 @@
 #include "Schedule.h"
 #include "Storage.h"
 #include "Sparks.h"
+#include "RtsTypeable.h"
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 /* Hash table mapping symbol names to Symbol */
 static /*Str*/HashTable *symhash;
 
+typedef struct {
+  void *addr;
+} rootEntry;
+
+/* Hash table mapping symbol names to StgStablePtr */
+static /*Str*/HashTable *stablehash;
+rootEntry *root_ptr_table = NULL;
+static rootEntry *root_ptr_free = NULL;
+
+static unsigned int RPT_size = 0;
+
 /* List of currently loaded objects */
 ObjectCode *objects = NULL;    /* initially empty */
 
@@ -322,6 +334,7 @@ typedef struct _RtsSymbolVal {
       Sym(mktime)                               \
       Sym(_imp___timezone)                      \
       Sym(_imp___tzname)                        \
+      Sym(_imp__tzname)                         \
       Sym(_imp___iob)                           \
       Sym(_imp___osver)                         \
       Sym(localtime)                            \
@@ -475,6 +488,7 @@ typedef struct _RtsSymbolVal {
       SymX(catchzh_fast)                       \
       SymX(catchRetryzh_fast)                  \
       SymX(catchSTMzh_fast)                    \
+      SymX(checkzh_fast)                        \
       SymX(closure_flags)                       \
       SymX(cmp_thread)                         \
       SymX(cmpIntegerzh_fast)                  \
@@ -496,6 +510,7 @@ typedef struct _RtsSymbolVal {
       SymX(forkOS_createThread)                        \
       SymX(freeHaskellFunctionPtr)             \
       SymX(freeStablePtr)                      \
+      SymX(getOrSetTypeableStore)              \
       SymX(gcdIntegerzh_fast)                  \
       SymX(gcdIntegerIntzh_fast)               \
       SymX(gcdIntzh_fast)                      \
@@ -526,6 +541,8 @@ typedef struct _RtsSymbolVal {
       SymX(isFloatNegativeZero)                        \
       SymX(killThreadzh_fast)                  \
       SymX(loadObj)                            \
+      SymX(insertStableSymbol)                         \
+      SymX(insertSymbol)                       \
       SymX(lookupSymbol)                       \
       SymX(makeStablePtrzh_fast)               \
       SymX(minusIntegerzh_fast)                        \
@@ -694,7 +711,8 @@ typedef struct _RtsSymbolVal {
       SymX(stg_interp_constr6_entry)            \
       SymX(stg_interp_constr7_entry)            \
       SymX(stg_interp_constr8_entry)            \
-      SymX(stgMallocBytesRWX)                   \
+      SymX(allocateExec)                       \
+      SymX(freeExec)                           \
       SymX(getAllocations)                      \
       SymX(revertCAFs)                          \
       SymX(RtsFlags)                            \
@@ -790,6 +808,95 @@ static RtsSymbolVal rtsSyms[] = {
       { 0, 0 } /* sentinel */
 };
 
+
+/* -----------------------------------------------------------------------------
+ * Utilities for handling root pointers.
+ * -------------------------------------------------------------------------- */
+
+
+#define INIT_RPT_SIZE 64
+
+STATIC_INLINE void
+initFreeList(rootEntry *table, nat n, rootEntry *free)
+{
+  rootEntry *p;
+
+  for (p = table + n - 1; p >= table; p--) {
+    p->addr   = (P_)free;
+    free = p;
+  }
+  root_ptr_free = table;
+}
+
+static void
+initRootPtrTable(void)
+{
+  if (RPT_size > 0)
+    return;
+
+  RPT_size = INIT_RPT_SIZE;
+  root_ptr_table = stgMallocBytes(RPT_size * sizeof(rootEntry),
+                                    "initRootPtrTable");
+
+  initFreeList(root_ptr_table,INIT_RPT_SIZE,NULL);
+}
+
+
+static void
+enlargeRootPtrTable(void)
+{
+  nat old_RPT_size = RPT_size;
+
+  // 2nd and subsequent times
+  RPT_size *= 2;
+  root_ptr_table =
+    stgReallocBytes(root_ptr_table,
+                    RPT_size * sizeof(rootEntry),
+                    "enlargeRootPtrTable");
+
+  initFreeList(root_ptr_table + old_RPT_size, old_RPT_size, NULL);
+}
+
+static void
+addRootObject(void *addr)
+{
+  StgWord rt;
+  initRootPtrTable();
+  if (root_ptr_free == NULL) {
+    enlargeRootPtrTable();
+  }
+
+  rt = root_ptr_free - root_ptr_table;
+  root_ptr_free  = (rootEntry*)(root_ptr_free->addr);
+  root_ptr_table[rt].addr = addr;
+}
+
+/* -----------------------------------------------------------------------------
+ * Treat root pointers as roots for the garbage collector.
+ * -------------------------------------------------------------------------- */
+
+void
+markRootPtrTable(evac_fn evac)
+{
+  rootEntry *p, *end_root_ptr_table;
+  StgPtr q;
+
+  end_root_ptr_table = &root_ptr_table[RPT_size];
+
+  for (p = root_ptr_table; p < end_root_ptr_table; p++) {
+    q = p->addr;
+
+    if (q && (q < (P_)root_ptr_table || q >= (P_)end_root_ptr_table)) {
+        evac((StgClosure **)p->addr);
+    }
+  }
+}
+
+/* -----------------------------------------------------------------------------
+ * End of utilities for handling root pointers.
+ * -------------------------------------------------------------------------- */
+
+
 /* -----------------------------------------------------------------------------
  * Insert symbols into hash tables, checking for duplicates.
  */
@@ -835,11 +942,6 @@ static int linker_init_done = 0 ;
 static void *dl_prog_handle;
 #endif
 
-/* dlopen(NULL,..) doesn't work so we grab libc explicitly */
-#if defined(openbsd_HOST_OS)
-static void *dl_libc_handle;
-#endif
-
 void
 initLinker( void )
 {
@@ -852,6 +954,7 @@ initLinker( void )
       linker_init_done = 1;
     }
 
+    stablehash = allocStrHashTable();
     symhash = allocStrHashTable();
 
     /* populate the symbol table with stuff from the RTS */
@@ -868,9 +971,6 @@ initLinker( void )
     dl_prog_handle = RTLD_DEFAULT;
 #   else
     dl_prog_handle = dlopen(NULL, RTLD_LAZY);
-#   if defined(openbsd_HOST_OS)
-    dl_libc_handle = dlopen("libc.so", RTLD_LAZY);
-#   endif
 #   endif /* RTLD_DEFAULT */
 #   endif
 }
@@ -989,6 +1089,26 @@ addDLL( char *dll_name )
 }
 
 /* -----------------------------------------------------------------------------
+ * insert a stable symbol in the hash table
+ */
+
+void
+insertStableSymbol(char* obj_name, char* key, StgPtr p)
+{
+  ghciInsertStrHashTable(obj_name, stablehash, key, getStablePtr(p));
+}
+
+
+/* -----------------------------------------------------------------------------
+ * insert a symbol in the hash table
+ */
+void
+insertSymbol(char* obj_name, char* key, void* data)
+{
+  ghciInsertStrHashTable(obj_name, symhash, key, data);
+}
+
+/* -----------------------------------------------------------------------------
  * lookup a symbol in the hash table
  */
 void *
@@ -1001,10 +1121,7 @@ lookupSymbol( char *lbl )
 
     if (val == NULL) {
 #       if defined(OBJFORMAT_ELF)
-#      if defined(openbsd_HOST_OS)
-       val = dlsym(dl_prog_handle, lbl);
-       return (val != NULL) ? val : dlsym(dl_libc_handle,lbl);
-#      elif defined(x86_64_HOST_ARCH)
+#      if defined(x86_64_HOST_ARCH)
        val = dlsym(dl_prog_handle, lbl);
        if (val >= (void *)0x80000000) {
            void *new_val;
@@ -1014,7 +1131,7 @@ lookupSymbol( char *lbl )
        } else {
            return val;
        }
-#      else /* not openbsd */
+#      else
        return dlsym(dl_prog_handle, lbl);
 #      endif
 #       elif defined(OBJFORMAT_MACHO)
@@ -2157,6 +2274,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
           && 0 != strcmp(".stabstr", sectab_i->Name)
           /* ignore constructor section for now */
           && 0 != strcmp(".ctors", sectab_i->Name)
+          /* ignore section generated from .ident */
+          && 0!= strcmp("/4", sectab_i->Name)
          ) {
          errorBelch("Unknown PEi386 section name `%s' (while processing: %s)", sectab_i->Name, oc->fileName);
          return 0;
@@ -2374,14 +2493,14 @@ ocResolve_PEi386 ( ObjectCode* oc )
                    + sym->Value);
          } else {
             copyName ( sym->Name, strtab, symbol, 1000-1 );
-            (void*)S = lookupLocalSymbol( oc, symbol );
+            S = (UInt32) lookupLocalSymbol( oc, symbol );
             if ((void*)S != NULL) goto foundit;
-            (void*)S = lookupSymbol( symbol );
+            S = (UInt32) lookupSymbol( symbol );
             if ((void*)S != NULL) goto foundit;
             zapTrailingAtSign ( symbol );
-            (void*)S = lookupLocalSymbol( oc, symbol );
+            S = (UInt32) lookupLocalSymbol( oc, symbol );
             if ((void*)S != NULL) goto foundit;
-            (void*)S = lookupSymbol( symbol );
+            S = (UInt32) lookupSymbol( symbol );
             if ((void*)S != NULL) goto foundit;
            /* Newline first because the interactive linker has printed "linking..." */
             errorBelch("\n%s: unknown symbol `%s'", oc->fileName, symbol);
@@ -2785,6 +2904,9 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    IF_DEBUG(linker,debugBelch( "Architecture is " ));
    switch (ehdr->e_machine) {
       case EM_386:   IF_DEBUG(linker,debugBelch( "x86" )); break;
+#ifdef EM_SPARC32PLUS
+      case EM_SPARC32PLUS:
+#endif
       case EM_SPARC: IF_DEBUG(linker,debugBelch( "sparc" )); break;
 #ifdef EM_IA_64
       case EM_IA_64: IF_DEBUG(linker,debugBelch( "ia64" )); break;
@@ -3134,6 +3256,8 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
       Elf_Addr  S;
       void*     S_tmp;
       Elf_Addr  value;
+      StgStablePtr stablePtr;
+      StgPtr stableVal;
 
       IF_DEBUG(linker,debugBelch( "Rel entry %3d is raw(%6p %6p)",
                              j, (void*)offset, (void*)info ));
@@ -3152,10 +3276,18 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
                        + stab[ELF_R_SYM(info)].st_value);
 
         } else {
-            /* No, so look up the name in our global table. */
             symbol = strtab + sym.st_name;
-            S_tmp = lookupSymbol( symbol );
-            S = (Elf_Addr)S_tmp;
+            stablePtr = (StgStablePtr)lookupHashTable(stablehash, (StgWord)symbol);
+            if (NULL == stablePtr) {
+              /* No, so look up the name in our global table. */
+              S_tmp = lookupSymbol( symbol );
+              S = (Elf_Addr)S_tmp;
+            } else {
+              stableVal = deRefStablePtr( stablePtr );
+              addRootObject((void*)P);
+              S_tmp = stableVal;
+              S = (Elf_Addr)S_tmp;
+            }
         }
          if (!S) {
             errorBelch("%s: unknown symbol `%s'", oc->fileName, symbol);