1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 2001
8 * ---------------------------------------------------------------------------*/
12 // Turn off inlining when debugging - it obfuscates things
21 #include "RetainerProfile.h"
22 #include "RetainerSet.h"
29 #include "Profiling.h"
31 #include "BlockAlloc.h"
36 Note: what to change in order to plug-in a new retainer profiling scheme?
37 (1) type retainer in ../includes/StgRetainerProf.h
38 (2) retainer function R(), i.e., getRetainerFrom()
39 (3) the two hashing functions, hashKeySingleton() and hashKeyAddElement(),
40 in RetainerSet.h, if needed.
41 (4) printRetainer() and printRetainerSetShort() in RetainerSet.c.
44 /* -----------------------------------------------------------------------------
46 * -------------------------------------------------------------------------- */
48 static nat retainerGeneration; // generation
50 static nat numObjectVisited; // total number of objects visited
51 static nat timesAnyObjectVisited; // number of times any objects are visited
54 The rs field in the profile header of any object points to its retainer
55 set in an indirect way: if flip is 0, it points to the retainer set;
56 if flip is 1, it points to the next byte after the retainer set (even
57 for NULL pointers). Therefore, with flip 1, (rs ^ 1) is the actual
58 pointer. See retainerSetOf().
61 StgWord flip = 0; // flip bit
62 // must be 0 if DEBUG_RETAINER is on (for static closures)
64 #define setRetainerSetToNull(c) \
65 (c)->header.prof.hp.rs = (RetainerSet *)((StgWord)NULL | flip)
67 static void retainStack(StgClosure *, retainer, StgPtr, StgPtr);
68 static void retainClosure(StgClosure *, StgClosure *, retainer);
70 static void belongToHeap(StgPtr p);
75 cStackSize records how many times retainStack() has been invoked recursively,
76 that is, the number of activation records for retainStack() on the C stack.
77 maxCStackSize records its max value.
79 cStackSize <= maxCStackSize
81 static nat cStackSize, maxCStackSize;
83 static nat sumOfNewCost; // sum of the cost of each object, computed
84 // when the object is first visited
85 static nat sumOfNewCostExtra; // for those objects not visited during
86 // retainer profiling, e.g., MUT_VAR
87 static nat costArray[N_CLOSURE_TYPES];
89 nat sumOfCostLinear; // sum of the costs of all object, computed
90 // when linearly traversing the heap after
92 nat costArrayLinear[N_CLOSURE_TYPES];
95 /* -----------------------------------------------------------------------------
96 * Retainer stack - header
98 * Although the retainer stack implementation could be separated *
99 * from the retainer profiling engine, there does not seem to be
100 * any advantage in doing that; retainer stack is an integral part
101 * of retainer profiling engine and cannot be use elsewhere at
103 * -------------------------------------------------------------------------- */
113 // fixed layout or layout specified by a field in the closure
118 // See StgClosureInfo in InfoTables.h
119 #if SIZEOF_VOID_P == 8
156 firstStack points to the first block group.
157 currentStack points to the block group currently being used.
158 currentStack->free == stackLimit.
159 stackTop points to the topmost byte in the stack of currentStack.
160 Unless the whole stack is empty, stackTop must point to the topmost
161 object (or byte) in the whole stack. Thus, it is only when the whole stack
162 is empty that stackTop == stackLimit (not during the execution of push()
164 stackBottom == currentStack->start.
165 stackLimit == currentStack->start + BLOCK_SIZE_W * currentStack->blocks.
167 When a current stack becomes empty, stackTop is set to point to
168 the topmost element on the previous block group so as to satisfy
169 the invariants described above.
171 static bdescr *firstStack = NULL;
172 static bdescr *currentStack;
173 static stackElement *stackBottom, *stackTop, *stackLimit;
176 currentStackBoundary is used to mark the current stack chunk.
177 If stackTop == currentStackBoundary, it means that the current stack chunk
178 is empty. It is the responsibility of the user to keep currentStackBoundary
179 valid all the time if it is to be employed.
181 static stackElement *currentStackBoundary;
184 stackSize records the current size of the stack.
185 maxStackSize records its high water mark.
187 stackSize <= maxStackSize
189 stackSize is just an estimate measure of the depth of the graph. The reason
190 is that some heap objects have only a single child and may not result
191 in a new element being pushed onto the stack. Therefore, at the end of
192 retainer profiling, maxStackSize + maxCStackSize is some value no greater
193 than the actual depth of the graph.
195 #ifdef DEBUG_RETAINER
196 static int stackSize, maxStackSize;
199 // number of blocks allocated for one stack
200 #define BLOCKS_IN_STACK 1
202 /* -----------------------------------------------------------------------------
203 * Add a new block group to the stack.
205 * currentStack->link == s.
206 * -------------------------------------------------------------------------- */
208 newStackBlock( bdescr *bd )
211 stackTop = (stackElement *)(bd->start + BLOCK_SIZE_W * bd->blocks);
212 stackBottom = (stackElement *)bd->start;
213 stackLimit = (stackElement *)stackTop;
214 bd->free = (StgPtr)stackLimit;
217 /* -----------------------------------------------------------------------------
218 * Return to the previous block group.
220 * s->link == currentStack.
221 * -------------------------------------------------------------------------- */
223 returnToOldStack( bdescr *bd )
226 stackTop = (stackElement *)bd->free;
227 stackBottom = (stackElement *)bd->start;
228 stackLimit = (stackElement *)(bd->start + BLOCK_SIZE_W * bd->blocks);
229 bd->free = (StgPtr)stackLimit;
232 /* -----------------------------------------------------------------------------
233 * Initializes the traverse stack.
234 * -------------------------------------------------------------------------- */
236 initializeTraverseStack( void )
238 if (firstStack != NULL) {
239 freeChain(firstStack);
242 firstStack = allocGroup(BLOCKS_IN_STACK);
243 firstStack->link = NULL;
244 firstStack->u.back = NULL;
246 newStackBlock(firstStack);
249 /* -----------------------------------------------------------------------------
250 * Frees all the block groups in the traverse stack.
253 * -------------------------------------------------------------------------- */
255 closeTraverseStack( void )
257 freeChain(firstStack);
261 /* -----------------------------------------------------------------------------
262 * Returns rtsTrue if the whole stack is empty.
263 * -------------------------------------------------------------------------- */
264 static INLINE rtsBool
265 isEmptyRetainerStack( void )
267 return (firstStack == currentStack) && stackTop == stackLimit;
270 /* -----------------------------------------------------------------------------
271 * Returns size of stack
272 * -------------------------------------------------------------------------- */
275 retainerStackBlocks( void )
280 for (bd = firstStack; bd != NULL; bd = bd->link)
287 /* -----------------------------------------------------------------------------
288 * Returns rtsTrue if stackTop is at the stack boundary of the current stack,
289 * i.e., if the current stack chunk is empty.
290 * -------------------------------------------------------------------------- */
291 static INLINE rtsBool
294 return stackTop == currentStackBoundary;
297 /* -----------------------------------------------------------------------------
298 * Initializes *info from ptrs and payload.
300 * payload[] begins with ptrs pointers followed by non-pointers.
301 * -------------------------------------------------------------------------- */
303 init_ptrs( stackPos *info, nat ptrs, StgPtr payload )
305 info->type = posTypePtrs;
306 info->next.ptrs.pos = 0;
307 info->next.ptrs.ptrs = ptrs;
308 info->next.ptrs.payload = payload;
311 /* -----------------------------------------------------------------------------
312 * Find the next object from *info.
313 * -------------------------------------------------------------------------- */
314 static INLINE StgClosure *
315 find_ptrs( stackPos *info )
317 if (info->next.ptrs.pos < info->next.ptrs.ptrs) {
318 return (StgClosure *)info->next.ptrs.payload[info->next.ptrs.pos++];
324 /* -----------------------------------------------------------------------------
325 * Initializes *info from SRT information stored in *infoTable.
326 * -------------------------------------------------------------------------- */
328 init_srt_fun( stackPos *info, StgFunInfoTable *infoTable )
330 if (infoTable->i.srt_bitmap == (StgHalfWord)(-1)) {
331 info->type = posTypeLargeSRT;
332 info->next.large_srt.srt = (StgLargeSRT *)GET_FUN_SRT(infoTable);
333 info->next.large_srt.offset = 0;
335 info->type = posTypeSRT;
336 info->next.srt.srt = (StgClosure **)GET_FUN_SRT(infoTable);
337 info->next.srt.srt_bitmap = infoTable->i.srt_bitmap;
342 init_srt_thunk( stackPos *info, StgThunkInfoTable *infoTable )
344 if (infoTable->i.srt_bitmap == (StgHalfWord)(-1)) {
345 info->type = posTypeLargeSRT;
346 info->next.large_srt.srt = (StgLargeSRT *)GET_SRT(infoTable);
347 info->next.large_srt.offset = 0;
349 info->type = posTypeSRT;
350 info->next.srt.srt = (StgClosure **)GET_SRT(infoTable);
351 info->next.srt.srt_bitmap = infoTable->i.srt_bitmap;
355 /* -----------------------------------------------------------------------------
356 * Find the next object from *info.
357 * -------------------------------------------------------------------------- */
358 static INLINE StgClosure *
359 find_srt( stackPos *info )
364 if (info->type == posTypeSRT) {
366 bitmap = info->next.srt.srt_bitmap;
367 while (bitmap != 0) {
368 if ((bitmap & 1) != 0) {
369 #ifdef ENABLE_WIN32_DLL_SUPPORT
371 if ((unsigned long)(*(info->next.srt.srt)) & 0x1)
372 c = (* (StgClosure **)((unsigned long)*(info->next.srt.srt)) & ~0x1);
374 c = *(info->next.srt.srt);
376 c = *(info->next.srt.srt);
378 bitmap = bitmap >> 1;
379 info->next.srt.srt++;
380 info->next.srt.srt_bitmap = bitmap;
383 bitmap = bitmap >> 1;
384 info->next.srt.srt++;
386 // bitmap is now zero...
391 nat i = info->next.large_srt.offset;
394 // Follow the pattern from GC.c:scavenge_large_srt_bitmap().
395 bitmap = info->next.large_srt.srt->l.bitmap[i / BITS_IN(W_)];
396 bitmap = bitmap >> (i % BITS_IN(StgWord));
397 while (i < info->next.large_srt.srt->l.size) {
398 if ((bitmap & 1) != 0) {
399 c = ((StgClosure **)info->next.large_srt.srt->srt)[i];
401 info->next.large_srt.offset = i;
405 if (i % BITS_IN(W_) == 0) {
406 bitmap = info->next.large_srt.srt->l.bitmap[i / BITS_IN(W_)];
408 bitmap = bitmap >> 1;
411 // reached the end of this bitmap.
412 info->next.large_srt.offset = i;
417 /* -----------------------------------------------------------------------------
418 * push() pushes a stackElement representing the next child of *c
419 * onto the traverse stack. If *c has no child, *first_child is set
420 * to NULL and nothing is pushed onto the stack. If *c has only one
421 * child, *c_chlid is set to that child and nothing is pushed onto
422 * the stack. If *c has more than two children, *first_child is set
423 * to the first child and a stackElement representing the second
424 * child is pushed onto the stack.
427 * *c_child_r is the most recent retainer of *c's children.
428 * *c is not any of TSO, AP, PAP, AP_STACK, which means that
429 * there cannot be any stack objects.
430 * Note: SRTs are considered to be children as well.
431 * -------------------------------------------------------------------------- */
433 push( StgClosure *c, retainer c_child_r, StgClosure **first_child )
436 bdescr *nbd; // Next Block Descriptor
438 #ifdef DEBUG_RETAINER
439 // debugBelch("push(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary);
442 ASSERT(get_itbl(c)->type != TSO);
443 ASSERT(get_itbl(c)->type != AP_STACK);
450 se.c_child_r = c_child_r;
453 switch (get_itbl(c)->type) {
460 case SE_CAF_BLACKHOLE:
465 // one child (fixed), no SRT
467 *first_child = ((StgMutVar *)c)->var;
470 *first_child = ((StgSelector *)c)->selectee;
473 case IND_OLDGEN_PERM:
475 *first_child = ((StgInd *)c)->indirectee;
479 *first_child = c->payload[0];
482 // For CONSTR_2_0 and MVAR, we use se.info.step to record the position
483 // of the next child. We do not write a separate initialization code.
484 // Also we do not have to initialize info.type;
486 // two children (fixed), no SRT
487 // need to push a stackElement, but nothing to store in se.info
489 *first_child = c->payload[0]; // return the first pointer
490 // se.info.type = posTypeStep;
491 // se.info.next.step = 2; // 2 = second
494 // three children (fixed), no SRT
495 // need to push a stackElement
497 // head must be TSO and the head of a linked list of TSOs.
498 // Shoule it be a child? Seems to be yes.
499 *first_child = (StgClosure *)((StgMVar *)c)->head;
500 // se.info.type = posTypeStep;
501 se.info.next.step = 2; // 2 = second
504 // three children (fixed), no SRT
506 *first_child = ((StgWeak *)c)->key;
507 // se.info.type = posTypeStep;
508 se.info.next.step = 2;
511 // layout.payload.ptrs, no SRT
516 init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs,
518 *first_child = find_ptrs(&se.info);
519 if (*first_child == NULL)
523 // StgMutArrPtr.ptrs, no SRT
525 case MUT_ARR_PTRS_FROZEN:
526 init_ptrs(&se.info, ((StgMutArrPtrs *)c)->ptrs,
527 (StgPtr)(((StgMutArrPtrs *)c)->payload));
528 *first_child = find_ptrs(&se.info);
529 if (*first_child == NULL)
533 // layout.payload.ptrs, SRT
534 case FUN: // *c is a heap object.
536 init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, (StgPtr)c->payload);
537 *first_child = find_ptrs(&se.info);
538 if (*first_child == NULL)
539 // no child from ptrs, so check SRT
545 init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs,
546 (StgPtr)((StgThunk *)c)->payload);
547 *first_child = find_ptrs(&se.info);
548 if (*first_child == NULL)
549 // no child from ptrs, so check SRT
553 // 1 fixed child, SRT
556 *first_child = c->payload[0];
557 ASSERT(*first_child != NULL);
558 init_srt_fun(&se.info, get_fun_itbl(c));
563 *first_child = ((StgThunk *)c)->payload[0];
564 ASSERT(*first_child != NULL);
565 init_srt_thunk(&se.info, get_thunk_itbl(c));
568 case FUN_STATIC: // *c is a heap object.
569 ASSERT(get_itbl(c)->srt_bitmap != 0);
573 init_srt_fun(&se.info, get_fun_itbl(c));
574 *first_child = find_srt(&se.info);
575 if (*first_child == NULL)
581 ASSERT(get_itbl(c)->srt_bitmap != 0);
585 init_srt_thunk(&se.info, get_thunk_itbl(c));
586 *first_child = find_srt(&se.info);
587 if (*first_child == NULL)
598 case CONSTR_CHARLIKE:
599 case CONSTR_NOCAF_STATIC:
620 barf("Invalid object *c in push()");
624 if (stackTop - 1 < stackBottom) {
625 #ifdef DEBUG_RETAINER
626 // debugBelch("push() to the next stack.\n");
628 // currentStack->free is updated when the active stack is switched
629 // to the next stack.
630 currentStack->free = (StgPtr)stackTop;
632 if (currentStack->link == NULL) {
633 nbd = allocGroup(BLOCKS_IN_STACK);
635 nbd->u.back = currentStack;
636 currentStack->link = nbd;
638 nbd = currentStack->link;
643 // adjust stackTop (acutal push)
645 // If the size of stackElement was huge, we would better replace the
646 // following statement by either a memcpy() call or a switch statement
647 // on the type of the element. Currently, the size of stackElement is
648 // small enough (5 words) that this direct assignment seems to be enough.
651 #ifdef DEBUG_RETAINER
653 if (stackSize > maxStackSize) maxStackSize = stackSize;
654 // ASSERT(stackSize >= 0);
655 // debugBelch("stackSize = %d\n", stackSize);
659 /* -----------------------------------------------------------------------------
660 * popOff() and popOffReal(): Pop a stackElement off the traverse stack.
662 * stackTop cannot be equal to stackLimit unless the whole stack is
663 * empty, in which case popOff() is not allowed.
665 * You can think of popOffReal() as a part of popOff() which is
666 * executed at the end of popOff() in necessary. Since popOff() is
667 * likely to be executed quite often while popOffReal() is not, we
668 * separate popOffReal() from popOff(), which is declared as an
669 * INLINE function (for the sake of execution speed). popOffReal()
670 * is called only within popOff() and nowhere else.
671 * -------------------------------------------------------------------------- */
675 bdescr *pbd; // Previous Block Descriptor
677 #ifdef DEBUG_RETAINER
678 // debugBelch("pop() to the previous stack.\n");
681 ASSERT(stackTop + 1 == stackLimit);
682 ASSERT(stackBottom == (stackElement *)currentStack->start);
684 if (firstStack == currentStack) {
685 // The stack is completely empty.
687 ASSERT(stackTop == stackLimit);
688 #ifdef DEBUG_RETAINER
690 if (stackSize > maxStackSize) maxStackSize = stackSize;
692 ASSERT(stackSize >= 0);
693 debugBelch("stackSize = %d\n", stackSize);
699 // currentStack->free is updated when the active stack is switched back
700 // to the previous stack.
701 currentStack->free = (StgPtr)stackLimit;
703 // find the previous block descriptor
704 pbd = currentStack->u.back;
707 returnToOldStack(pbd);
709 #ifdef DEBUG_RETAINER
711 if (stackSize > maxStackSize) maxStackSize = stackSize;
713 ASSERT(stackSize >= 0);
714 debugBelch("stackSize = %d\n", stackSize);
721 #ifdef DEBUG_RETAINER
722 // debugBelch("\tpopOff(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary);
725 ASSERT(stackTop != stackLimit);
726 ASSERT(!isEmptyRetainerStack());
728 // <= (instead of <) is wrong!
729 if (stackTop + 1 < stackLimit) {
731 #ifdef DEBUG_RETAINER
733 if (stackSize > maxStackSize) maxStackSize = stackSize;
735 ASSERT(stackSize >= 0);
736 debugBelch("stackSize = %d\n", stackSize);
745 /* -----------------------------------------------------------------------------
746 * Finds the next object to be considered for retainer profiling and store
748 * Test if the topmost stack element indicates that more objects are left,
749 * and if so, retrieve the first object and store its pointer to *c. Also,
750 * set *cp and *r appropriately, both of which are stored in the stack element.
751 * The topmost stack element then is overwritten so as for it to now denote
753 * If the topmost stack element indicates no more objects are left, pop
754 * off the stack element until either an object can be retrieved or
755 * the current stack chunk becomes empty, indicated by rtsTrue returned by
756 * isOnBoundary(), in which case *c is set to NULL.
758 * It is okay to call this function even when the current stack chunk
760 * -------------------------------------------------------------------------- */
762 pop( StgClosure **c, StgClosure **cp, retainer *r )
766 #ifdef DEBUG_RETAINER
767 // debugBelch("pop(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary);
771 if (isOnBoundary()) { // if the current stack chunk is depleted
778 switch (get_itbl(se->c)->type) {
779 // two children (fixed), no SRT
780 // nothing in se.info
782 *c = se->c->payload[1];
788 // three children (fixed), no SRT
789 // need to push a stackElement
791 if (se->info.next.step == 2) {
792 *c = (StgClosure *)((StgMVar *)se->c)->tail;
793 se->info.next.step++; // move to the next step
796 *c = ((StgMVar *)se->c)->value;
803 // three children (fixed), no SRT
805 if (se->info.next.step == 2) {
806 *c = ((StgWeak *)se->c)->value;
807 se->info.next.step++;
810 *c = ((StgWeak *)se->c)->finalizer;
821 // StgMutArrPtr.ptrs, no SRT
823 case MUT_ARR_PTRS_FROZEN:
824 *c = find_ptrs(&se->info);
833 // layout.payload.ptrs, SRT
834 case FUN: // always a heap object
836 if (se->info.type == posTypePtrs) {
837 *c = find_ptrs(&se->info);
843 init_srt_fun(&se->info, get_fun_itbl(se->c));
849 if (se->info.type == posTypePtrs) {
850 *c = find_ptrs(&se->info);
856 init_srt_thunk(&se->info, get_thunk_itbl(se->c));
872 *c = find_srt(&se->info);
881 // no child (fixed), no SRT
887 case SE_CAF_BLACKHOLE:
889 // one child (fixed), no SRT
893 case IND_OLDGEN_PERM:
903 case CONSTR_CHARLIKE:
904 case CONSTR_NOCAF_STATIC:
925 barf("Invalid object *c in pop()");
931 /* -----------------------------------------------------------------------------
932 * RETAINER PROFILING ENGINE
933 * -------------------------------------------------------------------------- */
936 initRetainerProfiling( void )
938 initializeAllRetainerSet();
939 retainerGeneration = 0;
942 /* -----------------------------------------------------------------------------
943 * This function must be called before f-closing prof_file.
944 * -------------------------------------------------------------------------- */
946 endRetainerProfiling( void )
948 #ifdef SECOND_APPROACH
949 outputAllRetainerSet(prof_file);
953 /* -----------------------------------------------------------------------------
954 * Returns the actual pointer to the retainer set of the closure *c.
955 * It may adjust RSET(c) subject to flip.
957 * RSET(c) is initialized to NULL if its current value does not
960 * Even though this function has side effects, they CAN be ignored because
961 * subsequent calls to retainerSetOf() always result in the same return value
962 * and retainerSetOf() is the only way to retrieve retainerSet of a given
964 * We have to perform an XOR (^) operation each time a closure is examined.
965 * The reason is that we do not know when a closure is visited last.
966 * -------------------------------------------------------------------------- */
968 maybeInitRetainerSet( StgClosure *c )
970 if (!isRetainerSetFieldValid(c)) {
971 setRetainerSetToNull(c);
975 /* -----------------------------------------------------------------------------
976 * Returns rtsTrue if *c is a retainer.
977 * -------------------------------------------------------------------------- */
978 static INLINE rtsBool
979 isRetainer( StgClosure *c )
981 switch (get_itbl(c)->type) {
985 // TSOs MUST be retainers: they constitute the set of roots.
992 case MUT_ARR_PTRS_FROZEN:
994 // thunks are retainers.
1001 case THUNK_SELECTOR:
1005 // Static thunks, or CAFS, are obviously retainers.
1008 // WEAK objects are roots; there is separate code in which traversing
1009 // begins from WEAK objects.
1031 // partial applications
1037 case SE_CAF_BLACKHOLE:
1040 case IND_OLDGEN_PERM:
1054 // IND_STATIC cannot be *c, *cp, *r in the retainer profiling loop.
1056 // CONSTR_INTLIKE, CONSTR_CHARLIKE, and CONSTR_NOCAF_STATIC
1057 // cannot be *c, *cp, *r in the retainer profiling loop.
1058 case CONSTR_INTLIKE:
1059 case CONSTR_CHARLIKE:
1060 case CONSTR_NOCAF_STATIC:
1061 // Stack objects are invalid because they are never treated as
1062 // legal objects during retainer profiling.
1080 case INVALID_OBJECT:
1082 barf("Invalid object in isRetainer(): %d", get_itbl(c)->type);
1087 /* -----------------------------------------------------------------------------
1088 * Returns the retainer function value for the closure *c, i.e., R(*c).
1089 * This function does NOT return the retainer(s) of *c.
1091 * *c must be a retainer.
1093 * Depending on the definition of this function, the maintenance of retainer
1094 * sets can be made easier. If most retainer sets are likely to be created
1095 * again across garbage collections, refreshAllRetainerSet() in
1096 * RetainerSet.c can simply do nothing.
1097 * If this is not the case, we can free all the retainer sets and
1098 * re-initialize the hash table.
1099 * See refreshAllRetainerSet() in RetainerSet.c.
1100 * -------------------------------------------------------------------------- */
1101 static INLINE retainer
1102 getRetainerFrom( StgClosure *c )
1104 ASSERT(isRetainer(c));
1106 #if defined(RETAINER_SCHEME_INFO)
1107 // Retainer scheme 1: retainer = info table
1109 #elif defined(RETAINER_SCHEME_CCS)
1110 // Retainer scheme 2: retainer = cost centre stack
1111 return c->header.prof.ccs;
1112 #elif defined(RETAINER_SCHEME_CC)
1113 // Retainer scheme 3: retainer = cost centre
1114 return c->header.prof.ccs->cc;
1118 /* -----------------------------------------------------------------------------
1119 * Associates the retainer set *s with the closure *c, that is, *s becomes
1120 * the retainer set of *c.
1124 * -------------------------------------------------------------------------- */
1126 associate( StgClosure *c, RetainerSet *s )
1128 // StgWord has the same size as pointers, so the following type
1130 RSET(c) = (RetainerSet *)((StgWord)s | flip);
1133 /* -----------------------------------------------------------------------------
1134 Call retainClosure for each of the closures covered by a large bitmap.
1135 -------------------------------------------------------------------------- */
1138 retain_large_bitmap (StgPtr p, StgLargeBitmap *large_bitmap, nat size,
1139 StgClosure *c, retainer c_child_r)
1145 bitmap = large_bitmap->bitmap[b];
1146 for (i = 0; i < size; ) {
1147 if ((bitmap & 1) == 0) {
1148 retainClosure((StgClosure *)*p, c, c_child_r);
1152 if (i % BITS_IN(W_) == 0) {
1154 bitmap = large_bitmap->bitmap[b];
1156 bitmap = bitmap >> 1;
1161 static INLINE StgPtr
1162 retain_small_bitmap (StgPtr p, nat size, StgWord bitmap,
1163 StgClosure *c, retainer c_child_r)
1166 if ((bitmap & 1) == 0) {
1167 retainClosure((StgClosure *)*p, c, c_child_r);
1170 bitmap = bitmap >> 1;
1176 /* -----------------------------------------------------------------------------
1177 * Call retainClosure for each of the closures in an SRT.
1178 * ------------------------------------------------------------------------- */
1181 retain_large_srt_bitmap (StgLargeSRT *srt, StgClosure *c, retainer c_child_r)
1188 p = (StgClosure **)srt->srt;
1190 bitmap = srt->l.bitmap[b];
1191 for (i = 0; i < size; ) {
1192 if ((bitmap & 1) != 0) {
1193 retainClosure((StgClosure *)*p, c, c_child_r);
1197 if (i % BITS_IN(W_) == 0) {
1199 bitmap = srt->l.bitmap[b];
1201 bitmap = bitmap >> 1;
1207 retainSRT (StgClosure **srt, nat srt_bitmap, StgClosure *c, retainer c_child_r)
1212 bitmap = srt_bitmap;
1215 if (bitmap == (StgHalfWord)(-1)) {
1216 retain_large_srt_bitmap( (StgLargeSRT *)srt, c, c_child_r );
1220 while (bitmap != 0) {
1221 if ((bitmap & 1) != 0) {
1222 #ifdef ENABLE_WIN32_DLL_SUPPORT
1223 if ( (unsigned long)(*srt) & 0x1 ) {
1224 retainClosure(*stgCast(StgClosure**,(stgCast(unsigned long, *srt) & ~0x1)),
1227 retainClosure(*srt,c,c_child_r);
1230 retainClosure(*srt,c,c_child_r);
1234 bitmap = bitmap >> 1;
1238 /* -----------------------------------------------------------------------------
1239 * Process all the objects in the stack chunk from stackStart to stackEnd
1240 * with *c and *c_child_r being their parent and their most recent retainer,
1241 * respectively. Treat stackOptionalFun as another child of *c if it is
1244 * *c is one of the following: TSO, AP_STACK.
1245 * If *c is TSO, c == c_child_r.
1246 * stackStart < stackEnd.
1247 * RSET(c) and RSET(c_child_r) are valid, i.e., their
1248 * interpretation conforms to the current value of flip (even when they
1249 * are interpreted to be NULL).
1250 * If *c is TSO, its state is not any of ThreadRelocated, ThreadComplete,
1251 * or ThreadKilled, which means that its stack is ready to process.
1253 * This code was almost plagiarzied from GC.c! For each pointer,
1254 * retainClosure() is invoked instead of evacuate().
1255 * -------------------------------------------------------------------------- */
1257 retainStack( StgClosure *c, retainer c_child_r,
1258 StgPtr stackStart, StgPtr stackEnd )
1260 stackElement *oldStackBoundary;
1262 StgRetInfoTable *info;
1266 #ifdef DEBUG_RETAINER
1268 if (cStackSize > maxCStackSize) maxCStackSize = cStackSize;
1272 Each invocation of retainStack() creates a new virtual
1273 stack. Since all such stacks share a single common stack, we
1274 record the current currentStackBoundary, which will be restored
1277 oldStackBoundary = currentStackBoundary;
1278 currentStackBoundary = stackTop;
1280 #ifdef DEBUG_RETAINER
1281 // debugBelch("retainStack() called: oldStackBoundary = 0x%x, currentStackBoundary = 0x%x\n", oldStackBoundary, currentStackBoundary);
1284 ASSERT(get_itbl(c)->type != TSO ||
1285 (((StgTSO *)c)->what_next != ThreadRelocated &&
1286 ((StgTSO *)c)->what_next != ThreadComplete &&
1287 ((StgTSO *)c)->what_next != ThreadKilled));
1290 while (p < stackEnd) {
1291 info = get_ret_itbl((StgClosure *)p);
1293 switch(info->i.type) {
1296 retainClosure(((StgUpdateFrame *)p)->updatee, c, c_child_r);
1297 p += sizeofW(StgUpdateFrame);
1304 bitmap = BITMAP_BITS(info->i.layout.bitmap);
1305 size = BITMAP_SIZE(info->i.layout.bitmap);
1307 p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
1310 retainSRT((StgClosure **)GET_SRT(info), info->i.srt_bitmap, c, c_child_r);
1317 retainClosure((StgClosure *)*p, c, c_child_r);
1320 size = BCO_BITMAP_SIZE(bco);
1321 retain_large_bitmap(p, BCO_BITMAP(bco), size, c, c_child_r);
1326 // large bitmap (> 32 entries, or > 64 on a 64-bit machine)
1329 size = GET_LARGE_BITMAP(&info->i)->size;
1331 retain_large_bitmap(p, GET_LARGE_BITMAP(&info->i),
1332 size, c, c_child_r);
1334 // and don't forget to follow the SRT
1337 // Dynamic bitmap: the mask is stored on the stack
1340 dyn = ((StgRetDyn *)p)->liveness;
1342 // traverse the bitmap first
1343 bitmap = RET_DYN_LIVENESS(dyn);
1344 p = (P_)&((StgRetDyn *)p)->payload[0];
1345 size = RET_DYN_BITMAP_SIZE;
1346 p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
1348 // skip over the non-ptr words
1349 p += RET_DYN_NONPTRS(dyn) + RET_DYN_NONPTR_REGS_SIZE;
1351 // follow the ptr words
1352 for (size = RET_DYN_PTRS(dyn); size > 0; size--) {
1353 retainClosure((StgClosure *)*p, c, c_child_r);
1360 StgRetFun *ret_fun = (StgRetFun *)p;
1361 StgFunInfoTable *fun_info;
1363 retainClosure(ret_fun->fun, c, c_child_r);
1364 fun_info = get_fun_itbl(ret_fun->fun);
1366 p = (P_)&ret_fun->payload;
1367 switch (fun_info->f.fun_type) {
1369 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
1370 size = BITMAP_SIZE(fun_info->f.b.bitmap);
1371 p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
1374 size = GET_FUN_LARGE_BITMAP(fun_info)->size;
1375 retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info),
1376 size, c, c_child_r);
1380 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
1381 size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
1382 p = retain_small_bitmap(p, size, bitmap, c, c_child_r);
1389 barf("Invalid object found in retainStack(): %d",
1390 (int)(info->i.type));
1394 // restore currentStackBoundary
1395 currentStackBoundary = oldStackBoundary;
1396 #ifdef DEBUG_RETAINER
1397 // debugBelch("retainStack() finished: currentStackBoundary = 0x%x\n", currentStackBoundary);
1400 #ifdef DEBUG_RETAINER
1405 /* ----------------------------------------------------------------------------
1406 * Call retainClosure for each of the children of a PAP/AP
1407 * ------------------------------------------------------------------------- */
1409 static INLINE StgPtr
1410 retain_PAP_payload (StgClosure *pap, retainer c_child_r, StgClosure *fun,
1411 StgClosure** payload, StgWord n_args)
1415 StgFunInfoTable *fun_info;
1417 retainClosure(fun, pap, c_child_r);
1418 fun_info = get_fun_itbl(fun);
1419 ASSERT(fun_info->i.type != PAP);
1421 p = (StgPtr)payload;
1423 switch (fun_info->f.fun_type) {
1425 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
1426 p = retain_small_bitmap(p, n_args, bitmap,
1430 retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info),
1431 n_args, pap, c_child_r);
1435 retain_large_bitmap((StgPtr)payload, BCO_BITMAP(fun),
1436 n_args, pap, c_child_r);
1440 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
1441 p = retain_small_bitmap(p, n_args, bitmap, pap, c_child_r);
1447 /* -----------------------------------------------------------------------------
1448 * Compute the retainer set of *c0 and all its desecents by traversing.
1449 * *cp0 is the parent of *c0, and *r0 is the most recent retainer of *c0.
1451 * c0 = cp0 = r0 holds only for root objects.
1452 * RSET(cp0) and RSET(r0) are valid, i.e., their
1453 * interpretation conforms to the current value of flip (even when they
1454 * are interpreted to be NULL).
1455 * However, RSET(c0) may be corrupt, i.e., it may not conform to
1456 * the current value of flip. If it does not, during the execution
1457 * of this function, RSET(c0) must be initialized as well as all
1460 * stackTop must be the same at the beginning and the exit of this function.
1461 * *c0 can be TSO (as well as AP_STACK).
1462 * -------------------------------------------------------------------------- */
1464 retainClosure( StgClosure *c0, StgClosure *cp0, retainer r0 )
1466 // c = Current closure
1467 // cp = Current closure's Parent
1468 // r = current closures' most recent Retainer
1469 // c_child_r = current closure's children's most recent retainer
1470 // first_child = first child of c
1471 StgClosure *c, *cp, *first_child;
1472 RetainerSet *s, *retainerSetOfc;
1473 retainer r, c_child_r;
1476 #ifdef DEBUG_RETAINER
1477 // StgPtr oldStackTop;
1480 #ifdef DEBUG_RETAINER
1481 // oldStackTop = stackTop;
1482 // debugBelch("retainClosure() called: c0 = 0x%x, cp0 = 0x%x, r0 = 0x%x\n", c0, cp0, r0);
1485 // (c, cp, r) = (c0, cp0, r0)
1492 //debugBelch("loop");
1493 // pop to (c, cp, r);
1497 #ifdef DEBUG_RETAINER
1498 // debugBelch("retainClosure() ends: oldStackTop = 0x%x, stackTop = 0x%x\n", oldStackTop, stackTop);
1503 //debugBelch("inner_loop");
1506 // c = current closure under consideration,
1507 // cp = current closure's parent,
1508 // r = current closure's most recent retainer
1510 // Loop invariants (on the meaning of c, cp, r, and their retainer sets):
1511 // RSET(cp) and RSET(r) are valid.
1512 // RSET(c) is valid only if c has been visited before.
1514 // Loop invariants (on the relation between c, cp, and r)
1515 // if cp is not a retainer, r belongs to RSET(cp).
1516 // if cp is a retainer, r == cp.
1518 typeOfc = get_itbl(c)->type;
1520 #ifdef DEBUG_RETAINER
1523 case CONSTR_INTLIKE:
1524 case CONSTR_CHARLIKE:
1525 case CONSTR_NOCAF_STATIC:
1531 if (retainerSetOf(c) == NULL) { // first visit?
1532 costArray[typeOfc] += cost(c);
1533 sumOfNewCost += cost(c);
1542 if (((StgTSO *)c)->what_next == ThreadComplete ||
1543 ((StgTSO *)c)->what_next == ThreadKilled) {
1544 #ifdef DEBUG_RETAINER
1545 debugBelch("ThreadComplete or ThreadKilled encountered in retainClosure()\n");
1549 if (((StgTSO *)c)->what_next == ThreadRelocated) {
1550 #ifdef DEBUG_RETAINER
1551 debugBelch("ThreadRelocated encountered in retainClosure()\n");
1553 c = (StgClosure *)((StgTSO *)c)->link;
1559 // We just skip IND_STATIC, so its retainer set is never computed.
1560 c = ((StgIndStatic *)c)->indirectee;
1562 case CONSTR_INTLIKE:
1563 case CONSTR_CHARLIKE:
1564 // static objects with no pointers out, so goto loop.
1565 case CONSTR_NOCAF_STATIC:
1566 // It is not just enough not to compute the retainer set for *c; it is
1567 // mandatory because CONSTR_NOCAF_STATIC are not reachable from
1568 // scavenged_static_objects, the list from which is assumed to traverse
1569 // all static objects after major garbage collections.
1573 if (get_itbl(c)->srt_bitmap == 0) {
1574 // No need to compute the retainer set; no dynamic objects
1575 // are reachable from *c.
1577 // Static objects: if we traverse all the live closures,
1578 // including static closures, during each heap census then
1579 // we will observe that some static closures appear and
1580 // disappear. eg. a closure may contain a pointer to a
1581 // static function 'f' which is not otherwise reachable
1582 // (it doesn't indirectly point to any CAFs, so it doesn't
1583 // appear in any SRTs), so we would find 'f' during
1584 // traversal. However on the next sweep there may be no
1585 // closures pointing to 'f'.
1587 // We must therefore ignore static closures whose SRT is
1588 // empty, because these are exactly the closures that may
1589 // "appear". A closure with a non-empty SRT, and which is
1590 // still required, will always be reachable.
1592 // But what about CONSTR_STATIC? Surely these may be able
1593 // to appear, and they don't have SRTs, so we can't
1594 // check. So for now, we're calling
1595 // resetStaticObjectForRetainerProfiling() from the
1596 // garbage collector to reset the retainer sets in all the
1597 // reachable static objects.
1604 // The above objects are ignored in computing the average number of times
1605 // an object is visited.
1606 timesAnyObjectVisited++;
1608 // If this is the first visit to c, initialize its retainer set.
1609 maybeInitRetainerSet(c);
1610 retainerSetOfc = retainerSetOf(c);
1613 // isRetainer(cp) == rtsTrue => s == NULL
1614 // isRetainer(cp) == rtsFalse => s == cp.retainer
1618 s = retainerSetOf(cp);
1620 // (c, cp, r, s) is available.
1622 // (c, cp, r, s, R_r) is available, so compute the retainer set for *c.
1623 if (retainerSetOfc == NULL) {
1624 // This is the first visit to *c.
1628 associate(c, singleton(r));
1630 // s is actually the retainer set of *c!
1633 // compute c_child_r
1634 c_child_r = isRetainer(c) ? getRetainerFrom(c) : r;
1636 // This is not the first visit to *c.
1637 if (isMember(r, retainerSetOfc))
1638 goto loop; // no need to process child
1641 associate(c, addElement(r, retainerSetOfc));
1643 // s is not NULL and cp is not a retainer. This means that
1644 // each time *cp is visited, so is *c. Thus, if s has
1645 // exactly one more element in its retainer set than c, s
1646 // is also the new retainer set for *c.
1647 if (s->num == retainerSetOfc->num + 1) {
1650 // Otherwise, just add R_r to the current retainer set of *c.
1652 associate(c, addElement(r, retainerSetOfc));
1657 goto loop; // no need to process child
1659 // compute c_child_r
1663 // now, RSET() of all of *c, *cp, and *r is valid.
1664 // (c, c_child_r) are available.
1668 // Special case closures: we process these all in one go rather
1669 // than attempting to save the current position, because doing so
1673 retainStack(c, c_child_r,
1675 ((StgTSO *)c)->stack + ((StgTSO *)c)->stack_size);
1680 StgPAP *pap = (StgPAP *)c;
1681 retain_PAP_payload(c, c_child_r, pap->fun, pap->payload, pap->n_args);
1687 StgAP *ap = (StgAP *)c;
1688 retain_PAP_payload(c, c_child_r, ap->fun, ap->payload, ap->n_args);
1693 retainClosure(((StgAP_STACK *)c)->fun, c, c_child_r);
1694 retainStack(c, c_child_r,
1695 (StgPtr)((StgAP_STACK *)c)->payload,
1696 (StgPtr)((StgAP_STACK *)c)->payload +
1697 ((StgAP_STACK *)c)->size);
1701 push(c, c_child_r, &first_child);
1703 // If first_child is null, c has no child.
1704 // If first_child is not null, the top stack element points to the next
1705 // object. push() may or may not push a stackElement on the stack.
1706 if (first_child == NULL)
1709 // (c, cp, r) = (first_child, c, c_child_r)
1716 /* -----------------------------------------------------------------------------
1717 * Compute the retainer set for every object reachable from *tl.
1718 * -------------------------------------------------------------------------- */
1720 retainRoot( StgClosure **tl )
1722 // We no longer assume that only TSOs and WEAKs are roots; any closure can
1725 ASSERT(isEmptyRetainerStack());
1726 currentStackBoundary = stackTop;
1728 if (isRetainer(*tl)) {
1729 retainClosure(*tl, *tl, getRetainerFrom(*tl));
1731 retainClosure(*tl, *tl, CCS_SYSTEM);
1734 // NOT TRUE: ASSERT(isMember(getRetainerFrom(*tl), retainerSetOf(*tl)));
1735 // *tl might be a TSO which is ThreadComplete, in which
1736 // case we ignore it for the purposes of retainer profiling.
1739 /* -----------------------------------------------------------------------------
1740 * Compute the retainer set for each of the objects in the heap.
1741 * -------------------------------------------------------------------------- */
1743 computeRetainerSet( void )
1750 #ifdef DEBUG_RETAINER
1751 RetainerSet tmpRetainerSet;
1754 GetRoots(retainRoot); // for scheduler roots
1756 // This function is called after a major GC, when key, value, and finalizer
1757 // all are guaranteed to be valid, or reachable.
1759 // The following code assumes that WEAK objects are considered to be roots
1760 // for retainer profilng.
1761 for (weak = weak_ptr_list; weak != NULL; weak = weak->link)
1762 // retainRoot((StgClosure *)weak);
1763 retainRoot((StgClosure **)&weak);
1765 // Consider roots from the stable ptr table.
1766 markStablePtrTable(retainRoot);
1768 // The following code resets the rs field of each unvisited mutable
1769 // object (computing sumOfNewCostExtra and updating costArray[] when
1770 // debugging retainer profiler).
1771 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1772 ASSERT(g != 0 || (generations[g].mut_list == NULL));
1774 // Traversing through mut_list is necessary
1775 // because we can find MUT_VAR objects which have not been
1776 // visited during retainer profiling.
1777 for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) {
1778 for (ml = bd->start; ml < bd->free; ml++) {
1780 maybeInitRetainerSet((StgClosure *)ml);
1781 rtl = retainerSetOf((StgClosure *)ml);
1783 #ifdef DEBUG_RETAINER
1785 // first visit to *ml
1786 // This is a violation of the interface rule!
1787 RSET(ml) = (RetainerSet *)((StgWord)(&tmpRetainerSet) | flip);
1789 switch (get_itbl((StgClosure *)ml)->type) {
1793 case CONSTR_INTLIKE:
1794 case CONSTR_CHARLIKE:
1795 case CONSTR_NOCAF_STATIC:
1799 barf("Invalid object in computeRetainerSet(): %d", get_itbl((StgClosure*)ml)->type);
1803 costArray[get_itbl((StgClosure *)ml)->type] += cost((StgClosure *)ml);
1804 sumOfNewCostExtra += cost((StgClosure *)ml);
1814 /* -----------------------------------------------------------------------------
1815 * Traverse all static objects for which we compute retainer sets,
1816 * and reset their rs fields to NULL, which is accomplished by
1817 * invoking maybeInitRetainerSet(). This function must be called
1818 * before zeroing all objects reachable from scavenged_static_objects
1819 * in the case of major gabage collections. See GarbageCollect() in
1822 * The mut_once_list of the oldest generation must also be traversed?
1823 * Why? Because if the evacuation of an object pointed to by a static
1824 * indirection object fails, it is put back to the mut_once_list of
1825 * the oldest generation.
1826 * However, this is not necessary because any static indirection objects
1827 * are just traversed through to reach dynamic objects. In other words,
1828 * they are not taken into consideration in computing retainer sets.
1829 * -------------------------------------------------------------------------- */
1831 resetStaticObjectForRetainerProfiling( void )
1833 #ifdef DEBUG_RETAINER
1838 #ifdef DEBUG_RETAINER
1841 p = scavenged_static_objects;
1842 while (p != END_OF_STATIC_LIST) {
1843 #ifdef DEBUG_RETAINER
1846 switch (get_itbl(p)->type) {
1848 // Since we do not compute the retainer set of any
1849 // IND_STATIC object, we don't have to reset its retainer
1851 p = (StgClosure*)*IND_STATIC_LINK(p);
1854 maybeInitRetainerSet(p);
1855 p = (StgClosure*)*THUNK_STATIC_LINK(p);
1858 maybeInitRetainerSet(p);
1859 p = (StgClosure*)*FUN_STATIC_LINK(p);
1862 maybeInitRetainerSet(p);
1863 p = (StgClosure*)*STATIC_LINK(get_itbl(p), p);
1866 barf("resetStaticObjectForRetainerProfiling: %p (%s)",
1867 p, get_itbl(p)->type);
1871 #ifdef DEBUG_RETAINER
1872 // debugBelch("count in scavenged_static_objects = %d\n", count);
1876 /* -----------------------------------------------------------------------------
1877 * Perform retainer profiling.
1878 * N is the oldest generation being profilied, where the generations are
1879 * numbered starting at 0.
1882 * This function should be called only immediately after major garbage
1884 * ------------------------------------------------------------------------- */
1886 retainerProfile(void)
1888 #ifdef DEBUG_RETAINER
1890 nat totalHeapSize; // total raw heap size (computed by linear scanning)
1893 #ifdef DEBUG_RETAINER
1894 debugBelch(" < retainerProfile() invoked : %d>\n", retainerGeneration);
1899 // We haven't flipped the bit yet.
1900 #ifdef DEBUG_RETAINER
1901 debugBelch("Before traversing:\n");
1902 sumOfCostLinear = 0;
1903 for (i = 0;i < N_CLOSURE_TYPES; i++)
1904 costArrayLinear[i] = 0;
1905 totalHeapSize = checkHeapSanityForRetainerProfiling();
1907 debugBelch("\tsumOfCostLinear = %d, totalHeapSize = %d\n", sumOfCostLinear, totalHeapSize);
1909 debugBelch("costArrayLinear[] = ");
1910 for (i = 0;i < N_CLOSURE_TYPES; i++)
1911 debugBelch("[%u:%u] ", i, costArrayLinear[i]);
1915 ASSERT(sumOfCostLinear == totalHeapSize);
1918 #define pcostArrayLinear(index) \
1919 if (costArrayLinear[index] > 0) \
1920 debugBelch("costArrayLinear[" #index "] = %u\n", costArrayLinear[index])
1921 pcostArrayLinear(THUNK_STATIC);
1922 pcostArrayLinear(FUN_STATIC);
1923 pcostArrayLinear(CONSTR_STATIC);
1924 pcostArrayLinear(CONSTR_NOCAF_STATIC);
1925 pcostArrayLinear(CONSTR_INTLIKE);
1926 pcostArrayLinear(CONSTR_CHARLIKE);
1930 // Now we flips flip.
1933 #ifdef DEBUG_RETAINER
1939 numObjectVisited = 0;
1940 timesAnyObjectVisited = 0;
1942 #ifdef DEBUG_RETAINER
1943 debugBelch("During traversing:\n");
1945 sumOfNewCostExtra = 0;
1946 for (i = 0;i < N_CLOSURE_TYPES; i++)
1951 We initialize the traverse stack each time the retainer profiling is
1952 performed (because the traverse stack size varies on each retainer profiling
1953 and this operation is not costly anyhow). However, we just refresh the
1956 initializeTraverseStack();
1957 #ifdef DEBUG_RETAINER
1958 initializeAllRetainerSet();
1960 refreshAllRetainerSet();
1962 computeRetainerSet();
1964 #ifdef DEBUG_RETAINER
1965 debugBelch("After traversing:\n");
1966 sumOfCostLinear = 0;
1967 for (i = 0;i < N_CLOSURE_TYPES; i++)
1968 costArrayLinear[i] = 0;
1969 totalHeapSize = checkHeapSanityForRetainerProfiling();
1971 debugBelch("\tsumOfCostLinear = %d, totalHeapSize = %d\n", sumOfCostLinear, totalHeapSize);
1972 ASSERT(sumOfCostLinear == totalHeapSize);
1974 // now, compare the two results
1977 costArray[] must be exactly the same as costArrayLinear[].
1979 1) Dead weak pointers, whose type is CONSTR. These objects are not
1980 reachable from any roots.
1982 debugBelch("Comparison:\n");
1983 debugBelch("\tcostArrayLinear[] (must be empty) = ");
1984 for (i = 0;i < N_CLOSURE_TYPES; i++)
1985 if (costArray[i] != costArrayLinear[i])
1986 // nothing should be printed except MUT_VAR after major GCs
1987 debugBelch("[%u:%u] ", i, costArrayLinear[i]);
1990 debugBelch("\tsumOfNewCost = %u\n", sumOfNewCost);
1991 debugBelch("\tsumOfNewCostExtra = %u\n", sumOfNewCostExtra);
1992 debugBelch("\tcostArray[] (must be empty) = ");
1993 for (i = 0;i < N_CLOSURE_TYPES; i++)
1994 if (costArray[i] != costArrayLinear[i])
1995 // nothing should be printed except MUT_VAR after major GCs
1996 debugBelch("[%u:%u] ", i, costArray[i]);
1999 // only for major garbage collection
2000 ASSERT(sumOfNewCost + sumOfNewCostExtra == sumOfCostLinear);
2004 closeTraverseStack();
2005 #ifdef DEBUG_RETAINER
2006 closeAllRetainerSet();
2008 // Note that there is no post-processing for the retainer sets.
2010 retainerGeneration++;
2013 retainerGeneration - 1, // retainerGeneration has just been incremented!
2014 #ifdef DEBUG_RETAINER
2015 maxCStackSize, maxStackSize,
2017 (double)timesAnyObjectVisited / numObjectVisited);
2020 /* -----------------------------------------------------------------------------
2022 * -------------------------------------------------------------------------- */
2024 #ifdef DEBUG_RETAINER
2026 #define LOOKS_LIKE_PTR(r) ((LOOKS_LIKE_STATIC_CLOSURE(r) || \
2027 ((HEAP_ALLOCED(r) && ((Bdescr((P_)r)->flags & BF_FREE) == 0)))) && \
2028 ((StgWord)(*(StgPtr)r)!=0xaaaaaaaa))
2031 sanityCheckHeapClosure( StgClosure *c )
2035 ASSERT(LOOKS_LIKE_GHC_INFO(c->header.info));
2036 ASSERT(!closure_STATIC(c));
2037 ASSERT(LOOKS_LIKE_PTR(c));
2039 if ((((StgWord)RSET(c) & 1) ^ flip) != 0) {
2040 if (get_itbl(c)->type == CONSTR &&
2041 !strcmp(get_itbl(c)->prof.closure_type, "DEAD_WEAK") &&
2042 !strcmp(get_itbl(c)->prof.closure_desc, "DEAD_WEAK")) {
2043 debugBelch("\tUnvisited dead weak pointer object found: c = %p\n", c);
2044 costArray[get_itbl(c)->type] += cost(c);
2045 sumOfNewCost += cost(c);
2048 "Unvisited object: flip = %d, c = %p(%d, %s, %s), rs = %p\n",
2049 flip, c, get_itbl(c)->type,
2050 get_itbl(c)->prof.closure_type, get_itbl(c)->prof.closure_desc,
2053 // debugBelch("sanityCheckHeapClosure) S: flip = %d, c = %p(%d), rs = %p\n", flip, c, get_itbl(c)->type, RSET(c));
2057 switch (info->type) {
2059 return tso_sizeW((StgTSO *)c);
2067 return stg_max(sizeW_fromITBL(info), sizeofW(StgHeader) + MIN_UPD_SIZE);
2070 return sizeofW(StgMVar);
2073 case MUT_ARR_PTRS_FROZEN:
2074 return mut_arr_ptrs_sizeW((StgMutArrPtrs *)c);
2078 return pap_sizeW((StgPAP *)c);
2081 return ap_stack_sizeW((StgAP_STACK *)c);
2084 return arr_words_sizeW((StgArrWords *)c);
2103 case SE_CAF_BLACKHOLE:
2106 case IND_OLDGEN_PERM:
2109 return sizeW_fromITBL(info);
2111 case THUNK_SELECTOR:
2112 return sizeofW(StgHeader) + MIN_UPD_SIZE;
2121 case CONSTR_INTLIKE:
2122 case CONSTR_CHARLIKE:
2123 case CONSTR_NOCAF_STATIC:
2140 case INVALID_OBJECT:
2142 barf("Invalid object in sanityCheckHeapClosure(): %d",
2149 heapCheck( bdescr *bd )
2152 static nat costSum, size;
2155 while (bd != NULL) {
2157 while (p < bd->free) {
2158 size = sanityCheckHeapClosure((StgClosure *)p);
2159 sumOfCostLinear += size;
2160 costArrayLinear[get_itbl((StgClosure *)p)->type] += size;
2162 // no need for slop check; I think slops are not used currently.
2164 ASSERT(p == bd->free);
2165 costSum += bd->free - bd->start;
2173 smallObjectPoolCheck(void)
2177 static nat costSum, size;
2179 bd = small_alloc_list;
2187 while (p < alloc_Hp) {
2188 size = sanityCheckHeapClosure((StgClosure *)p);
2189 sumOfCostLinear += size;
2190 costArrayLinear[get_itbl((StgClosure *)p)->type] += size;
2193 ASSERT(p == alloc_Hp);
2194 costSum += alloc_Hp - bd->start;
2197 while (bd != NULL) {
2199 while (p < bd->free) {
2200 size = sanityCheckHeapClosure((StgClosure *)p);
2201 sumOfCostLinear += size;
2202 costArrayLinear[get_itbl((StgClosure *)p)->type] += size;
2205 ASSERT(p == bd->free);
2206 costSum += bd->free - bd->start;
2214 chainCheck(bdescr *bd)
2219 while (bd != NULL) {
2220 // bd->free - bd->start is not an accurate measurement of the
2221 // object size. Actually it is always zero, so we compute its
2223 size = sanityCheckHeapClosure((StgClosure *)bd->start);
2224 sumOfCostLinear += size;
2225 costArrayLinear[get_itbl((StgClosure *)bd->start)->type] += size;
2234 checkHeapSanityForRetainerProfiling( void )
2239 debugBelch("START: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2240 if (RtsFlags.GcFlags.generations == 1) {
2241 costSum += heapCheck(g0s0->to_blocks);
2242 debugBelch("heapCheck: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2243 costSum += chainCheck(g0s0->large_objects);
2244 debugBelch("chainCheck: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2246 for (g = 0; g < RtsFlags.GcFlags.generations; g++)
2247 for (s = 0; s < generations[g].n_steps; s++) {
2249 After all live objects have been scavenged, the garbage
2250 collector may create some objects in
2251 scheduleFinalizers(). These objects are created throught
2252 allocate(), so the small object pool or the large object
2253 pool of the g0s0 may not be empty.
2255 if (g == 0 && s == 0) {
2256 costSum += smallObjectPoolCheck();
2257 debugBelch("smallObjectPoolCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2258 costSum += chainCheck(generations[g].steps[s].large_objects);
2259 debugBelch("chainCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2261 costSum += heapCheck(generations[g].steps[s].blocks);
2262 debugBelch("heapCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2263 costSum += chainCheck(generations[g].steps[s].large_objects);
2264 debugBelch("chainCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum);
2273 findPointer(StgPtr p)
2279 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
2280 for (s = 0; s < generations[g].n_steps; s++) {
2281 // if (g == 0 && s == 0) continue;
2282 bd = generations[g].steps[s].blocks;
2283 for (; bd; bd = bd->link) {
2284 for (q = bd->start; q < bd->free; q++) {
2285 if (*q == (StgWord)p) {
2287 while (!LOOKS_LIKE_GHC_INFO(*r)) r--;
2288 debugBelch("Found in gen[%d], step[%d]: q = %p, r = %p\n", g, s, q, r);
2293 bd = generations[g].steps[s].large_objects;
2294 for (; bd; bd = bd->link) {
2295 e = bd->start + cost((StgClosure *)bd->start);
2296 for (q = bd->start; q < e; q++) {
2297 if (*q == (StgWord)p) {
2299 while (*r == 0 || !LOOKS_LIKE_GHC_INFO(*r)) r--;
2300 debugBelch("Found in gen[%d], large_objects: %p\n", g, r);
2310 belongToHeap(StgPtr p)
2315 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
2316 for (s = 0; s < generations[g].n_steps; s++) {
2317 // if (g == 0 && s == 0) continue;
2318 bd = generations[g].steps[s].blocks;
2319 for (; bd; bd = bd->link) {
2320 if (bd->start <= p && p < bd->free) {
2321 debugBelch("Belongs to gen[%d], step[%d]", g, s);
2325 bd = generations[g].steps[s].large_objects;
2326 for (; bd; bd = bd->link) {
2327 if (bd->start <= p && p < bd->start + getHeapClosureSize((StgClosure *)bd->start)) {
2328 debugBelch("Found in gen[%d], large_objects: %p\n", g, bd->start);
2335 #endif /* DEBUG_RETAINER */
2337 #endif /* PROFILING */