rts: Make function pointer parameters `const` where possible
[ghc.git] / includes / rts / storage / ClosureMacros.h
1 /* ----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 1998-2012
4 *
5 * Macros for building and manipulating closures
6 *
7 * -------------------------------------------------------------------------- */
8
9 #ifndef RTS_STORAGE_CLOSUREMACROS_H
10 #define RTS_STORAGE_CLOSUREMACROS_H
11
12 /* -----------------------------------------------------------------------------
13 Info tables are slammed up against the entry code, and the label
14 for the info table is at the *end* of the table itself. This
15 inline function adjusts an info pointer to point to the beginning
16 of the table, so we can use standard C structure indexing on it.
17
18 Note: this works for SRT info tables as long as you don't want to
19 access the SRT, since they are laid out the same with the SRT
20 pointer as the first word in the table.
21
22 NOTES ABOUT MANGLED C VS. MINI-INTERPRETER:
23
24 A couple of definitions:
25
26 "info pointer" The first word of the closure. Might point
27 to either the end or the beginning of the
28 info table, depending on whether we're using
29 the mini interpreter or not. GET_INFO(c)
30 retrieves the info pointer of a closure.
31
32 "info table" The info table structure associated with a
33 closure. This is always a pointer to the
34 beginning of the structure, so we can
35 use standard C structure indexing to pull out
36 the fields. get_itbl(c) returns a pointer to
37 the info table for closure c.
38
39 An address of the form xxxx_info points to the end of the info
40 table or the beginning of the info table depending on whether we're
41 mangling or not respectively. So,
42
43 c->header.info = xxx_info
44
45 makes absolute sense, whether mangling or not.
46
47 -------------------------------------------------------------------------- */
48
49 INLINE_HEADER void SET_INFO(StgClosure *c, const StgInfoTable *info) {
50 c->header.info = info;
51 }
52 INLINE_HEADER const StgInfoTable *GET_INFO(StgClosure *c) {
53 return c->header.info;
54 }
55
56 #define GET_ENTRY(c) (ENTRY_CODE(GET_INFO(c)))
57
58 #ifdef TABLES_NEXT_TO_CODE
59 EXTERN_INLINE StgInfoTable *INFO_PTR_TO_STRUCT(const StgInfoTable *info);
60 EXTERN_INLINE StgInfoTable *INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgInfoTable *)info - 1;}
61 EXTERN_INLINE StgRetInfoTable *RET_INFO_PTR_TO_STRUCT(const StgInfoTable *info);
62 EXTERN_INLINE StgRetInfoTable *RET_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgRetInfoTable *)info - 1;}
63 INLINE_HEADER StgFunInfoTable *FUN_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgFunInfoTable *)info - 1;}
64 INLINE_HEADER StgThunkInfoTable *THUNK_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgThunkInfoTable *)info - 1;}
65 INLINE_HEADER StgConInfoTable *CON_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgConInfoTable *)info - 1;}
66 INLINE_HEADER StgFunInfoTable *itbl_to_fun_itbl(const StgInfoTable *i) {return (StgFunInfoTable *)(i + 1) - 1;}
67 INLINE_HEADER StgRetInfoTable *itbl_to_ret_itbl(const StgInfoTable *i) {return (StgRetInfoTable *)(i + 1) - 1;}
68 INLINE_HEADER StgThunkInfoTable *itbl_to_thunk_itbl(const StgInfoTable *i) {return (StgThunkInfoTable *)(i + 1) - 1;}
69 INLINE_HEADER StgConInfoTable *itbl_to_con_itbl(const StgInfoTable *i) {return (StgConInfoTable *)(i + 1) - 1;}
70 #else
71 EXTERN_INLINE StgInfoTable *INFO_PTR_TO_STRUCT(const StgInfoTable *info);
72 EXTERN_INLINE StgInfoTable *INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgInfoTable *)info;}
73 EXTERN_INLINE StgRetInfoTable *RET_INFO_PTR_TO_STRUCT(const StgInfoTable *info);
74 EXTERN_INLINE StgRetInfoTable *RET_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgRetInfoTable *)info;}
75 INLINE_HEADER StgFunInfoTable *FUN_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgFunInfoTable *)info;}
76 INLINE_HEADER StgThunkInfoTable *THUNK_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgThunkInfoTable *)info;}
77 INLINE_HEADER StgConInfoTable *CON_INFO_PTR_TO_STRUCT(const StgInfoTable *info) {return (StgConInfoTable *)info;}
78 INLINE_HEADER StgFunInfoTable *itbl_to_fun_itbl(const StgInfoTable *i) {return (StgFunInfoTable *)i;}
79 INLINE_HEADER StgRetInfoTable *itbl_to_ret_itbl(const StgInfoTable *i) {return (StgRetInfoTable *)i;}
80 INLINE_HEADER StgThunkInfoTable *itbl_to_thunk_itbl(const StgInfoTable *i) {return (StgThunkInfoTable *)i;}
81 INLINE_HEADER StgConInfoTable *itbl_to_con_itbl(const StgInfoTable *i) {return (StgConInfoTable *)i;}
82 #endif
83
84 EXTERN_INLINE StgInfoTable *get_itbl(const StgClosure *c);
85 EXTERN_INLINE StgInfoTable *get_itbl(const StgClosure *c) {return INFO_PTR_TO_STRUCT(c->header.info);}
86
87 EXTERN_INLINE StgRetInfoTable *get_ret_itbl(const StgClosure *c);
88 EXTERN_INLINE StgRetInfoTable *get_ret_itbl(const StgClosure *c) {return RET_INFO_PTR_TO_STRUCT(c->header.info);}
89
90 INLINE_HEADER StgFunInfoTable *get_fun_itbl(const StgClosure *c) {return FUN_INFO_PTR_TO_STRUCT(c->header.info);}
91
92 INLINE_HEADER StgThunkInfoTable *get_thunk_itbl(const StgClosure *c) {return THUNK_INFO_PTR_TO_STRUCT(c->header.info);}
93
94 INLINE_HEADER StgConInfoTable *get_con_itbl(const StgClosure *c) {return CON_INFO_PTR_TO_STRUCT((c)->header.info);}
95
96 INLINE_HEADER StgHalfWord GET_TAG(const StgClosure *con) {
97 return get_itbl(con)->srt_bitmap;
98 }
99
100 /* -----------------------------------------------------------------------------
101 Macros for building closures
102 -------------------------------------------------------------------------- */
103
104 #ifdef PROFILING
105 #ifdef DEBUG_RETAINER
106 /*
107 For the sake of debugging, we take the safest way for the moment. Actually, this
108 is useful to check the sanity of heap before beginning retainer profiling.
109 flip is defined in RetainerProfile.c, and declared as extern in RetainerProfile.h.
110 Note: change those functions building Haskell objects from C datatypes, i.e.,
111 all rts_mk???() functions in RtsAPI.c, as well.
112 */
113 #define SET_PROF_HDR(c,ccs_) \
114 ((c)->header.prof.ccs = ccs_, (c)->header.prof.hp.rs = (retainerSet *)((StgWord)NULL | flip))
115 #else
116 /*
117 For retainer profiling only: we do not have to set (c)->header.prof.hp.rs to
118 NULL | flip (flip is defined in RetainerProfile.c) because even when flip
119 is 1, rs is invalid and will be initialized to NULL | flip later when
120 the closure *c is visited.
121 */
122 /*
123 #define SET_PROF_HDR(c,ccs_) \
124 ((c)->header.prof.ccs = ccs_, (c)->header.prof.hp.rs = NULL)
125 */
126 /*
127 The following macro works for both retainer profiling and LDV profiling:
128 for retainer profiling, ldvTime remains 0, so rs fields are initialized to 0.
129 See the invariants on ldvTime.
130 */
131 #define SET_PROF_HDR(c,ccs_) \
132 ((c)->header.prof.ccs = ccs_, \
133 LDV_RECORD_CREATE((c)))
134 #endif /* DEBUG_RETAINER */
135 #else
136 #define SET_PROF_HDR(c,ccs)
137 #endif
138
139 #define SET_HDR(c,_info,ccs) \
140 { \
141 (c)->header.info = _info; \
142 SET_PROF_HDR((StgClosure *)(c),ccs); \
143 }
144
145 #define SET_ARR_HDR(c,info,costCentreStack,n_bytes) \
146 SET_HDR(c,info,costCentreStack); \
147 (c)->bytes = n_bytes;
148
149 // Use when changing a closure from one kind to another
150 #define OVERWRITE_INFO(c, new_info) \
151 OVERWRITING_CLOSURE((StgClosure *)(c)); \
152 SET_INFO((StgClosure *)(c), (new_info)); \
153 LDV_RECORD_CREATE(c);
154
155 /* -----------------------------------------------------------------------------
156 How to get hold of the static link field for a static closure.
157 -------------------------------------------------------------------------- */
158
159 /* These are hard-coded. */
160 #define FUN_STATIC_LINK(p) (&(p)->payload[0])
161 #define THUNK_STATIC_LINK(p) (&(p)->payload[1])
162 #define IND_STATIC_LINK(p) (&(p)->payload[1])
163
164 INLINE_HEADER StgClosure **
165 STATIC_LINK(const StgInfoTable *info, StgClosure *p)
166 {
167 switch (info->type) {
168 case THUNK_STATIC:
169 return THUNK_STATIC_LINK(p);
170 case FUN_STATIC:
171 return FUN_STATIC_LINK(p);
172 case IND_STATIC:
173 return IND_STATIC_LINK(p);
174 default:
175 return &(p)->payload[info->layout.payload.ptrs +
176 info->layout.payload.nptrs];
177 }
178 }
179
180 /* -----------------------------------------------------------------------------
181 INTLIKE and CHARLIKE closures.
182 -------------------------------------------------------------------------- */
183
184 INLINE_HEADER P_ CHARLIKE_CLOSURE(int n) {
185 return (P_)&stg_CHARLIKE_closure[(n)-MIN_CHARLIKE];
186 }
187 INLINE_HEADER P_ INTLIKE_CLOSURE(int n) {
188 return (P_)&stg_INTLIKE_closure[(n)-MIN_INTLIKE];
189 }
190
191 /* ----------------------------------------------------------------------------
192 Macros for untagging and retagging closure pointers
193 For more information look at the comments in Cmm.h
194 ------------------------------------------------------------------------- */
195
196 static inline StgWord
197 GET_CLOSURE_TAG(const StgClosure * p)
198 {
199 return (StgWord)p & TAG_MASK;
200 }
201
202 static inline StgClosure *
203 UNTAG_CLOSURE(const StgClosure * p)
204 {
205 return (StgClosure*)((StgWord)p & ~TAG_MASK);
206 }
207
208 static inline StgClosure *
209 TAG_CLOSURE(StgWord tag,StgClosure * p)
210 {
211 return (StgClosure*)((StgWord)p | tag);
212 }
213
214 /* -----------------------------------------------------------------------------
215 Forwarding pointers
216 -------------------------------------------------------------------------- */
217
218 #define IS_FORWARDING_PTR(p) ((((StgWord)p) & 1) != 0)
219 #define MK_FORWARDING_PTR(p) (((StgWord)p) | 1)
220 #define UN_FORWARDING_PTR(p) (((StgWord)p) - 1)
221
222 /* -----------------------------------------------------------------------------
223 DEBUGGING predicates for pointers
224
225 LOOKS_LIKE_INFO_PTR(p) returns False if p is definitely not an info ptr
226 LOOKS_LIKE_CLOSURE_PTR(p) returns False if p is definitely not a closure ptr
227
228 These macros are complete but not sound. That is, they might
229 return false positives. Do not rely on them to distinguish info
230 pointers from closure pointers, for example.
231
232 We don't use address-space predicates these days, for portability
233 reasons, and the fact that code/data can be scattered about the
234 address space in a dynamically-linked environment. Our best option
235 is to look at the alleged info table and see whether it seems to
236 make sense...
237 -------------------------------------------------------------------------- */
238
239 INLINE_HEADER rtsBool LOOKS_LIKE_INFO_PTR_NOT_NULL (StgWord p)
240 {
241 StgInfoTable *info = INFO_PTR_TO_STRUCT((StgInfoTable *)p);
242 return (info->type != INVALID_OBJECT && info->type < N_CLOSURE_TYPES) ? rtsTrue : rtsFalse;
243 }
244
245 INLINE_HEADER rtsBool LOOKS_LIKE_INFO_PTR (StgWord p)
246 {
247 return (p && (IS_FORWARDING_PTR(p) || LOOKS_LIKE_INFO_PTR_NOT_NULL(p))) ? rtsTrue : rtsFalse;
248 }
249
250 INLINE_HEADER rtsBool LOOKS_LIKE_CLOSURE_PTR (const void *p)
251 {
252 return LOOKS_LIKE_INFO_PTR((StgWord)(UNTAG_CLOSURE((StgClosure *)(p)))->header.info);
253 }
254
255 /* -----------------------------------------------------------------------------
256 Macros for calculating the size of a closure
257 -------------------------------------------------------------------------- */
258
259 EXTERN_INLINE StgOffset PAP_sizeW ( uint32_t n_args );
260 EXTERN_INLINE StgOffset PAP_sizeW ( uint32_t n_args )
261 { return sizeofW(StgPAP) + n_args; }
262
263 EXTERN_INLINE StgOffset AP_sizeW ( uint32_t n_args );
264 EXTERN_INLINE StgOffset AP_sizeW ( uint32_t n_args )
265 { return sizeofW(StgAP) + n_args; }
266
267 EXTERN_INLINE StgOffset AP_STACK_sizeW ( uint32_t size );
268 EXTERN_INLINE StgOffset AP_STACK_sizeW ( uint32_t size )
269 { return sizeofW(StgAP_STACK) + size; }
270
271 EXTERN_INLINE StgOffset CONSTR_sizeW( uint32_t p, uint32_t np );
272 EXTERN_INLINE StgOffset CONSTR_sizeW( uint32_t p, uint32_t np )
273 { return sizeofW(StgHeader) + p + np; }
274
275 EXTERN_INLINE StgOffset THUNK_SELECTOR_sizeW ( void );
276 EXTERN_INLINE StgOffset THUNK_SELECTOR_sizeW ( void )
277 { return sizeofW(StgSelector); }
278
279 EXTERN_INLINE StgOffset BLACKHOLE_sizeW ( void );
280 EXTERN_INLINE StgOffset BLACKHOLE_sizeW ( void )
281 { return sizeofW(StgInd); } // a BLACKHOLE is a kind of indirection
282
283 /* --------------------------------------------------------------------------
284 Sizes of closures
285 ------------------------------------------------------------------------*/
286
287 EXTERN_INLINE StgOffset sizeW_fromITBL( const StgInfoTable* itbl );
288 EXTERN_INLINE StgOffset sizeW_fromITBL( const StgInfoTable* itbl )
289 { return sizeofW(StgClosure)
290 + sizeofW(StgPtr) * itbl->layout.payload.ptrs
291 + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
292
293 EXTERN_INLINE StgOffset thunk_sizeW_fromITBL( const StgInfoTable* itbl );
294 EXTERN_INLINE StgOffset thunk_sizeW_fromITBL( const StgInfoTable* itbl )
295 { return sizeofW(StgThunk)
296 + sizeofW(StgPtr) * itbl->layout.payload.ptrs
297 + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
298
299 EXTERN_INLINE StgOffset ap_stack_sizeW( StgAP_STACK* x );
300 EXTERN_INLINE StgOffset ap_stack_sizeW( StgAP_STACK* x )
301 { return AP_STACK_sizeW(x->size); }
302
303 EXTERN_INLINE StgOffset ap_sizeW( StgAP* x );
304 EXTERN_INLINE StgOffset ap_sizeW( StgAP* x )
305 { return AP_sizeW(x->n_args); }
306
307 EXTERN_INLINE StgOffset pap_sizeW( StgPAP* x );
308 EXTERN_INLINE StgOffset pap_sizeW( StgPAP* x )
309 { return PAP_sizeW(x->n_args); }
310
311 EXTERN_INLINE StgWord arr_words_words( StgArrBytes* x);
312 EXTERN_INLINE StgWord arr_words_words( StgArrBytes* x)
313 { return ROUNDUP_BYTES_TO_WDS(x->bytes); }
314
315 EXTERN_INLINE StgOffset arr_words_sizeW( StgArrBytes* x );
316 EXTERN_INLINE StgOffset arr_words_sizeW( StgArrBytes* x )
317 { return sizeofW(StgArrBytes) + arr_words_words(x); }
318
319 EXTERN_INLINE StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x );
320 EXTERN_INLINE StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
321 { return sizeofW(StgMutArrPtrs) + x->size; }
322
323 EXTERN_INLINE StgOffset small_mut_arr_ptrs_sizeW( StgSmallMutArrPtrs* x );
324 EXTERN_INLINE StgOffset small_mut_arr_ptrs_sizeW( StgSmallMutArrPtrs* x )
325 { return sizeofW(StgSmallMutArrPtrs) + x->ptrs; }
326
327 EXTERN_INLINE StgWord stack_sizeW ( StgStack *stack );
328 EXTERN_INLINE StgWord stack_sizeW ( StgStack *stack )
329 { return sizeofW(StgStack) + stack->stack_size; }
330
331 EXTERN_INLINE StgWord bco_sizeW ( StgBCO *bco );
332 EXTERN_INLINE StgWord bco_sizeW ( StgBCO *bco )
333 { return bco->size; }
334
335 /*
336 * TODO: Consider to switch return type from 'uint32_t' to 'StgWord' #8742
337 *
338 * (Also for 'closure_sizeW' below)
339 */
340 EXTERN_INLINE uint32_t closure_sizeW_ (const StgClosure *p, StgInfoTable *info);
341 EXTERN_INLINE uint32_t
342 closure_sizeW_ (const StgClosure *p, StgInfoTable *info)
343 {
344 switch (info->type) {
345 case THUNK_0_1:
346 case THUNK_1_0:
347 return sizeofW(StgThunk) + 1;
348 case FUN_0_1:
349 case CONSTR_0_1:
350 case FUN_1_0:
351 case CONSTR_1_0:
352 return sizeofW(StgHeader) + 1;
353 case THUNK_0_2:
354 case THUNK_1_1:
355 case THUNK_2_0:
356 return sizeofW(StgThunk) + 2;
357 case FUN_0_2:
358 case CONSTR_0_2:
359 case FUN_1_1:
360 case CONSTR_1_1:
361 case FUN_2_0:
362 case CONSTR_2_0:
363 return sizeofW(StgHeader) + 2;
364 case THUNK:
365 return thunk_sizeW_fromITBL(info);
366 case THUNK_SELECTOR:
367 return THUNK_SELECTOR_sizeW();
368 case AP_STACK:
369 return ap_stack_sizeW((StgAP_STACK *)p);
370 case AP:
371 return ap_sizeW((StgAP *)p);
372 case PAP:
373 return pap_sizeW((StgPAP *)p);
374 case IND:
375 return sizeofW(StgInd);
376 case ARR_WORDS:
377 return arr_words_sizeW((StgArrBytes *)p);
378 case MUT_ARR_PTRS_CLEAN:
379 case MUT_ARR_PTRS_DIRTY:
380 case MUT_ARR_PTRS_FROZEN:
381 case MUT_ARR_PTRS_FROZEN0:
382 return mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
383 case SMALL_MUT_ARR_PTRS_CLEAN:
384 case SMALL_MUT_ARR_PTRS_DIRTY:
385 case SMALL_MUT_ARR_PTRS_FROZEN:
386 case SMALL_MUT_ARR_PTRS_FROZEN0:
387 return small_mut_arr_ptrs_sizeW((StgSmallMutArrPtrs*)p);
388 case TSO:
389 return sizeofW(StgTSO);
390 case STACK:
391 return stack_sizeW((StgStack*)p);
392 case BCO:
393 return bco_sizeW((StgBCO *)p);
394 case TREC_CHUNK:
395 return sizeofW(StgTRecChunk);
396 default:
397 return sizeW_fromITBL(info);
398 }
399 }
400
401 // The definitive way to find the size, in words, of a heap-allocated closure
402 EXTERN_INLINE uint32_t closure_sizeW (const StgClosure *p);
403 EXTERN_INLINE uint32_t closure_sizeW (const StgClosure *p)
404 {
405 return closure_sizeW_(p, get_itbl(p));
406 }
407
408 /* -----------------------------------------------------------------------------
409 Sizes of stack frames
410 -------------------------------------------------------------------------- */
411
412 EXTERN_INLINE StgWord stack_frame_sizeW( StgClosure *frame );
413 EXTERN_INLINE StgWord stack_frame_sizeW( StgClosure *frame )
414 {
415 StgRetInfoTable *info;
416
417 info = get_ret_itbl(frame);
418 switch (info->i.type) {
419
420 case RET_FUN:
421 return sizeofW(StgRetFun) + ((StgRetFun *)frame)->size;
422
423 case RET_BIG:
424 return 1 + GET_LARGE_BITMAP(&info->i)->size;
425
426 case RET_BCO:
427 return 2 + BCO_BITMAP_SIZE((StgBCO *)((P_)frame)[1]);
428
429 default:
430 return 1 + BITMAP_SIZE(info->i.layout.bitmap);
431 }
432 }
433
434 /* -----------------------------------------------------------------------------
435 StgMutArrPtrs macros
436
437 An StgMutArrPtrs has a card table to indicate which elements are
438 dirty for the generational GC. The card table is an array of
439 bytes, where each byte covers (1 << MUT_ARR_PTRS_CARD_BITS)
440 elements. The card table is directly after the array data itself.
441 -------------------------------------------------------------------------- */
442
443 // The number of card bytes needed
444 INLINE_HEADER W_ mutArrPtrsCards (W_ elems)
445 {
446 return (W_)((elems + (1 << MUT_ARR_PTRS_CARD_BITS) - 1)
447 >> MUT_ARR_PTRS_CARD_BITS);
448 }
449
450 // The number of words in the card table
451 INLINE_HEADER W_ mutArrPtrsCardTableSize (W_ elems)
452 {
453 return ROUNDUP_BYTES_TO_WDS(mutArrPtrsCards(elems));
454 }
455
456 // The address of the card for a particular card number
457 INLINE_HEADER StgWord8 *mutArrPtrsCard (StgMutArrPtrs *a, W_ n)
458 {
459 return ((StgWord8 *)&(a->payload[a->ptrs]) + n);
460 }
461
462 /* -----------------------------------------------------------------------------
463 Replacing a closure with a different one. We must call
464 OVERWRITING_CLOSURE(p) on the old closure that is about to be
465 overwritten.
466
467 Note [zeroing slop]
468
469 In some scenarios we write zero words into "slop"; memory that is
470 left unoccupied after we overwrite a closure in the heap with a
471 smaller closure.
472
473 Zeroing slop is required for:
474
475 - full-heap sanity checks (DEBUG, and +RTS -DS)
476 - LDV profiling (PROFILING, and +RTS -hb)
477
478 Zeroing slop must be disabled for:
479
480 - THREADED_RTS with +RTS -N2 and greater, because we cannot
481 overwrite slop when another thread might be reading it.
482
483 Hence, slop is zeroed when either:
484
485 - PROFILING && era <= 0 (LDV is on)
486 - !THREADED_RTS && DEBUG
487
488 And additionally:
489
490 - LDV profiling and +RTS -N2 are incompatible
491 - full-heap sanity checks are disabled for THREADED_RTS
492
493 -------------------------------------------------------------------------- */
494
495 #define ZERO_SLOP_FOR_LDV_PROF (defined(PROFILING))
496 #define ZERO_SLOP_FOR_SANITY_CHECK (defined(DEBUG) && !defined(THREADED_RTS))
497
498 #if ZERO_SLOP_FOR_LDV_PROF || ZERO_SLOP_FOR_SANITY_CHECK
499 #define OVERWRITING_CLOSURE(c) overwritingClosure(c)
500 #define OVERWRITING_CLOSURE_OFS(c,n) \
501 overwritingClosureOfs(c,n)
502 #else
503 #define OVERWRITING_CLOSURE(c) /* nothing */
504 #define OVERWRITING_CLOSURE_OFS(c,n) /* nothing */
505 #endif
506
507 #ifdef PROFILING
508 void LDV_recordDead (const StgClosure *c, uint32_t size);
509 #endif
510
511 EXTERN_INLINE void overwritingClosure (StgClosure *p);
512 EXTERN_INLINE void overwritingClosure (StgClosure *p)
513 {
514 uint32_t size, i;
515
516 #if ZERO_SLOP_FOR_LDV_PROF && !ZERO_SLOP_FOR_SANITY_CHECK
517 // see Note [zeroing slop], also #8402
518 if (era <= 0) return;
519 #endif
520
521 size = closure_sizeW(p);
522
523 // For LDV profiling, we need to record the closure as dead
524 #if defined(PROFILING)
525 LDV_recordDead(p, size);
526 #endif
527
528 for (i = 0; i < size - sizeofW(StgThunkHeader); i++) {
529 ((StgThunk *)(p))->payload[i] = 0;
530 }
531 }
532
533 // Version of 'overwritingClosure' which overwrites only a suffix of a
534 // closure. The offset is expressed in words relative to 'p' and shall
535 // be less than or equal to closure_sizeW(p), and usually at least as
536 // large as the respective thunk header.
537 //
538 // Note: As this calls LDV_recordDead() you have to call LDV_RECORD()
539 // on the final state of the closure at the call-site
540 EXTERN_INLINE void overwritingClosureOfs (StgClosure *p, uint32_t offset);
541 EXTERN_INLINE void overwritingClosureOfs (StgClosure *p, uint32_t offset)
542 {
543 uint32_t size, i;
544
545 #if ZERO_SLOP_FOR_LDV_PROF && !ZERO_SLOP_FOR_SANITY_CHECK
546 // see Note [zeroing slop], also #8402
547 if (era <= 0) return;
548 #endif
549
550 size = closure_sizeW(p);
551
552 ASSERT(offset <= size);
553
554 // For LDV profiling, we need to record the closure as dead
555 #if defined(PROFILING)
556 LDV_recordDead(p, size);
557 #endif
558
559 for (i = offset; i < size; i++)
560 ((StgWord *)p)[i] = 0;
561 }
562
563 #endif /* RTS_STORAGE_CLOSUREMACROS_H */