/* -----------------------------------------------------------------------------
- * $Id: Sanity.c,v 1.2 1998/12/02 13:28:43 simonm Exp $
+ * $Id: Sanity.c,v 1.4 1999/01/15 17:57:10 simonm Exp $
*
* Sanity checking code for the heap and stack.
*
#include "BlockAlloc.h"
#include "Sanity.h"
-static nat heap_step;
-
#define LOOKS_LIKE_PTR(r) \
- (IS_DATA_PTR(r) || ((IS_USER_PTR(r) && Bdescr((P_)r)->step == heap_step)))
+ (IS_DATA_PTR(r) || ((IS_USER_PTR(r) && Bdescr((P_)r)->free != (void *)-1)))
/* -----------------------------------------------------------------------------
Check stack sanity
case THUNK:
case CONSTR:
case IND_PERM:
+ case IND_OLDGEN:
case IND_OLDGEN_PERM:
case CAF_UNENTERED:
case CAF_ENTERED:
case CAF_BLACKHOLE:
case BLACKHOLE:
+ case BLACKHOLE_BQ:
case FOREIGN:
case MVAR:
case MUT_VAR:
return sizeofW(StgHeader) + MIN_UPD_SIZE;
case IND:
- case IND_OLDGEN:
{
/* we don't expect to see any of these after GC
* but they might appear during execution
*/
+ P_ q;
StgInd *ind = stgCast(StgInd*,p);
ASSERT(LOOKS_LIKE_PTR(ind->indirectee));
- return sizeofW(StgInd);
+ q = (P_)p + sizeofW(StgInd);
+ while (!*q) { q++; }; /* skip padding words (see GC.c: evacuate())*/
+ return q - (P_)p;
}
case RET_BCO:
case MUT_ARR_WORDS:
return arr_words_sizeW(stgCast(StgArrWords*,p));
- case ARR_PTRS:
case MUT_ARR_PTRS:
case MUT_ARR_PTRS_FROZEN:
{
- StgArrPtrs* a = stgCast(StgArrPtrs*,p);
+ StgMutArrPtrs* a = stgCast(StgMutArrPtrs*,p);
nat i;
for (i = 0; i < a->ptrs; i++) {
- ASSERT(LOOKS_LIKE_PTR(payloadPtr(a,i)));
+ ASSERT(LOOKS_LIKE_PTR(a->payload[i]));
}
- return arr_ptrs_sizeW(a);
+ return mut_arr_ptrs_sizeW(a);
}
case TSO:
- checkTSO((StgTSO *)p, heap_step);
+ checkTSO((StgTSO *)p);
return tso_sizeW((StgTSO *)p);
case BLOCKED_FETCH:
After garbage collection, the live heap is in a state where we can
run through and check that all the pointers point to the right
- place.
+ place. This function starts at a given position and sanity-checks
+ all the objects in the remainder of the chain.
-------------------------------------------------------------------------- */
extern void
-checkHeap(bdescr *bd, nat step)
+checkHeap(bdescr *bd, StgPtr start)
{
StgPtr p;
- heap_step = step;
+ if (start == NULL) {
+ p = bd->start;
+ } else {
+ p = start;
+ }
while (bd != NULL) {
- p = bd->start;
while (p < bd->free) {
nat size = checkClosure(stgCast(StgClosure*,p));
/* This is the smallest size of closure that can live in the heap. */
ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
p += size;
+ while (*p == 0) { p++; } /* skip over slop */
}
bd = bd->link;
+ if (bd != NULL) {
+ p = bd->start;
+ }
}
-}
+}
+
+extern void
+checkChain(bdescr *bd)
+{
+ while (bd != NULL) {
+ checkClosure((StgClosure *)bd->start);
+ bd = bd->link;
+ }
+}
/* check stack - making sure that update frames are linked correctly */
void
}
extern void
-checkTSO(StgTSO *tso, nat step)
+checkTSO(StgTSO *tso)
{
StgPtr sp = tso->sp;
StgPtr stack = tso->stack;
StgOffset stack_size = tso->stack_size;
StgPtr stack_end = stack + stack_size;
- heap_step = step;
+ if (tso->whatNext == ThreadComplete || tso->whatNext == ThreadKilled) {
+ /* The garbage collector doesn't bother following any pointers
+ * from dead threads, so don't check sanity here.
+ */
+ return;
+ }
ASSERT(stack <= sp && sp < stack_end);
ASSERT(sp <= stgCast(StgPtr,su));