X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FRetainerProfile.c;h=1ff0027f8af7a611dcc65b743c83848b3d7cb0c2;hb=423d477bfecd490de1449c59325c8776f91d7aac;hp=916ce9090db264eff143dd07283953a26f1cb05f;hpb=557947d3f93e11285e36423ddb08d859af60ab47;p=ghc-hetmet.git diff --git a/ghc/rts/RetainerProfile.c b/ghc/rts/RetainerProfile.c index 916ce90..1ff0027 100644 --- a/ghc/rts/RetainerProfile.c +++ b/ghc/rts/RetainerProfile.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: RetainerProfile.c,v 1.7 2003/02/22 04:51:52 sof Exp $ + * $Id: RetainerProfile.c,v 1.11 2004/08/13 13:10:28 simonmar Exp $ * * (c) The GHC Team, 2001 * Author: Sungwoo Park @@ -10,6 +10,13 @@ #ifdef PROFILING +// Turn off inlining when debugging - it obfuscates things +#ifdef DEBUG +#define INLINE +#else +#define INLINE inline +#endif + #include #include "Rts.h" @@ -19,11 +26,9 @@ #include "Schedule.h" #include "Printer.h" #include "Storage.h" -#include "StoragePriv.h" #include "RtsFlags.h" #include "Weak.h" #include "Sanity.h" -#include "StablePriv.h" #include "Profiling.h" #include "Stats.h" #include "BlockAlloc.h" @@ -104,6 +109,7 @@ typedef enum { posTypeStep, posTypePtrs, posTypeSRT, + posTypeLargeSRT, } nextPosType; typedef union { @@ -126,8 +132,15 @@ typedef union { // SRT struct { StgClosure **srt; - StgClosure **srt_end; + StgWord srt_bitmap; } srt; + + // Large SRT + struct { + StgLargeSRT *srt; + StgWord offset; + } large_srt; + } nextPos; typedef struct { @@ -158,7 +171,7 @@ typedef struct { the topmost element on the previous block group so as to satisfy the invariants described above. */ -bdescr *firstStack = NULL; +static bdescr *firstStack = NULL; static bdescr *currentStack; static stackElement *stackBottom, *stackTop, *stackLimit; @@ -194,7 +207,7 @@ static int stackSize, maxStackSize; * Invariants: * currentStack->link == s. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void newStackBlock( bdescr *bd ) { currentStack = bd; @@ -209,7 +222,7 @@ newStackBlock( bdescr *bd ) * Invariants: * s->link == currentStack. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void returnToOldStack( bdescr *bd ) { currentStack = bd; @@ -251,17 +264,34 @@ closeTraverseStack( void ) /* ----------------------------------------------------------------------------- * Returns rtsTrue if the whole stack is empty. * -------------------------------------------------------------------------- */ -static inline rtsBool +static INLINE rtsBool isEmptyRetainerStack( void ) { return (firstStack == currentStack) && stackTop == stackLimit; } /* ----------------------------------------------------------------------------- + * Returns size of stack + * -------------------------------------------------------------------------- */ +#ifdef DEBUG +lnat +retainerStackBlocks( void ) +{ + bdescr* bd; + lnat res = 0; + + for (bd = firstStack; bd != NULL; bd = bd->link) + res += bd->blocks; + + return res; +} +#endif + +/* ----------------------------------------------------------------------------- * Returns rtsTrue if stackTop is at the stack boundary of the current stack, * i.e., if the current stack chunk is empty. * -------------------------------------------------------------------------- */ -static inline rtsBool +static INLINE rtsBool isOnBoundary( void ) { return stackTop == currentStackBoundary; @@ -272,7 +302,7 @@ isOnBoundary( void ) * Invariants: * payload[] begins with ptrs pointers followed by non-pointers. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void init_ptrs( stackPos *info, nat ptrs, StgPtr payload ) { info->type = posTypePtrs; @@ -284,7 +314,7 @@ init_ptrs( stackPos *info, nat ptrs, StgPtr payload ) /* ----------------------------------------------------------------------------- * Find the next object from *info. * -------------------------------------------------------------------------- */ -static inline StgClosure * +static INLINE StgClosure * find_ptrs( stackPos *info ) { if (info->next.ptrs.pos < info->next.ptrs.ptrs) { @@ -297,43 +327,92 @@ find_ptrs( stackPos *info ) /* ----------------------------------------------------------------------------- * Initializes *info from SRT information stored in *infoTable. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void init_srt_fun( stackPos *info, StgFunInfoTable *infoTable ) { - info->type = posTypeSRT; - info->next.srt.srt = (StgClosure **)(infoTable->srt); - info->next.srt.srt_end = info->next.srt.srt + infoTable->i.srt_len; + if (infoTable->i.srt_bitmap == (StgHalfWord)(-1)) { + info->type = posTypeLargeSRT; + info->next.large_srt.srt = (StgLargeSRT *)infoTable->f.srt; + info->next.large_srt.offset = 0; + } else { + info->type = posTypeSRT; + info->next.srt.srt = (StgClosure **)(infoTable->f.srt); + info->next.srt.srt_bitmap = infoTable->i.srt_bitmap; + } } -static inline void +static INLINE void init_srt_thunk( stackPos *info, StgThunkInfoTable *infoTable ) { - info->type = posTypeSRT; - info->next.srt.srt = (StgClosure **)(infoTable->srt); - info->next.srt.srt_end = info->next.srt.srt + infoTable->i.srt_len; + if (infoTable->i.srt_bitmap == (StgHalfWord)(-1)) { + info->type = posTypeLargeSRT; + info->next.large_srt.srt = (StgLargeSRT *)infoTable->srt; + info->next.large_srt.offset = 0; + } else { + info->type = posTypeSRT; + info->next.srt.srt = (StgClosure **)(infoTable->srt); + info->next.srt.srt_bitmap = infoTable->i.srt_bitmap; + } } /* ----------------------------------------------------------------------------- * Find the next object from *info. * -------------------------------------------------------------------------- */ -static inline StgClosure * +static INLINE StgClosure * find_srt( stackPos *info ) { StgClosure *c; + StgWord bitmap; - if (info->next.srt.srt < info->next.srt.srt_end) { - // See scavenge_srt() in GC.c for details. + if (info->type == posTypeSRT) { + // Small SRT bitmap + bitmap = info->next.srt.srt_bitmap; + while (bitmap != 0) { + if ((bitmap & 1) != 0) { #ifdef ENABLE_WIN32_DLL_SUPPORT - 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 - info->next.srt.srt++; - return c; - } else { + 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; } } @@ -353,7 +432,7 @@ find_srt( stackPos *info ) * there cannot be any stack objects. * Note: SRTs are considered to be children as well. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) { stackElement se; @@ -496,7 +575,7 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) break; case FUN_STATIC: // *c is a heap object. - ASSERT(get_itbl(c)->srt_len != 0); + ASSERT(get_itbl(c)->srt_bitmap != 0); case FUN_0_1: case FUN_0_2: fun_srt_only: @@ -508,7 +587,7 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) // SRT only case THUNK_STATIC: - ASSERT(get_itbl(c)->srt_len != 0); + ASSERT(get_itbl(c)->srt_bitmap != 0); case THUNK_0_1: case THUNK_0_2: thunk_srt_only: @@ -596,7 +675,7 @@ push( StgClosure *c, retainer c_child_r, StgClosure **first_child ) * executed at the end of popOff() in necessary. Since popOff() is * likely to be executed quite often while popOffReal() is not, we * separate popOffReal() from popOff(), which is declared as an - * inline function (for the sake of execution speed). popOffReal() + * INLINE function (for the sake of execution speed). popOffReal() * is called only within popOff() and nowhere else. * -------------------------------------------------------------------------- */ static void @@ -646,7 +725,7 @@ popOffReal(void) #endif } -static inline void +static INLINE void popOff(void) { #ifdef DEBUG_RETAINER // fprintf(stderr, "\tpopOff(): stackTop = 0x%x, currentStackBoundary = 0x%x\n", stackTop, currentStackBoundary); @@ -688,7 +767,7 @@ popOff(void) { * It is okay to call this function even when the current stack chunk * is empty. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void pop( StgClosure **c, StgClosure **cp, retainer *r ) { stackElement *se; @@ -897,7 +976,7 @@ endRetainerProfiling( void ) * We have to perform an XOR (^) operation each time a closure is examined. * The reason is that we do not know when a closure is visited last. * -------------------------------------------------------------------------- */ -static inline void +static INLINE void maybeInitRetainerSet( StgClosure *c ) { if (!isRetainerSetFieldValid(c)) { @@ -908,7 +987,7 @@ maybeInitRetainerSet( StgClosure *c ) /* ----------------------------------------------------------------------------- * Returns rtsTrue if *c is a retainer. * -------------------------------------------------------------------------- */ -static inline rtsBool +static INLINE rtsBool isRetainer( StgClosure *c ) { switch (get_itbl(c)->type) { @@ -1034,7 +1113,7 @@ isRetainer( StgClosure *c ) * re-initialize the hash table. * See refreshAllRetainerSet() in RetainerSet.c. * -------------------------------------------------------------------------- */ -static inline retainer +static INLINE retainer getRetainerFrom( StgClosure *c ) { ASSERT(isRetainer(c)); @@ -1058,7 +1137,7 @@ getRetainerFrom( StgClosure *c ) * c != NULL * s != NULL * -------------------------------------------------------------------------- */ -static inline void +static INLINE void associate( StgClosure *c, RetainerSet *s ) { // StgWord has the same size as pointers, so the following type @@ -1067,40 +1146,6 @@ associate( StgClosure *c, RetainerSet *s ) } /* ----------------------------------------------------------------------------- - * Call retainClosure for each of the closures in an SRT. - * ------------------------------------------------------------------------- */ - -static inline void -retainSRT (StgClosure **srt, nat srt_len, StgClosure *c, retainer c_child_r) -{ - StgClosure **srt_end; - - srt_end = srt + srt_len; - - for (; srt < srt_end; srt++) { - /* Special-case to handle references to closures hiding out in DLLs, since - double indirections required to get at those. The code generator knows - which is which when generating the SRT, so it stores the (indirect) - reference to the DLL closure in the table by first adding one to it. - We check for this here, and undo the addition before evacuating it. - - If the SRT entry hasn't got bit 0 set, the SRT entry points to a - closure that's fixed at link-time, and no extra magic is required. - */ -#ifdef ENABLE_WIN32_DLL_SUPPORT - if ( (unsigned long)(*srt) & 0x1 ) { - retainClosure(*stgCast(StgClosure**,(stgCast(unsigned long, *srt) & ~0x1)), - c, c_child_r); - } else { - retainClosure(*srt,c,c_child_r); - } -#else - retainClosure(*srt,c,c_child_r); -#endif - } -} - -/* ----------------------------------------------------------------------------- Call retainClosure for each of the closures covered by a large bitmap. -------------------------------------------------------------------------- */ @@ -1128,7 +1173,7 @@ retain_large_bitmap (StgPtr p, StgLargeBitmap *large_bitmap, nat size, } } -static inline StgPtr +static INLINE StgPtr retain_small_bitmap (StgPtr p, nat size, StgWord bitmap, StgClosure *c, retainer c_child_r) { @@ -1144,6 +1189,68 @@ retain_small_bitmap (StgPtr p, nat size, StgWord bitmap, } /* ----------------------------------------------------------------------------- + * Call retainClosure for each of the closures in an SRT. + * ------------------------------------------------------------------------- */ + +static void +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; + } + } +} + +static INLINE void +retainSRT (StgClosure **srt, nat srt_bitmap, StgClosure *c, retainer c_child_r) +{ + nat bitmap; + StgClosure **p; + + bitmap = srt_bitmap; + p = srt; + + if (bitmap == (StgHalfWord)(-1)) { + retain_large_srt_bitmap( (StgLargeSRT *)srt, c, c_child_r ); + return; + } + + while (bitmap != 0) { + if ((bitmap & 1) != 0) { +#ifdef ENABLE_WIN32_DLL_SUPPORT + if ( (unsigned long)(*srt) & 0x1 ) { + retainClosure(*stgCast(StgClosure**,(stgCast(unsigned long, *srt) & ~0x1)), + c, c_child_r); + } else { + retainClosure(*srt,c,c_child_r); + } +#else + retainClosure(*srt,c,c_child_r); +#endif + } + p++; + bitmap = bitmap >> 1; + } +} + +/* ----------------------------------------------------------------------------- * Process all the objects in the stack chunk from stackStart to stackEnd * with *c and *c_child_r being their parent and their most recent retainer, * respectively. Treat stackOptionalFun as another child of *c if it is @@ -1215,7 +1322,7 @@ retainStack( StgClosure *c, retainer c_child_r, p = retain_small_bitmap(p, size, bitmap, c, c_child_r); follow_srt: - retainSRT((StgClosure **)info->srt, info->i.srt_len, c, c_child_r); + retainSRT((StgClosure **)info->srt, info->i.srt_bitmap, c, c_child_r); continue; case RET_BCO: { @@ -1248,16 +1355,16 @@ retainStack( StgClosure *c, retainer c_child_r, dyn = ((StgRetDyn *)p)->liveness; // traverse the bitmap first - bitmap = GET_LIVENESS(dyn); + bitmap = RET_DYN_LIVENESS(dyn); p = (P_)&((StgRetDyn *)p)->payload[0]; - size = RET_DYN_SIZE; + size = RET_DYN_BITMAP_SIZE; p = retain_small_bitmap(p, size, bitmap, c, c_child_r); // skip over the non-ptr words - p += GET_NONPTRS(dyn); + p += RET_DYN_NONPTRS(dyn) + RET_DYN_NONPTR_REGS_SIZE; // follow the ptr words - for (size = GET_PTRS(dyn); size > 0; size--) { + for (size = RET_DYN_PTRS(dyn); size > 0; size--) { retainClosure((StgClosure *)*p, c, c_child_r); p++; } @@ -1272,21 +1379,21 @@ retainStack( StgClosure *c, retainer c_child_r, fun_info = get_fun_itbl(ret_fun->fun); p = (P_)&ret_fun->payload; - switch (fun_info->fun_type) { + switch (fun_info->f.fun_type) { case ARG_GEN: - bitmap = BITMAP_BITS(fun_info->bitmap); - size = BITMAP_SIZE(fun_info->bitmap); + bitmap = BITMAP_BITS(fun_info->f.bitmap); + size = BITMAP_SIZE(fun_info->f.bitmap); p = retain_small_bitmap(p, size, bitmap, c, c_child_r); break; case ARG_GEN_BIG: - size = ((StgLargeBitmap *)fun_info->bitmap)->size; - retain_large_bitmap(p, (StgLargeBitmap *)fun_info->bitmap, + size = ((StgLargeBitmap *)fun_info->f.bitmap)->size; + retain_large_bitmap(p, (StgLargeBitmap *)fun_info->f.bitmap, size, c, c_child_r); p += size; break; default: - bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->fun_type]); - size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->fun_type]); + 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; } @@ -1314,7 +1421,7 @@ retainStack( StgClosure *c, retainer c_child_r, * Call retainClosure for each of the children of a PAP/AP * ------------------------------------------------------------------------- */ -static inline StgPtr +static INLINE StgPtr retain_PAP (StgPAP *pap, retainer c_child_r) { StgPtr p; @@ -1328,14 +1435,14 @@ retain_PAP (StgPAP *pap, retainer c_child_r) p = (StgPtr)pap->payload; size = pap->n_args; - switch (fun_info->fun_type) { + switch (fun_info->f.fun_type) { case ARG_GEN: - bitmap = BITMAP_BITS(fun_info->bitmap); + bitmap = BITMAP_BITS(fun_info->f.bitmap); p = retain_small_bitmap(p, pap->n_args, bitmap, (StgClosure *)pap, c_child_r); break; case ARG_GEN_BIG: - retain_large_bitmap(p, (StgLargeBitmap *)fun_info->bitmap, + retain_large_bitmap(p, (StgLargeBitmap *)fun_info->f.bitmap, size, (StgClosure *)pap, c_child_r); p += size; break; @@ -1345,7 +1452,7 @@ retain_PAP (StgPAP *pap, retainer c_child_r) p += size; break; default: - bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->fun_type]); + bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); p = retain_small_bitmap(p, pap->n_args, bitmap, (StgClosure *)pap, c_child_r); break; @@ -1479,7 +1586,7 @@ inner_loop: goto loop; case THUNK_STATIC: case FUN_STATIC: - if (get_itbl(c)->srt_len == 0) { + if (get_itbl(c)->srt_bitmap == 0) { // No need to compute the retainer set; no dynamic objects // are reachable from *c. //