fix haddock submodule pointer
[ghc-hetmet.git] / compiler / codeGen / CgClosure.lhs
index fd85115..d158bf7 100644 (file)
@@ -31,9 +31,8 @@ import CgCallConv
 import CgUtils
 import ClosureInfo
 import SMRep
-import MachOp
-import Cmm
-import CmmUtils
+import OldCmm
+import OldCmmUtils
 import CLabel
 import StgSyn
 import CostCentre      
@@ -43,9 +42,13 @@ import Module
 import ListSetOps
 import Util
 import BasicTypes
+import StaticFlags
+import DynFlags
 import Constants
 import Outputable
 import FastString
+
+import Data.List
 \end{code}
 
 %********************************************************
@@ -61,21 +64,20 @@ They should have no free variables.
 cgTopRhsClosure :: Id
                -> CostCentreStack      -- Optional cost centre annotation
                -> StgBinderInfo
-               -> SRT
                -> UpdateFlag
                -> [Id]         -- Args
                -> StgExpr
                -> FCode (Id, CgIdInfo)
 
-cgTopRhsClosure id ccs binder_info srt upd_flag args body = do
+cgTopRhsClosure id ccs binder_info upd_flag args body = do
   {    -- LAY OUT THE OBJECT
     let name = idName id
   ; lf_info  <- mkClosureLFInfo id TopLevel [] upd_flag args
-  ; srt_info <- getSRTInfo name srt
+  ; srt_info <- getSRTInfo
   ; mod_name <- getModuleName
   ; let descr         = closureDescription mod_name name
        closure_info  = mkClosureInfo True id lf_info 0 0 srt_info descr
-       closure_label = mkLocalClosureLabel name
+       closure_label = mkLocalClosureLabel name $ idCafInfo id
        cg_id_info    = stableIdInfo id (mkLblExpr closure_label) lf_info
        closure_rep   = mkStaticClosureFields closure_info ccs True []
 
@@ -107,7 +109,7 @@ cgStdRhsClosure
        -> [StgArg]             -- payload
        -> FCode (Id, CgIdInfo)
 
-cgStdRhsClosure bndr cc bndr_info fvs args body lf_info payload 
+cgStdRhsClosure bndr cc _bndr_info _fvs args body lf_info payload 
   = do -- AHA!  A STANDARD-FORM THUNK
   {    -- LAY OUT THE OBJECT
     amodes <- getArgAmodes payload
@@ -136,14 +138,13 @@ Here's the general case.
 cgRhsClosure   :: Id
                -> CostCentreStack      -- Optional cost centre annotation
                -> StgBinderInfo
-               -> SRT
                -> [Id]                 -- Free vars
                -> UpdateFlag
                -> [Id]                 -- Args
                -> StgExpr
                -> FCode (Id, CgIdInfo)
 
-cgRhsClosure bndr cc bndr_info srt fvs upd_flag args body = do
+cgRhsClosure bndr cc bndr_info fvs upd_flag args body = do
   {    -- LAY OUT THE OBJECT
        -- If the binder is itself a free variable, then don't store
        -- it in the closure.  Instead, just bind it to Node on entry.
@@ -154,14 +155,13 @@ cgRhsClosure bndr cc bndr_info srt fvs upd_flag args body = do
        -- Node points to it...
     let
        name         = idName bndr
-       is_elem      = isIn "cgRhsClosure"
-       bndr_is_a_fv = bndr `is_elem` fvs
+       bndr_is_a_fv = bndr `elem` fvs
        reduced_fvs | bndr_is_a_fv = fvs `minusList` [bndr]
                    | otherwise    = fvs
 
   ; lf_info <- mkClosureLFInfo bndr NotTopLevel fvs upd_flag args
   ; fv_infos <- mapFCs getCgIdInfo reduced_fvs
-  ; srt_info <- getSRTInfo name srt
+  ; srt_info <- getSRTInfo
   ; mod_name <- getModuleName
   ; let        bind_details :: [(CgIdInfo, VirtualHpOffset)]
        (tot_wds, ptr_wds, bind_details) 
@@ -177,7 +177,14 @@ cgRhsClosure bndr cc bndr_info srt fvs upd_flag args body = do
        -- BUILD ITS INFO TABLE AND CODE
   ; forkClosureBody (do
        {       -- Bind the fvs
-         let bind_fv (info, offset) 
+         let 
+              -- A function closure pointer may be tagged, so we
+              -- must take it into account when accessing the free variables.
+              mbtag       = tagForArity (length args)
+              bind_fv (info, offset)
+                | Just tag <- mbtag
+                = bindNewToUntagNode (cgIdInfoId info) offset (cgIdInfoLF info) tag
+                | otherwise
                = bindNewToNode (cgIdInfoId info) offset (cgIdInfoLF info)
        ; mapCs bind_fv bind_details
 
@@ -233,10 +240,10 @@ So it should set up an update frame (if it is shared).
 NB: Thunks cannot have a primitive type!
 
 \begin{code}
-closureCodeBody binder_info cl_info cc [{- No args i.e. thunk -}] body = do
+closureCodeBody _binder_info cl_info cc [{- No args i.e. thunk -}] body = do
   { body_absC <- getCgStmts $ do
        { tickyEnterThunk cl_info
-       ; ldvEnter (CmmReg nodeReg)  -- NB: Node always points when profiling
+       ; ldvEnterClosure cl_info  -- NB: Node always points when profiling
        ; thunkWrapper cl_info $ do
                -- We only enter cc after setting up update so
                -- that cc of enclosing scope will be recorded
@@ -257,7 +264,7 @@ argSatisfactionCheck (by calling fetchAndReschedule).  There info if
 Node points to closure is available. -- HWL
 
 \begin{code}
-closureCodeBody binder_info cl_info cc args body 
+closureCodeBody _binder_info cl_info cc args body 
   = ASSERT( length args > 0 )
   do {         -- Get the current virtual Sp (it might not be zero, 
        -- eg. if we're compiling a let-no-escape).
@@ -266,7 +273,7 @@ closureCodeBody binder_info cl_info cc args body
        (sp_top, stk_args)     = mkVirtStkOffsets vSp other_args
 
        -- Allocate the global ticky counter
-  ; let ticky_ctr_lbl = mkRednCountsLabel (closureName cl_info)
+  ; let ticky_ctr_lbl = mkRednCountsLabel (closureName cl_info) (clHasCafRefs cl_info)
   ; emitTickyCounter cl_info args sp_top
 
        -- ...and establish the ticky-counter 
@@ -339,7 +346,8 @@ mkSlowEntryCode cl_info reg_args
   | otherwise = return noStmts
   where
      name = closureName cl_info
-     slow_lbl = mkSlowEntryLabel name
+     has_caf_refs = clHasCafRefs cl_info
+     slow_lbl = mkSlowEntryLabel name has_caf_refs
 
      load_stmts = mkStmts load_assts `plusStmts` mkStmts [stk_adj_pop, jump_to_entry]
      save_stmts = oneStmt stk_adj_push `plusStmts`  mkStmts save_assts
@@ -356,13 +364,13 @@ mkSlowEntryCode cl_info reg_args
                                                   (argMachRep rep))
 
      save_assts = zipWithEqual "mk_save" mk_save reps_w_regs stk_offsets
-     mk_save (rep,reg) offset = ASSERT( argMachRep rep == globalRegRep reg )
+     mk_save (rep,reg) offset = ASSERT( argMachRep rep `cmmEqType` globalRegType reg )
                                CmmStore (cmmRegOffW spReg offset) 
                                         (CmmReg (CmmGlobal reg))
 
      stk_adj_pop   = CmmAssign spReg (cmmRegOffW spReg final_stk_offset)
      stk_adj_push  = CmmAssign spReg (cmmRegOffW spReg (- final_stk_offset))
-     jump_to_entry = CmmJump (mkLblExpr (enterLocalIdLabel name)) []
+     jump_to_entry = CmmJump (mkLblExpr (enterLocalIdLabel name has_caf_refs)) []
 \end{code}
 
 
@@ -385,8 +393,10 @@ thunkWrapper closure_info thunk_code = do
 
         -- Stack and/or heap checks
   ; thunkEntryChecks closure_info $ do
-       {       -- Overwrite with black hole if necessary
-         whenC (blackHoleOnEntry closure_info && node_points)
+       {
+          dflags <- getDynFlags
+          -- Overwrite with black hole if necessary
+       ; whenC (blackHoleOnEntry dflags closure_info && node_points)
                (blackHoleIt closure_info)
        ; setupUpdate closure_info thunk_code }
                -- setupUpdate *encloses* the thunk_code
@@ -400,8 +410,19 @@ funWrapper :: ClosureInfo  -- Closure whose code body this is
 funWrapper closure_info arg_regs reg_save_code fun_body = do
   { let node_points = nodeMustPointToIt (closureLFInfo closure_info)
 
+  {-
+        -- Debugging: check that R1 has the correct tag
+  ; let tag = funTag closure_info
+  ; whenC (tag /= 0 && node_points) $ do
+        l <- newLabelC
+        stmtC (CmmCondBranch (CmmMachOp mo_wordEq [cmmGetTag (CmmReg nodeReg),
+                                                   CmmLit (mkIntCLit tag)]) l)
+        stmtC (CmmStore (CmmLit (mkWordCLit 0)) (CmmLit (mkWordCLit 0)))
+        labelC l
+  -}
+
        -- Enter for Ldv profiling
-  ; whenC node_points (ldvEnter (CmmReg nodeReg))
+  ; whenC node_points (ldvEnterClosure closure_info)
 
        -- GranSim yeild poin
   ; granYield arg_regs node_points
@@ -427,15 +448,9 @@ blackHoleIt :: ClosureInfo -> Code
 blackHoleIt closure_info = emitBlackHoleCode (closureSingleEntry closure_info)
 
 emitBlackHoleCode :: Bool -> Code
-emitBlackHoleCode is_single_entry 
-  | eager_blackholing = do 
-       tickyBlackHole (not is_single_entry)
-       stmtC (CmmStore (CmmReg nodeReg) (CmmLit (CmmLabel bh_lbl)))
-  | otherwise = 
-       nopC
-  where
-    bh_lbl | is_single_entry = mkRtsDataLabel SLIT("stg_SE_BLACKHOLE_info")
-          | otherwise       = mkRtsDataLabel SLIT("stg_BLACKHOLE_info")
+emitBlackHoleCode is_single_entry = do
+
+  dflags <- getDynFlags
 
        -- If we wanted to do eager blackholing with slop filling,
        -- we'd need to do it at the *end* of a basic block, otherwise
@@ -451,7 +466,21 @@ emitBlackHoleCode is_single_entry
         -- to bring back minimal ticky-ticky, so now EAGER_BLACKHOLING 
         -- is unconditionally disabled. -- krc 1/2007
 
-    eager_blackholing = False 
+  let eager_blackholing =  not opt_SccProfilingOn
+                        && dopt Opt_EagerBlackHoling dflags
+
+  if eager_blackholing
+     then do
+          tickyBlackHole (not is_single_entry)
+          let bh_info = CmmReg (CmmGlobal EagerBlackholeInfo)
+         stmtsC [
+              CmmStore (cmmOffsetW (CmmReg nodeReg) fixedHdrSize)
+                       (CmmReg (CmmGlobal CurrentTSO)),
+              CmmCall (CmmPrim MO_WriteBarrier) [] [] CmmUnsafe CmmMayReturn,
+             CmmStore (CmmReg nodeReg) bh_info
+            ]
+     else
+          nopC
 \end{code}
 
 \begin{code}
@@ -464,17 +493,23 @@ setupUpdate closure_info code
   = code
 
   | not (isStaticClosure closure_info)
-  = if closureUpdReqd closure_info
-    then do { tickyPushUpdateFrame;  pushUpdateFrame (CmmReg nodeReg) code }
-    else do { tickyUpdateFrameOmitted; code }
+  = do
+   if not (closureUpdReqd closure_info)
+      then do tickyUpdateFrameOmitted; code
+      else do
+          tickyPushUpdateFrame
+          dflags <- getDynFlags
+          if not opt_SccProfilingOn && dopt Opt_EagerBlackHoling dflags
+              then pushBHUpdateFrame (CmmReg nodeReg) code
+              else pushUpdateFrame   (CmmReg nodeReg) code
+  
   | otherwise  -- A static closure
   = do         { tickyUpdateBhCaf closure_info
 
        ; if closureUpdReqd closure_info
          then do       -- Blackhole the (updatable) CAF:
                { upd_closure <- link_caf closure_info True
-               ; pushUpdateFrame upd_closure code }
+               ; pushBHUpdateFrame upd_closure code }
          else do
                { -- krc: removed some ticky-related code here.
                ; tickyUpdateFrameOmitted
@@ -524,18 +559,22 @@ link_caf :: ClosureInfo
 -- updated with the new value when available.  The reason for all of this
 -- is that we only want to update dynamic heap objects, not static ones,
 -- so that generational GC is easier.
-link_caf cl_info is_upd = do
+link_caf cl_info _is_upd = do
   {    -- Alloc black hole specifying CC_HDR(Node) as the cost centre
   ; let        use_cc   = costCentreFrom (CmmReg nodeReg)
         blame_cc = use_cc
-  ; hp_offset <- allocDynClosure bh_cl_info use_cc blame_cc []
+        tso      = CmmReg (CmmGlobal CurrentTSO)
+  ; hp_offset <- allocDynClosure bh_cl_info use_cc blame_cc [(tso,fixedHdrSize)]
   ; hp_rel    <- getHpRelOffset hp_offset
 
        -- Call the RTS function newCAF to add the CAF to the CafList
        -- so that the garbage collector can find them
        -- This must be done *before* the info table pointer is overwritten, 
        -- because the old info table ptr is needed for reversion
-  ; emitRtsCallWithVols SLIT("newCAF") [(CmmReg nodeReg,PtrHint)] [node]
+  ; emitRtsCallWithVols rtsPackageId (fsLit "newCAF")
+      [ CmmHinted (CmmReg (CmmGlobal BaseReg)) AddrHint,
+        CmmHinted (CmmReg nodeReg) AddrHint ]
+      [node] False
        -- node is live, so save it.
 
        -- Overwrite the closure with a (static) indirection 
@@ -546,8 +585,7 @@ link_caf cl_info is_upd = do
   ; returnFC hp_rel }
   where
     bh_cl_info :: ClosureInfo
-    bh_cl_info | is_upd    = cafBlackHoleClosureInfo   cl_info
-              | otherwise = seCafBlackHoleClosureInfo cl_info
+    bh_cl_info = cafBlackHoleClosureInfo cl_info
 
     ind_static_info :: CmmExpr
     ind_static_info = mkLblExpr mkIndStaticInfoLabel
@@ -574,11 +612,11 @@ closureDescription :: Module              -- Module
        -- Not called for StgRhsCon which have global info tables built in
        -- CgConTbls.lhs with a description generated from the data constructor
 closureDescription mod_name name
-  = showSDocDump (char '<' <>
+  = showSDocDumpOneLine (char '<' <>
                    (if isExternalName name
                      then ppr name -- ppr will include the module name prefix
                      else pprModule mod_name <> char '.' <> ppr name) <>
                    char '>')
-   -- showSDocDump, because we want to see the unique on the Name.
+   -- showSDocDumpOneLine, because we want to see the unique on the Name.
 \end{code}