-/* --------------------------------------------------------------------------
- Macros for distinguishing data pointers from code pointers
- --------------------------------------------------------------------------
-
- Specification
- ~~~~~~~~~~~~~
- The garbage collector needs to make some critical distinctions between pointers.
- In particular we need
-
- LOOKS_LIKE_GHC_INFO(p) p points to an info table
-
- For both of these macros, p is
- *either* a pointer to a closure (static or heap allocated)
- *or* a return address on the (Haskell) stack
-
- (Return addresses are in fact info-pointers, so that the Haskell stack
- looks very like a chunk of heap.)
-
- The garbage collector uses LOOKS_LIKE_GHC_INFO when walking the stack, as it
- walks over the "pending arguments" on its way to the next return address.
- It is called moderately often, but not as often as HEAP_ALLOCED
-
- ToDo: LOOKS_LIKE_GHC_INFO(p) does not return True when p points to a
- constructor info table allocated by GHCi. We should really rename
- LOOKS_LIKE_GHC_INFO to LOOKS_LIKE_GHC_RETURN_INFO.
-
- Implementation
- ~~~~~~~~~~~~~~
- LOOKS_LIKE_GHC_INFO is more complicated because of the need to distinguish
- between static closures and info tables. It's a known portability problem.
- We have three approaches:
-
- Plan A: Address-space partitioning.
- Keep info tables in the (single, contiguous) text segment: IS_CODE_PTR(p)
- and static closures in the (single, contiguous) data segment: IS_DATA_PTR(p)
-
- Plan A can fail for two reasons:
- * In many environments (eg. dynamic loading),
- text and data aren't in a single contiguous range.
- * When we compile through vanilla C (no mangling) we sometimes
- can't guaranteee to put info tables in the text section. This
- happens eg. on MacOS where the C compiler refuses to put const
- data in the text section if it has any code pointers in it
- (which info tables do *only* when we're compiling without
- TABLES_NEXT_TO_CODE).
-
- Hence, Plan B: (compile-via-C-with-mangling, or native code generation)
- Put a zero word before each static closure.
- When compiling to native code, or via C-with-mangling, info tables
- are laid out "backwards" from the address specified in the info pointer
- (the entry code goes forward from the info pointer). Hence, the word
- before the one referenced the info pointer is part of the info table,
- and is guaranteed non-zero.
-
- For reasons nobody seems to fully understand, the statically-allocated tables
- of INTLIKE and CHARLIKE closures can't have this zero word, so we
- have to test separately for them.
-
- Plan B fails altogether for the compile-through-vanilla-C route, because
- info tables aren't laid out backwards.
-
-
- Hence, Plan C: (unregisterised, compile-through-vanilla-C route only)
- If we didn't manage to get info tables into the text section, then
- we can distinguish between a static closure pointer and an info
- pointer as follows: the first word of an info table is a code pointer,
- and therefore in text space, whereas the first word of a closure pointer
- is an info pointer, and therefore not. Shazam!
-*/
-
-
-/* When working with Win32 DLLs, static closures are identified by
- being prefixed with a zero word. This is needed so that we can
- distinguish between pointers to static closures and (reversed!)
- info tables.
-
- This 'scheme' breaks down for closure tables such as CHARLIKE,
- so we catch these separately.
-
- LOOKS_LIKE_STATIC_CLOSURE()
- - discriminates between static closures and info tbls
- (needed by LOOKS_LIKE_GHC_INFO() below - [Win32 DLLs only.])
- LOOKS_LIKE_STATIC()
- - distinguishes between static and heap allocated data.
- */
-#if defined(ENABLE_WIN32_DLL_SUPPORT)
- /* definitely do not enable for mingw DietHEP */
-#define LOOKS_LIKE_STATIC(r) (!(HEAP_ALLOCED(r)))
-
-/* Tiresome predicates needed to check for pointers into the closure tables */
-#define IS_CHARLIKE_CLOSURE(p) \
- ( (P_)(p) >= (P_)stg_CHARLIKE_closure && \
- (char*)(p) <= ((char*)stg_CHARLIKE_closure + \
- (MAX_CHARLIKE-MIN_CHARLIKE) * sizeof(StgIntCharlikeClosure)) )
-#define IS_INTLIKE_CLOSURE(p) \
- ( (P_)(p) >= (P_)stg_INTLIKE_closure && \
- (char*)(p) <= ((char*)stg_INTLIKE_closure + \
- (MAX_INTLIKE-MIN_INTLIKE) * sizeof(StgIntCharlikeClosure)) )
-
-#define LOOKS_LIKE_STATIC_CLOSURE(r) (((*(((unsigned long *)(r))-1)) == 0) || IS_CHARLIKE_CLOSURE(r) || IS_INTLIKE_CLOSURE(r))
-#else
-#define LOOKS_LIKE_STATIC(r) IS_DATA_PTR(r)
-#define LOOKS_LIKE_STATIC_CLOSURE(r) IS_DATA_PTR(r)
-#endif