[project @ 1999-06-24 13:04:13 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgHeapery.lhs
index c383998..1663846 100644 (file)
@@ -1,14 +1,14 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CgHeapery.lhs,v 1.13 1999/01/26 16:16:33 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,
-       allocDynClosure
+       allocDynClosure, inPlaceAllocDynClosure
 
         -- new functions, basically inserting macro calls into Code -- HWL
         ,fetchAndReschedule, yield
@@ -31,6 +31,7 @@ import ClosureInfo    ( closureSize, closureGoodStuffSize,
                          closureSMRep
                        )
 import PrimRep         ( PrimRep(..), isFollowableRep )
+import Unique          ( Unique )
 import CmdLineOpts     ( opt_SccProfilingOn )
 import GlaExts
 import Outputable
@@ -226,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
 
@@ -251,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)] 
 
@@ -258,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 ->
@@ -274,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:
@@ -300,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 ->
@@ -341,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
 
@@ -456,11 +468,42 @@ allocDynClosure closure_info use_cc blame_cc amodes_with_offsets
   where
     closure_size = closureSize closure_info
     slop_size    = slopSize closure_info
+\end{code}
+
+Occasionally we can update a closure in place instead of allocating
+new space for it.  This is the function that does the business, assuming:
+
+       - node points to the closure to be overwritten
+
+       - the new closure doesn't contain any pointers if we're
+         using a generational collector.
+
+\begin{code}
+inPlaceAllocDynClosure
+       :: ClosureInfo
+       -> CAddrMode            -- Pointer to beginning of closure
+       -> CAddrMode            -- Cost Centre to stick in the object
+
+       -> [(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
+       -- GENERATE THE CODE
+    absC ( mkAbstractCs (
+          [ CInitHdr closure_info head use_cc ]
+          ++ (map do_move amodes_with_offsets)))
 
 -- Avoid hanging on to anything in the CC field when we're not profiling.
 
 cInitHdr closure_info amode cc 
-  | opt_SccProfilingOn = CInitHdr closure_info amode cc
-  | otherwise          = CInitHdr closure_info amode (panic "absent cc")
+  | opt_SccProfilingOn = CInitHdr closure_info (CAddr amode) cc
+  | otherwise          = CInitHdr closure_info (CAddr amode) (panic "absent cc")
        
 \end{code}