[project @ 1999-06-24 13:04:13 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgHeapery.lhs
index bc3f5e5..1663846 100644 (file)
@@ -1,14 +1,14 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CgHeapery.lhs,v 1.10 1998/12/02 13:17:50 simonm Exp $
+% $Id: CgHeapery.lhs,v 1.18 1999/06/24 13:04:19 simonmar Exp $
 %
 \section[CgHeapery]{Heap management functions}
 
 \begin{code}
 module CgHeapery (
        fastEntryChecks, altHeapCheck, thunkChecks,
-       allocHeap, allocDynClosure
+       allocDynClosure, inPlaceAllocDynClosure
 
         -- new functions, basically inserting macro calls into Code -- HWL
         ,fetchAndReschedule, yield
@@ -21,7 +21,7 @@ import CLabel
 import CgMonad
 
 import CgStackery      ( getFinalStackHW, mkTaggedStkAmodes, mkTagAssts )
-import SMRep           ( fixedHdrSize, getSMRepStr )
+import SMRep           ( fixedHdrSize )
 import AbsCUtils       ( mkAbstractCs, getAmodeRep )
 import CgUsages                ( getVirtAndRealHp, getRealSp, setVirtHp, setRealHp,
                          initHeapUsage
@@ -31,13 +31,13 @@ import ClosureInfo  ( closureSize, closureGoodStuffSize,
                          closureSMRep
                        )
 import PrimRep         ( PrimRep(..), isFollowableRep )
-import Util            ( panic )
+import Unique          ( Unique )
 import CmdLineOpts     ( opt_SccProfilingOn )
 import GlaExts
+import Outputable
 
 #ifdef DEBUG
 import PprAbsC         ( pprMagicId ) -- tmp
-import Outputable      -- tmp
 #endif
 \end{code}
 
@@ -227,7 +227,7 @@ altHeapCheck
        -> [MagicId]                    -- live registers
        -> [(VirtualSpOffset,Int)]      -- stack slots to tag
        -> AbstractC
-       -> Maybe CLabel                 -- ret address if not on top of stack.
+       -> Maybe Unique                 -- uniq of ret address (possibly)
        -> Code
        -> Code
 
@@ -252,6 +252,12 @@ altHeapCheck is_fun regs tags fail_code (Just ret_addr) code
        checking_code tag_assts = 
          case non_void_regs of
 
+{- no: there might be stuff on top of the retn. addr. on the stack.
+           [{-no regs-}] ->
+               CCheck HP_CHK_NOREGS
+                   [mkIntCLit words_required]
+                   tag_assts
+-}
            -- this will cover all cases for x86
            [VanillaReg rep ILIT(1)] 
 
@@ -259,14 +265,14 @@ altHeapCheck is_fun regs tags fail_code (Just ret_addr) code
                  CCheck HP_CHK_UT_ALT
                      [mkIntCLit words_required, mkIntCLit 1, mkIntCLit 0,
                        CReg (VanillaReg RetRep ILIT(2)),
-                       CLbl ret_addr RetRep]
+                       CLbl (mkReturnInfoLabel ret_addr) RetRep]
                      tag_assts
 
               | otherwise ->
                  CCheck HP_CHK_UT_ALT
                      [mkIntCLit words_required, mkIntCLit 0, mkIntCLit 1,
                        CReg (VanillaReg RetRep ILIT(2)),
-                       CLbl ret_addr RetRep]
+                       CLbl (mkReturnInfoLabel ret_addr) RetRep]
                      tag_assts
 
            several_regs ->
@@ -275,7 +281,10 @@ altHeapCheck is_fun regs tags fail_code (Just ret_addr) code
                CCheck HP_CHK_GEN
                     [mkIntCLit words_required, 
                      mkIntCLit (IBOX(word2Int# liveness)),
-                     CLbl ret_addr RetRep] 
+                       -- HP_CHK_GEN needs a direct return address,
+                       -- not an info table (might be different if
+                       -- we're not assembly-mangling/tail-jumping etc.)
+                     CLbl (mkReturnPtLabel ret_addr) RetRep] 
                     tag_assts
 
 -- normal algebraic and primitive case alternatives:
@@ -301,6 +310,9 @@ altHeapCheck is_fun regs [] AbsCNop Nothing code
               CCheck HP_CHK_NOREGS [mkIntCLit words_required] AbsCNop
 
            -- The SEQ case (polymophic/function typed case branch)
+           -- We need this case because the closure in Node won't return
+           -- directly when we enter it (it could be a function), so the
+           -- heap check code needs to push a seq frame on top of the stack.
            [VanillaReg rep ILIT(1)]
                |  rep == PtrRep
                && is_fun ->
@@ -342,11 +354,10 @@ altHeapCheck is_fun regs [] AbsCNop Nothing code
 -- build up a bitmap of the live pointer registers
 
 mkRegLiveness :: [MagicId] -> Word#
-mkRegLiveness [] = int2Word# 0#
-mkRegLiveness (VanillaReg rep i : regs) 
-   | isFollowableRep rep = ((int2Word# 1#) `shiftL#` (i -# 1#)) 
-                               `or#` mkRegLiveness regs
-   | otherwise           = mkRegLiveness regs
+mkRegLiveness []  =  int2Word# 0#
+mkRegLiveness (VanillaReg rep i : regs) | isFollowableRep rep 
+  =  ((int2Word# 1#) `shiftL#` (i -# 1#)) `or#` mkRegLiveness regs
+mkRegLiveness (_ : regs)  =  mkRegLiveness regs
 
 -- Emit macro for simulating a fetch and then reschedule
 
@@ -437,10 +448,8 @@ allocDynClosure closure_info use_cc blame_cc amodes_with_offsets
     in
        -- SAY WHAT WE ARE ABOUT TO DO
     profCtrC (allocProfilingMsg closure_info)
-                          [mkIntCLit fixedHdrSize,
-                           mkIntCLit (closureGoodStuffSize closure_info),
-                           mkIntCLit slop_size,
-                           mkIntCLit closure_size]     `thenC`
+                          [mkIntCLit (closureGoodStuffSize closure_info),
+                           mkIntCLit slop_size]        `thenC`
 
        -- GENERATE THE CODE
     absC ( mkAbstractCs (
@@ -449,7 +458,6 @@ allocDynClosure closure_info use_cc blame_cc amodes_with_offsets
 
        -- GENERATE CC PROFILING MESSAGES
     costCentresC SLIT("CCS_ALLOC") [blame_cc, mkIntCLit closure_size]
-       -- CLitLit (_PK_ type_str) IntRep] -- not necessary? --SDM
                                                        `thenC`
 
        -- BUMP THE VIRTUAL HEAP POINTER
@@ -460,36 +468,42 @@ allocDynClosure closure_info use_cc blame_cc amodes_with_offsets
   where
     closure_size = closureSize closure_info
     slop_size    = slopSize closure_info
-    type_str     = getSMRepStr (closureSMRep closure_info)
+\end{code}
 
--- Avoid hanging on to anything in the CC field when we're not profiling.
+Occasionally we can update a closure in place instead of allocating
+new space for it.  This is the function that does the business, assuming:
 
-cInitHdr closure_info amode cc 
-  | opt_SccProfilingOn = CInitHdr closure_info amode cc
-  | otherwise          = CInitHdr closure_info amode (panic "absent cc")
-       
-\end{code}
+       - node points to the closure to be overwritten
 
-%************************************************************************
-%*                                                                     *
-\subsection{Allocate uninitialized heap space}
-%*                                                                     *
-%************************************************************************
+       - the new closure doesn't contain any pointers if we're
+         using a generational collector.
 
 \begin{code}
-allocHeap :: HeapOffset                -- Size of the space required
-         -> FCode CAddrMode    -- Addr mode for first word of object
+inPlaceAllocDynClosure
+       :: ClosureInfo
+       -> CAddrMode            -- Pointer to beginning of closure
+       -> CAddrMode            -- Cost Centre to stick in the object
 
-allocHeap space
-  = getVirtAndRealHp                           `thenFC` \ (virtHp, realHp) ->
-    let block_start = virtHp + 1
+       -> [(CAddrMode, VirtualHeapOffset)]     -- Offsets from start of the object
+                                               -- ie Info ptr has offset zero.
+       -> Code
+
+inPlaceAllocDynClosure closure_info head use_cc amodes_with_offsets
+  = let        -- do_move IS THE ASSIGNMENT FUNCTION
+        do_move (amode, offset_from_start)
+          = CAssign (CVal (CIndex head (mkIntCLit offset_from_start) WordRep)
+                       (getAmodeRep amode))
+                    amode
     in
-       -- We charge the allocation to "PRIM" (which is probably right)
-    profCtrC SLIT("ALLOC_PRIM2") [mkIntCLit space]     `thenC`
+       -- GENERATE THE CODE
+    absC ( mkAbstractCs (
+          [ CInitHdr closure_info head use_cc ]
+          ++ (map do_move amodes_with_offsets)))
 
-       -- BUMP THE VIRTUAL HEAP POINTER
-    setVirtHp (virtHp + space)                 `thenC`
+-- Avoid hanging on to anything in the CC field when we're not profiling.
 
-       -- RETURN PTR TO START OF OBJECT
-    returnFC (CAddr (hpRel realHp block_start))
+cInitHdr closure_info amode cc 
+  | opt_SccProfilingOn = CInitHdr closure_info (CAddr amode) cc
+  | otherwise          = CInitHdr closure_info (CAddr amode) (panic "absent cc")
+       
 \end{code}