[project @ 1999-03-18 14:16:00 by kw217]
[ghc-hetmet.git] / docs / rts / rts.verb
index c6d0de0..4fb0a01 100644 (file)
 \newcommand{\note}[1]{{{\bf Note:}\sl #1}}
 \newcommand{\ToDo}[1]{{{\bf ToDo:}\sl #1}}
 \newcommand{\Arg}[1]{\mbox{${\tt arg}_{#1}$}}
-\newcommand{\bottom}{bottom} % foo, can't remember the symbol name
+\newcommand{\bottom}{\perp}
+
+\newcommand{\secref}[1]{Section~\ref{sec:#1}}
+\newcommand{\figref}[1]{Figure~\ref{fig:#1}}
+\newcommand{\Section}[2]{\section{#1}\label{sec:#2}}
+\newcommand{\Subsection}[2]{\subsection{#1}\label{sec:#2}}
+\newcommand{\Subsubsection}[2]{\subsubsection{#1}\label{sec:#2}}
 
 % DIMENSION OF TEXT:
 \textheight 8.5 in
@@ -48,8 +54,8 @@
 \begin{document}
 
 \title{The STG runtime system (revised)}
-\author{Simon Peyton Jones \\ Glasgow University and Oregon Graduate Institute \and
-Simon Marlow \\ Glasgow University \and
+\author{Simon Peyton Jones \\ Microsoft Research Ltd., Cambridge \and
+Simon Marlow \\ Microsoft Research Ltd., Cambridge \and
 Alastair Reid \\ Yale University} 
 
 \maketitle
@@ -58,12 +64,12 @@ Alastair Reid \\ Yale University}
 \newpage
 
 \part{Introduction}
-\section{Overview}
+\Section{Overview}{overview}
 
 This document describes the GHC/Hugs run-time system.  It serves as 
 a Glasgow/Yale/Nottingham ``contract'' about what the RTS does.
 
-\subsection{New features compared to GHC 2.04}
+\Subsection{New features compared to GHC 3.xx}{new-features}
 
 \begin{itemize}
 \item The RTS supports mixed compiled/interpreted execution, so
@@ -80,29 +86,31 @@ in code, this means that the garbage collector must traverse the whole
 accessible code tree.  This feature eliminates a whole class of painful
 space leaks.
 
-\item A running thread has only one stack, which contains a mixture
-of pointers and non-pointers.  Section~\ref{sect:stacks} describes how
-we find out which is which.  (GHC has used two stacks for some while.
-Using one stack instead of two reduces register pressure, reduces the
-size of update frames, and eliminates
-``stack-stubbing'' instructions.)
+\item A running thread has only one stack, which contains a mixture of
+pointers and non-pointers.  \secref{TSO} describes how we find out
+which is which.  (GHC has used two stacks for some while.  Using one
+stack instead of two reduces register pressure, reduces the size of
+update frames, and eliminates ``stack-stubbing'' instructions.)
 
 \item The ``return in registers'' return convention has been dropped
 because it was complicated and doesn't work well on register-poor
 architectures.  It has been partly replaced by unboxed tuples
-(section~\ref{sect:unboxed-tuples}) which allow the programmer to
+(\secref{unboxed-tuples}) which allow the programmer to
 explicitly state where results should be returned in registers (or on
 the stack) instead of on the heap.
 
-\item
+\item Exceptions are supported by the RTS.
+
+\item Weak Pointers generalise the previously available Foreign Object
+interface.
 
-Lazy black-holing has been replaced by eager black-holing.  The
-problem with lazy black-holing is that it leaves slop in the heap
-which conflicts with the use of a mostly-copying collector.
+\item The garbage collector supports a number of new features,
+including a dynamically resizable heap and multiple generations with
+aging within a generation.
 
-\end{itemize} 
+\end{itemize}
 
-\subsection{Wish list}
+\Subsection{Wish list}{wish-list}
 
 Here's a list of things we'd like to support in the future.
 \begin{itemize}
@@ -113,19 +121,13 @@ The SM could tune the size of the allocation arena, the number of
 generations, etc taking into account residency, GC rate and page fault
 rate.
 
-\item
-There should be no need to specify the amnount of stack/heap space to
-allocate when you started a program - let it just take as much or as
-little as it wants.  (It might be useful to be able to specify maximum
-sizes and to be able to suggest an initial size.)
-
 \item 
 We could trigger a GC when all threads are blocked waiting for IO if
 the allocation arena (or some of the generations) are nearly full.
 
 \end{itemize}
 
-\subsection{Configuration}
+\Subsection{Configuration}{configuration}
 
 Some of the above features are expensive or less portable, so we
 envision building a number of different configurations supporting
@@ -155,7 +157,7 @@ Which garbage collector to use.  At the moment we
 only anticipate one, however.
 \end{itemize}
 
-\subsection{Glossary}
+\Subsection{Glossary}{glossary}
 
 \ToDo{This terminology is not used consistently within the document.
 If you find something which disagrees with this terminology, fix the
@@ -215,13 +217,12 @@ function pointer or a data pointer.
 
 Occasionally, a field of a data structure must hold either a word or a
 pointer.  In such circumstances, it is \emph{not safe} to assume that
-words and pointers are the same size.
+words and pointers are the same size.  \ToDo{GHC currently makes words
+the same size as pointers to reduce complexity in the code
+generator/RTS.  It would be useful to relax this restriction, and have
+eg. 32-bit Ints on a 64-bit machine.}
 
-
-
-% Todo:
-% More terminology to mention.
-% unboxed, unpointed
+% should define terms like SRT, CAF, PAP, etc. here?  --KSW 1999-03
 
 \subsection{Subtle Dependencies}
 
@@ -234,20 +235,20 @@ down in case we want to change our minds.
 
 If the garbage collector is allowed to shrink the stack of a thread,
 we cannot omit the stack check in return continuations
-(section~\ref{sect:heap-and-stack-checks}).
+(\secref{heap-and-stack-checks}).
 
 \item
 
 When we return to the scheduler, the top object on the stack is a closure.
 The scheduler restarts the thread by entering the closure.
 
-Section~\ref{sect:hugs-return-convention} discusses how Hugs returns an
+\secref{hugs-return-convention} discusses how Hugs returns an
 unboxed value to GHC and how GHC returns an unboxed value to Hugs.
 
 \item 
 
 When we return to the scheduler, we need a few empty words on the stack
-to store a closure to reenter.  Section~\ref{sect:heap-and-stack-checks}
+to store a closure to reenter.  \secref{heap-and-stack-checks}
 discusses who does the stack check and how much space they need.
 
 \item
@@ -258,12 +259,18 @@ support mostly-copying garbage collection.
 This is a big problem when updating since the updatee is usually
 bigger than an indirection object.  The fix is to overwrite the end of
 the updatee with ``slop objects'' (described in
-section~\ref{sect:slop-objects}).
-This is hard to arrange if we do \emph{lazy} blackholing
-(section~\ref{sect:lazy-black-holing}) so we currently plan to
-blackhole an object when we push the update frame.
-
-
+\secref{slop-objects}).  This is hard to arrange if we do
+\emph{lazy} blackholing (\secref{lazy-black-holing}) so we
+currently plan to blackhole an object when we push the update frame.
+
+% Idea: have specialised update code for various common sizes of
+% updatee, the update frame hence encodes the length of the object.
+% Specialised indirections will also encode the length of the object.  A
+% generic version of the update code will overwrite the slop with a slop
+% object.  We can do the same thing for blackhole objects, or just have
+% a generic version that is the same size as an indirection and
+% overwrite the slop with a slop object when blackholing.  So: does this
+% avoid the need to do eager black holing?
 
 \item
 
@@ -274,9 +281,9 @@ choice of return convention.
 
 \end{itemize}
 
-\section{Source Language}
+\Section{Source Language}{source-language}
 
-\subsection{Explicit Allocation}\label{sect:explicit-allocation}
+\Subsection{Explicit Allocation}{explicit-allocation}
 
 As in the original STG machine, (almost) all heap allocation is caused
 by executing a let(rec).  Since we no longer support the return in
@@ -294,7 +301,7 @@ instead of
 
 \note{For historical reasons, GHC doesn't use this syntax --- but it should.}
 
-\subsection{Unboxed tuples}\label{sect:unboxed-tuples}
+\Subsection{Unboxed tuples}{unboxed-tuples}
 
 Functions can take multiple arguments as easily as they can take one
 argument: there's no cost for adding another argument.  But functions
@@ -366,7 +373,7 @@ in a return continuation for an unboxed-tuple scrutinee.
 
 \end{itemize}
 
-\subsection{STG Syntax}
+\Subsection{STG Syntax}{stg-syntax}
 
 
 \ToDo{Insert STG syntax with appropriate changes.}
@@ -385,32 +392,32 @@ The major components of the system are:
 
 \item 
 
-The evaluators (section~\ref{sect:sm-overview}) are responsible for
+The evaluators (\secref{sm-overview}) are responsible for
 evaluating heap objects.  The system supports two evaluators: the
 machine code evaluator; and the bytecode evaluator.
 
 \item 
 
-The scheduler (section~\ref{sect:scheduler-overview}) acts as the
+The scheduler (\secref{scheduler-overview}) acts as the
 coordinator for the whole system.  It is responsible for switching
 between evaluators, switching between threads, garbage collection,
 communication between multiple processors, etc.
 
 \item 
 
-The storage manager (section~\ref{sect:evaluators-overview}) is
+The storage manager (\secref{evaluators-overview}) is
 responsible for allocating blocks of contiguous memory and for garbage
 collection.
 
 \item 
 
-The loader (section~\ref{sect:loader-overview}) is responsible for
+The loader (\secref{loader-overview}) is responsible for
 loading machine code and bytecode files from the file system and for
 resolving references between separately compiled modules.
 
 \item 
 
-The compilers (section~\ref{sect:compilers-overview}) generate machine
+The compilers (\secref{compilers-overview}) generate machine
 code and bytecode files which can be loaded by the loader.
 
 \end{itemize}
@@ -419,7 +426,7 @@ code and bytecode files which can be loaded by the loader.
 and communicating only with the scheduler}
 
 
-\section{The Evaluators}\label{sect:evaluators-overview}
+\Section{The Evaluators}{evaluators-overview}
 
 There are two evaluators: a machine code evaluator and a bytecode
 evaluator.  The evaluators task is to evaluate code within a thread
@@ -437,13 +444,12 @@ until one of the following happens:
 The evaluators expect to find a closure on top of the thread's stack
 and terminate with a closure on top of the thread's stack.
 
-\subsection{Evaluation Model}
-\label{sect:evaluation-model}
+\Subsection{Evaluation Model}{evaluation-model}
 
 Whilst the evaluators differ internally, they share a common
 evaluation model and many object representations.
 
-\subsubsection{Heap Objects}
+\Subsubsection{Heap objects}{heap-objects-overview}
 
 The choice of heap and stack objects used by the evaluators is tightly
 bound to the evaluation model.  This section provides an overview of
@@ -458,15 +464,14 @@ All heap objects look like this:
 \end{tabular}
 \end{center}
 
-The header's vary between different kinds of object but they all start
+The headers vary between different kinds of object but they all start
 with a pointer to a pair consisting of an \emph{info table} and some
 \emph{entry code}.  The info table is used both by the evaluators and
-by the storage manager and contains an @INFO_TYPE@ field which
-identifies which kind of heap object uses it and determines the
-interpretation of the payload and of the other fields of the info
-table.  The entry code is some machine code used by the machine code
-evaluator to evaluate closures and raises an error for other kinds of
-objects.
+by the storage manager and contains a @type@ field which identifies
+which kind of heap object uses it and determines the interpretation of
+the payload and of the other fields of the info table.  The entry code
+is some machine code used by the machine code evaluator to evaluate
+closures and raises an error for other kinds of objects.
 
 The major kinds of heap object used are as follows.  (For simplicity,
 this description omits certain optimisations and extra fields required
@@ -484,14 +489,14 @@ constructor is stored in the info table.
 \end{tabular}
 \end{center}
 
-\item[Primitive objects] are used to represent objects with unpointed
+\item[Primitive objects] are used to represent objects with unlifted
 types which are too large to fit in a register (or stack slot) or for
 which sharing must be preserved.  Primitive objects include large
 objects such as multiple precision integers and immutable arrays and
 mutable objects such as mutable arrays, mutable variables, MVar's,
-IVar's and foreign object pointers.  Since unpointed objects are not
-pointed, they cannot be entered.  Their payload varies according to
-the kind of object.
+IVar's and foreign object pointers.  Since primitive objects are not
+lifted, they cannot be entered.  Their payload varies according to the
+kind of object.
 
 \item[Function closures] are used to represent functions.  Their
 payload (if any) consists of the free variables of the function.
@@ -507,10 +512,10 @@ Function closures are only generated by the machine code compiler.
 \item[Thunks] are used to represent unevaluated expressions which will
 be updated with their result.  Their payload (if any) consists of the
 free variables of the function.  The entry code for a thunk starts by
-pushing an \emph{update frame} onto the stack and overwriting the
-thunk with a \emph{black hole}.  When evaluation of the thunk
-completes, the update frame will cause the thunk to be overwritten
-again with an \emph{indirection} to the result of the thunk.
+pushing an \emph{update frame} onto the stack.  When evaluation of the
+thunk completes, the update frame will cause the thunk to be
+overwritten again with an \emph{indirection} to the result of the
+thunk, which is always a constructor or a partial application.
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
@@ -518,11 +523,11 @@ again with an \emph{indirection} to the result of the thunk.
 \end{tabular}
 \end{center}
 
-Thunks are only generated by the machine code compiler.
+Thunks are only generated by the machine code evaluator.
 
 \item[Byte-code Objects (@BCO@s)] are generated by the bytecode
-compiler.  In conjunction with \emph{updateable applications} and
-\emph{non-updateeable applications} they are used to represent
+compiler.  In conjunction with \emph{updatable applications} and
+\emph{non-updatable applications} they are used to represent
 functions, unevaluated expressions and return addresses.
 
 \begin{center}
@@ -531,7 +536,7 @@ functions, unevaluated expressions and return addresses.
 \end{tabular}
 \end{center}
 
-\item[Non-updatable Applications] are used to represent the
+\item[Non-updatable (Partial) Applications] are used to represent the
 application of a function to an insufficient number of arguments.
 Their payload consists of the function and the arguments received so far.
 
@@ -574,14 +579,18 @@ When evaluation of the black-holed closure completes, the black hole
 is overwritten with an indirection to the result of the closure and
 any blocked threads are restored to the runnable queue.
 
+Closures are overwritten by black-holes during a ``lazy black-holing''
+phase which runs on each thread when it returns to the scheduler.
+\ToDo{section describing lazy black-holing}.
+
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
-@BH@ & \emph{Blocked threads} \\ \hline
+@BLACKHOLE@ & \emph{Blocked threads} \\ \hline
 \end{tabular}
 \end{center}
 
 \ToDo{In a single threaded system, it's trivial to detect infinite
-loops: reentering a BH is always an error.  How easy is it in a
+loops: reentering a BLACKHOLE is always an error.  How easy is it in a
 multi-threaded system?}
 
 \item[Indirections] are used to update an unevaluated closure with its
@@ -596,25 +605,26 @@ an update in place.)
 \end{tabular}
 \end{center}
 
-Indirections needn't always point to an evaluated closure.  They can
+Indirections needn't always point to a closure in WHNF.  They can
 point to a chain of indirections which point to an evaluated closure.
-When revertible black holes are added, they may also point to reverted
-black holes.
 
 \item[Thread State Objects (@TSO@s)] represent Haskell threads.  Their
-payload consists of a unique thread id, the status of the thread
-(runnable, blocked, etc) and the stack.  @TSO@s may be resized by the
-scheduler if its stack is too small or too large.
+payload consists of some per-thread information such as the Thread ID
+and the status of the thread (runnable, blocked etc.), and the
+thread's stack.  See @TSO.h@ for the full story.  @TSO@s may be
+resized by the scheduler if its stack is too small or too large.
+
+The thread stack grows downwards from higher to lower addresses.
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
-@TSO@ & \emph{Thread Id} & \emph{Status} & \emph{Stack} \\ \hline
+@TSO@ & \emph{Thread info} & \emph{Stack} \\ \hline
 \end{tabular}
 \end{center}
 
 \end{description}
 
-\subsubsection{Stack Objects}
+\Subsubsection{Stack objects}{stack-objects-overview}
 
 The stack contains a mixture of \emph{pending arguments} and 
 \emph{stack objects}.
@@ -652,12 +662,15 @@ generated by the machine code compiler look like this:
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
-\emph{@RET_ADDR@} & \emph{Free Variables of the case alternatives} \\ \hline
+\emph{@RET_XXX@} & \emph{Free Variables of the case alternatives} \\ \hline
 \end{tabular}
 \end{center}
 
 The free variables are a mixture of pointers and non-pointers whose
-layout is described by the info table.
+layout is described by a bitmask in the info table.
+
+There are several kinds of @RET_XXX@ return address - see
+\secref{activation-records} for the details.
 
 Return addresses generated by the bytecode compiler look like this:
 \begin{center}
@@ -672,32 +685,43 @@ though they were pending arguments.
 
 \item[Update frames] are used to trigger updates.  When an update
 frame is entered, it overwrites the updatee with an indirection to the
-result, restarts any threads blocked on the @BH@ and returns to the
-stack object underneath the update frame.
+result, restarts any threads blocked on the @BLACKHOLE@ and returns to
+the stack object underneath the update frame.
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
-\emph{@UPDATE@} & \emph{Next Update Frame} & \emph{Updatee} \\ \hline
+\emph{@UPDATE_FRAME@} & \emph{Next Update Frame} & \emph{Updatee} \\ \hline
 \end{tabular}
 \end{center}
 
-\item[Seq frames] are used to implement the polymorphic @seq@ primitive.
-They are a special kind of update frame.
-
-\ToDo{Describe them properly}
+\item[Seq frames] are used to implement the polymorphic @seq@
+primitive.  They are a special kind of update frame, and are linked on
+the update frame list.
 
+\begin{center}
+\begin{tabular}{|l|l|l|l|}\hline
+\emph{@SEQ_FRAME@} & \emph{Next Update Frame} \\ \hline
+\end{tabular}
+\end{center}
 
-\end{description}
+\item[Stop frames] are put on the bottom of each thread's stack, and
+act as sentinels for the update frame list (i.e. the last update frame
+points to the stop frame).  Returning to a stop frame terminates the
+thread.  Stop frames have no payload:
 
-\ToDo{We also need a stop frame which goes on the bottom of the stack 
-when the thread terminates.}
+\begin{center}
+\begin{tabular}{|l|l|l|l|}\hline
+\emph{@SEQ_FRAME@} \\ \hline
+\end{tabular}
+\end{center}
 
+\end{description}
 
-\subsubsection{Case expressions}
+\Subsubsection{Case expressions}{case-expr-overview}
 
 In the STG language, all evaluation is triggered by evaluating a case
 expression.  When evaluating a case expression @case e of alts@, the
-evaluator push a return address onto the stack and evaluate the
+evaluators pushes a return address onto the stack and evaluate the
 expression @e@.  When @e@ eventually reduces to a constructor, the
 return address on the stack is entered.  The details of how the
 constructor is passed to the return address and how the appropriate
@@ -709,7 +733,7 @@ evaluating the scrutinee; when a function returns an unboxed value, it
 enters the return address on top of the stack.
 
 
-\subsubsection{Function Applications}
+\Subsubsection{Function applications}{fun-app-overview}
 
 In the STG language, all function calls are tail calls.  The arguments
 are pushed onto the stack and the function closure is entered.  If any
@@ -718,15 +742,16 @@ arguments.  Entering a closure is just a special case of calling a
 function with no arguments.
 
 
-\subsubsection{Let expressions}
+\Subsubsection{Let expressions}{let-expr-overview}
 
 In the STG language, almost all heap allocation is caused by let
 expressions.  Filling in the contents of a set of mutually recursive
-heap objects is simple enough; the only difficulty is that once the heap space has been allocated, the thread must not return to the scheduler until
-after the objects are filled in.
+heap objects is simple enough; the only difficulty is that once the
+heap space has been allocated, the thread must not return to the
+scheduler until after the objects are filled in.
 
 
-\subsubsection{Primitive Operations}
+\Subsubsection{Primitive operations}{primop-overview}
 
 \ToDo{}
 
@@ -737,17 +762,17 @@ Most primops are simple, some aren't.
 
 
 
-\section{Scheduler}\label{sect:scheduler-overview}
+\Section{Scheduler}{scheduler-overview}
 
 The Scheduler is the heart of the run-time system.  A running program
 consists of a single running thread, and a list of runnable and
-blocked threads.  A thread is represented by a \emph{Thread Status Object} (TSO), which contains a few words consist of a stack and a few words of
-status information.  Except for the running thread, all threads have a
-closure on top of their stack; the scheduler restarts a thread by
-entering an evaluator which performs some reduction and returns to the
-scheduler.
+blocked threads.  A thread is represented by a \emph{Thread Status
+Object} (TSO), which contains a few words status information and a
+stack.  Except for the running thread, all threads have a closure on
+top of their stack; the scheduler restarts a thread by entering an
+evaluator which performs some reduction and returns to the scheduler.
 
-\subsection{The scheduler's main loop}
+\Subsection{The scheduler's main loop}{scheduler-main-loop}
 
 The scheduler consists of a loop which chooses a runnable thread and
 invokes one of the evaluators which performs some reduction and
@@ -757,7 +782,7 @@ The scheduler also takes care of system-wide issues such as heap
 overflow or communication with other processors (in the parallel
 system) and thread-specific problems such as stack overflow.
 
-\subsection{Creating a thread}
+\Subsection{Creating a thread}{create-thread}
 
 Threads are created:
 
@@ -783,7 +808,7 @@ By @forkIO@, @takeMVar@ and (maybe) other Concurrent Haskell primitives.
 \end{itemize}
 
 
-\subsection{Restarting a thread}
+\Subsection{Restarting a thread}{thread-restart}
 
 When the scheduler decides to run a thread, it has to decide which
 evaluator to use.  It does this by looking at the type of the closure
@@ -811,57 +836,46 @@ the TSO status whenever we leave the evaluator.  This is required for
 any thread, no matter what state it is in (blocked, stack overflow,
 etc).  It isn't clear whether this would accomplish anything.}
 
-\subsection{Returning from a thread}
+\Subsection{Returning from a thread}{thread-return}
 
 The evaluators return to the scheduler when any of the following
 conditions arise:
 
 \begin{itemize}
-\item A heap check fails, and a garbage collection is required
-\item Compiled code needs to switch to interpreted code, and vice versa.
-\item The evaluator needs to perform a ``safe'' C call.
-\item The thread becomes blocked.
-\item The thread is preempted.
-\item The thread terminates.
-\end{itemize}
-
-Except when the thread terminates, the thread always terminates with a
-closure on the top of the stack.  
-
-\subsection{Returning to the Scheduler}
-\label{sect:switching-worlds}
-
-\ToDo{This ignores the other three ways of returning}
-
-The evaluators return to the scheduler under three circumstances:
-\begin{itemize}
+\item A heap check fails, and a garbage collection is required.
 
-\item
-
-When they enter a closure built by the other evaluator.  That is, when
-the bytecode interpreter enters a closure compiled by GHC or when the
-machine code evaluator enters a BCO.
+\item A stack check fails, and the scheduler must either enlarge the
+current thread's stack, or flag an out of memory condition.
 
-\item
+\item A thread enters a closure built by the other evaluator.  That
+is, when the bytecode interpreter enters a closure compiled by GHC or
+when the machine code evaluator enters a BCO.
 
-When they return to a return continuation built by the other
+\item A thread returns to a return continuation built by the other
 evaluator.  That is, when the machine code evaluator returns to a
 continuation built by Hugs or when the bytecode evaluator returns to a
 continuation built by GHC.
 
-\item
+\item The evaluator needs to perform a ``safe'' C call
+(\secref{c-calls}).
+
+\item The thread becomes blocked.  This happens when a thread requires
+the result of a computation currently being performed by another
+thread, or it reads a synchronisation variable that is currently empty
+(\secref{MVAR}).
 
-When a heap or stack check fails or when the preemption flag is set.
+\item The thread is preempted (the preemption mechanism is described
+in \secref{thread-preemption}).
 
+\item The thread terminates.
 \end{itemize}
 
-In all cases, they return to the scheduler with a closure on top of
-the stack.  The mechanism used to trigger the world switch and the
-choice of closure left on top of the stack varies according to which
-world is being left and what is being returned.
+Except when the thread terminates, the thread always terminates with a
+closure on the top of the stack.  The mechanism used to trigger the
+world switch and the choice of closure left on top of the stack varies
+according to which world is being left and what is being returned.
 
-\subsubsection{Leaving the bytecode evaluator}
-\label{sect:hugs-to-ghc-switch}
+\Subsubsection{Leaving the bytecode evaluator}{hugs-to-ghc-switch}
 
 \paragraph{Entering a machine code closure}
 
@@ -902,8 +916,7 @@ The bytecode evaluator tests for heap/stack overflow and preemption
 when entering a BCO and simply returns with the BCO on top of the
 stack.
 
-\subsubsection{Leaving the machine code evaluator}
-\label{sect:ghc-to-hugs-switch}
+\Subsubsection{Leaving the machine code evaluator}{ghc-to-hugs-switch}
 
 \paragraph{Entering a BCO}
 
@@ -914,7 +927,7 @@ the scheduler.
 
 We avoid the need to test return addresses in the machine code
 evaluator by pushing a special return address on top of a pointer to
-the bytecode return continuation.  Figure~\ref{fig:hugs-return-stack}
+the bytecode return continuation.  \figref{hugs-return-stack1}
 shows the state of the stack just before evaluating the scrutinee.
 
 \begin{figure}[ht]
@@ -930,12 +943,12 @@ shows the state of the stack just before evaluating the scrutinee.
 %\input{hugs_return1.pstex_t}
 \end{center}
 \caption{Stack layout for evaluating a scrutinee}
-\label{fig:hugs-return-stack}
+\label{fig:hugs-return-stack1}
 \end{figure}
 
 This return address rearranges the stack so that the bco pointer is
 above the constructor on the stack (as shown in
-figure~\ref{fig:hugs-boxed-return}) and returns to the scheduler.
+\figref{hugs-boxed-return}) and returns to the scheduler.
 
 \begin{figure}[ht]
 \begin{center}
@@ -958,8 +971,9 @@ figure~\ref{fig:hugs-boxed-return}) and returns to the scheduler.
 We avoid the need to test return addresses in the machine code
 evaluator by pushing a special return address on top of a pointer to
 the bytecode return continuation.  This return address rearranges the
-stack so that the bco pointer is above the tagged unboxed value (as shown in
-figure~\ref{fig:hugs-entering-unboxed-return}) and returns to the scheduler.
+stack so that the bco pointer is above the tagged unboxed value (as
+shown in \figref{hugs-entering-unboxed-return}) and returns to the
+scheduler.
 
 \begin{figure}[ht]
 \begin{center}
@@ -984,7 +998,7 @@ figure~\ref{fig:hugs-entering-unboxed-return}) and returns to the scheduler.
 \ToDo{}
 
 
-\subsection{Preempting a thread}
+\Subsection{Preempting a thread}{thread-preemption}
 
 Strictly speaking, threads cannot be preempted --- the scheduler
 merely sets a preemption request flag which the thread must arrange to
@@ -1003,7 +1017,7 @@ infinite loop which does not allocate any space.  If the flag is set,
 the evaluator returns to the scheduler exactly as if a heap check had
 failed.
 
-\subsection{``Safe'' and ``unsafe'' C calls}
+\Subsection{``Safe'' and ``unsafe'' C calls}{c-calls}
 
 There are two ways of calling C: 
 
@@ -1065,13 +1079,13 @@ have a single thread at the moment.}
 
 
 
-\section{The Storage Manager}\label{sect:sm-overview}
+\Section{The Storage Manager}{sm-overview}
 
 The storage manager is responsible for managing the heap and all
 objects stored in it.  It provides special support for lazy evaluation
 and for foreign function calls.
 
-\subsection{SM support for lazy evaluation}
+\Subsection{SM support for lazy evaluation}{sm-lazy-evaluation}
 
 \begin{itemize}
 \item
@@ -1082,6 +1096,8 @@ Indirections are shorted out.
 
 Update frames pointing to unreachable objects are squeezed out.
 
+\ToDo{Part IV suggests this doesn't happen.}
+
 \item
 
 Adjacent update frames (for different closures) are compressed to a
@@ -1090,7 +1106,7 @@ single update frame pointing to a single black hole.
 \end{itemize}
 
 
-\subsection{SM support for foreign function calls}
+\Subsection{SM support for foreign function calls}{sm-foreign-calls}
 
 \begin{itemize}
 
@@ -1100,12 +1116,12 @@ Stable pointers allow other languages to access Haskell objects.
 
 \item
 
-Foreign Objects are a form of weak pointer which let's Haskell access
-foreign objects.
+Weak pointers and foreign objects provide finalisation support for
+Haskell references to external objects.
 
 \end{itemize}
 
-\subsection{Misc}
+\Subsection{Misc}{sm-misc}
 
 \begin{itemize}
 
@@ -1116,8 +1132,6 @@ manager may shrink the stack.  If it shrinks the stack, it guarantees
 never to leave less than @MIN_SIZE_SHRUNKEN_STACK@ empty words on the
 stack when it does so.
 
-\ToDo{Would it be useful for the storage manager to enlarge the stack?}
-
 \item
 
 For efficiency reasons, very large objects (eg large arrays and TSOs)
@@ -1126,12 +1140,12 @@ are not moved if possible.
 \end{itemize}
 
 
-\section{The Compilers}\label{sect:compilers-overview}
+\Section{The Compilers}{compilers-overview}
 
 Need to describe interface files, format of bytecode files, symbols
 defined by machine code files.
 
-\subsection{Interface Files}
+\Subsection{Interface Files}{interface-files}
 
 Here's an example - but I don't know the grammar - ADR.
 @
@@ -1142,25 +1156,15 @@ _declarations_
 1 main _:_ IOBase.IO PrelBase.();;
 @
 
-\subsection{Bytecode files}
+\Subsection{Bytecode files}{bytecode-files}
 
 (All that matters here is what the loader sees.)
 
-\subsection{Machine code files}
+\Subsection{Machine code files}{asm-files}
 
 (Again, all that matters is what the loader sees.)
 
-
-\subsection{Bytecode files}
-
-(All that matters here is what the loader sees.)
-
-\subsection{Machine code files}
-
-(Again, all that matters is what the loader sees.)
-
-
-\section{The Loader}\label{sect:loader-overview}
+\Section{The Loader}{loader-overview}
 
 In a batch mode system, we can statically link all the modules
 together.  In an interactive system we need a loader which will
@@ -1179,7 +1183,7 @@ An initialisation routine.  (Might also be used for finalisation.)
 \item
 A table of symbols it exports.
 Entries in this table consist of the symbol name and the address of the
-names value.
+name's value.
 \item
 A table of symbols it imports.
 Entries in this table consist of the symbol name and a list of references
@@ -1208,8 +1212,9 @@ info tables be writable.
 Either we patch the SRTs and constructors directly or we somehow use
 indirections through the symbol table.  Patching the SRTs requires
 that we make them writable and prevents us from making effective use
-of virtual memories that use copy-on-write policies.  Using an
-indirection is possible but tricky.
+of virtual memories that use copy-on-write policies (this only makes a
+difference if we want to run several copies of the same program
+simultaneously).  Using an indirection is possible but tricky.
 
 Note: We could avoid patching machine code if all references to
 external references went through the SRT --- then we just have one
@@ -1236,15 +1241,14 @@ described in the previous part.
 
 The major components of the system are:
 \begin{itemize}
-\item The scheduler (section~\ref{sect:storage-manager-internals})
-\item The storage manager (section~\ref{sect:storage-manager-internals})
+\item The scheduler (\secref{scheduler-internals})
+\item The storage manager (\secref{storage-manager-internals})
 \item The evaluators
 \item The loader
 \item The compilers
 \end{itemize}
 
-\section{The Scheduler}
-\label{sect:scheduler-internals}
+\Section{The Scheduler}{scheduler-internals}
 
 \ToDo{Detailed description of scheduler}
 
@@ -1259,20 +1263,20 @@ waiting for timeout and threads waiting for I/O.
 
 \item The \emph{mutables list} is a list of all objects in the old
 generation which might contain pointers into the new generation.  Most
-of the objects on this list are indirections (section~\ref{sect:IND})
-or ``mutable.''  (Section~\ref{sect:mutables}.)
+of the objects on this list are indirections (\secref{IND})
+or ``mutable.''  (\secref{mutables}.)
 
 \item The \emph{Foreign Object list} is a list of all foreign objects
- which have not yet been deallocated. (Section~\ref{sect:FOREIGN}.)
+ which have not yet been deallocated. (\secref{FOREIGN}.)
 
 \item The \emph{Spark pool} is a doubly(?) linked list of Spark objects
-maintained by the parallel system.  (Section~\ref{sect:SPARK}.)
+maintained by the parallel system.  (\secref{SPARK}.)
 
 \item The \emph{Blocked Fetch list} (or
-lists?). (Section~\ref{sect:BLOCKED_FETCH}.)
+lists?). (\secref{BLOCKED_FETCH}.)
 
 \item For each thread, there is a list of all update frames on the
-stack.  (Section~\ref{sect:data-updates}.)
+stack.  (\secref{data-updates}.)
 
 \item The Stable Pointer Table is a table of pointers to objects which
 are known to the outside world and must be retained by the garbage
@@ -1285,8 +1289,7 @@ after the fixed header except ...}
 
 
 
-\section{The Storage Manager}
-\label{sect:storage-manager-internals}
+\Section{The Storage Manager}{storage-manager-internals}
 
 \subsection{Misc Text looking for a home}
 
@@ -1298,7 +1301,8 @@ A \emph{value} may be:
 All \emph{pointed} values are \emph{boxed}.  
 
 
-\subsection{Heap Objects}
+\Subsection{Heap Objects}{heap-objects}
+\label{sec:fixed-header}
 
 \begin{figure}
 \begin{center}
@@ -1309,9 +1313,9 @@ All \emph{pointed} values are \emph{boxed}.
 \label{fig:closure}
 \end{figure}
 
-Every \emph{heap object} is a contiguous block
-of memory, consisting of a fixed-format \emph{header} followed
-by zero or more \emph{data words}.
+Every \emph{heap object} is a contiguous block of memory, consisting
+of a fixed-format \emph{header} followed by zero or more \emph{data
+words}.
 
 The header consists of the following fields:
 \begin{itemize}
@@ -1329,66 +1333,120 @@ though GUM keeps a separate hash table).
 We add a Ticky word to the fixed-header part of closures.  This is
 used to indicate if a closure has been updated but not yet entered. It
 is set when the closure is updated and cleared when subsequently
-entered.
-\footnote{%
-NB: It is \emph{not} an ``entry count'', it is an
-``entries-after-update count.''  The commoning up of @CONST@,
+entered.  \footnote{% NB: It is \emph{not} an ``entry count'', it is
+an ``entries-after-update count.''  The commoning up of @CONST@,
 @CHARLIKE@ and @INTLIKE@ closures is turned off(?) if this is
-required. This has only been done for 2s collection.
-}
+required. This has only been done for 2s collection.  }
 
 \end{itemize}
 \end{itemize}
 
-Most of the RTS is completely insensitive to the number of admin words.
-The total size of the fixed header is @FIXED_HS@.
+Most of the RTS is completely insensitive to the number of admin
+words.  The total size of the fixed header is given by
+@sizeof(StgHeader)@.
 
-\subsection{Info Tables}
+\Subsection{Info Tables}{info-tables}
 
-An \emph{info table} is a contiguous block of memory, \emph{laid out
-backwards}.  That is, the first field in the list that follows
-occupies the highest memory address, and the successive fields occupy
-successive decreasing memory addresses.
+An \emph{info table} is a contiguous block of memory, laid out as follows:
 
 \begin{center}
-\begin{tabular}{|c|}
-   \hline Parallelism Info 
-\\ \hline Profile Info 
-\\ \hline Debug Info 
-\\ \hline Tag / Static reference table
-\\ \hline Storage manager layout info
-\\ \hline Closure type 
+\begin{tabular}{|r|l|}
+   \hline Parallelism Info     & variable
+\\ \hline Profile Info                 & variable
+\\ \hline Debug Info           & variable
+\\ \hline Static reference table  & pointer word (optional)
+\\ \hline Storage manager layout info & pointer word
+\\ \hline Closure flags                & 8 bits
+\\ \hline Closure type                 & 8 bits
+\\ \hline Constructor Tag / SRT length         & 16 bits
 \\ \hline entry code
 \\       \vdots
 \end{tabular}
 \end{center}
+
+On a 64-bit machine the tag, type and flags fields will all be doubled
+in size, so the info table is a multiple of 64 bits.
+
 An info table has the following contents (working backwards in memory
 addresses):
+
 \begin{itemize}
-\item The \emph{entry code} for the closure.
-This code appears literally as the (large) last entry in the
-info table, immediately preceded by the rest of the info table.
-An \emph{info pointer} always points to the first byte of the entry code.
-
-\item A one-word \emph{closure type field}, @INFO_TYPE@, identifies what kind
-of closure the object is.  The various types of closure are described
-in Section~\ref{sect:closures}.
-In some configurations, some useful properties of 
-closures (is it a HNF?  can it be sparked?)
-are represented as high-order bits so they can be tested quickly.
-
-\item A single pointer or word --- the \emph{storage manager info field},
-@INFO_SM@, contains auxiliary information describing the closure's
+
+\item The \emph{entry code} for the closure.  This code appears
+literally as the (large) last entry in the info table, immediately
+preceded by the rest of the info table.  An \emph{info pointer} always
+points to the first byte of the entry code.
+
+\item A 16-bit constructor tag / SRT length.  For a constructor info
+table this field contains the tag of the constructor, in the range
+$0..n-1$ where $n$ is the number of constructors in the datatype.
+Otherwise, it contains the number of entries in this closure's Static
+Reference Table (\secref{srt}).
+
+\item An 8-bit {\em closure type field}, which identifies what kind of
+closure the object is.  The various types of closure are described in
+\secref{closures}.
+
+\item an 8-bit flags field, which holds various flags pertaining to
+the closure type.
+
+\item A single pointer or word --- the {\em storage manager info
+field}, contains auxiliary information describing the closure's
 precise layout, for the benefit of the garbage collector and the code
 that stuffs graph into packets for transmission over the network.
+There are three kinds of layout information:
 
-\item A one-word \emph{Tag/Static Reference Table} field, @INFO_SRT@.
-For data constructors, this field contains the constructor tag, in the
-range $0..n-1$ where $n$ is the number of constructors.  For all other
-objects it contains a pointer to a table which enables the garbage
-collector to identify all accessible code and CAFs.  They are fully
-described in Section~\ref{sect:srt}.
+\begin{itemize}
+\item Standard layout information is for closures which place pointers
+before non-pointers in instances of the closure (this applies to most
+heap-based and static closures, but not activation records).  The
+layout information for standard closures is
+
+       \begin{itemize}
+       \item Number of pointer fields (16 bits).
+       \item Number of non-pointer fields (16 bits).
+       \end{itemize}
+
+\item Activation records don't have pointers before non-pointers,
+since stack-stubbing requires that the record has holes in it.  The
+layout is therefore represented by a bitmap in which each '1' bit
+represents a non-pointer word.  This kind of layout info is used for
+@RET_SMALL@ and @RET_VEC_SMALL@ closures.
+
+\item If an activation record is longer than 32 words, then the layout
+field contains a pointer to a bitmap record, consisting of a length
+field followed by two or more bitmap words.  This layout information
+is used for @RET_BIG@ and @RET_VEC_BIG@ closures.
+
+\item Selector Thunks (\secref{THUNK_SELECTOR}) use the closure
+layout field to hold the selector index, since the layout is always
+known (the closure contains a single pointer field).
+\end{itemize}
 
+\item A one-word {\em Static Reference Table} field.  This field
+points to the static reference table for the closure (\secref{srt}),
+and is only present for the following closure types:
+
+       \begin{itemize}
+       \item @FUN_*@
+       \item @THUNK_*@
+       \item @RET_*@
+       \end{itemize}
+
+\ToDo{Expand the following explanation.}
+
+An SRT is basically a vector of pointers to static closures.  A
+top-level function or thunk will have an SRT (which might be empty),
+which points to all the static closures referenced by that function or
+thunk.  Every non-top-level thunk or function also has an SRT, but
+it'll be a sub-sequence of the top-level SRT, so we just store a
+pointer and a length in the info table - the pointer points into the
+middle of the larger SRT.
+
+At GC time, the garbage collector traverses the transitive closure of
+all the SRTs reachable from the roots, and thereby discovers which
+CAFs are live.
+  
 \item \emph{Profiling info\/}
 
 \ToDo{The profiling info is completely bogus.  I've not deleted it
@@ -1497,8 +1555,7 @@ Something internal to the runtime system.
 
 
 %-----------------------------------------------------------------------------
-\subsection{Kinds of Heap Object}
-\label{sect:closures}
+\Subsection{Kinds of Heap Object}{closures}
 
 Heap objects can be classified in several ways, but one useful one is
 this:
@@ -1514,21 +1571,23 @@ locations, with globally known addresses.
 \emph{Stack closures} are closures allocated within a thread's stack
 (which is itself a heap object).  Unlike other closures, there are
 never any pointers to stack closures.  Stack closures are discussed in
-Section~\ref{sect:stacks}.
+\secref{TSO}.
 
 \end{itemize}
 A second useful classification is this:
 \begin{itemize}
-\item 
-\emph{Executive objects}, such as thunks and data constructors,
-participate directly in a program's execution.  They can be subdivided into
-three kinds of objects according to their type:
-\begin{itemize}
-\item 
-\emph{Pointed objects}, represent values of a \emph{pointed} type
-(<.pointed types launchbury.>) --i.e.~a type that includes $\bottom$ such as @Int@ or @Int# -> Int#@.
 
-\item \emph{Unpointed objects}, represent values of a \emph{unpointed} type --i.e.~a type that does not include $\bottom$ such as @Int#@ or @Array#@.
+\item \emph{Executive objects}, such as thunks and data constructors,
+participate directly in a program's execution.  They can be subdivided
+into three kinds of objects according to their type: \begin{itemize}
+
+\item \emph{Pointed objects}, represent values of a \emph{pointed}
+type (<.pointed types launchbury.>) --i.e.~a type that includes
+$\bottom$ such as @Int@ or @Int# -> Int#@.
+
+\item \emph{Unpointed objects}, represent values of a \emph{unpointed}
+type --i.e.~a type that does not include $\bottom$ such as @Int#@ or
+@Array#@.
 
 \item \emph{Activation frames}, represent ``continuations''.  They are
 always stored on the stack and are never pointed to by heap objects or
@@ -1541,63 +1600,69 @@ once we support speculative evaluation.}
 state objects, do not represent values in the original program.
 \end{itemize}
 
-Only pointed objects can be entered.  All pointed objects share a
-common header format: the ``pointed header''; while all unpointed
-objects share a common header format: the ``unpointed header''.
-\ToDo{Describe the difference and update the diagrams to mention
-an appropriate header type.}
+Only pointed objects can be entered.  If an unpointed object is
+entered the program will usually terminate with a fatal error.
 
 This section enumerates all the kinds of heap objects in the system.
-Each is identified by a distinct @INFO_TYPE@ tag in its info table.
+Each is identified by a distinct closure type field in its info table.
 
 \begin{tabular}{|l|l|l|l|l|l|l|l|l|l|l|}
 \hline
 
-closure kind          & Section \\
+closure type          & Section \\
                      
 \hline                          
 \emph{Pointed} \\      
 \hline                       
                      
-@CONSTR@              & \ref{sect:CONSTR}    \\
-@CONSTR_STATIC@       & \ref{sect:CONSTR}    \\
-@CONSTR_STATIC_NOCAF@ & \ref{sect:CONSTR}    \\
+@CONSTR@              & \ref{sec:CONSTR}    \\
+@CONSTR_p_n@         & \ref{sec:CONSTR}    \\
+@CONSTR_STATIC@       & \ref{sec:CONSTR}    \\
+@CONSTR_NOCAF_STATIC@ & \ref{sec:CONSTR}    \\
                      
-@FUN@                 & \ref{sect:FUN}       \\
-@FUN_STATIC@          & \ref{sect:FUN}       \\
+@FUN@                 & \ref{sec:FUN}       \\
+@FUN_p_n@             & \ref{sec:FUN}       \\
+@FUN_STATIC@          & \ref{sec:FUN}       \\
                      
-@THUNK@               & \ref{sect:THUNK}     \\
-@THUNK_STATIC@        & \ref{sect:THUNK}     \\
-@THUNK_SELECTOR@      & \ref{sect:THUNK_SEL} \\
+@THUNK@               & \ref{sec:THUNK}     \\
+@THUNK_p_n@           & \ref{sec:THUNK}     \\
+@THUNK_STATIC@        & \ref{sec:THUNK}     \\
+@THUNK_SELECTOR@      & \ref{sec:THUNK_SELECTOR} \\
                      
-@BCO@                & \ref{sect:BCO}       \\
-@BCO_CAF@            & \ref{sect:BCO}       \\
+@BCO@                & \ref{sec:BCO}       \\
                      
-@AP@                 & \ref{sect:AP}            \\
-@PAP@                 & \ref{sect:PAP}       \\
+@AP_UPD@             & \ref{sec:AP_UPD}    \\
+@PAP@                 & \ref{sec:PAP}       \\
                      
-@IND@                 & \ref{sect:IND}       \\
-@IND_OLDGEN@          & \ref{sect:IND}       \\
-@IND_PERM@            & \ref{sect:IND}       \\
-@IND_OLDGEN_PERM@     & \ref{sect:IND}       \\
-@IND_STATIC@          & \ref{sect:IND}       \\
+@IND@                 & \ref{sec:IND}       \\
+@IND_OLDGEN@          & \ref{sec:IND}       \\
+@IND_PERM@            & \ref{sec:IND}       \\
+@IND_OLDGEN_PERM@     & \ref{sec:IND}       \\
+@IND_STATIC@          & \ref{sec:IND}       \\
                      
+@CAF_UNENTERED@              & \ref{sec:CAF}       \\
+@CAF_ENTERED@        & \ref{sec:CAF}       \\
+@CAF_BLACKHOLE@              & \ref{sec:CAF}       \\
+
 \hline               
 \emph{Unpointed} \\    
 \hline               
                                      
-@ARR_WORDS@           & \ref{sect:ARR_WORDS1},\ref{sect:ARR_WORDS2} \\
-@ARR_PTRS@            & \ref{sect:ARR_PTRS}  \\
-@MUTVAR@              & \ref{sect:MUTVAR}    \\
-@MUTARR_PTRS@         & \ref{sect:MUTARR_PTRS} \\
-@MUTARR_PTRS_FROZEN@  & \ref{sect:MUTARR_PTRS_FROZEN} \\
-                     
-@FOREIGN@             & \ref{sect:FOREIGN}   \\
-                     
-@BH@                  & \ref{sect:BH}        \\
-@MVAR@                       & \ref{sect:MVAR}      \\
-@IVAR@                       & \ref{sect:IVAR}      \\
-@FETCHME@             & \ref{sect:FETCHME}   \\
+@BLACKHOLE@           & \ref{sec:BLACKHOLE} \\
+@BLACKHOLE_BQ@        & \ref{sec:BLACKHOLE_BQ} \\
+
+@MVAR@                       & \ref{sec:MVAR}      \\
+
+@ARR_WORDS@           & \ref{sec:ARR_WORDS} \\
+
+@MUTARR_PTRS@         & \ref{sec:MUT_ARR_PTRS} \\
+@MUTARR_PTRS_FROZEN@  & \ref{sec:MUT_ARR_PTRS_FROZEN} \\
+
+@MUT_VAR@              & \ref{sec:MUT_VAR}    \\
+
+@WEAK@               & \ref{sec:WEAK}   \\
+@FOREIGN@             & \ref{sec:FOREIGN}   \\
+@STABLE_NAME@        & \ref{sec:STABLE_NAME}   \\
 \hline
 \end{tabular}
 
@@ -1605,42 +1670,36 @@ Activation frames do not live (directly) on the heap --- but they have
 a similar organisation.
 
 \begin{tabular}{|l|l|}\hline
-closure kind           & Section                       \\ \hline
-@RET_SMALL@            & \ref{sect:activation-records} \\
-@RET_VEC_SMALL@        & \ref{sect:activation-records} \\
-@RET_BIG@              & \ref{sect:activation-records} \\
-@RET_VEC_BIG@          & \ref{sect:activation-records} \\
-@UPDATE_FRAME@                 & \ref{sect:activation-records} \\
+closure type           & Section                       \\ \hline
+@RET_SMALL@            & \ref{sec:activation-records}  \\
+@RET_VEC_SMALL@        & \ref{sec:activation-records}  \\
+@RET_BIG@              & \ref{sec:activation-records}  \\
+@RET_VEC_BIG@          & \ref{sec:activation-records}  \\
+@UPDATE_FRAME@                 & \ref{sec:activation-records}  \\
+@CATCH_FRAME@          & \ref{sec:activation-records}  \\
+@SEQ_FRAME@            & \ref{sec:activation-records}  \\
+@STOP_FRAME@           & \ref{sec:activation-records}  \\
 \hline
 \end{tabular}
 
-There are also a number of administrative objects.
+There are also a number of administrative objects.  It is an error to
+enter one of these objects.
 
 \begin{tabular}{|l|l|}\hline
-closure kind           & Section                       \\ \hline
-@TSO@                   & \ref{sect:TSO}               \\
-@STACK_OBJECT@          & \ref{sect:STACK_OBJECT}      \\
-@STABLEPTR_TABLE@       & \ref{sect:STABLEPTR_TABLE}   \\
-@SPARK_OBJECT@          & \ref{sect:SPARK}             \\
-@BLOCKED_FETCH@        & \ref{sect:BLOCKED_FETCH}      \\
+closure type           & Section                       \\ \hline
+@TSO@                   & \ref{sec:TSO}                \\
+@SPARK_OBJECT@          & \ref{sec:SPARK}              \\
+@BLOCKED_FETCH@        & \ref{sec:BLOCKED_FETCH}       \\
+@FETCHME@               & \ref{sec:FETCHME}   \\
 \hline
 \end{tabular}
 
-\ToDo{I guess the parallel system has something like a stable ptr
-table.  Is there any opportunity for sharing code/data structures
-here?}
-
-
-\subsection{Predicates}
-
-\ToDo{The following is a first attempt at defining a useful set of
-predicates.  Some (such as @isWHNF@ and @isSparkable@) may need their
-definitions tweaked a little.}
+\Subsection{Predicates}{closure-predicates}
 
 The runtime system sometimes needs to be able to distinguish objects
 according to their properties: is the object updateable? is it in weak
 head normal form? etc.  These questions can be answered by examining
-the @INFO_TYPE@ field of the object's info table.  
+the closure type field of the object's info table.  
 
 We define the following predicates to detect families of related
 info types.  They are mutually exclusive and exhaustive.
@@ -1687,7 +1746,7 @@ Note that unpointed objects are (arbitrarily) not considered to be in WHNF.
 @isWHNF@ is true for @PAP@s, @CONSTR@s, @FUN@s and all @BCO@s.
 
 \ToDo{Need to distinguish between whnf BCOs and non-whnf BCOs in their
-@INFO_TYPE@}
+closure type}
 
 \item @isUPDATEABLE@ is true if the object may be overwritten with an
  indirection object.
@@ -1716,6 +1775,11 @@ It is true for return addresses and update frames.
 \item @isADMINISTRATIVE@ is true for administrative objects:
 @TSO@s, the stable pointer table, spark objects and blocked fetches.
 
+\item @hasSRT@ is true if the info table for the object contains an
+SRT pointer.  
+
+@hasSRT@ is true for @THUNK@s, @FUN@s, and @RET@s.
+
 \end{itemize}
 
 \begin{itemize}
@@ -1735,76 +1799,15 @@ As a minor optimisation, we might use the top bits of the @INFO_TYPE@
 field to ``cache'' the answers to some of these predicates.
 
 An indirection either points to HNF (post update); or is result of
-overwriting a FetchMe, in which case the thing fetched is either
-under evaluation (BH), or by now an HNF.  Thus, indirections get NoSpark flag.
-
-
-\iffalse
-@
-#define _NF                    0x0001  /* Normal form  */
-#define _NS                    0x0002  /* Don't spark  */
-#define _ST                    0x0004  /* Is static    */
-#define _MU                    0x0008  /* Is mutable   */
-#define _UP                    0x0010  /* Is updatable (but not mutable) */
-#define _BM                    0x0020  /* Is a "rimitive" array */
-#define _BH                    0x0040  /* Is a black hole */
-#define _IN                    0x0080  /* Is an indirection */
-#define _TH                    0x0100  /* Is a thunk */
-
-
-
-SPEC   
-SPEC_N         SPEC | _NF | _NS
-SPEC_S         SPEC | _TH
-SPEC_U         SPEC | _UP | _TH
-               
-GEN    
-GEN_N          GEN | _NF | _NS
-GEN_S          GEN | _TH
-GEN_U          GEN | _UP | _TH
-               
-DYN            _NF | _NS
-TUPLE          _NF | _NS | _BM
-DATA           _NF | _NS | _BM
-MUTUPLE                _NF | _NS | _MU | _BM
-IMMUTUPLE      _NF | _NS | _BM
-STATIC         _NS | _ST
-CONST          _NF | _NS
-CHARLIKE       _NF | _NS
-INTLIKE                _NF | _NS
-
-BH             _NS | _BH
-BH_N           BH
-BH_U           BH | _UP
-               
-BQ             _NS | _MU | _BH
-IND            _NS | _IN
-CAF            _NF | _NS | _ST | _IN
-
-FM             
-FETCHME                FM | _MU
-FMBQ           FM | _MU | _BH
-
-TSO            _MU
-
-STKO   
-STKO_DYNAMIC   STKO | _MU
-STKO_STATIC    STKO | _ST
-               
-SPEC_RBH       _NS | _MU | _BH
-GEN_RBH                _NS | _MU | _BH
-BF             _NS | _MU | _BH
-INTERNAL       
-
-@
-\fi
-
+overwriting a FetchMe, in which case the thing fetched is either under
+evaluation (BLACKHOLE), or by now an HNF.  Thus, indirections get
+NoSpark flag.
 
 \subsection{Closures (aka Pointed Objects)}
 
 An object can be entered iff it is a closure.
 
-\subsubsection{Function closures}\label{sect:FUN}
+\Subsubsection{Function closures}{FUN}
 
 Function closures represent lambda abstractions.  For example,
 consider the top-level declaration:
@@ -1821,87 +1824,101 @@ The layout of a function closure is as follows:
 \emph{Fixed header}  & \emph{Pointers} & \emph{Non-pointers} \\ \hline
 \end{tabular}
 \end{center}
+
 The data words (pointers and non-pointers) are the free variables of
-the function closure.  
-The number of pointers
-and number of non-pointers are stored in the @INFO_SM@ word, in the least significant
-and most significant half-word respectively.
+the function closure.  The number of pointers and number of
+non-pointers are stored in @info->layout.ptrs@ and
+@info->layout.nptrs@ respecively.
 
 There are several different sorts of function closure, distinguished
-by their @INFO_TYPE@ field:
+by their closure type field:
+
 \begin{itemize}
-\item @FUN@: a vanilla, dynamically allocated on the heap. 
+
+\item @FUN@: a vanilla, dynamically allocated on the heap.
 
 \item $@FUN_@p@_@np$: to speed up garbage collection a number of
-specialised forms of @FUN@ are provided, for particular $(p,np)$ pairs,
-where $p$ is the number of pointers and $np$ the number of non-pointers.
+specialised forms of @FUN@ are provided, for particular $(p,np)$
+pairs, where $p$ is the number of pointers and $np$ the number of
+non-pointers.
+
+\item @FUN_STATIC@.  Top-level, static, function closures (such as @f@
+above) have a different layout than dynamic ones:
 
-\item @FUN_STATIC@.  Top-level, static, function closures (such as
-@f@ above) have a different
-layout than dynamic ones:
 \begin{center}
 \begin{tabular}{|l|l|l|}\hline
 \emph{Fixed header}  & \emph{Static object link} \\ \hline
 \end{tabular}
 \end{center}
-Static function closures have no free variables.  (However they may refer to other 
-static closures; these references are recorded in the function closure's SRT.)
-They have one field that is not present in dynamic closures, the \emph{static object
-link} field.  This is used by the garbage collector in the same way that to-space
-is, to gather closures that have been determined to be live but that have not yet
+
+Static function closures have no free variables.  (However they may
+refer to other static closures; these references are recorded in the
+function closure's SRT.)  They have one field that is not present in
+dynamic closures, the \emph{static object link} field.  This is used
+by the garbage collector in the same way that to-space is, to gather
+closures that have been determined to be live but that have not yet
 been scavenged.
-\note{Static function closures that have no static references, and hence
-a null SRT pointer, don't need the static object link field.  Is it worth
-taking advantage of this?  See @CONSTR_STATIC_NOCAF@.}
+
+\note{Static function closures that have no static references, and
+hence a null SRT pointer, don't need the static object link field.  We
+don't take advantage of this at the moment, but we could.  See
+@CONSTR_NOCAF_STATIC@.}  
 \end{itemize}
 
-Each lambda abstraction, $f$, in the STG program has its own private info table.
-The following labels are relevant:
+Each lambda abstraction, $f$, in the STG program has its own private
+info table.  The following labels are relevant:
+
 \begin{itemize}
+
 \item $f$@_info@  is $f$'s info table.
-\item $f$@_entry@ is $f$'s slow entry point (i.e. the entry code of its
-info table; so it will label the same byte as $f$@_info@).
-\item $f@_fast_@k$ is $f$'s fast entry point.  $k$ is the number of arguments
-$f$ takes; encoding this number in the fast-entry label occasionally catches some nasty
-code-generation errors.
+
+\item $f$@_entry@ is $f$'s slow entry point (i.e. the entry code of
+its info table; so it will label the same byte as $f$@_info@).
+
+\item $f@_fast_@k$ is $f$'s fast entry point.  $k$ is the number of
+arguments $f$ takes; encoding this number in the fast-entry label
+occasionally catches some nasty code-generation errors.
+
 \end{itemize}
 
-\subsubsection{Data Constructors}\label{sect:CONSTR}
+\Subsubsection{Data constructors}{CONSTR}
+
+Data-constructor closures represent values constructed with algebraic
+data type constructors.  The general layout of data constructors is
+the same as that for function closures.  That is
 
-Data-constructor closures represent values constructed with
-algebraic data type constructors.
-The general layout of data constructors is the same as that for function
-closures.  That is
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
 \emph{Fixed header}  & \emph{Pointers} & \emph{Non-pointers} \\ \hline
 \end{tabular}
 \end{center}
 
-The SRT pointer in a data constructor's info table is used for the
-constructor tag, since a constructor never has any static references.
-
 There are several different sorts of constructor:
+
 \begin{itemize}
+
 \item @CONSTR@: a vanilla, dynamically allocated constructor.
+
 \item @CONSTR_@$p$@_@$np$: just like $@FUN_@p@_@np$.
-\item @CONSTR_INTLIKE@.
-A dynamically-allocated heap object that looks just like an @Int@.  The 
-garbage collector checks to see if it can common it up with one of a fixed
-set of static int-like closures, thus getting it out of the dynamic heap
-altogether.
+
+\item @CONSTR_INTLIKE@.  A dynamically-allocated heap object that
+looks just like an @Int@.  The garbage collector checks to see if it
+can common it up with one of a fixed set of static int-like closures,
+thus getting it out of the dynamic heap altogether.
 
 \item @CONSTR_CHARLIKE@:  same deal, but for @Char@.
 
-\item @CONSTR_STATIC@ is similar to @FUN_STATIC@, with the complication that
-the layout of the constructor must mimic that of a dynamic constructor,
-because a static constructor might be returned to some code that unpacks it.
-So its layout is like this:
+\item @CONSTR_STATIC@ is similar to @FUN_STATIC@, with the
+complication that the layout of the constructor must mimic that of a
+dynamic constructor, because a static constructor might be returned to
+some code that unpacks it.  So its layout is like this:
+
 \begin{center}
 \begin{tabular}{|l|l|l|l|l|}\hline
 \emph{Fixed header}  & \emph{Pointers} & \emph{Non-pointers} & \emph{Static object link}\\ \hline
 \end{tabular}
 \end{center}
+
 The static object link, at the end of the closure, serves the same purpose
 as that for @FUN_STATIC@.  The pointers in the static constructor can point
 only to other static closures.
@@ -1910,29 +1927,37 @@ The static object link occurs last in the closure so that static
 constructors can store their data fields in exactly the same place as
 dynamic constructors.
 
-\item @CONSTR_STATIC_NOCAF@.  A statically allocated data constructor
+\item @CONSTR_NOCAF_STATIC@.  A statically allocated data constructor
 that guarantees not to point (directly or indirectly) to any CAF
-(section~\ref{sect:CAF}).  This means it does not need a static object
+(\secref{CAF}).  This means it does not need a static object
 link field.  Since we expect that there might be quite a lot of static
 constructors this optimisation makes sense.  Furthermore, the @NOCAF@
 tag allows the compiler to indicate that no CAFs can be reached
 anywhere \emph{even indirectly}.
 
-
 \end{itemize}
 
-For each data constructor $Con$, two
-info tables are generated:
+For each data constructor $Con$, two info tables are generated:
+
 \begin{itemize}
-\item $Con$@_info@ labels $Con$'s dynamic info table, 
+\item $Con$@_con_info@ labels $Con$'s dynamic info table, 
 shared by all dynamic instances of the constructor.
 \item $Con$@_static@ labels $Con$'s static info table, 
 shared by all static instances of the constructor.
 \end{itemize}
 
+Each constructor also has a \emph{constructor function}, which is a
+curried function which builds an instance of the constructor.  The
+constructor function has an info table labelled as @$Con$_info@, and
+entry code pointed to by @$Con$_entry@.
+
+Nullary constructors are represented by a single static info table,
+which everyone points to.  Thus for a nullary constructor we can omit
+the dynamic info table and the constructor function.
+
 \subsubsection{Thunks}
-\label{sect:THUNK}
-\label{sect:THUNK_SEL}
+\label{sec:THUNK}
+\label{sec:THUNK_SELECTOR}
 
 A thunk represents an expression that is not obviously in head normal 
 form.  For example, consider the following top-level definitions:
@@ -1945,70 +1970,84 @@ Here the right-hand sides of @range@ and @ys@ are both thunks; the former
 is static while the latter is dynamic.
 
 The layout of a thunk is the same as that for a function closure.
-However, thunks must have a payload of at least @MIN_UPD_PAYLOAD@ words
-to allow it to be overwritten with a black hole and an indirection.
-The compiler may have to add extra non-pointer fields to satisfy this constraint.
+However, thunks must have a payload of at least @MIN_UPD_SIZE@
+words to allow it to be overwritten with a black hole and an
+indirection.  The compiler may have to add extra non-pointer fields to
+satisfy this constraint.
+
 \begin{center}
 \begin{tabular}{|l|l|l|l|l|}\hline
 \emph{Fixed header}  & \emph{Pointers} & \emph{Non-pointers} \\ \hline
 \end{tabular}
 \end{center}
-The @INFO_SM@ word contains the same information as for function
-closures; that is, number of pointers and number of non-pointers.
+
+The layout word in the info table contains the same information as for
+function closures; that is, number of pointers and number of
+non-pointers.
 
 A thunk differs from a function closure in that it can be updated.
 
 There are several forms of thunk:
+
 \begin{itemize}
-\item @THUNK@ and $@THUNK_@p@_@np$: vanilla, dynamically allocated thunks.
-Dynamic thunks are overwritten with normal indirections.
 
-\item @THUNK_STATIC@.  A static thunk is also known as 
-a \emph{constant applicative form}, or \emph{CAF}.
-Static thunks are overwritten with static indirections.
+\item @THUNK@ and $@THUNK_@p@_@np$: vanilla, dynamically allocated
+thunks.  Dynamic thunks are overwritten with normal indirections
+(@IND@), or old generation indirections (@IND_OLDGEN@): see
+\secref{IND}.
+
+\item @THUNK_STATIC@.  A static thunk is also known as a
+\emph{constant applicative form}, or \emph{CAF}.  Static thunks are
+overwritten with static indirections.
 
 \begin{center}
-\begin{tabular}{|l|l|l|l|l|}\hline
-\emph{Fixed header}  & \emph{Pointers} & \emph{Non-pointers} \emph{Static object link}\\ \hline
+\begin{tabular}{|l|l|}\hline
+\emph{Fixed header}  & \emph{Static object link}\\ \hline
 \end{tabular}
 \end{center}
 
-\item @THUNK_SELECTOR@ is a (dynamically allocated) thunk
-whose entry code performs a simple selection operation from
-a data constructor drawn from a single-constructor type.  For example,
-the thunk
+\item @THUNK_SELECTOR@ is a (dynamically allocated) thunk whose entry
+code performs a simple selection operation from a data constructor
+drawn from a single-constructor type.  For example, the thunk
 @
        x = case y of (a,b) -> a
 @
 is a selector thunk.  A selector thunk is laid out like this:
+
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
 \emph{Fixed header}  & \emph{Selectee pointer} \\ \hline
 \end{tabular}
 \end{center}
-The @INFO_SM@ word contains the byte offset of the desired word in
-the selectee.  Note that this is different from all other thunks.
-
-The garbage collector ``peeks'' at the selectee's
-tag (in its info table).  If it is evaluated, then it goes ahead and do
-the selection, and then behaves just as if the selector thunk was an
-indirection to the selected field.
-If it is not
-evaluated, it treats the selector thunk like any other thunk of that
-shape.  [Implementation notes.  
-Copying: only the evacuate routine needs to be special.
-Compacting: only the PRStart (marking) routine needs to be special.]
-\end{itemize}
 
+The layout word contains the byte offset of the desired word in the
+selectee.  Note that this is different from all other thunks.
+
+The garbage collector ``peeks'' at the selectee's tag (in its info
+table).  If it is evaluated, then it goes ahead and does the
+selection, and then behaves just as if the selector thunk was an
+indirection to the selected field.  If it is not evaluated, it treats
+the selector thunk like any other thunk of that shape.
+[Implementation notes.  Copying: only the evacuate routine needs to be
+special.  Compacting: only the PRStart (marking) routine needs to be
+special.]
+
+There is a fixed set of pre-compiled selector thunks built into the
+RTS, representing offsets from 0 to @MAX_SPEC_SELECTOR_THUNK@.  The
+info tables are labelled @__sel_$n$_upd_info@ where $n$ is the offset.
+Non-updating versions are also built in, with info tables labelled
+@__sel_$n$_noupd_info@.
+
+\end{itemize}
 
 The only label associated with a thunk is its info table:
+
 \begin{description}
 \item[$f$@_info@] is $f$'s info table.
 \end{description}
 
 
-\subsubsection{Byte-Code Objects}
-\label{sect:BCO}
+\Subsubsection{Byte-code objects}{BCO}
 
 A Byte-Code Object (BCO) is a container for a a chunk of byte-code,
 which can be executed by Hugs.  The byte-code represents a
@@ -2016,11 +2055,11 @@ supercombinator in the program: when Hugs compiles a module, it
 performs lambda lifting and each resulting supercombinator becomes a
 byte-code object in the heap.
 
-BCOs are not updateable; the bytecode compiler represents updatable thunks
-using a combination of @AP@s and @BCO@s.
+BCOs are not updateable; the bytecode compiler represents updatable
+thunks using a combination of @AP@s and @BCO@s.
 
-The semantics of BCOs are described in Section
-\ref{sect:hugs-heap-objects}.  A BCO has the following structure:
+The semantics of BCOs are described in \secref{hugs-heap-objects}.  A
+BCO has the following structure:
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|l|l|}
@@ -2033,9 +2072,8 @@ The semantics of BCOs are described in Section
 
 \noindent where:
 \begin{itemize}
-\item The entry code is a static code fragment/info table that
-returns to the scheduler to invoke Hugs (Section
-\ref{sect:ghc-to-hugs-switch}).
+\item The entry code is a static code fragment/info table that returns
+to the scheduler to invoke Hugs (\secref{ghc-to-hugs-switch}).
 \item \emph{Layout} contains the number of pointer literals in the
 \emph{Literals} field.
 \item \emph{Offset} is the offset to the byte code from the start of
@@ -2048,44 +2086,61 @@ code.
 \end{itemize}
 
 
-\subsubsection{Partial applications (PAPs)}\label{sect:PAP}
+\Subsubsection{Partial applications}{PAP}
 
-\ToDo{PAPs don't contains update frames or activation frames.  When we
-add revertible black holes, we'll introduce a new kind of object which
-can contain activation frames.}
+A partial application (PAP) represents a function applied to too few
+arguments.  It is only built as a result of updating after an
+argument-satisfaction check failure.  A PAP has the following shape:
 
-A partial application (PAP) represents a function applied to too few arguments.
-It is only built as a result of updating after an argument-satisfaction
-check failure.  A PAP has the following shape:
 \begin{center}
 \begin{tabular}{|l|l|l|l|}\hline
-\emph{Fixed header}  & \emph{No of arg words} & \emph{Function closure} & \emph{Arg stack} \\ \hline
+\emph{Fixed header}  & \emph{No of words of stack} & \emph{Function closure} & \emph{Stack chunk ...} \\ \hline
 \end{tabular}
 \end{center}
-The ``arg stack'' is a copy of the chunk of stack above the update
-frame; ``no of arg words'' tells how many words it consists of.  The
-function closure is (a pointer to) the closure for the function whose
-argument-satisfaction check failed.
 
-There is just one standard form of PAP with @INFO_TYPE@ = @PAP@.
-There is just one info table too, called @PAP_info@.
-Its entry code simply copies the arg stack chunk back on top of the
-stack and enters the function closure.  (It has to do a stack overflow test first.)
+The ``Stack chunk'' is a copy of the chunk of stack above the update
+frame; ``No of words of stack'' tells how many words it consists of.
+The function closure is (a pointer to) the closure for the function
+whose argument-satisfaction check failed.
+
+In the normal case where a PAP is built as a result of an argument
+satisfaction check failure, the stack chunk will just contain
+``pending arguments'', ie. pointers and tagged non-pointers.  It may
+in fact also contain activation records, but not update frames, seq
+frames, or catch frames.  The reason is the garbage collector uses the
+same code to scavenge a stack as it does to scavenge the payload of a
+PAP, but an update frame contains a link to the next update frame in
+the chain and this link would need to be relocated during garbage
+collection.  Revertible black holes and asynchronous exceptions use
+the more general form of PAPs (see Section \ref{revertible-bh}).
+
+There is just one standard form of PAP. There is just one info table
+too, called @PAP_info@.  Its entry code simply copies the arg stack
+chunk back on top of the stack and enters the function closure.  (It
+has to do a stack overflow test first.)
+
+There is just one way to build a PAP: by calling @stg_update_PAP@ with
+the function closure in register @R1@ and the pending arguments on the
+stack.  The @stg_update_PAP@ function will build the PAP, perform the
+update, and return to the next activation record on the stack.  If
+there are \emph{no} pending arguments on the stack, then no PAP need
+be built: in this case @stg_update_PAP@ just overwrites the updatee
+with an indirection to the function closure.
 
 PAPs are also used to implement Hugs functions (where the arguments
 are free variables).  PAPs generated by Hugs can be static so we need
 both @PAP@ and @PAP_STATIC@.
 
-\subsubsection{@AP@ objects}
-\label{sect:AP}
+\Subsubsection{@AP_UPD@ objects}{AP_UPD}
 
-@AP@ objects are used to represent thunks built by Hugs.  The only distintion between
-an @AP@ and a @PAP@ is that an @AP@ is updateable.
+@AP_UPD@ objects are used to represent thunks built by Hugs.  The only
+distintion between an @AP_UPD@ and a @PAP@ is that an @AP_UPD@ is
+updateable.
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|}
 \hline
-\emph{Fixed Header} & \emph{No of arg words} & \emph{Function closure} & \emph{Arg stack} \\
+\emph{Fixed Header} & \emph{No of stack words} & \emph{Function closure} & \emph{Stack chunk} \\
 \hline
 \end{tabular}
 \end{center}
@@ -2094,38 +2149,51 @@ The entry code pushes an update frame, copies the arg stack chunk on
 top of the stack, and enters the function closure.  (It has to do a
 stack overflow test first.)
 
-The ``arg stack'' is a block of (tagged) arguments representing the
-free variables of the thunk; ``no of arg words'' tells how many words
-it consists of.  The function closure is (a pointer to) the closure
-for the thunk.  The argument stack may be empty if the thunk has no
-free variables.
+The ``stack chunk'' is a block of stack not containing update frames,
+seq frames or catch frames (just like a PAP).  In the case of Hugs,
+the stack chunk will contain the free variables of the thunk, and the
+function closure is (a pointer to) the closure for the thunk.  The
+argument stack may be empty if the thunk has no free variables.
 
-\note{Since @AP@s are updateable, the @MIN_UPD_PAYLOAD@ constraint
+\note{Since @AP_UPD@s are updateable, the @MIN_UPD_SIZE@ constraint
 applies here too.}
 
-\subsubsection{Indirections}
-\label{sect:IND}
+\Subsubsection{Indirections}{IND}
 
 Indirection closures just point to other closures. They are introduced
-when a thunk is updated to point to its value. 
-The entry code for all indirections simply enters the closure it points to.
+when a thunk is updated to point to its value.  The entry code for all
+indirections simply enters the closure it points to.
 
 There are several forms of indirection:
+
 \begin{description}
 \item[@IND@] is the vanilla, dynamically-allocated indirection.
 It is removed by the garbage collector. It has the following
 shape:
 \begin{center}
 \begin{tabular}{|l|l|l|}\hline
-\emph{Fixed header} & \emph{Mutable link field} & \emph{Target closure} \\ \hline
+\emph{Fixed header} & \emph{Target closure} \\ \hline
 \end{tabular}
 \end{center}
-It contains a \emph{mutable link field} that is used to string together
-indirections in each generation.
 
+An @IND@ only exists in the youngest generation.  In older
+generations, we have @IND_OLDGEN@s.  The update code
+(@Upd_frame_$n$_entry@) checks whether the updatee is in the youngest
+generation before deciding which kind of indirection to use.
 
-\item[@IND_PERMANENT@]
-for lexical profiling, it is necessary to maintain cost centre
+\item[@IND_OLDGEN@] is the vanilla, dynamically-allocated indirection.
+It is removed by the garbage collector. It has the following
+shape:
+\begin{center}
+\begin{tabular}{|l|l|l|}\hline
+\emph{Fixed header} & \emph{Target closure} & \emph{Mutable link field} \\ \hline
+\end{tabular}
+\end{center}
+It contains a \emph{mutable link field} that is used to string together
+mutable objects in each old generation.
+
+\item[@IND_PERM@]
+For lexical profiling, it is necessary to maintain cost centre
 information in an indirection, so ``permanent indirections'' are
 retained forever.  Otherwise they are just like vanilla indirections.
 \note{If a permanent indirection points to another permanent
@@ -2135,6 +2203,9 @@ since it will have no effect on the profiler.}
 \note{Do we still need @IND@ in the profiling build, or do we just
 need @IND@ but its behaviour changes when profiling is on?}
 
+\item[@IND_OLDGEN_PERM@]
+Just like an @IND_OLDGEN@, but sticks around like an @IND_PERM@.
+
 \item[@IND_STATIC@] is used for overwriting CAFs when they have been
 evaluated.  Static indirections are not removed by the garbage
 collector; and are statically allocated outside the heap (and should
@@ -2144,47 +2215,81 @@ stay there).  Their static object link field is used just as for
 \begin{center}
 \begin{tabular}{|l|l|l|}
 \hline
-\emph{Fixed header} & \emph{Target closure} & \emph{Static object link} \\
+\emph{Fixed header} & \emph{Target closure} & \emph{Static link field} \\
 \hline
 \end{tabular}
 \end{center}
 
 \end{description}
 
-\subsubsection{Black holes and Blocking Queues}
-\label{sect:BH}
+\subsubsection{Black holes and blocking queues}
+\label{sec:BLACKHOLE}
+\label{sec:BLACKHOLE_BQ}
 
 Black hole closures are used to overwrite closures currently being
 evaluated. They inform the garbage collector that there are no live
 roots in the closure, thus removing a potential space leak.  
 
-Black holes also become synchronization points in the threaded world.
-They contain a pointer to a list of blocked threads to be awakened
-when the black hole is updated (or @NULL@ if the list is empty).
+Black holes also become synchronization points in the concurrent
+world.  When a thread attempts to enter a blackhole, it must wait for
+the result of the computation, which is presumably in progress in
+another thread.
+
+\note{In a single-threaded system, entering a black hole indicates an
+infinite loop.  In a concurrent system, entering a black hole
+indicates an infinite loop only if the hole is being entered by the
+same thread that originally entered the closure.  It could also bring
+about a deadlock situation where several threads are waiting
+circularly on computations in progress.}
+
+There are two types of black hole:
+
+\begin{description}
+
+\item[@BLACKHOLE@]
+A straightforward blackhole just consists of an info pointer and some
+padding to allow updating with an @IND_OLDGEN@ if necessary.  This
+type of blackhole has no waiting threads.
+
+\begin{center}
+\begin{tabular}{|l|l|l|}
+\hline 
+\emph{Fixed header} & \emph{Padding} & \emph{Padding} \\
+\hline
+\end{tabular}
+\end{center}
+
+If we're doing \emph{eager blackholing} then a thunk's info pointer is
+overwritten with @BLACKHOLE_info@ at the time of entry; hence the need
+for blackholes to be small, otherwise we'd be overwriting part of the
+thunk itself.
+
+\item[@BLACKHOLE_BQ@] 
+When a thread enters a @BLACKHOLE@, it is turned into a @BLACKHOLE_BQ@
+(blocking queue), which contains a linked list of blocked threads in
+addition to the info pointer.
+
 \begin{center}
 \begin{tabular}{|l|l|l|}
 \hline 
-\emph{Fixed header} & \emph{Mutable link} & \emph{Blocked thread link} \\
+\emph{Fixed header} & \emph{Blocked thread link} & \emph{Mutable link field} \\
 \hline
 \end{tabular}
 \end{center}
+
 The \emph{Blocked thread link} points to the TSO of the first thread
 waiting for the value of this thunk.  All subsequent TSOs in the list
-are linked together using their @TSO_LINK@ field.
-
-When the blocking queue is non-@NULL@ and the @BH@ is in the old
-generation, the black hole must be added to the mutables list since
-the TSOs on the list may contain pointers into the new generation.
-There is no need to clutter up the mutables list with black holes with
-empty blocking queues.
+are linked together using their @tso->link@ field, ending in
+@END_TSO_QUEUE_closure@.
 
-\note{In a single-threaded system, entering a black hole indicates an
-infinite loop.  In a concurrent system, entering a black hole
-indicates an infinite loop only if the hole is being entered by the
-same thread that originally entered the closure.}
+Because new threads can be added to the \emph{Blocked thread link}, a
+blocking queue is \emph{mutable}, so we need a mutable link field in
+order to chain it on to a mutable list for the generational garbage
+collector.
 
+\end{description}
 
-\subsubsection{FetchMes}\label{sect:FETCHME}
+\Subsubsection{FetchMes}{FETCHME} 
 
 In the parallel systems, FetchMes are used to represent pointers into
 the global heap.  When evaluated, the value they point to is read from
@@ -2198,119 +2303,151 @@ shipped in its entirety if its parent closure is shipped.
 
 
 
-\subsection{Unpointed Objects}
+\Subsection{Unpointed Objects}{unpointed-objects}
 
 A variable of unpointed type is always bound to a \emph{value}, never
 to a \emph{thunk}.  For this reason, unpointed objects cannot be
 entered.
 
-\subsubsection{Immutable Objects}
-\label{sect:ARR_WORDS1}
-\label{sect:ARR_PTRS}
+\subsubsection{Immutable objects}
+\label{sec:ARR_WORDS}
 
 \begin{description}
 \item[@ARR_WORDS@] is a variable-sized object consisting solely of
-non-pointers.  It is used for arrays of all
-sorts of things (bytes, words, floats, doubles... it doesn't matter).
-\begin{center}
-\begin{tabular}{|c|c|c|c|}
-\hline
-\emph{Fixed Hdr} & \emph{No of non-pointers} & \emph{Non-pointers\ldots}       \\ \hline
-\end{tabular}
-\end{center}
+non-pointers.  It is used for arrays of all sorts of things (bytes,
+words, floats, doubles... it doesn't matter).
+
+Strictly speaking, an @ARR_WORDS@ could be mutable, but because it
+only contains non-pointers we don't need to track this fact.
 
-\item[@ARR_PTRS@] is an immutable, variable sized array of pointers.
 \begin{center}
 \begin{tabular}{|c|c|c|c|}
 \hline
-\emph{Fixed Hdr} & \emph{Mutable link} & \emph{No of pointers} & \emph{Pointers\ldots} \\ \hline
+\emph{Fixed Hdr} & \emph{No of non-pointers} & \emph{Non-pointers\ldots}       \\ \hline
 \end{tabular}
 \end{center}
-The mutable link is present so that we can easily freeze and thaw an
-array (by changing the header and adding/removing the array to the
-mutables list).
-
 \end{description}
 
-\subsubsection{Mutable Objects}
-\label{sect:mutables}
-\label{sect:ARR_WORDS2}
-\label{sect:MUTVAR}
-\label{sect:MUTARR_PTRS}
-\label{sect:MUTARR_PTRS_FROZEN}
+\subsubsection{Mutable objects}
+\label{sec:mutables}
+\label{sec:MUT_VAR}
+\label{sec:MUT_ARR_PTRS}
+\label{sec:MUT_ARR_PTRS_FROZEN}
+\label{sec:MVAR}
 
 Some of these objects are \emph{mutable}; they represent objects which
-are explicitly mutated by Haskell code through the @ST@ monad.
-They're not used for thunks which are updated precisely once.
+are explicitly mutated by Haskell code through the @ST@ or @IO@
+monads.  They're not used for thunks which are updated precisely once.
 Depending on the garbage collector, mutable closures may contain extra
 header information which allows a generational collector to implement
 the ``write barrier.''
 
-\begin{description}
+Notice that mutable objects all have the same general layout: there is
+a mutable link field as the second word after the header.  This is so
+that code to process old-generation mutable lists doesn't need to look
+at the type of the object to determine where its link field is.
 
-\item[@ARR_WORDS@] is also used to represent \emph{mutable} arrays of
-bytes, words, floats, doubles, etc.  It's possible to use the same
-object type because even generational collectors don't need to
-distinguish them.
+\begin{description}
 
-\item[@MUTVAR@] is a mutable variable.
+\item[@MUT_VAR@] is a mutable variable.
 \begin{center}
 \begin{tabular}{|c|c|c|}
 \hline
-\emph{Fixed Hdr} & \emph{Mutable link} & \emph{Pointer} \\ \hline
+\emph{Fixed Hdr} \emph{Pointer} & \emph{Mutable link} & \\ \hline
 \end{tabular}
 \end{center}
 
-\item[@MUTARR_PTRS@] is a mutable array of pointers.
-Such an array may be \emph{frozen}, becoming an @ARR_PTRS@, with a
+\item[@MUT_ARR_PTRS@] is a mutable array of pointers.  Such an array
+may be \emph{frozen}, becoming an @MUT_ARR_PTRS_FROZEN@, with a
 different info-table.
+
+\begin{center}
+\begin{tabular}{|c|c|c|c|}
+\hline
+\emph{Fixed Hdr} & \emph{No of ptrs} & \emph{Mutable link} & \emph{Pointers\ldots} \\ \hline
+\end{tabular}
+\end{center}
+
+\item[@MUT_ARR_PTRS_FROZEN@] This is the immutable version of
+@MUT_ARR_PTRS@.  It still has a mutable link field for two reasons: we
+need to keep it on the mutable list for an old generation at least
+until the next garbage collection, and it may become mutable again via
+@thawArray@.
+
 \begin{center}
 \begin{tabular}{|c|c|c|c|}
 \hline
-\emph{Fixed Hdr} & \emph{Mutable link} & \emph{No of ptrs} & \emph{Pointers\ldots} \\ \hline
+\emph{Fixed Hdr} & \emph{No of ptrs} & \emph{Mutable link} & \emph{Pointers\ldots} \\ \hline
 \end{tabular}
 \end{center}
 
+\item[@MVAR@]
+
+\begin{center}
+\begin{tabular}{|l|l|l|l|l|}
+\hline 
+\emph{Fixed header} & \emph{Head} & \emph{Mutable link} & \emph{Tail}
+& \emph{Value}\\
+\hline
+\end{tabular}
+\end{center}
+
+\ToDo{MVars}
+
 \end{description}
 
 
-\subsubsection{Foreign Objects}\label{sect:FOREIGN}
+\Subsubsection{Foreign objects}{FOREIGN}
 
 Here's what a ForeignObj looks like:
 
 \begin{center}
 \begin{tabular}{|l|l|l|l|}
 \hline 
-\emph{Fixed header} & \emph{Data} & \emph{Free Routine} & \emph{Foreign object link} \\
+\emph{Fixed header} & \emph{Data} \\
 \hline
 \end{tabular}
 \end{center}
 
-The @FreeRoutine@ is a reference to the finalisation routine to call
-when the @ForeignObj@ becomes garbage.  If @freeForeignObject@ is
-called on a Foreign Object, the @FreeRoutine@ is set to zero and the
-garbage collector will not attempt to call @FreeRoutine@ when the 
-object becomes garbage.
+A foreign object is simple a boxed pointer to an address outside the
+Haskell heap, possible to @malloc@ed data.  The only reason foreign
+objects exist is so that we can track the lifetime of one using weak
+pointers (see \secref{WEAK}) and run a finaliser when the foreign
+object is unreachable.
+
+\subsubsection{Weak pointers}
+\label{sec:WEAK}
 
-The Foreign object link is a link to the next foreign object in the
-list.  This list is traversed at the end of garbage collection: if an
-object is about to be deallocated (e.g.~it was not marked or
-evacuated), the free routine is called and the object is deleted from
-the list.  
+\begin{center}
+\begin{tabular}{|l|l|l|l|l|}
+\hline 
+\emph{Fixed header} & \emph{Key} & \emph{Value} & \emph{Finaliser}
+& \emph{Link}\\
+\hline
+\end{tabular}
+\end{center}
 
-\subsubsection{MVars and IVars}
-\label{sect:MVAR}
-\label{sect:IVAR}
+\ToDo{Weak poitners}
 
-\ToDo{MVars and IVars}
+\subsubsection{Stable names}
+\label{sec:STABLE_NAME}
 
+\begin{center}
+\begin{tabular}{|l|l|l|l|}
+\hline 
+\emph{Fixed header} & \emph{Index} \\
+\hline
+\end{tabular}
+\end{center}
 
+\ToDo{Stable names}
 
-The remaining objects types are all administrative --- none of them may be entered.
+The remaining objects types are all administrative --- none of them
+may be entered.
 
 \subsection{Other weird objects}
-\label{sect:SPARK}
-\label{sect:BLOCKED_FETCH}
+\label{sec:SPARK}
+\label{sec:BLOCKED_FETCH}
 
 \begin{description}
 \item[@BlockedFetch@ heap objects (`closures')] (parallel only)
@@ -2338,7 +2475,7 @@ the closures in the pool.  It may also choose to delete sparks from the pool.
 \end{tabular}
 \end{center}
 
-\item[Slop Objects]\label{sect:slop-objects}
+\item[Slop Objects]\label{sec:slop-objects}
 
 Slop objects are used to overwrite the end of an updatee if it is
 larger than an indirection.  Normal slop objects consist of an info
@@ -2358,14 +2495,13 @@ fixed header.  This doesn't cause problems because slop objects are
 always unreachable --- they can only be accessed by linearly scanning
 the heap.
 
-\end{description}
+\note{Currently we don't use slop objects because the storage manager
+isn't reliant on objects being adjacent, but if we move to a ``mostly
+copying'' style collector, this will become an issue.}
 
-\subsection{Thread State Objects (TSOs)}\label{sect:TSO}
+\end{description}
 
-\ToDo{This is very out of date.  We now embed a single stack object
-within the TSO.  TSOs include an ID number which can be used to
-generate a hash value.  The gransim, profiling and ticky info is
-surely bogus.}
+\Subsection{Thread State Objects (TSOs)}{TSO}
 
 In the multi-threaded system, the state of a suspended thread is
 packed up into a Thread State Object (TSO) which contains all the
@@ -2387,13 +2523,21 @@ ones.
 \begin{center}
 \begin{tabular}{|l|l|}
    \hline \emph{Fixed header}
-\\ \hline @TSO_LINK@
-\\ \hline @TSO_STATE@
+\\ \hline \emph{Link field}
+\\ \hline \emph{Mutable link field}
+\\ \hline \emph{What next}
+\\ \hline \emph{State}
+\\ \hline \emph{Thread Id}
 \\ \hline \emph{Exception Handlers}
 \\ \hline \emph{Ticky Info}
 \\ \hline \emph{Profiling Info}
 \\ \hline \emph{Parallel Info}
 \\ \hline \emph{GranSim Info}
+\\ \hline \emph{Stack size}
+\\ \hline \emph{Max Stack size}
+\\ \hline \emph{Sp}
+\\ \hline \emph{Su}
+\\ \hline \emph{SpLim}
 \\ \hline 
 \\
           \emph{Stack}
@@ -2402,21 +2546,48 @@ ones.
 \end{tabular}
 \end{center}
 The contents of a TSO are:
-\begin{itemize}
+\begin{description}
 
-\item A pointer (@TSO_LINK@) used to maintain a list of threads with a similar
-  state (e.g.~all runnable, all sleeping, all blocked on the same black
-  hole, all blocked on the same MVar, etc.)
+\item[\emph{Link field}] This is a pointer used to maintain a list of
+threads with a similar state (e.g.~all runnable, all sleeping, all
+blocked on the same black hole, all blocked on the same MVar,
+etc.)
 
-\item A word (@TSO_STATE@) which records the current state of a thread: running, runnable, blocked, etc.
+\item[\emph{Mutable link field}] Because the stack is mutable by
+definition, the generational collector needs to track TSOs in older
+generations that may point into younger ones (which is just about any
+TSO for a thread that has run recently).  Hence the need for a mutable
+link field (see \secref{mutables}).
+
+\item[\emph{What next}]
+This field has five values:  
+\begin{description}
+\item[@ThreadEnterGHC@]  The thread can be started by entering the
+closure pointed to by the word on the top of the stack.
+\item[@ThreadRunGHC@]  The thread can be started by jumping to the
+address on the top of the stack.
+\item[@ThreadEnterHugs@]  The stack has a pointer to a Hugs-built
+closure on top of the stack: enter the closure to run the thread.
+\item[@ThreadKilled@] The thread has been killed (by @killThread#@).
+It is probably still around because it is on some queue somewhere and
+hasn't been garbage collected yet.
+\item[@ThreadComplete@] The thread has finished.  Its @TSO@ hasn't
+been garbage collected yet.
+\end{description}
 
-\item Optional information for ``Ticky Ticky'' statistics: @TSO_STK_HWM@ is
-  the maximum number of words allocated to this thread.
+\item[\emph{Thread Id}]
+This field contains a (not necessarily unique) integer that identifies
+the thread.  It can be used eg. for hashing.
 
-\item Optional information for profiling: 
-  @TSO_CCC@ is the current cost centre.
+\item[\emph{Ticky Info}] Optional information for ``Ticky Ticky''
+statistics: @TSO_STK_HWM@ is the maximum number of words allocated to
+this thread.
 
-\item Optional information for parallel execution:
+\item[\emph{Profiling Info}] Optional information for profiling:
+@TSO_CCC@ is the current cost centre.
+
+\item[\emph{Parallel Info}]
+Optional information for parallel execution.
 
 % \begin{itemize}
 % 
@@ -2431,7 +2602,10 @@ The contents of a TSO are:
 % \item I've no idea what else
 % 
 % \end{itemize}
-% 
+
+\item[\emph{GranSim Info}]
+Optional information for gransim execution.
+
 % \item Optional information for GranSim execution:
 % \begin{itemize}
 % \item locked         
@@ -2462,55 +2636,20 @@ The contents of a TSO are:
 % Q_MIGRATING 
 % 
 
-\end{itemize}
+\item[\emph{Stack Info}] Various fields contain information on the
+stack: its current size, its maximum size (to avoid infinite loops
+overflowing the memory), the current stack pointer (\emph{Sp}), the
+current stack update frame pointer (\emph{Su}), and the stack limit
+(\emph{SpLim}).  The latter three fields are loaded into the relevant
+registers when the thread is run.
 
-\subsection{Stack Objects}
-\label{sect:STACK_OBJECT}
-\label{sect:stacks}
+\item[\emph{Stack}] This is the actual stack for the thread,
+\emph{Stack size} words long.  It grows downwards from higher
+addresses to lower addresses.  When the stack overflows, it will
+generally be relocated into larger premises unless \emph{Max stack
+size} is reached.
 
-\ToDo{Merge this in with the section on TSOs}
-
-These are ``stack objects,'' which are used in the threaded world as
-the stack for each thread is allocated from the heap in smallish
-chunks.  (The stack in the sequential world is allocated outside of
-the heap.)
-
-Each reduction thread has to have its own stack space.  As there may
-be many such threads, and as any given one may need quite a big stack,
-a naive give-'em-a-big-stack-and-let-'em-run approach will cost a {\em
-lot} of memory.
-
-Our approach is to give a thread a small stack space, and then link
-on/off extra ``chunks'' as the need arises.  Again, this is a
-storage-management problem, and, yet again, we choose to graft the
-whole business onto the existing heap-management machinery.  So stack
-objects will live in the heap, be garbage collected, etc., etc..
-
-A stack object is laid out like this:
-
-\begin{center}
-\begin{tabular}{|l|}
-\hline
-\emph{Fixed header} 
-\\ \hline
-\emph{Link to next stack object (0 for last)}
-\\ \hline
-\emph{N, the payload size in words}
-\\ \hline
-\emph{@Sp@ (byte offset from head of object)}
-\\ \hline
-\emph{@Su@ (byte offset from head of object)}
-\\ \hline
-\emph{Payload (N words)}
-\\ \hline
-\end{tabular}
-\end{center}
-
-The stack grows downwards, towards decreasing
-addresses.  This makes it easier to print out the stack
-when debugging, and it means that a return address is
-at the lowest address of the chunk of stack it ``knows about''
-just like an info pointer on a closure.
+\end{description}
 
 The garbage collector needs to be able to find all the
 pointers in a stack.  How does it do this?
@@ -2538,14 +2677,13 @@ a well-defined activation record.
 
 \end{itemize}
 
-The game plan is this.  The garbage collector
-walks the stack from the top, traversing pending-argument sections and
-activation records alternately.  Next we discuss how it finds
-the pointers in each of these two stack regions.
+The game plan is this.  The garbage collector walks the stack from the
+top, traversing pending-argument sections and activation records
+alternately.  Next we discuss how it finds the pointers in each of
+these two stack regions.
 
 
-\subsubsection{Activation records}\label{sect:activation-records}
-
+\Subsubsection{Activation records}{activation-records}
 
 An \emph{activation record} is a contiguous chunk of stack,
 with a return address as its first word, followed by as many
@@ -2555,52 +2693,51 @@ to an info table, replete with:
 
 \begin{itemize}
 \item entry code (i.e. the code to return to).
-\item @INFO_TYPE@ is either @RET_SMALL/RET_VEC_SMALL@ or @RET_BIG/RET_VEC_BIG@, depending
-on whether the activation record has more than 32 data words (\note{64 for 8-byte-word architectures}) and on whether 
-to use a direct or a vectored return.
-\item @INFO_SM@ for @RET_SMALL@ is a bitmap telling the layout
+
+\item closure type is either @RET_SMALL/RET_VEC_SMALL@ or
+@RET_BIG/RET_VEC_BIG@, depending on whether the activation record has
+more than 32 data words (\note{64 for 8-byte-word architectures}) and
+on whether to use a direct or a vectored return.
+
+\item the layout info for @RET_SMALL@ is a bitmap telling the layout
 of the activation record, one bit per word.  The least-significant bit
 describes the first data word of the record (adjacent to the fixed
 header) and so on.  A ``@1@'' indicates a non-pointer, a ``@0@''
-indicates
-a pointer.  We don't need to indicate exactly how many words there
-are,
-because when we get to all zeros we can treat the rest of the 
-activation record as part of the next pending-argument region.
-
-For @RET_BIG@ the @INFO_SM@ field points to a block of bitmap
-words, starting with a word that tells how many words are in
-the block.
-
-\item @INFO_SRT@ is the Static Reference Table for the return
-address (Section~\ref{sect:srt}).
+indicates a pointer.  We don't need to indicate exactly how many words
+there are, because when we get to all zeros we can treat the rest of
+the activation record as part of the next pending-argument region.
+
+For @RET_BIG@ the layout field points to a block of bitmap words,
+starting with a word that tells how many words are in the block.
+
+\item the info table contains a Static Reference Table pointer for the
+return address (\secref{srt}).
 \end{itemize}
 
-The activation record is a fully fledged closure too.
-As well as an info pointer, it has all the other attributes of
-a fixed header (Section~\ref{sect:fixed-header}) including a saved cost
-centre which is reloaded when the return address is entered.
+The activation record is a fully fledged closure too.  As well as an
+info pointer, it has all the other attributes of a fixed header
+(\secref{fixed-header}) including a saved cost centre which
+is reloaded when the return address is entered.
 
 In other words, all the attributes of closures are needed for
 activation records, so it's very convenient to make them look alike.
 
 
-\subsubsection{Pending arguments}
+\Subsubsection{Pending arguments}{pending-args}
 
-So that the garbage collector can correctly identify pointers
-in pending-argument sections we explicitly tag all non-pointers.
-Every non-pointer in a pending-argument section is preceded
-(at the next lower memory word) by a one-word byte count that
-says how many bytes to skip over (excluding the tag word).
+So that the garbage collector can correctly identify pointers in
+pending-argument sections we explicitly tag all non-pointers.  Every
+non-pointer in a pending-argument section is preceded (at the next
+lower memory word) by a one-word byte count that says how many bytes
+to skip over (excluding the tag word).
 
-The garbage collector traverses a pending argument section from 
-the top (i.e. lowest memory address).  It looks at each word in turn:
+The garbage collector traverses a pending argument section from the
+top (i.e. lowest memory address).  It looks at each word in turn:
 
 \begin{itemize}
-\item If it is less than or equal to a small constant @MAX_STACK_TAG@
-then
-it treats it as a tag heralding zero or more words of non-pointers,
-so it just skips over them.
+\item If it is less than or equal to a small constant @ARGTAG_MAX@
+then it treats it as a tag heralding zero or more words of
+non-pointers, so it just skips over them.
 
 \item If it points to the code segment, it must be a return
 address, so we have come to the end of the pending-argument section.
@@ -2609,7 +2746,7 @@ address, so we have come to the end of the pending-argument section.
 \end{itemize}
 
 
-\subsection{The Stable Pointer Table}\label{sect:STABLEPTR_TABLE}
+\Subsection{The Stable Pointer Table}{STABLEPTR_TABLE}
 
 A stable pointer is a name for a Haskell object which can be passed to
 the external world.  It is ``stable'' in the sense that the name does
@@ -2663,9 +2800,273 @@ are evacuated and @NULL@-values are chained together to form a new free list.
 There's no need to link the stable pointer table onto the mutable
 list because we always treat it as a root.
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\Subsection{Garbage Collecting CAFs}{CAF}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% begin{direct quote from current paper}
+A CAF (constant applicative form) is a top-level expression with no
+arguments.  The expression may need a large, even unbounded, amount of
+storage when it is fully evaluated.
+
+CAFs are represented by closures in static memory that are updated
+with indirections to objects in the heap space once the expression is
+evaluated.  Previous version of GHC maintained a list of all evaluated
+CAFs and traversed them during GC, the result being that the storage
+allocated by a CAF would reside in the heap until the program ended.
+% end{direct quote from current paper}
+
+% begin{elaboration on why CAFs are very very bad}
+Treating CAFs this way has two problems:
+\begin{itemize}
+\item
+It can cause a very large space leak.  For example, this program
+should run in constant space but, instead, will run out of memory.
+\begin{verbatim}
+> main :: IO ()
+> main = print nats
+>
+> nats :: [Int]
+> nats = [0..maxInt]
+\end{verbatim}
+
+\item
+Expressions with no arguments have very different space behaviour
+depending on whether or not they occur at the top level.  For example, 
+if we make \verb+nats+ a local definition, the space leak goes away 
+and the resulting program runs in constant space, as expected.
+\begin{verbatim}
+> main :: IO ()
+> main = print nats
+>  where
+>   nats :: [Int]
+>   nats = [0..maxInt]
+\end{verbatim}
+
+This huge change in the operational behaviour of the program 
+is a problem for optimising compilers and for programmers.
+For example, GHC will normally flatten a set of let bindings using
+this transformation:
+\begin{verbatim}
+let x1 = let x2 = e2 in e1   ==>   let x2 = e2 in let x1 = e1
+\end{verbatim}
+but it does not do so if this would raise \verb+x2+ to the top level
+since that may create a CAF.  Many Haskell programmers avoid creating
+large CAFs by adding a dummy argument to a CAF or by moving a CAF away
+from the top level.
+
+\end{itemize}
+% end{elaboration on why CAFs are very very bad}
+
+Solving the CAF problem requires different treatment in interactive
+systems such as Hugs than in batch-mode systems such as GHC 
+\begin{itemize}
+\item
+In a batch-mode the program the runtime system is terminated
+after every execution of the runtime system.  In such systems,
+the garbage collector can completely ``destroy'' a CAF when it 
+is no longer live --- in much the same way as it ``destroys''
+normal closures when they are no longer live.
+
+\item
+In an interactive system, many expressions are evaluated without
+restarting the runtime system between each evaluation.  In such
+systems, the garbage collector cannot completely ``destroy'' a CAF
+when it is no longer live because, whilst it might not be required in
+the evaluation of the current expression, it might be required in the
+next evaluation.
+
+There are two possible behaviours we might want:
+\begin{enumerate}
+\item
+When a CAF is no longer required for the current evaluation, the CAF
+should be reverted to its original form.  This behaviour ensures that
+the operational behaviour of the interactive system is a reasonable
+predictor of the operational behaviour of the batch-mode system.  This
+allows us to use Hugs for performance debugging (in particular, trying
+to understand and reduce the heap usage of a program) --- an area of
+increasing importance as Haskell is used more and more to solve ``real
+problems'' in ``real problem domains''.
+
+\item
+Even if a CAF is no longer required for the current evaluation, we might
+choose to hang onto it by collecting it in the normal way.  This keeps
+the space leak but might be useful in a teaching environment when
+trying to teach the difference between call by name evaluation (which
+doesn't share work) and lazy evaluation (which does share work).
+
+\end{enumerate}
+
+It turns out that it is easy to support both styles of use, so the
+runtime system provides a switch which lets us turn this on and off
+during execution.  \ToDo{What is this switch called?}  It would also
+be easy to provide a function \verb+RevertCAF+ to let the interpreter
+revert any CAF it wanted between (but not during) executions, if we so
+desired.  Running \verb+RevertCAF+ during execution would lose some sharing
+but is otherwise harmless.
+
+\end{itemize}
+
+% % begin{even more pointless observation?}
+% The simplest fix would be to remove the special treatment of 
+% top level variables.  This works but is very inefficient.
+% ToDo: say why.
+% (Note: delete this paragraph from final version.)
+% % end{even more pointless observation?}
+
+% begin{pointless observation?}
+An easy but inefficient fix to the CAF problem would be to make a
+complete copy of the heap before every evaluation and discard the copy
+after evaluation.  This works but is inefficient.
+% end{pointless observation?}
+
+An efficient way to achieve a similar effect is to revert all
+updatable thunks to their original form as they become unnecessary for
+the current evaluation.  To do this, we modify the compiler to ensure
+that the only updatable thunks generated by the compiler are CAFs and
+we modify the garbage collector to revert entered CAFs to unentered
+CAFs as their value becomes unnecessary.
+
+
+\subsubsection{New Heap Objects}
+
+We add three new kinds of heap object: unentered CAF closures, entered
+CAF objects and CAF blackholes.  We first describe how they are
+evaluated and then how they are garbage collected.
+\begin{itemize}
+\item
+Unentered CAF closures contain a pointer to closure representing the
+body of the CAF.  The ``body closure'' is not updatable.
+
+Unentered CAF closures contain two unused fields to make them the same
+size as entered CAF closures --- which allows us to perform an inplace
+update.  \ToDo{Do we have to add another kind of inplace update operation
+to the storage manager interface or do we consider this to be internal
+to the SM?}
+\begin{center}
+\begin{tabular}{|l|l|l|l|}\hline
+\verb+CAF_unentered+ & \emph{body closure} & \emph{unused} & \emph{unused} \\ \hline
+\end{tabular}
+\end{center}
+When an unentered CAF is entered, we do the following:
+\begin{itemize}
+\item
+allocate a CAF black hole;
+
+\item
+push an update frame (to update the CAF black hole) onto the stack;
+
+\item
+overwrite the CAF with an entered CAF object (see below) with the same
+body and whose value field points to the black hole;
+
+\item
+add the CAF to a list of all entered CAFs (called ``the CAF list'');
+and
+
+\item
+the closure representing the value of the CAF is entered.
+
+\end{itemize}
+
+When evaluation of the CAF body returns a value, the update frame
+causes the CAF black hole to be updated with the value in the normal
+way.
+
+\ToDo{Add a picture}
+
+\item
+Entered CAF closures contain two pointers: a pointer to the CAF body
+(the same as for unentered CAF closures); a pointer to the CAF value
+(this is initialised with a CAF blackhole, as previously described);
+and a link to the next CAF in the CAF list 
+
+\ToDo{How is the end of the list marked?  Null pointer or sentinel value?}.
+
+\begin{center}
+\begin{tabular}{|l|l|l|l|}\hline
+\verb+CAF_entered+ & \emph{body closure} & \emph{value} & \emph{link} \\ \hline
+\end{tabular}
+\end{center}
+When an entered CAF is entered, it enters its value closure.
+
+\item
+CAF blackholes are identical to normal blackholes except that they
+have a different infotable.  The only reason for having CAF blackholes
+is to allow an optimisation of lazy blackholing where we stop scanning
+the stack when we see the first {\em normal blackhole} but not
+when we see a {\em CAF blackhole.}
+\ToDo{The optimisation we want to allow should be described elsewhere
+so that all we have to do here is describe the difference.}
+
+Instead of allocating a blackhole to update with the value of the CAF,
+it might seem simpler to update the CAF directly.  This would require
+a new kind of update frame which would update the value field of the
+CAF with a pointer to the value and wouldn't catch blackholes caused
+by CAFs that depend on themselves so we chose not to do so.
+
+\end{itemize}
+
+\subsubsection{Garbage Collection}
+
+To avoid the space leak, each run of the garbage collector must revert
+the entered CAFs which are not required to complete the current
+evaluation (that is all the closures reachable from the set of
+runnable threads and the stable pointer table).
+
+It does this by performing garbage collection in three phases:
+\begin{enumerate}
+\item
+During the first phase, we ``mark'' all closures reachable from the
+scheduler state.  
 
+How we ``mark'' closures depends on the garbage collector.  For
+example, in a 2-space collector, closures are ``marked'' by copying
+them into ``to-space'', overwriting them with a forwarding node and
+``marking'' all the closures reachable from the copy.  The only
+requirements are that we can test whether a closure is marked and if a
+closure is marked then so are all closures reachable from it.
 
-\section{The Bytecode Evaluator}
+\ToDo{At present we say that the scheduler state includes any state
+that Hugs may have.  This is not true anymore.}
+
+Performing this phase first provides us with a cheap test for
+execution closures: at this stage in execution, the execution closures
+are precisely the marked closures.
+
+\item
+During the second phase, we revert all unmarked CAFs on the CAF list
+and remove them from the CAF list.
+
+Since the CAF list is exactly the set of all entered CAFs, this reverts
+all entered CAFs which are not execution closures.
+
+\item
+During the third phase, we mark all top level objects (including CAFs)
+by calling \verb+MarkHugsRoots+ which will call \verb+MarkRoot+ for
+each top level object known to Hugs.
+
+\end{enumerate}
+
+To implement the second style of interactive behaviour (where we
+deliberately keep the CAF-related space leak), we simply omit the
+second phase.  Omitting the second phase causes the third phase to
+mark any unmarked CAF value closures.
+
+So far, we have been describing a pure Hugs system which contains no
+machine generated code.  The main difference in a hybrid system is
+that GHC-generated code is statically allocated in memory instead of
+being dynamically allocated on the heap.  We split both
+\verb+CAF_unentered+ and \verb+CAF_entered+ into two versions: a
+static and a dynamic version.  The static and dynamic versions of each
+CAF differ only in whether they are moved during garbage collection.
+When reverting CAFs, we revert dynamic entered CAFs to dynamic
+unentered CAFs and static entered CAFs to static unentered CAFs.
+
+
+
+
+\Section{The Bytecode Evaluator}{bytecode-evaluator}
 
 This section describes how the Hugs interpreter interprets code in the
 same environment as compiled code executes.  Both evaluation models
@@ -2693,7 +3094,7 @@ by compiled code:
 \item
 
 Whereas compiled code has five different ways of entering a closure
-(section~\ref{sect:entering-closures}), interpreted code has only one.
+(\secref{ghc-fun-call}), interpreted code has only one.
 The entry point for interpreted code behaves like slow entry points for
 compiled code.
 
@@ -2734,7 +3135,7 @@ heap and restricting BCOs to a single basic block.
 
 \end{itemize}
 
-\subsection{Hugs Info Tables}
+\Subsection{Hugs Info Tables}{hugs-info-tables}
 
 Hugs requires the following info tables and closures:
 \begin{description}
@@ -2742,9 +3143,9 @@ Hugs requires the following info tables and closures:
 
 Contains both a vectored return table and a direct entry point.  All
 entry points are the same: they rearrange the stack to match the Hugs
-return convention (section~\label{sect:hugs-return-convention}) and return
-to the scheduler.  When the scheduler restarts the thread, it will
-find a BCO on top of the stack and will enter the Hugs interpreter.
+return convention (\secref{hugs-return-convention}) and return to the
+scheduler.  When the scheduler restarts the thread, it will find a BCO
+on top of the stack and will enter the Hugs interpreter.
 
 \item [@UPD_RET@].
 
@@ -2785,14 +3186,13 @@ types in a Haskell source file.
 
 \end{description}
 
-\subsection{Hugs Heap Objects}
-\label{sect:hugs-heap-objects}
+\Subsection{Hugs Heap Objects}{hugs-heap-objects}
 
-\subsubsection{Byte-Code Objects}
+\subsubsection{Byte-code objects}
 
 Compiled byte code lives on the global heap, in objects called
 Byte-Code Objects (or BCOs).  The layout of BCOs is described in
-detail in Section \ref{sect:BCO}, in this section we will describe
+detail in \secref{BCO}, in this section we will describe
 their semantics.
 
 Since byte-code lives on the heap, it can be garbage collected just
@@ -2817,21 +3217,19 @@ of that code.  Since Hugs byte-code is lambda-lifted, free variables
 become arguments and are expected to be on the stack by the called
 function.
 
-Hugs represents updateable thunks with @AP@ objects applying a closure
+Hugs represents updateable thunks with @AP_UPD@ objects applying a closure
 to a list of arguments.  (As for @PAP@s, unboxed arguments should be
 preceded by a tag.)  When it is entered, it pushes an update frame
 followed by its payload on the stack, and enters the first word (which
-will be a pointer to a BCO).  The layout of @AP@ objects is described
-in more detail in Section \ref{sect:AP}.
+will be a pointer to a BCO).  The layout of @AP_UPD@ objects is described
+in more detail in \secref{AP_UPD}.
 
 Partial applications are represented by @PAP@ objects, which are
 non-updatable.
 
 \ToDo{Hugs Constructors}.
 
-\subsection{Calling conventions}
-\label{sect:hugs-calling-conventions}
-\label{sect:standard-closures}
+\Subsection{Calling conventions}{hugs-calling-conventions}
 
 The calling convention for any byte-code function is straightforward:
 \begin{itemize}
@@ -2843,28 +3241,27 @@ The calling convention for any byte-code function is straightforward:
 In a system containing both GHC and Hugs, the bytecode interpreter
 only has to be able to enter BCOs: everything else can be handled by
 returning to the compiled world (as described in
-Section~\ref{sect:hugs-to-ghc-switch}) and entering the closure
+\secref{hugs-to-ghc-switch}) and entering the closure
 there.
 
-This would work but it would obviously be very inefficient if
-we entered a @AP@ by switching worlds, entering the @AP@,
-pushing the arguments and function onto the stack, and entering the
-function which, likely as not, will be a byte-code object which we
-will enter by \emph{returning} to the byte-code interpreter.  To avoid
-such gratuitious world switching, we choose to recognise certain
-closure types as being ``standard'' --- and duplicate the entry code
-for the ``standard closures'' in the bytecode interpreter.
+This would work but it would obviously be very inefficient if we
+entered a @AP@ by switching worlds, entering the @AP@, pushing the
+arguments and function onto the stack, and entering the function
+which, likely as not, will be a byte-code object which we will enter
+by \emph{returning} to the byte-code interpreter.  To avoid such
+gratuitious world switching, we choose to recognise certain closure
+types as being ``standard'' --- and duplicate the entry code for the
+``standard closures'' in the bytecode interpreter.
 
 A closure is said to be ``standard'' if its entry code is entirely
 determined by its info table.  \emph{Standard Closures} have the
-desirable property that the byte-code interpreter can enter
-the closure by simply ``interpreting'' the info table instead of
-switching to the compiled world.  The standard closures include:
+desirable property that the byte-code interpreter can enter the
+closure by simply ``interpreting'' the info table instead of switching
+to the compiled world.  The standard closures include:
 
 \begin{description}
-\item[Constructor]
-To enter a constructor, we simply return (see Section
-\ref{sect:hugs-return-convention}).
+\item[Constructor] To enter a constructor, we simply return (see
+\secref{hugs-return-convention}).
 
 \item[Indirection]
 To enter an indirection, we simply enter the object it points to
@@ -2881,26 +3278,26 @@ arguments, push the function and enter the function.
 To enter a @PAP@, we push the arguments, push the function and enter
 the function.  (Not forgetting a stack check at the start.)
 
-\item[Selector] 
-To enter a selector, we test whether the selectee is a value.  If so,
-we simply select the appropriate component; if not, it's simplest to
-treat it as a GHC-built closure --- though we could interpret it if we
-wanted.
+\item[Selector]
+
+To enter a selector (\secref{THUNK_SELECTOR}), we test whether the
+selectee is a value.  If so, we simply select the appropriate
+component; if not, it's simplest to treat it as a GHC-built closure
+--- though we could interpret it if we wanted.
 
 \end{description}
 
 The most obvious omissions from the above list are @BCO@s (which we
-dealt with above) and GHC-built closures (which are covered in Section
-\ref{sect:hugs-to-ghc-switch}).
+dealt with above) and GHC-built closures (which are covered in
+\secref{hugs-to-ghc-switch}).
 
 
-\subsection{Return convention}
-\label{sect:hugs-return-convention}
+\Subsection{Return convention}{hugs-return-convention}
 
 When Hugs pushes a return address, it pushes both a pointer to the BCO
 to return to, and a pointer to a static code fragment @HUGS_RET@ (this
-is described in Section \ref{sect:ghc-to-hugs-switch}).  The
-stack layout is shown in Figure \ref{fig:hugs-return-stack}.
+is described in \secref{ghc-to-hugs-switch}).  The
+stack layout is shown in \figref{hugs-return-stack}.
 
 \begin{figure}[ht]
 \begin{center}
@@ -2916,6 +3313,7 @@ stack layout is shown in Figure \ref{fig:hugs-return-stack}.
 \end{center}
 \caption{Stack layout for a Hugs return address}
 \label{fig:hugs-return-stack}
+% this figure apparently duplicates {fig:hugs-return-stack1} earlier.
 \end{figure}
 
 \begin{figure}[ht]
@@ -2945,7 +3343,7 @@ stack layout is shown in Figure \ref{fig:hugs-return-stack}.
 %\input{hugs_ret2.pstex_t}
 \end{center}
 \caption{Stack layout on entering a Hugs return address with an unboxed value}
-\label{fig:hugs-return-int}
+\label{fig:hugs-return-int1}
 \end{figure}
 
 \begin{figure}[ht]
@@ -2992,22 +3390,22 @@ return address on top of the stack.
 \item If the return address is @HUGS_RET@, pop the @HUGS_RET@ and the
 bco for the continuation off the stack, push a pointer to the constructor onto
 the stack and enter the BCO with the current object pointer set to the BCO
-(Figure \ref{fig:hugs-return2}).
+(\figref{hugs-return2}).
 
 \item If the top of the stack is not @HUGS_RET@, we need to do a world
-switch as described in Section \ref{sect:hugs-to-ghc-switch}.
+switch as described in \secref{hugs-to-ghc-switch}.
 
 \end{itemize}
 
 \ToDo{This duplicates what we say about switching worlds
-(section~\ref{sect:switching-worlds}) - kill one or t'other.}
+(\secref{switching-worlds}) - kill one or t'other.}
 
 
 \ToDo{This was in the evaluation model part but it really belongs in
 this part which is about the internal details of each of the major
 sections.}
 
-\subsection{Addressing Modes}
+\Subsection{Addressing Modes}{hugs-addressing-modes}
 
 To avoid potential alignment problems and simplify garbage collection,
 all literal constants are stored in two tables (one boxed, the other
@@ -3023,7 +3421,7 @@ char, int, nat and float since they all occupy 32 bits --- but it
 costs almost nothing to distinguish them and may improve portability
 and simplify debugging.
 
-\subsection{Compilation}
+\Subsection{Compilation}{hugs-compilation}
 
 
 \def\is{\mbox{\it is}}
@@ -3125,7 +3523,7 @@ used.  Here is a small compiler for the STG language.
 
 \ToDo{Optimise thunks of the form @f{x1,...xm}@ so that we build an AP directly}
 
-\subsection{Instructions}
+\Subsection{Instructions}{hugs-instructions}
 
 We specify the semantics of instructions using transition rules of
 the form:
@@ -3141,7 +3539,7 @@ where $\is$ is an instruction stream, $s$ is the stack, $\su$ is the
 update frame pointer and $h$ is the heap.
 
 
-\subsection{Stack manipulation}
+\Subsection{Stack manipulation}{hugs-stack-manipulation}
 
 \begin{description}
 
@@ -3219,7 +3617,7 @@ where $\size{\as} = m$ and $\size{\bs} = n$.
 \end{description}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\subsection{Heap manipulation}
+\Subsection{Heap manipulation}{hugs-heap-manipulation}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \begin{description}
@@ -3281,7 +3679,7 @@ always push the args in reverse order.
 \end{description}
 
 
-\subsection{Entering a closure}
+\Subsection{Entering a closure}{hugs-entering}
 
 \begin{description}
 
@@ -3361,7 +3759,7 @@ Optimisations:
 \end{description}
 
 
-\subsection{Updates}
+\Subsection{Updates}{hugs-updates}
 
 \begin{description}
 
@@ -3401,7 +3799,7 @@ in different directions.
 
 \end{description}
 
-\subsection{Branches}
+\Subsection{Branches}{hugs-branches}
 
 \begin{description}
 
@@ -3428,7 +3826,7 @@ where $C.\tag \neq tag$
 \end{description}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\subsection{Heap and stack checks}
+\Subsection{Heap and stack checks}{hugs-heap-stack-checks}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \begin{tabular}{|llrrrrr|}
@@ -3464,22 +3862,22 @@ Optimisations:
 
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\subsection{Primops}
+\Subsection{Primops}{hugs-primops}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \ToDo{primops take m words and return n words. The expect boxed arguments on the stack.}
 
 
-\section{The Machine Code Evaluator}
+\Section{The Machine Code Evaluator}{asm-evaluator}
 
 This section describes the framework in which compiled code evaluates
 expressions.  Only at certain points will compiled code need to be
-able to talk to the interpreted world; these are discussed in Section
-\ref{sect:switching-worlds}.
+able to talk to the interpreted world; these are discussed in
+\secref{switching-worlds}.
 
-\subsection{Calling conventions}
+\Subsection{Calling conventions}{ghc-calling-conventions}
 
-\subsubsection{The call/return registers}
+\Subsubsection{The call/return registers}{ghc-regs}
 
 One of the problems in designing a virtual machine is that we want it
 abstract away from tedious machine details but still reveal enough of
@@ -3508,24 +3906,24 @@ registers then we could pass between 2 and 4 arguments in machine
 registers --- depending on whether they all have the same kind or they
 have different kinds.
 
-\subsubsection{Entering closures}
-\label{sect:entering-closures}
+\Subsubsection{Entering closures}{entering-closures}
 
 To evaluate a closure we jump to the entry code for the closure
 passing a pointer to the closure in \Arg{1} so that the entry code can
 access its environment.
 
-\subsubsection{Function call}
+\Subsubsection{Function call}{ghc-fun-call}
 
 The function-call mechanism is obviously crucial.  There are five different
 cases to consider:
 \begin{enumerate}
 
-\item \emph{Known combinator (function with no free variables) and enough arguments.}  
+\item \emph{Known combinator (function with no free variables) and
+enough arguments.}
 
 A fast call can be made: push excess arguments onto stack and jump to
 function's \emph{fast entry point} passing arguments in \Arg{1} \ldots
-\Arg{m}.  
+\Arg{m}.
 
 The \emph{fast entry point} is only called with exactly the right
 number of arguments (in \Arg{1} \ldots \Arg{m}) so it can instantly
@@ -3554,7 +3952,7 @@ This \emph{argument satisfaction check} consists of checking that
 \item If the argument satisfaction check fails, it is because there is
 one or more update frames on the stack before the rest of the
 arguments that the function needs.  In this case, we construct a PAP
-(partial application, section~\ref{sect:PAP}) containing the arguments
+(partial application, \secref{PAP}) containing the arguments
 which are on the stack.  The PAP construction code will return to the
 update frame with the address of the PAP in \Arg{1}.
 
@@ -3577,7 +3975,8 @@ fast entry point without performing a jump.
 \end{itemize}
 
 
-\item \emph{Known function closure (function with free variables) and enough arguments.}
+\item \emph{Known function closure (function with free variables) and
+enough arguments.}
 
 A fast call can be made: push excess arguments onto stack and jump to
 function's \emph{fast entry point} passing a pointer to closure in
@@ -3618,7 +4017,7 @@ the thunk for @(g x)@.
 The \emph{entry code} for an updateable thunk (which must have arity 0)
 pushes an update frame on the stack and starts executing the body of
 the closure --- using \Arg{1} to access any free variables.  This is
-described in more detail in section~\ref{sect:data-updates}.
+described in more detail in \secref{data-updates}.
 
 The \emph{entry code} for a non-updateable closure is just the
 closure's slow entry point.
@@ -3629,7 +4028,9 @@ In addition to the above considerations, if there are \emph{too many}
 arguments then the extra arguments are simply pushed on the stack with
 appropriate tags.
 
-To summarise, a closure's standard (slow) entry point performs the following:
+To summarise, a closure's standard (slow) entry point performs the
+following:
+
 \begin{description}
 \item[Argument satisfaction check.] (function closure only)
 \item[Stack overflow check.]
@@ -3641,8 +4042,7 @@ To summarise, a closure's standard (slow) entry point performs the following:
 \end{description}
 
 
-\subsection{Case expressions and return conventions}
-\label{sect:return-conventions}
+\Subsection{Case expressions and return conventions}{return-conventions}
 
 The \emph{evaluation} of a thunk is always initiated by
 a @case@ expression.  For example:
@@ -3674,8 +4074,8 @@ type of the scrutinee @x@:
 (A space for) the return address is left on the top of the stack.
 Leaving the return address on the stack ensures that the top of the
 stack contains a valid activation record
-(section~\ref{sect:activation-records}) --- should a garbage collection
-be required.
+(\secref{activation-records}) --- should a garbage
+collection be required.
 
 \item If @x@ has a boxed type (e.g.~a data constructor or a function),
 a pointer to @x@ is returned in \Arg{1}.
@@ -3695,7 +4095,7 @@ flattened out and passed in \Arg{1} \ldots \Arg{n} as usual.
 
 \end{itemize}
 
-\subsection{Vectored Returns}
+\Subsection{Vectored Returns}{vectored-returns}
 
 Many algebraic data types have more than one constructor.  For
 example, the @Maybe@ type is defined like this:
@@ -3727,7 +4127,7 @@ It might seem that we could avoid loading \Arg{1} in this case since the
 first item in the return vector will know that @Nothing@ was returned
 (and can easily access the Nothing closure in the (unlikely) event
 that it needs it.  The only reason we load \Arg{1} is in case we have to
-perform an update (section~\ref{sect:data-updates}).
+perform an update (\secref{data-updates}).
 
 \item 
 
@@ -3740,7 +4140,7 @@ In this way no test need be made to see which constructor returns;
 instead, execution resumes immediately in the appropriate branch of
 the @case@.
 
-\subsection{Direct Returns}
+\Subsection{Direct Returns}{direct-returns}
 
 When a datatype has a large number of constructors, it may be
 inappropriate to use vectored returns.  The vector tables may be
@@ -3753,22 +4153,22 @@ In a direct return, the return address pushed on the stack really is a
 code pointer.  The returning code loads a pointer to the closure being
 returned in \Arg{1} as usual, and also loads the tag into \Arg{2}.
 The code at the return address will test the tag and jump to the
-appropriate code for the case branch.
+appropriate code for the case branch.  If \Arg{2} isn't mapped to a
+real machine register on this architecture, then we don't load it on a
+return, instead using the tag directly from the info table.
 
 The choice of whether to use a vectored return or a direct return is
 made on a type-by-type basis --- up to a certain maximum number of
 constructors imposed by the update mechanism
-(section~\ref{sect:data-updates}).
+(\secref{data-updates}).
 
 Single-constructor data types also use direct returns, although in
 that case there is no need to return a tag in \Arg{2}.
 
-\ToDo{Say whether we pop the return address before returning}
-
-\ToDo{Stack stubbing?}
+\ToDo{for a nullary constructor we needn't return a pointer to the
+constructor in \Arg{1}.}
 
-\subsection{Updates}
-\label{sect:data-updates}
+\Subsection{Updates}{data-updates}
 
 The entry code for an updatable thunk (which must be of arity 0):
 
@@ -3793,10 +4193,9 @@ what we're going to do when we add support for speculative
 evaluation.}
 \ToDo{I think update frames contain cost centres sometimes}
 
-\item 
-If we are doing ``eager blackholing,'' we then overwrite the thunk
-with a black hole.  Otherwise, we leave it to the garbage collector to
-black hole the thunk.
+\item If we are doing ``eager blackholing,'' we then overwrite the
+thunk with a black hole (\secref{BLACKHOLE}).  Otherwise, we leave it
+to the garbage collector to black hole the thunk.
 
 \item 
 Start evaluating the body of the expression.
@@ -3851,8 +4250,7 @@ it knows whether to perform a direct or vectored return.  This could
 be optimised by compiling special update code for each slot in the
 return vector, which performs the correct return.
 
-\subsection{Semi-tagging}
-\label{sect:semi-tagging}
+\Subsection{Semi-tagging}{semi-tagging}
 
 When a @case@ expression evaluates a variable that might be bound
 to a thunk it is often the case that the scrutinee is already evaluated.
@@ -3931,8 +4329,7 @@ heap check, we will actually have to write the return address before
 entering the garbage collector.
 
 
-\subsection{Heap and Stack Checks}
-\label{sect:heap-and-stack-checks}
+\Subsection{Heap and Stack Checks}{heap-and-stack-checks}
 
 The storage manager detects that it needs to garbage collect the old
 generation when the evaluator requests a garbage collection without
@@ -3968,7 +4365,7 @@ using the fast entry point to guarantee that there is enough space.
 \ToDo{Be more precise about how much space is required - document it
 in the calling convention section.}
 
-\subsection{Handling interrupts/signals}
+\Subsection{Handling interrupts/signals}{signals}
 
 @
 May have to keep C stack pointer in register to placate OS?
@@ -4012,7 +4409,7 @@ running thread should be preempted at the next opportunity.
 \end{itemize}
 
 Each thread is represented by a Thread State Object (TSO), which is
-described in detail in Section \ref{sect:TSO}.
+described in detail in \secref{TSO}.
 
 The following is pseudo-code for the inner loop of the scheduler
 itself.
@@ -4044,10 +4441,11 @@ while (threads_exist) {
 }
 @
 
-\subsection{Invoking the garbage collector}
-\subsection{Putting the thread to sleep}
+\Subsection{Invoking the garbage collector}{ghc-invoking-gc}
+
+\Subsection{Putting the thread to sleep}{ghc-thread-sleeps}
 
-\subsection{Calling C from Haskell}
+\Subsection{Calling C from Haskell}{ghc-ccall}
 
 We distinguish between "safe calls" where the programmer guarantees
 that the C function will not call a Haskell function or, in a
@@ -4068,7 +4466,7 @@ runnable threads list.
 \ToDo{Describe this in more detail.}
 
 
-\subsection{Calling Haskell from C}
+\Subsection{Calling Haskell from C}{ghc-c-calls-haskell}
 
 When C calls a Haskell closure, it sends a message to the scheduler
 thread.  On receiving the message, the scheduler creates a new Haskell
@@ -4083,8 +4481,7 @@ awakens the (C) thread.
 \ToDo{Do we need to worry about the garbage collector deallocating the
 thread if it gets blocked?}
 
-\subsection{Switching Worlds}
-\label{sect:switching-worlds}
+\Subsection{Switching Worlds}{switching-worlds}
 
 \ToDo{This has all changed: we always leave a closure on top of the
 stack if we mean to continue executing it.  The scheduler examines the
@@ -4100,7 +4497,7 @@ interpreter will sometimes encounter compiled code, and vice-versa.
 All world-switches go via the scheduler, ensuring that the world is in
 a known state ready to enter either compiled code or the interpreter.
 When a thread is run from the scheduler, the @whatNext@ field in the
-TSO (Section \ref{sect:TSO}) is checked to find out how to execute the
+TSO (\secref{TSO}) is checked to find out how to execute the
 thread.
 
 \begin{itemize}
@@ -4134,7 +4531,7 @@ We now examine the various cases one by one and describe how the
 switch happens in each situation.
 
 \subsection{A GHC thread enters a Hugs-built closure}
-\label{sect:ghc-to-hugs-switch}
+\label{sec:ghc-to-hugs-switch}
 
 There is three possibilities: GHC has entered a @PAP@, or it has
 entered a @AP@, or it has entered the BCO directly (for a top-level
@@ -4154,12 +4551,12 @@ slow entry points: they expect to find their arguments on the stac
 with unboxed arguments preceded by appropriate tags.
 
 \subsection{A GHC thread returns to a Hugs-compiled return address}
-\label{sect:ghc-to-hugs-switch}
+\label{sec:ghc-to-hugs-switch}
 
-Hugs return addresses are laid out as in Figure
-\ref{fig:hugs-return-stack}.  If GHC is returning, it will return to
-the address at the top of the stack, namely @HUGS_RET@.  The code at
-@HUGS_RET@ performs the following:
+Hugs return addresses are laid out as in \figref{hugs-return-stack}.
+If GHC is returning, it will return to the address at the top of the
+stack, namely @HUGS_RET@.  The code at @HUGS_RET@ performs the
+following:
 
 \begin{itemize}
 \item pushes \Arg{1} (the return value) on the stack.
@@ -4168,12 +4565,12 @@ the address at the top of the stack, namely @HUGS_RET@.  The code at
 \end{itemize}
 
 \noindent When Hugs runs, it will enter the return value, which will
-return using the correct Hugs convention (Section
-\ref{sect:hugs-return-convention}) to the return address underneath it
+return using the correct Hugs convention
+(\secref{hugs-return-convention}) to the return address underneath it
 on the stack.
 
 \subsection{A Hugs thread enters a GHC-compiled closure}
-\label{sect:hugs-to-ghc-switch}
+\label{sec:hugs-to-ghc-switch}
 
 Hugs can recognise a GHC-built closure as not being one of the
 following types of object:
@@ -4197,7 +4594,7 @@ following sequence of instructions:
 \end{itemize}
 
 \subsection{A Hugs thread returns to a GHC-compiled return address}
-\label{sect:hugs-to-ghc-switch}
+\label{sec:hugs-to-ghc-switch}
 
 When Hugs encounters a return address on the stack that is not
 @HUGS_RET@, it knows that a world-switch is required.  At this point