Reorganisation of the source tree
[ghc-hetmet.git] / ghc / rts / parallel / Pack.c
diff --git a/ghc/rts/parallel/Pack.c b/ghc/rts/parallel/Pack.c
deleted file mode 100644 (file)
index e8653f6..0000000
+++ /dev/null
@@ -1,4293 +0,0 @@
-/* 
-   Time-stamp: <Wed Mar 21 2001 16:32:47 Stardate: [-30]6363.44 hwloidl>
-
-   Graph packing and unpacking code for sending it to another processor
-   and retrieving the original graph structure from the packet.
-   In the old RTS the code was split into Pack.c and Unpack.c (now deceased)
-   Used in GUM and GrAnSim.
-
-   The GrAnSim version of the code defines routines for *simulating* the
-   packing of closures in the same way it is done in the parallel runtime
-   system. Basically GrAnSim only puts the addresses of the closures to be
-   transferred into a buffer. This buffer will then be associated with the
-   event of transferring the graph. When this event is scheduled, the
-   @UnpackGraph@ routine is called and the buffer can be discarded
-   afterwards.
-
-   Note that in GranSim we need many buffers, not just one per PE.
-*/
-
-//@node Graph packing, , ,
-//@section Graph packing
-
-#if defined(PAR) || defined(GRAN)   /* whole file */
-
-//@menu
-//* Includes::                 
-//* Prototypes::               
-//* Global variables::         
-//* ADT of Closure Queues::    
-//* Initialisation for packing::  
-//* Packing Functions::                
-//* Low level packing routines::  
-//* Unpacking routines::       
-//* Aux fcts for packing::     
-//* Printing Packet Contents:: 
-//* End of file::              
-//@end menu
-//*/
-
-//@node Includes, Prototypes, Graph packing, Graph packing
-//@subsection Includes
-
-#include "Rts.h"
-#include "RtsFlags.h"
-#include "RtsUtils.h"
-#include "ClosureTypes.h"
-#include "Storage.h"
-#include "Hash.h"
-#include "Parallel.h"
-#include "GranSimRts.h"
-#include "ParallelRts.h"
-# if defined(DEBUG)
-# include "Sanity.h"
-# include "Printer.h"
-# include "ParallelDebug.h"
-# endif
-#include "FetchMe.h"
-
-/* Which RTS flag should be used to get the size of the pack buffer ? */
-# if defined(PAR)
-#  define RTS_PACK_BUFFER_SIZE   RtsFlags.ParFlags.packBufferSize
-# else   /* GRAN */
-#  define RTS_PACK_BUFFER_SIZE   RtsFlags.GranFlags.packBufferSize
-# endif
-
-//@node Prototypes, Global variables, Includes, Graph packing
-//@subsection Prototypes
-/* 
-   Code declarations. 
-*/
-
-//@node ADT of closure queues, Init for packing, Prototypes, Prototypes
-//@subsubsection ADT of closure queues
-
-static inline void       InitClosureQueue(void);
-static inline rtsBool    QueueEmpty(void);
-static inline void       QueueClosure(StgClosure *closure);
-static inline StgClosure *DeQueueClosure(void);
-
-//@node Init for packing, Packing routines, ADT of closure queues, Prototypes
-//@subsubsection Init for packing
-
-static void     InitPacking(rtsBool unpack);
-# if defined(PAR)
-rtsBool         InitPackBuffer(void);
-# elif defined(GRAN)
-rtsPackBuffer  *InstantiatePackBuffer (void);
-static void     reallocPackBuffer (void);
-# endif
-
-//@node Packing routines, Low level packing fcts, Init for packing, Prototypes
-//@subsubsection Packing routines
-
-static void    PackClosure (StgClosure *closure);
-
-//@node Low level packing fcts, Unpacking routines, Packing routines, Prototypes
-//@subsubsection Low level packing fcts
-
-# if defined(GRAN)
-static  void    Pack (StgClosure *data);
-# else
-static  void    Pack (StgWord data);
-
-static void    PackGeneric(StgClosure *closure);
-static void    PackArray(StgClosure *closure);
-static void    PackPLC (StgPtr addr);
-static void    PackOffset (int offset);
-static void    PackPAP(StgPAP *pap);
-static rtsPackBuffer *PackTSO(StgTSO *tso, nat *packBufferSize);
-static rtsPackBuffer *PackStkO(StgPtr stko, nat *packBufferSize);
-static void           PackFetchMe(StgClosure *closure);
-
-static void    GlobaliseAndPackGA (StgClosure *closure);
-# endif
-
-//@node Unpacking routines, Aux fcts for packing, Low level packing fcts, Prototypes
-//@subsubsection Unpacking routines
-
-# if defined(PAR)
-void        InitPendingGABuffer(nat size); 
-void        CommonUp(StgClosure *src, StgClosure *dst);
-static StgClosure *SetGAandCommonUp(globalAddr *gaP, StgClosure *closure, 
-                                 rtsBool hasGA);
-static nat         FillInClosure(StgWord ***bufptrP, StgClosure *graph);
-static void        LocateNextParent(StgClosure **parentP,
-                                   nat *pptrP, nat *pptrsP, nat *sizeP);
-StgClosure        *UnpackGraph(rtsPackBuffer *packBuffer,
-                              globalAddr **gamap,
-                              nat *nGAs);
-static  StgClosure *UnpackClosure (StgWord ***bufptrP, StgClosure **graphP, 
-                                  globalAddr *ga);
-static  StgWord   **UnpackGA(StgWord **bufptr, globalAddr *ga);
-static  StgClosure *UnpackOffset(globalAddr *ga);
-static  StgClosure *UnpackPLC(globalAddr *ga);
-static  void        UnpackArray(StgWord ***bufptrP, StgClosure *graph);
-static  nat         UnpackPAP(StgWord ***bufptrP, StgClosure *graph);
-
-# elif defined(GRAN)
-void        CommonUp(StgClosure *src, StgClosure *dst);
-StgClosure *UnpackGraph(rtsPackBuffer* buffer);
-#endif
-
-//@node Aux fcts for packing,  , Unpacking routines, Prototypes
-//@subsubsection Aux fcts for packing
-
-# if defined(PAR)
-static void    DonePacking(void);
-static void    AmPacking(StgClosure *closure);
-static int     OffsetFor(StgClosure *closure);
-static rtsBool  NotYetPacking(int offset);
-static inline rtsBool  RoomToPack (nat size, nat ptrs);
-static inline rtsBool  isOffset(globalAddr *ga);
-static inline rtsBool  isFixed(globalAddr *ga);
-static inline rtsBool  isConstr(globalAddr *ga);
-static inline rtsBool  isUnglobalised(globalAddr *ga);
-# elif defined(GRAN)
-static void     DonePacking(void);
-static rtsBool  NotYetPacking(StgClosure *closure);
-# endif
-
-//@node Global variables, ADT of Closure Queues, Prototypes, Graph packing
-//@subsection Global variables
-/*
-  Static data declarations
-*/
-
-static nat     pack_locn,           /* ptr to first free loc in pack buffer */
-               clq_size, clq_pos,
-               buf_id = 1;          /* identifier for buffer */
-static nat     unpacked_size;
-static rtsBool roomInBuffer;
-#if defined(PAR)
-static GlobalTaskId dest_gtid=0;    /* destination for message to send */
-#endif
-
-/* 
-   The pack buffer
-   To be pedantic: in GrAnSim we're packing *addresses* of closures,
-   not the closures themselves.
-*/
-static rtsPackBuffer *globalPackBuffer = NULL,    /* for packing a graph */
-                     *globalUnpackBuffer = NULL;  /* for unpacking a graph */
-
-
-/*
-  Bit of a hack for testing if a closure is the root of the graph. This is
-  set in @PackNearbyGraph@ and tested in @PackClosure@.  
-*/
-
-static nat          packed_thunks = 0;
-static StgClosure  *graph_root;
-
-# if defined(PAR)
-/*
-  The offset hash table is used during packing to record the location in
-  the pack buffer of each closure which is packed.
-*/
-//@cindex offsetTable
-static HashTable *offsetTable;
-
-//@cindex PendingGABuffer
-static globalAddr *PendingGABuffer, *gaga;
-
-# endif /* PAR */
-
-
-//@node ADT of Closure Queues, Initialisation for packing, Global variables, Graph packing
-//@subsection ADT of Closure Queues
-
-//@menu
-//* Closure Queues::           
-//* Init routines::            
-//* Basic routines::           
-//@end menu
-
-//@node Closure Queues, Init routines, ADT of Closure Queues, ADT of Closure Queues
-//@subsubsection Closure Queues
-/*
-  Closure Queues
-
-  These routines manage the closure queue.
-*/
-
-static nat clq_pos, clq_size;
-
-static StgClosure **ClosureQueue = NULL;   /* HWL: init in main */
-
-#if defined(DEBUG)
-static char graphFingerPrint[MAX_FINGER_PRINT_LEN];
-#endif
-
-//@node Init routines, Basic routines, Closure Queues, ADT of Closure Queues
-//@subsubsection Init routines
-
-/* @InitClosureQueue@ allocates and initialises the closure queue. */
-
-//@cindex InitClosureQueue
-static inline void
-InitClosureQueue(void)
-{
-  clq_pos = clq_size = 0;
-
-  if (ClosureQueue==NULL)
-    ClosureQueue = (StgClosure**) stgMallocWords(RTS_PACK_BUFFER_SIZE, 
-                                                "InitClosureQueue");
-}
-
-//@node Basic routines, Types of Global Addresses, Init routines, ADT of Closure Queues
-//@subsubsection Basic routines
-
-/*
-  QueueEmpty returns rtsTrue if the closure queue is empty; rtsFalse otherwise.
-*/
-
-//@cindex QueueEmpty
-static inline rtsBool
-QueueEmpty(void)
-{
-  return(clq_pos >= clq_size);
-}
-
-/* QueueClosure adds its argument to the closure queue. */
-
-//@cindex QueueClosure
-static inline void
-QueueClosure(closure)
-StgClosure *closure;
-{
-  if(clq_size < RTS_PACK_BUFFER_SIZE ) {
-    IF_PAR_DEBUG(paranoia,
-                belch(">__> <<%d>> Q: %p (%s); %d elems in q",
-                      globalPackBuffer->id, closure, info_type(closure), clq_size-clq_pos));
-    ClosureQueue[clq_size++] = closure;
-  } else { 
-    barf("Closure Queue Overflow (EnQueueing %p (%s))", 
-        closure, info_type(closure));
-  }
-}
-
-/* DeQueueClosure returns the head of the closure queue. */
-
-//@cindex DeQueueClosure
-static inline StgClosure * 
-DeQueueClosure(void)
-{
-  if(!QueueEmpty()) {
-    IF_PAR_DEBUG(paranoia,
-                belch(">__> <<%d>> DeQ: %p (%s); %d elems in q",
-                      globalPackBuffer->id, ClosureQueue[clq_pos], info_type(ClosureQueue[clq_pos]), 
-                      clq_size-clq_pos));
-    return(ClosureQueue[clq_pos++]);
-  } else {
-    return((StgClosure*)NULL);
-  }
-}
-
-/* DeQueueClosure returns the head of the closure queue. */
-
-#if defined(DEBUG)
-//@cindex PrintQueueClosure
-static void
-PrintQueueClosure(void)
-{
-  nat i;
-
-  fputs("Closure queue:", stderr);
-  for (i=clq_pos; i < clq_size; i++)
-    fprintf(stderr, "%p (%s), ", 
-           (StgClosure *)ClosureQueue[clq_pos++], 
-           info_type(ClosureQueue[clq_pos++]));
-  fputc('\n', stderr);
-}
-#endif
-
-//@node Types of Global Addresses,  , Basic routines, ADT of Closure Queues
-//@subsubsection Types of Global Addresses
-
-/*
-  Types of Global Addresses
-
-  These routines determine whether a GA is one of a number of special types
-  of GA.
-*/
-
-# if defined(PAR)
-//@cindex isOffset
-static inline rtsBool 
-isOffset(globalAddr *ga)
-{
-    return (ga->weight == 1U && ga->payload.gc.gtid == (GlobalTaskId)0);
-}
-
-//@cindex isFixed
-static inline rtsBool
-isFixed(globalAddr *ga)
-{
-    return (ga->weight == 0U);
-}
-
-//@cindex isConstr
-static inline rtsBool
-isConstr(globalAddr *ga)
-{
-    return (ga->weight == 2U);
-}
-
-//@cindex isUnglobalised
-static inline rtsBool
-isUnglobalised(globalAddr *ga)
-{
-    return (ga->weight == 2U);
-}
-# endif
-
-//@node Initialisation for packing, Packing Functions, ADT of Closure Queues, Graph packing
-//@subsection Initialisation for packing
-/*
-  Simple Packing Routines
-
-  About packet sizes in GrAnSim: In GrAnSim we use a malloced block of
-  gransim_pack_buffer_size words to simulate a packet of pack_buffer_size
-  words.  In the simulated PackBuffer we only keep the addresses of the
-  closures that would be packed in the parallel system (see Pack). To
-  decide if a packet overflow occurs pack_buffer_size must be compared
-  versus unpacked_size (see RoomToPack).  Currently, there is no multi
-  packet strategy implemented, so in the case of an overflow we just stop
-  adding closures to the closure queue.  If an overflow of the simulated
-  packet occurs, we just realloc some more space for it and carry on as
-  usual.  -- HWL
-*/
-
-# if defined(GRAN)
-rtsPackBuffer *
-InstantiatePackBuffer (void) {
-  extern rtsPackBuffer *globalPackBuffer;
-
-  globalPackBuffer = (rtsPackBuffer *) stgMallocWords(sizeofW(rtsPackBuffer), 
-                        "InstantiatePackBuffer: failed to alloc packBuffer");
-  globalPackBuffer->size = RtsFlags.GranFlags.packBufferSize_internal;
-  globalPackBuffer->buffer = (StgWord **) stgMallocWords(RtsFlags.GranFlags.packBufferSize_internal,
-                                "InstantiatePackBuffer: failed to alloc GranSim internal packBuffer");
-  /* NB: gransim_pack_buffer_size instead of pack_buffer_size -- HWL */
-  /* stgMallocWords is now simple allocate in Storage.c */
-
-  return (globalPackBuffer);
-}
-
-/* 
-   Reallocate the GranSim internal pack buffer to make room for more closure
-   pointers. This is independent of the check for packet overflow as in GUM
-*/
-static void
-reallocPackBuffer (void) {
-
-  ASSERT(pack_locn >= (int)globalPackBuffer->size+sizeofW(rtsPackBuffer));
-
-  IF_GRAN_DEBUG(packBuffer,
-               belch("** Increasing size of PackBuffer %p to %d words (PE %u @ %d)\n",
-                     globalPackBuffer, globalPackBuffer->size+REALLOC_SZ,
-                     CurrentProc, CurrentTime[CurrentProc]));
-  
-  globalPackBuffer = (rtsPackBuffer*)realloc(globalPackBuffer, 
-                                 sizeof(StgClosure*)*(REALLOC_SZ +
-                                                      (int)globalPackBuffer->size +
-                                                      sizeofW(rtsPackBuffer))) ;
-  if (globalPackBuffer==(rtsPackBuffer*)NULL) 
-    barf("Failing to realloc %d more words for PackBuffer %p (PE %u @ %d)\n", 
-        REALLOC_SZ, globalPackBuffer, CurrentProc, CurrentTime[CurrentProc]);
-  
-  globalPackBuffer->size += REALLOC_SZ;
-
-  ASSERT(pack_locn < globalPackBuffer->size+sizeofW(rtsPackBuffer));
-}
-# endif
-
-# if defined(PAR)
-/* @initPacking@ initialises the packing buffer etc. */
-//@cindex InitPackBuffer
-rtsBool
-InitPackBuffer(void)
-{
-  if (globalPackBuffer==(rtsPackBuffer*)NULL) {
-    if ((globalPackBuffer = (rtsPackBuffer *) 
-        stgMallocWords(sizeofW(rtsPackBuffer)+RtsFlags.ParFlags.packBufferSize+DEBUG_HEADROOM,
-                       "InitPackBuffer")) == NULL)
-      return rtsFalse;
-  }
-  return rtsTrue;
-}
-
-# endif 
-//@cindex InitPacking
-static void
-InitPacking(rtsBool unpack)
-{
-# if defined(GRAN)
-  globalPackBuffer = InstantiatePackBuffer();     /* for GrAnSim only -- HWL */
-                                       /* NB: free in UnpackGraph */
-# elif defined(PAR)
-  if (unpack) {
-    /* allocate a GA-to-GA map (needed for ACK message) */
-    InitPendingGABuffer(RtsFlags.ParFlags.packBufferSize);
-  } else {
-    /* allocate memory to pack the graph into */
-    InitPackBuffer();
-  }
-# endif
-  /* init queue of closures seen during packing */
-  InitClosureQueue();
-
-  if (unpack) 
-    return;
-
-  globalPackBuffer->id = buf_id++;  /* buffer id are only used for debugging! */
-  pack_locn = 0;         /* the index into the actual pack buffer */
-  unpacked_size = 0;     /* the size of the whole graph when unpacked */
-  roomInBuffer = rtsTrue;
-  packed_thunks = 0;   /* total number of thunks packed so far */
-# if defined(PAR)
-  offsetTable = allocHashTable();
-# endif
-}
-
-//@node Packing Functions, Low level packing routines, Initialisation for packing, Graph packing
-//@subsection Packing Functions
-
-//@menu
-//* Packing Sections of Nearby Graph:: 
-//* Packing Closures::         
-//@end menu
-
-//@node Packing Sections of Nearby Graph, Packing Closures, Packing Functions, Packing Functions
-//@subsubsection Packing Sections of Nearby Graph
-/*
-  Packing Sections of Nearby Graph
-
-  @PackNearbyGraph@ packs a closure and associated graph into a static
-  buffer (@PackBuffer@).  It returns the address of this buffer and the
-  size of the data packed into the buffer (in its second parameter,
-  @packBufferSize@).  The associated graph is packed in a depth first
-  manner, hence it uses an explicit queue of closures to be packed rather
-  than simply using a recursive algorithm.  Once the packet is full,
-  closures (other than primitive arrays) are packed as FetchMes, and their
-  children are not queued for packing.  */
-
-//@cindex PackNearbyGraph
-
-/* NB: this code is shared between GranSim and GUM;
-       tso only used in GranSim */
-rtsPackBuffer *
-PackNearbyGraph(closure, tso, packBufferSize, dest)
-StgClosure* closure;
-StgTSO* tso;
-nat *packBufferSize;
-GlobalTaskId dest;
-{
-  IF_PAR_DEBUG(resume,
-              graphFingerPrint[0] = '\0');
-
-  ASSERT(RTS_PACK_BUFFER_SIZE > 0);
-  ASSERT(_HS==1);  // HWL HACK; compile time constant
-
-#if defined(PAR_TICKY) // HWL HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
-  PAR_TICKY_PACK_NEARBY_GRAPH_START();
-#endif
-
-  /* ToDo: check that we have enough heap for the packet
-     ngoq ngo'
-     if (Hp + PACK_HEAP_REQUIRED > HpLim) 
-     return NULL;
-  */
-  InitPacking(rtsFalse);
-# if defined(PAR)
-  dest_gtid=dest; //-1 to disable
-# elif defined(GRAN)
-  graph_root = closure;
-# endif
-
-  IF_GRAN_DEBUG(pack,
-               belch(">>> Packing <<%d>> (buffer @ %p); graph root @ %p [PE %d]\n    demanded by TSO %d (%p) [PE %u]",
-                     globalPackBuffer->id, globalPackBuffer, closure, where_is(closure), 
-                     tso->id, tso, where_is((StgClosure*)tso)));
-
-  IF_GRAN_DEBUG(pack,
-               belch("** PrintGraph of %p is:", closure); 
-               PrintGraph(closure,0));
-
-  IF_PAR_DEBUG(resume,
-              GraphFingerPrint(closure, graphFingerPrint);
-              ASSERT(strlen(graphFingerPrint)<=MAX_FINGER_PRINT_LEN);
-              belch(">>> Packing <<%d>> (buffer @ %p); graph root @ %p [%x]\n    demanded by TSO %d (%p); Finger-print is\n    {%s}",
-                    globalPackBuffer->id, globalPackBuffer, closure, mytid,
-                    tso->id, tso, graphFingerPrint)); 
-
-  IF_PAR_DEBUG(packet,
-              belch("** PrintGraph of %p is:", closure); 
-              belch("** pack_locn=%d", pack_locn);
-              PrintGraph(closure,0));
-
-  QueueClosure(closure);
-  do {
-    PackClosure(DeQueueClosure());
-  } while (!QueueEmpty());
-  
-# if defined(PAR)
-
-  /* Record how much space the graph needs in packet and in heap */
-  globalPackBuffer->tso = tso;       // currently unused, I think (debugging?)
-  globalPackBuffer->unpacked_size = unpacked_size;
-  globalPackBuffer->size = pack_locn;
-
-  /* Check for buffer overflow (again) */
-  ASSERT(pack_locn <= RtsFlags.ParFlags.packBufferSize+DEBUG_HEADROOM);
-  IF_DEBUG(sanity,                           // write magic end-of-buffer word
-          globalPackBuffer->buffer[pack_locn] = END_OF_BUFFER_MARKER);
-  *packBufferSize = pack_locn;
-
-# else  /* GRAN */
-
-  /* Record how much space is needed to unpack the graph */
-  // PackBuffer[PACK_FLAG_LOCN] = (P_) MAGIC_PACK_FLAG;  for testing
-  globalPackBuffer->tso = tso;
-  globalPackBuffer->unpacked_size = unpacked_size;
-
-  // ASSERT(pack_locn <= PackBuffer[PACK_SIZE_LOCN]+PACK_HDR_SIZE);
-  /* ToDo: Print an earlier, more meaningful message */
-  if (pack_locn==0)   /* i.e. packet is empty */
-    barf("EMPTY PACKET! Can't transfer closure %p at all!!\n",
-        closure);
-  globalPackBuffer->size = pack_locn;
-  *packBufferSize = pack_locn;
-
-# endif
-
-  DonePacking();                               /* {GrAnSim}vaD 'ut'Ha' */
-
-# if defined(GRAN)
-  IF_GRAN_DEBUG(pack ,
-               belch("** Finished <<%d>> packing graph %p; closures packed: %d; thunks packed: %d; size of graph: %d",
-                     globalPackBuffer->id, closure, globalPackBuffer->size, packed_thunks, globalPackBuffer->unpacked_size));
-  if (RtsFlags.GranFlags.GranSimStats.Global) {
-    globalGranStats.tot_packets++; 
-    globalGranStats.tot_packet_size += pack_locn; 
-  }
-  
-  IF_GRAN_DEBUG(pack, PrintPacket(globalPackBuffer));
-# elif defined(PAR)
-  IF_PAR_DEBUG(packet,
-               belch("** Finished <<%d>> packing graph %p (%s); closures packed: %d; thunks packed: %d; size of graph: %d",
-                     globalPackBuffer->id, closure, info_type(closure),
-                     globalPackBuffer->size, packed_thunks, 
-                     globalPackBuffer->unpacked_size));;
-
-  IF_DEBUG(sanity, // do a sanity check on the packet just constructed 
-          checkPacket(globalPackBuffer));
-# endif   /* GRAN */
-
-#if defined(PAR_TICKY) // HWL HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
-  PAR_TICKY_PACK_NEARBY_GRAPH_END(globalPackBuffer->size, packed_thunks);
-#endif
-  
-  return (globalPackBuffer);
-}
-
-//@cindex PackOneNode
-
-# if defined(GRAN)
-/* This version is used when the node is already local */
-
-rtsPackBuffer *
-PackOneNode(closure, tso, packBufferSize)
-StgClosure* closure;
-StgTSO* tso;
-nat *packBufferSize;
-{
-  extern rtsPackBuffer *globalPackBuffer;
-  int i, clpack_locn;
-
-  InitPacking(rtsFalse);
-
-  IF_GRAN_DEBUG(pack,
-               belch("** PackOneNode: %p (%s)[PE %d] requested by TSO %d (%p) [PE %d]",
-                     closure, info_type(closure),
-                     where_is(closure), tso->id, tso, where_is((StgClosure *)tso)));
-
-  Pack(closure);
-
-  /* Record how much space is needed to unpack the graph */
-  globalPackBuffer->tso = tso;
-  globalPackBuffer->unpacked_size = unpacked_size;
-
-  /* Set the size parameter */
-  ASSERT(pack_locn <= RTS_PACK_BUFFER_SIZE);
-  globalPackBuffer->size =  pack_locn;
-  *packBufferSize = pack_locn;
-
-  if (RtsFlags.GranFlags.GranSimStats.Global) {
-    globalGranStats.tot_packets++; 
-    globalGranStats.tot_packet_size += pack_locn; 
-  }
-  IF_GRAN_DEBUG(pack,
-    PrintPacket(globalPackBuffer));
-
-  return (globalPackBuffer);
-}
-# endif  /* GRAN */
-
-#if defined(GRAN)
-
-/*
-   PackTSO and PackStkO are entry points for two special kinds of closure
-   which are used in the parallel RTS.  Compared with other closures they
-   are rather awkward to pack because they don't follow the normal closure
-   layout (where all pointers occur before all non-pointers).  Luckily,
-   they're only needed when migrating threads between processors.  */
-
-//@cindex PackTSO
-rtsPackBuffer*
-PackTSO(tso, packBufferSize)
-StgTSO *tso;
-nat *packBufferSize;
-{
-  extern rtsPackBuffer *globalPackBuffer;
-  IF_GRAN_DEBUG(pack,
-               belch("** Packing TSO %d (%p)", tso->id, tso));
-  *packBufferSize = 0;
-  // PackBuffer[0] = PackBuffer[1] = 0; ???
-  return(globalPackBuffer);
-}
-
-//@cindex PackStkO
-static rtsPackBuffer*
-PackStkO(stko, packBufferSize)
-StgPtr stko;
-nat *packBufferSize;
-{
-  extern rtsPackBuffer *globalPackBuffer;
-  IF_GRAN_DEBUG(pack,
-               belch("** Packing STKO %p", stko));
-  *packBufferSize = 0;
-  // PackBuffer[0] = PackBuffer[1] = 0;
-  return(globalPackBuffer);
-}
-
-static void
-PackFetchMe(StgClosure *closure)
-{
-  barf("{PackFetchMe}Daq Qagh: no FetchMe closures in GRAN!");
-}
-
-#elif defined(PAR)
-
-static rtsPackBuffer*
-PackTSO(tso, packBufferSize)
-StgTSO *tso;
-nat *packBufferSize;
-{
-  barf("{PackTSO}Daq Qagh: trying to pack a TSO %d (%p) of size %d; thread migrations not supported, yet",
-       tso->id, tso, packBufferSize);
-}
-
-rtsPackBuffer*
-PackStkO(stko, packBufferSize)
-StgPtr stko;
-nat *packBufferSize;
-{
-  barf("{PackStkO}Daq Qagh: trying to pack a STKO (%p) of size %d; thread migrations not supported, yet",
-       stko, packBufferSize);
-}
-
-//@cindex PackFetchMe
-static void
-PackFetchMe(StgClosure *closure)
-{
-  StgInfoTable *ip;
-  nat i;
-  int offset;
-#if defined(DEBUG)
-  nat x = pack_locn;
-#endif
-
-#if defined(GRAN)
-  barf("{PackFetchMe}Daq Qagh: no FetchMe closures in GRAN!");
-#else
-  offset = OffsetFor(closure);
-  if (!NotYetPacking(offset)) {
-    IF_PAR_DEBUG(pack,
-                belch("*>.. Packing FETCH_ME for closure %p (s) as offset to %d",
-                      closure, info_type(closure), offset));
-    PackOffset(offset);
-    // unpacked_size += 0;   // unpacked_size unchanged (closure is shared!!)
-    return;
-  }
-
-  /* Need a GA even when packing a constructed FETCH_ME (cruel world!) */
-  AmPacking(closure);
-  /* FMs must be always globalised */
-  GlobaliseAndPackGA(closure);
-
-  IF_PAR_DEBUG(pack,
-              belch("*>.. Packing FETCH_ME for closure %p (%s) with GA: ((%x, %d, %x))",
-                    closure, info_type(closure), 
-                    globalPackBuffer->buffer[pack_locn-2],
-                    globalPackBuffer->buffer[pack_locn-1],
-                    globalPackBuffer->buffer[pack_locn-3]));
-
-  /* Pack a FetchMe closure instead of closure */
-  ip = &stg_FETCH_ME_info;
-  /* this assumes that the info ptr is always the first word in a closure*/
-  Pack((StgWord)ip);
-  for (i = 1; i < _HS; ++i)               // pack rest of fixed header
-    Pack((StgWord)*(((StgPtr)closure)+i));
-  
-  unpacked_size += sizeofW(StgFetchMe);
-  /* size of FETCHME in packed is the same as that constant */
-  ASSERT(pack_locn-x==PACK_FETCHME_SIZE);
-  /* In the pack buffer the pointer to a GA (in the FetchMe closure) 
-     is expanded to the full GA; this is a compile-time const */
-  //ASSERT(PACK_FETCHME_SIZE == sizeofW(StgFetchMe)-1+PACK_GA_SIZE);  
-#endif
-}
-
-#endif
-
-#ifdef DIST
-static void
-PackRemoteRef(StgClosure *closure)
-{
-  StgInfoTable *ip;
-  nat i;
-  int offset;
-
-  offset = OffsetFor(closure);
-  if (!NotYetPacking(offset)) {
-    PackOffset(offset);
-    unpacked_size += 2;
-    return;
-  }
-
-  /* Need a GA even when packing a constructed REMOTE_REF (cruel world!) */
-  AmPacking(closure);
-  
-  /* basically we just Globalise, but for sticky things we can't have multiple GAs,
-     so we must prevent the GAs being split.
-     
-     In returning things to the true sticky owner, this case is already handled, but for
-     anything else we just give up at the moment... This needs to be fixed! 
-  */
-  { globalAddr *ga;
-    ga = LAGAlookup(closure); // surely this ga must exist?
-    
-    // ***************************************************************************
-    // ***************************************************************************
-    // REMOTE_REF HACK - dual is in SetGAandCommonUp
-    // - prevents the weight from ever reaching zero
-    if(ga != NULL) 
-      ga->weight=0x06660666; //anything apart from 0 really...
-    // ***************************************************************************
-    // ***************************************************************************
-    
-    if((ga != NULL)&&(ga->weight / 2 <= 2))
-      barf("Cant split the weight any further when packing REMOTE_REF for closure %p (%s) with GA: ((%x, %d, %x))",
-               closure, info_type(closure), 
-               ga->payload.gc.gtid, ga->payload.gc.slot, ga->weight);                               
-  } 
-  GlobaliseAndPackGA(closure);
-      
-  IF_PAR_DEBUG(pack,
-              belch("*>.. Packing REMOTE_REF for closure %p (%s) with GA: ((%x, %d, %x))",
-                    closure, info_type(closure), 
-                    globalPackBuffer->buffer[pack_locn-2],
-                    globalPackBuffer->buffer[pack_locn-1],
-                    globalPackBuffer->buffer[pack_locn-3]));
-
-  /* Pack a REMOTE_REF closure instead of closure */
-  ip = &stg_REMOTE_REF_info;
-  /* this assumes that the info ptr is always the first word in a closure*/
-  Pack((StgWord)ip);
-  for (i = 1; i < _HS; ++i)               // pack rest of fixed header
-    Pack((StgWord)*(((StgPtr)closure)+i));
-  
-  unpacked_size += PACK_FETCHME_SIZE;
-}
-#endif /* DIST */
-
-//@node Packing Closures,  , Packing Sections of Nearby Graph, Packing Functions
-//@subsubsection Packing Closures
-/*
-  Packing Closures
-
-  @PackClosure@ is the heart of the normal packing code.  It packs a single
-  closure into the pack buffer, skipping over any indirections and
-  globalising it as necessary, queues any child pointers for further
-  packing, and turns it into a @FetchMe@ or revertible black hole (@RBH@)
-  locally if it was a thunk.  Before the actual closure is packed, a
-  suitable global address (GA) is inserted in the pack buffer.  There is
-  always room to pack a fetch-me to the closure (guaranteed by the
-  RoomToPack calculation), and this is packed if there is no room for the
-  entire closure.
-
-  Space is allocated for any primitive array children of a closure, and
-  hence a primitive array can always be packed along with it's parent
-  closure.  */
-
-//@cindex PackClosure
-
-# if defined(PAR)
-
-void
-PackClosure(closure)
-StgClosure *closure;
-{
-  StgInfoTable *info;
-  nat clpack_locn;
-
-  ASSERT(LOOKS_LIKE_GHC_INFO(get_itbl(closure)));
-
-  closure = UNWIND_IND(closure);
-  /* now closure is the thing we want to pack */
-  info = get_itbl(closure);
-
-  clpack_locn = OffsetFor(closure);
-
-  /* If the closure has been packed already, just pack an indirection to it
-     to guarantee that the graph doesn't become a tree when unpacked */
-  if (!NotYetPacking(clpack_locn)) {
-    PackOffset(clpack_locn);
-    return;
-  }
-
-  switch (info->type) {
-
-  case CONSTR_CHARLIKE:
-    IF_PAR_DEBUG(pack,
-                belch("*>^^ Packing a charlike closure %d", 
-                      ((StgIntCharlikeClosure*)closure)->data));
-    
-    PackPLC((StgPtr)CHARLIKE_CLOSURE(((StgIntCharlikeClosure*)closure)->data));
-    // NB: unpacked_size of a PLC is 0
-    return;
-      
-  case CONSTR_INTLIKE:
-    {
-      StgInt val = ((StgIntCharlikeClosure*)closure)->data;
-
-      if ((val <= MAX_INTLIKE) && (val >= MIN_INTLIKE)) {
-       IF_PAR_DEBUG(pack,
-                    belch("*>^^ Packing a small intlike %d as a PLC", 
-                          val));
-       PackPLC((StgPtr)INTLIKE_CLOSURE(val));
-       // NB: unpacked_size of a PLC is 0
-       return;
-      } else {
-       IF_PAR_DEBUG(pack,
-                    belch("*>^^ Packing a big intlike %d as a normal closure", 
-                          val));
-       PackGeneric(closure);
-       return;
-      }
-    }
-
-  case CONSTR:
-  case CONSTR_1_0:
-  case CONSTR_0_1:
-  case CONSTR_2_0:
-  case CONSTR_1_1:
-  case CONSTR_0_2:
-    /* it's a constructor (i.e. plain data) */
-    IF_PAR_DEBUG(pack,
-                belch("*>^^ Packing a CONSTR %p (%s) using generic packing", 
-                      closure, info_type(closure)));
-    PackGeneric(closure);
-    return;
-
-  case THUNK_STATIC:       // ToDo: check whether that's ok
-  case FUN_STATIC:       // ToDo: check whether that's ok
-  case CONSTR_STATIC:
-  case CONSTR_NOCAF_STATIC:// For now we ship indirections to CAFs: They are
-                          // evaluated on each PE if needed
-    IF_PAR_DEBUG(pack,
-                belch("*>~~ Packing a %p (%s) as a PLC", 
-                      closure, info_type(closure)));
-
-    PackPLC((StgPtr)closure);
-    // NB: unpacked_size of a PLC is 0
-    return;
-
-  case THUNK_SELECTOR: 
-    {
-      StgClosure *selectee = ((StgSelector *)closure)->selectee;
-
-      IF_PAR_DEBUG(pack,
-                  belch("*>** Found THUNK_SELECTOR at %p (%s) pointing to %p (%s); using PackGeneric", 
-                        closure, info_type(closure), 
-                        selectee, info_type(selectee)));
-      PackGeneric(closure);
-      /* inlined code; probably could use PackGeneric
-      Pack((StgWord)(*(StgPtr)closure));  
-      Pack((StgWord)(selectee));
-      QueueClosure(selectee);
-      unpacked_size += 2;
-      */
-    }
-    return;
-
-  case  FUN:
-  case FUN_1_0:
-  case FUN_0_1:
-  case FUN_2_0:
-  case FUN_1_1:
-  case FUN_0_2:
-  case  THUNK:
-  case THUNK_1_0:
-  case THUNK_0_1:
-  case THUNK_2_0:
-  case THUNK_1_1:
-  case THUNK_0_2:
-    PackGeneric(closure);
-    return;
-
-  case AP_UPD:
-  case PAP:
-    /* 
-    barf("*>   Packing of PAP not implemented %p (%s)",
-                      closure, info_type(closure));
-        
-       Currently we don't pack PAPs; we pack a FETCH_ME to the closure, 
-       instead. Note that since PAPs contain a chunk of stack as payload,
-       implementing packing of PAPs is a first step towards thread migration.
-    IF_PAR_DEBUG(pack,
-                belch("*>.. Packing a PAP closure at %p (%s) as a FETCH_ME", 
-                      closure, info_type(closure)));
-    PackFetchMe(closure);
-    */
-    PackPAP((StgPAP *)closure);
-    return;
-
-  case CAF_BLACKHOLE:
-  case BLACKHOLE:
-  case BLACKHOLE_BQ:
-  case SE_BLACKHOLE:
-  case SE_CAF_BLACKHOLE:
-  case RBH:
-  case FETCH_ME:
-  case FETCH_ME_BQ:
-
-    /* If it's a (revertible) black-hole, pack a FetchMe closure to it */
-    //ASSERT(pack_locn > PACK_HDR_SIZE);
-    
-    IF_PAR_DEBUG(pack,
-                belch("*>.. Packing a BH-like closure at %p (%s) as a FETCH_ME", 
-                      closure, info_type(closure)));
-    /* NB: in case of a FETCH_ME this might build up a chain of FETCH_MEs;
-           phps short-cut the GA here */
-    PackFetchMe(closure);
-    return;
-
-#ifdef DIST    
-  case REMOTE_REF:
-    IF_PAR_DEBUG(pack,
-                belch("*>.. Packing %p (%s) as a REMOTE_REF", 
-                      closure, info_type(closure)));
-    PackRemoteRef(closure);
-    /* we hopefully don't end up with a chain of REMOTE_REFs!!!!!!!!!! */
-
-    return;
-#endif  
-    
-  case TSO:
-  case MVAR:
-#ifdef DIST
-          IF_PAR_DEBUG(pack,
-                belch("*>.. Packing %p (%s) as a RemoteRef", 
-                      closure, info_type(closure)));
-    PackRemoteRef(closure);
-#else
-    barf("{Pack}Daq Qagh: Only GdH can pack %p (%s)", 
-        closure, info_type(closure));
-#endif    
-    return;
-    
-  case ARR_WORDS:
-    PackArray(closure);
-    return;
-
-  case MUT_ARR_PTRS:
-  case MUT_ARR_PTRS_FROZEN:
-  case MUT_VAR:
-    /* 
-       Eventually, this should use the same packing routine as ARR_WRODS
-
-       GlobaliseAndPackGA(closure);
-       PackArray(closure);
-       return;
-    */
-    barf("Qagh{Pack}Doq: packing of mutable closures not yet implemented: %p (%s)",
-        closure, info_type(closure));
-
-#  ifdef DEBUG
-  case BCO:
-    barf("{Pack}Daq Qagh: found BCO closure %p (%s); GUM hates interpreted code", 
-        closure, info_type(closure));
-    /* never reached */
-    
-    // check error cases only in a debugging setup
-  case RET_BCO:
-  case RET_SMALL:
-  case RET_VEC_SMALL:
-  case RET_BIG:
-  case RET_VEC_BIG:
-  case RET_DYN:
-    barf("{Pack}Daq Qagh: found return vector %p (%s) when packing (thread migration not implemented)", 
-        closure, info_type(closure));
-    /* never reached */
-    
-  case UPDATE_FRAME:
-  case STOP_FRAME:
-  case CATCH_FRAME:
-  case SEQ_FRAME:
-    barf("{Pack}Daq Qagh: found stack frame %p (%s) when packing (thread migration not implemented)", 
-        closure, info_type(closure));
-    /* never reached */
-
-  case BLOCKED_FETCH:
-  case EVACUATED:
-    /* something's very wrong */
-    barf("{Pack}Daq Qagh: found %s (%p) when packing", 
-        info_type(closure), closure);
-    /* never reached */
-
-  case IND:
-  case IND_OLDGEN:
-  case IND_PERM:
-  case IND_OLDGEN_PERM:
-  case IND_STATIC:
-    barf("Pack: found IND_... after shorting out indirections %d (%s)", 
-        (nat)(info->type), info_type(closure));
-
-  case WEAK:
-  case FOREIGN:
-  case STABLE_NAME:
-    barf("Pack: found foreign thingy; not yet implemented in %d (%s)", 
-        (nat)(info->type), info_type(closure));
-#endif
-
-  default:
-    barf("Pack: strange closure %d", (nat)(info->type));
-  } /* switch */
-}
-
-/*
-  Pack a constructor of unknown size.
-  Similar to PackGeneric but without creating GAs.
-*/
-#if 0
-//@cindex PackConstr
-static void
-PackConstr(StgClosure *closure)
-{
-  StgInfoTable *info;
-  nat size, ptrs, nonptrs, vhs, i;
-  char str[80];
-
-  ASSERT(LOOKS_LIKE_GHC_INFO(closure->header.info));
-
-  /* get info about basic layout of the closure */
-  info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
-
-  ASSERT(info->type == CONSTR ||
-         info->type == CONSTR_1_0 ||
-         info->type == CONSTR_0_1 ||
-         info->type == CONSTR_2_0 ||
-         info->type == CONSTR_1_1 ||
-         info->type == CONSTR_0_2);
-
-  IF_PAR_DEBUG(pack,
-              fprintf(stderr, "*>^^ packing a constructor at %p (%s) (size=%d, ptrs=%d, nonptrs=%d)\n",
-                      closure, info_type(closure), size, ptrs, nonptrs));
-
-  /* Primitive arrays have gone; now we have (MUT_)ARR_WORDS etc */
-
-  if (!RoomToPack(PACK_GA_SIZE + _HS + vhs + nonptrs, ptrs)) {
-    IF_PAR_DEBUG(pack,
-                belch("*>&& pack buffer is full; packing FETCH_ME for closure %p (%s)",
-                      closure, info_type(closure)));
-    PackFetchMe(closure);
-    return;
-  }
-
-  /* Record the location of the GA */
-  AmPacking(closure);
-
-  /* Pack Constructor marker */
-  Pack((StgWord)2);
-
-  /* pack fixed and variable header */
-  for (i = 0; i < _HS + vhs; ++i)
-    Pack((StgWord)*(((StgPtr)closure)+i));
-      
-  /* register all ptrs for further packing */
-  for (i = 0; i < ptrs; ++i)
-    QueueClosure(((StgClosure *) *(((StgPtr)closure)+(_HS+vhs)+i)));
-
-  /* pack non-ptrs */
-  for (i = 0; i < nonptrs; ++i)
-    Pack((StgWord)*(((StgPtr)closure)+(_HS+vhs)+ptrs+i));
-}
-#endif
-
-/*
-  Generic packing code.
-  This code is performed for `ordinary' closures such as CONSTR, THUNK etc.
-*/
-//@cindex PackGeneric
-static void
-PackGeneric(StgClosure *closure)
-{
-  StgInfoTable *info;
-  StgClosure *rbh;
-  nat size, ptrs, nonptrs, vhs, i, m;
-  char str[80];
-
-  ASSERT(LOOKS_LIKE_COOL_CLOSURE(closure));
-
-  /* get info about basic layout of the closure */
-  info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
-
-  ASSERT(!IS_BLACK_HOLE(closure));
-
-  IF_PAR_DEBUG(pack,
-              fprintf(stderr, "*>== %p (%s): generic packing (size=%d, ptrs=%d, nonptrs=%d)\n",
-                      closure, info_type(closure), size, ptrs, nonptrs));
-
-  /* packing strategies: how many thunks to add to a packet; 
-     default is infinity i.e. RtsFlags.ParFlags.thunksToPack==0 */
-  if (RtsFlags.ParFlags.thunksToPack &&
-      packed_thunks >= RtsFlags.ParFlags.thunksToPack &&
-      closure_THUNK(closure)) {
-    IF_PAR_DEBUG(pack,
-                belch("*>&& refusing to pack more than %d thunks per packet; packing FETCH_ME for closure %p (%s)",
-                      packed_thunks, closure, info_type(closure)));
-    PackFetchMe(closure);
-    return;
-  }
-
-  /* Primitive arrays have gone; now we have (MUT_)ARR_WORDS etc */
-
-  if (!RoomToPack(PACK_GA_SIZE + _HS + vhs + nonptrs, ptrs)) {
-    IF_PAR_DEBUG(pack,
-                belch("*>&& pack buffer is full; packing FETCH_ME for closure %p (%s)",
-                      closure, info_type(closure)));
-    PackFetchMe(closure);
-    return;
-  }
-
-  /* Record the location of the GA */
-  AmPacking(closure);
-  /* Allocate a GA for this closure and put it into the buffer */
-  /* Checks for globalisation scheme; default: globalise everything thunks */
-  if ( RtsFlags.ParFlags.globalising == 0 || 
-       (closure_THUNK(closure) && !closure_UNPOINTED(closure)) )
-    GlobaliseAndPackGA(closure);
-  else
-    Pack((StgWord)2);  // marker for unglobalised closure
-
-
-  ASSERT(!(info->type == ARR_WORDS || info->type == MUT_ARR_PTRS ||
-          info->type == MUT_ARR_PTRS_FROZEN || info->type == MUT_VAR));
-
-  /* At last! A closure we can actually pack! */
-  if (ip_MUTABLE(info) && ((info->type != FETCH_ME)||(info->type != REMOTE_REF)))
-    barf("*>// %p (%s) PackClosure: trying to replicate a Mutable closure!",
-        closure, info_type(closure));
-      
-  /* 
-     Remember, the generic closure layout is as follows:
-        +-------------------------------------------------+
-       | FIXED HEADER | VARIABLE HEADER | PTRS | NON-PRS |
-        +-------------------------------------------------+
-  */
-  /* pack fixed and variable header */
-  for (i = 0; i < _HS + vhs; ++i)
-    Pack((StgWord)*(((StgPtr)closure)+i));
-      
-  /* register all ptrs for further packing */
-  for (i = 0; i < ptrs; ++i)
-    QueueClosure(((StgClosure *) *(((StgPtr)closure)+(_HS+vhs)+i)));
-
-  /* pack non-ptrs */
-  for (i = 0; i < nonptrs; ++i)
-    Pack((StgWord)*(((StgPtr)closure)+(_HS+vhs)+ptrs+i));
-      
-  // ASSERT(_HS+vhs+ptrs+nonptrs==size);
-  if ((m=_HS+vhs+ptrs+nonptrs)<size) {
-    IF_PAR_DEBUG(pack,
-                belch("*>** WARNING: slop in closure %p (%s); filling %d words; SHOULD NEVER HAPPEN",
-                      closure, info_type(closure), size-m));
-    for (i=m; i<size; i++) 
-      Pack((StgWord)*(((StgPtr)closure)+i));
-  }
-
-  unpacked_size += size;
-  //unpacked_size += (size < MIN_UPD_SIZE) ? MIN_UPD_SIZE : size;
-
-  /*
-   * Record that this is a revertable black hole so that we can fill in
-   * its address from the fetch reply.  Problem: unshared thunks may cause
-   * space leaks this way, their GAs should be deallocated following an
-   * ACK.
-   */
-      
-  if (closure_THUNK(closure) && !closure_UNPOINTED(closure)) { 
-    rbh = convertToRBH(closure);
-    ASSERT(size>=_HS+MIN_UPD_SIZE); // min size for any updatable closure
-    ASSERT(rbh == closure);         // rbh at the same position (minced version)
-    packed_thunks++;
-  } else if ( closure==graph_root ) {
-    packed_thunks++;                // root of graph is counted as a thunk
-  }
-}
-/*
-  Pack an array of words.
-  ToDo: implement packing of MUT_ARRAYs
-*/
-
-//@cindex PackArray
-static void
-PackArray(StgClosure *closure)
-{
-  StgInfoTable *info;
-  nat size, ptrs, nonptrs, vhs;
-  nat i, n;
-  char str[80];
-
-  /* get info about basic layout of the closure */
-  info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
-
-  ASSERT(info->type == ARR_WORDS || info->type == MUT_ARR_PTRS ||
-        info->type == MUT_ARR_PTRS_FROZEN || info->type == MUT_VAR);
-
-  n = ((StgArrWords *)closure)->words;
-  // this includes the header!: arr_words_sizeW(stgCast(StgArrWords*,q)); 
-
-  IF_PAR_DEBUG(pack,
-              belch("*>== %p (%s): packing an array of %d words (size=%d)\n",
-                    closure, info_type(closure), n,
-                    arr_words_sizeW((StgArrWords *)closure)));
-
-  /* check that we have enough room in the pack buffer */
-  if (!RoomToPack(PACK_GA_SIZE + _HS + vhs + nonptrs, ptrs)) {
-    IF_PAR_DEBUG(pack,
-                belch("*>&& pack buffer is full; packing FETCH_ME for closure %p (%s)",
-                      closure, info_type(closure)));
-    PackFetchMe(closure);
-    return;
-  }
-
-  /* global stats about arrays sent */
-  if (RtsFlags.ParFlags.ParStats.Global &&
-      RtsFlags.GcFlags.giveStats > NO_GC_STATS) {
-    globalParStats.tot_arrs++;
-    globalParStats.tot_arr_size += ((StgArrWords *)closure)->words;
-  }
-
-  /* record offset of the closure and allocate a GA */
-  AmPacking(closure);
-  /* Checks for globalisation scheme; default: globalise everything thunks */
-  if ( RtsFlags.ParFlags.globalising == 0 || 
-       (closure_THUNK(closure) && !closure_UNPOINTED(closure)) )
-    GlobaliseAndPackGA(closure);
-  else
-    Pack((StgWord)2);  // marker for unglobalised closure
-
-  /* Pack the header (2 words: info ptr and the number of words to follow) */
-  Pack((StgWord)*(StgPtr)closure);
-  Pack(((StgArrWords *)closure)->words);
-
-  /* pack the payload of the closure (all non-ptrs) */
-  for (i=0; i<n; i++)
-    Pack((StgWord)((StgArrWords *)closure)->payload[i]);
-
-  unpacked_size += arr_words_sizeW((StgArrWords *)closure);
-}
-
-/*
-   Pack a PAP closure.
-   Note that the representation of a PAP in the buffer is different from
-   its representation in the heap. In particular, pointers to local
-   closures are packed directly as FETCHME closures, using
-   PACK_FETCHME_SIZE words to represent q 1 word pointer in the orig graph
-   structure. To account for the difference in size we store the packed
-   size of the closure as part of the PAP's variable header in the buffer.
-*/
-
-//@cindex PackPAP
-static void
-PackPAP(StgPAP *pap) {
-  nat n, i, j, pack_start;
-  StgPtr p, q;
-  const StgInfoTable* info;
-  StgWord bitmap;
-  /* debugging only */
-  StgPtr end;
-  nat size, ptrs, nonptrs, vhs;
-  char str[80];
-  nat unpacked_size_before_PAP, FMs_in_PAP=0; // debugging only
-
-  /* This is actually a setup invariant; checked here 'cause it affects PAPs*/
-  //ASSERT(PACK_FETCHME_SIZE == sizeofW(StgFetchMe)-1+PACK_GA_SIZE);
-  ASSERT(NotYetPacking(OffsetFor((StgClosure *)pap)));
-  IF_DEBUG(sanity,
-          unpacked_size_before_PAP = unpacked_size);
-
-  n = (nat)(pap->n_args);
-
-  /* get info about basic layout of the closure */
-  info = get_closure_info((StgClosure *)pap, &size, &ptrs, &nonptrs, &vhs, str);
-  ASSERT(ptrs==0 && nonptrs==0 && size==pap_sizeW(pap));
-
-  IF_PAR_DEBUG(pack,
-              belch("*>**  %p (%s): PackPAP: packing PAP with %d words (size=%d; ptrs=%d; nonptrs=%d:", 
-                    (StgClosure *)pap, info_type((StgClosure *)pap),
-                    n, size, ptrs, nonptrs);
-               printClosure((StgClosure *)pap));
-
-  /* check that we have enough room in the pack buffer */
-  if (!RoomToPack(PACK_GA_SIZE + _HS + vhs + nonptrs, ptrs)) {
-    IF_PAR_DEBUG(pack,
-                belch("*>&& pack buffer is full; packing FETCH_ME for closure %p (%s)",
-                      (StgClosure *)pap, info_type((StgClosure *)pap)));
-    PackFetchMe((StgClosure *)pap);
-    return;
-  }
-
-  /* record offset of the closure and allocate a GA */
-  AmPacking((StgClosure *)pap);
-  /* Checks for globalisation scheme; default: globalise everything thunks */
-  if ( RtsFlags.ParFlags.globalising == 0 || 
-       (closure_THUNK(pap) && !closure_UNPOINTED(pap)) )
-    GlobaliseAndPackGA((StgClosure *)pap);
-  else
-    Pack((StgWord)2);  // marker for unglobalised closure
-
-  /* Pack the PAP header */
-  Pack((StgWord)(pap->header.info));
-  Pack((StgWord)(pap->n_args));
-  Pack((StgWord)(pap->fun));
-  pack_start = pack_locn;   // to compute size of PAP in buffer
-  Pack((StgWord)0);    // this will be filled in later (size of PAP in buffer)
-
-  /* Pack the payload of a PAP i.e. a stack chunk */
-  /* pointers to start of stack chunk */
-  p = (StgPtr)(pap->payload);
-  end = (StgPtr)((nat)pap+pap_sizeW(pap)*sizeof(StgWord)); // (StgPtr)((nat)pap+sizeof(StgPAP)+sizeof(StgPtr)*n);
-  while (p<end) {
-    /* the loop body has been borrowed from scavenge_stack */
-    q = (StgPtr)*p;
-
-    /* If we've got a tag, pack all words in that block */
-    if (IS_ARG_TAG((W_)q)) {   // q stands for the no. of non-ptrs to follow
-      nat m = ARG_TAG((W_)q);      // first word after this block
-      IF_PAR_DEBUG(pack,
-                  belch("*>**    PackPAP @ %p: packing %d words (tagged), starting @ %p", 
-                        p, m, p));
-      for (i=0; i<m+1; i++)
-       Pack((StgWord)*(p+i));
-      p += m+1;                // m words + the tag
-      continue;
-    }
-     
-    /* If q is is a pointer to a (heap allocated) closure we pack a FETCH_ME
-       ToDo: provide RTS flag to also pack these closures
-    */
-    if (! LOOKS_LIKE_GHC_INFO(q) ) {
-      /* distinguish static closure (PLC) from other closures (FM) */
-      switch (get_itbl((StgClosure*)q)->type) {
-      case CONSTR_CHARLIKE:
-       IF_PAR_DEBUG(pack,
-                    belch("*>**    PackPAP: packing a charlike closure %d", 
-                          ((StgIntCharlikeClosure*)q)->data));
-    
-       PackPLC((StgPtr)CHARLIKE_CLOSURE(((StgIntCharlikeClosure*)q)->data));
-       p++;
-       break;
-      
-      case CONSTR_INTLIKE:
-       {
-         StgInt val = ((StgIntCharlikeClosure*)q)->data;
-      
-         if ((val <= MAX_INTLIKE) && (val >= MIN_INTLIKE)) {
-           IF_PAR_DEBUG(pack,
-                        belch("*>**    PackPAP: Packing ptr to a small intlike %d as a PLC", val));
-           PackPLC((StgPtr)INTLIKE_CLOSURE(val));
-           p++;
-           break;
-         } else {
-           IF_PAR_DEBUG(pack,
-                        belch("*>**    PackPAP: Packing a ptr to a big intlike %d as a FM", 
-                              val));
-           Pack((StgWord)(ARGTAG_MAX+1));
-           PackFetchMe((StgClosure *)q);
-           p++;
-           IF_DEBUG(sanity, FMs_in_PAP++);
-           break;
-         }
-       }
-       case THUNK_STATIC:       // ToDo: check whether that's ok
-       case FUN_STATIC:       // ToDo: check whether that's ok
-       case CONSTR_STATIC:
-       case CONSTR_NOCAF_STATIC:
-         {
-           IF_PAR_DEBUG(pack,
-                        belch("*>**    PackPAP: packing a ptr to a %p (%s) as a PLC", 
-                              q, info_type((StgClosure *)q)));
-           
-           PackPLC((StgPtr)q);
-           p++;
-           break;
-         }
-      default:
-         IF_PAR_DEBUG(pack,
-                      belch("*>**    PackPAP @ %p: packing FM to %p (%s)", 
-                            p, q, info_type((StgClosure*)q)));
-         Pack((StgWord)(ARGTAG_MAX+1));
-         PackFetchMe((StgClosure *)q);
-         p++;
-         IF_DEBUG(sanity, FMs_in_PAP++);
-         break;
-      }
-      continue;
-    }
-       
-    /* 
-     * Otherwise, q must be the info pointer of an activation
-     * record.  All activation records have 'bitmap' style layout
-     * info.
-     */
-    info  = get_itbl((StgClosure *)p);
-    switch (info->type) {
-       
-      /* Dynamic bitmap: the mask is stored on the stack */
-    case RET_DYN:
-      IF_PAR_DEBUG(pack,
-                  belch("*>**    PackPAP @ %p: RET_DYN", 
-                        p));
-
-      /* Pack the header as is */
-      Pack((StgWord)(((StgRetDyn *)p)->info));
-      Pack((StgWord)(((StgRetDyn *)p)->liveness));
-      Pack((StgWord)(((StgRetDyn *)p)->ret_addr));
-
-      bitmap = ((StgRetDyn *)p)->liveness;
-      p      = (P_)&((StgRetDyn *)p)->payload[0];
-      goto small_bitmap;
-
-      /* probably a slow-entry point return address: */
-    case FUN:
-    case FUN_STATIC:
-      {
-      IF_PAR_DEBUG(pack,
-                  belch("*>**    PackPAP @ %p: FUN or FUN_STATIC", 
-                        p));
-
-      Pack((StgWord)(((StgClosure *)p)->header.info));
-      p++;
-
-      goto follow_srt; //??
-      }
-
-      /* Using generic code here; could inline as in scavenge_stack */
-    case UPDATE_FRAME:
-      {
-       StgUpdateFrame *frame = (StgUpdateFrame *)p;
-       nat type = get_itbl(frame->updatee)->type;
-
-       ASSERT(type==BLACKHOLE || type==CAF_BLACKHOLE || type==BLACKHOLE_BQ);
-
-       IF_PAR_DEBUG(pack,
-                    belch("*>**    PackPAP @ %p: UPDATE_FRAME (updatee=%p; link=%p)", 
-                          p, frame->updatee, frame->link));
-
-       Pack((StgWord)(frame->header.info));
-       Pack((StgWord)(frame->link));     // ToDo: fix intra-stack pointer
-       Pack((StgWord)(frame->updatee));  // ToDo: follow link 
-
-       p += 3;
-      }
-
-      /* small bitmap (< 32 entries, or 64 on a 64-bit machine) */
-    case STOP_FRAME:
-      {
-       IF_PAR_DEBUG(pack,
-                    belch("*>**    PackPAP @ %p: STOP_FRAME", 
-                          p));
-       Pack((StgWord)((StgStopFrame *)p)->header.info);
-       p++;
-      }
-
-    case CATCH_FRAME:
-      {
-       IF_PAR_DEBUG(pack,
-                    belch("*>**    PackPAP @ %p: CATCH_FRAME (handler=%p)", 
-                          p, ((StgCatchFrame *)p)->handler));
-
-       Pack((StgWord)((StgCatchFrame *)p)->header.info);
-       Pack((StgWord)((StgCatchFrame *)p)->link); // ToDo: fix intra-stack pointer
-       Pack((StgWord)((StgCatchFrame *)p)->exceptions_blocked);
-       Pack((StgWord)((StgCatchFrame *)p)->handler);
-       p += 4;
-      }
-
-    case SEQ_FRAME:
-      {
-       IF_PAR_DEBUG(pack,
-                    belch("*>**    PackPAP @ %p: UPDATE_FRAME (link=%p)", 
-                          p, ((StgSeqFrame *)p)->link));
-
-       Pack((StgWord)((StgSeqFrame *)p)->header.info);
-       Pack((StgWord)((StgSeqFrame *)p)->link); // ToDo: fix intra-stack pointer
-
-        // ToDo: handle bitmap
-        bitmap = info->layout.bitmap;
-
-        p = (StgPtr)&(((StgClosure *)p)->payload);
-        goto small_bitmap;
-      }
-    case RET_BCO:
-    case RET_SMALL:
-    case RET_VEC_SMALL:
-      IF_PAR_DEBUG(pack,
-                  belch("*>**    PackPAP @ %p: RET_{BCO,SMALL,VEC_SMALL} (bitmap=%o)", 
-                        p, info->layout.bitmap));
-
-
-      Pack((StgWord)((StgClosure *)p)->header.info);
-      p++;
-      // ToDo: handle bitmap
-      bitmap = info->layout.bitmap;
-      /* this assumes that the payload starts immediately after the info-ptr */
-
-    small_bitmap:
-      while (bitmap != 0) {
-       if ((bitmap & 1) == 0) {
-         Pack((StgWord)(ARGTAG_MAX+1));
-         PackFetchMe((StgClosure *)*p++); // pack a FetchMe to the closure
-         IF_DEBUG(sanity, FMs_in_PAP++);
-       } else {
-         Pack((StgWord)*p++);
-       }
-       bitmap = bitmap >> 1;
-      }
-      
-    follow_srt:
-       IF_PAR_DEBUG(pack,
-                    belch("*>--    PackPAP: nothing to do for follow_srt"));
-      continue;
-
-      /* large bitmap (> 32 entries) */
-    case RET_BIG:
-    case RET_VEC_BIG:
-      {
-       StgPtr q;
-       StgLargeBitmap *large_bitmap;
-
-       IF_PAR_DEBUG(pack,
-                    belch("*>**    PackPAP @ %p: RET_{BIG,VEC_BIG} (large_bitmap=%p)", 
-                          p, info->layout.large_bitmap));
-
-
-       Pack((StgWord)((StgClosure *)p)->header.info);
-       p++;
-
-       large_bitmap = info->layout.large_bitmap;
-
-       for (j=0; j<large_bitmap->size; j++) {
-         bitmap = large_bitmap->bitmap[j];
-         q = p + BITS_IN(W_);
-         while (bitmap != 0) {
-           if ((bitmap & 1) == 0) {
-             Pack((StgWord)(ARGTAG_MAX+1));
-             PackFetchMe((StgClosure *)*p++); // ToDo: pack pointer(StgClosure *)*p = evacuate((StgClosure *)*p);
-             IF_DEBUG(sanity, FMs_in_PAP++);
-           } else {
-             Pack((StgWord)*p++);
-           }
-           bitmap = bitmap >> 1;
-         }
-         if (j+1 < large_bitmap->size) {
-           while (p < q) {
-             Pack((StgWord)(ARGTAG_MAX+1));
-             PackFetchMe((StgClosure *)*p++); // ToDo: pack pointer (StgClosure *)*p = evacuate((StgClosure *)*p);
-             IF_DEBUG(sanity, FMs_in_PAP++);
-           }
-         }
-       }
-
-       /* and don't forget to follow the SRT */
-       goto follow_srt;
-      }
-
-    default:
-      barf("PackPAP: weird activation record found on stack (@ %p): %d", 
-          p, (int)(info->type));
-    }
-  }
-  // fill in size of the PAP (only the payload!) in buffer
-  globalPackBuffer->buffer[pack_start] = (StgWord)(pack_locn - pack_start - 1*sizeofW(StgWord));
-  /*
-    We can use the generic pap_sizeW macro to compute the size of the
-    unpacked PAP because whenever we pack a new FETCHME as part of the
-    PAP's payload we also adjust unpacked_size accordingly (smart, aren't we?)
-
-    NB: the current PAP (un-)packing code  relies on the fact that
-    the size of the unpacked PAP + size of all unpacked FMs is the same as
-    the size of the packed PAP!!
-  */
-  unpacked_size += pap_sizeW(pap); // sizeofW(pap) + (nat)(globalPackBuffer->buffer[pack_start]);
-  IF_DEBUG(sanity,
-          ASSERT(unpacked_size-unpacked_size_before_PAP==pap_sizeW(pap)+FMs_in_PAP*sizeofW(StgFetchMe)));
-}
-# else  /* GRAN */
-
-/* Fake the packing of a closure */
-
-void
-PackClosure(closure)
-StgClosure *closure;
-{
-  StgInfoTable *info, *childInfo;
-  nat size, ptrs, nonptrs, vhs;
-  char info_hdr_ty[80];
-  nat i;
-  StgClosure *indirectee, *rbh;
-  char str[80];
-  rtsBool is_mutable, will_be_rbh, no_more_thunks_please;
-
-  is_mutable = rtsFalse;
-
-  /* In GranSim we don't pack and unpack closures -- we just simulate
-     packing by updating the bitmask. So, the graph structure is unchanged
-     i.e. we don't short out indirections here. -- HWL */
-
-  /* Nothing to do with packing but good place to (sanity) check closure;
-     if the closure is a thunk, it must be unique; otherwise we have copied
-     work at some point before that which violates one of our main global
-     assertions in GranSim/GUM */
-  ASSERT(!closure_THUNK(closure) || is_unique(closure));
-
-  IF_GRAN_DEBUG(pack,
-               belch("**  Packing closure %p (%s)",
-                     closure, info_type(closure)));
-
-  if (where_is(closure) != where_is(graph_root)) {
-    IF_GRAN_DEBUG(pack,
-                 belch("**   faking a FETCHME [current PE: %d, closure's PE: %d]",
-                       where_is(graph_root), where_is(closure)));
-
-    /* GUM would pack a FETCHME here; simulate that by increasing the */
-    /* unpacked size accordingly but don't pack anything -- HWL */
-    unpacked_size += _HS + 2 ; // sizeofW(StgFetchMe);
-    return; 
-  }
-
-  /* If the closure's not already being packed */
-  if (!NotYetPacking(closure)) 
-    /* Don't have to do anything in GrAnSim if closure is already */
-    /* packed -- HWL */
-    {
-      IF_GRAN_DEBUG(pack,
-                   belch("**    Closure %p is already packed and omitted now!",
-                           closure));
-      return;
-    }
-
-  switch (get_itbl(closure)->type) {
-    /* ToDo: check for sticky bit here? */
-    /* BH-like closures which must not be moved to another PE */
-    case CAF_BLACKHOLE:       /* # of ptrs, nptrs: 0,2 */
-    case SE_BLACKHOLE:        /* # of ptrs, nptrs: 0,2 */
-    case SE_CAF_BLACKHOLE:    /* # of ptrs, nptrs: 0,2 */
-    case BLACKHOLE:           /* # of ptrs, nptrs: 0,2 */
-    case BLACKHOLE_BQ:        /* # of ptrs, nptrs: 1,1 */
-    case RBH:                 /* # of ptrs, nptrs: 1,1 */
-      /* same for these parallel specific closures */
-    case BLOCKED_FETCH:
-    case FETCH_ME:
-    case FETCH_ME_BQ:
-      IF_GRAN_DEBUG(pack,
-       belch("**    Avoid packing BH-like closures (%p, %s)!", 
-             closure, info_type(closure)));
-      /* Just ignore RBHs i.e. they stay where they are */
-      return;
-
-    case THUNK_SELECTOR:
-      {
-       StgClosure *selectee = ((StgSelector *)closure)->selectee;
-
-       IF_GRAN_DEBUG(pack,
-                     belch("**    Avoid packing THUNK_SELECTOR (%p, %s) but queuing %p (%s)!", 
-                           closure, info_type(closure), selectee, info_type(selectee)));
-       QueueClosure(selectee);
-       IF_GRAN_DEBUG(pack,
-                     belch("**    [%p (%s) (Queueing closure) ....]",
-                           selectee, info_type(selectee)));
-      }
-      return;
-
-    case CONSTR_STATIC:
-    case CONSTR_NOCAF_STATIC:
-                                  /* For now we ship indirections to CAFs:
-                                  * They are evaluated on each PE if needed */
-      IF_GRAN_DEBUG(pack,
-       belch("**    Nothing to pack for %p (%s)!", 
-             closure, info_type(closure)));
-      // Pack(closure); GUM only
-      return;
-
-    case CONSTR_CHARLIKE:
-    case CONSTR_INTLIKE:
-      IF_GRAN_DEBUG(pack,
-       belch("**    Nothing to pack for %s (%p)!", 
-             closure, info_type(closure)));
-      // PackPLC(((StgIntCharlikeClosure *)closure)->data); GUM only
-      return;
-
-    case AP_UPD:   
-    case PAP:
-      /* partial applications; special treatment necessary? */
-      break;
-
-    case MVAR:
-      barf("{PackClosure}Daq Qagh: found an MVAR (%p, %s); ToDo: implement proper treatment of MVARs",
-          closure, info_type(closure));
-
-    case ARR_WORDS:
-    case MUT_VAR:
-    case MUT_ARR_PTRS:
-    case MUT_ARR_PTRS_FROZEN:
-      /* Mutable objects; require special treatment to ship all data */
-      is_mutable = rtsTrue;
-      break;     
-
-    case WEAK:
-    case FOREIGN:
-    case STABLE_NAME:
-         /* weak pointers and other FFI objects */
-      barf("{PackClosure}Daq Qagh: found an FFI object (%p, %s); FFI not yet supported by GranSim, sorry",
-          closure, info_type(closure));
-
-    case TSO:
-      /* parallel objects */
-      barf("{PackClosure}Daq Qagh: found a TSO when packing (%p, %s); thread migration not yet implemented, sorry",
-          closure, info_type(closure));
-
-    case BCO:
-      /* Hugs objects (i.e. closures used by the interpreter) */
-      barf("{PackClosure}Daq Qagh: found a Hugs closure when packing (%p, %s); GranSim not yet integrated with Hugs, sorry",
-          closure, info_type(closure));
-      
-    case IND:              /* # of ptrs, nptrs: 1,0 */
-    case IND_STATIC:       /* # of ptrs, nptrs: 1,0 */
-    case IND_PERM:         /* # of ptrs, nptrs: 1,1 */
-    case IND_OLDGEN:       /* # of ptrs, nptrs: 1,1 */
-    case IND_OLDGEN_PERM:  /* # of ptrs, nptrs: 1,1 */
-      /* we shouldn't find an indirection here, because we have shorted them
-        out at the beginning of this functions already.
-      */
-      break;
-      /* should be:
-      barf("{PackClosure}Daq Qagh: found indirection when packing (%p, %s)",
-          closure, info_type(closure));
-      */
-
-    case UPDATE_FRAME:
-    case CATCH_FRAME:
-    case SEQ_FRAME:
-    case STOP_FRAME:
-      /* stack frames; should never be found when packing for now;
-        once we support thread migration these have to be covered properly
-      */
-      barf("{PackClosure}Daq Qagh: found stack frame when packing (%p, %s)",
-          closure, info_type(closure));
-
-    case RET_BCO:
-    case RET_SMALL:
-    case RET_VEC_SMALL:
-    case RET_BIG:
-    case RET_VEC_BIG:
-    case RET_DYN:
-      /* vectored returns; should never be found when packing; */
-      barf("{PackClosure}Daq Qagh: found vectored return (%p, %s)",
-          closure, info_type(closure));
-
-    case INVALID_OBJECT:
-      barf("{PackClosure}Daq Qagh: found Invalid object (%p, %s)",
-          closure, info_type(closure));
-
-    default:
-      /* 
-        Here we know that the closure is a CONSTR, FUN or THUNK (maybe
-        a specialised version with wired in #ptr/#nptr info; currently
-        we treat these specialised versions like the generic version)
-      */
-    }     /* switch */
-
-    /* Otherwise it's not Fixed */
-
-    info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
-    will_be_rbh = closure_THUNK(closure) && !closure_UNPOINTED(closure);
-
-    IF_GRAN_DEBUG(pack,
-               belch("**    Info on closure %p (%s): size=%d; ptrs=%d",
-                     closure, info_type(closure),
-                     size, ptrs, 
-                     (will_be_rbh) ? "will become RBH" : "will NOT become RBH"));
-    
-    // check whether IS_UPDATABLE(closure) == !closure_UNPOINTED(closure) -- HWL
-    no_more_thunks_please = 
-      (RtsFlags.GranFlags.ThunksToPack>0) && 
-      (packed_thunks>=RtsFlags.GranFlags.ThunksToPack);
-
-    /*
-      should be covered by get_closure_info
-    if (info->type == FETCH_ME || info->type == FETCH_ME_BQ || 
-       info->type == BLACKHOLE || info->type == RBH )
-      size = ptrs = nonptrs = vhs = 0;
-    */
-    /* Now peek ahead to see whether the closure has any primitive */
-    /* array children */ 
-    /* 
-       ToDo: fix this code
-       for (i = 0; i < ptrs; ++i) {
-       P_ childInfo;
-       W_ childSize, childPtrs, childNonPtrs, childVhs;
-       
-       childInfo = get_closure_info(((StgPtrPtr) (closure))[i + _HS + vhs],
-       &childSize, &childPtrs, &childNonPtrs,
-       &childVhs, junk_str);
-       if (IS_BIG_MOTHER(childInfo)) {
-       reservedPAsize += PACK_GA_SIZE + _HS + 
-       childVhs + childNonPtrs +
-       childPtrs * PACK_FETCHME_SIZE;
-       PAsize += PACK_GA_SIZE + _HS + childSize;
-       PAptrs += childPtrs;
-       }
-       }
-    */
-    /* Don't pack anything (GrAnSim) if it's a black hole, or the buffer
-     * is full and it isn't a primitive array. N.B. Primitive arrays are
-     * always packed (because their parents index into them directly) */
-
-    if (IS_BLACK_HOLE(closure))
-       /*
-         ToDo: fix this code
-         || 
-         !(RoomToPack(PACK_GA_SIZE + _HS + vhs + nonptrs, ptrs) 
-         || IS_BIG_MOTHER(info))) 
-         */
-      return;
-
-    /* At last! A closure we can actually pack! */
-
-    if (closure_MUTABLE(closure)) // not nec. && (info->type != FETCHME))
-      belch("ghuH: Replicated a Mutable closure!");
-
-    if (RtsFlags.GranFlags.GranSimStats.Global &&  
-       no_more_thunks_please && will_be_rbh) {
-      globalGranStats.tot_cuts++;
-      if ( RtsFlags.GranFlags.Debug.pack ) 
-       belch("**    PackClosure (w/ ThunksToPack=%d): Cutting tree with root at %#x\n",
-               RtsFlags.GranFlags.ThunksToPack, closure);
-    } else if (will_be_rbh || (closure==graph_root) ) {
-      packed_thunks++;
-      globalGranStats.tot_thunks++;
-    }
-
-    if (no_more_thunks_please && will_be_rbh) 
-      return; /* don't pack anything */
-
-    /* actual PACKING done here --  HWL */
-    Pack(closure);         
-    for (i = 0; i < ptrs; ++i) {
-      /* extract i-th pointer from closure */
-      QueueClosure((StgClosure *)(closure->payload[i]));
-      IF_GRAN_DEBUG(pack,
-                   belch("**    [%p (%s) (Queueing closure) ....]",
-                         closure->payload[i], 
-                         info_type(*stgCast(StgPtr*,((closure)->payload+(i))))));
-                                  //^^^^^^^^^^^ payloadPtr(closure,i))));
-    }
-
-    /* 
-       for packing words (GUM only) do something like this:
-
-       for (i = 0; i < ptrs; ++i) {
-         Pack(payloadWord(obj,i+j));
-       }
-    */
-    /* Turn thunk into a revertible black hole. */
-    if (will_be_rbh) { 
-       rbh = convertToRBH(closure);
-       ASSERT(rbh != NULL);
-    }
-}
-# endif  /* PAR */
-
-//@node Low level packing routines, Unpacking routines, Packing Functions, Graph packing
-//@subsection Low level packing routines
-
-/*
-   @Pack@ is the basic packing routine.  It just writes a word of data into
-   the pack buffer and increments the pack location.  */
-
-//@cindex Pack
-
-# if defined(PAR)
-static  void
-Pack(data)
-StgWord data;
-{
-  ASSERT(pack_locn < RtsFlags.ParFlags.packBufferSize);
-  globalPackBuffer->buffer[pack_locn++] = data;
-}
-#endif
-
-#if defined(GRAN)
-static  void
-Pack(closure)
-StgClosure *closure;
-{
-  StgInfoTable *info;
-  nat size, ptrs, nonptrs, vhs;
-  char str[80];
-
-  /* This checks the size of the GrAnSim internal pack buffer. The simulated
-     pack buffer is checked via RoomToPack (as in GUM) */
-  if (pack_locn >= (int)globalPackBuffer->size+sizeofW(rtsPackBuffer)) 
-    reallocPackBuffer();
-
-  if (closure==(StgClosure*)NULL) 
-    belch("Qagh {Pack}Daq: Trying to pack 0");
-  globalPackBuffer->buffer[pack_locn++] = closure;
-  /* ASSERT: Data is a closure in GrAnSim here */
-  info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
-  // ToDo: is check for MIN_UPD_SIZE really needed? */
-  unpacked_size += _HS + (size < MIN_UPD_SIZE ? 
-                                       MIN_UPD_SIZE : 
-                                       size);
-}
-# endif  /* GRAN */
-
-/*
-   If a closure is local, make it global.  Then, divide its weight for
-   export.  The GA is then packed into the pack buffer.  */
-
-# if defined(PAR)
-//@cindex GlobaliseAndPackGA
-static void
-GlobaliseAndPackGA(closure)
-StgClosure *closure;
-{
-  globalAddr *ga;
-  globalAddr packGA;
-
-  if ((ga = LAGAlookup(closure)) == NULL) {
-    ga = makeGlobal(closure, rtsTrue);
-
-    // Global statistics: increase amount of global data by closure-size
-    if (RtsFlags.ParFlags.ParStats.Global &&
-       RtsFlags.GcFlags.giveStats > NO_GC_STATS) {
-      StgInfoTable *info;
-      nat size, ptrs, nonptrs, vhs, i, m; // stats only!!
-      char str[80]; // stats only!!
-
-      info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
-      globalParStats.tot_global += size;
-    }
-  }
-  ASSERT(ga->weight==MAX_GA_WEIGHT || ga->weight > 2);
-  
-  if(dest_gtid==ga->payload.gc.gtid)
-  {  packGA.payload = ga->payload;
-     packGA.weight = 0xFFFFFFFF; // 0,1,2 are used already
-  }
-  else
-  { splitWeight(&packGA, ga);
-    ASSERT(packGA.weight > 0);
-  }  
-  IF_PAR_DEBUG(pack,
-              fprintf(stderr, "*>## %p (%s): Globalising (%s) closure with GA ",
-                      closure, info_type(closure),
-                      ( (ga->payload.gc.gtid==dest_gtid)?"returning":
-                          ( (ga->payload.gc.gtid==mytid)?"creating":"sharing" ) ));
-              printGA(&packGA);
-              fputc('\n', stderr));
-
-
-  Pack((StgWord) packGA.weight);
-  Pack((StgWord) packGA.payload.gc.gtid);
-  Pack((StgWord) packGA.payload.gc.slot);
-}
-
-/*
-   @PackPLC@ makes up a bogus GA for a PLC. Weight 0 implies that a PLC
-   address follows instead of PE, slot.  */
-
-//@cindex PackPLC
-
-static void
-PackPLC(addr)
-StgPtr addr;
-{
-  Pack(0L);                    /* weight */
-  Pack((StgWord) addr);                /* address */
-}
-
-/*
-   @PackOffset@ packs a special GA value that will be interpreted as an
-   offset to a closure in the pack buffer.  This is used to avoid unfolding
-   the graph structure into a tree.  */
-
-static void
-PackOffset(offset)
-int offset;
-{
-  /*
-  IF_PAR_DEBUG(pack,
-              belch("** Packing Offset %d at pack location %u",
-                    offset, pack_locn));
-  */
-  Pack(1L);                    /* weight */
-  Pack(0L);                    /* pe */
-  Pack(offset);                        /* slot/offset */
-}
-# endif  /* PAR */
-
-//@node Unpacking routines, Aux fcts for packing, Low level packing routines, Graph packing
-//@subsection Unpacking routines
-
-/*
-  This was formerly in the (now deceased) module Unpack.c
-
-  Unpacking closures which have been exported to remote processors
-
-  This module defines routines for unpacking closures in the parallel
-  runtime system (GUM).
-
-  In the case of GrAnSim, this module defines routines for *simulating* the
-  unpacking of closures as it is done in the parallel runtime system.
-*/
-
-//@node GUM code, GranSim Code, Unpacking routines, Unpacking routines
-//@subsubsection GUM code
-
-#if defined(PAR) 
-
-//@cindex InitPendingGABuffer
-void
-InitPendingGABuffer(size)
-nat size; 
-{
-  if (PendingGABuffer==(globalAddr *)NULL)
-    PendingGABuffer = (globalAddr *) 
-      stgMallocBytes(size*2*sizeof(globalAddr),
-                    "InitPendingGABuffer");
-
-  /* current location in the buffer */
-  gaga = PendingGABuffer; 
-}
-
-/*
-  @CommonUp@ commons up two closures which we have discovered to be
-  variants of the same object.  One is made an indirection to the other.  */
-
-//@cindex CommonUp
-void
-CommonUp(StgClosure *src, StgClosure *dst)
-{
-  StgBlockingQueueElement *bqe;
-#if defined(DEBUG)
-  StgInfoTable *info;
-  nat size, ptrs, nonptrs, vhs, i;
-  char str[80];
-
-  /* get info about basic layout of the closure */
-  info = get_closure_info(src, &size, &ptrs, &nonptrs, &vhs, str);
-#endif
-
-  ASSERT(src != (StgClosure *)NULL && dst != (StgClosure *)NULL);
-  ASSERT(src != dst);
-
-  IF_PAR_DEBUG(pack,
-              belch("*___  CommonUp %p (%s) --> %p (%s)",
-                    src, info_type(src), dst, info_type(dst)));
-  
-  switch (get_itbl(src)->type) {
-  case BLACKHOLE_BQ:
-    bqe = ((StgBlockingQueue *)src)->blocking_queue;
-    break;
-
-  case FETCH_ME_BQ:
-    bqe = ((StgFetchMeBlockingQueue *)src)->blocking_queue;
-    break;
-    
-  case RBH:
-    bqe = ((StgRBH *)src)->blocking_queue;
-    break;
-    
-  case BLACKHOLE:
-  case FETCH_ME:
-    bqe = END_BQ_QUEUE;
-    break;
-
-    /* These closures are too small to be updated with an indirection!!! */
-  case CONSTR_1_0:
-  case CONSTR_0_1:
-    ASSERT(size<_HS+MIN_UPD_SIZE); // that's why we have to avoid UPD_IND
-    return;
-
-    /* currently we also common up 2 CONSTRs; this should reduce heap 
-     * consumption but also does more work; not sure whether it's worth doing 
-     */ 
-  case CONSTR:
-  case CONSTR_2_0:
-  case CONSTR_1_1:
-  case CONSTR_0_2:
-  case ARR_WORDS:
-  case MUT_ARR_PTRS:
-  case MUT_ARR_PTRS_FROZEN:
-  case MUT_VAR:
-    break;
-
-  default:
-    /* Don't common up anything else */
-    return;
-  }
-
-  /* closure must be big enough to permit update with ind */
-  ASSERT(size>=_HS+MIN_UPD_SIZE);
-  /* NB: this also awakens the blocking queue for src */
-  UPD_IND(src, dst);
-}
-
-/*
- * Common up the new closure with any existing closure having the same
- * GA
- */
-//@cindex SetGAandCommonUp
-static StgClosure *
-SetGAandCommonUp(globalAddr *ga, StgClosure *closure, rtsBool hasGA)
-{
-  StgClosure *existing;
-  StgInfoTable *ip, *oldip;
-  globalAddr *newGA;
-
-  if (!hasGA)
-    return closure;
-  
-  /* should we already have a local copy? */
-  if (ga->weight==0xFFFFFFFF) { 
-    ASSERT(ga->payload.gc.gtid==mytid); //sanity
-    ga->weight=0;
-    /* probably should also ASSERT that a commonUp takes place...*/
-  }
-  
-  ip = get_itbl(closure);
-  if ((existing = GALAlookup(ga)) == NULL) {
-    /* Just keep the new object */
-    IF_PAR_DEBUG(pack,
-                belch("*<##  New local object for GA ((%x, %d, %x)) is %p (%s)", 
-                      ga->payload.gc.gtid, ga->payload.gc.slot, ga->weight,
-                      closure, info_type(closure)));
-
-    // make an entry binding closure to ga in the RemoteGA table
-    newGA = setRemoteGA(closure, ga, rtsTrue);
-    // if local closure is a FETCH_ME etc fill in the global indirection
-    if (ip->type == FETCH_ME || ip->type == REMOTE_REF)
-      ((StgFetchMe *)closure)->ga = newGA;
-  } else {
-    
-
-#ifdef DIST 
-// ***************************************************************************
-// ***************************************************************************
-// REMOTE_REF HACK - dual is in PackRemoteRef  
-// - prevents the weight ever being updated
-  if (ip->type == REMOTE_REF)
-    ga->weight=0;
-// ***************************************************************************
-// ***************************************************************************
-#endif /* DIST */
-    
-    /* Two closures, one global name.  Someone loses */
-    oldip = get_itbl(existing);
-    if ((oldip->type == FETCH_ME || 
-        IS_BLACK_HOLE(existing) ||
-        /* try to share evaluated closures */
-         oldip->type == CONSTR ||
-        oldip->type == CONSTR_1_0 ||
-        oldip->type == CONSTR_0_1 ||
-        oldip->type == CONSTR_2_0 ||
-        oldip->type == CONSTR_1_1 ||
-        oldip->type == CONSTR_0_2 
-       ) &&
-       ip->type != FETCH_ME) 
-    {
-      IF_PAR_DEBUG(pack,
-                  belch("*<#-  Duplicate local object for GA ((%x, %d, %x)); redirecting %p (%s) -> %p (%s)",
-                        ga->payload.gc.gtid, ga->payload.gc.slot, ga->weight,
-                        existing, info_type(existing), closure, info_type(closure)));
-
-      /* 
-       * What we had wasn't worth keeping, so make the old closure an
-       * indirection to the new closure (copying BQs if necessary) and
-       * make sure that the old entry is not the preferred one for this
-       * closure.
-       */
-      CommonUp(existing, closure);
-      //GALAdeprecate(ga);
-#if defined(DEBUG)
-      { 
-        StgInfoTable *info;
-        nat size, ptrs, nonptrs, vhs, i;
-        char str[80];
-      
-        /* get info about basic layout of the closure */
-        info = get_closure_info(GALAlookup(ga), &size, &ptrs, &nonptrs, &vhs, str);
-      
-        /* now ga indirectly refers to the new closure */
-        ASSERT(size<_HS+MIN_UPD_SIZE || 
-               UNWIND_IND(GALAlookup(ga))==closure);
-      }
-#endif
-    } else {
-      /*
-       * Either we already had something worthwhile by this name or
-       * the new thing is just another FetchMe.  However, the thing we
-       * just unpacked has to be left as-is, or the child unpacking
-       * code will fail.  Remember that the way pointer words are
-       * filled in depends on the info pointers of the parents being
-       * the same as when they were packed.
-       */
-      IF_PAR_DEBUG(pack,
-                  belch("*<#@  Duplicate local object for GA ((%x, %d, %x)); keeping %p (%s) nuking unpacked %p (%s)", 
-                        ga->payload.gc.gtid, ga->payload.gc.slot, ga->weight,
-                        existing, info_type(existing), closure, info_type(closure)));
-
-      /* overwrite 2nd word; indicates that the closure is garbage */
-      IF_DEBUG(sanity,
-              ((StgFetchMe*)closure)->ga = (globalAddr*)GARBAGE_MARKER;
-              IF_PAR_DEBUG(pack,
-                           belch("++++  unpacked closure %p (%s) is garbage: %p",
-                                 closure, info_type(closure), *(closure+1))));
-
-      closure = existing;
-#if 0
-      // HACK
-      ty = get_itbl(closure)->type;
-      if (ty == CONSTR ||
-         ty == CONSTR_1_0 ||
-         ty == CONSTR_0_1 ||
-         ty == CONSTR_2_0 ||
-         ty == CONSTR_1_1 ||
-         ty == CONSTR_0_2)
-       CommonUp(closure, graph);
-#endif
-    }
-    /* We don't use this GA after all, so give back the weight */
-    (void) addWeight(ga);
-  }
-
-  /* if we have unpacked a FETCH_ME, we have a GA, too */
-  ASSERT(get_itbl(closure)->type!=FETCH_ME || 
-        looks_like_ga(((StgFetchMe*)closure)->ga));
-
-  /* Sort out the global address mapping */
-  if (ip_THUNK(ip)){ 
-    // || // (ip_THUNK(ip) && !ip_UNPOINTED(ip)) || 
-    //(ip_MUTABLE(ip) && ip->type != FETCH_ME)) {
-    /* Make up new GAs for single-copy closures */
-    globalAddr *newGA = makeGlobal(closure, rtsTrue);
-    
-    // It's a new GA and therefore has the full weight
-    ASSERT(newGA->weight==0);
-
-    /* Create an old GA to new GA mapping */
-    *gaga++ = *ga;
-    splitWeight(gaga, newGA);
-    /* inlined splitWeight; we know that newGALA has full weight 
-    newGA->weight = gaga->weight = 1L << (BITS_IN(unsigned) - 1);    
-    gaga->payload = newGA->payload;
-    */
-    ASSERT(gaga->weight == 1U << (BITS_IN(unsigned) - 1));
-    gaga++;
-  }
-  return closure;
-}
-
-/*
-  Copies a segment of the buffer, starting at @bufptr@, representing a closure
-  into the heap at @graph@.
- */
-//@cindex FillInClosure
-static nat
-FillInClosure(StgWord ***bufptrP, StgClosure *graph)
-{
-  StgInfoTable *ip;
-  StgWord **bufptr = *bufptrP;
-  nat ptrs, nonptrs, vhs, i, size;
-  char str[80];
-
-  ASSERT(LOOKS_LIKE_GHC_INFO(((StgClosure*)bufptr)->header.info));
-
-  /*
-   * Close your eyes.  You don't want to see where we're looking. You
-   * can't get closure info until you've unpacked the variable header,
-   * but you don't know how big it is until you've got closure info.
-   * So...we trust that the closure in the buffer is organized the
-   * same way as they will be in the heap...at least up through the
-   * end of the variable header.
-   */
-  ip = get_closure_info((StgClosure *)bufptr, &size, &ptrs, &nonptrs, &vhs, str);
-         
-  /* Make sure that nothing sans the fixed header is filled in
-     The ga field of the FETCH_ME is filled in in SetGAandCommonUp */
-  if (ip->type == FETCH_ME || ip->type == REMOTE_REF) {
-    ASSERT(size>=_HS+MIN_UPD_SIZE);    // size of the FM in the heap
-    ptrs = nonptrs = vhs = 0;      // i.e. only unpack FH from buffer
-  }
-  /* ToDo: check whether this is really needed */
-  if (ip->type == ARR_WORDS) {
-    UnpackArray(bufptrP, graph);
-    return arr_words_sizeW((StgArrWords *)bufptr);
-  }
-
-  if (ip->type == PAP || ip->type == AP_UPD) {
-    return UnpackPAP(bufptrP, graph); // includes size of unpackes FMs
-  }
-
-  /* 
-     Remember, the generic closure layout is as follows:
-     +-------------------------------------------------+
-     | FIXED HEADER | VARIABLE HEADER | PTRS | NON-PRS |
-     +-------------------------------------------------+
-  */
-  /* Fill in the fixed header */
-  for (i = 0; i < _HS; i++)
-    ((StgPtr)graph)[i] = (StgWord)*bufptr++;
-
-  /* Fill in the packed variable header */
-  for (i = 0; i < vhs; i++)
-    ((StgPtr)graph)[_HS + i] = (StgWord)*bufptr++;
-  
-  /* Pointers will be filled in later */
-  
-  /* Fill in the packed non-pointers */
-  for (i = 0; i < nonptrs; i++)
-    ((StgPtr)graph)[_HS + i + vhs + ptrs] = (StgWord)*bufptr++;
-
-  /* Indirections are never packed */
-  // ASSERT(INFO_PTR(graph) != (W_) Ind_info_TO_USE);
-  // return bufptr;
-   *bufptrP = bufptr;
-   ASSERT(((ip->type==FETCH_ME || ip->type==REMOTE_REF)&& sizeofW(StgFetchMe)==size) ||
-         _HS+vhs+ptrs+nonptrs == size);
-   return size; 
-}
-
-/*
-  Find the next pointer field in the parent closure.
-  If the current parent has been completely unpacked already, get the
-  next closure from the global closure queue.
-*/
-//@cindex LocateNextParent
-static void
-LocateNextParent(parentP, pptrP, pptrsP, sizeP)
-StgClosure **parentP;
-nat *pptrP, *pptrsP, *sizeP;
-{
-  StgInfoTable *ip; // debugging
-  nat nonptrs, pvhs;
-  char str[80];
-
-  /* pptr as an index into the current parent; find the next pointer field
-     in the parent by increasing pptr; if that takes us off the closure
-     (i.e. *pptr + 1 > *pptrs) grab a new parent from the closure queue
-  */
-  (*pptrP)++;
-  while (*pptrP + 1 > *pptrsP) {
-    /* *parentP has been constructed (all pointer set); so check it now */
-    IF_DEBUG(sanity,
-            if ((*parentP!=(StgClosure*)NULL) &&         // not root
-                (*((StgPtr)(*parentP)+1)!=GARBAGE_MARKER) && // not commoned up
-                (get_itbl(*parentP)->type != FETCH_ME))
-              checkClosure(*parentP));
-
-    *parentP = DeQueueClosure();
-    
-    if (*parentP == NULL)
-      break;
-    else {
-      ip = get_closure_info(*parentP, sizeP, pptrsP, &nonptrs,
-                           &pvhs, str);
-      *pptrP = 0;
-    }
-  }
-  /* *parentP points to the new (or old) parent; */
-  /* *pptr, *pptrs and *size have been updated referring to the new parent */
-}
-
-/* 
-   UnpackClosure is the heart of the unpacking routine. It is called for 
-   every closure found in the packBuffer. Any prefix such as GA, PLC marker
-   etc has been unpacked into the *ga structure. 
-   UnpackClosure does the following:
-     - check for the kind of the closure (PLC, Offset, std closure)
-     - copy the contents of the closure from the buffer into the heap
-     - update LAGA tables (in particular if we end up with 2 closures 
-       having the same GA, we make one an indirection to the other)
-     - set the GAGA map in order to send back an ACK message
-
-   At the end of this function *graphP has been updated to point to the
-   next free word in the heap for unpacking the rest of the graph and
-   *bufptrP points to the next word in the pack buffer to be unpacked.
-*/
-
-static  StgClosure*
-UnpackClosure (StgWord ***bufptrP, StgClosure **graphP, globalAddr *ga) {
-  StgClosure *closure;
-  nat size;
-  rtsBool hasGA = rtsFalse, unglobalised = rtsFalse;
-
-  /* Now unpack the closure body, if there is one; three cases:
-     - PLC: closure is just a pointer to a static closure
-     - Offset: closure has been unpacked already
-     - else: copy data from packet into closure
-  */
-  if (isFixed(ga)) {
-    closure = UnpackPLC(ga);
-  } else if (isOffset(ga)) {
-    closure = UnpackOffset(ga);
-  } else {
-    /* if not PLC or Offset it must be a GA and then the closure */
-    ASSERT(RtsFlags.ParFlags.globalising!=0 || LOOKS_LIKE_GA(ga));
-    /* check whether this is an unglobalised closure */
-    unglobalised = isUnglobalised(ga);
-    /* Now we have to build something. */
-    hasGA = !isConstr(ga);
-    /* the new closure will be built here */
-    closure = *graphP;
-
-    /* fill in the closure from the buffer */
-    size = FillInClosure(/*in/out*/bufptrP, /*in*/closure);
-    /* if it is unglobalised, it may not be a thunk!! */
-    ASSERT(!unglobalised || !closure_THUNK(closure));
-    
-   /* Add to queue for processing */
-    QueueClosure(closure);
-
-    /* common up with other graph if necessary */
-    if (!unglobalised)
-      closure = SetGAandCommonUp(ga, closure, hasGA);
-
-    /* if we unpacked a THUNK, check that it is large enough to update */
-    ASSERT(!closure_THUNK(closure) || size>=_HS+MIN_UPD_SIZE);
-    /* graph shall point to next free word in the heap */
-    *graphP += size;
-    //*graphP += (size < _HS+MIN_UPD_SIZE) ? _HS+MIN_UPD_SIZE : size; // see ASSERT
-  }
-  return closure;
-}
-
-/*
-  @UnpackGraph@ unpacks the graph contained in a message buffer.  It
-  returns a pointer to the new graph.  The @gamap@ parameter is set to
-  point to an array of (oldGA,newGA) pairs which were created as a result
-  of unpacking the buffer; @nGAs@ is set to the number of GA pairs which
-  were created.
-
-  The format of graph in the pack buffer is as defined in @Pack.lc@.  */
-
-//@cindex UnpackGraph
-StgClosure *
-UnpackGraph(packBuffer, gamap, nGAs)
-rtsPackBuffer *packBuffer;
-globalAddr **gamap;
-nat *nGAs;
-{
-  StgWord **bufptr, **slotptr;
-  globalAddr gaS;
-  StgClosure *closure, *graphroot, *graph, *parent;
-  nat size, heapsize, bufsize, 
-      pptr = 0, pptrs = 0, pvhs = 0;
-  nat unpacked_closures = 0, unpacked_thunks = 0; // stats only
-
-  IF_PAR_DEBUG(resume,
-              graphFingerPrint[0] = '\0');
-
-  ASSERT(_HS==1);  // HWL HACK; compile time constant
-
-#if defined(PAR_TICKY) // HWL HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
-  PAR_TICKY_UNPACK_GRAPH_START();
-#endif
-  
-  /* Initialisation */
-  InitPacking(rtsTrue);      // same as in PackNearbyGraph
-  globalUnpackBuffer = packBuffer;
-
-  IF_DEBUG(sanity, // do a sanity check on the incoming packet
-          checkPacket(packBuffer));
-
-  ASSERT(gaga==PendingGABuffer); 
-  graphroot = (StgClosure *)NULL;
-
-  /* Unpack the header */
-  bufsize = packBuffer->size;
-  heapsize = packBuffer->unpacked_size;
-  bufptr = packBuffer->buffer;
-
-  /* allocate heap */
-  if (heapsize > 0) {
-    graph = (StgClosure *)allocate(heapsize);
-    ASSERT(graph != NULL);
-    // parallel global statistics: increase amount of global data
-    if (RtsFlags.ParFlags.ParStats.Global &&
-       RtsFlags.GcFlags.giveStats > NO_GC_STATS) {
-      globalParStats.tot_global += heapsize;
-    }
-  }
-
-  /* iterate over the buffer contents and unpack all closures */
-  parent = (StgClosure *)NULL;
-  do {
-    /* check that we aren't at the end of the buffer, yet */
-    IF_DEBUG(sanity, ASSERT(*bufptr != END_OF_BUFFER_MARKER));
-
-    /* This is where we will ultimately save the closure's address */
-    slotptr = bufptr;
-
-    /* fill in gaS from buffer; gaS may receive GA, PLC- or offset-marker */
-    bufptr = UnpackGA(/*in*/bufptr, /*out*/&gaS);
-
-    /* this allocates heap space, updates LAGA tables etc */
-    closure = UnpackClosure (/*in/out*/&bufptr, /*in/out*/&graph, /*in*/&gaS);
-    unpacked_closures++; // stats only; doesn't count FMs in PAP!!!
-    unpacked_thunks += (closure_THUNK(closure)) ? 1 : 0; // stats only
-
-    /*
-     * Set parent pointer to point to chosen closure.  If we're at the top of
-     * the graph (our parent is NULL), then we want to arrange to return the
-     * chosen closure to our caller (possibly in place of the allocated graph
-     * root.)
-     */
-    if (parent == NULL)
-      graphroot = closure;
-    else
-      ((StgPtr)parent)[_HS + pvhs + pptr] = (StgWord) closure;
-
-    /* Save closure pointer for resolving offsets */
-    *slotptr = (StgWord*) closure;
-
-    /* Locate next parent pointer */
-    LocateNextParent(&parent, &pptr, &pptrs, &size);
-
-    IF_DEBUG(sanity,
-            gaS.weight          = 0xdeadffff;
-            gaS.payload.gc.gtid = 0xdead;
-            gaS.payload.gc.slot = 0xdeadbeef;);
-  } while (parent != NULL);
-
-  IF_PAR_DEBUG(resume,
-              GraphFingerPrint(graphroot, graphFingerPrint);
-              ASSERT(strlen(graphFingerPrint)<=MAX_FINGER_PRINT_LEN);
-              belch(">>> Fingerprint of graph rooted at %p (after unpacking <<%d>>:\n    {%s}",
-                    graphroot, packBuffer->id, graphFingerPrint));
-
-  /* we unpacked exactly as many words as there are in the buffer */
-  ASSERT(bufsize == (nat) (bufptr-(packBuffer->buffer)));
-  /* we filled no more heap closure than we allocated at the beginning; 
-     ideally this should be a ==; 
-     NB: test is only valid if we unpacked anything at all (graphroot might
-         end up to be a PLC!), therfore the strange test for HEAP_ALLOCED 
-  */
-
-  /*
-  {
-   StgInfoTable *info = get_itbl(graphroot);
-   ASSERT(!HEAP_ALLOCED(graphroot) || heapsize >= (nat) (graph-graphroot) ||
-          // ToDo: check whether CAFs are really a special case here!!
-          info->type==CAF_BLACKHOLE || info->type==FETCH_ME || info->type==FETCH_ME_BQ); 
-  }
-  */
-
-  /* check for magic end-of-buffer word */
-  IF_DEBUG(sanity, ASSERT(*bufptr == END_OF_BUFFER_MARKER));
-
-  *gamap = PendingGABuffer;
-  *nGAs = (gaga - PendingGABuffer) / 2;
-
-  IF_PAR_DEBUG(tables,
-              belch("**   LAGA table after unpacking closure %p:",
-                    graphroot);
-              printLAGAtable());
-
-  /* ToDo: are we *certain* graphroot has been set??? WDP 95/07 */
-  ASSERT(graphroot!=NULL);
-
-  IF_DEBUG(sanity,
-           {
-            StgPtr p;
-
-            /* check the unpacked graph */
-            //checkHeapChunk(graphroot,graph-sizeof(StgWord));
-
-            // if we do sanity checks, then wipe the pack buffer after unpacking
-            for (p=(StgPtr)packBuffer->buffer; p<(StgPtr)(packBuffer->buffer)+(packBuffer->size); )
-              *p++ = 0xdeadbeef;
-            });
-
-  /* reset the global variable */
-  globalUnpackBuffer = (rtsPackBuffer*)NULL;
-
-#if defined(PAR_TICKY) // HWL HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
-  PAR_TICKY_UNPACK_GRAPH_END(unpacked_closures, unpacked_thunks);
-#endif
-
-  return (graphroot);
-}
-
-//@cindex UnpackGA
-static  StgWord **
-UnpackGA(StgWord **bufptr, globalAddr *ga)
-{
-  /* First, unpack the next GA or PLC */
-  ga->weight = (rtsWeight) *bufptr++;
-
-  if (ga->weight == 2) {  // unglobalised closure to follow
-    // nothing to do; closure starts at *bufptr
-  } else if (ga->weight > 0) { // fill in GA
-    ga->payload.gc.gtid = (GlobalTaskId) *bufptr++;
-    ga->payload.gc.slot = (int) *bufptr++;
-  } else {
-    ga->payload.plc = (StgPtr) *bufptr++;
-  }
-  return bufptr;
-}
-
-//@cindex UnpackPLC
-static  StgClosure *
-UnpackPLC(globalAddr *ga)
-{
-  /* No more to unpack; just set closure to local address */
-  IF_PAR_DEBUG(pack,
-              belch("*<^^ Unpacked PLC at %x", ga->payload.plc)); 
-  return (StgClosure*)ga->payload.plc;
-}
-
-//@cindex UnpackOffset
-static  StgClosure *
-UnpackOffset(globalAddr *ga)
-{
-  /* globalUnpackBuffer is a global var init in UnpackGraph */
-  ASSERT(globalUnpackBuffer!=(rtsPackBuffer*)NULL);
-  /* No more to unpack; just set closure to cached address */
-  IF_PAR_DEBUG(pack,
-              belch("*<__ Unpacked indirection to %p (was OFFSET %d)", 
-                    (StgClosure *)((globalUnpackBuffer->buffer)[ga->payload.gc.slot]),
-                    ga->payload.gc.slot)); 
-  return (StgClosure *)(globalUnpackBuffer->buffer)[ga->payload.gc.slot];
-}
-
-/*
-  Input: *bufptrP, *graphP  ... ptrs to the pack buffer and into the heap.
-
-  *bufptrP points to something that should be unpacked as a FETCH_ME:
-    |
-    v
-    +-------------------------------
-    |    GA    | FH of FM
-    +-------------------------------
-
-  The first 3 words starting at *bufptrP are the GA address; the next
-  word is the generic FM info ptr followed by the remaining FH (if any)
-  The result after unpacking will be a FETCH_ME closure, pointed to by
-  *graphP at the start of the fct;
-    |
-    v
-    +------------------------+
-    | FH of FM | ptr to a GA |
-    +------------------------+
-
-   The ptr field points into the RemoteGA table, which holds the actual GA.
-   *bufptrP has been updated to point to the next word in the buffer.
-   *graphP has been updated to point to the first free word at the end.
-*/
-
-static StgClosure*
-UnpackFetchMe (StgWord ***bufptrP, StgClosure **graphP) {
-  StgClosure *closure, *foo;
-  globalAddr gaS;
-
-  /* This fct relies on size of FM < size of FM in pack buffer */
-  ASSERT(sizeofW(StgFetchMe)<=PACK_FETCHME_SIZE);
-
-  /* fill in gaS from buffer */
-  *bufptrP = UnpackGA(*bufptrP, &gaS);
-  /* might be an offset to a closure in the pack buffer */
-  if (isOffset(&gaS)) {
-    belch("*<   UnpackFetchMe: found OFFSET to %d when unpacking FM at buffer loc %p",
-                 gaS.payload.gc.slot, *bufptrP);
-
-    closure = UnpackOffset(&gaS);
-    /* return address of previously unpacked closure; leaves *graphP unchanged */
-    return closure;
-  }
-
-  /* we have a proper GA at hand */
-  ASSERT(LOOKS_LIKE_GA(&gaS));
-
-  IF_DEBUG(sanity,
-          if (isFixed(&gaS)) 
-          barf("*<   UnpackFetchMe: found PLC where FM was expected %p (%s)",
-               *bufptrP, info_type((StgClosure*)*bufptrP)));
-
-  IF_PAR_DEBUG(pack,
-              belch("*<_- Unpacked @ %p a FETCH_ME to GA ", 
-                    *graphP);
-              printGA(&gaS);
-              fputc('\n', stderr));
-
-  /* the next thing must be the IP to a FETCH_ME closure */
-  ASSERT(get_itbl((StgClosure *)*bufptrP)->type == FETCH_ME);
-  
-  closure = *graphP;
-  /* fill in the closure from the buffer */
-  FillInClosure(bufptrP, closure);
-  
-  /* the newly built closure is a FETCH_ME */
-  ASSERT(get_itbl(closure)->type == FETCH_ME);
-  
-  /* common up with other graph if necessary 
-     this also assigns the contents of gaS to the ga field of the FM closure */
-  foo = SetGAandCommonUp(&gaS, closure, rtsTrue);
-  
-  ASSERT(foo!=closure || LOOKS_LIKE_GA(((StgFetchMe*)closure)->ga));
-  
-  IF_PAR_DEBUG(pack,
-              if (foo==closure) {  // only if not commoned up 
-                belch("*<_- current FM @ %p next FM @ %p; unpacked FM @ %p is ", 
-                      *graphP, *graphP+sizeofW(StgFetchMe), closure);
-                printClosure(closure);
-               });
-  *graphP += sizeofW(StgFetchMe);
-  return foo;
-}
-
-/*
-  Unpack an array of words.
-  Could use generic unpack most of the time, but cleaner to separate it.
-  ToDo: implement packing of MUT_ARRAYs
-*/
-
-//@cindex UnackArray
-static void
-UnpackArray(StgWord ***bufptrP, StgClosure *graph)
-{
-  StgInfoTable *info;
-  StgWord **bufptr=*bufptrP;
-  nat size, ptrs, nonptrs, vhs, i, n;
-  char str[80];
-
-  /* yes, I know I am paranoid; but who's asking !? */
-  IF_DEBUG(sanity,
-          info = get_closure_info((StgClosure*)bufptr, 
-                                  &size, &ptrs, &nonptrs, &vhs, str);
-          ASSERT(info->type == ARR_WORDS || info->type == MUT_ARR_PTRS ||
-                 info->type == MUT_ARR_PTRS_FROZEN || info->type == MUT_VAR));
-
-  n = ((StgArrWords *)bufptr)->words;
-  // this includes the header!: arr_words_sizeW(stgCast(StgArrWords*,q)); 
-
-  IF_PAR_DEBUG(pack,
-               if (n<100) 
-                belch("*<== unpacking an array of %d words %p (%s) (size=%d) |%s|\n",
-                    n, (StgClosure*)bufptr, info_type((StgClosure*)bufptr), 
-                    arr_words_sizeW((StgArrWords *)bufptr), 
-                      /* print array (string?) */
-                     ((StgArrWords *)graph)->payload);
-               else
-                belch("*<== unpacking an array of %d words %p (%s) (size=%d)\n",
-                    n, (StgClosure*)bufptr, info_type((StgClosure*)bufptr), 
-                    arr_words_sizeW((StgArrWords *)bufptr)));
-
-  /* Unpack the header (2 words: info ptr and the number of words to follow) */
-  ((StgArrWords *)graph)->header.info = (StgInfoTable*)*bufptr++;  // assumes _HS==1; yuck!
-  ((StgArrWords *)graph)->words = (StgWord)*bufptr++;
-
-  /* unpack the payload of the closure (all non-ptrs) */
-  for (i=0; i<n; i++)
-    ((StgArrWords *)graph)->payload[i] = (StgWord)*bufptr++;
-
-  ASSERT(bufptr==*bufptrP+arr_words_sizeW((StgArrWords *)*bufptrP));
-  *bufptrP = bufptr;
-}
-
-/* 
-   Unpack a PAP in the buffer into a heap closure.
-   For each FETCHME we find in the packed PAP we have to unpack a separate
-   FETCHME closure and insert a pointer to this closure into the PAP. 
-   We unpack all FETCHMEs into an area after the PAP proper (the `FM area').
-   Note that the size of a FETCHME in the buffer is exactly the same as
-   the size of an unpacked FETCHME plus 1 word for the pointer to it.
-   Therefore, we just allocate packed_size words in the heap for the unpacking.
-   After this routine the heap starting from *graph looks like this:
-
-   graph
-     |
-     v             PAP closure                 |   FM area        |
-     +------------------------------------------------------------+
-     | PAP header | n_args | fun | payload ... | FM_1 | FM_2 .... |
-     +------------------------------------------------------------+
-
-   where payload contains pointers to each of the unpacked FM_1, FM_2 ...
-   The size of the PAP closure plus all FMs is _HS+2+packed_size.
-*/
-
-//@cindex UnpackPAP
-static nat
-UnpackPAP(StgWord ***bufptrP, StgClosure *graph) 
-{
-  nat n, i, j, packed_size = 0;
-  StgPtr p, q, end, payload_start, p_FMs;
-  const StgInfoTable* info;
-  StgWord bitmap;
-  StgWord **bufptr = *bufptrP;
-#if defined(DEBUG)
-  nat FMs_in_PAP=0;
-  void checkPAPSanity(StgPAP *graph, StgPtr p_FM_begin, StgPtr p_FM_end);
-#endif
-
-  IF_PAR_DEBUG(pack,
-              belch("*<** UnpackPAP: unpacking PAP @ %p with %d words to closure %p", 
-                        *bufptr, *(bufptr+1), graph));
-
-  /* Unpack the PAP header (both fixed and variable) */
-  ((StgPAP *)graph)->header.info = (StgInfoTable*)*bufptr++;
-  n = ((StgPAP *)graph)->n_args = (StgWord)*bufptr++;
-  ((StgPAP *)graph)->fun = (StgClosure*)*bufptr++;
-  packed_size = (nat)*bufptr++;
-
-  IF_PAR_DEBUG(pack,
-              belch("*<** UnpackPAP: PAP header is [%p, %d, %p] %d",
-                    ((StgPAP *)graph)->header.info,
-                    ((StgPAP *)graph)->n_args,
-                    ((StgPAP *)graph)->fun,
-                    packed_size));
-
-  payload_start = (StgPtr)bufptr;
-  /* p points to the current word in the heap */
-  p = (StgPtr)((StgPAP *)graph)->payload;      // payload of PAP will be unpacked here
-  p_FMs = (StgPtr)graph+pap_sizeW((StgPAP*)graph);  // FMs will be unpacked here
-  end = (StgPtr) payload_start+packed_size;
-  /*
-    The main loop unpacks the PAP in *bufptr into *p, with *p_FMS as the
-    FM area for unpacking all FETCHMEs encountered during unpacking.
-  */
-  while ((StgPtr)bufptr<end) {
-    /* be sure that we don't write more than we allocated for this closure */
-    ASSERT(p_FMs <= (StgPtr)(graph+_HS+2+packed_size));
-    /* be sure that the unpacked PAP doesn't run into the FM area */
-    ASSERT(p < (StgPtr)(graph+pap_sizeW((StgPAP*)graph)));
-    /* the loop body has been borrowed from scavenge_stack */
-    q = *bufptr; // let q be the contents of the current pointer into the buffer
-
-    /* Test whether the next thing is a FETCH_ME.
-       In PAPs FETCH_ME are encoded via a starting marker of ARGTAG_MAX+1
-    */
-    if (q==(StgPtr)(ARGTAG_MAX+1)) {
-      IF_PAR_DEBUG(pack,
-                  belch("*<** UnpackPAP @ %p: unpacking FM; filling in ptr to FM area: %p", 
-                        p, p_FMs));
-      bufptr++;         // skip ARGTAG_MAX+1 marker
-      // Unpack a FM into the FM area after the PAP proper and insert pointer
-      *p++ = (StgWord)UnpackFetchMe(&bufptr, (StgClosure**)&p_FMs); 
-      IF_DEBUG(sanity, FMs_in_PAP++);
-      continue;
-    }
-
-    /* Test whether it is a PLC */
-    if (q==(StgPtr)0) { // same as isFixed(q)
-      IF_PAR_DEBUG(pack,
-                  belch("*<** UnpackPAP @ %p: unpacking PLC to %p", 
-                        p, *(bufptr+1)));
-      bufptr++;          // skip 0 marker
-      *p++ = (StgWord)*bufptr++;
-      continue;
-    }
-
-    /* If we've got a tag, pack all words in that block */
-    if (IS_ARG_TAG((W_)q)) {   // q stands for the no. of non-ptrs to follow
-      nat m = ARG_SIZE(q);     // first word after this block
-      IF_PAR_DEBUG(pack,
-                  belch("*<** UnpackPAP @ %p: unpacking %d words (tagged), starting @ %p", 
-                        p, m, p));
-      for (i=0; i<m+1; i++)
-       *p++ = (StgWord)*bufptr++;
-      continue;
-    }
-
-    /* 
-     * Otherwise, q must be the info pointer of an activation
-     * record.  All activation records have 'bitmap' style layout
-     * info.
-     */
-    info  = get_itbl((StgClosure *)q);
-    switch (info->type) {
-       
-      /* Dynamic bitmap: the mask is stored on the stack */
-    case RET_DYN:
-      IF_PAR_DEBUG(pack,
-                  belch("*<** UnpackPAP @ %p: RET_DYN", 
-                        p));
-
-      /* Pack the header as is */
-      ((StgRetDyn *)p)->info     = (StgWord)*bufptr++;
-      ((StgRetDyn *)p)->liveness = (StgWord)*bufptr++;
-      ((StgRetDyn *)p)->ret_addr = (StgWord)*bufptr++;
-      p += 3;
-
-      //bitmap = ((StgRetDyn *)p)->liveness;
-      //p      = (P_)&((StgRetDyn *)p)->payload[0];
-      goto small_bitmap;
-
-      /* probably a slow-entry point return address: */
-    case FUN:
-    case FUN_STATIC:
-      {
-      IF_PAR_DEBUG(pack,
-                  belch("*<** UnpackPAP @ %p: FUN or FUN_STATIC", 
-                        p));
-
-      ((StgClosure *)p)->header.info = (StgInfoTable*)*bufptr;
-      p++;
-
-      goto follow_srt; //??
-      }
-
-      /* Using generic code here; could inline as in scavenge_stack */
-    case UPDATE_FRAME:
-      {
-       StgUpdateFrame *frame = (StgUpdateFrame *)p;
-       //nat type = get_itbl(frame->updatee)->type;
-
-       //ASSERT(type==BLACKHOLE || type==CAF_BLACKHOLE || type==BLACKHOLE_BQ);
-
-       IF_PAR_DEBUG(pack,
-                    belch("*<** UnackPAP @ %p: UPDATE_FRAME", 
-                          p));
-
-       ((StgUpdateFrame *)p)->header.info = (StgInfoTable*)*bufptr++;
-       ((StgUpdateFrame *)p)->link        = (StgUpdateFrame*)*bufptr++;     // ToDo: fix intra-stack pointer
-       ((StgUpdateFrame *)p)->updatee     = (StgClosure*)*bufptr++;   // ToDo: follow link 
-
-       p += 3;
-      }
-
-      /* small bitmap (< 32 entries, or 64 on a 64-bit machine) */
-    case STOP_FRAME:
-      {
-       IF_PAR_DEBUG(pack,
-                    belch("*<** UnpackPAP @ %p: STOP_FRAME", 
-                          p));
-       ((StgStopFrame *)p)->header.info = (StgInfoTable*)*bufptr;
-       p++;
-      }
-
-    case CATCH_FRAME:
-      {
-       IF_PAR_DEBUG(pack,
-                    belch("*<** UnpackPAP @ %p: CATCH_FRAME",
-                          p));
-
-       ((StgCatchFrame *)p)->header.info = (StgInfoTable*)*bufptr++;
-       ((StgCatchFrame *)p)->link        = (StgUpdateFrame*)*bufptr++;
-       ((StgCatchFrame *)p)->exceptions_blocked = (StgInt)*bufptr++;
-       ((StgCatchFrame *)p)->handler     = (StgClosure*)*bufptr++;
-       p += 4;
-      }
-
-    case SEQ_FRAME:
-      {
-       IF_PAR_DEBUG(pack,
-                    belch("*<** UnpackPAP @ %p: UPDATE_FRAME",
-                          p));
-
-       ((StgSeqFrame *)p)->header.info = (StgInfoTable*)*bufptr++;
-       ((StgSeqFrame *)p)->link        = (StgUpdateFrame*)*bufptr++;
-
-        // ToDo: handle bitmap
-        bitmap = info->layout.bitmap;
-
-        p = (StgPtr)&(((StgClosure *)p)->payload);
-        goto small_bitmap;
-      }
-    case RET_BCO:
-    case RET_SMALL:
-    case RET_VEC_SMALL:
-      IF_PAR_DEBUG(pack,
-                  belch("*<** UnpackPAP @ %p: RET_{BCO,SMALL,VEC_SMALL}",
-                        p));
-
-
-      ((StgClosure *)p)->header.info = (StgInfoTable*)*bufptr++;
-      p++;
-      // ToDo: handle bitmap
-      bitmap = info->layout.bitmap;
-      /* this assumes that the payload starts immediately after the info-ptr */
-
-    small_bitmap:
-      while (bitmap != 0) {
-       if ((bitmap & 1) == 0) {
-         *p++ = (StgWord)UnpackFetchMe(&bufptr, (StgClosure**)&p_FMs);
-         IF_DEBUG(sanity, FMs_in_PAP++);
-       } else {
-         *p++ = (StgWord)*bufptr++;
-       }
-       bitmap = bitmap >> 1;
-      }
-      
-    follow_srt:
-      belch("*<-- UnpackPAP: nothing to do for follow_srt");
-      continue;
-
-      /* large bitmap (> 32 entries) */
-    case RET_BIG:
-    case RET_VEC_BIG:
-      {
-       StgPtr q;
-       StgLargeBitmap *large_bitmap;
-
-       IF_PAR_DEBUG(pack,
-                    belch("*<** UnpackPAP @ %p: RET_{BIG,VEC_BIG} (large_bitmap=%p)", 
-                          p, info->layout.large_bitmap));
-
-
-       ((StgClosure *)p)->header.info = (StgInfoTable*)*bufptr++;
-       p++;
-
-       large_bitmap = info->layout.large_bitmap;
-
-       for (j=0; j<large_bitmap->size; j++) {
-         bitmap = large_bitmap->bitmap[j];
-         q = p + BITS_IN(W_);
-         while (bitmap != 0) {
-           if ((bitmap & 1) == 0) {
-             *p++ = (StgWord)UnpackFetchMe(&bufptr, (StgClosure**)&p_FMs);
-             IF_DEBUG(sanity, FMs_in_PAP++);
-           } else {
-             *p++ = (StgWord)*bufptr;
-           }
-           bitmap = bitmap >> 1;
-         }
-         if (j+1 < large_bitmap->size) {
-           while (p < q) {
-             *p++ = (StgWord)UnpackFetchMe(&bufptr, (StgClosure**)&p_FMs);
-             IF_DEBUG(sanity, FMs_in_PAP++);
-           }
-         }
-       }
-
-       /* and don't forget to follow the SRT */
-       goto follow_srt;
-      }
-
-    default:
-      barf("UnpackPAP: weird activation record found on stack: %d", 
-          (int)(info->type));
-    }
-  }
-  IF_PAR_DEBUG(pack,
-              belch("*<** UnpackPAP finished; unpacked closure @ %p is:",
-                    (StgClosure *)graph);
-              printClosure((StgClosure *)graph));
-
-  IF_DEBUG(sanity,               /* check sanity of unpacked PAP */
-          checkClosure(graph));
-
-  *bufptrP = bufptr;
-  /* 
-     Now p points to the first word after the PAP proper and p_FMs points 
-     to the next free word in the heap; everything between p and p_FMs are 
-     FETCHMEs 
-  */
-  IF_DEBUG(sanity,
-          checkPAPSanity(graph, p, p_FMs));
-
-  /* we have to return the size of PAP + FMs as size of the unpacked thing */
-  ASSERT(graph+pap_sizeW((StgPAP*)graph)==p);
-  return (nat)((StgClosure*)p_FMs-graph);
-}
-
-#if defined(DEBUG)
-/* 
-   Check sanity of a PAP after unpacking the PAP.
-   This means that there is slice of heap after the PAP containing FETCHMEs
-*/
-void
-checkPAPSanity(StgPAP *graph, StgPtr p_FM_begin, StgPtr p_FM_end)
-{
-  StgPtr xx;
-
-  /* check that the main unpacked closure is a PAP */
-  ASSERT(graph->header.info = &stg_PAP_info);
-  checkClosure(graph);
-  /* check that all of the closures in the FM-area are FETCHMEs */
-  for (xx=p_FM_begin; xx<p_FM_end; xx += sizeofW(StgFetchMe)) {
-    /* must be a FETCHME closure */
-    ASSERT(((StgClosure*)xx)->header.info == &stg_FETCH_ME_info);
-    /* it might have been commoned up (=> marked as garbage);
-       otherwise it points to a GA */
-    ASSERT((((StgFetchMe*)xx)->ga)==GARBAGE_MARKER ||
-          LOOKS_LIKE_GA(((StgFetchMe*)xx)->ga));
-  }
-  /* traverse the payload of the PAP */
-  for (xx=graph->payload; xx-(StgPtr)(graph->payload)<graph->n_args; xx++) {
-    /* if the current elem is a pointer into the FM area, check that
-       the GA field is ok */
-    ASSERT(!(p_FM_begin<(StgPtr)*xx && (StgPtr)*xx<p_FM_end) ||
-          LOOKS_LIKE_GA(((StgFetchMe*)*xx)->ga));
-  }
-}
-#endif  /* DEBUG */
-#endif  /* PAR */
-
-//@node GranSim Code,  , GUM code, Unpacking routines
-//@subsubsection GranSim Code
-
-/*
-   For GrAnSim: No actual unpacking should be necessary. We just
-   have to walk over the graph and set the bitmasks appropriately.
-   Since we use RBHs similarly to GUM but without an ACK message/event
-   we have to revert the RBH from within the UnpackGraph routine (good luck!)
-   -- HWL 
-*/
-
-#if defined(GRAN)
-void
-CommonUp(StgClosure *src, StgClosure *dst)
-{
-  barf("CommonUp: should never be entered in a GranSim setup");
-}
-
-StgClosure*
-UnpackGraph(buffer)
-rtsPackBuffer* buffer;
-{
-  nat size, ptrs, nonptrs, vhs,
-      bufptr = 0;
-  StgClosure *closure, *graphroot, *graph;
-  StgInfoTable *ip;
-  StgWord bufsize, unpackedsize,
-          pptr = 0, pptrs = 0, pvhs;
-  StgTSO* tso;
-  char str[240], str1[80];
-  int i;
-
-  bufptr = 0;
-  graphroot = buffer->buffer[0];
-
-  tso = buffer->tso;
-
-  /* Unpack the header */
-  unpackedsize = buffer->unpacked_size;
-  bufsize = buffer->size;
-
-  IF_GRAN_DEBUG(pack,
-               belch("<<< Unpacking <<%d>> (buffer @ %p):\n    (root @ %p, PE %d,size=%d), demanded by TSO %d (%p)[PE %d]",
-                     buffer->id, buffer, graphroot, where_is(graphroot), 
-                     bufsize, tso->id, tso, 
-                     where_is((StgClosure *)tso)));
-
-  do {
-    closure = buffer->buffer[bufptr++]; /* that's all we need for GrAnSim -- HWL */
-      
-    /* Actually only ip is needed; rest is useful for TESTING -- HWL */
-    ip = get_closure_info(closure, 
-                         &size, &ptrs, &nonptrs, &vhs, str);
-      
-    IF_GRAN_DEBUG(pack,
-                 sprintf(str, "**    (%p): Changing bitmask[%s]: 0x%x ",
-                         closure, (closure_HNF(closure) ? "NF" : "__"),
-                         PROCS(closure)));
-
-    if (get_itbl(closure)->type == RBH) {
-      /* if it's an RBH, we have to revert it into a normal closure, thereby
-        awakening the blocking queue; not that this is code currently not
-        needed in GUM, but it should be added with the new features in
-        GdH (and the implementation of an NACK message)
-      */
-      // closure->header.gran.procs = PE_NUMBER(CurrentProc);
-      SET_GRAN_HDR(closure, PE_NUMBER(CurrentProc));    /* Move node */
-
-      IF_GRAN_DEBUG(pack,
-                   strcat(str, " (converting RBH) ")); 
-
-      convertFromRBH(closure);   /* In GUM that's done by convertToFetchMe */
-
-      IF_GRAN_DEBUG(pack,
-                   belch("::  closure %p (%s) is a RBH; after reverting: IP=%p",
-                         closure, info_type(closure), get_itbl(closure)));
-    } else if (IS_BLACK_HOLE(closure)) {
-      IF_GRAN_DEBUG(pack,
-                   belch("::  closure %p (%s) is a BH; copying node to %d",
-                         closure, info_type(closure), CurrentProc));
-      closure->header.gran.procs |= PE_NUMBER(CurrentProc); /* Copy node */
-    } else if ( (closure->header.gran.procs & PE_NUMBER(CurrentProc)) == 0 ) {
-      if (closure_HNF(closure)) {
-       IF_GRAN_DEBUG(pack,
-                     belch("::  closure %p (%s) is a HNF; copying node to %d",
-                           closure, info_type(closure), CurrentProc));
-       closure->header.gran.procs |= PE_NUMBER(CurrentProc); /* Copy node */
-      } else { 
-       IF_GRAN_DEBUG(pack,
-                     belch("::  closure %p (%s) is no (R)BH or HNF; moving node to %d",
-                           closure, info_type(closure), CurrentProc));
-       closure->header.gran.procs = PE_NUMBER(CurrentProc);  /* Move node */
-      }
-    }
-
-    IF_GRAN_DEBUG(pack,
-                 sprintf(str1, "0x%x",   PROCS(closure)); strcat(str, str1));
-    IF_GRAN_DEBUG(pack, belch(str));
-    
-  } while (bufptr<buffer->size) ;   /*  (parent != NULL);  */
-
-  /* In GrAnSim we allocate pack buffers dynamically! -- HWL */
-  free(buffer->buffer);
-  free(buffer);
-
-  IF_GRAN_DEBUG(pack,
-               belch("PrintGraph of %p is:", graphroot); PrintGraph(graphroot,0));
-
-  return (graphroot);
-}
-#endif  /* GRAN */
-
-//@node Aux fcts for packing, Printing Packet Contents, Unpacking routines, Graph packing
-//@subsection Aux fcts for packing
-
-//@menu
-//* Offset table::             
-//* Packet size::              
-//* Types of Global Addresses::         
-//* Closure Info::             
-//@end menu
-
-//@node Offset table, Packet size, Aux fcts for packing, Aux fcts for packing
-//@subsubsection Offset table
-
-/*
-   DonePacking is called when we've finished packing.  It releases memory
-   etc.  */
-
-//@cindex DonePacking
-
-# if defined(PAR)
-
-static void
-DonePacking(void)
-{
-  freeHashTable(offsetTable, NULL);
-  offsetTable = NULL;
-}
-
-/*
-   AmPacking records that the closure is being packed.  Note the abuse of
-   the data field in the hash table -- this saves calling @malloc@!  */
-
-//@cindex AmPacking
-
-static void
-AmPacking(closure)
-StgClosure *closure;
-{
-  insertHashTable(offsetTable, (StgWord) closure, (void *) (StgWord) pack_locn);
-}
-
-/*
-   OffsetFor returns an offset for a closure which is already being packed.  */
-
-//@cindex OffsetFor
-
-static int
-OffsetFor(closure)
-StgClosure *closure;
-{
-  return (int) (StgWord) lookupHashTable(offsetTable, (StgWord) closure);
-}
-
-/*
-   NotYetPacking determines whether the closure's already being packed.
-   Offsets $<$ @PACK_HDR_SIZE@ (e.g. 0) mean no.  */
-
-//@cindex NotYetPacking
-
-static rtsBool
-NotYetPacking(offset)
-int offset;
-{
-  return(offset == 0); // ToDo: what if root is found again?? FIX 
-}
-
-# else  /* GRAN */
-
-static void
-DonePacking(void)
-{
-  /* nothing */
-}
-
-/* 
-   NotYetPacking searches through the whole pack buffer for closure.  */
-
-static rtsBool
-NotYetPacking(closure)
-StgClosure *closure;
-{ nat i;
-  rtsBool found = rtsFalse;
-
-  for (i=0; (i<pack_locn) && !found; i++)
-    found = globalPackBuffer->buffer[i]==closure;
-
-  return (!found);
-}
-# endif
-
-//@node Packet size, Closure Info, Offset table, Aux fcts for packing
-//@subsubsection Packet size
-
-/* 
-   The size needed if all currently queued closures are packed as FETCH_ME
-   closures. This represents the headroom we must have when packing the
-   buffer in order to maintain all links in the graphs.
-*/
-// ToDo: check and merge cases
-#if defined(PAR)
-static nat
-QueuedClosuresMinSize (nat ptrs) {
-  return ((clq_size - clq_pos) + ptrs) * PACK_FETCHME_SIZE;
-}
-#else /* GRAN */
-static nat
-QueuedClosuresMinSize (nat ptrs) {
-  return ((clq_size - clq_pos) + ptrs) * PACK_FETCHME_SIZE;
-}
-#endif 
-
-/*
-  RoomToPack determines whether there's room to pack the closure into
-  the pack buffer based on 
-
-  o how full the buffer is already,
-  o the closures' size and number of pointers (which must be packed as GAs),
-  o the size and number of pointers held by any primitive arrays that it 
-    points to
-  
-    It has a *side-effect* (naughty, naughty) in assigning roomInBuffer 
-    to rtsFalse.
-*/
-
-//@cindex RoomToPack
-static rtsBool
-RoomToPack(size, ptrs)
-nat size, ptrs;
-{
-# if defined(PAR)
-  if (roomInBuffer &&
-      (pack_locn +                 // where we are in the buffer right now
-       size +                      // space needed for the current closure
-       QueuedClosuresMinSize(ptrs) // space for queued closures as FETCH_MEs
-       + 1                         // headroom (DEBUGGING only)
-       >= 
-       RTS_PACK_BUFFER_SIZE))
-    {
-      roomInBuffer = rtsFalse;
-    }
-# else   /* GRAN */
-  if (roomInBuffer &&
-      (unpacked_size + 
-       size +
-       QueuedClosuresMinSize(ptrs)
-       >= 
-       RTS_PACK_BUFFER_SIZE))
-    {
-      roomInBuffer = rtsFalse;
-    }
-# endif
-  return (roomInBuffer);
-}
-
-//@node Closure Info,  , Packet size, Aux fcts for packing
-//@subsubsection Closure Info
-
-/*
-   Closure Info
-
-   @get_closure_info@ determines the size, number of pointers etc. for this
-   type of closure -- see @SMInfoTables.lh@ for the legal info. types etc.
-
-[Can someone please keep this function up to date.  I keep needing it
- (or something similar) for interpretive code, and it keeps
- bit-rotting.  {\em It really belongs somewhere else too}.  KH @@ 17/2/95] */
-
-#if 0
-
-// {Parallel.h}Daq ngoqvam vIroQpu'
-
-# if defined(GRAN) || defined(PAR)
-/* extracting specific info out of closure; currently only used in GRAN -- HWL */
-//@cindex get_closure_info
-StgInfoTable*
-get_closure_info(node, size, ptrs, nonptrs, vhs, info_hdr_ty)
-StgClosure* node;
-nat *size, *ptrs, *nonptrs, *vhs;
-char *info_hdr_ty;
-{
-  StgInfoTable *info;
-
-  info = get_itbl(node);
-  /* the switch shouldn't be necessary, really; just use default case */
-  switch (info->type) {
-#if 0
-   case CONSTR_1_0:
-   case THUNK_1_0:
-   case FUN_1_0:
-     *size = sizeW_fromITBL(info);
-     *ptrs = (nat) 1; // (info->layout.payload.ptrs);
-     *nonptrs = (nat) 0; // (info->layout.payload.nptrs);
-     *vhs = (nat) 0; // unknown
-     info_hdr_type(node, info_hdr_ty);
-     return info;
-     
-  case CONSTR_0_1:
-  case THUNK_0_1:
-  case FUN_0_1:
-     *size = sizeW_fromITBL(info);
-     *ptrs = (nat) 0; // (info->layout.payload.ptrs);
-     *nonptrs = (nat) 1; // (info->layout.payload.nptrs);
-     *vhs = (nat) 0; // unknown
-     info_hdr_type(node, info_hdr_ty);
-     return info;
-
-  case CONSTR_2_0:
-  case THUNK_2_0:
-  case FUN_2_0:
-     *size = sizeW_fromITBL(info);
-     *ptrs = (nat) 2; // (info->layout.payload.ptrs);
-     *nonptrs = (nat) 0; // (info->layout.payload.nptrs);
-     *vhs = (nat) 0; // unknown
-     info_hdr_type(node, info_hdr_ty);
-     return info;
-
-  case CONSTR_1_1:
-  case THUNK_1_1:
-  case FUN_1_1:
-     *size = sizeW_fromITBL(info);
-     *ptrs = (nat) 1; // (info->layout.payload.ptrs);
-     *nonptrs = (nat) 1; // (info->layout.payload.nptrs);
-     *vhs = (nat) 0; // unknown
-     info_hdr_type(node, info_hdr_ty);
-     return info;
-
-  case CONSTR_0_2:
-  case THUNK_0_2:
-  case FUN_0_2:
-     *size = sizeW_fromITBL(info);
-     *ptrs = (nat) 0; // (info->layout.payload.ptrs);
-     *nonptrs = (nat) 2; // (info->layout.payload.nptrs);
-     *vhs = (nat) 0; // unknown
-     info_hdr_type(node, info_hdr_ty);
-     return info;
-#endif
-  case RBH:
-    {
-      StgInfoTable *rip = REVERT_INFOPTR(info); // closure to revert to
-      *size = sizeW_fromITBL(rip);
-      *ptrs = (nat) (rip->layout.payload.ptrs);
-      *nonptrs = (nat) (rip->layout.payload.nptrs);
-      *vhs = (nat) 0; // unknown
-      info_hdr_type(node, info_hdr_ty);
-      return rip;  // NB: we return the reverted info ptr for a RBH!!!!!!
-    }
-
-  default:
-    *size = sizeW_fromITBL(info);
-    *ptrs = (nat) (info->layout.payload.ptrs);
-    *nonptrs = (nat) (info->layout.payload.nptrs);
-    *vhs = (nat) 0; // unknown
-    info_hdr_type(node, info_hdr_ty);
-    return info;
-  }
-} 
-
-//@cindex IS_BLACK_HOLE
-rtsBool
-IS_BLACK_HOLE(StgClosure* node)          
-{ 
-  StgInfoTable *info;
-  info = get_itbl(node);
-  return ((info->type == BLACKHOLE || info->type == RBH) ? rtsTrue : rtsFalse);
-}
-
-//@cindex IS_INDIRECTION
-StgClosure *
-IS_INDIRECTION(StgClosure* node)          
-{ 
-  StgInfoTable *info;
-  info = get_itbl(node);
-  switch (info->type) {
-    case IND:
-    case IND_OLDGEN:
-    case IND_PERM:
-    case IND_OLDGEN_PERM:
-    case IND_STATIC:
-      /* relies on indirectee being at same place for all these closure types */
-      return (((StgInd*)node) -> indirectee);
-    default:
-      return NULL;
-  }
-}
-
-/*
-rtsBool
-IS_THUNK(StgClosure* node)
-{
-  StgInfoTable *info;
-  info = get_itbl(node);
-  return ((info->type == THUNK ||
-          info->type == THUNK_STATIC ||
-          info->type == THUNK_SELECTOR) ? rtsTrue : rtsFalse);
-}
-*/
-
-# endif /* GRAN */
-#endif /* 0 */
-
-# if 0
-/* ngoq ngo' */
-
-P_
-get_closure_info(closure, size, ptrs, nonptrs, vhs, type)
-P_ closure;
-W_ *size, *ptrs, *nonptrs, *vhs;
-char *type;
-{
-   P_ ip = (P_) INFO_PTR(closure);
-
-   if (closure==NULL) {
-     fprintf(stderr, "Qagh {get_closure_info}Daq: NULL closure\n");
-     *size = *ptrs = *nonptrs = *vhs = 0; 
-     strcpy(type,"ERROR in get_closure_info");
-     return;
-   } else if (closure==PrelBase_Z91Z93_closure) {
-     /* fprintf(stderr, "Qagh {get_closure_info}Daq: PrelBase_Z91Z93_closure closure\n"); */
-     *size = *ptrs = *nonptrs = *vhs = 0; 
-     strcpy(type,"PrelBase_Z91Z93_closure");
-     return;
-   };
-
-    ip = (P_) INFO_PTR(closure);
-
-    switch (INFO_TYPE(ip)) {
-    case INFO_SPEC_U_TYPE:
-    case INFO_SPEC_S_TYPE:
-    case INFO_SPEC_N_TYPE:
-       *size = SPEC_CLOSURE_SIZE(closure);
-       *ptrs = SPEC_CLOSURE_NoPTRS(closure);
-       *nonptrs = SPEC_CLOSURE_NoNONPTRS(closure);
-       *vhs = 0 /*SPEC_VHS*/;
-       strcpy(type,"SPEC");
-       break;
-
-    case INFO_GEN_U_TYPE:
-    case INFO_GEN_S_TYPE:
-    case INFO_GEN_N_TYPE:
-       *size = GEN_CLOSURE_SIZE(closure);
-       *ptrs = GEN_CLOSURE_NoPTRS(closure);
-       *nonptrs = GEN_CLOSURE_NoNONPTRS(closure);
-       *vhs = GEN_VHS;
-       strcpy(type,"GEN");
-       break;
-
-    case INFO_DYN_TYPE:
-       *size = DYN_CLOSURE_SIZE(closure);
-       *ptrs = DYN_CLOSURE_NoPTRS(closure);
-       *nonptrs = DYN_CLOSURE_NoNONPTRS(closure);
-       *vhs = DYN_VHS;
-       strcpy(type,"DYN");
-       break;
-
-    case INFO_TUPLE_TYPE:
-       *size = TUPLE_CLOSURE_SIZE(closure);
-       *ptrs = TUPLE_CLOSURE_NoPTRS(closure);
-       *nonptrs = TUPLE_CLOSURE_NoNONPTRS(closure);
-       *vhs = TUPLE_VHS;
-       strcpy(type,"TUPLE");
-       break;
-
-    case INFO_DATA_TYPE:
-       *size = DATA_CLOSURE_SIZE(closure);
-       *ptrs = DATA_CLOSURE_NoPTRS(closure);
-       *nonptrs = DATA_CLOSURE_NoNONPTRS(closure);
-       *vhs = DATA_VHS;
-       strcpy(type,"DATA");
-       break;
-
-    case INFO_IMMUTUPLE_TYPE:
-    case INFO_MUTUPLE_TYPE:
-       *size = MUTUPLE_CLOSURE_SIZE(closure);
-       *ptrs = MUTUPLE_CLOSURE_NoPTRS(closure);
-       *nonptrs = MUTUPLE_CLOSURE_NoNONPTRS(closure);
-       *vhs = MUTUPLE_VHS;
-       strcpy(type,"(IM)MUTUPLE");
-       break;
-
-    case INFO_STATIC_TYPE:
-       *size = STATIC_CLOSURE_SIZE(closure);
-       *ptrs = STATIC_CLOSURE_NoPTRS(closure);
-       *nonptrs = STATIC_CLOSURE_NoNONPTRS(closure);
-       *vhs = STATIC_VHS;
-       strcpy(type,"STATIC");
-       break;
-
-    case INFO_CAF_TYPE:
-    case INFO_IND_TYPE:
-       *size = IND_CLOSURE_SIZE(closure);
-       *ptrs = IND_CLOSURE_NoPTRS(closure);
-       *nonptrs = IND_CLOSURE_NoNONPTRS(closure);
-       *vhs = IND_VHS;
-       strcpy(type,"CAF|IND");
-       break;
-
-    case INFO_CONST_TYPE:
-       *size = CONST_CLOSURE_SIZE(closure);
-       *ptrs = CONST_CLOSURE_NoPTRS(closure);
-       *nonptrs = CONST_CLOSURE_NoNONPTRS(closure);
-       *vhs = CONST_VHS;
-       strcpy(type,"CONST");
-       break;
-
-    case INFO_SPEC_RBH_TYPE:
-       *size = SPEC_RBH_CLOSURE_SIZE(closure);
-       *ptrs = SPEC_RBH_CLOSURE_NoPTRS(closure);
-       *nonptrs = SPEC_RBH_CLOSURE_NoNONPTRS(closure);
-       if (*ptrs <= 2) {
-           *nonptrs -= (2 - *ptrs);
-           *ptrs = 1;
-       } else
-           *ptrs -= 1;
-       *vhs = SPEC_RBH_VHS;
-       strcpy(type,"SPEC_RBH");
-       break;
-
-    case INFO_GEN_RBH_TYPE:
-       *size = GEN_RBH_CLOSURE_SIZE(closure);
-       *ptrs = GEN_RBH_CLOSURE_NoPTRS(closure);
-       *nonptrs = GEN_RBH_CLOSURE_NoNONPTRS(closure);
-       if (*ptrs <= 2) {
-           *nonptrs -= (2 - *ptrs);
-           *ptrs = 1;
-       } else
-           *ptrs -= 1;
-       *vhs = GEN_RBH_VHS;
-       strcpy(type,"GEN_RBH");
-       break;
-
-    case INFO_CHARLIKE_TYPE:
-       *size = CHARLIKE_CLOSURE_SIZE(closure);
-       *ptrs = CHARLIKE_CLOSURE_NoPTRS(closure);
-       *nonptrs = CHARLIKE_CLOSURE_NoNONPTRS(closure);
-       *vhs = CHARLIKE_VHS;
-       strcpy(type,"CHARLIKE");
-       break;
-
-    case INFO_INTLIKE_TYPE:
-       *size = INTLIKE_CLOSURE_SIZE(closure);
-       *ptrs = INTLIKE_CLOSURE_NoPTRS(closure);
-       *nonptrs = INTLIKE_CLOSURE_NoNONPTRS(closure);
-       *vhs = INTLIKE_VHS;
-       strcpy(type,"INTLIKE");
-       break;
-
-#  if !defined(GRAN)
-    case INFO_FETCHME_TYPE:
-       *size = FETCHME_CLOSURE_SIZE(closure);
-        *ptrs = FETCHME_CLOSURE_NoPTRS(closure);
-        *nonptrs = FETCHME_CLOSURE_NoNONPTRS(closure);
-        *vhs = FETCHME_VHS;
-       strcpy(type,"FETCHME");
-       break;
-
-    case INFO_FMBQ_TYPE:
-       *size = FMBQ_CLOSURE_SIZE(closure);
-        *ptrs = FMBQ_CLOSURE_NoPTRS(closure);
-        *nonptrs = FMBQ_CLOSURE_NoNONPTRS(closure);
-        *vhs = FMBQ_VHS;
-       strcpy(type,"FMBQ");
-       break;
-#  endif
-
-    case INFO_BQ_TYPE:
-       *size = BQ_CLOSURE_SIZE(closure);
-        *ptrs = BQ_CLOSURE_NoPTRS(closure);
-        *nonptrs = BQ_CLOSURE_NoNONPTRS(closure);
-        *vhs = BQ_VHS;
-       strcpy(type,"BQ");
-       break;
-
-    case INFO_BH_TYPE:
-       *size = BH_CLOSURE_SIZE(closure);
-        *ptrs = BH_CLOSURE_NoPTRS(closure);
-        *nonptrs = BH_CLOSURE_NoNONPTRS(closure);
-        *vhs = BH_VHS;
-       strcpy(type,"BH");
-       break;
-
-    case INFO_TSO_TYPE:
-       *size = 0; /* TSO_CLOSURE_SIZE(closure); */
-        *ptrs = 0; /* TSO_CLOSURE_NoPTRS(closure); */
-        *nonptrs = 0; /* TSO_CLOSURE_NoNONPTRS(closure); */
-        *vhs = TSO_VHS;
-       strcpy(type,"TSO");
-       break;
-
-    case INFO_STKO_TYPE:
-        *size = 0;
-       *ptrs = 0;
-        *nonptrs = 0;
-       *vhs = STKO_VHS;
-       strcpy(type,"STKO");
-        break;
-
-    default:
-       fprintf(stderr, "get_closure_info:  Unexpected closure type (%lu), closure %lx\n",
-         INFO_TYPE(ip), (StgWord) closure);
-       EXIT(EXIT_FAILURE);
-    }
-
-    return ip;
-}
-# endif
-
-# if 0
-// Use allocate in Storage.c instead
-/*
-   @AllocateHeap@ will bump the heap pointer by @size@ words if the space
-   is available, but it will not perform garbage collection.
-   ToDo: check whether we can use an existing STG allocation routine -- HWL
-*/
-
-
-//@cindex AllocateHeap
-StgPtr
-AllocateHeap(size)
-nat size;
-{
-  StgPtr newClosure;
-  
-  /* Allocate a new closure */
-  if (Hp + size > HpLim)
-    return NULL;
-  
-  newClosure = Hp + 1;
-  Hp += size;
-  
-  return newClosure;
-}
-# endif
-
-# if defined(PAR)
-
-//@cindex doGlobalGC
-void
-doGlobalGC(void)
-{
-  fprintf(stderr,"Splat -- we just hit global GC!\n");
-  stg_exit(EXIT_FAILURE);
-  //fishing = rtsFalse;
-  outstandingFishes--;
-}
-
-# endif /* PAR */
-
-//@node Printing Packet Contents, End of file, Aux fcts for packing, Graph packing
-//@subsection Printing Packet Contents
-/*
-  Printing Packet Contents
-  */
-
-#if defined(DEBUG) || defined(GRAN_CHECK)
-
-//@cindex PrintPacket
-
-#if defined(PAR)
-void
-PrintPacket(packBuffer)
-rtsPackBuffer *packBuffer;
-{
-  StgClosure *parent, *graphroot, *closure_start;
-  const StgInfoTable *ip;
-  globalAddr ga;
-  StgWord **bufptr, **slotptr;
-
-  nat bufsize;
-  nat pptr = 0, pptrs = 0, pvhs;
-  nat locn = 0;
-  nat i;
-  nat size, ptrs, nonptrs, vhs;
-  char str[80];
-
-  /* disable printing if a non-std globalisation scheme is used; ToDo: FIX */
-  if (RtsFlags.ParFlags.globalising != 0)
-    return;
-
-  /* NB: this whole routine is more or less a copy of UnpackGraph with all
-     unpacking components replaced by printing fcts
-     Long live higher-order fcts!
-  */
-  /* Initialisation */
-  //InitPackBuffer();                  /* in case it isn't already init'd */
-  InitClosureQueue();
-  // ASSERT(gaga==PendingGABuffer); 
-  graphroot = (StgClosure *)NULL;
-
-  /* Unpack the header */
-  bufsize = packBuffer->size;
-  bufptr = packBuffer->buffer;
-
-  fprintf(stderr, "*. Printing <<%d>> (buffer @ %p):\n", 
-         packBuffer->id, packBuffer);
-  fprintf(stderr, "*.   size: %d; unpacked_size: %d; tso: %p; buffer: %p\n",
-         packBuffer->size, packBuffer->unpacked_size, 
-         packBuffer->tso, packBuffer->buffer);
-
-  parent = (StgClosure *)NULL;
-
-  do {
-    /* This is where we will ultimately save the closure's address */
-    slotptr = bufptr;
-    locn = slotptr-(packBuffer->buffer); // index of closure in buffer
-
-    /* First, unpack the next GA or PLC */
-    ga.weight = (rtsWeight) *bufptr++;
-
-    if (ga.weight == 2) {  // unglobalised closure to follow
-      // nothing to do; closure starts at *bufptr
-    } else if (ga.weight > 0) { // fill in GA
-      ga.payload.gc.gtid = (GlobalTaskId) *bufptr++;
-      ga.payload.gc.slot = (int) *bufptr++;
-    } else
-      ga.payload.plc = (StgPtr) *bufptr++;
-    
-    /* Now unpack the closure body, if there is one */
-    if (isFixed(&ga)) {
-      fprintf(stderr, "*. %u: PLC @ %p\n", locn, ga.payload.plc);
-      // closure = ga.payload.plc;
-    } else if (isOffset(&ga)) {
-      fprintf(stderr, "*. %u: OFFSET TO %d\n", locn, ga.payload.gc.slot);
-      // closure = (StgClosure *) buffer[ga.payload.gc.slot];
-    } else {
-      /* Print normal closures */
-
-      ASSERT(bufsize > 0);
-
-      fprintf(stderr, "*. %u: ((%x, %d, %x)) ", locn,
-              ga.payload.gc.gtid, ga.payload.gc.slot, ga.weight);
-
-      closure_start = (StgClosure*)bufptr;
-      ip = get_closure_info((StgClosure *)bufptr, 
-                           &size, &ptrs, &nonptrs, &vhs, str);
-         
-      /* ToDo: check whether this is really needed */
-      if (ip->type == FETCH_ME || ip->type == REMOTE_REF) {
-       size = _HS;
-       ptrs = nonptrs = vhs = 0;
-      }
-      /* ToDo: check whether this is really needed */
-      if (ip->type == ARR_WORDS) {
-       ptrs = vhs = 0;
-       nonptrs = ((StgArrWords *)bufptr)->words;
-       size = arr_words_sizeW((StgArrWords *)bufptr);
-      }
-
-      /* special code for printing a PAP in a buffer */
-      if (ip->type == PAP || ip->type == AP_UPD) {
-        vhs = 3; 
-       ptrs = 0;
-        nonptrs = (nat)((StgPAP *)bufptr)->payload[0];
-       size = _HS+vhs+ptrs+nonptrs;
-      }
-
-      /* 
-        Remember, the generic closure layout is as follows:
-        +-------------------------------------------------+
-        | FIXED HEADER | VARIABLE HEADER | PTRS | NON-PRS |
-        +-------------------------------------------------+
-      */
-      /* Print fixed header */
-      fprintf(stderr, "FH ["); 
-      for (i = 0; i < _HS; i++)
-       fprintf(stderr, " %p", *bufptr++);
-
-      if (ip->type == FETCH_ME || ip->type == REMOTE_REF)
-       size = ptrs = nonptrs = vhs = 0;
-
-      // VH is always empty in the new RTS
-      ASSERT(vhs==0 ||
-             ip->type == PAP || ip->type == AP_UPD);
-      /* Print variable header */
-      fprintf(stderr, "] VH ["); 
-      for (i = 0; i < vhs; i++)
-       fprintf(stderr, " %p", *bufptr++);
-
-      //fprintf(stderr, "] %d PTRS [", ptrs); 
-      /* Pointers will be filled in later */
-
-      fprintf(stderr, " ] (%d, %d) [", ptrs, nonptrs); 
-      /* Print non-pointers */
-      for (i = 0; i < nonptrs; i++)
-       fprintf(stderr, " %p", *bufptr++);
-
-      fprintf(stderr, "] (%s)\n", str);
-
-      /* Indirections are never packed */
-      // ASSERT(INFO_PTR(graph) != (W_) Ind_info_TO_USE);
-
-      /* Add to queue for processing 
-        When just printing the packet we do not have an unpacked closure
-        in hand, so we feed it the packet entry; 
-        again, this assumes that at least the fixed header of the closure
-        has the same layout in the packet; also we may not overwrite entries
-        in the packet (done in Unpack), but for printing that's a bad idea
-        anyway */
-      QueueClosure((StgClosure *)closure_start);
-       
-      /* No Common up needed for printing */
-
-      /* No Sort out the global address mapping for printing */
-
-    } /* normal closure case */
-
-    /* Locate next parent pointer */
-    pptr++;
-    while (pptr + 1 > pptrs) {
-      parent = DeQueueClosure();
-
-      if (parent == NULL)
-       break;
-      else {
-       (void) get_closure_info(parent, &size, &pptrs, &nonptrs,
-                                       &pvhs, str);
-       pptr = 0;
-      }
-    }
-  } while (parent != NULL);
-  fprintf(stderr, "*. --- End packet <<%d>> (claimed size=%d; real size=%d)---\n", 
-         packBuffer->id, packBuffer->size, size);
-
-}
-
-/*
-  Doing a sanity check on a packet.
-  This does a full iteration over the packet, as in PrintPacket.
-*/
-//@cindex checkPacket
-void
-checkPacket(packBuffer)
-rtsPackBuffer *packBuffer;
-{
-  StgClosure *parent, *graphroot, *closure_start;
-  const StgInfoTable *ip;
-  globalAddr ga;
-  StgWord **bufptr, **slotptr;
-
-  nat bufsize;
-  nat pptr = 0, pptrs = 0, pvhs;
-  nat locn = 0;
-  nat size, ptrs, nonptrs, vhs;
-  char str[80];
-
-  /* NB: this whole routine is more or less a copy of UnpackGraph with all
-     unpacking components replaced by printing fcts
-     Long live higher-order fcts!
-  */
-  /* Initialisation */
-  //InitPackBuffer();                  /* in case it isn't already init'd */
-  InitClosureQueue();
-  // ASSERT(gaga==PendingGABuffer); 
-  graphroot = (StgClosure *)NULL;
-
-  /* Unpack the header */
-  bufsize = packBuffer->size;
-  bufptr = packBuffer->buffer;
-  parent = (StgClosure *)NULL;
-  ASSERT(bufsize > 0);
-  do {
-    /* check that we are not at the end of the buffer, yet */
-    IF_DEBUG(sanity, ASSERT(*bufptr != END_OF_BUFFER_MARKER));
-
-    /* This is where we will ultimately save the closure's address */
-    slotptr = bufptr;
-    locn = slotptr-(packBuffer->buffer); // index of closure in buffer
-    ASSERT(locn<=bufsize);
-  
-    /* First, check whether we have a GA, a PLC, or an OFFSET at hand */
-    ga.weight = (rtsWeight) *bufptr++;
-
-    if (ga.weight == 2) {  // unglobalised closure to follow
-      // nothing to do; closure starts at *bufptr
-    } else if (ga.weight > 0) { // fill in GA
-      ga.payload.gc.gtid = (GlobalTaskId) *bufptr++;
-      ga.payload.gc.slot = (int) *bufptr++;
-    } else
-      ga.payload.plc = (StgPtr) *bufptr++;
-    
-    /* Now unpack the closure body, if there is one */
-    if (isFixed(&ga)) {
-      /* It's a PLC */
-      ASSERT(LOOKS_LIKE_STATIC(ga.payload.plc));
-    } else if (isOffset(&ga)) {
-      ASSERT(ga.payload.gc.slot<=(int)bufsize);
-    } else {
-      /* normal closure */
-      ASSERT(!RtsFlags.ParFlags.globalising==0 || LOOKS_LIKE_GA(&ga));
-
-      closure_start = (StgClosure*)bufptr;
-      ASSERT(LOOKS_LIKE_GHC_INFO((StgPtr)*bufptr));
-      ip = get_closure_info((StgClosure *)bufptr, 
-                           &size, &ptrs, &nonptrs, &vhs, str);
-
-      /* ToDo: check whether this is really needed */
-      if (ip->type == FETCH_ME || ip->type == REMOTE_REF) {
-       size = _HS;
-       ptrs = nonptrs = vhs = 0;
-      }
-      /* ToDo: check whether this is really needed */
-      if (ip->type == ARR_WORDS) {
-       ptrs = vhs = 0;
-       nonptrs = ((StgArrWords *)bufptr)->words+1; // payload+words
-       size = arr_words_sizeW((StgArrWords *)bufptr);
-       ASSERT(size==_HS+vhs+nonptrs);
-      }
-      /* special code for printing a PAP in a buffer */
-      if (ip->type == PAP || ip->type == AP_UPD) {
-        vhs = 3; 
-       ptrs = 0;
-        nonptrs = (nat)((StgPAP *)bufptr)->payload[0];
-       size = _HS+vhs+ptrs+nonptrs;
-      }
-
-      /* no checks on contents of closure (pointers aren't packed anyway) */
-      ASSERT(_HS+vhs+nonptrs>=MIN_NONUPD_SIZE);
-      bufptr += _HS+vhs+nonptrs;
-
-      /* Add to queue for processing */
-      QueueClosure((StgClosure *)closure_start);
-       
-      /* No Common up needed for checking */
-
-      /* No Sort out the global address mapping for checking */
-
-    } /* normal closure case */
-
-    /* Locate next parent pointer */
-    pptr++;
-    while (pptr + 1 > pptrs) {
-      parent = DeQueueClosure();
-
-      if (parent == NULL)
-       break;
-      else {
-       //ASSERT(LOOKS_LIKE_GHC_INFO((StgPtr)*parent));
-       (void) get_closure_info(parent, &size, &pptrs, &nonptrs,
-                                       &pvhs, str);
-       pptr = 0;
-      }
-    }
-  } while (parent != NULL);
-  /* we unpacked exactly as many words as there are in the buffer */
-  ASSERT(packBuffer->size == bufptr-(packBuffer->buffer));
-  /* check for magic end-of-buffer word */  
-  IF_DEBUG(sanity, ASSERT(*bufptr == END_OF_BUFFER_MARKER));
-}
-#else  /* GRAN */
-void
-PrintPacket(buffer)
-rtsPackBuffer *buffer;
-{
-    // extern char *info_hdr_type(P_ infoptr);  /* defined in Threads.lc */
-    // extern char *display_info_type(P_ infoptr);      /* defined in Threads.lc */
-
-    StgInfoTable *info;
-    nat size, ptrs, nonptrs, vhs;
-    char info_hdr_ty[80];
-    char str1[80], str2[80], junk_str[80];
-
-    /* globalAddr ga; */
-
-    nat bufsize, unpacked_size ;
-    StgClosure *parent;
-    nat pptr = 0, pptrs = 0, pvhs;
-
-    nat unpack_locn = 0;
-    nat gastart = unpack_locn;
-    nat closurestart = unpack_locn;
-
-    StgTSO *tso;
-    StgClosure *closure, *p;
-
-    nat i;
-
-    fprintf(stderr, "*** Printing <<%d>> (buffer @ %p):\n", buffer->id, buffer);
-    fprintf(stderr, "  size: %d; unpacked_size: %d; tso: %d (%p); buffer: %p\n",
-           buffer->size, buffer->unpacked_size, buffer->tso, buffer->buffer);
-    fputs("  contents: ", stderr);
-    for (unpack_locn=0; unpack_locn<buffer->size; unpack_locn++) {
-      closure = buffer->buffer[unpack_locn];
-      fprintf(stderr, ", %p (%s)", 
-             closure, info_type(closure)); 
-    }
-    fputc('\n', stderr);
-
-#if 0
-    /* traverse all elements of the graph; omitted for now, but might be usefule */
-    InitClosureQueue();
-
-    tso = buffer->tso;
-
-    /* Unpack the header */
-    unpacked_size = buffer->unpacked_size;
-    bufsize = buffer->size;
-
-    fprintf(stderr, "Packet %p, size %u (unpacked size is %u); demanded by TSO %d (%p)[PE %d]\n--- Begin ---\n", 
-                   buffer, bufsize, unpacked_size,  
-                   tso->id, tso, where_is((StgClosure*)tso));
-
-    do {
-       closurestart = unpack_locn;
-       closure = buffer->buffer[unpack_locn++];
-       
-       fprintf(stderr, "[%u]: (%p) ", closurestart, closure);
-
-       info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str1);
-       strcpy(str2, str1);
-       fprintf(stderr, "(%s|%s) ", str1, str2);
-       
-        if (info->type == FETCH_ME || info->type == FETCH_ME_BQ || 
-           IS_BLACK_HOLE(closure))
-         size = ptrs = nonptrs = vhs = 0;
-       
-       if (closure_THUNK(closure)) {
-               if (closure_UNPOINTED(closure))
-                   fputs("UNPOINTED ", stderr);
-               else
-                   fputs("POINTED ", stderr);
-       } 
-        if (IS_BLACK_HOLE(closure)) {
-               fputs("BLACK HOLE\n", stderr);
-       } else {
-               /* Fixed header */
-               fprintf(stderr, "FH ["); 
-               for (i = 0, p = (StgClosure*)&(closure->header); i < _HS; i++, p++)
-                   fprintf(stderr, " %p", *p);
-       
-               /* Variable header 
-               if (vhs > 0) {
-                   fprintf(stderr, "] VH [%p", closure->payload[_HS]);
-       
-                   for (i = 1; i < vhs; i++)
-                       fprintf(stderr, " %p", closure->payload[_HS+i]);
-               }
-               */
-               fprintf(stderr, "] PTRS %u", ptrs);
-       
-               /* Non-pointers */
-               if (nonptrs > 0) {
-                   fprintf(stderr, " NPTRS [%p", closure->payload[_HS+vhs]);
-               
-                   for (i = 1; i < nonptrs; i++)
-                       fprintf(stderr, " %p", closure->payload[_HS+vhs+i]);
-       
-                   putc(']', stderr);
-               }
-               putc('\n', stderr);
-       }
-    } while (unpack_locn<bufsize) ;  /* (parent != NULL); */
-
-    fprintf(stderr, "--- End ---\n\n");
-#endif /* 0 */
-}
-#endif /* PAR */
-#endif /* DEBUG || GRAN_CHECK */
-
-#endif /* PAR  || GRAN  -- whole file */
-
-//@node End of file,  , Printing Packet Contents, Graph packing
-//@subsection End of file
-
-//@index
-//* AllocateHeap::  @cindex\s-+AllocateHeap
-//* AmPacking::  @cindex\s-+AmPacking
-//* CommonUp::  @cindex\s-+CommonUp
-//* DeQueueClosure::  @cindex\s-+DeQueueClosure
-//* DeQueueClosure::  @cindex\s-+DeQueueClosure
-//* DonePacking::  @cindex\s-+DonePacking
-//* FillInClosure::  @cindex\s-+FillInClosure
-//* IS_BLACK_HOLE::  @cindex\s-+IS_BLACK_HOLE
-//* IS_INDIRECTION::  @cindex\s-+IS_INDIRECTION
-//* InitClosureQueue::  @cindex\s-+InitClosureQueue
-//* InitPendingGABuffer::  @cindex\s-+InitPendingGABuffer
-//* LocateNextParent::  @cindex\s-+LocateNextParent
-//* NotYetPacking::  @cindex\s-+NotYetPacking
-//* OffsetFor::  @cindex\s-+OffsetFor
-//* Pack::  @cindex\s-+Pack
-//* PackArray::  @cindex\s-+PackArray
-//* PackClosure::  @cindex\s-+PackClosure
-//* PackFetchMe::  @cindex\s-+PackFetchMe
-//* PackGeneric::  @cindex\s-+PackGeneric
-//* PackNearbyGraph::  @cindex\s-+PackNearbyGraph
-//* PackOneNode::  @cindex\s-+PackOneNode
-//* PackPAP::  @cindex\s-+PackPAP
-//* PackPLC::  @cindex\s-+PackPLC
-//* PackStkO::  @cindex\s-+PackStkO
-//* PackTSO::  @cindex\s-+PackTSO
-//* PendingGABuffer::  @cindex\s-+PendingGABuffer
-//* PrintPacket::  @cindex\s-+PrintPacket
-//* QueueClosure::  @cindex\s-+QueueClosure
-//* QueueEmpty::  @cindex\s-+QueueEmpty
-//* RoomToPack::  @cindex\s-+RoomToPack
-//* SetGAandCommonUp::  @cindex\s-+SetGAandCommonUp
-//* UnpackGA::  @cindex\s-+UnpackGA
-//* UnpackGraph::  @cindex\s-+UnpackGraph
-//* UnpackOffset::  @cindex\s-+UnpackOffset
-//* UnpackPLC::  @cindex\s-+UnpackPLC
-//* doGlobalGC::  @cindex\s-+doGlobalGC
-//* get_closure_info::  @cindex\s-+get_closure_info
-//* InitPackBuffer::  @cindex\s-+initPackBuffer
-//* isFixed::  @cindex\s-+isFixed
-//* isOffset::  @cindex\s-+isOffset
-//* offsetTable::  @cindex\s-+offsetTable
-//@end index
-