[commit: ghc] cardinality: Generate static code for nested no-free-variable thunks (ebdc6e5)

Simon Peyton Jones simonpj at microsoft.com
Thu Mar 14 14:39:01 CET 2013


Repository : http://darcs.haskell.org/ghc.git/

On branch  : cardinality

http://hackage.haskell.org/trac/ghc/changeset/ebdc6e5637643820292568d27fb93b3bc96703c3

>---------------------------------------------------------------

commit ebdc6e5637643820292568d27fb93b3bc96703c3
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Thu Mar 14 13:38:09 2013 +0000

    Generate static code for nested no-free-variable thunks
    
    You might wonder why such things can happen, or (if they do)
    why we should generate static code, but see
    Note [Nested constant closures] in StgCmmBind.
    
    I'm not quite sure why this problem has only just popped up now.

>---------------------------------------------------------------

 compiler/codeGen/StgCmmBind.hs | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/compiler/codeGen/StgCmmBind.hs b/compiler/codeGen/StgCmmBind.hs
index c98bebf..d023bcd 100644
--- a/compiler/codeGen/StgCmmBind.hs
+++ b/compiler/codeGen/StgCmmBind.hs
@@ -130,8 +130,7 @@ cgBind (StgNonRec name rhs)
   = do  { (info, fcode) <- cgRhs name rhs
         ; addBindC (cg_id info) info
         ; init <- fcode
-        ; emit init
-        }
+        ; emit init }
         -- init cannot be used in body, so slightly better to sink it eagerly
 
 cgBind (StgRec pairs)
@@ -208,9 +207,34 @@ cgRhs name (StgRhsCon cc con args)
   = buildDynCon name cc con args
 
 cgRhs name (StgRhsClosure cc bi fvs upd_flag _srt args body)
+  | null fvs   -- See Note [Nested constant closures]
+  = do { (info, fcode) <- cgTopRhsClosure Recursive name cc bi upd_flag args body 
+       ; return (info, fcode >> return mkNop) }
+  | otherwise 
   = do dflags <- getDynFlags
        mkRhsClosure dflags name cc bi (nonVoidIds fvs) upd_flag args body
 
+{- Note [Nested constant closures]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If we have
+  f x = let funny = not True 
+        in ...
+then 'funny' is a nested closure (compiled with cgRhs) that has no free vars.
+This does not happen often, because let-floating takes them all to top 
+level; but it CAN happen.  (Reason: let-floating may make a function f smaller
+so it can be inlined, so now (f True) may generate a local no-fv closure.
+This actually happened during bootsrapping GHC itself, with f=mkRdrFunBind 
+in TcGenDeriv.)
+
+If we have one of these things, AND they allocate, the heap check will
+refer to the static funny_closure; but there isn't one! (Why does the
+heap check refer to the static closure? Becuase nodeMustPointToIt is
+False, which is fair enough.)
+
+Simple solution: compile the RHS as if it was top level.  Then
+everything works.  A minor benefit is eliminating the allocation code
+too.  -}
+
 ------------------------------------------------------------------------
 --              Non-constructor right hand sides
 ------------------------------------------------------------------------





More information about the ghc-commits mailing list