[project @ 2004-08-13 13:04:50 by simonmar]
[ghc-hetmet.git] / ghc / rts / MBlock.h
index 40461a0..64fd459 100644 (file)
@@ -1,54 +1,21 @@
 /* -----------------------------------------------------------------------------
- * $Id: MBlock.h,v 1.14 2002/05/14 08:15:49 matthewc Exp $
+ * $Id: MBlock.h,v 1.20 2004/08/13 13:10:10 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
  * MegaBlock Allocator interface.
  *
  * ---------------------------------------------------------------------------*/
+
 #ifndef __MBLOCK_H__
 #define __MBLOCK_H__
-extern lnat mblocks_allocated;
 
-#if defined(mingw32_TARGET_OS)
-extern int is_heap_alloced(const void* p);
-#endif
+extern lnat RTS_VAR(mblocks_allocated);
 
 extern void * getMBlock(void);
 extern void * getMBlocks(nat n);
 
-#if freebsd2_TARGET_OS || freebsd_TARGET_OS
-/* Executable is loaded from      0x0
- * Shared libraries are loaded at 0x2000000
- * Stack is at the top of the address space.  The kernel probably owns
- * 0x8000000 onwards, so we'll pick 0x5000000.
- */
-#define HEAP_BASE 0x50000000
-
-#elif netbsd_TARGET_OS
-/* NetBSD i386 shared libs are at 0x40000000
- */
-#define HEAP_BASE 0x50000000
-#elif openbsd_TARGET_OS
-#define HEAP_BASE 0x50000000
-
-#elif linux_TARGET_OS
-#if ia64_TARGET_ARCH
-/* Shared libraries are in region 1, text in region 2, data in region 3.
- * Stack is at the top of region 4.  We use the bottom.
- */
-#define HEAP_BASE (4L<<61)
-#else
-/* Any ideas?
- */
-#define HEAP_BASE 0x50000000
-#endif
-
-#elif solaris2_TARGET_OS
-/* guess */
-#define HEAP_BASE 0x50000000
-
-#elif osf3_TARGET_OS
+#if osf3_TARGET_OS
 /* ToDo: Perhaps by adjusting this value we can make linking without
  * -static work (i.e., not generate a core-dumping executable)? */
 #if SIZEOF_VOID_P == 8
@@ -57,20 +24,66 @@ extern void * getMBlocks(nat n);
 #error I have no idea where to begin the heap on a non-64-bit osf3 machine.
 #endif
 
-#elif hpux_TARGET_OS
-/* guess */
-#define HEAP_BASE 0x50000000
+#else
 
-#elif darwin_TARGET_OS
-/* guess */
-#define HEAP_BASE 0x50000000
+// we're using the generic method
+#define HEAP_BASE 0
+
+#endif
+
+/* -----------------------------------------------------------------------------
+   The HEAP_ALLOCED() test.
+
+   HEAP_ALLOCED is called FOR EVERY SINGLE CLOSURE during GC.
+   It needs to be FAST.
+
+   Implementation of HEAP_ALLOCED
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+   Since heap is allocated in chunks of megablocks (MBLOCK_SIZE), we
+   can just use a table to record which megablocks in the address
+   space belong to the heap.  On a 32-bit machine, with 1Mb
+   megablocks, using 8 bits for each entry in the table, the table
+   requires 4k.  Lookups during GC will be fast, because the table
+   will be quickly cached (indeed, performance measurements showed no
+   measurable difference between doing the table lookup and using a
+   constant comparison).
+   -------------------------------------------------------------------------- */
+
+extern StgWord8 mblock_map[];
+
+#if SIZEOF_VOID_P == 4
+/* On a 32-bit machine a 4KB table is always sufficient */
+# define MBLOCK_MAP_SIZE       4096
+# define MBLOCK_MAP_ENTRY(p)   ((StgWord)(p) >> MBLOCK_SHIFT)
+# define HEAP_ALLOCED(p)       mblock_map[MBLOCK_MAP_ENTRY(p)]
+# define MARK_HEAP_ALLOCED(p)  (mblock_map[MBLOCK_MAP_ENTRY(p)] = 1)
+
+#elif defined(ia64_TARGET_ARCH)
+/* Instead of trying to cover the whole 64-bit address space (which would
+ * require a better data structure), we assume that mmap allocates mappings
+ * from the bottom of region 1, and track some portion of address space from
+ * there upwards (currently 4GB). */
+# define MBLOCK_MAP_SIZE       4096
+# define MBLOCK_MAP_ENTRY(p)   (((StgWord)(p) - (1UL << 61)) >> MBLOCK_SHIFT)
+# define HEAP_ALLOCED(p)       ((MBLOCK_MAP_ENTRY(p) < MBLOCK_MAP_SIZE) \
+                                       && mblock_map[MBLOCK_MAP_ENTRY(p)])
+# define MARK_HEAP_ALLOCED(p)  ((MBLOCK_MAP_ENTRY(p) < MBLOCK_MAP_SIZE) \
+                                       && (mblock_map[MBLOCK_MAP_ENTRY(p)] = 1))
+
+#elif SIZEOF_VOID_P == 8
+/* XXX: This is a HACK, and will not work in general!  We just use the
+ * lower 32 bits of the address, and do the same as for the 32-bit
+ * version.  As long as the OS gives us memory in a roughly linear
+ * fashion, it won't go wrong until we've allocated 4G.  */
+# define MBLOCK_MAP_SIZE       4096
+# define MBLOCK_MAP_ENTRY(p)   (((StgWord)(p) & 0xffffffff) >> MBLOCK_SHIFT)
+# define HEAP_ALLOCED(p)       (mblock_map[MBLOCK_MAP_ENTRY(p)])
+# define MARK_HEAP_ALLOCED(p)  (mblock_map[MBLOCK_MAP_ENTRY(p)] = 1)
 
-#elif defined(mingw32_TARGET_OS) || defined(cygwin32_TARGET_OS)
-/* doesn't matter, we use a reserve/commit algorithm */
 
 #else
-#error Dont know where to get memory from on this architecture
-/* ToDo: memory locations on other architectures */
+# error HEAP_ALLOCED not defined
 #endif
 
-#endif
+#endif // __MBLOCK_H__