/* -----------------------------------------------------------------------------
- * $Id: MBlock.h,v 1.18 2003/08/29 16:00:29 simonmar Exp $
*
- * (c) The GHC Team, 1998-1999
+ * (c) The GHC Team, 1998-2005
*
* MegaBlock Allocator interface.
*
* ---------------------------------------------------------------------------*/
-#ifndef __MBLOCK_H__
-#define __MBLOCK_H__
-extern lnat mblocks_allocated;
+#ifndef MBLOCK_H
+#define MBLOCK_H
+
+extern lnat RTS_VAR(mblocks_allocated);
extern void * getMBlock(void);
extern void * getMBlocks(nat n);
+extern void freeAllMBlocks(void);
-#if osf3_TARGET_OS
+#if osf3_HOST_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
will be quickly cached (indeed, performance measurements showed no
measurable difference between doing the table lookup and using a
constant comparison).
+
+ On 64-bit machines, we cache one 12-bit block map that describes
+ 4096 megablocks or 4GB of memory. If HEAP_ALLOCED is called for
+ an address that is not in the cache, it calls slowIsHeapAlloced
+ (see MBlock.c) which will find the block map for the 4GB block in
+ question.
-------------------------------------------------------------------------- */
+#if SIZEOF_VOID_P == 4
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 defined(x86_64_TARGET_ARCH)
-/* 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. */
+#elif SIZEOF_VOID_P == 8
+
# 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)
+typedef struct {
+ StgWord32 addrHigh32;
+ StgWord8 mblocks[MBLOCK_MAP_SIZE];
+} MBlockMap;
+
+extern MBlockMap *mblock_cache;
+
+StgBool slowIsHeapAlloced(void *p);
+
+# define HEAP_ALLOCED(p) \
+ ( ((((StgWord)(p)) >> 32) == mblock_cache->addrHigh32) \
+ ? mblock_cache->mblocks[MBLOCK_MAP_ENTRY(p)] \
+ : slowIsHeapAlloced(p) )
#else
# error HEAP_ALLOCED not defined
#endif
-#endif // __MBLOCK_H__
+#endif /* MBLOCK_H */