diff options
Diffstat (limited to 'compiler/codeGen/StgCmmHeap.hs')
-rw-r--r-- | compiler/codeGen/StgCmmHeap.hs | 27 |
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) |