Fixes to "Retract Hp *before* checking for HpLim==0"
authorSimon Marlow <marlowsd@gmail.com>
Wed, 18 Mar 2009 11:18:47 +0000 (11:18 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Wed, 18 Mar 2009 11:18:47 +0000 (11:18 +0000)
compiler/codeGen/CgForeignCall.hs
rts/HeapStackCheck.cmm

index cf99f31..87c82cb 100644 (file)
@@ -212,7 +212,11 @@ emitLoadThreadState = do
                              bWord),
        -- SpLim = tso->stack + RESERVED_STACK_WORDS;
        CmmAssign spLim (cmmOffsetW (cmmOffset (CmmReg (CmmLocal tso)) tso_STACK)
                              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:
     ]
   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
 
 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
 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
 
 -- -----------------------------------------------------------------------------
 -- For certain types passed to foreign calls, we adjust the actual
index 1533ae0..a1b6d65 100644 (file)
@@ -26,6 +26,17 @@ import LeaveCriticalSection;
  *    - If HpLim==0, indicating that we should context-switch, we yield
  *      to the scheduler (return ThreadYielding).
  *
  *    - 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).
  *    - 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) {          \
         }                                              \
         if (HpAlloc <= BLOCK_SIZE                              \
             && bdescr_link(CurrentNursery) != NULL) {          \
+            HpAlloc = 0;                                        \
             CLOSE_NURSERY();                                   \
             CurrentNursery = bdescr_link(CurrentNursery);      \
             OPEN_NURSERY();                                    \
             CLOSE_NURSERY();                                   \
             CurrentNursery = bdescr_link(CurrentNursery);      \
             OPEN_NURSERY();                                    \