| 1 | /* ---------------------------------------------------------------------------- |
|---|
| 2 | * |
|---|
| 3 | * (c) The GHC Team, 1998-2002 |
|---|
| 4 | * |
|---|
| 5 | * Info Tables |
|---|
| 6 | * |
|---|
| 7 | * -------------------------------------------------------------------------- */ |
|---|
| 8 | |
|---|
| 9 | #ifndef RTS_STORAGE_INFOTABLES_H |
|---|
| 10 | #define RTS_STORAGE_INFOTABLES_H |
|---|
| 11 | |
|---|
| 12 | /* ---------------------------------------------------------------------------- |
|---|
| 13 | Relative pointers |
|---|
| 14 | |
|---|
| 15 | Several pointer fields in info tables are expressed as offsets |
|---|
| 16 | relative to the info pointer, so that we can generate |
|---|
| 17 | position-independent code. |
|---|
| 18 | |
|---|
| 19 | Note [x86-64-relative] |
|---|
| 20 | There is a complication on the x86_64 platform, where pointeres are |
|---|
| 21 | 64 bits, but the tools don't support 64-bit relative relocations. |
|---|
| 22 | However, the default memory model (small) ensures that all symbols |
|---|
| 23 | have values in the lower 2Gb of the address space, so offsets all |
|---|
| 24 | fit in 32 bits. Hence we can use 32-bit offset fields. |
|---|
| 25 | |
|---|
| 26 | Somewhere between binutils-2.16.1 and binutils-2.16.91.0.6, |
|---|
| 27 | support for 64-bit PC-relative relocations was added, so maybe this |
|---|
| 28 | hackery can go away sometime. |
|---|
| 29 | ------------------------------------------------------------------------- */ |
|---|
| 30 | |
|---|
| 31 | #if x86_64_TARGET_ARCH |
|---|
| 32 | #define OFFSET_FIELD(n) StgHalfInt n; StgHalfWord __pad_##n |
|---|
| 33 | #else |
|---|
| 34 | #define OFFSET_FIELD(n) StgInt n |
|---|
| 35 | #endif |
|---|
| 36 | |
|---|
| 37 | /* ----------------------------------------------------------------------------- |
|---|
| 38 | Profiling info |
|---|
| 39 | -------------------------------------------------------------------------- */ |
|---|
| 40 | |
|---|
| 41 | typedef struct { |
|---|
| 42 | #ifndef TABLES_NEXT_TO_CODE |
|---|
| 43 | char *closure_type; |
|---|
| 44 | char *closure_desc; |
|---|
| 45 | #else |
|---|
| 46 | OFFSET_FIELD(closure_type_off); |
|---|
| 47 | OFFSET_FIELD(closure_desc_off); |
|---|
| 48 | #endif |
|---|
| 49 | } StgProfInfo; |
|---|
| 50 | |
|---|
| 51 | /* ----------------------------------------------------------------------------- |
|---|
| 52 | Ticky info |
|---|
| 53 | |
|---|
| 54 | There is no ticky-specific stuff in an info table at this time. |
|---|
| 55 | -------------------------------------------------------------------------- */ |
|---|
| 56 | |
|---|
| 57 | /* ----------------------------------------------------------------------------- |
|---|
| 58 | Debugging info |
|---|
| 59 | -------------------------------------------------------------------------- */ |
|---|
| 60 | |
|---|
| 61 | #ifdef DEBUG_CLOSURE |
|---|
| 62 | |
|---|
| 63 | typedef struct { |
|---|
| 64 | ... whatever ... |
|---|
| 65 | } StgDebugInfo; |
|---|
| 66 | |
|---|
| 67 | #else /* !DEBUG_CLOSURE */ |
|---|
| 68 | |
|---|
| 69 | /* There is no DEBUG-specific stuff in an info table at this time. */ |
|---|
| 70 | |
|---|
| 71 | #endif /* DEBUG_CLOSURE */ |
|---|
| 72 | |
|---|
| 73 | /* ----------------------------------------------------------------------------- |
|---|
| 74 | Closure flags |
|---|
| 75 | -------------------------------------------------------------------------- */ |
|---|
| 76 | |
|---|
| 77 | /* The type flags provide quick access to certain properties of a closure. */ |
|---|
| 78 | |
|---|
| 79 | #define _HNF (1<<0) /* head normal form? */ |
|---|
| 80 | #define _BTM (1<<1) /* uses info->layout.bitmap */ |
|---|
| 81 | #define _NS (1<<2) /* non-sparkable */ |
|---|
| 82 | #define _STA (1<<3) /* static? */ |
|---|
| 83 | #define _THU (1<<4) /* thunk? */ |
|---|
| 84 | #define _MUT (1<<5) /* mutable? */ |
|---|
| 85 | #define _UPT (1<<6) /* unpointed? */ |
|---|
| 86 | #define _SRT (1<<7) /* has an SRT? */ |
|---|
| 87 | #define _IND (1<<8) /* is an indirection? */ |
|---|
| 88 | |
|---|
| 89 | #define isSTATIC(flags) ((flags) &_STA) |
|---|
| 90 | #define isMUTABLE(flags) ((flags) &_MUT) |
|---|
| 91 | #define isBITMAP(flags) ((flags) &_BTM) |
|---|
| 92 | #define isTHUNK(flags) ((flags) &_THU) |
|---|
| 93 | #define isUNPOINTED(flags) ((flags) &_UPT) |
|---|
| 94 | #define hasSRT(flags) ((flags) &_SRT) |
|---|
| 95 | |
|---|
| 96 | extern StgWord16 closure_flags[]; |
|---|
| 97 | |
|---|
| 98 | #define closureFlags(c) (closure_flags[get_itbl(UNTAG_CLOSURE(c))->type]) |
|---|
| 99 | |
|---|
| 100 | #define closure_HNF(c) ( closureFlags(c) & _HNF) |
|---|
| 101 | #define closure_BITMAP(c) ( closureFlags(c) & _BTM) |
|---|
| 102 | #define closure_NON_SPARK(c) ( (closureFlags(c) & _NS)) |
|---|
| 103 | #define closure_SHOULD_SPARK(c) (!(closureFlags(c) & _NS)) |
|---|
| 104 | #define closure_STATIC(c) ( closureFlags(c) & _STA) |
|---|
| 105 | #define closure_THUNK(c) ( closureFlags(c) & _THU) |
|---|
| 106 | #define closure_MUTABLE(c) ( closureFlags(c) & _MUT) |
|---|
| 107 | #define closure_UNPOINTED(c) ( closureFlags(c) & _UPT) |
|---|
| 108 | #define closure_SRT(c) ( closureFlags(c) & _SRT) |
|---|
| 109 | #define closure_IND(c) ( closureFlags(c) & _IND) |
|---|
| 110 | |
|---|
| 111 | /* same as above but for info-ptr rather than closure */ |
|---|
| 112 | #define ipFlags(ip) (closure_flags[ip->type]) |
|---|
| 113 | |
|---|
| 114 | #define ip_HNF(ip) ( ipFlags(ip) & _HNF) |
|---|
| 115 | #define ip_BITMAP(ip) ( ipFlags(ip) & _BTM) |
|---|
| 116 | #define ip_SHOULD_SPARK(ip) (!(ipFlags(ip) & _NS)) |
|---|
| 117 | #define ip_STATIC(ip) ( ipFlags(ip) & _STA) |
|---|
| 118 | #define ip_THUNK(ip) ( ipFlags(ip) & _THU) |
|---|
| 119 | #define ip_MUTABLE(ip) ( ipFlags(ip) & _MUT) |
|---|
| 120 | #define ip_UNPOINTED(ip) ( ipFlags(ip) & _UPT) |
|---|
| 121 | #define ip_SRT(ip) ( ipFlags(ip) & _SRT) |
|---|
| 122 | #define ip_IND(ip) ( ipFlags(ip) & _IND) |
|---|
| 123 | |
|---|
| 124 | /* ----------------------------------------------------------------------------- |
|---|
| 125 | Bitmaps |
|---|
| 126 | |
|---|
| 127 | These are used to describe the pointerhood of a sequence of words |
|---|
| 128 | (usually on the stack) to the garbage collector. The two primary |
|---|
| 129 | uses are for stack frames, and functions (where we need to describe |
|---|
| 130 | the layout of a PAP to the GC). |
|---|
| 131 | |
|---|
| 132 | In these bitmaps: 0 == ptr, 1 == non-ptr. |
|---|
| 133 | -------------------------------------------------------------------------- */ |
|---|
| 134 | |
|---|
| 135 | /* |
|---|
| 136 | * Small bitmaps: for a small bitmap, we store the size and bitmap in |
|---|
| 137 | * the same word, using the following macros. If the bitmap doesn't |
|---|
| 138 | * fit in a single word, we use a pointer to an StgLargeBitmap below. |
|---|
| 139 | */ |
|---|
| 140 | #define MK_SMALL_BITMAP(size,bits) (((bits)<<BITMAP_BITS_SHIFT) | (size)) |
|---|
| 141 | |
|---|
| 142 | #define BITMAP_SIZE(bitmap) ((bitmap) & BITMAP_SIZE_MASK) |
|---|
| 143 | #define BITMAP_BITS(bitmap) ((bitmap) >> BITMAP_BITS_SHIFT) |
|---|
| 144 | |
|---|
| 145 | /* |
|---|
| 146 | * A large bitmap. |
|---|
| 147 | */ |
|---|
| 148 | typedef struct { |
|---|
| 149 | StgWord size; |
|---|
| 150 | StgWord bitmap[FLEXIBLE_ARRAY]; |
|---|
| 151 | } StgLargeBitmap; |
|---|
| 152 | |
|---|
| 153 | /* ----------------------------------------------------------------------------- |
|---|
| 154 | SRTs (Static Reference Tables) |
|---|
| 155 | |
|---|
| 156 | These tables are used to keep track of the static objects referred |
|---|
| 157 | to by the code for a closure or stack frame, so that we can follow |
|---|
| 158 | static data references from code and thus accurately |
|---|
| 159 | garbage-collect CAFs. |
|---|
| 160 | -------------------------------------------------------------------------- */ |
|---|
| 161 | |
|---|
| 162 | /* An SRT is just an array of closure pointers: */ |
|---|
| 163 | typedef StgClosure* StgSRT[]; |
|---|
| 164 | |
|---|
| 165 | /* |
|---|
| 166 | * Each info table refers to some subset of the closure pointers in an |
|---|
| 167 | * SRT. It does this using a pair of an StgSRT pointer and a |
|---|
| 168 | * half-word bitmap. If the half-word bitmap isn't large enough, then |
|---|
| 169 | * we fall back to a large SRT, including an unbounded bitmap. If the |
|---|
| 170 | * half-word bitmap is set to all ones (0xffff), then the StgSRT |
|---|
| 171 | * pointer instead points to an StgLargeSRT: |
|---|
| 172 | */ |
|---|
| 173 | typedef struct StgLargeSRT_ { |
|---|
| 174 | StgSRT *srt; |
|---|
| 175 | StgLargeBitmap l; |
|---|
| 176 | } StgLargeSRT; |
|---|
| 177 | |
|---|
| 178 | /* ---------------------------------------------------------------------------- |
|---|
| 179 | Info Tables |
|---|
| 180 | ------------------------------------------------------------------------- */ |
|---|
| 181 | |
|---|
| 182 | /* |
|---|
| 183 | * Stuff describing the closure layout. Well, actually, it might |
|---|
| 184 | * contain the selector index for a THUNK_SELECTOR. This union is one |
|---|
| 185 | * word long. |
|---|
| 186 | */ |
|---|
| 187 | typedef union { |
|---|
| 188 | struct { /* Heap closure payload layout: */ |
|---|
| 189 | StgHalfWord ptrs; /* number of pointers */ |
|---|
| 190 | StgHalfWord nptrs; /* number of non-pointers */ |
|---|
| 191 | } payload; |
|---|
| 192 | |
|---|
| 193 | StgWord bitmap; /* word-sized bit pattern describing */ |
|---|
| 194 | /* a stack frame: see below */ |
|---|
| 195 | |
|---|
| 196 | #ifndef TABLES_NEXT_TO_CODE |
|---|
| 197 | StgLargeBitmap* large_bitmap; /* pointer to large bitmap structure */ |
|---|
| 198 | #else |
|---|
| 199 | OFFSET_FIELD(large_bitmap_offset); /* offset from info table to large bitmap structure */ |
|---|
| 200 | #endif |
|---|
| 201 | |
|---|
| 202 | StgWord selector_offset; /* used in THUNK_SELECTORs */ |
|---|
| 203 | |
|---|
| 204 | } StgClosureInfo; |
|---|
| 205 | |
|---|
| 206 | |
|---|
| 207 | /* |
|---|
| 208 | * The "standard" part of an info table. Every info table has this bit. |
|---|
| 209 | */ |
|---|
| 210 | typedef struct StgInfoTable_ { |
|---|
| 211 | |
|---|
| 212 | #if !defined(TABLES_NEXT_TO_CODE) |
|---|
| 213 | StgFunPtr entry; /* pointer to the entry code */ |
|---|
| 214 | #endif |
|---|
| 215 | |
|---|
| 216 | #ifdef PROFILING |
|---|
| 217 | StgProfInfo prof; |
|---|
| 218 | #endif |
|---|
| 219 | #ifdef TICKY |
|---|
| 220 | /* Ticky-specific stuff would go here. */ |
|---|
| 221 | #endif |
|---|
| 222 | #ifdef DEBUG_CLOSURE |
|---|
| 223 | /* Debug-specific stuff would go here. */ |
|---|
| 224 | #endif |
|---|
| 225 | |
|---|
| 226 | StgClosureInfo layout; /* closure layout info (one word) */ |
|---|
| 227 | |
|---|
| 228 | StgHalfWord type; /* closure type */ |
|---|
| 229 | StgHalfWord srt_bitmap; |
|---|
| 230 | /* In a CONSTR: |
|---|
| 231 | - the constructor tag |
|---|
| 232 | In a FUN/THUNK |
|---|
| 233 | - a bitmap of SRT entries |
|---|
| 234 | */ |
|---|
| 235 | |
|---|
| 236 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 237 | StgCode code[FLEXIBLE_ARRAY]; |
|---|
| 238 | #endif |
|---|
| 239 | } *StgInfoTablePtr; |
|---|
| 240 | |
|---|
| 241 | |
|---|
| 242 | /* ----------------------------------------------------------------------------- |
|---|
| 243 | Function info tables |
|---|
| 244 | |
|---|
| 245 | This is the general form of function info tables. The compiler |
|---|
| 246 | will omit some of the fields in common cases: |
|---|
| 247 | |
|---|
| 248 | - If fun_type is not ARG_GEN or ARG_GEN_BIG, then the slow_apply |
|---|
| 249 | and bitmap fields may be left out (they are at the end, so omitting |
|---|
| 250 | them doesn't affect the layout). |
|---|
| 251 | |
|---|
| 252 | - If srt_bitmap (in the std info table part) is zero, then the srt |
|---|
| 253 | field may be omitted. This only applies if the slow_apply and |
|---|
| 254 | bitmap fields have also been omitted. |
|---|
| 255 | -------------------------------------------------------------------------- */ |
|---|
| 256 | |
|---|
| 257 | typedef struct StgFunInfoExtraRev_ { |
|---|
| 258 | OFFSET_FIELD(slow_apply_offset); /* apply to args on the stack */ |
|---|
| 259 | union { |
|---|
| 260 | StgWord bitmap; |
|---|
| 261 | OFFSET_FIELD(bitmap_offset); /* arg ptr/nonptr bitmap */ |
|---|
| 262 | } b; |
|---|
| 263 | OFFSET_FIELD(srt_offset); /* pointer to the SRT table */ |
|---|
| 264 | StgHalfWord fun_type; /* function type */ |
|---|
| 265 | StgHalfWord arity; /* function arity */ |
|---|
| 266 | } StgFunInfoExtraRev; |
|---|
| 267 | |
|---|
| 268 | typedef struct StgFunInfoExtraFwd_ { |
|---|
| 269 | StgHalfWord fun_type; /* function type */ |
|---|
| 270 | StgHalfWord arity; /* function arity */ |
|---|
| 271 | StgSRT *srt; /* pointer to the SRT table */ |
|---|
| 272 | union { /* union for compat. with TABLES_NEXT_TO_CODE version */ |
|---|
| 273 | StgWord bitmap; /* arg ptr/nonptr bitmap */ |
|---|
| 274 | } b; |
|---|
| 275 | StgFun *slow_apply; /* apply to args on the stack */ |
|---|
| 276 | } StgFunInfoExtraFwd; |
|---|
| 277 | |
|---|
| 278 | typedef struct { |
|---|
| 279 | #if defined(TABLES_NEXT_TO_CODE) |
|---|
| 280 | StgFunInfoExtraRev f; |
|---|
| 281 | StgInfoTable i; |
|---|
| 282 | #else |
|---|
| 283 | StgInfoTable i; |
|---|
| 284 | StgFunInfoExtraFwd f; |
|---|
| 285 | #endif |
|---|
| 286 | } StgFunInfoTable; |
|---|
| 287 | |
|---|
| 288 | // canned bitmap for each arg type, indexed by constants in FunTypes.h |
|---|
| 289 | extern StgWord stg_arg_bitmaps[]; |
|---|
| 290 | |
|---|
| 291 | /* ----------------------------------------------------------------------------- |
|---|
| 292 | Return info tables |
|---|
| 293 | -------------------------------------------------------------------------- */ |
|---|
| 294 | |
|---|
| 295 | /* |
|---|
| 296 | * When info tables are laid out backwards, we can omit the SRT |
|---|
| 297 | * pointer iff srt_bitmap is zero. |
|---|
| 298 | */ |
|---|
| 299 | |
|---|
| 300 | typedef struct { |
|---|
| 301 | #if defined(TABLES_NEXT_TO_CODE) |
|---|
| 302 | OFFSET_FIELD(srt_offset); /* offset to the SRT table */ |
|---|
| 303 | StgInfoTable i; |
|---|
| 304 | #else |
|---|
| 305 | StgInfoTable i; |
|---|
| 306 | StgSRT *srt; /* pointer to the SRT table */ |
|---|
| 307 | #endif |
|---|
| 308 | } StgRetInfoTable; |
|---|
| 309 | |
|---|
| 310 | /* ----------------------------------------------------------------------------- |
|---|
| 311 | Thunk info tables |
|---|
| 312 | -------------------------------------------------------------------------- */ |
|---|
| 313 | |
|---|
| 314 | /* |
|---|
| 315 | * When info tables are laid out backwards, we can omit the SRT |
|---|
| 316 | * pointer iff srt_bitmap is zero. |
|---|
| 317 | */ |
|---|
| 318 | |
|---|
| 319 | typedef struct StgThunkInfoTable_ { |
|---|
| 320 | #if !defined(TABLES_NEXT_TO_CODE) |
|---|
| 321 | StgInfoTable i; |
|---|
| 322 | #endif |
|---|
| 323 | #if defined(TABLES_NEXT_TO_CODE) |
|---|
| 324 | OFFSET_FIELD(srt_offset); /* offset to the SRT table */ |
|---|
| 325 | #else |
|---|
| 326 | StgSRT *srt; /* pointer to the SRT table */ |
|---|
| 327 | #endif |
|---|
| 328 | #if defined(TABLES_NEXT_TO_CODE) |
|---|
| 329 | StgInfoTable i; |
|---|
| 330 | #endif |
|---|
| 331 | } StgThunkInfoTable; |
|---|
| 332 | |
|---|
| 333 | /* ----------------------------------------------------------------------------- |
|---|
| 334 | Constructor info tables |
|---|
| 335 | -------------------------------------------------------------------------- */ |
|---|
| 336 | |
|---|
| 337 | typedef struct StgConInfoTable_ { |
|---|
| 338 | #if !defined(TABLES_NEXT_TO_CODE) |
|---|
| 339 | StgInfoTable i; |
|---|
| 340 | #endif |
|---|
| 341 | |
|---|
| 342 | #if defined(TABLES_NEXT_TO_CODE) |
|---|
| 343 | OFFSET_FIELD(con_desc); // the name of the data constructor |
|---|
| 344 | // as: Package:Module.Name |
|---|
| 345 | #else |
|---|
| 346 | char *con_desc; |
|---|
| 347 | #endif |
|---|
| 348 | |
|---|
| 349 | #if defined(TABLES_NEXT_TO_CODE) |
|---|
| 350 | StgInfoTable i; |
|---|
| 351 | #endif |
|---|
| 352 | } StgConInfoTable; |
|---|
| 353 | |
|---|
| 354 | |
|---|
| 355 | /* ----------------------------------------------------------------------------- |
|---|
| 356 | Accessor macros for fields that might be offsets (C version) |
|---|
| 357 | -------------------------------------------------------------------------- */ |
|---|
| 358 | |
|---|
| 359 | /* |
|---|
| 360 | * GET_SRT(info) |
|---|
| 361 | * info must be a Stg[Ret|Thunk]InfoTable* (an info table that has a SRT) |
|---|
| 362 | */ |
|---|
| 363 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 364 | #define GET_SRT(info) ((StgSRT*) (((StgWord) ((info)+1)) + (info)->srt_offset)) |
|---|
| 365 | #else |
|---|
| 366 | #define GET_SRT(info) ((info)->srt) |
|---|
| 367 | #endif |
|---|
| 368 | |
|---|
| 369 | /* |
|---|
| 370 | * GET_CON_DESC(info) |
|---|
| 371 | * info must be a StgConInfoTable*. |
|---|
| 372 | */ |
|---|
| 373 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 374 | #define GET_CON_DESC(info) ((char *)((StgWord)((info)+1) + (info->con_desc))) |
|---|
| 375 | #else |
|---|
| 376 | #define GET_CON_DESC(info) ((info)->con_desc) |
|---|
| 377 | #endif |
|---|
| 378 | |
|---|
| 379 | /* |
|---|
| 380 | * GET_FUN_SRT(info) |
|---|
| 381 | * info must be a StgFunInfoTable* |
|---|
| 382 | */ |
|---|
| 383 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 384 | #define GET_FUN_SRT(info) ((StgSRT*) (((StgWord) ((info)+1)) + (info)->f.srt_offset)) |
|---|
| 385 | #else |
|---|
| 386 | #define GET_FUN_SRT(info) ((info)->f.srt) |
|---|
| 387 | #endif |
|---|
| 388 | |
|---|
| 389 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 390 | #define GET_LARGE_BITMAP(info) ((StgLargeBitmap*) (((StgWord) ((info)+1)) \ |
|---|
| 391 | + (info)->layout.large_bitmap_offset)) |
|---|
| 392 | #else |
|---|
| 393 | #define GET_LARGE_BITMAP(info) ((info)->layout.large_bitmap) |
|---|
| 394 | #endif |
|---|
| 395 | |
|---|
| 396 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 397 | #define GET_FUN_LARGE_BITMAP(info) ((StgLargeBitmap*) (((StgWord) ((info)+1)) \ |
|---|
| 398 | + (info)->f.b.bitmap_offset)) |
|---|
| 399 | #else |
|---|
| 400 | #define GET_FUN_LARGE_BITMAP(info) ((StgLargeBitmap*) ((info)->f.b.bitmap)) |
|---|
| 401 | #endif |
|---|
| 402 | |
|---|
| 403 | /* |
|---|
| 404 | * GET_PROF_TYPE, GET_PROF_DESC |
|---|
| 405 | */ |
|---|
| 406 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 407 | #define GET_PROF_TYPE(info) ((char *)((StgWord)((info)+1) + (info->prof.closure_type_off))) |
|---|
| 408 | #else |
|---|
| 409 | #define GET_PROF_TYPE(info) ((info)->prof.closure_type) |
|---|
| 410 | #endif |
|---|
| 411 | #ifdef TABLES_NEXT_TO_CODE |
|---|
| 412 | #define GET_PROF_DESC(info) ((char *)((StgWord)((info)+1) + (info->prof.closure_desc_off))) |
|---|
| 413 | #else |
|---|
| 414 | #define GET_PROF_DESC(info) ((info)->prof.closure_desc) |
|---|
| 415 | #endif |
|---|
| 416 | |
|---|
| 417 | #endif /* RTS_STORAGE_INFOTABLES_H */ |
|---|