#367: Infinite loops can hang Concurrent Haskell ------------------------------------------+--------------------------------- Reporter: simonpj | Owner: ezyang Type: bug | Status: new Priority: lowest | Milestone: _|_ Component: Compiler | Version: 6.4.1 Resolution: None | Keywords: scheduler allocation Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: Incorrect result at runtime | Difficulty: Unknown Testcase: | Blockedby: Blocking: | Related: ------------------------------------------+---------------------------------
Comment(by ezyang): Here is a variant of the patch that only does heap checks when not returning (since it's not possible to "infinitely return".) We do much better on runtime and binary size; maybe good enough to ship by default! {{{ diff --git a/compiler/codeGen/StgCmmHeap.hs b/compiler/codeGen/StgCmmHeap.hs index fb37391..4c53bc2 100644 --- a/compiler/codeGen/StgCmmHeap.hs +++ b/compiler/codeGen/StgCmmHeap.hs @@ -371,7 +371,7 @@ entryHeapCheck cl_info nodeSet arity args code loop_id <- newLabelC emitLabel loop_id - heapCheck True (gc_call updfr_sz <*> mkBranch loop_id) code + heapCheck True True (gc_call updfr_sz <*> mkBranch loop_id) code {- -- This code is slightly outdated now and we could easily keep the above @@ -461,7 +461,7 @@ cannedGCReturnsTo :: Bool -> CmmExpr -> [LocalReg] -> Label -> ByteOff cannedGCReturnsTo cont_on_stack gc regs lret off code = do dflags <- getDynFlags updfr_sz <- getUpdFrameOff - heapCheck False (gc_call dflags gc updfr_sz) code + heapCheck False False (gc_call dflags gc updfr_sz) code where reg_exprs = map (CmmReg . CmmLocal) regs -- Note [stg_gc arguments] @@ -476,7 +476,7 @@ genericGC code lretry <- newLabelC emitLabel lretry call <- mkCall generic_gc (GC, GC) [] [] updfr_sz (0,[]) - heapCheck False (call <*> mkBranch lretry) code + heapCheck False True (call <*> mkBranch lretry) code cannedGCEntryPoint :: DynFlags -> [LocalReg] -> Maybe CmmExpr cannedGCEntryPoint dflags regs @@ -524,22 +524,23 @@ mkGcLabel :: String -> CmmExpr mkGcLabel s = CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit s))) ------------------------------- -heapCheck :: Bool -> CmmAGraph -> FCode a -> FCode a -heapCheck checkStack do_gc code +heapCheck :: Bool -> Bool -> CmmAGraph -> FCode a -> FCode a +heapCheck checkStack checkYield do_gc code = getHeapUsage $ \ hpHw -> -- Emit heap checks, but be sure to do it lazily so -- that the conditionals on hpHw don't cause a black hole - do { codeOnly $ do_checks checkStack hpHw do_gc + do { codeOnly $ do_checks checkStack checkYield hpHw do_gc ; tickyAllocHeap hpHw ; doGranAllocate hpHw ; setRealHp hpHw ; code } do_checks :: Bool -- Should we check the stack? + -> Bool -- Should we check for preemption? -> WordOff -- Heap headroom -> CmmAGraph -- What to do on failure -> FCode () -do_checks checkStack alloc do_gc = do +do_checks checkStack checkYield alloc do_gc = do dflags <- getDynFlags let alloc_lit = mkIntExpr dflags (alloc * wORD_SIZE dflags) -- Bytes @@ -557,15 +558,22 @@ do_checks checkStack alloc do_gc = do hp_oflo = CmmMachOp (mo_wordUGt dflags) [CmmReg hpReg, CmmReg (CmmGlobal HpLim)] + -- Yielding if HpLim == 0 + yielding = CmmMachOp (mo_wordEq dflags) + [CmmReg (CmmGlobal HpLim), CmmLit (zeroCLit dflags)] + alloc_n = mkAssign (CmmGlobal HpAlloc) alloc_lit gc_id <- newLabelC when checkStack $ do emit =<< mkCmmIfGoto sp_oflo gc_id - when (alloc /= 0) $ do - emitAssign hpReg bump_hp - emit =<< mkCmmIfThen hp_oflo (alloc_n <*> mkBranch gc_id) + if (alloc /= 0) + then do + emitAssign hpReg bump_hp + emit =<< mkCmmIfThen hp_oflo (alloc_n <*> mkBranch gc_id) + else do + emit =<< mkCmmIfGoto yielding gc_id emitOutOfLine gc_id $ do_gc -- this is expected to jump back somewhere }}} {{{ -------------------------------------------------------------------------------- Program Size Allocs Runtime Elapsed TotalMem -------------------------------------------------------------------------------- anna +5.5% +0.0% 0.13 0.13 +0.0% ansi +6.0% +0.0% 0.00 0.00 +0.0% atom +6.0% +0.0% +0.0% +0.3% +0.0% awards +6.0% +0.0% 0.00 0.00 +0.0% banner +5.9% +0.0% 0.00 0.00 +0.0% bernouilli +6.0% +0.0% +0.3% +0.3% +0.0% boyer +5.9% +0.0% 0.06 0.06 +0.0% boyer2 +5.9% +0.0% 0.01 0.01 +0.0% bspt +5.8% +0.0% 0.02 0.02 +0.0% cacheprof +5.7% -0.1% -0.3% -0.3% +0.0% calendar +6.0% +0.0% 0.00 0.00 +0.0% cichelli +6.0% +0.0% 0.10 0.10 +0.0% circsim +6.0% +0.0% +1.0% +1.0% +0.0% clausify +6.0% +0.0% 0.05 0.05 +0.0% comp_lab_zift +6.0% +0.0% +2.1% +1.6% +0.0% compress +6.0% +0.0% +0.0% +0.0% +0.0% compress2 +6.0% +0.0% +0.0% +0.0% +0.0% constraints +6.0% +0.0% +0.9% +0.9% +0.0% cryptarithm1 +6.0% +0.0% -2.7% -2.8% +0.0% cryptarithm2 +6.0% +0.0% 0.02 0.02 +0.0% cse +6.0% +0.0% 0.00 0.00 +0.0% eliza +5.9% +0.0% 0.00 0.00 +0.0% event +6.0% +0.0% 0.17 0.17 +0.0% exp3_8 +6.0% +0.0% +0.0% -0.3% +0.0% expert +5.9% +0.0% 0.00 0.00 +0.0% fem +5.9% +0.0% 0.03 0.03 +0.0% fft +6.0% +0.0% 0.05 0.05 +0.0% fft2 +6.0% +0.0% 0.08 0.08 +0.0% fibheaps +6.0% +0.0% 0.04 0.04 +0.0% fish +6.0% +0.0% 0.03 0.03 +0.0% fluid +5.8% +0.0% 0.01 0.01 +0.0% fulsom +5.9% +0.0% +1.7% +1.0% +0.9% gamteb +6.0% +0.0% 0.06 0.06 +0.0% gcd +6.0% +0.0% 0.04 0.04 +0.0% gen_regexps +6.0% +0.0% 0.00 0.00 +0.0% genfft +6.0% +0.0% 0.04 0.04 +0.0% gg +5.9% +0.0% 0.02 0.02 +0.0% grep +5.9% +0.0% 0.00 0.00 +0.0% hidden +5.9% +0.0% +8.9% +9.3% +0.0% hpg +5.9% +0.0% 0.16 0.16 +0.0% ida +6.0% +0.0% 0.13 0.13 +0.0% infer +5.9% +0.0% 0.08 0.08 +0.0% integer +6.0% +0.0% +1.1% +1.0% +0.0% integrate +6.0% +0.0% -4.9% -4.7% +0.0% knights +6.0% +0.0% 0.01 0.01 +0.0% lcss +6.0% +0.0% +0.0% +0.0% +0.0% life +6.0% +0.0% +5.3% +4.6% +0.0% lift +6.0% +0.0% 0.00 0.00 +0.0% listcompr +6.0% +0.0% 0.11 0.11 +0.0% listcopy +6.0% +0.0% 0.12 0.12 +0.0% maillist +6.0% +0.0% 0.10 0.10 +1.7% mandel +6.0% +0.0% 0.09 0.09 +0.0% mandel2 +6.0% +0.0% 0.01 0.01 +0.0% minimax +6.0% +0.0% 0.01 0.01 +0.0% mkhprog +6.0% +0.0% 0.01 0.01 +0.0% multiplier +6.0% +0.0% 0.15 0.15 +0.0% nucleic2 +6.0% +0.0% 0.08 0.08 +0.0% para +6.0% +0.0% -0.2% -0.0% +0.0% paraffins +6.0% +0.0% 0.11 0.11 +0.0% parser +5.8% +0.0% 0.04 0.04 +0.0% parstof +5.7% +0.0% 0.01 0.01 +0.0% pic +5.9% +0.0% 0.02 0.02 +0.0% power +6.0% +0.0% +3.1% +2.8% +0.0% pretty +6.0% +0.0% 0.00 0.00 +0.0% primes +6.0% +0.0% 0.08 0.08 +0.0% primetest +6.0% +0.0% 0.14 0.14 +0.0% prolog +6.0% +0.0% 0.01 0.01 +0.0% puzzle +6.0% +0.0% 0.18 0.18 +0.0% queens +6.0% +0.0% 0.03 0.03 +0.0% reptile +5.8% +0.0% 0.02 0.02 +0.0% rewrite +6.0% +0.0% 0.02 0.02 +0.0% rfib +6.0% +0.0% 0.02 0.02 +0.0% rsa +6.0% +0.0% 0.04 0.04 +0.0% scc +6.0% +0.0% 0.00 0.00 +0.0% sched +6.0% +0.0% 0.03 0.03 +0.0% scs +5.9% +0.0% +1.5% +1.6% +0.0% simple +5.7% +0.0% +1.0% +1.8% +0.0% solid +5.9% +0.0% 0.17 0.17 +0.0% sorting +6.0% +0.0% 0.00 0.00 +0.0% sphere +6.0% +0.0% 0.08 0.08 +0.0% symalg +6.0% +0.0% 0.02 0.02 +0.0% tak +6.0% +0.0% 0.02 0.02 +0.0% transform +5.9% +0.0% -6.7% -6.7% +0.0% treejoin +6.0% +0.0% -0.3% -0.3% +0.0% typecheck +5.9% +0.0% +0.5% +1.1% +0.0% veritas +5.4% +0.0% 0.01 0.01 +0.0% wang +6.0% +0.0% 0.14 0.14 +0.0% wave4main +6.0% +0.0% +1.1% +0.9% +0.0% wheel-sieve1 +6.0% +0.0% +4.3% +4.6% +0.0% wheel-sieve2 +6.0% +0.0% +1.0% +1.0% +0.0% x2n1 +6.0% +0.0% 0.01 0.01 +0.0% -------------------------------------------------------------------------------- Min +5.4% -0.1% -6.7% -6.7% +0.0% Max +6.0% +0.0% +8.9% +9.3% +1.7% Geometric Mean +5.9% -0.0% +0.7% +0.7% +0.0% }}} -- Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/367#comment:24> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler _______________________________________________ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs