Commit a586b33f authored by Matthew Pickering's avatar Matthew Pickering Committed by Marge Bot

rts: Correct handling of LARGE ARR_WORDS in LDV profiler

This implements the correct fix for #11627 by skipping over the slop
(which is zeroed) rather than adding special case logic for LARGE
ARR_WORDS which runs the risk of not performing a correct census by
ignoring any subsequent blocks.

This approach implements similar logic to that in Sanity.c
parent 1c4f18d0
...@@ -147,6 +147,14 @@ void _assertFail(const char *filename, unsigned int linenum) ...@@ -147,6 +147,14 @@ void _assertFail(const char *filename, unsigned int linenum)
#define USED_IF_NOT_THREADS #define USED_IF_NOT_THREADS
#endif #endif
#if defined(PROFILING)
#define USED_IF_PROFILING
#define USED_IF_NOT_PROFILING STG_UNUSED
#else
#define USED_IF_PROFILING STG_UNUSED
#define USED_IF_NOT_PROFILING
#endif
#define FMT_SizeT "zu" #define FMT_SizeT "zu"
#define FMT_HexSizeT "zx" #define FMT_HexSizeT "zx"
......
...@@ -542,8 +542,10 @@ void LDV_recordDead (const StgClosure *c, uint32_t size); ...@@ -542,8 +542,10 @@ void LDV_recordDead (const StgClosure *c, uint32_t size);
EXTERN_INLINE void overwritingClosure_ (StgClosure *p, EXTERN_INLINE void overwritingClosure_ (StgClosure *p,
uint32_t offset /* in words */, uint32_t offset /* in words */,
uint32_t size /* closure size, in words */); uint32_t size /* closure size, in words */,
EXTERN_INLINE void overwritingClosure_ (StgClosure *p, uint32_t offset, uint32_t size) bool prim /* Whether to call LDV_recordDead */
);
EXTERN_INLINE void overwritingClosure_ (StgClosure *p, uint32_t offset, uint32_t size, bool prim USED_IF_PROFILING)
{ {
#if ZERO_SLOP_FOR_LDV_PROF && !ZERO_SLOP_FOR_SANITY_CHECK #if ZERO_SLOP_FOR_LDV_PROF && !ZERO_SLOP_FOR_SANITY_CHECK
// see Note [zeroing slop], also #8402 // see Note [zeroing slop], also #8402
...@@ -552,7 +554,7 @@ EXTERN_INLINE void overwritingClosure_ (StgClosure *p, uint32_t offset, uint32_t ...@@ -552,7 +554,7 @@ EXTERN_INLINE void overwritingClosure_ (StgClosure *p, uint32_t offset, uint32_t
// For LDV profiling, we need to record the closure as dead // For LDV profiling, we need to record the closure as dead
#if defined(PROFILING) #if defined(PROFILING)
LDV_recordDead(p, size); if (!prim) { LDV_recordDead(p, size); };
#endif #endif
for (uint32_t i = offset; i < size; i++) { for (uint32_t i = offset; i < size; i++) {
...@@ -563,7 +565,7 @@ EXTERN_INLINE void overwritingClosure_ (StgClosure *p, uint32_t offset, uint32_t ...@@ -563,7 +565,7 @@ EXTERN_INLINE void overwritingClosure_ (StgClosure *p, uint32_t offset, uint32_t
EXTERN_INLINE void overwritingClosure (StgClosure *p); EXTERN_INLINE void overwritingClosure (StgClosure *p);
EXTERN_INLINE void overwritingClosure (StgClosure *p) EXTERN_INLINE void overwritingClosure (StgClosure *p)
{ {
overwritingClosure_(p, sizeofW(StgThunkHeader), closure_sizeW(p)); overwritingClosure_(p, sizeofW(StgThunkHeader), closure_sizeW(p), false);
} }
// Version of 'overwritingClosure' which overwrites only a suffix of a // Version of 'overwritingClosure' which overwrites only a suffix of a
...@@ -576,12 +578,14 @@ EXTERN_INLINE void overwritingClosure (StgClosure *p) ...@@ -576,12 +578,14 @@ EXTERN_INLINE void overwritingClosure (StgClosure *p)
EXTERN_INLINE void overwritingClosureOfs (StgClosure *p, uint32_t offset); EXTERN_INLINE void overwritingClosureOfs (StgClosure *p, uint32_t offset);
EXTERN_INLINE void overwritingClosureOfs (StgClosure *p, uint32_t offset) EXTERN_INLINE void overwritingClosureOfs (StgClosure *p, uint32_t offset)
{ {
overwritingClosure_(p, offset, closure_sizeW(p)); // Set prim = true because only called on ARR_WORDS with the
// shrinkMutableByteArray# primop
overwritingClosure_(p, offset, closure_sizeW(p), true);
} }
// Version of 'overwritingClosure' which takes closure size as argument. // Version of 'overwritingClosure' which takes closure size as argument.
EXTERN_INLINE void overwritingClosureSize (StgClosure *p, uint32_t size /* in words */); EXTERN_INLINE void overwritingClosureSize (StgClosure *p, uint32_t size /* in words */);
EXTERN_INLINE void overwritingClosureSize (StgClosure *p, uint32_t size) EXTERN_INLINE void overwritingClosureSize (StgClosure *p, uint32_t size)
{ {
overwritingClosure_(p, sizeofW(StgThunkHeader), size); overwritingClosure_(p, sizeofW(StgThunkHeader), size, false);
} }
...@@ -1010,19 +1010,6 @@ heapCensusChain( Census *census, bdescr *bd ) ...@@ -1010,19 +1010,6 @@ heapCensusChain( Census *census, bdescr *bd )
p = bd->start; p = bd->start;
// When we shrink a large ARR_WORDS, we do not adjust the free pointer
// of the associated block descriptor, thus introducing slop at the end
// of the object. This slop remains after GC, violating the assumption
// of the loop below that all slop has been eliminated (#11627).
// Consequently, we handle large ARR_WORDS objects as a special case.
if (bd->flags & BF_LARGE
&& get_itbl((StgClosure *)p)->type == ARR_WORDS) {
size = arr_words_sizeW((StgArrBytes *)p);
prim = true;
heapProfObject(census, (StgClosure *)p, size, prim);
continue;
}
while (p < bd->free) { while (p < bd->free) {
info = get_itbl((const StgClosure *)p); info = get_itbl((const StgClosure *)p);
prim = false; prim = false;
...@@ -1172,6 +1159,8 @@ heapCensusChain( Census *census, bdescr *bd ) ...@@ -1172,6 +1159,8 @@ heapCensusChain( Census *census, bdescr *bd )
heapProfObject(census,(StgClosure*)p,size,prim); heapProfObject(census,(StgClosure*)p,size,prim);
p += size; p += size;
/* skip over slop */
while (p < bd->free && !*p) p++; // skip slop
} }
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment