summaryrefslogtreecommitdiff
path: root/compiler/codeGen/StgCmmHeap.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/codeGen/StgCmmHeap.hs')
-rw-r--r--compiler/codeGen/StgCmmHeap.hs27
1 files changed, 25 insertions, 2 deletions
diff --git a/compiler/codeGen/StgCmmHeap.hs b/compiler/codeGen/StgCmmHeap.hs
index f4c58e95e1..1d1100c6be 100644
--- a/compiler/codeGen/StgCmmHeap.hs
+++ b/compiler/codeGen/StgCmmHeap.hs
@@ -533,6 +533,27 @@ heapStackCheckGen stk_hwm mb_bytes
call <- mkCall generic_gc (GC, GC) [] [] updfr_sz []
do_checks stk_hwm False mb_bytes (call <*> mkBranch lretry)
+-- Note [Single stack check]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- When compiling a function we can determine how much stack space it will
+-- use. We therefore need to perform only a single stack check at the beginning
+-- of a function to see if we have enough stack space. Instead of referring
+-- directly to Sp - as we used to do in the past - the code generator uses
+-- (old + 0) in the stack check. Stack layout phase turns (old + 0) into Sp.
+--
+-- The idea here is that, while we need to perform only one stack check for
+-- each function, we could in theory place more stack checks later in the
+-- function. They would be redundant, but not incorrect (in a sense that they
+-- should not change program behaviour). We need to make sure however that a
+-- stack check inserted after incrementing the stack pointer checks for a
+-- respectively smaller stack space. This would not be the case if the code
+-- generator produced direct references to Sp. By referencing (old + 0) we make
+-- sure that we always check for a correct amount of stack: when converting
+-- (old + 0) to Sp the stack layout phase takes into account changes already
+-- made to stack pointer. The idea for this change came from observations made
+-- while debugging #8275.
+
do_checks :: Maybe CmmExpr -- Should we check the stack?
-> Bool -- Should we check for preemption?
-> Maybe CmmExpr -- Heap headroom (bytes)
@@ -547,11 +568,13 @@ do_checks mb_stk_hwm checkYield mb_alloc_lit do_gc = do
bump_hp = cmmOffsetExprB dflags (CmmReg hpReg) alloc_lit
- -- Sp overflow if (Sp - CmmHighStack < SpLim)
+ -- Sp overflow if ((old + 0) - CmmHighStack < SpLim)
+ -- At the beginning of a function old + 0 = Sp
+ -- See Note [Single stack check]
sp_oflo sp_hwm =
CmmMachOp (mo_wordULt dflags)
[CmmMachOp (MO_Sub (typeWidth (cmmRegType dflags spReg)))
- [CmmReg spReg, sp_hwm],
+ [CmmStackSlot Old 0, sp_hwm],
CmmReg spLimReg]
-- Hp overflow if (Hp > HpLim)