From bd78c94a3b41f8d2097efc0415fa26e0cd1140ef Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Wed, 18 Mar 2009 11:18:47 +0000 Subject: [PATCH] Fixes to "Retract Hp *before* checking for HpLim==0" --- compiler/codeGen/CgForeignCall.hs | 9 +++++++-- rts/HeapStackCheck.cmm | 12 ++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/compiler/codeGen/CgForeignCall.hs b/compiler/codeGen/CgForeignCall.hs index cf99f31..87c82cb 100644 --- a/compiler/codeGen/CgForeignCall.hs +++ b/compiler/codeGen/CgForeignCall.hs @@ -212,7 +212,11 @@ emitLoadThreadState = do bWord), -- SpLim = tso->stack + RESERVED_STACK_WORDS; CmmAssign spLim (cmmOffsetW (cmmOffset (CmmReg (CmmLocal tso)) tso_STACK) - rESERVED_STACK_WORDS) + rESERVED_STACK_WORDS), + -- HpAlloc = 0; + -- HpAlloc is assumed to be set to non-zero only by a failed + -- a heap check, see HeapStackCheck.cmm:GC_GENERIC + CmmAssign hpAlloc (CmmLit zeroCLit) ] emitOpenNursery -- and load the current cost centre stack from the TSO when profiling: @@ -267,13 +271,14 @@ stgHp = CmmReg hp stgCurrentTSO = CmmReg currentTSO stgCurrentNursery = CmmReg currentNursery -sp, spLim, hp, hpLim, currentTSO, currentNursery :: CmmReg +sp, spLim, hp, hpLim, currentTSO, currentNursery, hpAlloc :: CmmReg sp = CmmGlobal Sp spLim = CmmGlobal SpLim hp = CmmGlobal Hp hpLim = CmmGlobal HpLim currentTSO = CmmGlobal CurrentTSO currentNursery = CmmGlobal CurrentNursery +hpAlloc = CmmGlobal HpAlloc -- ----------------------------------------------------------------------------- -- For certain types passed to foreign calls, we adjust the actual diff --git a/rts/HeapStackCheck.cmm b/rts/HeapStackCheck.cmm index 1533ae0..a1b6d65 100644 --- a/rts/HeapStackCheck.cmm +++ b/rts/HeapStackCheck.cmm @@ -26,6 +26,17 @@ import LeaveCriticalSection; * - If HpLim==0, indicating that we should context-switch, we yield * to the scheduler (return ThreadYielding). * + * Note that we must leave no slop in the heap (this is a requirement + * for LDV profiling, at least), so if we just had a heap-check + * failure, then we must retract Hp by HpAlloc. How do we know + * whether there was a heap-check failure? HpLim might be zero, and + * yet we got here as a result of a stack-check failure. Hence, we + * require that HpAlloc is only non-zero if there was a heap-check + * failure, otherwise it is zero, so we can always safely subtract + * HpAlloc from Hp. + * + * Hence, HpAlloc is zeroed in LOAD_THREAD_STATE(). + * * - If the context_switch flag is set (the backup plan if setting HpLim * to 0 didn't trigger a context switch), we yield to the scheduler * (return ThreadYielding). @@ -70,6 +81,7 @@ import LeaveCriticalSection; } \ if (HpAlloc <= BLOCK_SIZE \ && bdescr_link(CurrentNursery) != NULL) { \ + HpAlloc = 0; \ CLOSE_NURSERY(); \ CurrentNursery = bdescr_link(CurrentNursery); \ OPEN_NURSERY(); \ -- 1.7.10.4