/* -----------------------------------------------------------------------------
*
- * (c) The GHC Team, 1998-2001
+ * (c) The GHC Team, 1998-2006
*
* Sanity checking code for the heap and stack.
*
switch (fun_info->f.fun_type) {
case ARG_GEN:
checkSmallBitmap((StgPtr)ret_fun->payload,
- BITMAP_BITS(fun_info->f.bitmap), size);
+ BITMAP_BITS(fun_info->f.b.bitmap), size);
break;
case ARG_GEN_BIG:
checkLargeBitmap((StgPtr)ret_fun->payload,
// ASSERT( p == stack_end ); -- HWL
}
+static void
+checkPAP (StgClosure *fun, StgClosure** payload, StgWord n_args)
+{
+ StgClosure *p;
+ StgFunInfoTable *fun_info;
+
+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(fun));
+ fun_info = get_fun_itbl(fun);
+
+ p = (StgClosure *)payload;
+ switch (fun_info->f.fun_type) {
+ case ARG_GEN:
+ checkSmallBitmap( (StgPtr)payload,
+ BITMAP_BITS(fun_info->f.b.bitmap), n_args );
+ break;
+ case ARG_GEN_BIG:
+ checkLargeBitmap( (StgPtr)payload,
+ GET_FUN_LARGE_BITMAP(fun_info),
+ n_args );
+ break;
+ case ARG_BCO:
+ checkLargeBitmap( (StgPtr)payload,
+ BCO_BITMAP(fun),
+ n_args );
+ break;
+ default:
+ checkSmallBitmap( (StgPtr)payload,
+ BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]),
+ n_args );
+ break;
+ }
+}
+
+
StgOffset
checkClosure( StgClosure* p )
{
{
nat i;
for (i = 0; i < info->layout.payload.ptrs; i++) {
- ASSERT(LOOKS_LIKE_CLOSURE_PTR(p->payload[i]));
+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(((StgThunk *)p)->payload[i]));
}
- return stg_max(sizeW_fromITBL(info), sizeofW(StgHeader) + MIN_UPD_SIZE);
+ return thunk_sizeW_fromITBL(info);
}
- case BLACKHOLE_BQ:
- checkBQ(((StgBlockingQueue *)p)->blocking_queue, p);
- /* fall through to basic ptr check */
case FUN:
case FUN_1_0:
case FUN_0_1:
#endif
case BLACKHOLE:
case CAF_BLACKHOLE:
- case FOREIGN:
case STABLE_NAME:
- case MUT_VAR:
+ case MUT_VAR_CLEAN:
+ case MUT_VAR_DIRTY:
case CONSTR_INTLIKE:
case CONSTR_CHARLIKE:
case CONSTR_STATIC:
/* we don't expect to see any of these after GC
* but they might appear during execution
*/
- P_ q;
StgInd *ind = (StgInd *)p;
ASSERT(LOOKS_LIKE_CLOSURE_PTR(ind->indirectee));
- q = (P_)p + sizeofW(StgInd);
- while (!*q) { q++; }; /* skip padding words (see GC.c: evacuate())*/
- return q - (P_)p;
+ return sizeofW(StgInd);
}
case RET_BCO:
case CATCH_STM_FRAME:
barf("checkClosure: stack frame");
- case AP: /* we can treat this as being the same as a PAP */
+ case AP:
+ {
+ StgAP* ap = (StgAP *)p;
+ checkPAP (ap->fun, ap->payload, ap->n_args);
+ return ap_sizeW(ap);
+ }
+
case PAP:
- {
- StgFunInfoTable *fun_info;
- StgPAP* pap = (StgPAP *)p;
-
- ASSERT(LOOKS_LIKE_CLOSURE_PTR(pap->fun));
- fun_info = get_fun_itbl(pap->fun);
-
- p = (StgClosure *)pap->payload;
- switch (fun_info->f.fun_type) {
- case ARG_GEN:
- checkSmallBitmap( (StgPtr)pap->payload,
- BITMAP_BITS(fun_info->f.bitmap), pap->n_args );
- break;
- case ARG_GEN_BIG:
- checkLargeBitmap( (StgPtr)pap->payload,
- GET_FUN_LARGE_BITMAP(fun_info),
- pap->n_args );
- break;
- case ARG_BCO:
- checkLargeBitmap( (StgPtr)pap->payload,
- BCO_BITMAP(pap->fun),
- pap->n_args );
- break;
- default:
- checkSmallBitmap( (StgPtr)pap->payload,
- BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]),
- pap->n_args );
- break;
- }
- return pap_sizeW(pap);
- }
+ {
+ StgPAP* pap = (StgPAP *)p;
+ checkPAP (pap->fun, pap->payload, pap->n_args);
+ return pap_sizeW(pap);
+ }
case AP_STACK:
{
case ARR_WORDS:
return arr_words_sizeW((StgArrWords *)p);
- case MUT_ARR_PTRS:
+ case MUT_ARR_PTRS_CLEAN:
+ case MUT_ARR_PTRS_DIRTY:
case MUT_ARR_PTRS_FROZEN:
+ case MUT_ARR_PTRS_FROZEN0:
{
StgMutArrPtrs* a = (StgMutArrPtrs *)p;
nat i;
#ifdef DIST
case REMOTE_REF:
return sizeofW(StgFetchMe);
-#endif //DIST
+#endif /*DIST */
case FETCH_ME:
ASSERT(LOOKS_LIKE_GA(((StgFetchMe *)p)->ga));
{
StgPtr p;
+#if defined(THREADED_RTS)
+ // heap sanity checking doesn't work with SMP, because we can't
+ // zero the slop (see Updates.h).
+ return;
+#endif
+
for (; bd != NULL; bd = bd->link) {
p = bd->start;
while (p < bd->free) {
nat size = checkClosure((StgClosure *)p);
/* This is the smallest size of closure that can live in the heap */
- ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
+ ASSERT( size >= MIN_PAYLOAD_SIZE + sizeofW(StgHeader) );
p += size;
/* skip over slop */
size = sizeofW(StgFetchMe);
} else if (get_itbl((StgClosure*)p)->type == IND) {
*(p+2) = 0x0000ee11; /* mark slop in IND as garbage */
- size = MIN_UPD_SIZE;
+ size = sizeofW(StgInd);
} else {
size = checkClosure((StgClosure *)p);
/* This is the smallest size of closure that can live in the heap. */
- ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
+ ASSERT( size >= MIN_PAYLOAD_SIZE + sizeofW(StgHeader) );
}
}
}
ASSERT(LOOKS_LIKE_INFO_PTR((void*)*p));
size = checkClosure((StgClosure *)p);
/* This is the smallest size of closure that can live in the heap. */
- ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
+ ASSERT( size >= MIN_PAYLOAD_SIZE + sizeofW(StgHeader) );
}
}
#endif
break;
case BlockedOnBlackHole:
checkClosureShallow(tso->block_info.closure);
- ASSERT(/* Can't be a BLACKHOLE because *this* closure is on its BQ */
- get_itbl(tso->block_info.closure)->type==BLACKHOLE_BQ ||
+ ASSERT(get_itbl(tso->block_info.closure)->type==BLACKHOLE ||
get_itbl(tso->block_info.closure)->type==RBH);
break;
case BlockedOnRead:
ASSERT(LOOKS_LIKE_CLOSURE_PTR(indirectee));
ASSERT(LOOKS_LIKE_INFO_PTR(indirectee->header.info));
- p = IND_STATIC_LINK((StgClosure *)p);
+ p = *IND_STATIC_LINK((StgClosure *)p);
break;
}
case THUNK_STATIC:
- p = THUNK_STATIC_LINK((StgClosure *)p);
+ p = *THUNK_STATIC_LINK((StgClosure *)p);
break;
case FUN_STATIC:
- p = FUN_STATIC_LINK((StgClosure *)p);
+ p = *FUN_STATIC_LINK((StgClosure *)p);
break;
case CONSTR_STATIC:
- p = STATIC_LINK(info,(StgClosure *)p);
+ p = *STATIC_LINK(info,(StgClosure *)p);
break;
default:
rtsBool end = rtsFalse;
StgInfoTable *info = get_itbl(closure);
- ASSERT(info->type == BLACKHOLE_BQ || info->type == MVAR
- || info->type == FETCH_ME_BQ || info->type == RBH);
+ ASSERT(info->type == MVAR || info->type == FETCH_ME_BQ || info->type == RBH);
do {
switch (get_itbl(bqe)->type) {
rtsBool end = rtsFalse;
StgInfoTable *info = get_itbl(closure);
- ASSERT(info->type == BLACKHOLE_BQ || info->type == MVAR);
+ ASSERT(info->type == MVAR);
do {
switch (get_itbl(bqe)->type) {
}
} while (!end);
}
-#else
-void
-checkBQ (StgTSO *bqe, StgClosure *closure)
-{
- rtsBool end = rtsFalse;
- StgInfoTable *info = get_itbl(closure);
-
- ASSERT(info->type == BLACKHOLE_BQ || info->type == MVAR);
-
- do {
- switch (get_itbl(bqe)->type) {
- case TSO:
- checkClosure((StgClosure *)bqe);
- bqe = bqe->link;
- end = (bqe==END_TSO_QUEUE);
- break;
-
- default:
- barf("checkBQ: strange closure %d in blocking queue for closure %p\n",
- get_itbl(bqe)->type, closure, info->type);
- }
- } while (!end);
-}
-
#endif