diff options
author | Austin Seipp <austin@well-typed.com> | 2014-10-21 16:44:19 -0500 |
---|---|---|
committer | Austin Seipp <austin@well-typed.com> | 2014-10-21 16:44:19 -0500 |
commit | 5106e201241aa8f07ba97decab301a01e363bdc2 (patch) | |
tree | fabc4410b5592fac2d1dd6bef719b9a6ba76f039 /rts/RetainerProfile.c | |
parent | c8173d5105a8463890e536d621c35805d6f67e4b (diff) | |
download | haskell-5106e201241aa8f07ba97decab301a01e363bdc2.tar.gz |
[skip ci] rts: Detabify RetainerProfile.c
Signed-off-by: Austin Seipp <austin@well-typed.com>
Diffstat (limited to 'rts/RetainerProfile.c')
-rw-r--r-- | rts/RetainerProfile.c | 1626 |
1 files changed, 813 insertions, 813 deletions
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c index bfc96247aa..f3e8c72eb8 100644 --- a/rts/RetainerProfile.c +++ b/rts/RetainerProfile.c @@ -46,9 +46,9 @@ * Declarations... * -------------------------------------------------------------------------- */ -static nat retainerGeneration; // generation +static nat retainerGeneration; // generation -static nat numObjectVisited; // total number of objects visited +static nat numObjectVisited; // total number of objects visited static nat timesAnyObjectVisited; // number of times any objects are visited /* @@ -81,15 +81,15 @@ static void belongToHeap(StgPtr p); */ static nat cStackSize, maxCStackSize; -static nat sumOfNewCost; // sum of the cost of each object, computed - // when the object is first visited +static nat sumOfNewCost; // sum of the cost of each object, computed + // when the object is first visited static nat sumOfNewCostExtra; // for those objects not visited during // retainer profiling, e.g., MUT_VAR static nat costArray[N_CLOSURE_TYPES]; -nat sumOfCostLinear; // sum of the costs of all object, computed - // when linearly traversing the heap after - // retainer profiling +nat sumOfCostLinear; // sum of the costs of all object, computed + // when linearly traversing the heap after + // retainer profiling nat costArrayLinear[N_CLOSURE_TYPES]; #endif @@ -118,27 +118,27 @@ typedef union { struct { // See StgClosureInfo in InfoTables.h #if SIZEOF_VOID_P == 8 - StgWord32 pos; - StgWord32 ptrs; + StgWord32 pos; + StgWord32 ptrs; #else - StgWord16 pos; - StgWord16 ptrs; + StgWord16 pos; + StgWord16 ptrs; #endif - StgPtr payload; + StgPtr payload; } ptrs; // SRT struct { - StgClosure **srt; - StgWord srt_bitmap; + StgClosure **srt; + StgWord srt_bitmap; } srt; // Large SRT struct { - StgLargeSRT *srt; - StgWord offset; + StgLargeSRT *srt; + StgWord offset; } large_srt; - + } nextPos; typedef struct { @@ -237,7 +237,7 @@ static void initializeTraverseStack( void ) { if (firstStack != NULL) { - freeChain(firstStack); + freeChain(firstStack); } firstStack = allocGroup(BLOCKS_IN_STACK); @@ -278,7 +278,7 @@ retainerStackBlocks( void ) bdescr* bd; W_ res = 0; - for (bd = firstStack; bd != NULL; bd = bd->link) + for (bd = firstStack; bd != NULL; bd = bd->link) res += bd->blocks; return res; @@ -316,9 +316,9 @@ static INLINE StgClosure * find_ptrs( stackPos *info ) { if (info->next.ptrs.pos < info->next.ptrs.ptrs) { - return (StgClosure *)info->next.ptrs.payload[info->next.ptrs.pos++]; + return (StgClosure *)info->next.ptrs.payload[info->next.ptrs.pos++]; } else { - return NULL; + return NULL; } } @@ -329,13 +329,13 @@ static INLINE void init_srt_fun( stackPos *info, StgFunInfoTable *infoTable ) { if (infoTable->i.srt_bitmap == (StgHalfWord)(-1)) { - info->type = posTypeLargeSRT; - info->next.large_srt.srt = (StgLargeSRT *)GET_FUN_SRT(infoTable); - info->next.large_srt.offset = 0; + info->type = posTypeLargeSRT; + info->next.large_srt.srt = (StgLargeSRT *)GET_FUN_SRT(infoTable); + info->next.large_srt.offset = 0; } else { - info->type = posTypeSRT; - info->next.srt.srt = (StgClosure **)GET_FUN_SRT(infoTable); - info->next.srt.srt_bitmap = infoTable->i.srt_bitmap; + info->type = posTypeSRT; + info->next.srt.srt = (StgClosure **)GET_FUN_SRT(infoTable); + info->next.srt.srt_bitmap = infoTable->i.srt_bitmap; } } @@ -343,13 +343,13 @@ static INLINE void init_srt_thunk( stackPos *info, StgThunkInfoTable *infoTable ) { if (infoTable->i.srt_bitmap == (StgHalfWord)(-1)) { - info->type = posTypeLargeSRT; - info->next.large_srt.srt = (StgLargeSRT *)GET_SRT(infoTable); - info->next.large_srt.offset = 0; + info->type = posTypeLargeSRT; + info->next.large_srt.srt = (StgLargeSRT *)GET_SRT(infoTable); + info->next.large_srt.offset = 0; } else { - info->type = posTypeSRT; - info->next.srt.srt = (StgClosure **)GET_SRT(infoTable); - info->next.srt.srt_bitmap = infoTable->i.srt_bitmap; + info->type = posTypeSRT; + info->next.srt.srt = (StgClosure **)GET_SRT(infoTable); + info->next.srt.srt_bitmap = infoTable->i.srt_bitmap; } } @@ -363,54 +363,54 @@ find_srt( stackPos *info ) StgWord bitmap; if (info->type == posTypeSRT) { - // Small SRT bitmap - bitmap = info->next.srt.srt_bitmap; - while (bitmap != 0) { - if ((bitmap & 1) != 0) { + // Small SRT bitmap + bitmap = info->next.srt.srt_bitmap; + while (bitmap != 0) { + if ((bitmap & 1) != 0) { #if defined(COMPILING_WINDOWS_DLL) - if ((unsigned long)(*(info->next.srt.srt)) & 0x1) - c = (* (StgClosure **)((unsigned long)*(info->next.srt.srt)) & ~0x1); - else - c = *(info->next.srt.srt); + if ((unsigned long)(*(info->next.srt.srt)) & 0x1) + c = (* (StgClosure **)((unsigned long)*(info->next.srt.srt)) & ~0x1); + else + c = *(info->next.srt.srt); #else - c = *(info->next.srt.srt); + c = *(info->next.srt.srt); #endif - bitmap = bitmap >> 1; - info->next.srt.srt++; - info->next.srt.srt_bitmap = bitmap; - return c; - } - bitmap = bitmap >> 1; - info->next.srt.srt++; - } - // bitmap is now zero... - return NULL; + bitmap = bitmap >> 1; + info->next.srt.srt++; + info->next.srt.srt_bitmap = bitmap; + return c; + } + bitmap = bitmap >> 1; + info->next.srt.srt++; + } + // bitmap is now zero... + return NULL; } else { - // Large SRT bitmap - nat i = info->next.large_srt.offset; - StgWord bitmap; - - // Follow the pattern from GC.c:scavenge_large_srt_bitmap(). - bitmap = info->next.large_srt.srt->l.bitmap[i / BITS_IN(W_)]; - bitmap = bitmap >> (i % BITS_IN(StgWord)); - while (i < info->next.large_srt.srt->l.size) { - if ((bitmap & 1) != 0) { - c = ((StgClosure **)info->next.large_srt.srt->srt)[i]; - i++; - info->next.large_srt.offset = i; - return c; - } - i++; - if (i % BITS_IN(W_) == 0) { - bitmap = info->next.large_srt.srt->l.bitmap[i / BITS_IN(W_)]; - } else { - bitmap = bitmap >> 1; - } - } - // reached the end of this bitmap. - info->next.large_srt.offset = i; - return NULL; + // Large SRT bitmap + nat i = info->next.large_srt.offset; + StgWord bitmap; + + // Follow the pattern from GC.c:scavenge_large_srt_bitmap(). + bitmap = info->next.large_srt.srt->l.bitmap[i / BITS_IN(W_)]; + bitmap = bitmap >> (i % BITS_IN(StgWord)); + while (i < info->next.large_srt.srt->l.size) { + if ((bitmap & 1) != 0) { + c = ((StgClosure **)info->next.large_srt.srt->srt)[i]; + i++; + info->next.large_srt.offset = i; + return c; + } + i++; + if (i % BITS_IN(W_) == 0) { + bitmap = info->next.large_srt.srt->l.bitmap[i / BITS_IN(W_)]; + } else { + bitmap = bitmap >> 1; + } + } + // reached the end of this bitmap. + info->next.large_srt.offset = i; + return NULL; } } @@ -451,162 +451,162 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) // fill in se.info switch (get_itbl(c)->type) { - // no child, no SRT + // no child, no SRT case CONSTR_0_1: case CONSTR_0_2: case ARR_WORDS: - *first_child = NULL; - return; + *first_child = NULL; + return; - // one child (fixed), no SRT + // one child (fixed), no SRT case MUT_VAR_CLEAN: case MUT_VAR_DIRTY: - *first_child = ((StgMutVar *)c)->var; - return; + *first_child = ((StgMutVar *)c)->var; + return; case THUNK_SELECTOR: - *first_child = ((StgSelector *)c)->selectee; - return; + *first_child = ((StgSelector *)c)->selectee; + return; case IND_PERM: case BLACKHOLE: - *first_child = ((StgInd *)c)->indirectee; - return; + *first_child = ((StgInd *)c)->indirectee; + return; case CONSTR_1_0: case CONSTR_1_1: - *first_child = c->payload[0]; - return; + *first_child = c->payload[0]; + return; - // For CONSTR_2_0 and MVAR, we use se.info.step to record the position - // of the next child. We do not write a separate initialization code. - // Also we do not have to initialize info.type; + // For CONSTR_2_0 and MVAR, we use se.info.step to record the position + // of the next child. We do not write a separate initialization code. + // Also we do not have to initialize info.type; - // two children (fixed), no SRT - // need to push a stackElement, but nothing to store in se.info + // two children (fixed), no SRT + // need to push a stackElement, but nothing to store in se.info case CONSTR_2_0: - *first_child = c->payload[0]; // return the first pointer - // se.info.type = posTypeStep; - // se.info.next.step = 2; // 2 = second - break; + *first_child = c->payload[0]; // return the first pointer + // se.info.type = posTypeStep; + // se.info.next.step = 2; // 2 = second + break; - // three children (fixed), no SRT - // need to push a stackElement + // three children (fixed), no SRT + // need to push a stackElement case MVAR_CLEAN: case MVAR_DIRTY: - // head must be TSO and the head of a linked list of TSOs. - // Shoule it be a child? Seems to be yes. - *first_child = (StgClosure *)((StgMVar *)c)->head; - // se.info.type = posTypeStep; - se.info.next.step = 2; // 2 = second - break; - - // three children (fixed), no SRT + // head must be TSO and the head of a linked list of TSOs. + // Shoule it be a child? Seems to be yes. + *first_child = (StgClosure *)((StgMVar *)c)->head; + // se.info.type = posTypeStep; + se.info.next.step = 2; // 2 = second + break; + + // three children (fixed), no SRT case WEAK: - *first_child = ((StgWeak *)c)->key; - // se.info.type = posTypeStep; - se.info.next.step = 2; - break; + *first_child = ((StgWeak *)c)->key; + // se.info.type = posTypeStep; + se.info.next.step = 2; + break; - // layout.payload.ptrs, no SRT + // layout.payload.ptrs, no SRT case TVAR: case CONSTR: case PRIM: case MUT_PRIM: case BCO: case CONSTR_STATIC: - init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, - (StgPtr)c->payload); - *first_child = find_ptrs(&se.info); - if (*first_child == NULL) - return; // no child - break; - - // StgMutArrPtr.ptrs, no SRT + init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, + (StgPtr)c->payload); + *first_child = find_ptrs(&se.info); + if (*first_child == NULL) + return; // no child + break; + + // StgMutArrPtr.ptrs, no SRT case MUT_ARR_PTRS_CLEAN: case MUT_ARR_PTRS_DIRTY: case MUT_ARR_PTRS_FROZEN: case MUT_ARR_PTRS_FROZEN0: - init_ptrs(&se.info, ((StgMutArrPtrs *)c)->ptrs, - (StgPtr)(((StgMutArrPtrs *)c)->payload)); - *first_child = find_ptrs(&se.info); - if (*first_child == NULL) - return; - break; - - // StgMutArrPtr.ptrs, no SRT + init_ptrs(&se.info, ((StgMutArrPtrs *)c)->ptrs, + (StgPtr)(((StgMutArrPtrs *)c)->payload)); + *first_child = find_ptrs(&se.info); + if (*first_child == NULL) + return; + break; + + // StgMutArrPtr.ptrs, no SRT case SMALL_MUT_ARR_PTRS_CLEAN: case SMALL_MUT_ARR_PTRS_DIRTY: case SMALL_MUT_ARR_PTRS_FROZEN: case SMALL_MUT_ARR_PTRS_FROZEN0: - init_ptrs(&se.info, ((StgSmallMutArrPtrs *)c)->ptrs, - (StgPtr)(((StgSmallMutArrPtrs *)c)->payload)); - *first_child = find_ptrs(&se.info); - if (*first_child == NULL) - return; - break; + init_ptrs(&se.info, ((StgSmallMutArrPtrs *)c)->ptrs, + (StgPtr)(((StgSmallMutArrPtrs *)c)->payload)); + *first_child = find_ptrs(&se.info); + if (*first_child == NULL) + return; + break; // layout.payload.ptrs, SRT case FUN: // *c is a heap object. case FUN_2_0: - init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, (StgPtr)c->payload); - *first_child = find_ptrs(&se.info); - if (*first_child == NULL) - // no child from ptrs, so check SRT - goto fun_srt_only; - break; + init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, (StgPtr)c->payload); + *first_child = find_ptrs(&se.info); + if (*first_child == NULL) + // no child from ptrs, so check SRT + goto fun_srt_only; + break; case THUNK: case THUNK_2_0: - init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, - (StgPtr)((StgThunk *)c)->payload); - *first_child = find_ptrs(&se.info); - if (*first_child == NULL) - // no child from ptrs, so check SRT - goto thunk_srt_only; - break; - - // 1 fixed child, SRT + init_ptrs(&se.info, get_itbl(c)->layout.payload.ptrs, + (StgPtr)((StgThunk *)c)->payload); + *first_child = find_ptrs(&se.info); + if (*first_child == NULL) + // no child from ptrs, so check SRT + goto thunk_srt_only; + break; + + // 1 fixed child, SRT case FUN_1_0: case FUN_1_1: - *first_child = c->payload[0]; - ASSERT(*first_child != NULL); - init_srt_fun(&se.info, get_fun_itbl(c)); - break; + *first_child = c->payload[0]; + ASSERT(*first_child != NULL); + init_srt_fun(&se.info, get_fun_itbl(c)); + break; case THUNK_1_0: case THUNK_1_1: - *first_child = ((StgThunk *)c)->payload[0]; - ASSERT(*first_child != NULL); - init_srt_thunk(&se.info, get_thunk_itbl(c)); - break; + *first_child = ((StgThunk *)c)->payload[0]; + ASSERT(*first_child != NULL); + init_srt_thunk(&se.info, get_thunk_itbl(c)); + break; case FUN_STATIC: // *c is a heap object. - ASSERT(get_itbl(c)->srt_bitmap != 0); + ASSERT(get_itbl(c)->srt_bitmap != 0); case FUN_0_1: case FUN_0_2: fun_srt_only: init_srt_fun(&se.info, get_fun_itbl(c)); - *first_child = find_srt(&se.info); - if (*first_child == NULL) - return; // no child - break; + *first_child = find_srt(&se.info); + if (*first_child == NULL) + return; // no child + break; // SRT only case THUNK_STATIC: - ASSERT(get_itbl(c)->srt_bitmap != 0); + ASSERT(get_itbl(c)->srt_bitmap != 0); case THUNK_0_1: case THUNK_0_2: thunk_srt_only: init_srt_thunk(&se.info, get_thunk_itbl(c)); - *first_child = find_srt(&se.info); - if (*first_child == NULL) - return; // no child - break; - + *first_child = find_srt(&se.info); + if (*first_child == NULL) + return; // no child + break; + case TREC_CHUNK: - *first_child = (StgClosure *)((StgTRecChunk *)c)->prev_chunk; - se.info.next.step = 0; // entry no. - break; + *first_child = (StgClosure *)((StgTRecChunk *)c)->prev_chunk; + se.info.next.step = 0; // entry no. + break; - // cannot appear + // cannot appear case PAP: case AP: case AP_STACK: @@ -614,7 +614,7 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) case STACK: case IND_STATIC: case CONSTR_NOCAF_STATIC: - // stack objects + // stack objects case UPDATE_FRAME: case CATCH_FRAME: case UNDERFLOW_FRAME: @@ -622,31 +622,31 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) case RET_BCO: case RET_SMALL: case RET_BIG: - // invalid objects + // invalid objects case IND: case INVALID_OBJECT: default: - barf("Invalid object *c in push()"); - return; + barf("Invalid object *c in push()"); + return; } if (stackTop - 1 < stackBottom) { #ifdef DEBUG_RETAINER - // debugBelch("push() to the next stack.\n"); + // debugBelch("push() to the next stack.\n"); #endif - // currentStack->free is updated when the active stack is switched - // to the next stack. - currentStack->free = (StgPtr)stackTop; - - if (currentStack->link == NULL) { - nbd = allocGroup(BLOCKS_IN_STACK); - nbd->link = NULL; - nbd->u.back = currentStack; - currentStack->link = nbd; - } else - nbd = currentStack->link; - - newStackBlock(nbd); + // currentStack->free is updated when the active stack is switched + // to the next stack. + currentStack->free = (StgPtr)stackTop; + + if (currentStack->link == NULL) { + nbd = allocGroup(BLOCKS_IN_STACK); + nbd->link = NULL; + nbd->u.back = currentStack; + currentStack->link = nbd; + } else + nbd = currentStack->link; + + newStackBlock(nbd); } // adjust stackTop (acutal push) @@ -697,18 +697,18 @@ popOffReal(void) ASSERT(stackBottom == (stackElement *)currentStack->start); if (firstStack == currentStack) { - // The stack is completely empty. - stackTop++; - ASSERT(stackTop == stackLimit); + // The stack is completely empty. + stackTop++; + ASSERT(stackTop == stackLimit); #ifdef DEBUG_RETAINER - stackSize--; - if (stackSize > maxStackSize) maxStackSize = stackSize; - /* - ASSERT(stackSize >= 0); - debugBelch("stackSize = %d\n", stackSize); - */ + stackSize--; + if (stackSize > maxStackSize) maxStackSize = stackSize; + /* + ASSERT(stackSize >= 0); + debugBelch("stackSize = %d\n", stackSize); + */ #endif - return; + return; } // currentStack->free is updated when the active stack is switched back @@ -742,16 +742,16 @@ popOff(void) { // <= (instead of <) is wrong! if (stackTop + 1 < stackLimit) { - stackTop++; + stackTop++; #ifdef DEBUG_RETAINER - stackSize--; - if (stackSize > maxStackSize) maxStackSize = stackSize; - /* - ASSERT(stackSize >= 0); - debugBelch("stackSize = %d\n", stackSize); - */ + stackSize--; + if (stackSize > maxStackSize) maxStackSize = stackSize; + /* + ASSERT(stackSize >= 0); + debugBelch("stackSize = %d\n", stackSize); + */ #endif - return; + return; } popOffReal(); @@ -783,182 +783,182 @@ pop( StgClosure **c, StgClosure **cp, retainer *r ) #endif do { - if (isOnBoundary()) { // if the current stack chunk is depleted - *c = NULL; - return; - } - - se = stackTop; - - switch (get_itbl(se->c)->type) { - // two children (fixed), no SRT - // nothing in se.info - case CONSTR_2_0: - *c = se->c->payload[1]; - *cp = se->c; - *r = se->c_child_r; - popOff(); - return; - - // three children (fixed), no SRT - // need to push a stackElement + if (isOnBoundary()) { // if the current stack chunk is depleted + *c = NULL; + return; + } + + se = stackTop; + + switch (get_itbl(se->c)->type) { + // two children (fixed), no SRT + // nothing in se.info + case CONSTR_2_0: + *c = se->c->payload[1]; + *cp = se->c; + *r = se->c_child_r; + popOff(); + return; + + // three children (fixed), no SRT + // need to push a stackElement case MVAR_CLEAN: case MVAR_DIRTY: - if (se->info.next.step == 2) { - *c = (StgClosure *)((StgMVar *)se->c)->tail; - se->info.next.step++; // move to the next step - // no popOff - } else { - *c = ((StgMVar *)se->c)->value; - popOff(); - } - *cp = se->c; - *r = se->c_child_r; - return; - - // three children (fixed), no SRT - case WEAK: - if (se->info.next.step == 2) { - *c = ((StgWeak *)se->c)->value; - se->info.next.step++; - // no popOff - } else { - *c = ((StgWeak *)se->c)->finalizer; - popOff(); - } - *cp = se->c; - *r = se->c_child_r; - return; - - case TREC_CHUNK: { - // These are pretty complicated: we have N entries, each - // of which contains 3 fields that we want to follow. So - // we divide the step counter: the 2 low bits indicate - // which field, and the rest of the bits indicate the - // entry number (starting from zero). - TRecEntry *entry; - nat entry_no = se->info.next.step >> 2; - nat field_no = se->info.next.step & 3; - if (entry_no == ((StgTRecChunk *)se->c)->next_entry_idx) { - *c = NULL; - popOff(); - return; - } - entry = &((StgTRecChunk *)se->c)->entries[entry_no]; - if (field_no == 0) { - *c = (StgClosure *)entry->tvar; - } else if (field_no == 1) { - *c = entry->expected_value; - } else { - *c = entry->new_value; - } - *cp = se->c; - *r = se->c_child_r; - se->info.next.step++; - return; - } + if (se->info.next.step == 2) { + *c = (StgClosure *)((StgMVar *)se->c)->tail; + se->info.next.step++; // move to the next step + // no popOff + } else { + *c = ((StgMVar *)se->c)->value; + popOff(); + } + *cp = se->c; + *r = se->c_child_r; + return; + + // three children (fixed), no SRT + case WEAK: + if (se->info.next.step == 2) { + *c = ((StgWeak *)se->c)->value; + se->info.next.step++; + // no popOff + } else { + *c = ((StgWeak *)se->c)->finalizer; + popOff(); + } + *cp = se->c; + *r = se->c_child_r; + return; + + case TREC_CHUNK: { + // These are pretty complicated: we have N entries, each + // of which contains 3 fields that we want to follow. So + // we divide the step counter: the 2 low bits indicate + // which field, and the rest of the bits indicate the + // entry number (starting from zero). + TRecEntry *entry; + nat entry_no = se->info.next.step >> 2; + nat field_no = se->info.next.step & 3; + if (entry_no == ((StgTRecChunk *)se->c)->next_entry_idx) { + *c = NULL; + popOff(); + return; + } + entry = &((StgTRecChunk *)se->c)->entries[entry_no]; + if (field_no == 0) { + *c = (StgClosure *)entry->tvar; + } else if (field_no == 1) { + *c = entry->expected_value; + } else { + *c = entry->new_value; + } + *cp = se->c; + *r = se->c_child_r; + se->info.next.step++; + return; + } case TVAR: case CONSTR: - case PRIM: - case MUT_PRIM: - case BCO: - case CONSTR_STATIC: - // StgMutArrPtr.ptrs, no SRT - case MUT_ARR_PTRS_CLEAN: - case MUT_ARR_PTRS_DIRTY: - case MUT_ARR_PTRS_FROZEN: - case MUT_ARR_PTRS_FROZEN0: - *c = find_ptrs(&se->info); - if (*c == NULL) { - popOff(); - break; - } - *cp = se->c; - *r = se->c_child_r; - return; - - // layout.payload.ptrs, SRT - case FUN: // always a heap object - case FUN_2_0: - if (se->info.type == posTypePtrs) { - *c = find_ptrs(&se->info); - if (*c != NULL) { - *cp = se->c; - *r = se->c_child_r; - return; - } - init_srt_fun(&se->info, get_fun_itbl(se->c)); - } - goto do_srt; - - case THUNK: - case THUNK_2_0: - if (se->info.type == posTypePtrs) { - *c = find_ptrs(&se->info); - if (*c != NULL) { - *cp = se->c; - *r = se->c_child_r; - return; - } - init_srt_thunk(&se->info, get_thunk_itbl(se->c)); - } - goto do_srt; - - // SRT - do_srt: - case THUNK_STATIC: - case FUN_STATIC: - case FUN_0_1: - case FUN_0_2: - case THUNK_0_1: - case THUNK_0_2: - case FUN_1_0: - case FUN_1_1: - case THUNK_1_0: - case THUNK_1_1: - *c = find_srt(&se->info); - if (*c != NULL) { - *cp = se->c; - *r = se->c_child_r; - return; - } - popOff(); - break; - - // no child (fixed), no SRT - case CONSTR_0_1: - case CONSTR_0_2: - case ARR_WORDS: - // one child (fixed), no SRT - case MUT_VAR_CLEAN: - case MUT_VAR_DIRTY: - case THUNK_SELECTOR: - case IND_PERM: - case CONSTR_1_1: - // cannot appear - case PAP: - case AP: - case AP_STACK: - case TSO: + case PRIM: + case MUT_PRIM: + case BCO: + case CONSTR_STATIC: + // StgMutArrPtr.ptrs, no SRT + case MUT_ARR_PTRS_CLEAN: + case MUT_ARR_PTRS_DIRTY: + case MUT_ARR_PTRS_FROZEN: + case MUT_ARR_PTRS_FROZEN0: + *c = find_ptrs(&se->info); + if (*c == NULL) { + popOff(); + break; + } + *cp = se->c; + *r = se->c_child_r; + return; + + // layout.payload.ptrs, SRT + case FUN: // always a heap object + case FUN_2_0: + if (se->info.type == posTypePtrs) { + *c = find_ptrs(&se->info); + if (*c != NULL) { + *cp = se->c; + *r = se->c_child_r; + return; + } + init_srt_fun(&se->info, get_fun_itbl(se->c)); + } + goto do_srt; + + case THUNK: + case THUNK_2_0: + if (se->info.type == posTypePtrs) { + *c = find_ptrs(&se->info); + if (*c != NULL) { + *cp = se->c; + *r = se->c_child_r; + return; + } + init_srt_thunk(&se->info, get_thunk_itbl(se->c)); + } + goto do_srt; + + // SRT + do_srt: + case THUNK_STATIC: + case FUN_STATIC: + case FUN_0_1: + case FUN_0_2: + case THUNK_0_1: + case THUNK_0_2: + case FUN_1_0: + case FUN_1_1: + case THUNK_1_0: + case THUNK_1_1: + *c = find_srt(&se->info); + if (*c != NULL) { + *cp = se->c; + *r = se->c_child_r; + return; + } + popOff(); + break; + + // no child (fixed), no SRT + case CONSTR_0_1: + case CONSTR_0_2: + case ARR_WORDS: + // one child (fixed), no SRT + case MUT_VAR_CLEAN: + case MUT_VAR_DIRTY: + case THUNK_SELECTOR: + case IND_PERM: + case CONSTR_1_1: + // cannot appear + case PAP: + case AP: + case AP_STACK: + case TSO: case STACK: case IND_STATIC: - case CONSTR_NOCAF_STATIC: - // stack objects + case CONSTR_NOCAF_STATIC: + // stack objects case UPDATE_FRAME: - case CATCH_FRAME: + case CATCH_FRAME: case UNDERFLOW_FRAME: case STOP_FRAME: - case RET_BCO: - case RET_SMALL: - case RET_BIG: - // invalid objects - case IND: - case INVALID_OBJECT: - default: - barf("Invalid object *c in pop()"); - return; - } + case RET_BCO: + case RET_SMALL: + case RET_BIG: + // invalid objects + case IND: + case INVALID_OBJECT: + default: + barf("Invalid object *c in pop()"); + return; + } } while (rtsTrue); } @@ -1002,7 +1002,7 @@ static INLINE void maybeInitRetainerSet( StgClosure *c ) { if (!isRetainerSetFieldValid(c)) { - setRetainerSetToNull(c); + setRetainerSetToNull(c); } } @@ -1013,14 +1013,14 @@ static INLINE rtsBool isRetainer( StgClosure *c ) { switch (get_itbl(c)->type) { - // - // True case - // - // TSOs MUST be retainers: they constitute the set of roots. + // + // True case + // + // TSOs MUST be retainers: they constitute the set of roots. case TSO: case STACK: - // mutable objects + // mutable objects case MUT_PRIM: case MVAR_CLEAN: case MVAR_DIRTY: @@ -1030,7 +1030,7 @@ isRetainer( StgClosure *c ) case MUT_ARR_PTRS_CLEAN: case MUT_ARR_PTRS_DIRTY: - // thunks are retainers. + // thunks are retainers. case THUNK: case THUNK_1_0: case THUNK_0_1: @@ -1041,63 +1041,63 @@ isRetainer( StgClosure *c ) case AP: case AP_STACK: - // Static thunks, or CAFS, are obviously retainers. + // Static thunks, or CAFS, are obviously retainers. case THUNK_STATIC: - // WEAK objects are roots; there is separate code in which traversing - // begins from WEAK objects. + // WEAK objects are roots; there is separate code in which traversing + // begins from WEAK objects. case WEAK: - return rtsTrue; + return rtsTrue; - // - // False case - // + // + // False case + // - // constructors + // constructors case CONSTR: case CONSTR_1_0: case CONSTR_0_1: case CONSTR_2_0: case CONSTR_1_1: case CONSTR_0_2: - // functions + // functions case FUN: case FUN_1_0: case FUN_0_1: case FUN_2_0: case FUN_1_1: case FUN_0_2: - // partial applications + // partial applications case PAP: - // indirection + // indirection case IND_PERM: // IND_STATIC used to be an error, but at the moment it can happen // as isAlive doesn't look through IND_STATIC as it ignores static // closures. See trac #3956 for a program that hit this error. case IND_STATIC: case BLACKHOLE: - // static objects + // static objects case CONSTR_STATIC: case FUN_STATIC: - // misc + // misc case PRIM: case BCO: case ARR_WORDS: - // STM + // STM case TREC_CHUNK: // immutable arrays case MUT_ARR_PTRS_FROZEN: case MUT_ARR_PTRS_FROZEN0: - return rtsFalse; + return rtsFalse; - // - // Error case - // - // CONSTR_NOCAF_STATIC - // cannot be *c, *cp, *r in the retainer profiling loop. + // + // Error case + // + // CONSTR_NOCAF_STATIC + // cannot be *c, *cp, *r in the retainer profiling loop. case CONSTR_NOCAF_STATIC: - // Stack objects are invalid because they are never treated as - // legal objects during retainer profiling. + // Stack objects are invalid because they are never treated as + // legal objects during retainer profiling. case UPDATE_FRAME: case CATCH_FRAME: case UNDERFLOW_FRAME: @@ -1105,12 +1105,12 @@ isRetainer( StgClosure *c ) case RET_BCO: case RET_SMALL: case RET_BIG: - // other cases + // other cases case IND: case INVALID_OBJECT: default: - barf("Invalid object in isRetainer(): %d", get_itbl(c)->type); - return rtsFalse; + barf("Invalid object in isRetainer(): %d", get_itbl(c)->type); + return rtsFalse; } } @@ -1166,39 +1166,39 @@ associate( StgClosure *c, RetainerSet *s ) static void retain_large_bitmap (StgPtr p, StgLargeBitmap *large_bitmap, nat size, - StgClosure *c, retainer c_child_r) + StgClosure *c, retainer c_child_r) { nat i, b; StgWord bitmap; - + b = 0; bitmap = large_bitmap->bitmap[b]; for (i = 0; i < size; ) { - if ((bitmap & 1) == 0) { - retainClosure((StgClosure *)*p, c, c_child_r); - } - i++; - p++; - if (i % BITS_IN(W_) == 0) { - b++; - bitmap = large_bitmap->bitmap[b]; - } else { - bitmap = bitmap >> 1; - } + if ((bitmap & 1) == 0) { + retainClosure((StgClosure *)*p, c, c_child_r); + } + i++; + p++; + if (i % BITS_IN(W_) == 0) { + b++; + bitmap = large_bitmap->bitmap[b]; + } else { + bitmap = bitmap >> 1; + } } } static INLINE StgPtr retain_small_bitmap (StgPtr p, nat size, StgWord bitmap, - StgClosure *c, retainer c_child_r) + StgClosure *c, retainer c_child_r) { while (size > 0) { - if ((bitmap & 1) == 0) { - retainClosure((StgClosure *)*p, c, c_child_r); - } - p++; - bitmap = bitmap >> 1; - size--; + if ((bitmap & 1) == 0) { + retainClosure((StgClosure *)*p, c, c_child_r); + } + p++; + bitmap = bitmap >> 1; + size--; } return p; } @@ -1213,23 +1213,23 @@ retain_large_srt_bitmap (StgLargeSRT *srt, StgClosure *c, retainer c_child_r) nat i, b, size; StgWord bitmap; StgClosure **p; - + b = 0; p = (StgClosure **)srt->srt; size = srt->l.size; bitmap = srt->l.bitmap[b]; for (i = 0; i < size; ) { - if ((bitmap & 1) != 0) { - retainClosure((StgClosure *)*p, c, c_child_r); - } - i++; - p++; - if (i % BITS_IN(W_) == 0) { - b++; - bitmap = srt->l.bitmap[b]; - } else { - bitmap = bitmap >> 1; - } + if ((bitmap & 1) != 0) { + retainClosure((StgClosure *)*p, c, c_child_r); + } + i++; + p++; + if (i % BITS_IN(W_) == 0) { + b++; + bitmap = srt->l.bitmap[b]; + } else { + bitmap = bitmap >> 1; + } } } @@ -1242,7 +1242,7 @@ retainSRT (StgClosure **srt, nat srt_bitmap, StgClosure *c, retainer c_child_r) bitmap = srt_bitmap; p = srt; - if (bitmap == (StgHalfWord)(-1)) { + if (bitmap == (StgHalfWord)(-1)) { retain_large_srt_bitmap( (StgLargeSRT *)srt, c, c_child_r ); return; } @@ -1250,14 +1250,14 @@ retainSRT (StgClosure **srt, nat srt_bitmap, StgClosure *c, retainer c_child_r) while (bitmap != 0) { if ((bitmap & 1) != 0) { #if defined(COMPILING_WINDOWS_DLL) - if ( (unsigned long)(*srt) & 0x1 ) { - retainClosure(* (StgClosure**) ((unsigned long) (*srt) & ~0x1), - c, c_child_r); - } else { - retainClosure(*srt,c,c_child_r); - } + if ( (unsigned long)(*srt) & 0x1 ) { + retainClosure(* (StgClosure**) ((unsigned long) (*srt) & ~0x1), + c, c_child_r); + } else { + retainClosure(*srt,c,c_child_r); + } #else - retainClosure(*srt,c,c_child_r); + retainClosure(*srt,c,c_child_r); #endif } p++; @@ -1277,7 +1277,7 @@ retainSRT (StgClosure **srt, nat srt_bitmap, StgClosure *c, retainer c_child_r) * RSET(c) and RSET(c_child_r) are valid, i.e., their * interpretation conforms to the current value of flip (even when they * are interpreted to be NULL). - * If *c is TSO, its state is not ThreadComplete,or ThreadKilled, + * If *c is TSO, its state is not ThreadComplete,or ThreadKilled, * which means that its stack is ready to process. * Note: * This code was almost plagiarzied from GC.c! For each pointer, @@ -1285,7 +1285,7 @@ retainSRT (StgClosure **srt, nat srt_bitmap, StgClosure *c, retainer c_child_r) * -------------------------------------------------------------------------- */ static void retainStack( StgClosure *c, retainer c_child_r, - StgPtr stackStart, StgPtr stackEnd ) + StgPtr stackStart, StgPtr stackEnd ) { stackElement *oldStackBoundary; StgPtr p; @@ -1315,87 +1315,87 @@ retainStack( StgClosure *c, retainer c_child_r, p = stackStart; while (p < stackEnd) { - info = get_ret_itbl((StgClosure *)p); + info = get_ret_itbl((StgClosure *)p); - switch(info->i.type) { + switch(info->i.type) { - case UPDATE_FRAME: - retainClosure(((StgUpdateFrame *)p)->updatee, c, c_child_r); - p += sizeofW(StgUpdateFrame); - continue; + case UPDATE_FRAME: + retainClosure(((StgUpdateFrame *)p)->updatee, c, c_child_r); + p += sizeofW(StgUpdateFrame); + continue; case UNDERFLOW_FRAME: case STOP_FRAME: - case CATCH_FRAME: - case CATCH_STM_FRAME: - case CATCH_RETRY_FRAME: - case ATOMICALLY_FRAME: - case RET_SMALL: - bitmap = BITMAP_BITS(info->i.layout.bitmap); - size = BITMAP_SIZE(info->i.layout.bitmap); - p++; - p = retain_small_bitmap(p, size, bitmap, c, c_child_r); - - follow_srt: - retainSRT((StgClosure **)GET_SRT(info), info->i.srt_bitmap, c, c_child_r); - continue; - - case RET_BCO: { - StgBCO *bco; - - p++; - retainClosure((StgClosure *)*p, c, c_child_r); - bco = (StgBCO *)*p; - p++; - size = BCO_BITMAP_SIZE(bco); - retain_large_bitmap(p, BCO_BITMAP(bco), size, c, c_child_r); - p += size; - continue; - } - - // large bitmap (> 32 entries, or > 64 on a 64-bit machine) - case RET_BIG: - size = GET_LARGE_BITMAP(&info->i)->size; - p++; - retain_large_bitmap(p, GET_LARGE_BITMAP(&info->i), - size, c, c_child_r); - p += size; - // and don't forget to follow the SRT - goto follow_srt; + case CATCH_FRAME: + case CATCH_STM_FRAME: + case CATCH_RETRY_FRAME: + case ATOMICALLY_FRAME: + case RET_SMALL: + bitmap = BITMAP_BITS(info->i.layout.bitmap); + size = BITMAP_SIZE(info->i.layout.bitmap); + p++; + p = retain_small_bitmap(p, size, bitmap, c, c_child_r); + + follow_srt: + retainSRT((StgClosure **)GET_SRT(info), info->i.srt_bitmap, c, c_child_r); + continue; + + case RET_BCO: { + StgBCO *bco; + + p++; + retainClosure((StgClosure *)*p, c, c_child_r); + bco = (StgBCO *)*p; + p++; + size = BCO_BITMAP_SIZE(bco); + retain_large_bitmap(p, BCO_BITMAP(bco), size, c, c_child_r); + p += size; + continue; + } + + // large bitmap (> 32 entries, or > 64 on a 64-bit machine) + case RET_BIG: + size = GET_LARGE_BITMAP(&info->i)->size; + p++; + retain_large_bitmap(p, GET_LARGE_BITMAP(&info->i), + size, c, c_child_r); + p += size; + // and don't forget to follow the SRT + goto follow_srt; case RET_FUN: { - StgRetFun *ret_fun = (StgRetFun *)p; - StgFunInfoTable *fun_info; - - retainClosure(ret_fun->fun, c, c_child_r); - fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun)); - - p = (P_)&ret_fun->payload; - switch (fun_info->f.fun_type) { - case ARG_GEN: - bitmap = BITMAP_BITS(fun_info->f.b.bitmap); - size = BITMAP_SIZE(fun_info->f.b.bitmap); - p = retain_small_bitmap(p, size, bitmap, c, c_child_r); - break; - case ARG_GEN_BIG: - size = GET_FUN_LARGE_BITMAP(fun_info)->size; - retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), - size, c, c_child_r); - p += size; - break; - default: - bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); - size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]); - p = retain_small_bitmap(p, size, bitmap, c, c_child_r); - break; - } - goto follow_srt; - } - - default: - barf("Invalid object found in retainStack(): %d", - (int)(info->i.type)); - } + StgRetFun *ret_fun = (StgRetFun *)p; + StgFunInfoTable *fun_info; + + retainClosure(ret_fun->fun, c, c_child_r); + fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun)); + + p = (P_)&ret_fun->payload; + switch (fun_info->f.fun_type) { + case ARG_GEN: + bitmap = BITMAP_BITS(fun_info->f.b.bitmap); + size = BITMAP_SIZE(fun_info->f.b.bitmap); + p = retain_small_bitmap(p, size, bitmap, c, c_child_r); + break; + case ARG_GEN_BIG: + size = GET_FUN_LARGE_BITMAP(fun_info)->size; + retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), + size, c, c_child_r); + p += size; + break; + default: + bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); + size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]); + p = retain_small_bitmap(p, size, bitmap, c, c_child_r); + break; + } + goto follow_srt; + } + + default: + barf("Invalid object found in retainStack(): %d", + (int)(info->i.type)); + } } // restore currentStackBoundary @@ -1415,9 +1415,9 @@ retainStack( StgClosure *c, retainer c_child_r, static INLINE StgPtr retain_PAP_payload (StgClosure *pap, /* NOT tagged */ - retainer c_child_r, /* NOT tagged */ + retainer c_child_r, /* NOT tagged */ StgClosure *fun, /* tagged */ - StgClosure** payload, StgWord n_args) + StgClosure** payload, StgWord n_args) { StgPtr p; StgWord bitmap; @@ -1432,24 +1432,24 @@ retain_PAP_payload (StgClosure *pap, /* NOT tagged */ switch (fun_info->f.fun_type) { case ARG_GEN: - bitmap = BITMAP_BITS(fun_info->f.b.bitmap); - p = retain_small_bitmap(p, n_args, bitmap, - pap, c_child_r); - break; + bitmap = BITMAP_BITS(fun_info->f.b.bitmap); + p = retain_small_bitmap(p, n_args, bitmap, + pap, c_child_r); + break; case ARG_GEN_BIG: - retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), - n_args, pap, c_child_r); - p += n_args; - break; + retain_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), + n_args, pap, c_child_r); + p += n_args; + break; case ARG_BCO: - retain_large_bitmap((StgPtr)payload, BCO_BITMAP(fun), - n_args, pap, c_child_r); - p += n_args; - break; + retain_large_bitmap((StgPtr)payload, BCO_BITMAP(fun), + n_args, pap, c_child_r); + p += n_args; + break; default: - bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); - p = retain_small_bitmap(p, n_args, bitmap, pap, c_child_r); - break; + bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); + p = retain_small_bitmap(p, n_args, bitmap, pap, c_child_r); + break; } return p; } @@ -1505,9 +1505,9 @@ loop: if (c == NULL) { #ifdef DEBUG_RETAINER - // debugBelch("retainClosure() ends: oldStackTop = 0x%x, stackTop = 0x%x\n", oldStackTop, stackTop); + // debugBelch("retainClosure() ends: oldStackTop = 0x%x, stackTop = 0x%x\n", oldStackTop, stackTop); #endif - return; + return; } //debugBelch("inner_loop"); @@ -1536,70 +1536,70 @@ inner_loop: case CONSTR_STATIC: case THUNK_STATIC: case FUN_STATIC: - break; + break; default: - if (retainerSetOf(c) == NULL) { // first visit? - costArray[typeOfc] += cost(c); - sumOfNewCost += cost(c); - } - break; + if (retainerSetOf(c) == NULL) { // first visit? + costArray[typeOfc] += cost(c); + sumOfNewCost += cost(c); + } + break; } #endif // special cases switch (typeOfc) { case TSO: - if (((StgTSO *)c)->what_next == ThreadComplete || - ((StgTSO *)c)->what_next == ThreadKilled) { + if (((StgTSO *)c)->what_next == ThreadComplete || + ((StgTSO *)c)->what_next == ThreadKilled) { #ifdef DEBUG_RETAINER - debugBelch("ThreadComplete or ThreadKilled encountered in retainClosure()\n"); + debugBelch("ThreadComplete or ThreadKilled encountered in retainClosure()\n"); #endif - goto loop; - } + goto loop; + } break; case IND_STATIC: - // We just skip IND_STATIC, so its retainer set is never computed. - c = ((StgIndStatic *)c)->indirectee; - goto inner_loop; - // static objects with no pointers out, so goto loop. + // We just skip IND_STATIC, so its retainer set is never computed. + c = ((StgIndStatic *)c)->indirectee; + goto inner_loop; + // static objects with no pointers out, so goto loop. case CONSTR_NOCAF_STATIC: - // It is not just enough not to compute the retainer set for *c; it is - // mandatory because CONSTR_NOCAF_STATIC are not reachable from - // scavenged_static_objects, the list from which is assumed to traverse - // all static objects after major garbage collections. - goto loop; + // It is not just enough not to compute the retainer set for *c; it is + // mandatory because CONSTR_NOCAF_STATIC are not reachable from + // scavenged_static_objects, the list from which is assumed to traverse + // all static objects after major garbage collections. + goto loop; case THUNK_STATIC: case FUN_STATIC: - if (get_itbl(c)->srt_bitmap == 0) { - // No need to compute the retainer set; no dynamic objects - // are reachable from *c. - // - // Static objects: if we traverse all the live closures, - // including static closures, during each heap census then - // we will observe that some static closures appear and - // disappear. eg. a closure may contain a pointer to a - // static function 'f' which is not otherwise reachable - // (it doesn't indirectly point to any CAFs, so it doesn't - // appear in any SRTs), so we would find 'f' during - // traversal. However on the next sweep there may be no - // closures pointing to 'f'. - // - // We must therefore ignore static closures whose SRT is - // empty, because these are exactly the closures that may - // "appear". A closure with a non-empty SRT, and which is - // still required, will always be reachable. - // - // But what about CONSTR_STATIC? Surely these may be able - // to appear, and they don't have SRTs, so we can't - // check. So for now, we're calling - // resetStaticObjectForRetainerProfiling() from the - // garbage collector to reset the retainer sets in all the - // reachable static objects. - goto loop; - } + if (get_itbl(c)->srt_bitmap == 0) { + // No need to compute the retainer set; no dynamic objects + // are reachable from *c. + // + // Static objects: if we traverse all the live closures, + // including static closures, during each heap census then + // we will observe that some static closures appear and + // disappear. eg. a closure may contain a pointer to a + // static function 'f' which is not otherwise reachable + // (it doesn't indirectly point to any CAFs, so it doesn't + // appear in any SRTs), so we would find 'f' during + // traversal. However on the next sweep there may be no + // closures pointing to 'f'. + // + // We must therefore ignore static closures whose SRT is + // empty, because these are exactly the closures that may + // "appear". A closure with a non-empty SRT, and which is + // still required, will always be reachable. + // + // But what about CONSTR_STATIC? Surely these may be able + // to appear, and they don't have SRTs, so we can't + // check. So for now, we're calling + // resetStaticObjectForRetainerProfiling() from the + // garbage collector to reset the retainer sets in all the + // reachable static objects. + goto loop; + } default: - break; + break; } // The above objects are ignored in computing the average number of times @@ -1614,51 +1614,51 @@ inner_loop: // isRetainer(cp) == rtsTrue => s == NULL // isRetainer(cp) == rtsFalse => s == cp.retainer if (isRetainer(cp)) - s = NULL; + s = NULL; else - s = retainerSetOf(cp); + s = retainerSetOf(cp); // (c, cp, r, s) is available. // (c, cp, r, s, R_r) is available, so compute the retainer set for *c. if (retainerSetOfc == NULL) { - // This is the first visit to *c. - numObjectVisited++; + // This is the first visit to *c. + numObjectVisited++; - if (s == NULL) - associate(c, singleton(r)); - else - // s is actually the retainer set of *c! - associate(c, s); + if (s == NULL) + associate(c, singleton(r)); + else + // s is actually the retainer set of *c! + associate(c, s); - // compute c_child_r - c_child_r = isRetainer(c) ? getRetainerFrom(c) : r; + // compute c_child_r + c_child_r = isRetainer(c) ? getRetainerFrom(c) : r; } else { - // This is not the first visit to *c. - if (isMember(r, retainerSetOfc)) - goto loop; // no need to process child - - if (s == NULL) - associate(c, addElement(r, retainerSetOfc)); - else { - // s is not NULL and cp is not a retainer. This means that - // each time *cp is visited, so is *c. Thus, if s has - // exactly one more element in its retainer set than c, s - // is also the new retainer set for *c. - if (s->num == retainerSetOfc->num + 1) { - associate(c, s); - } - // Otherwise, just add R_r to the current retainer set of *c. - else { - associate(c, addElement(r, retainerSetOfc)); - } - } - - if (isRetainer(c)) - goto loop; // no need to process child - - // compute c_child_r - c_child_r = r; + // This is not the first visit to *c. + if (isMember(r, retainerSetOfc)) + goto loop; // no need to process child + + if (s == NULL) + associate(c, addElement(r, retainerSetOfc)); + else { + // s is not NULL and cp is not a retainer. This means that + // each time *cp is visited, so is *c. Thus, if s has + // exactly one more element in its retainer set than c, s + // is also the new retainer set for *c. + if (s->num == retainerSetOfc->num + 1) { + associate(c, s); + } + // Otherwise, just add R_r to the current retainer set of *c. + else { + associate(c, addElement(r, retainerSetOfc)); + } + } + + if (isRetainer(c)) + goto loop; // no need to process child + + // compute c_child_r + c_child_r = r; } // now, RSET() of all of *c, *cp, and *r is valid. @@ -1671,10 +1671,10 @@ inner_loop: // would be hard. switch (typeOfc) { case STACK: - retainStack(c, c_child_r, + retainStack(c, c_child_r, ((StgStack *)c)->sp, ((StgStack *)c)->stack + ((StgStack *)c)->stack_size); - goto loop; + goto loop; case TSO: { @@ -1696,25 +1696,25 @@ inner_loop: case PAP: { - StgPAP *pap = (StgPAP *)c; - retain_PAP_payload(c, c_child_r, pap->fun, pap->payload, pap->n_args); - goto loop; + StgPAP *pap = (StgPAP *)c; + retain_PAP_payload(c, c_child_r, pap->fun, pap->payload, pap->n_args); + goto loop; } case AP: { - StgAP *ap = (StgAP *)c; - retain_PAP_payload(c, c_child_r, ap->fun, ap->payload, ap->n_args); - goto loop; + StgAP *ap = (StgAP *)c; + retain_PAP_payload(c, c_child_r, ap->fun, ap->payload, ap->n_args); + goto loop; } case AP_STACK: - retainClosure(((StgAP_STACK *)c)->fun, c, c_child_r); - retainStack(c, c_child_r, - (StgPtr)((StgAP_STACK *)c)->payload, - (StgPtr)((StgAP_STACK *)c)->payload + - ((StgAP_STACK *)c)->size); - goto loop; + retainClosure(((StgAP_STACK *)c)->fun, c, c_child_r); + retainStack(c, c_child_r, + (StgPtr)((StgAP_STACK *)c)->payload, + (StgPtr)((StgAP_STACK *)c)->payload + + ((StgAP_STACK *)c)->size); + goto loop; } push(c, c_child_r, &first_child); @@ -1723,7 +1723,7 @@ inner_loop: // If first_child is not null, the top stack element points to the next // object. push() may or may not push a stackElement on the stack. if (first_child == NULL) - goto loop; + goto loop; // (c, cp, r) = (first_child, c, c_child_r) r = c_child_r; @@ -1749,9 +1749,9 @@ retainRoot(void *user STG_UNUSED, StgClosure **tl) c = UNTAG_CLOSURE(*tl); maybeInitRetainerSet(c); if (c != &stg_END_TSO_QUEUE_closure && isRetainer(c)) { - retainClosure(c, c, getRetainerFrom(c)); + retainClosure(c, c, getRetainerFrom(c)); } else { - retainClosure(c, c, CCS_SYSTEM); + retainClosure(c, c, CCS_SYSTEM); } // NOT TRUE: ASSERT(isMember(getRetainerFrom(*tl), retainerSetOf(*tl))); @@ -1774,7 +1774,7 @@ computeRetainerSet( void ) RetainerSet tmpRetainerSet; #endif - markCapabilities(retainRoot, NULL); // for scheduler roots + markCapabilities(retainRoot, NULL); // for scheduler roots // This function is called after a major GC, when key, value, and finalizer // all are guaranteed to be valid, or reachable. @@ -1801,44 +1801,44 @@ computeRetainerSet( void ) // object (computing sumOfNewCostExtra and updating costArray[] when // debugging retainer profiler). for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - // NOT TRUE: even G0 has a block on its mutable list + // NOT TRUE: even G0 has a block on its mutable list // ASSERT(g != 0 || (generations[g].mut_list == NULL)); - // Traversing through mut_list is necessary - // because we can find MUT_VAR objects which have not been - // visited during retainer profiling. + // Traversing through mut_list is necessary + // because we can find MUT_VAR objects which have not been + // visited during retainer profiling. for (n = 0; n < n_capabilities; n++) { for (bd = capabilities[n]->mut_lists[g]; bd != NULL; bd = bd->link) { - for (ml = bd->start; ml < bd->free; ml++) { + for (ml = bd->start; ml < bd->free; ml++) { - maybeInitRetainerSet((StgClosure *)*ml); - rtl = retainerSetOf((StgClosure *)*ml); + maybeInitRetainerSet((StgClosure *)*ml); + rtl = retainerSetOf((StgClosure *)*ml); #ifdef DEBUG_RETAINER - if (rtl == NULL) { - // first visit to *ml - // This is a violation of the interface rule! - RSET(ml) = (RetainerSet *)((StgWord)(&tmpRetainerSet) | flip); - - switch (get_itbl((StgClosure *)ml)->type) { - case IND_STATIC: - // no cost involved - break; - case CONSTR_NOCAF_STATIC: - case CONSTR_STATIC: - case THUNK_STATIC: - case FUN_STATIC: - barf("Invalid object in computeRetainerSet(): %d", get_itbl((StgClosure*)ml)->type); - break; - default: - // dynamic objects - costArray[get_itbl((StgClosure *)ml)->type] += cost((StgClosure *)ml); - sumOfNewCostExtra += cost((StgClosure *)ml); - break; - } - } + if (rtl == NULL) { + // first visit to *ml + // This is a violation of the interface rule! + RSET(ml) = (RetainerSet *)((StgWord)(&tmpRetainerSet) | flip); + + switch (get_itbl((StgClosure *)ml)->type) { + case IND_STATIC: + // no cost involved + break; + case CONSTR_NOCAF_STATIC: + case CONSTR_STATIC: + case THUNK_STATIC: + case FUN_STATIC: + barf("Invalid object in computeRetainerSet(): %d", get_itbl((StgClosure*)ml)->type); + break; + default: + // dynamic objects + costArray[get_itbl((StgClosure *)ml)->type] += cost((StgClosure *)ml); + sumOfNewCostExtra += cost((StgClosure *)ml); + break; + } + } #endif - } + } } } } @@ -1883,32 +1883,32 @@ resetStaticObjectForRetainerProfiling( StgClosure *static_objects ) p = static_objects; while (p != END_OF_STATIC_LIST) { #ifdef DEBUG_RETAINER - count++; + count++; #endif - switch (get_itbl(p)->type) { - case IND_STATIC: - // Since we do not compute the retainer set of any - // IND_STATIC object, we don't have to reset its retainer - // field. - p = (StgClosure*)*IND_STATIC_LINK(p); - break; - case THUNK_STATIC: - maybeInitRetainerSet(p); - p = (StgClosure*)*THUNK_STATIC_LINK(p); - break; - case FUN_STATIC: - maybeInitRetainerSet(p); - p = (StgClosure*)*FUN_STATIC_LINK(p); - break; - case CONSTR_STATIC: - maybeInitRetainerSet(p); - p = (StgClosure*)*STATIC_LINK(get_itbl(p), p); - break; - default: - barf("resetStaticObjectForRetainerProfiling: %p (%s)", - p, get_itbl(p)->type); - break; - } + switch (get_itbl(p)->type) { + case IND_STATIC: + // Since we do not compute the retainer set of any + // IND_STATIC object, we don't have to reset its retainer + // field. + p = (StgClosure*)*IND_STATIC_LINK(p); + break; + case THUNK_STATIC: + maybeInitRetainerSet(p); + p = (StgClosure*)*THUNK_STATIC_LINK(p); + break; + case FUN_STATIC: + maybeInitRetainerSet(p); + p = (StgClosure*)*FUN_STATIC_LINK(p); + break; + case CONSTR_STATIC: + maybeInitRetainerSet(p); + p = (StgClosure*)*STATIC_LINK(get_itbl(p), p); + break; + default: + barf("resetStaticObjectForRetainerProfiling: %p (%s)", + p, get_itbl(p)->type); + break; + } } #ifdef DEBUG_RETAINER // debugBelch("count in scavenged_static_objects = %d\n", count); @@ -2077,20 +2077,20 @@ sanityCheckHeapClosure( StgClosure *c ) ASSERT(LOOKS_LIKE_PTR(c)); if ((((StgWord)RSET(c) & 1) ^ flip) != 0) { - if (get_itbl(c)->type == CONSTR && - !strcmp(GET_PROF_TYPE(get_itbl(c)), "DEAD_WEAK") && - !strcmp(GET_PROF_DESC(get_itbl(c)), "DEAD_WEAK")) { - debugBelch("\tUnvisited dead weak pointer object found: c = %p\n", c); - costArray[get_itbl(c)->type] += cost(c); - sumOfNewCost += cost(c); - } else - debugBelch( - "Unvisited object: flip = %d, c = %p(%d, %s, %s), rs = %p\n", - flip, c, get_itbl(c)->type, - get_itbl(c)->prof.closure_type, GET_PROF_DESC(get_itbl(c)), - RSET(c)); + if (get_itbl(c)->type == CONSTR && + !strcmp(GET_PROF_TYPE(get_itbl(c)), "DEAD_WEAK") && + !strcmp(GET_PROF_DESC(get_itbl(c)), "DEAD_WEAK")) { + debugBelch("\tUnvisited dead weak pointer object found: c = %p\n", c); + costArray[get_itbl(c)->type] += cost(c); + sumOfNewCost += cost(c); + } else + debugBelch( + "Unvisited object: flip = %d, c = %p(%d, %s, %s), rs = %p\n", + flip, c, get_itbl(c)->type, + get_itbl(c)->prof.closure_type, GET_PROF_DESC(get_itbl(c)), + RSET(c)); } else { - // debugBelch("sanityCheckHeapClosure) S: flip = %d, c = %p(%d), rs = %p\n", flip, c, get_itbl(c)->type, RSET(c)); + // debugBelch("sanityCheckHeapClosure) S: flip = %d, c = %p(%d), rs = %p\n", flip, c, get_itbl(c)->type, RSET(c)); } return closure_sizeW(c); @@ -2104,17 +2104,17 @@ heapCheck( bdescr *bd ) costSum = 0; while (bd != NULL) { - p = bd->start; - while (p < bd->free) { - size = sanityCheckHeapClosure((StgClosure *)p); - sumOfCostLinear += size; - costArrayLinear[get_itbl((StgClosure *)p)->type] += size; - p += size; - // no need for slop check; I think slops are not used currently. - } - ASSERT(p == bd->free); - costSum += bd->free - bd->start; - bd = bd->link; + p = bd->start; + while (p < bd->free) { + size = sanityCheckHeapClosure((StgClosure *)p); + sumOfCostLinear += size; + costArrayLinear[get_itbl((StgClosure *)p)->type] += size; + p += size; + // no need for slop check; I think slops are not used currently. + } + ASSERT(p == bd->free); + costSum += bd->free - bd->start; + bd = bd->link; } return costSum; @@ -2132,30 +2132,30 @@ smallObjectPoolCheck(void) // first block if (bd == NULL) - return costSum; + return costSum; p = bd->start; while (p < alloc_Hp) { - size = sanityCheckHeapClosure((StgClosure *)p); - sumOfCostLinear += size; - costArrayLinear[get_itbl((StgClosure *)p)->type] += size; - p += size; + size = sanityCheckHeapClosure((StgClosure *)p); + sumOfCostLinear += size; + costArrayLinear[get_itbl((StgClosure *)p)->type] += size; + p += size; } ASSERT(p == alloc_Hp); costSum += alloc_Hp - bd->start; bd = bd->link; while (bd != NULL) { - p = bd->start; - while (p < bd->free) { - size = sanityCheckHeapClosure((StgClosure *)p); - sumOfCostLinear += size; - costArrayLinear[get_itbl((StgClosure *)p)->type] += size; - p += size; - } - ASSERT(p == bd->free); - costSum += bd->free - bd->start; - bd = bd->link; + p = bd->start; + while (p < bd->free) { + size = sanityCheckHeapClosure((StgClosure *)p); + sumOfCostLinear += size; + costArrayLinear[get_itbl((StgClosure *)p)->type] += size; + p += size; + } + ASSERT(p == bd->free); + costSum += bd->free - bd->start; + bd = bd->link; } return costSum; @@ -2168,14 +2168,14 @@ chainCheck(bdescr *bd) costSum = 0; while (bd != NULL) { - // bd->free - bd->start is not an accurate measurement of the - // object size. Actually it is always zero, so we compute its - // size explicitly. - size = sanityCheckHeapClosure((StgClosure *)bd->start); - sumOfCostLinear += size; - costArrayLinear[get_itbl((StgClosure *)bd->start)->type] += size; - costSum += size; - bd = bd->link; + // bd->free - bd->start is not an accurate measurement of the + // object size. Actually it is always zero, so we compute its + // size explicitly. + size = sanityCheckHeapClosure((StgClosure *)bd->start); + sumOfCostLinear += size; + costArrayLinear[get_itbl((StgClosure *)bd->start)->type] += size; + costSum += size; + bd = bd->link; } return costSum; @@ -2189,32 +2189,32 @@ checkHeapSanityForRetainerProfiling( void ) costSum = 0; debugBelch("START: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); if (RtsFlags.GcFlags.generations == 1) { - costSum += heapCheck(g0s0->to_blocks); - debugBelch("heapCheck: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); - costSum += chainCheck(g0s0->large_objects); - debugBelch("chainCheck: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); + costSum += heapCheck(g0s0->to_blocks); + debugBelch("heapCheck: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); + costSum += chainCheck(g0s0->large_objects); + debugBelch("chainCheck: sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); } else { - for (g = 0; g < RtsFlags.GcFlags.generations; g++) - for (s = 0; s < generations[g].n_steps; s++) { - /* - After all live objects have been scavenged, the garbage - collector may create some objects in - scheduleFinalizers(). These objects are created throught - allocate(), so the small object pool or the large object - pool of the g0s0 may not be empty. - */ - if (g == 0 && s == 0) { - costSum += smallObjectPoolCheck(); - debugBelch("smallObjectPoolCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); - costSum += chainCheck(generations[g].steps[s].large_objects); - debugBelch("chainCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); - } else { - costSum += heapCheck(generations[g].steps[s].blocks); - debugBelch("heapCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); - costSum += chainCheck(generations[g].steps[s].large_objects); - debugBelch("chainCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); - } - } + for (g = 0; g < RtsFlags.GcFlags.generations; g++) + for (s = 0; s < generations[g].n_steps; s++) { + /* + After all live objects have been scavenged, the garbage + collector may create some objects in + scheduleFinalizers(). These objects are created throught + allocate(), so the small object pool or the large object + pool of the g0s0 may not be empty. + */ + if (g == 0 && s == 0) { + costSum += smallObjectPoolCheck(); + debugBelch("smallObjectPoolCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); + costSum += chainCheck(generations[g].steps[s].large_objects); + debugBelch("chainCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); + } else { + costSum += heapCheck(generations[g].steps[s].blocks); + debugBelch("heapCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); + costSum += chainCheck(generations[g].steps[s].large_objects); + debugBelch("chainCheck(): sumOfCostLinear = %d, costSum = %d\n", sumOfCostLinear, costSum); + } + } } return costSum; @@ -2228,32 +2228,32 @@ findPointer(StgPtr p) nat g, s; for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - for (s = 0; s < generations[g].n_steps; s++) { - // if (g == 0 && s == 0) continue; - bd = generations[g].steps[s].blocks; - for (; bd; bd = bd->link) { - for (q = bd->start; q < bd->free; q++) { - if (*q == (StgWord)p) { - r = q; - while (!LOOKS_LIKE_GHC_INFO(*r)) r--; - debugBelch("Found in gen[%d], step[%d]: q = %p, r = %p\n", g, s, q, r); - // return; - } - } - } - bd = generations[g].steps[s].large_objects; - for (; bd; bd = bd->link) { - e = bd->start + cost((StgClosure *)bd->start); - for (q = bd->start; q < e; q++) { - if (*q == (StgWord)p) { - r = q; - while (*r == 0 || !LOOKS_LIKE_GHC_INFO(*r)) r--; - debugBelch("Found in gen[%d], large_objects: %p\n", g, r); - // return; - } - } - } - } + for (s = 0; s < generations[g].n_steps; s++) { + // if (g == 0 && s == 0) continue; + bd = generations[g].steps[s].blocks; + for (; bd; bd = bd->link) { + for (q = bd->start; q < bd->free; q++) { + if (*q == (StgWord)p) { + r = q; + while (!LOOKS_LIKE_GHC_INFO(*r)) r--; + debugBelch("Found in gen[%d], step[%d]: q = %p, r = %p\n", g, s, q, r); + // return; + } + } + } + bd = generations[g].steps[s].large_objects; + for (; bd; bd = bd->link) { + e = bd->start + cost((StgClosure *)bd->start); + for (q = bd->start; q < e; q++) { + if (*q == (StgWord)p) { + r = q; + while (*r == 0 || !LOOKS_LIKE_GHC_INFO(*r)) r--; + debugBelch("Found in gen[%d], large_objects: %p\n", g, r); + // return; + } + } + } + } } } @@ -2264,23 +2264,23 @@ belongToHeap(StgPtr p) nat g, s; for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - for (s = 0; s < generations[g].n_steps; s++) { - // if (g == 0 && s == 0) continue; - bd = generations[g].steps[s].blocks; - for (; bd; bd = bd->link) { - if (bd->start <= p && p < bd->free) { - debugBelch("Belongs to gen[%d], step[%d]", g, s); - return; - } - } - bd = generations[g].steps[s].large_objects; - for (; bd; bd = bd->link) { - if (bd->start <= p && p < bd->start + getHeapClosureSize((StgClosure *)bd->start)) { - debugBelch("Found in gen[%d], large_objects: %p\n", g, bd->start); - return; - } - } - } + for (s = 0; s < generations[g].n_steps; s++) { + // if (g == 0 && s == 0) continue; + bd = generations[g].steps[s].blocks; + for (; bd; bd = bd->link) { + if (bd->start <= p && p < bd->free) { + debugBelch("Belongs to gen[%d], step[%d]", g, s); + return; + } + } + bd = generations[g].steps[s].large_objects; + for (; bd; bd = bd->link) { + if (bd->start <= p && p < bd->start + getHeapClosureSize((StgClosure *)bd->start)) { + debugBelch("Found in gen[%d], large_objects: %p\n", g, bd->start); + return; + } + } + } } } #endif /* DEBUG_RETAINER */ |