diff --git a/mps/code/commpost.nmk b/mps/code/commpost.nmk
index 793ec8e6035..942caf26a01 100644
--- a/mps/code/commpost.nmk
+++ b/mps/code/commpost.nmk
@@ -1,44 +1,21 @@
-# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING MV AND NMAKE
+# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-
#
# $Id$
-# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
#
# DESCRIPTION
#
# Second common makefile fragment for w3*mv.nmk. See commpre.nmk
-# PSEUDO-TARGETS
+# == Pseudo-targets ==
-# "all" builds all the varieties of all targets
-# %%TARGET: When adding a new target, add it to the all dependencies.
-
-all: mpmss.exe amcss.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe\
- mpsicv.exe lockutw3.exe lockcov.exe poolncv.exe locv.exe qs.exe apss.exe \
- sacss.exe finalcv.exe finaltest.exe \
- arenacv.exe bttest.exe teletest.exe \
- abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \
- locbwcss.exe locusss.exe zcoll.exe zmess.exe \
- mpseventcnv.exe mpseventtxt.exe \
- mps.lib
+all: $(ALL_TARGETS)
# Convenience targets
-# %%TARGET: When adding a new target, add a pseudo-target for it here,
-# first rule for variety-dependent targets, and second for
-# variety-independent ones.
-
-mpmss.exe amcss.exe amcsshe.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe dwstress.exe \
- mpsicv.exe lockutw3.exe lockcov.exe poolncv.exe locv.exe qs.exe apss.exe \
- sacss.exe finalcv.exe finaltest.exe \
- arenacv.exe bttest.exe teletest.exe \
- expt825.exe \
- abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \
- walkt0.exe locbwcss.exe locusss.exe \
- exposet0.exe zcoll.exe zmess.exe \
- replay.exe replaysw.exe mpseventcnv.exe mpseventtxt.exe mpseventsql.exe \
- mps.lib:
+$(ALL_TARGETS):
!IFDEF VARIETY
$(MAKE) /nologo /f $(PFM).nmk TARGET=$@ variety
!ELSE
@@ -79,6 +56,17 @@ variety: $(PFM)\$(VARIETY)\$(TARGET)
mpsicv.cov:
$(MAKE) /nologo /f $(PFM).nmk TARGET=$@ VARIETY=cv variety
+# testrun
+# Runs automated test cases.
+
+testrun: $(AUTO_TEST_TARGETS)
+!IFDEF VARIETY
+ ..\tool\testrun.bat $(PFM) $(VARIETY) $(AUTO_TEST_TARGETS)
+!ELSE
+ $(MAKE) /nologo /f $(PFM).nmk VARIETY=hot testrun
+ $(MAKE) /nologo /f $(PFM).nmk VARIETY=cool testrun
+!ENDIF
+
# THE MPS LIBRARY
#
@@ -133,41 +121,8 @@ $(PFM)\di\mps.lib: \
!IFDEF VARIETY
-$(PFM)\$(VARIETY)\finalcv.exe: $(PFM)\$(VARIETY)\finalcv.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\finaltest.exe: $(PFM)\$(VARIETY)\finaltest.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\expt825.exe: $(PFM)\$(VARIETY)\expt825.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\locv.exe: $(PFM)\$(VARIETY)\locv.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\mpmss.exe: $(PFM)\$(VARIETY)\mpmss.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\apss.exe: $(PFM)\$(VARIETY)\apss.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\sacss.exe: $(PFM)\$(VARIETY)\sacss.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\bttest.exe: $(PFM)\$(VARIETY)\bttest.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\teletest.exe: $(PFM)\$(VARIETY)\teletest.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\lockcov.exe: $(PFM)\$(VARIETY)\lockcov.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\lockutw3.exe: $(PFM)\$(VARIETY)\lockutw3.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\mpsicv.exe: $(PFM)\$(VARIETY)\mpsicv.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+$(PFM)\$(VARIETY)\abqtest.exe: $(PFM)\$(VARIETY)\abqtest.obj \
+ $(PFM)\$(VARIETY)\abq.obj $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
$(PFM)\$(VARIETY)\amcss.exe: $(PFM)\$(VARIETY)\amcss.obj \
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
@@ -175,24 +130,21 @@ $(PFM)\$(VARIETY)\amcss.exe: $(PFM)\$(VARIETY)\amcss.obj \
$(PFM)\$(VARIETY)\amcsshe.exe: $(PFM)\$(VARIETY)\amcsshe.obj \
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+$(PFM)\$(VARIETY)\amcssth.exe: $(PFM)\$(VARIETY)\amcssth.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
$(PFM)\$(VARIETY)\amsss.exe: $(PFM)\$(VARIETY)\amsss.obj \
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
$(PFM)\$(VARIETY)\amssshe.exe: $(PFM)\$(VARIETY)\amssshe.obj \
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\segsmss.exe: $(PFM)\$(VARIETY)\segsmss.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\locbwcss.exe: $(PFM)\$(VARIETY)\locbwcss.obj \
+$(PFM)\$(VARIETY)\apss.exe: $(PFM)\$(VARIETY)\apss.obj \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\locusss.exe: $(PFM)\$(VARIETY)\locusss.obj \
+$(PFM)\$(VARIETY)\arenacv.exe: $(PFM)\$(VARIETY)\arenacv.obj \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\dwstress.exe: $(PFM)\$(VARIETY)\dwstress.obj \
- $(DWOBJ) $(PFM)\$(VARIETY)\mps.lib
-
$(PFM)\$(VARIETY)\awlut.exe: $(PFM)\$(VARIETY)\awlut.obj \
$(FMTTESTOBJ) \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
@@ -201,27 +153,75 @@ $(PFM)\$(VARIETY)\awluthe.exe: $(PFM)\$(VARIETY)\awluthe.obj \
$(FMTTESTOBJ) \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+$(PFM)\$(VARIETY)\btcv.exe: $(PFM)\$(VARIETY)\btcv.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\bttest.exe: $(PFM)\$(VARIETY)\bttest.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\cbstest.exe: $(PFM)\$(VARIETY)\cbstest.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\expt825.exe: $(PFM)\$(VARIETY)\expt825.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\finalcv.exe: $(PFM)\$(VARIETY)\finalcv.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\finaltest.exe: $(PFM)\$(VARIETY)\finaltest.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\locbwcss.exe: $(PFM)\$(VARIETY)\locbwcss.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\lockcov.exe: $(PFM)\$(VARIETY)\lockcov.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\lockutw3.exe: $(PFM)\$(VARIETY)\lockutw3.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\locusss.exe: $(PFM)\$(VARIETY)\locusss.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\locv.exe: $(PFM)\$(VARIETY)\locv.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\messtest.exe: $(PFM)\$(VARIETY)\messtest.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\mpmss.exe: $(PFM)\$(VARIETY)\mpmss.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\mpsicv.exe: $(PFM)\$(VARIETY)\mpsicv.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\mv2test.exe: $(PFM)\$(VARIETY)\mv2test.obj \
+ $(PFM)\$(VARIETY)\poolmv2.obj $(PFM)\$(VARIETY)\abq.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+
$(PFM)\$(VARIETY)\poolncv.exe: $(PFM)\$(VARIETY)\poolncv.obj \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
$(PFM)\$(VARIETY)\qs.exe: $(PFM)\$(VARIETY)\qs.obj \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\arenacv.exe: $(PFM)\$(VARIETY)\arenacv.obj \
+$(PFM)\$(VARIETY)\sacss.exe: $(PFM)\$(VARIETY)\sacss.obj \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\abqtest.exe: $(PFM)\$(VARIETY)\abqtest.obj \
- $(PFM)\$(VARIETY)\abq.obj $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+$(PFM)\$(VARIETY)\segsmss.exe: $(PFM)\$(VARIETY)\segsmss.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\cbstest.exe: $(PFM)\$(VARIETY)\cbstest.obj \
+$(PFM)\$(VARIETY)\steptest.exe: $(PFM)\$(VARIETY)\steptest.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
+
+$(PFM)\$(VARIETY)\teletest.exe: $(PFM)\$(VARIETY)\teletest.obj \
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-$(PFM)\$(VARIETY)\btcv.exe: $(PFM)\$(VARIETY)\btcv.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\mv2test.exe: $(PFM)\$(VARIETY)\mv2test.obj \
- $(PFM)\$(VARIETY)\poolmv2.obj $(PFM)\$(VARIETY)\abq.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
+$(PFM)\$(VARIETY)\walkt0.exe: $(PFM)\$(VARIETY)\walkt0.obj \
+ $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
$(PFM)\$(VARIETY)\zcoll.exe: $(PFM)\$(VARIETY)\zcoll.obj \
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \
@@ -251,18 +251,6 @@ $(PFM)\$(VARIETY)\replaysw.obj: $(PFM)\$(VARIETY)\replay.obj
$(ECHO) $@
copy $** $@ >nul:
-$(PFM)\$(VARIETY)\messtest.exe: $(PFM)\$(VARIETY)\messtest.obj \
- $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\steptest.exe: $(PFM)\$(VARIETY)\steptest.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\walkt0.exe: $(PFM)\$(VARIETY)\walkt0.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
-$(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \
- $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
-
!ENDIF
@@ -307,7 +295,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
# C. COPYRIGHT AND LICENSE
#
-# Copyright (C) 2001-2002 Ravenbrook Limited .
+# Copyright (C) 2001-2013 Ravenbrook Limited .
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#
diff --git a/mps/code/commpre.nmk b/mps/code/commpre.nmk
index 47c66943164..eb49c3259b3 100644
--- a/mps/code/commpre.nmk
+++ b/mps/code/commpre.nmk
@@ -1,4 +1,4 @@
-# commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING MV AND NMAKE
+# commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-1
#
# $Id$
# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
@@ -14,17 +14,22 @@
# %%PART: When adding a new part, add a new parameter for the files included
# in the part
# Parameters:
-# PFM platform code, e.g. "nti3mv"
+# PFM platform code, e.g. "w3i3mv"
# PFMDEFS /D options to define platforms preprocessor symbols
# to the compiler. Eg "/DOS_NT /DARCH_386 /DBUILD_MVC"
-# MPM list of sources which make up the "mpm" part for this
-# platform. Each source is stripped of its .c extension
+# MPMCOMMON list of sources which make up the "mpm" part for all
+# platforms. Each source is stripped of its .c extension
# and surrounded in angle brackets (<>)
+# MPM as above, plus sources for the "mpm" part for the current
+# platform.
# PLINTH as above for the "plinth" part
# AMC as above for the "amc" part
# AMS as above for the "ams" part
# LO as above for the "lo" part
-# MRG as above for the "mrg" part
+# POOLN as above for the "pooln" part
+# SNC as above for the "snc" part
+# DW as above for the "dw" part
+# FMTTEST as above for the "fmttest" part
# TESTLIB as above for the "testlib" part
# NOISY if defined, causes command to be emitted
#
@@ -33,11 +38,75 @@
#
# To add new targets. varieties, and parts:
# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this makefile
-# and follow the instructions. If you're adding a part, you'll have to change
-# the makefile for all the platforms which use this makefile to define the
-# source list for that part.
+# and follow the instructions.
#
+
+# TARGETS
+#
+#
+# %%TARGET: When adding a new target, add it to one of the variables
+# in this section. Library components go in LIB_TARGETS.
+
+LIB_TARGETS=mps.lib
+
+# If it is suitable for running regularly (for example, after every
+# build) as an automated test case, add it to AUTO_TEST_TARGETS.
+
+AUTO_TEST_TARGETS=abqtest.exe amcss.exe amcsshe.exe amsss.exe \
+ amssshe.exe apss.exe arenacv.exe awlut.exe awluthe.exe btcv.exe \
+ cbstest.exe exposet0.exe expt825.exe finalcv.exe finaltest.exe \
+ locbwcss.exe lockcov.exe lockutw3.exe locusss.exe locv.exe \
+ messtest.exe mpmss.exe mpsicv.exe mv2test.exe poolncv.exe qs.exe \
+ sacss.exe segsmss.exe steptest.exe walkt0.exe zmess.exe
+
+# If it is not runnable as an automated test case, but is buildable,
+# add it to OTHER_TEST_TARGETS with a note.
+#
+# bttest and teletest -- interactive and so cannot be run unattended.
+# zcoll -- takes too long to be useful as a regularly run smoke test.
+
+OTHER_TEST_TARGETS=bttest.exe teletest.exe zcoll.exe
+
+# Stand-alone programs go in EXTRA_TARGETS.
+
+EXTRA_TARGETS=mpseventcnv.exe mpseventtxt.exe
+
+# This target records programs that we were once able to build but
+# can't at the moment:
+#
+# replay -- depends on the EPVM pool.
+
+UNBUILDABLE_TARGETS=replay.exe
+
+ALL_TARGETS=$(LIB_TARGETS) $(AUTO_TEST_TARGETS) $(OTHER_TEST_TARGETS) $(EXTRA_TARGETS)
+
+
+# PARAMETERS
+#
+#
+# %%PART: When adding a new part, add the sources for the new part here.
+
+MPMCOMMON = \
+ \
+ \
+ \
+ [ \
+ ] \
+
+PLINTH =
+AMC =
+AMS =
+AWL =
+LO =
+MVFF =
+POOLN =
+SNC =
+DW =
+FMTTEST =
+TESTLIB =
+
+
# CHECK PARAMETERS
#
#
@@ -50,8 +119,8 @@
!IFNDEF PFMDEFS
!ERROR commpre.nmk: PFMDEFS not defined
!ENDIF
-!IFNDEF MPM
-!ERROR commpre.nmk: MPM not defined
+!IFNDEF MPMCOMMON
+!ERROR commpre.nmk: MPMCOMMON not defined
!ENDIF
!IFNDEF PLINTH
!ERROR commpre.nmk: PLINTH not defined
@@ -166,7 +235,7 @@ LIBFLAGSCOOL =
# C. COPYRIGHT AND LICENSE
#
-# Copyright (C) 2001-2002 Ravenbrook Limited .
+# Copyright (C) 2001-2013 Ravenbrook Limited .
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#
diff --git a/mps/code/mpm.c b/mps/code/mpm.c
index 4623ca7fad6..04195a859dd 100644
--- a/mps/code/mpm.c
+++ b/mps/code/mpm.c
@@ -493,7 +493,9 @@ Res WriteF_firstformat_v(mps_lib_FILE *stream,
case 'F': { /* function */
WriteFF f = va_arg(args, WriteFF);
Byte *b = (Byte *)&f;
- /* TODO: Why do we always write these little-endian? */
+ /* ISO C forbits casting function pointers to integer, so
+ decode bytes (see design.writef.f).
+ TODO: Be smarter about endianness. */
for(i=0; i < sizeof(WriteFF); i++) {
res = WriteULongest(stream, (ULongest)(b[i]), 16,
(CHAR_BIT + 3) / 4);
diff --git a/mps/code/w3i3mv.nmk b/mps/code/w3i3mv.nmk
index 6de2c80db0d..49852582f61 100644
--- a/mps/code/w3i3mv.nmk
+++ b/mps/code/w3i3mv.nmk
@@ -1,7 +1,7 @@
-# w3i3mv.nmk: WINDOWS (INTEL) NMAKE FILE
+# w3i3mv.nmk: WINDOWS (IA-32) NMAKE FILE -*- makefile -*-
#
# $Id$
-# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
PFM = w3i3mv
@@ -11,31 +11,12 @@ PFM = w3i3mv
PFMDEFS = /DCONFIG_PF_STRING="w3i3mv" /DCONFIG_PF_W3I3MV \
/DWIN32 /D_WINDOWS /Gs
-MPM = \
- \
- \
- \
- [ \
- ] \
- \
- \
-
-PLINTH =
-AMC =
-AMS =
-AWL =
-LO =
-SNC =
-MVFF =
-N =
-DW =
-FMTTEST =
-POOLN =
-TESTLIB =
-
-
!INCLUDE commpre.nmk
+# MPM sources: core plus platform-specific.
+MPM = $(MPMCOMMON)
+
+
# Source to object file mappings and CFLAGS amalgamation
#
@@ -187,7 +168,7 @@ TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj)
# C. COPYRIGHT AND LICENSE
#
-# Copyright (C) 2001-2002 Ravenbrook Limited .
+# Copyright (C) 2001-2013 Ravenbrook Limited .
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#
diff --git a/mps/code/w3i6mv.nmk b/mps/code/w3i6mv.nmk
index ad238b05284..7df37c29172 100644
--- a/mps/code/w3i6mv.nmk
+++ b/mps/code/w3i6mv.nmk
@@ -1,7 +1,7 @@
-# w3i6mv.nmk: WINDOWS (x64) NMAKE FILE
+# w3i6mv.nmk: WINDOWS (x86-64) NMAKE FILE -*- makefile -*-
#
# $Id$
-# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
PFM = w3i6mv
@@ -12,26 +12,8 @@ PFMDEFS = /DCONFIG_PF_STRING="w3i6mv" /DCONFIG_PF_W3I6MV \
/DWIN32 /D_WINDOWS /Gs
MASM = ml64
-MPM = \
- \
- \
- \
- [ \
- ] \
- \
- \
-
-PLINTH =
-AMC =
-AMS =
-AWL =
-LO =
-SNC =
-MVFF =
-DW =
-FMTTEST =
-POOLN =
-TESTLIB =
+# MPM sources: core plus platform-specific.
+MPM = $(MPMCOMMON)
!INCLUDE commpre.nmk
@@ -187,7 +169,7 @@ TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj)
# C. COPYRIGHT AND LICENSE
#
-# Copyright (C) 2001-2002 Ravenbrook Limited .
+# Copyright (C) 2001-2013 Ravenbrook Limited .
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#
diff --git a/mps/design/alloc-frame.txt b/mps/design/alloc-frame.txt
index 9e8c46544b4..f4e19d977d3 100644
--- a/mps/design/alloc-frame.txt
+++ b/mps/design/alloc-frame.txt
@@ -9,6 +9,7 @@ Allocation frame protocol
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: allocation frames; design
Introduction
@@ -252,8 +253,7 @@ the ``SelectFrameOfAddr()`` operation.
_`.fn.client.in-frame`: This function is used by clients to invoke the
``AddrInFrame()`` operation.
-``mps_res_t mps_ap_set_frame_class(mps_ap_t buf, mps_frame_class_t
-class)``
+``mps_res_t mps_ap_set_frame_class(mps_ap_t buf, mps_frame_class_t class)``
_`.fn.client.set`: This function is used by clients to invoke the
``SetFrameClass()`` operation.
diff --git a/mps/design/arena.txt b/mps/design/arena.txt
index 38bdb52542d..7560a5a358d 100644
--- a/mps/design/arena.txt
+++ b/mps/design/arena.txt
@@ -9,6 +9,7 @@ Arena
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: arena; design
Introduction
diff --git a/mps/design/arenavm.txt b/mps/design/arenavm.txt
index 6de3f2e2331..85eb6c9ea3b 100644
--- a/mps/design/arenavm.txt
+++ b/mps/design/arenavm.txt
@@ -9,7 +9,9 @@ Virtual Memory Arena
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
-
+:Index terms:
+ pair: virtual memory arena; design
+ pair: VM arena; design
Introduction
diff --git a/mps/design/bt.txt b/mps/design/bt.txt
index a6d734376dd..21894893ee6 100644
--- a/mps/design/bt.txt
+++ b/mps/design/bt.txt
@@ -9,6 +9,7 @@ Bit tables
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: bit tables; design
Introduction
diff --git a/mps/design/buffer.txt b/mps/design/buffer.txt
index 78dbcfa97af..6c4d35f5f5f 100644
--- a/mps/design/buffer.txt
+++ b/mps/design/buffer.txt
@@ -9,6 +9,7 @@ Allocation buffers and allocation points
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: buffers; design
Introduction
diff --git a/mps/design/check.txt b/mps/design/check.txt
index a470cce775f..b044e87b6df 100644
--- a/mps/design/check.txt
+++ b/mps/design/check.txt
@@ -9,6 +9,7 @@ Checking
:Status: incomplete design
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
+:Index terms: pair: checking; design
Introduction
diff --git a/mps/design/class-interface.txt b/mps/design/class-interface.txt
index d130f7ab8fb..20c2b2f649e 100644
--- a/mps/design/class-interface.txt
+++ b/mps/design/class-interface.txt
@@ -9,6 +9,7 @@ Pool class interface
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: class interface; design
Introduction
diff --git a/mps/design/collection.txt b/mps/design/collection.txt
index 973a8c0f722..75b41629020 100644
--- a/mps/design/collection.txt
+++ b/mps/design/collection.txt
@@ -9,6 +9,7 @@ Collection framework
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: collection framework; design
Introduction
diff --git a/mps/design/config.txt b/mps/design/config.txt
index 693ffa93249..404db4c6206 100644
--- a/mps/design/config.txt
+++ b/mps/design/config.txt
@@ -9,6 +9,7 @@ MPS Configuration
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: configuration; design
Introduction
@@ -57,6 +58,7 @@ variety-reform_ branch. Client-specific customisation of the MPS will
be handled in source control, while the MPS source remains generic, to
reduce costs and increase reliability. See [RB_2012-09-13]_.
+.. _variety-reform: /project/mps/branch/2012-08-15/variety-reform
Definitions
diff --git a/mps/design/critical-path.txt b/mps/design/critical-path.txt
index 505200735c8..6d76dc82991 100644
--- a/mps/design/critical-path.txt
+++ b/mps/design/critical-path.txt
@@ -8,6 +8,10 @@ The critical path through the MPS
:Date: 2012-09-07
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
+:Index terms:
+ single: critical path
+ single: path; critical
+ single: Memory Pool System; critical path
Introduction
diff --git a/mps/design/diag.txt b/mps/design/diag.txt
index 0f3a84aeebe..cbc2e2ddfbd 100644
--- a/mps/design/diag.txt
+++ b/mps/design/diag.txt
@@ -9,6 +9,7 @@ Diagnostic feedback
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: diagnostic feedback; design
Introduction
diff --git a/mps/design/finalize.txt b/mps/design/finalize.txt
index f299a9a8f29..52e5ebbc651 100644
--- a/mps/design/finalize.txt
+++ b/mps/design/finalize.txt
@@ -9,6 +9,7 @@ Finalization
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: finalization; design
Overview
diff --git a/mps/design/fix.txt b/mps/design/fix.txt
index a48ac477b2b..8f11f5ea2be 100644
--- a/mps/design/fix.txt
+++ b/mps/design/fix.txt
@@ -9,6 +9,7 @@ The generic fix function
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: fix function; design
Introduction
diff --git a/mps/design/guide.hex.trans.txt b/mps/design/guide.hex.trans.txt
index 6e8777b8f0b..4664b4adcad 100644
--- a/mps/design/guide.hex.trans.txt
+++ b/mps/design/guide.hex.trans.txt
@@ -10,6 +10,7 @@ Transliterating the alphabet into hexadecimal
:Date: 1997-04-11
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
+:Index terms: pair: hexadecimal; transliterating
Introduction
diff --git a/mps/design/guide.impl.c.format.txt b/mps/design/guide.impl.c.format.txt
index 18ebb1badd1..50cfe34a4f5 100644
--- a/mps/design/guide.impl.c.format.txt
+++ b/mps/design/guide.impl.c.format.txt
@@ -10,6 +10,9 @@ C Style -- formatting
:Format: rst
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: C language; formatting guide
+ pair: C language formatting; guide
Introduction
diff --git a/mps/design/interface-c.txt b/mps/design/interface-c.txt
index ce94aa5fd56..fce695d4847 100644
--- a/mps/design/interface-c.txt
+++ b/mps/design/interface-c.txt
@@ -9,6 +9,7 @@ C interface design
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: C interface; design
Introduction
diff --git a/mps/design/io.txt b/mps/design/io.txt
index 8263e610144..f909b0fe6b2 100644
--- a/mps/design/io.txt
+++ b/mps/design/io.txt
@@ -9,6 +9,7 @@ I/O subsystem
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: I/O subsystem; design
Introduction
diff --git a/mps/design/keyword-arguments.txt b/mps/design/keyword-arguments.txt
index 2adb02b59c3..3549d6fabb7 100644
--- a/mps/design/keyword-arguments.txt
+++ b/mps/design/keyword-arguments.txt
@@ -8,6 +8,7 @@ Keyword arguments in the MPS
:Date: 2013-05-09
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: keyword arguments; design
Introduction
diff --git a/mps/design/lib.txt b/mps/design/lib.txt
index d1e2a793b50..f7d651189d6 100644
--- a/mps/design/lib.txt
+++ b/mps/design/lib.txt
@@ -9,6 +9,7 @@ Library interface
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: library interface; design
Introduction
diff --git a/mps/design/lock.txt b/mps/design/lock.txt
index df81d9f7c82..6b2001c124f 100644
--- a/mps/design/lock.txt
+++ b/mps/design/lock.txt
@@ -9,6 +9,7 @@ The lock module
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: locking; design
Purpose
diff --git a/mps/design/locus.txt b/mps/design/locus.txt
index 89260ae4b35..7975d4fefda 100644
--- a/mps/design/locus.txt
+++ b/mps/design/locus.txt
@@ -9,6 +9,7 @@ MPS Configuration
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: locus manager; design
Introduction
@@ -323,8 +324,7 @@ details, see implementation section and code, or user doc.
Loci
....
-``Res LocusCreate(Locus *locusReturn, LocusAttrs attrs, ZoneGroup zg,
-LocusAllocDesc adesc)``
+``Res LocusCreate(Locus *locusReturn, LocusAttrs attrs, ZoneGroup zg, LocusAllocDesc adesc)``
_`.function.create`: A function to create a locus: ``adesc`` contains
the information about the allocation sequences in the locus, ``zg`` is
diff --git a/mps/design/message-gc.txt b/mps/design/message-gc.txt
index 4a1f4fa7ded..e9682614649 100644
--- a/mps/design/message-gc.txt
+++ b/mps/design/message-gc.txt
@@ -9,6 +9,7 @@ GC messages
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: garbage collection messages; design
Introduction
diff --git a/mps/design/message.txt b/mps/design/message.txt
index 5b7026c10a8..7bf84004a1c 100644
--- a/mps/design/message.txt
+++ b/mps/design/message.txt
@@ -9,6 +9,9 @@ Client message protocol
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: messages; design
+ single: client message protocol
Introduction
diff --git a/mps/design/object-debug.txt b/mps/design/object-debug.txt
index 126f1b69d3a..1e596e53b5a 100644
--- a/mps/design/object-debug.txt
+++ b/mps/design/object-debug.txt
@@ -9,6 +9,7 @@ Debugging features for client objects
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: debugging; design
Introduction
diff --git a/mps/design/pool.txt b/mps/design/pool.txt
index aca58a3be2b..2db6f5422ee 100644
--- a/mps/design/pool.txt
+++ b/mps/design/pool.txt
@@ -9,6 +9,7 @@ Pool and pool class mechanisms
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: pool class mechanism; design
Definitions
diff --git a/mps/design/poolamc.txt b/mps/design/poolamc.txt
index 4023e8be978..5d89e8c298f 100644
--- a/mps/design/poolamc.txt
+++ b/mps/design/poolamc.txt
@@ -9,6 +9,9 @@ AMC pool class
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: AMC pool class; design
+ single: pool class; AMC design
Introduction
diff --git a/mps/design/poolams.txt b/mps/design/poolams.txt
index 62423359b6f..a30b829b185 100644
--- a/mps/design/poolams.txt
+++ b/mps/design/poolams.txt
@@ -9,6 +9,9 @@ AMS pool class
:Status: draft design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: AMS pool class; design
+ single: pool class; AMS design
Introduction
diff --git a/mps/design/poolawl.txt b/mps/design/poolawl.txt
index c1320244414..3b1dfd80dc3 100644
--- a/mps/design/poolawl.txt
+++ b/mps/design/poolawl.txt
@@ -9,6 +9,9 @@ AWL pool class
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: AWL pool class; design
+ single: pool class; AWL design
Introduction
diff --git a/mps/design/poollo.txt b/mps/design/poollo.txt
index a1d7f14861f..1ef448dd739 100644
--- a/mps/design/poollo.txt
+++ b/mps/design/poollo.txt
@@ -9,6 +9,9 @@ LO pool class
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: LO pool class; design
+ single: pool class; LO design
Introduction
diff --git a/mps/design/poolmfs.txt b/mps/design/poolmfs.txt
index 8a00ee706c9..846bcfce924 100644
--- a/mps/design/poolmfs.txt
+++ b/mps/design/poolmfs.txt
@@ -9,6 +9,9 @@ MFS pool class
:Status: Incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: MFS pool class; design
+ single: pool class; MFS design
Overview
diff --git a/mps/design/poolmrg.txt b/mps/design/poolmrg.txt
index 9425739dfae..24646dc284d 100644
--- a/mps/design/poolmrg.txt
+++ b/mps/design/poolmrg.txt
@@ -9,6 +9,9 @@ MRG pool class
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: MRG pool class; design
+ single: pool class; MRG design
Introduction
diff --git a/mps/design/poolmvff.txt b/mps/design/poolmvff.txt
index 366b9b9c810..4edf4c9b788 100644
--- a/mps/design/poolmvff.txt
+++ b/mps/design/poolmvff.txt
@@ -9,6 +9,9 @@ MVFF pool class
:Organization: Harlequin
:Status: incomplete doc
:Revision: $Id$
+:Index terms:
+ pair: MVFF pool class; design
+ single: pool class; MVFF design
Introduction
@@ -50,11 +53,11 @@ Methods
_`.method`: The MVFF pool supports the following methods:
-``Res MVFFInit(Pool pool, va_list arg)``
+``Res MVFFInit(Pool pool, Args arg)``
_`.method.init`: This takes six `keyword arguments`_:
-.. _`keyword arguments`: keyword-arguments.rst
+.. _`keyword arguments`: keyword-arguments
================================== ============================================
Keyword argument Description
@@ -117,6 +120,7 @@ Implementation
--------------
_`.impl.free-list`: The pool stores its free list in a CBS (see
+//gdr-peewit/info.ravenbrook.com/project/mps/branch/2013-05-17/emergency/design/poolmvff.txt
`design.mps.cbs `_), failing over in emergencies to a Freelist
(see design.mps.freelist) when the CBS cannot allocate new control
structures. This is the reason for the alignment restriction above.
@@ -131,7 +135,9 @@ object size (in both cases we align up).
_`.design.seg-fail`: If allocating a segment fails, we try again with
a segment size just large enough for the object we're allocating. This
-is in response to request.mps.170186.
+is in response to `request.mps.170186`_.
+
+.. _`request.mps.170186`: https://info.ravenbrook.com/project/mps/import/2001-11-05/mmprevol/request/mps/170186/
Document History
diff --git a/mps/design/prot.txt b/mps/design/prot.txt
index c7af5787d6e..e845de71f69 100644
--- a/mps/design/prot.txt
+++ b/mps/design/prot.txt
@@ -9,6 +9,7 @@ The protection module
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: protection interface; design
Introduction
diff --git a/mps/design/protan.txt b/mps/design/protan.txt
index 53c9811a0e7..2e76f0e4351 100644
--- a/mps/design/protan.txt
+++ b/mps/design/protan.txt
@@ -9,6 +9,9 @@ ANSI implementation of protection module
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: ANSI; protection interface design
+ pair: ANSI protection interface; design
Introduction
diff --git a/mps/design/protli.txt b/mps/design/protli.txt
index bb40360344b..678239f39ca 100644
--- a/mps/design/protli.txt
+++ b/mps/design/protli.txt
@@ -9,6 +9,9 @@ Linux implementation of protection module
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: Linux; protection interface design
+ pair: Linux protection interface; design
Introduction
diff --git a/mps/design/protocol.txt b/mps/design/protocol.txt
index 55bc76f58e6..ee2ff6f5328 100644
--- a/mps/design/protocol.txt
+++ b/mps/design/protocol.txt
@@ -9,6 +9,7 @@ Protocol inheritance
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: protocol inheritance; design
Introduction
diff --git a/mps/design/protsu.txt b/mps/design/protsu.txt
index e3518c1a2be..971dbdad354 100644
--- a/mps/design/protsu.txt
+++ b/mps/design/protsu.txt
@@ -9,6 +9,10 @@ SunOS 4 protection module
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: SunOS 4; protection interface design
+ pair: SunOS 4 protection interface; design
+
.. warning::
diff --git a/mps/design/pthreadext.txt b/mps/design/pthreadext.txt
index c68bde5ba8e..0f045d01f66 100644
--- a/mps/design/pthreadext.txt
+++ b/mps/design/pthreadext.txt
@@ -9,6 +9,7 @@ POSIX thread extensions
:Status: Draft document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: POSIX thread extensions; design
Introduction
diff --git a/mps/design/reservoir.txt b/mps/design/reservoir.txt
index 408f6d9d9ee..5f4c0833e12 100644
--- a/mps/design/reservoir.txt
+++ b/mps/design/reservoir.txt
@@ -9,6 +9,7 @@ The low-memory reservoir
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: reservoir; design
Introduction
diff --git a/mps/design/ring.txt b/mps/design/ring.txt
index f2acc49864a..d25b4f952bd 100644
--- a/mps/design/ring.txt
+++ b/mps/design/ring.txt
@@ -9,6 +9,7 @@ Ring data structure
:Status: incomplete design
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
+:Index terms: pair: ring structure; design
Introduction
diff --git a/mps/design/root.txt b/mps/design/root.txt
index 30cc285eed8..078d94f92a3 100644
--- a/mps/design/root.txt
+++ b/mps/design/root.txt
@@ -9,6 +9,7 @@ Root manager
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: root manager; design
Basics
diff --git a/mps/design/scan.txt b/mps/design/scan.txt
index 047eb6371d2..875858b556e 100644
--- a/mps/design/scan.txt
+++ b/mps/design/scan.txt
@@ -9,6 +9,7 @@ The generic scanner
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: generic scanner; design
Summaries
diff --git a/mps/design/seg.txt b/mps/design/seg.txt
index 5e7cdd1e529..ca54b78cec9 100644
--- a/mps/design/seg.txt
+++ b/mps/design/seg.txt
@@ -9,6 +9,7 @@ Segment data structure
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: segments; design
Introduction
diff --git a/mps/design/shield.txt b/mps/design/shield.txt
index 6ac60ecfa58..2d66193d4b0 100644
--- a/mps/design/shield.txt
+++ b/mps/design/shield.txt
@@ -9,6 +9,7 @@ Shield
:Status: incomplete guide
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: shield; design
Introduction
@@ -46,13 +47,13 @@ by MPS).
``void ShieldRaise(Arena arena, Seg seg, AccessSet mode)``
-Prevent the mutator accessing the memory in the specified mode
-(``AccessREAD``, ``AccessWRITE``, or both).
+ Prevent the mutator accessing the memory in the specified mode
+ (``AccessREAD``, ``AccessWRITE``, or both).
``void ShieldLower(Arena arena, Seg seg, AccessSet mode)``
-Allow the mutator to access the memory in the specified mode
-(``AccessREAD``, ``AccessWRITE``, or both).
+ Allow the mutator to access the memory in the specified mode
+ (``AccessREAD``, ``AccessWRITE``, or both).
If the mutator attempts an access that hits a shield, the MPS gets a
barrier hit (in the form of a fault, interrupt, exception), quickly
@@ -65,11 +66,11 @@ this.
``void ShieldSuspend(Arena arena)``
-Stop all registered mutator threads.
+ Stop all registered mutator threads.
``void ShieldResume(Arena arena)``
-Resume all registered mutator threads.
+ Resume all registered mutator threads.
Control of collector access
@@ -108,7 +109,7 @@ calls to ``ShieldExpose()`` on the same segment, as long as each is
balanced by a corresponding ``ShieldCover()`` before ``ShieldLeave()``
is called). A usage count is maintained on each segment in
``seg->depth``: a positive "depth" means a positive number of
-outstanding reasons why the segment must be exposed to the collector.
+outstanding *reasons* why the segment must be exposed to the collector.
When the usage count reaches zero, there is no longer any reason the
segment should be unprotected, and the Shield could re-instate
hardware protection.
@@ -116,14 +117,14 @@ hardware protection.
However, as a performance-improving hysteresis, the Shield defers
re-protection, maintaining a cache of the last ``ShieldCacheSIZE``
times a segment no longer had a reason to be collector-accessible.
-Presence in the cache counts as a 'reason': segments in the cache have
+Presence in the cache counts as a reason: segments in the cache have
``seg->depth`` increased by one. As segments get pushed out of the
-cache, or at ``ShieldLeave()``, this artificial 'reason' is
+cache, or at ``ShieldLeave()``, this artificial reason is
decremented from ``seg->depth``, and (if ``seg->depth`` is now zero)
the deferred reinstatement of hardware protection happens.
So whenever hardware protection is temporarily removed to allow
-collector access, there is a 'nurse' that will ensure this protection
+collector access, there is a *nurse* that will ensure this protection
is re-established: the nurse is either the balancing ``ShieldCover()``
call in collector code, or an entry in the shield cache.
diff --git a/mps/design/sig.txt b/mps/design/sig.txt
index 4013c1bd44c..4953026a44f 100644
--- a/mps/design/sig.txt
+++ b/mps/design/sig.txt
@@ -9,6 +9,9 @@ Signatures in the MPS
:Date: 2013-05-09
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
+:Index terms:
+ pair: structure signatures; design
+ single: signatures
Introduction
@@ -24,13 +27,15 @@ defects early.
Overview
--------
-Signatures are magic numbers which are written into structures when
+Signatures are `magic numbers`_ which are written into structures when
they are created and invalidated (by overwriting with ``SigInvalid``)
when they are destroyed. They provide a limited form of run-time type
checking and dynamic scope checking. They are a simplified form of
"Structure Marking", a technique used in the Multics filesystem
[THVV_1995]_.
+.. _`magic numbers`: http://en.wikipedia.org/wiki/Magic_number_(programming)
+
Definitions
-----------
@@ -54,7 +59,7 @@ This is a 32-bit hex constant, spelled according to guide.hex.trans_::
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEF9811C7340BC6520F3812
-.. _guide.hex.trans: ./guide.hex.trans.txt
+.. _guide.hex.trans: guide.hex.trans
This allows the structure to be recognised when looking at memory in a hex
dump or memory window, or found using memory searches.
@@ -97,10 +102,13 @@ Do not do anything else with signatures. See `.rule.purpose`_.
Checking
--------
The signature is checked in various ways. Every function that takes a
-(pointer to) a signed structure should check its argument using the ``AVERT``
-macro. This macro has different definitions depending on how the MPS is
-compiled. It may simply check the signature directly, or call the full
-checking function for the structure.
+(pointer to) a signed structure should check its argument using the
+``AVERT`` macro. This macro has different definitions depending on how
+the MPS is compiled (see design.mps.config.def.var_). It may simply check
+the signature directly, or call the full checking function for the
+structure.
+
+.. _design.mps.config.def.var: config#def-var
The checking function for the structure should also validate the
signature as its first step using the ``CHECKS()`` macro (see
diff --git a/mps/design/splay.txt b/mps/design/splay.txt
index 1efbd4800be..8f3fa79d459 100644
--- a/mps/design/splay.txt
+++ b/mps/design/splay.txt
@@ -9,6 +9,7 @@ Splay trees
:Status: draft document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: splay trees; design
Introduction
diff --git a/mps/design/sso1al.txt b/mps/design/sso1al.txt
index 0d48f189d20..60f156f902d 100644
--- a/mps/design/sso1al.txt
+++ b/mps/design/sso1al.txt
@@ -9,6 +9,9 @@ Stack scanner for Digital Unix on Alpha
:Status: draft document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: Digital Unix on Alpha stack scanner; design
+ pair: Digital Unix on Alpha; stack scanner design
.. warning::
diff --git a/mps/design/strategy.txt b/mps/design/strategy.txt
new file mode 100644
index 00000000000..a8b94cdd579
--- /dev/null
+++ b/mps/design/strategy.txt
@@ -0,0 +1,462 @@
+.. mode: -*- rst -*-
+
+MPS Strategy
+============
+
+:Tag: design.mps.strategy
+:Author: Nick Barnes
+:Organization: Ravenbrook Limited
+:Date: 2013-06-04
+:Revision: $Id$
+:Copyright: See section `Copyright and License`_.
+
+
+Introduction
+------------
+
+_`.intro` This is the design of collection strategy for the MPS.
+
+_`.readership` MPS developers.
+
+
+Overview
+--------
+
+_`.overview` The MPS uses "strategy" code to make three decisions:
+
+- when to start a collection trace;
+
+- what to condemn;
+
+- how to schedule tracing work.
+
+This document describes the current strategy, identifies some
+weaknesses in it, and outlines some possible future development
+directions.
+
+
+Requirements
+------------
+
+[TODO: source some from req.dylan, or do an up-to-date requirements
+analysis -- NB 2013-03-25]
+
+Garbage collection is a trade-off between time and space: it consumes
+some [CPU] time in order to save some [memory] space. Strategy shifts
+the balance point. A better strategy will take less time to produce
+more space. Examples of good strategy might include:
+
+- choosing segments to condemn which contain high proportions of dead
+ objects;
+
+- starting a trace when a large number of objects have just died;
+
+- doing enough collection soon enough that the client program never
+ suffers low-memory problems;
+
+- using otherwise-idle CPU resources for tracing.
+
+Conversely, it would be bad strategy to do the reverse of each of
+these (condemning live objects; tracing when there's very little
+garbage; not collecting enough; tracing when the client program is
+busy).
+
+Abstracting from these notions, requirements on strategy would
+relate to:
+
+- Maximum pause time and other utilization metrics (for example,
+ bounded mutator utilization, minimum mutator utilization, total MPS
+ CPU usage);
+
+- Collecting enough garbage (for example: overall heap size;
+ low-memory requirements).
+
+- Allowing client control (for example, client recommendations for
+ collection timing or condemnation).
+
+There are other possible strategy considerations which are so far
+outside the scope of current strategy and MPS design that this
+document disregards them. For example, either inferring or allowing
+the client to specify preferred relative object locations ("this
+object should be kept in the same cache line as that one"), to improve
+cache locality.
+
+Generations
+-----------
+
+The largest part of the current MPS strategy implementation is the
+support for generational GC. Generations are only fully supported for
+AMC (and AMCZ) pools. See under "Non-AMC Pools", below, for more
+information.
+
+Data Structures
+...............
+
+The fundamental structure of generational GC is the ``Chain``,
+which describes a set of generations. A chain is created by client
+code calling ``mps_chain_create()``, specifying the "size" and
+"mortality" for each generation. When creating an AMC pool, the
+client code must specify the chain which will control collections for
+that pool. The same chain may be used for multiple pools.
+
+Each generation in a chain has a ``GenDesc`` structure,
+allocated in an array pointed to from the chain. Each AMC pool has a
+set of ``PoolGen`` structures, one per generation. The PoolGens
+for each generation point to the GenDesc and are linked together in a
+ring on the GenDesc. These structures are (solely?) used to gather
+information for strategy decisions.
+
+The arena has a unique ``GenDesc`` structure, named
+``topGen`` and described in comments as "the dynamic generation"
+(although in fact it is the *least* dynamic generation). Each AMC
+pool has one more PoolGen than there are GenDescs in the chain. The
+extra PoolGen refers to this topGen.
+
+AMC segments have a segment descriptor ``amcSegStruct`` which is
+a ``GCSegStruct`` with two additional fields. One field
+``segTypeP`` is a pointer either to the per-generation per-pool
+``amcGen`` structure (a subclass of ``PoolGen``), or to a
+nailboard (which then points to an amcGen). The other field
+``new`` is a boolean used for keeping track of memory usage for
+strategy reasons (see below under 'Accounting'). The ``amcGen``
+is used for statistics (``->segs``) and forwarding buffers
+(``->forward``).
+
+The AMC pool class only ever allocates a segment in order to fill a
+buffer: either the buffer for a client Allocation Point, or a
+forwarding buffer. In order to support generational collection, there
+is a subclass ``amcBuf`` of ``SegBuf``, with a
+``gen`` field (pointing to a ``amcGen``). So in
+``AMCBufferFill()`` the generation of the new segment can be
+determined.
+
+When an AMC pool is created, these ``amcGen`` and
+``amcBuf`` structures are all created, and the
+``amcBuf->gen`` fields initialized so that the forwarding buffer
+of each amcGen knows that it belongs to the next "older" amcGen (apart
+from the "oldest" amcGen - that which refers to the topGen - whose
+forwarding buffer belongs to itself).
+
+When copying an object in ``AMCFix()``, the object's current
+generation is determined (``amcSegGen()``), and the object is
+copied to that amcGen's forwarding buffer, using the buffer protocol.
+Thus, objects are "promoted" up the chain of generations until they
+end up in the topGen, which is shared between all chains and all
+pools.
+
+For statistics and reporting purposes, when ``STATISTICS`` is
+on, each AMC pool has an array of ``PageRetStruct``s, one per
+trace. This structure has many ``Count`` fields, and is
+intended to help to assess AMC page retention code. See job001811.
+
+Zones
+.....
+
+All collections in the MPS start with condemnation of a complete
+``ZoneSet``. Each generation in each chain has a zoneset
+associated with it (``chain->gen[N].zones``); the condemned
+zoneset is the union of some number of generation's zonesets. It is
+condemned by code in the chain system calling
+``TraceCondemnZones()``. This is either for all chains
+(``ChainCondemnAll()`` called for every chain from
+``traceCondemnAll()``) or for some number of generations in a
+single chain (``ChainCondemnAuto()`` called from
+``TracePoll()``). Note that the condemnation is of every
+automatic-pool segment in any zone in the zoneset. It is not limited
+to the segments actually associated with the condemned generation(s).
+
+An attempt is made to use distinct zonesets for different generations.
+Whenever a segment is allocated (``AMCBufferFill()``), a
+``SegPref`` is created containing the generation number
+(obtained from ``amcBuf->gen->pgen->nr``) and passed to
+``SegAlloc()``. The arena keeps a zoneset for each generation
+number (up to ``VMArenaGenCount``, defined in
+``arenavm.c`` to be ``MPS_WORD_WIDTH/2``), and a
+``freeSet``. The zoneset for each generation number starts out
+empty, and the ``freeSet`` starts out ``ZoneSetUNIV``.
+When a segment is allocated with a ``SegPref`` with a generation
+number, an attempt is made to allocate it in the corresponding zoneset
+(``pagesFindFreeInZones()``). If the zoneset is empty, an
+attempt is made to allocate it in the ``freeSet`` zoneset.
+After it is allocated, the zones it occupies are removed from the
+``freeSet`` and (if there's a generation ``SegPref``)
+added to the zoneset for that generation number.
+
+Note that this zone placement code knows nothing of chains,
+generations, pool classes, etc. It is based solely on the generation
+*number*, so generations with the same number from different chains
+share a zoneset preference for the purpose of placing newly allocated
+segments. Combined with the fact that condemnation is per-zone, this
+effectively means that generations in distinct chains are collected
+together. One consequence of this is that we don't have a very fine
+granularity of control over collection: a garbage collection of all
+chains together is triggered by the most eager chain. There's no way
+for a library or other small part of a client program to arrange
+independent collection of a separate pool or chain.
+
+When ``AMCBufferFill()`` gets the allocated segment back, it
+adds it to the zoneset associated with that generation in the pool's
+controlling chain. Note that a chain's per-generation zonesets, which
+represent the zones in which segments for that generation in that
+chain have been placed, are quite distinct from the arena-wide
+per-generation-number zonesets, which represent the zones in which
+segments for that generation number in any chain have been placed.
+The arena-wide per-generation-number zoneset
+``vmArena->genZoneSet[N]`` is augmented in
+``vmAllocComm()``. The per-chain per-generation zoneset
+``chain->gen[N].zones`` is augmented in
+``PoolGenUpdateZones()``. Neither kind of zoneset can ever
+shrink.
+
+Accounting
+..........
+
+- ``gen[N].mortality``
+
+ - Specified by the client.
+ - TODO: fill in how this is used.
+
+- ``gen[N].capacity``
+
+ - Specified by the client.
+ - TODO: fill in how this is used.
+
+- ``amcSeg->new``
+
+ - TODO: fill this in
+
+- ``pgen->totalSize``:
+
+ - incremented by ``AMCBufferFill()``;
+ - decremented by ``amcReclaimNailed()`` and ``AMCReclaim()``;
+ - added up by ``GenDescTotalSize(gen)``.
+
+- ``pgen->newSize``:
+
+ - incremented by ``AMCBufferFill()`` (*when not ramping*) and ``AMCRampEnd()``;
+ - decremented by ``AMCWhiten()``,
+ - added up by ``GenDescNewSize(gen)``.
+
+- ``gen[N].proflow``:
+
+ - set to 1.0 by ``ChainCreate()``;
+ - ``arena->topGen.proflow`` set to 0.0 by ``LocusInit(arena)``;
+ - *The value of this field is never used*.
+
+
+- ``pgen->newSizeAtCreate``:
+
+ - set by ``traceCopySizes()`` (that is its purpose);
+ - output by ``TraceStartGenDesc_diag()``.
+
+Ramps
+.....
+The intended semantics of ramping are pretty simple. It allows the
+client to advise us of periods of large short-lived allocation on a
+particular AP. Stuff allocated using that AP during its "ramp" will
+probably be dead when the ramp finishes. How the MPS makes use of this
+advice is up to us, but for instance we might segregate those objects,
+collect them less enthusiastically during the ramp and then more
+enthusiastically soon after the ramp finishes. Ramps can nest.
+
+A ramp is entered by calling::
+
+ mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp())
+
+or similar, and left in a similar way.
+
+This is implemented on a per-pool basis, for AMC only (it's ignored by
+the other automatic pools). PoolAMC throws away the identity of the AP
+specified by the client. The implementation is intended to work by
+changing the generational forwarding behaviour, so that there is a "ramp
+generation" - one of the regular AMC generations - which forwards to
+itself if collected during a ramp (instead of promoting to an older
+generation). It also tweaks the strategy calculation code, in a way
+with consequences I am documenting elsewhere.
+
+Right now, the code sets this ramp generation to the last generation
+specified in the pool's "chain": it ordinarily forwards to the
+"after-ramp" generation, which is the "dynamic generation" (i.e. the
+least dynamic generation, i.e. the arena-wide "top generation"). My
+recollection, and some mentions in design/poolamc, suggests that the
+ramp generation used to be chosen differently from this.
+
+So far, it doesn't sound too ghastly, I guess, although the subversion
+of the generational system seems a little daft. Read on....
+
+An AMC pool has a ``rampMode`` (which is really a state of a state
+machine), taking one of five values: OUTSIDE, BEGIN, RAMPING, FINISH,
+and COLLECTING (actually the enum values are called RampX for these
+X). We initialize in OUTSIDE. The pool also has a ``rampCount``,
+which is the ramp nesting depth and is used to allow us to ignore ramp
+transitions other than the outermost. According to design/poolamc,
+there's an invariant (in BEGIN or RAMPING, ``rampCount > 0``; in
+COLLECTING or OUTSIDE, ``rampCount == 0``), but this isn't checked in
+``AMCCheck()`` and in fact is false for COLLECTING (see below).
+
+There is a small set of events causing state machine transitions:
+
+- entering an outermost ramp;
+- leaving an outermost ramp;
+- condemning any segment of a ramp generation (detected in AMCWhiten);
+- reclaiming any AMC segment.
+
+Here's pseudo-code for all the transition events:
+
+Entering an outermost ramp:
+ if not FINISH, go to BEGIN.
+
+Leaving an outermost ramp:
+ if RAMPING, go to FINISH. Otherwise, go to OUTSIDE.
+
+Condemning a ramp generation segment:
+ If BEGIN, go to RAMPING and make the ramp generation forward
+ to itself (detach the forwarding buffer and reset its generation).
+ If FINISH, go to COLLECTING and make the ramp generation
+ forward to the after-ramp generation.
+
+Reclaiming any AMC segment:
+ If COLLECTING:
+ if ``rampCount > 0``, go to BEGIN. Otherwise go to OUTSIDE.
+
+Now, some deductions:
+
+1. When OUTSIDE, the count is always zero, because (a) it starts that
+way, and the only ways to go OUTSIDE are (b) by leaving an outermost
+ramp (count goes to zero) or (c) by reclaiming when the count is zero.
+
+2. When BEGIN, the count is never zero (consider the transitions to
+BEGIN and the transition to zero).
+
+3. When RAMPING, the count is never zero (again consider transitions to
+RAMPING and the transition to zero).
+
+4. When FINISH, the count can be anything (the transition to FINISH has
+zero count, but the Enter transition when FINISH can change that and
+then it can increment to any value).
+
+5. When COLLECTING, the count can be anything (from the previous fact,
+and the transition to COLLECTING).
+
+6. *This is a bug!!* The ramp generation is not always reset (to forward
+to the after-ramp generation). If we get into FINISH and then see
+another ramp before the next condemnation of the ramp generation, we
+will Enter followed by Leave. The Enter will keep us in FINISH, and
+the Leave will take us back to OUTSIDE, skipping the transition to the
+COLLECTING state which is what resets the ramp generation forwarding
+buffer. [TODO: check whether I made an issue and/or fixed it; NB 2013-06-04]
+
+The simplest change to fix this is to change the behaviour of the Leave
+transition, which should only take us OUTSIDE if we are in BEGIN or
+COLLECTING. We should also update design/poolamc to tell the truth, and
+check the invariants, which will be these:
+
+ OUTSIDE => zero
+ BEGIN => non-zero
+ RAMPING => non-zero
+
+A cleverer change might radically rearrange the state machine
+(e.g. reduce the number of states to three) but that would require
+closer design thought and should probably be postponed until we have a
+clearer overall strategy plan.
+
+While I'm writing pseudo-code versions of ramp-related code, I should
+mention this other snippet, which is the only other code relating to
+ramping (these notes are useful when thinking about the broader strategy
+code):
+
+ In ``AMCBufferFill()``, if we're RAMPING, and filling the forwarding
+ buffer of the ramp generation, and the ramp generation is the
+ forwarding buffer's generation, set ``amcSeg->new`` to FALSE. Otherwise,
+ add the segment size to ``poolGen.newSize``.
+
+And since I've now mentioned the ``amcSeg->new`` flag, here are the only
+other uses of that:
+
+- it initializes as TRUE.
+
+- When leaving an outermost ramp, go through all the segments in the
+ pool. Any non-white segment in the rampGen with new set to FALSE has
+ its size added to ``poolGen->newSize`` and gets new set to TRUE.
+
+- in ``AMCWhiten()``, if new is TRUE, the segment size is deducted
+ from ``poolGen.newSize`` and new is set to FALSE.
+
+Non-AMC Pools
+.............
+
+The implementations of AMS, AWL, and LO pool classes are all aware of
+generations (this is necessary because all tracing is driven by the
+generational data structures described above), but do not make use of
+them. For LO and AWL, when a pool is created, a chain with a single
+generation is also created, with size and mortality parameters
+hard-wired into the pool-creation function (LOInit, AWLInit). For
+AMS, a chain is passed as a pool creation parameter into
+``mps_pool_create()``, but this chain must also have only a
+single generation (otherwise ``ResPARAM`` is returned).
+
+Note that these chains are separate from any chain used by an AMC pool
+(except in the trivial case when a single-generation chain is used for
+both AMC and AMS). Note also that these pools do not use or point to
+the ``arena->topGen``, which applies only to AMC.
+
+Non-AMC pools have no support for ramps.
+
+Starting a Trace
+................
+TODO: Why do we start a trace? How do we choose what to condemn?
+
+
+Trace Progress
+..............
+TODO: When do we do some tracing work? How much tracing work do we do?
+
+Document History
+----------------
+- 2013-06-04 NB Checked this in although it's far from complete.
+ Pasted in my 'ramping notes' from email, which mention some bugs
+ which I may have fixed (TODO: check this).
+
+.. _NB: http://www.ravenbrook.com/consultants/nb/
+
+
+Copyright and License
+---------------------
+Copyright © 2013 Ravenbrook Limited. All rights reserved.
+. This is an open source license. Contact
+Ravenbrook for commercial licensing options.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. Redistributions in any form must be accompanied by information on how
+to obtain complete source code for this software and any
+accompanying software that uses this software. The source code must
+either be included in the distribution or be available for no more than
+the cost of distribution plus a nominal fee, and must be freely
+redistributable under reasonable conditions. For an executable file,
+complete source code means the source code for all modules it contains.
+It does not include source code for modules or files that typically
+accompany the major components of the operating system on which the
+executable file runs.
+
+**This software is provided by the copyright holders and contributors
+"as is" and any express or implied warranties, including, but not
+limited to, the implied warranties of merchantability, fitness for a
+particular purpose, or non-infringement, are disclaimed. In no event
+shall the copyright holders and contributors be liable for any direct,
+indirect, incidental, special, exemplary, or consequential damages
+(including, but not limited to, procurement of substitute goods or
+services; loss of use, data, or profits; or business interruption)
+however caused and on any theory of liability, whether in contract,
+strict liability, or tort (including negligence or otherwise) arising in
+any way out of the use of this software, even if advised of the
+possibility of such damage.**
diff --git a/mps/design/telemetry.txt b/mps/design/telemetry.txt
index e930905db79..d829fc73be5 100644
--- a/mps/design/telemetry.txt
+++ b/mps/design/telemetry.txt
@@ -9,6 +9,7 @@ Telemetry
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: telemetry; design
Introduction
diff --git a/mps/design/thread-manager.txt b/mps/design/thread-manager.txt
index d3b78de6a63..70ece6a1548 100644
--- a/mps/design/thread-manager.txt
+++ b/mps/design/thread-manager.txt
@@ -9,6 +9,7 @@ Thread Manager
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: thread manager; design
Purpose
diff --git a/mps/design/thread-safety.txt b/mps/design/thread-safety.txt
index 4d17d8eafd5..8250eca0304 100644
--- a/mps/design/thread-safety.txt
+++ b/mps/design/thread-safety.txt
@@ -9,6 +9,7 @@ Thread safety in the MPS
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: thread safety; design
Introduction
diff --git a/mps/design/trace.txt b/mps/design/trace.txt
index 37557e0a8f9..683bcb4231e 100644
--- a/mps/design/trace.txt
+++ b/mps/design/trace.txt
@@ -9,6 +9,7 @@ Tracer
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: tracer; design
Introduction
diff --git a/mps/design/type.txt b/mps/design/type.txt
index 33e793411e1..eaf99eebaa9 100644
--- a/mps/design/type.txt
+++ b/mps/design/type.txt
@@ -9,6 +9,7 @@ General MPS types
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: general types; design
Introduction
diff --git a/mps/design/version-library.txt b/mps/design/version-library.txt
index 32c3427a4aa..736a9648e5d 100644
--- a/mps/design/version-library.txt
+++ b/mps/design/version-library.txt
@@ -9,6 +9,7 @@ Library version mechanism
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: library version mechanism; design
Introduction
diff --git a/mps/design/version.txt b/mps/design/version.txt
index 61dd3e41c4c..f2854f1ea8f 100644
--- a/mps/design/version.txt
+++ b/mps/design/version.txt
@@ -9,6 +9,9 @@ Software versions
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms:
+ pair: software versions; design
+ single: versions; design
Introduction
diff --git a/mps/design/vm.txt b/mps/design/vm.txt
index 3e75d50bab5..9f5cbb7c255 100644
--- a/mps/design/vm.txt
+++ b/mps/design/vm.txt
@@ -9,6 +9,7 @@ Virtual mapping
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: virtual mapping; design
Introduction
diff --git a/mps/design/vman.txt b/mps/design/vman.txt
index cfccf99cc12..0729cc381d8 100644
--- a/mps/design/vman.txt
+++ b/mps/design/vman.txt
@@ -9,6 +9,8 @@ ANSI fake VM
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: ANSI fake VM; design
+
_`.intro`: The ANSI fake VM is an implementation of the MPS VM
interface (see design.mps.vm) using services provided by the ANSI C
diff --git a/mps/design/vmo1.txt b/mps/design/vmo1.txt
index ca0eb49c083..1ff9fff1071 100644
--- a/mps/design/vmo1.txt
+++ b/mps/design/vmo1.txt
@@ -9,6 +9,8 @@ VM for Digital Unix
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: VM for Digital Unix; design
+
.. warning::
diff --git a/mps/design/vmso.txt b/mps/design/vmso.txt
index 9ec47d0967a..62d32e7f6cf 100644
--- a/mps/design/vmso.txt
+++ b/mps/design/vmso.txt
@@ -9,6 +9,7 @@ VM for Solaris
:Status: incomplete document
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: VM for Solaris; design
.. warning::
diff --git a/mps/design/writef.txt b/mps/design/writef.txt
index 9a346b01e3f..fec4bd72b6e 100644
--- a/mps/design/writef.txt
+++ b/mps/design/writef.txt
@@ -9,6 +9,7 @@ The WriteF function
:Status: incomplete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
+:Index terms: pair: WriteF function; design
Introduction
@@ -82,7 +83,7 @@ Code Bame Type Example rendering
======= =========== ================== ======================================
``$A`` address ``Addr`` ``000000019EF60010``
``$P`` pointer ``void *`` ``000000019EF60100``
-``$F`` function ``void *(*)()`` ``000000019EF60100``
+``$F`` function ``void *(*)()`` ``0001D69E01000000`` (see `.f`_)
``$S`` string ``char *`` ``hello``
``$C`` character ``char`` ``x``
``$W`` word ``ULongest`` ``0000000000109AE0``
@@ -99,10 +100,10 @@ incredible snazzy output engine. We only need it for ``Describe()``
methods and assertion messages. At the moment it's a very simple bit
of code -- let's keep it that way.
-_`.f`: The ``F`` code is used for function pointers. They are
-currently printed as a hexadecimal string of the appropriate length
-for the platform, and may one day be extended to include function name
-lookup.
+_`.f`: The ``F`` code is used for function pointers. ISO C forbids casting
+function pointers to other types, so the bytes of their representation are
+written sequentially, and may have a different endianness to other pointers.
+Could be smarter, or even look up function names, but see `.snazzy`_.
Document History
diff --git a/mps/manual/Makefile b/mps/manual/Makefile
index c4dab7a1b4b..ed3544169ba 100644
--- a/mps/manual/Makefile
+++ b/mps/manual/Makefile
@@ -40,7 +40,8 @@ help:
@echo " tools to install a local copy of the Python tools using virtualenv"
clean:
- -rm -rf $(BUILDDIR)/{changes,devhelp,dirhtml,doctest,doctrees,epub,html,htmlhelp,json,latex,linkcheck,locale,man,pickle,qthelp,singlehtml,texinfo,text,converted}
+ -rm -rf $(BUILDDIR)/{changes,devhelp,dirhtml,doctest,doctrees,epub,html,htmlhelp,json,latex,linkcheck,locale,man,pickle,qthelp,singlehtml,texinfo,text}
+ -find $(BUILDDIR)/source/design -name '*.rst' ! -name 'index.rst' ! -name 'old.rst' -exec rm -f '{}' ';'
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
diff --git a/mps/manual/html/_sources/design/alloc-frame.txt b/mps/manual/html/_sources/design/alloc-frame.txt
new file mode 100644
index 00000000000..9333d6e4414
--- /dev/null
+++ b/mps/manual/html/_sources/design/alloc-frame.txt
@@ -0,0 +1,459 @@
+.. _design-alloc-frame:
+
+
+.. index::
+ pair: allocation frames; design
+
+
+Allocation frame protocol
+=========================
+
+.. mps:prefix:: design.mps.alloc-frame
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document explains the design of the support for
+allocation frames in MPS.
+
+:mps:tag:`readership` This document is intended for any MM developer.
+
+:mps:tag:`overview` Allocation frames are used for implementing stack pools;
+each stack frame corresponds to an allocation frame. Allocation frames
+may also be suitable for implementing other sub-pool groupings, such
+as generations and ramp allocation patterns.
+
+:mps:tag:`overview.ambition` We now believe this to be a design that loses
+too many advantages of stack allocation for questionable gains. The
+requirements are almost entirely based on unanalysed anecdote, instead
+of actual clients.
+
+.. note::
+
+ We plan to supersede this with a stack pool design at some point
+ in the future. Pekka P. Pirinen, 2000-03-09.
+
+
+Definitions
+-----------
+
+:mps:tag:`def.alloc-frame` An allocation frame is a generic name for a
+device which groups objects together with other objects at allocation
+time, and which may have a parent/child relationship with other
+allocation frames.
+
+
+Purpose
+-------
+
+:mps:tag:`purpose.stack-allocation` The allocation frame protocol is
+intended to support efficient memory management for stack allocation,
+that is, the allocation of objects which have dynamic extent.
+
+:mps:tag:`purpose.general` The allocation frame protocol is intended to be
+sufficiently general that it will be useful in supporting other types
+of nested allocation patterns too. For example, it could be used to
+for EPVM-style save and restore, ramp allocation patterns or
+generations.
+
+
+Requirements
+------------
+
+Known requirements
+..................
+
+:mps:tag:`req.stack-alloc` Provide a interface for clients to describe a
+stack allocation pattern, as an alternative to using the control
+stack.
+
+:mps:tag:`req.efficient` Permit an implementation which is comparable in
+efficiency to allocating on the control stack.
+
+:mps:tag:`req.ap` Support allocation via allocation points (APs).
+
+:mps:tag:`req.format` Support the allocation of formatted objects.
+
+:mps:tag:`req.scan` Ensure that objects in allocation frames can participate
+in garbage collection by being scanned.
+
+:mps:tag:`req.fix` Ensure that objects in allocation frames can participate
+in garbage collection by accepting Fix requests.
+
+:mps:tag:`req.condemn` Ensure that objects in allocation frames can
+participate in garbage collection by being condemned.
+
+:mps:tag:`attr.locking` Minimize the synchronization cost for the creation
+and destruction of frames.
+
+
+Proto-requirements
+..................
+
+:mps:tag:`proto-req` The following are possible requirements that might be
+important in the future. The design does not necessarily meet all
+these requirements, but it does consider them all. Each requirement
+either has direct support in the framework, or could be supported with
+future additions to the framework.
+
+:mps:tag:`req.parallels` The allocation frame protocol should provide a
+framework for exploiting the parallels between stack extents,
+generations and "ramps".
+
+:mps:tag:`req.pool-destroy` It should be possible to use allocation frames
+to free all objects in a pool without destroying the pool.
+
+:mps:tag:`req.epvm` It should be possible to implement EPVM-style save and
+restore operations by creating and destroying allocation frames.
+
+:mps:tag:`req.subst` It should be possible to substitute a stack pool with a
+GC-ed pool so that erroneous use of a stack pool can be detected.
+
+:mps:tag:`req.format-extensions` It should be possible for stack pools to
+utilize the same format as any other pool, including debugging formats
+that include fenceposting, etc.
+
+:mps:tag:`req.mis-nest` Should ensure "mis-nested" stacks are safe.
+
+:mps:tag:`req.non-top-level` Should support allocation in the non-top stack
+extent.
+
+:mps:tag:`req.copy-if-necessary` Should ensure that stack pools can support
+"copy-if-necessary" (so that low-level system code can heapify stack
+objects.)
+
+:mps:tag:`req.preserve` When an object is in an allocation frame which is
+being destroyed, it should be possible to preserve that object in the
+parent frame.
+
+:mps:tag:`req.contained` Should allow clients to ask if an object is
+"contained" in a frame. The object is contained in a frame if it is
+affected when the frame is ended.
+
+:mps:tag:`req.alloc-with-other` Should allow clients to allocate an object
+in the same frame as another object.
+
+
+Overview
+--------
+
+:mps:tag:`frame-classes` The protocol supports different types of allocation
+frames, which are represented as "frame classes". It's up to pools to
+determine which classes of allocation frames they support. Pools which
+support more than one frame class rely on the client to indicate which
+class is currently of interest. The client indicates this by means of
+an operation which stores the class in the buffer to which the
+allocation point is attached.
+
+:mps:tag:`frame-handles` Allocation frames are described via abstract "frame
+handles". Pools may choose what the representation of a frame handle
+should be. Frame handles are static, and the client need not store
+them in a GC root.
+
+:mps:tag:`lightweight-frames` The design includes an extension to the
+allocation point protocol, which permits the creation and destruction
+of allocation frames without the necessity for claiming the arena
+lock. Such frames are called "lightweight frames".
+
+
+Operations
+----------
+
+:mps:tag:`op.intro` Each operation has both an external (client) interface
+and an internal (MPS) interface. The external function takes an
+allocation point as a parameter, determines which buffer and pool it
+belongs to, and calls the internal function with the buffer and pool
+as parameters.
+
+:mps:tag:`op.obligatory` The following operations are supported on any
+allocation point which supports allocation frames:-
+
+:mps:tag:`operation.push` The :c:func:`PushFrame()` operation creates a new
+allocation frame of the currently chosen frame class, makes this new
+frame the current frame, and returns a handle for the frame.
+
+:mps:tag:`operation.pop` The :c:func:`PopFrame()` operation takes a frame handle
+as a parameter. Some pool classes might insist or assume that this is
+the handle for the current frame. It finds the parent of that frame
+and makes it the current frame. The operation indicates that all
+children of the new current frame contain objects which are likely to
+be dead. The reclaim policy is up to the pool; some classes might
+insist or assume that the objects must be dead, and eagerly free them.
+Note that this might introduce the possibility of leaving dangling
+pointers elsewhere in the arena. If so, it's up to the pool to decide
+what to do about this.
+
+:mps:tag:`op.optional` The following operations are supported for some
+allocation frames, but not all. Pools may choose to support some or
+all of these operations for certain frame classes. An unsupported
+operation will return a failure value:-
+
+:mps:tag:`operation.select` The :c:func:`SelectFrame()` operation takes a frame
+handle as a parameter and makes that frame the current frame. It does
+not indicate that any children of the current frame contain objects
+which are likely to be dead.
+
+:mps:tag:`operation.select-addr` The :c:func:`SelectFrameOfAddr()` operation takes
+an address as a parameter and makes the frame of that address the
+current frame. It does not indicate that any children of the current
+frame contain objects which are likely to be dead.
+
+:mps:tag:`operation.in-frame` The :c:func:`AddrInFrame()` operation determines
+whether the supplied address is the address of an object allocated in
+the supplied frame, or any child of that frame.
+
+:mps:tag:`operation.set` The :c:func:`SetFrameClass()` operation takes a frame
+class and an allocation point as parameters, and makes that the
+current frame class for the allocation point. The next :c:func:`PushFrame()`
+operation will create a new frame of that class.
+
+
+Interface
+---------
+
+External types
+..............
+
+:mps:tag:`type.client.frame-handle` Frame handles are defined as the abstract
+type :c:type:`mps_frame_t`.
+
+.. c:type:: struct mps_frame_class_s *mps_frame_class_t
+
+:mps:tag:`type.client.frame-class` Frame classes are defined as an abstract
+type.
+
+:mps:tag:`type.client.frame-class.access` Clients access frame classes by
+means of dedicated functions for each frame class.
+
+External functions
+..................
+
+:mps:tag:`fn.client.push` :c:func:`mps_ap_frame_push()` is used by clients to
+invoke the :c:func:`PushFrame()` operation. For lightweight frames, this
+might not invoke the corresponding internal function.
+
+:mps:tag:`fn.client.pop` :c:func:`mps_ap_frame_pop()` is used by clients to invoke
+the :c:func:`PopFrame()` operation. For lightweight frames, this might not
+invoke the corresponding internal function.
+
+.. c:function:: mps_res_t mps_ap_frame_select(mps_ap_t buf, mps_frame_t frame)
+
+:mps:tag:`fn.client.select` This following function is used by clients to
+invoke the :c:func:`SelectFrame()` operation.
+
+.. c:function:: mps_res_t mps_ap_frame_select_from_addr(mps_ap_t buf, mps_addr_t addr)
+
+:mps:tag:`fn.client.select-addr` This function is used by clients to invoke
+the :c:func:`SelectFrameOfAddr()` operation.
+
+.. c:function:: mps_res_t mps_ap_addr_in_frame(mps_bool_t *inframe_o, mps_ap_t buf, mps_addr_t *addrref, mps_frame_t frame)
+
+:mps:tag:`fn.client.in-frame` This function is used by clients to invoke the
+:c:func:`AddrInFrame()` operation.
+
+.. c:function:: mps_res_t mps_ap_set_frame_class(mps_ap_t buf, mps_frame_class_t class)
+
+:mps:tag:`fn.client.set` This function is used by clients to invoke the
+:c:func:`SetFrameClass()` operation.
+
+.. c:function:: mps_frame_class_t mps_alloc_frame_class_stack(void)
+
+:mps:tag:`fn.client.stack-frame-class` This function is used by clients to
+access the frame class used for simple stack allocation.
+
+
+Internal types
+..............
+
+.. c:type:: struct AllocFrameStruct *AllocFrame
+
+:mps:tag:`type.frame-handle` Frame handles are defined as an abstract type.
+
+.. c:type:: struct AllocFrameClassStruct *AllocFrameClass
+
+:mps:tag:`type.frame-class` Frame classes are defined as an abstract type.
+
+.. c:type:: Res (*PoolFramePushMethod)(AllocFrame *frameReturn, Pool pool, Buffer buf)
+
+:mps:tag:`fn.push` A pool method of this type is called (if needed) to
+invoke the :c:func:`PushFrame()` operation.
+
+.. c:type:: Res (*PoolFramePopMethod)(Pool pool, Buffer buf, AllocFrame frame)
+
+:mps:tag:`fn.pop` A pool method of this type is called (if needed)
+to invoke the PopFrame operation:
+
+.. c:type:: Res (*PoolFrameSelectMethod)(Pool pool, Buffer buf, AllocFrame frame)
+
+:mps:tag:`fn.select` A pool method of this type is called to invoke the
+:c:func:`SelectFrame()` operation.
+
+.. c:type:: Res (*PoolFrameSelectFromAddrMethod)(Pool pool, Buffer buf, Addr addr)
+
+:mps:tag:`fn.select-addr` A pool method of this type is called to invoke the
+:c:func:`SelectFrameOfAddr()` operation.
+
+.. c:type:: Res (*PoolAddrInFrameMethod)(Bool *inframeReturn, Pool pool, Seg seg, Addr *addrref, AllocFrame frame)
+
+:mps:tag:`fn.in-frame` A pool method of this type is called to invoke the
+:c:func:`AddrInFrame()` operation.
+
+.. c:type:: Res (*PoolSetFrameClassMethod)(Pool pool, Buffer buf, AllocFrameClass class)
+
+:mps:tag:`fn.set` A pool method of this type is called to invoke the
+:c:func:`SetFrameClass()` operation.
+
+
+Lightweight frames
+-------------------
+
+Overview
+........
+
+:mps:tag:`lw-frame.overview` Allocation points provide direct support for
+lightweight frames, and are designed to permit PushFrame and PopFrame
+operations without the need for locking and delegation to the pool
+method. Pools can disable this mechanism for any allocation point, so
+that the pool method is always called. The pool method will be called
+whenever synchronization is required for other reasons (e.g. the
+buffer is tripped).
+
+:mps:tag:`lw-frame.model` Lightweight frames offer direct support for a
+particular model of allocation frame use, whereby the PushFrame
+operation returns the current allocation pointer as a frame handle,
+and the PopFrame operation causes the allocation pointer to be reset
+to the address of the frame handle. This model should be suitable for
+simple stack frames, where more advanced operations like SelectFrame
+are not supported. It may also be suitable for more advanced
+allocation frame models when they are being used simply. The use of a
+complex operation always involves synchronization via locking, and the
+pool may disable lightweight synchronization temporarily at this time.
+
+State
+.....
+
+:mps:tag:`lw-frame.states` Allocation points supporting lightweight frames
+will be in one of the following states:
+
+============ ================================================================
+Valid Indicates that :c:func:`PushFrame()` can be a lightweight
+ operation and need not be synchronized.
+PopPending Indicates that there has been a :c:func:`PopFrame()` operation
+ that the pool must respond to.
+Disabled Indicates that the pool has disabled support for lightweight
+ operations for this AP.
+============ ================================================================
+
+These states are in addition to the state normally held by an AP for
+allocation purposes. An AP will be in the Disabled state at creation.
+
+:mps:tag:`lw-frame.transitions` State transitions happen under the following
+circumstances:
+
+======================= ====================================================
+Valid → PopPending As a result of a client :c:func:`PopFrame()`
+ operation.
+Valid → Disabled At the choice of the pool (for example, when
+ responding to a :c:func:`SelectFrame()` operation).
+PopPending → Valid At the choice of the pool, when processing a
+ :c:func:`PopFrame()`.
+PopPending → Disabled At the choice of the pool, when processing a
+ :c:func:`PopFrame()`.
+Disabled → Valid At the choice of the pool.
+Disabled → Popframe Illegal.
+======================= ====================================================
+
+:mps:tag:`lw-frame.state-impl` Each AP contains 3 additional fields to hold this state::
+
+ mps_addr_t frameptr;
+ mps_bool_t enabled;
+ mps_bool_t lwPopPending;
+
+:mps:tag:`lw-frame.enabled` The ``enabled`` slot holds the following values for
+each state:
+
+========== ==========
+Valid :c:macro:`TRUE`
+PopPending :c:macro:`TRUE`
+Disabled :c:macro:`FALSE`
+========== ==========
+
+:mps:tag:`lw-frame.frameptr` The ``frameptr`` slot holds the following values
+for each state:
+
+========== ============================================
+Valid :c:macro:`NULL`
+PopPending Frame handle for most recently popped frame.
+Disabled :c:macro:`NULL`
+========== ============================================
+
+:mps:tag:`lw-frame.lwPopPending` The ``lwPopPending`` slot holds the
+following values for each state:
+
+========== =========
+Valid :c:macro:`FALSE`
+PopPending :c:macro:`TRUE`
+Disabled :c:macro:`FALSE`
+========== =========
+
+:mps:tag:`lw-frame.state-for-gc` It is not necessary for the tracer, format
+code, pool, or any other part of the GC support in MPS to read either
+of the two additional AP fields in order to scan a segment which
+supports a lightweight allocation frame.
+
+
+Synchronization
+...............
+
+:mps:tag:`lw-frame.sync` The purpose of the design is that mutator may
+access the state of an AP without locking with MPS (via the external
+functions). The design assumes the normal MPS restriction that an
+operation on an AP may only be performed by a single mutator thread at
+a time. Each of the operations on allocation frames counts as an
+operation on an AP.
+
+:mps:tag:`lw-frame.sync.pool` Pools are permitted to read or modify the
+lightweight frame state of an AP only in response to an operation on
+that AP.
+
+:mps:tag:`lw-frame.sync.external` The external functions
+:c:func:`mps_ap_frame_push()` and :c:func:`mps_ap_frame_pop()` are permitted to
+read the values of the ``enabled`` and ``frameptr`` fields for the
+supplied AP without claiming the arena lock. They are permitted to
+modify the ``frameptr`` field if and only if ``enabled == FALSE``.
+
+:mps:tag:`lw-frame.sync.trip` When a buffer trip happens, and the trap
+wasn't set by MPS itself (that is, it wasn't because of a flip or for
+logging), then the buffer code must check whether the AP has state
+PopPending. If it does, the buffer code must call the Pool.
+
+
+Implementation
+..............
+
+:mps:tag:`lw-frame.push` The external :c:func:`PushFrame()` operation
+(:c:func:`mps_ap_frame_push()`) performs the following operations::
+
+ IF (!APIsTrapped(ap) && StateOfFrame(ap) == Valid && ap->init == ap->alloc)
+ *frame_o = ap->init;
+ ELSE
+ WITH_ARENA_LOCK
+ PerformInternalPushFrameOperation(...)
+ END
+ END
+
+:mps:tag:`lw-frame.pop` The external :c:func:`PopFrame()` operation
+(:c:func:`mps_ap_frame_pop()`) performs the following operations::
+
+ IF (StateOfFrame(ap) != Disabled)
+ TrapAP(ap); /* ensure next allocation or push involves the pool */
+ ap->frameptr = frame;
+ ap->lwpopPending = TRUE;
+ ELSE
+ WITH_ARENA_LOCK
+ PerformInternalPopFrameOperation(...)
+ END
+ END
+
+
diff --git a/mps/manual/html/_sources/design/arena.txt b/mps/manual/html/_sources/design/arena.txt
index 6b89e3948c2..c0f671e419d 100644
--- a/mps/manual/html/_sources/design/arena.txt
+++ b/mps/manual/html/_sources/design/arena.txt
@@ -1,6 +1,535 @@
+.. _design-arena:
+
+
.. index::
pair: arena; design
-.. _design-arena:
-.. include:: ../../converted/arena.rst
+Arena
+=====
+
+.. mps:prefix:: design.mps.arena
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This is the design of the arena structure.
+
+:mps:tag:`readership` MPS developers.
+
+
+Overview
+--------
+
+:mps:tag:`overview` The arena serves two purposes. It is a structure that is
+the top-level state of the MPS, and as such contains a lot of fields
+which are considered "global". And it provides raw memory to pools.
+
+An arena belongs to a particular arena class. The class is selected
+when the arena is created. Classes encapsulate both policy (such as
+how pool placement preferences map into actual placement) and
+mechanism (such as where the memory originates: operating system
+virtual memory, client provided, or via malloc). Some behaviour
+(mostly serving the "top-level datastructure" purpose) is implemented
+by generic arena code, and some by arena class code.
+
+
+Definitions
+-----------
+
+:mps:tag:`def.tract` Pools request memory from the arena by calling
+:c:func:`ArenaAlloc()`. This returns a block comprising a contiguous sequence
+of "tracts". A tract has a specific size (also known as the "arena
+alignment", which typically corresponds to the operating system page
+size) and all tracts are aligned to that size. "Tract" is also used
+for the data structure used to manage tracts.
+
+
+Requirements
+------------
+
+.. note::
+
+ Where do these come from? Need to identify and document the
+ sources of requirements so that they are traceable to client
+ requirements. Most of these come from the architectural design
+ (design.mps.architecture) or the fix function design
+ (design.mps.fix). Richard Brooksby, 1995-08-28.
+
+ They were copied from design.mps.arena.vm(1) and edited slightly.
+ David Jones, 1999-06-23.
+
+
+Block management
+................
+
+:mps:tag:`req.fun.block.alloc` The arena must provide allocation of
+contiguous blocks of memory.
+
+:mps:tag:`req.fun.block.free` It must also provide freeing of contiguously
+allocated blocks owned by a pool - whether or not the block was
+allocated via a single request.
+
+:mps:tag:`req.attr.block.size.min` The arena must support management of
+blocks down to the size of the grain (page) provided by the virtual
+mapping interface if a virtual memory interface is being used, or a
+comparable size otherwise.
+
+:mps:tag:`req.attr.block.size.max` It must also support management of blocks
+up to the maximum size allowed by the combination of operating system
+and architecture. This is derived from req.dylan.attr.obj.max (at
+least).
+
+:mps:tag:`req.attr.block.align.min` The alignment of blocks shall not be less
+than :c:macro:`MPS_PF_ALIGN` for the architecture. This is so that pool
+classes can conveniently guarantee pool allocated blocks are aligned
+to :c:macro:`MPS_PF_ALIGN`. (A trivial requirement.)
+
+:mps:tag:`req.attr.block.grain.max` The granularity of allocation shall not
+be more than the grain size provided by the virtual mapping interface.
+
+
+Address translation
+...................
+
+:mps:tag:`req.fun.trans` The arena must provide a translation from any
+address to either an indication that the address is not in any tract
+(if that is so) or the following data associated with the tract
+containing that address:
+
+:mps:tag:`req.fun.trans.pool` The pool that allocated the tract.
+
+:mps:tag:`req.fun.trans.arbitrary` An arbitrary pointer value that the pool
+can associate with the tract at any time.
+
+:mps:tag:`req.fun.trans.white` The tracer whiteness information. That is, a
+bit for each active trace that indicates whether this tract is white
+(contains white objects). This is required so that the "fix" protocol
+can run very quickly.
+
+:mps:tag:`req.attr.trans.time` The translation shall take no more than @@@@
+[something not very large -- drj 1999-06-23]
+
+
+Iteration protocol
+..................
+
+:mps:tag:`req.iter` er, there's a tract iteration protocol which is
+presumably required for some reason?
+
+
+Arena partition
+...............
+
+:mps:tag:`req.fun.set` The arena must provide a method for approximating sets
+of addresses.
+
+:mps:tag:`req.fun.set.time` The determination of membership shall take no
+more than @@@@ [something very small indeed]. (the non-obvious
+solution is refsets)
+
+
+Constraints
+...........
+
+:mps:tag:`req.attr.space.overhead` req.dylan.attr.space.struct implies that
+the arena must limit the space overhead. The arena is not the only
+part that introduces an overhead (pool classes being the next most
+obvious), so multiple parts must cooperate in order to meet the
+ultimate requirements.
+
+:mps:tag:`req.attr.time.overhead` Time overhead constraint?
+
+.. note::
+
+ How can there be a time "overhead" on a necessary component? David
+ Jones, 1999-06-23.
+
+
+Architecture
+------------
+
+Statics
+.......
+
+:mps:tag:`static` There is no higher-level data structure than a arena, so in
+order to support several arenas, we have to have some static data in
+impl.c.arena. See impl.c.arena.static.
+
+:mps:tag:`static.init` All the static data items are initialized when the
+first arena is created.
+
+:mps:tag:`static.serial` ``arenaSerial`` is a static :c:type:`Serial`, containing
+the serial number of the next arena to be created. The serial of any
+existing arena is less than this.
+
+:mps:tag:`static.ring` ``arenaRing`` is the sentinel of the ring of arenas.
+
+:mps:tag:`static.ring.init` ``arenaRingInit`` is a :c:type:`Bool` showing whether
+the ring of arenas has been initialized.
+
+:mps:tag:`static.ring.lock` The ring of arenas has to be locked when
+traversing the ring, to prevent arenas being added or removed. This is
+achieved by using the (non-recursive) global lock facility, provided
+by the lock module.
+
+:mps:tag:`static.check` The statics are checked each time any arena is
+checked.
+
+
+Arena classes
+.............
+
+.. c:type:: mps_arena_s *Arena
+
+:mps:tag:`class` The :c:type:`Arena` data structure is designed to be subclassable
+(see design.mps.protocol(0)). Clients can select what arena class
+they'd like when instantiating one with :c:func:`mps_arena_create()`. The
+arguments to :c:func:`mps_arena_create()` are class-dependent.
+
+:mps:tag:`class.init` However, the generic :c:func:`ArenaInit()` is called from the
+class-specific method, rather than vice versa, because the method is
+responsible for allocating the memory for the arena descriptor and the
+arena lock in the first place. Likewise, :c:func:`ArenaFinish()` is called
+from the finish method.
+
+:mps:tag:`class.fields` The ``alignment`` (for tract allocations) and
+``zoneShift`` (for computing zone sizes and what zone an address is
+in) fields in the arena are the responsibility of the each class, and
+are initialized by the ``init`` method. The responsibility for
+maintaining the ``commitLimit``, ``spareCommitted``, and
+``spareCommitLimit`` fields is shared between the (generic) arena and
+the arena class. ``commitLimit`` (see :mps:ref:`.commit-limit`) is changed by
+the generic arena code, but arena classes are responsible for ensuring
+the semantics. For ``spareCommitted`` and ``spareCommitLimit`` see
+:mps:ref:`.spare-committed` below.
+
+:mps:tag:`class.abstract` The basic arena class (:c:type:`AbstractArenaClass`) is
+abstract and must not be instantiated. It provides little useful
+behaviour, and exists primarily as the root of the tree of arena
+classes. Each concrete class must specialize each of the class method
+fields, with the exception of the describe method (which has a trivial
+implementation) and the ``extend``, ``retract`` and
+``spareCommitExceeded`` methods which have non-callable methods for
+the benefit of arena classes which don't implement these features.
+
+:mps:tag:`class.abstract.null` The abstract class does not provide dummy
+implementations of those methods which must be overridden. Instead
+each abstract method is initialized to :c:macro:`NULL`.
+
+
+Tracts
+......
+
+:mps:tag:`tract` The arena allocation function :c:func:`ArenaAlloc()` allocates a
+block of memory to pools, of a size which is aligned to the arena
+alignment. Each alignment unit (grain) of allocation is represented by
+a tract. Tracts are the hook on which the segment module is
+implemented. Pools which don't use segments may use tracts for
+associating their own data with each allocation grain.
+
+:mps:tag:`tract.structure` The tract structure definition looks like this::
+
+ typedef struct TractStruct { /* Tract structure */
+ Pool pool; /* MUST BE FIRST (design.mps.arena.tract.field.pool) */
+ void *p; /* pointer for use of owning pool */
+ Addr base; /* Base address of the tract */
+ TraceSet white : TRACE_MAX; /* traces for which tract is white */
+ unsigned int hasSeg : 1; /* does tract have a seg in p? */
+ } TractStruct;
+
+:mps:tag:`tract.field.pool` The pool field indicates to which pool the tract
+has been allocated (:mps:ref:`.req.fun.trans.pool`). Tracts are only valid
+when they are allocated to pools. When tracts are not allocated to
+pools, arena classes are free to reuse tract objects in undefined
+ways. A standard technique is for arena class implementations to
+internally describe the objects as a union type of :c:type:`TractStruct` and
+some private representation, and to set the pool field to :c:macro:`NULL`
+when the tract is not allocated. The pool field must come first so
+that the private representation can share a common prefix with
+:c:type:`TractStruct`. This permits arena classes to determine from their
+private representation whether such an object is allocated or not,
+without requiring an extra field.
+
+:mps:tag:`tract.field.p` The ``p`` field is used by pools to associate tracts
+with other data (:mps:ref:`.req.fun.trans.arbitrary`). It's used by the
+segment module to indicate which segment a tract belongs to. If a pool
+doesn't use segments it may use the ``p`` field for its own purposes.
+This field has the non-specific type ``(void *)`` so that pools can
+use it for any purpose.
+
+:mps:tag:`tract.field.hasSeg` The ``hasSeg`` bit-field is a Boolean which
+indicates whether the ``p`` field is being used by the segment module.
+If this field is :c:macro:`TRUE`, then the value of ``p`` is a :c:type:`Seg`.
+``hasSeg`` is typed as an ``unsigned int``, rather than a :c:type:`Bool`.
+This ensures that there won't be sign conversion problems when
+converting the bit-field value.
+
+:mps:tag:`tract.field.base` The base field contains the base address of the
+memory represented by the tract.
+
+:mps:tag:`tract.field.white` The white bit-field indicates for which traces
+the tract is white (:mps:ref:`.req.fun.trans.white`). This information is also
+stored in the segment, but is duplicated here for efficiency during a
+call to ``TraceFix`` (see design.mps.trace.fix).
+
+:mps:tag:`tract.limit` The limit of the tract's memory may be determined by
+adding the arena alignment to the base address.
+
+:mps:tag:`tract.iteration` Iteration over tracts is described in
+design.mps.arena.tract-iter(0).
+
+.. c:function:: Bool TractOfAddr(Tract *tractReturn, Arena arena, Addr addr)
+
+:mps:tag:`tract.if.tractofaddr` The function :c:func:`TractOfAddr()` finds the tract
+corresponding to an address in memory. (See :mps:ref:`.req.fun.trans`.)
+
+If ``addr`` is an address which has been allocated to some pool, then
+:c:func:`TractOfAddr()` returns :c:macro:`TRUE`, and sets ``*tractReturn`` to the
+tract corresponding to that address. Otherwise, it returns :c:macro:`FALSE`.
+This function is similar to :c:func:`TractOfBaseAddr()` (see
+design.mps.arena.tract-iter.if.contig-base) but serves a more general
+purpose and is less efficient.
+
+:mps:tag:`tract.if.TRACT_OF_ADDR` :c:func:`TRACT_OF_ADDR()` is a macro version of
+:c:func:`TractOfAddr()`. It's provided for efficiency during a call to
+:c:func:`TraceFix()` (see design.mps.trace.fix.tractofaddr).
+
+
+Control pool
+............
+
+:mps:tag:`pool` Each arena has a "control pool",
+``arena->controlPoolStruct``, which is used for allocating MPS control
+data structures by calling :c:func:`ControlAlloc()`.
+
+
+Polling
+.......
+
+:mps:tag:`poll` :c:func:`ArenaPoll()` is called "often" by other code (for instance,
+on buffer fill or allocation). It is the entry point for doing tracing
+work. If the polling clock exceeds a set threshold, and we're not
+already doing some tracing work (that is, ``insidePoll`` is not set),
+it calls :c:func:`TracePoll()` on all busy traces.
+
+:mps:tag:`poll.size` The actual clock is ``arena->fillMutatorSize``. This is
+because internal allocation is only significant when copy segments are
+being allocated, and we don't want to have the pause times to shrink
+because of that. There is no current requirement for the trace rate to
+guard against running out of memory.
+
+.. note::
+
+ Clearly it really ought to: we have a requirement to not run out
+ of memory (see req.dylan.prot.fail-alloc, req.dylan.prot.consult),
+ and emergency tracing should not be our only story. David Jones,
+ 1999-06-22.
+
+:c:func:`BufferEmpty()` is not taken into account, because the splinter will
+rarely be useable for allocation and we are wary of the clock running
+backward.
+
+:mps:tag:`poll.clamp` Polling is disabled when the arena is "clamped", in
+which case ``arena->clamped`` is :c:macro:`TRUE`. Clamping the arena prevents
+background tracing work, and further new garbage collections from
+starting. Clamping and releasing are implemented by the :c:func:`ArenaClamp()`
+and :c:func:`ArenaRelease()` methods.
+
+:mps:tag:`poll.park` The arena is "parked" by clamping it, then polling until
+there are no active traces. This finishes all the active collections
+and prevents further collection. Parking is implemented by the
+:c:func:`ArenaPark()` method.
+
+
+Commit limit
+............
+
+:mps:tag:`commit-limit` The arena supports a client configurable "commit
+limit" which is a limit on the total amount of committed memory. The
+generic arena structure contains a field to hold the value of the
+commit limit and the implementation provides two functions for
+manipulating it: :c:func:`ArenaCommitLimit()` to read it, and
+:c:func:`ArenaSetCommitLimit()` to set it. Actually abiding by the contract of
+not committing more memory than the commit limit is left up to the
+individual arena classes.
+
+:mps:tag:`commit-limit.err` When allocation from the arena would otherwise
+succeed but cause the MPS to use more committed memory than specified
+by the commit limit :c:func:`ArenaAlloc()` should refuse the request and
+return ``ResCOMMIT_LIMIT``.
+
+:mps:tag:`commit-limit.err.multi` In the case where an :c:func:`ArenaAlloc()` request
+cannot be fulfilled for more than one reason including exceeding the
+commit limit then class implementations should strive to return a
+result code other than ``ResCOMMIT_LIMIT``. That is,
+``ResCOMMIT_LIMIT`` should only be returned if the *only* reason for
+failing the :c:func:`ArenaAlloc()` request is that the commit limit would be
+exceeded. The client documentation allows implementations to be
+ambiguous with respect to which result code in returned in such a
+situation however.
+
+
+Spare committed (aka "hysteresis")
+..................................
+
+:mps:tag:`spare-committed` See :c:func:`mps_arena_spare_committed()`. The generic
+arena structure contains two fields for the spare committed memory
+fund: ``spareCommitted`` records the total number of spare committed
+bytes; ``spareCommitLimit`` records the limit (set by the user) on the
+amount of spare committed memory. ``spareCommitted`` is modified by
+the arena class but its value is used by the generic arena code. There
+are two uses: a getter function for this value is provided through the
+MPS interface (:c:func:`mps_arena_spare_commit_limit_set()`), and by the
+:c:func:`SetSpareCommitLimit()` function to determine whether the amount of
+spare committed memory needs to be reduced. ``spareCommitLimit`` is
+manipulated by generic arena code, however the associated semantics
+are the responsibility of the class. It is the class's responsibility
+to ensure that it doesn't use more spare committed bytes than the
+value in ``spareCommitLimit``.
+
+:mps:tag:`spare-commit-limit` The function :c:func:`ArenaSetSpareCommitLimit()` sets
+the ``spareCommitLimit`` field. If the limit is set to a value lower
+than the amount of spare committed memory (stored in
+``spareCommitted``) then the class specific function
+``spareCommitExceeded`` is called.
+
+
+Locks
+.....
+
+:mps:tag:`lock.ring` :c:func:`ArenaAccess()` is called when we fault on a barrier.
+The first thing it does is claim the non-recursive global lock to
+protect the arena ring (see design.mps.lock(0)).
+
+:mps:tag:`lock.arena` After the arena ring lock is claimed, :c:func:`ArenaEnter()` is
+called on one or more arenas. This claims the lock for that arena.
+When the correct arena is identified or we run out of arenas, the lock
+on the ring is released.
+
+:mps:tag:`lock.avoid` Deadlocking is avoided as described below:
+
+:mps:tag:`lock.avoid.mps` Firstly we require the MPS not to fault (that is,
+when any of these locks are held by a thread, that thread does not
+fault).
+
+:mps:tag:`lock.avoid.thread` Secondly, we require that in a multi-threaded
+system, memory fault handlers do not suspend threads (although the
+faulting thread will, of course, wait for the fault handler to
+finish).
+
+:mps:tag:`lock.avoid.conflict` Thirdly, we avoid conflicting deadlock between
+the arena and global locks by ensuring we never claim the arena lock
+when the recursive global lock is already held, and we never claim the
+binary global lock when the arena lock is held.
+
+
+Location dependencies
+.....................
+
+:mps:tag:`ld` Location dependencies use fields in the arena to maintain a
+history of summaries of moved objects, and to keep a notion of time,
+so that the staleness of location dependency can be determined.
+
+
+Finalization
+............
+
+:mps:tag:`final` There is a pool which is optionally (and dynamically)
+instantiated to implement finalization. The fields ``finalPool`` and
+``isFinalPool`` are used.
+
+
+Implementation
+--------------
+
+
+Tract cache
+...........
+
+:mps:tag:`tract.cache` When tracts are allocated to pools by :c:func:`ArenaAlloc()`,
+the first tract of the block and it's base address are cached in arena
+fields ``lastTract`` and ``lastTractBase``. The function
+:c:func:`TractOfBaseAddr()` (see design.mps.arena.tract-iter.if.block-base(0))
+checks against these cached values and only calls the class method on
+a cache miss. This optimizes for the common case where a pool
+allocates a block and then iterates over all its tracts (for example,
+to attach them to a segment).
+
+:mps:tag:`tract.uncache` When blocks of memory are freed by pools,
+:c:func:`ArenaFree()` checks to see if the cached value for the most recently
+allocated tract (see :mps:ref:`.tract.cache`) is being freed. If so, the cache
+is invalid, and must be reset. The ``lastTract`` and ``lastTractBase``
+fields are set to :c:macro:`NULL`.
+
+
+Control pool
+............
+
+:mps:tag:`pool.init` The control pool is initialized by a call to
+:c:func:`PoolInit()` during :c:func:`ArenaCreate()`.
+
+:mps:tag:`pool.ready` All the other fields in the arena are made checkable
+before calling :c:func:`PoolInit()`, so :c:func:`PoolInit()` can call
+``ArenaCheck(arena)``. The pool itself is, of course, not checkable,
+so we have a field ``arena->poolReady``, which is false until after
+the return from :c:func:`PoolInit()`. :c:func:`ArenaCheck()` only checks the pool if
+``poolReady``.
+
+
+Traces
+......
+
+:mps:tag:`trace` ``arena->trace[ti]`` is valid if and only if
+``TraceSetIsMember(arena->busyTraces, ti)``.
+
+:mps:tag:`trace.create` Since the arena created by :c:func:`ArenaCreate()` has
+``arena->busyTraces = TraceSetEMPTY``, none of the traces are
+meaningful.
+
+:mps:tag:`trace.invalid` Invalid traces have signature ``SigInvalid``, which
+can be checked.
+
+
+Polling
+.......
+
+:mps:tag:`poll.fields` There are three fields of a arena used for polling:
+``pollThreshold``, ``insidePoll``, and ``clamped`` (see above).
+``pollThreshold`` is the threshold for the next poll: it is set at the
+end of :c:func:`ArenaPoll()` to the current polling time plus
+:c:macro:`ARENA_POLL_MAX`.
+
+
+Location dependencies
+.....................
+
+:mps:tag:`ld.epoch` ``arena->epoch`` is the "current epoch". This is the
+number of 'flips' of traces in the arena since the arena was created.
+From the mutator's point of view locations change atomically at flip.
+
+:mps:tag:`ld.history` ``arena->history`` is an array of :c:macro:`ARENA_LD_LENGTH`
+elements of type ``RefSet``. These are the summaries of moved objects
+since the last :c:macro:`ARENA_LD_LENGTH` epochs. If ``e`` is one of these
+recent epochs, then ::
+
+ arena->history[e % ARENA_LD_LENGTH]
+
+is a summary of (the original locations of) objects moved since epoch
+``e``.
+
+:mps:tag:`ld.prehistory` ``arena->prehistory`` is a ``RefSet`` summarizing
+the original locations of all objects ever moved. When considering
+whether a really old location dependency is stale, it is compared with
+this summary.
+
+
+Roots
+.....
+
+:mps:tag:`root-ring` The arena holds a member of a ring of roots in the
+arena. It holds an incremental serial which is the serial of the next
+root.
+
+
diff --git a/mps/manual/html/_sources/design/arenavm.txt b/mps/manual/html/_sources/design/arenavm.txt
new file mode 100644
index 00000000000..b4f3638928c
--- /dev/null
+++ b/mps/manual/html/_sources/design/arenavm.txt
@@ -0,0 +1,206 @@
+.. _design-arenavm:
+
+
+.. index::
+ pair: virtual memory arena; design
+ pair: VM arena; design
+
+
+Virtual Memory Arena
+====================
+
+.. mps:prefix:: design.mps.arena.vm
+ pair: virtual memory arena; design
+ pair: VM arena; design
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document describes the detailed design of the Virtual
+Memory Arena Class of the Memory Pool System. The VM Arena Class is
+just one class available in the MPS. The generic arena part is
+described in design.mps.arena.
+
+
+Overview
+--------
+
+:mps:tag:`overview` VM arenas provide blocks of memory to all other parts of
+the MPS in the form of "tracts" using the virtual mapping interface
+(design.mps.vm) to the operating system. The VM Arena Class is not
+expected to be provided on platforms that do not have virtual memory
+(like MacOS, os.s7(1)).
+
+:mps:tag:`overview.gc` The VM Arena Class provides some special services on
+these blocks in order to facilitate garbage collection:
+
+:mps:tag:`overview.gc.zone` Allocation of blocks with specific zones. This
+means that the generic fix function (design.mps.fix) can use a fast
+refset test to eliminate references to addresses that are not in the
+condemned set. This assumes that a pool class that uses this placement
+appropriately is being used (such as the generation placement policy
+used by AMC: see design.mps.poolamc(1)) and that the pool selects the
+condemned sets to coincide with zone stripes.
+
+:mps:tag:`overview.gc.tract` A fast translation from addresses to tract.
+(See design.mps.arena.req.fun.trans)
+
+
+Notes
+-----
+
+:mps:tag:`note.refset` Some of this document simply assumes that RefSets
+(see the horribly incomplete design.mps.refset) have been chosen as
+the solution for design.mps.arena.req.fun.set. It's a lot simpler that
+way. Both to write and understand.
+
+
+Requirements
+------------
+
+Most of the requirements are in fact on the generic arena (see
+design.mps.arena.req). However, many of those requirements can only be
+met by a suitable arena class design.
+
+Requirements particular to this arena class:
+
+Placement
+.........
+
+:mps:tag:`req.fun.place` It must be possible for pools to obtain tracts at
+particular addresses. Such addresses shall be declared by the pool
+specifying what refset zones the tracts should lie in and what refset
+zones the tracts should not lie in. It is acceptable for the arena to
+not always honour the request in terms of placement if it has run out
+of suitable addresses.
+
+Arena partition
+...............
+
+:mps:tag:`req.fun.set` See design.mps.arena.req.fun.set. The approximation
+to sets of address must cooperate with the placement mechanism in the
+way required by :mps:ref:`.req.fun.place` (above).
+
+
+Architecture
+------------
+
+:mps:tag:`arch.memory` The underlying memory is obtained from whatever
+Virtual Memory interface (see design.mps.vm). @@@@ Explain why this is
+used.
+
+
+Solution ideas
+--------------
+
+:mps:tag:`idea.grain` Set the arena granularity to the grain provided by the
+virtual mapping module.
+
+:mps:tag:`idea.mem` Get a single large contiguous address area from the
+virtual mapping interface and divide that up.
+
+:mps:tag:`idea.table` Maintain a table with one entry per grain in order to
+provide fast mapping (shift and add) between addresses and table
+entries.
+
+:mps:tag:`idea.table.figure` [missing figure]
+
+:mps:tag:`idea.map` Store the pointers (:mps:ref:`.req.fun.trans`) in the table
+directly for every grain.
+
+:mps:tag:`idea.zones` Partition the managed address space into zones (see
+idea.zones) and provide the set approximation as a reference
+signature.
+
+:mps:tag:`idea.first-fit` Use a simple first-fit allocation policy for
+tracts within each zone (:mps:ref:`.idea.zones`). Store the freelist in the
+table (:mps:ref:`.idea.table`).
+
+:mps:tag:`idea.base` Store information about each contiguous area (allocated
+of free) in the table entry (:mps:ref:`.idea.table`) corresponding to the base
+address of the area.
+
+:mps:tag:`idea.shadow` Use the table (:mps:ref:`.idea.table`) as a "shadow" of the
+operating system's page table. Keep information such as last access,
+protection, etc. in this table, since we can't get at this information
+otherwise.
+
+:mps:tag:`idea.barrier` Use the table (:mps:ref:`.idea.table`) to implement the
+software barrier. Each segment can have a read and/or write barrier
+placed on it by each process. (:mps:tag:`idea.barrier.bits` Store a
+bit-pattern which remembers which process protected what.) This will
+give a fast translation from a barrier-protected address to the
+barrier handler via the process table.
+
+:mps:tag:`idea.demand-table` For a 1 GiB managed address space with a 4 KiB
+page size, the table will have 256K-entries. At, say, four words per
+entry, this is 4 MiB of table. Although this is only an 0.4%, the
+table shouldn't be preallocated or initially it is an infinite
+overhead, and with 1 MiB active, it is a 300% overhead! The address
+space for the table should be reserved, but the pages for it mapped
+and unmapped on demand. By storing the table in a tract, the status of
+the table's pages can be determined by looking at it's own entries in
+itself, and thus the translation lookup (:mps:ref:`.req.fun.trans`) is slowed
+to two lookups rather than one.
+
+:mps:tag:`idea.pool` Make the Arena Manager a pool class. Arena
+initialization becomes pool creation. Tract allocation becomes
+:c:func:`PoolAlloc()`. Other operations become class-specific operations on
+the "arena pool".
+
+
+Data structures
+---------------
+
+:mps:tag:`tables` There are two table data structures: a page table, and an
+alloc table.
+
+:mps:tag:`table.page.map` Each page in the VM has a corresponding page table
+entry.
+
+:mps:tag:`table.page.linear` The table is a linear array of PageStruct
+entries; there is a simple mapping between the index in the table and
+the base address in the VM. Namely:
+
+- index to base address: ``base-address = arena-base + (index * page-size)``
+- base address to index: ``index = (base-address - arena-base) / page-size``
+
+:mps:tag:`table.page.partial` The table is partially mapped on an
+"as-needed" basis. The function :c:func:`unusedTablePages()` identifies
+entirely unused pages occupied by the page table itself (that is,
+those pages of the page table which are occupied by :c:type:`PageStruct`
+objects which all describe free pages). Tract allocation and freeing
+use this function to map and unmap the page table with no hysteresis.
+(There is restriction on the parameters you may pass to
+:c:func:`unusedTablePages()`.)
+
+:mps:tag:`table.page.tract` Each page table entry contains a tract, which is
+only valid if it is allocated to a pool. If it is not allocated to a
+pool, the fields of the tract are used for other purposes. (See
+design.mps.arena.tract.field.pool)
+
+:mps:tag:`table.alloc` The alloc table is a simple bit table (implemented
+using the BT module, design.mps.bt).
+
+:mps:tag:`table.alloc.map` Each page in the VM has a corresponding alloc
+table entry.
+
+:mps:tag:`table.alloc.semantics` The bit in the alloc table is set iff the
+corresponding page is allocated (to a pool).
+
+
+Notes
+-----
+
+:mps:tag:`fig.page` How the pages in the arena area are represented in the
+tables.
+
+[missing figure]
+
+:mps:tag:`fig.count` How a count table can be used to partially map the page
+table, as proposed in request.dylan.170049.sol.map.
+
+[missing figure]
+
+
diff --git a/mps/manual/html/_sources/design/bt.txt b/mps/manual/html/_sources/design/bt.txt
index f8ac21cb720..6690fb5c439 100644
--- a/mps/manual/html/_sources/design/bt.txt
+++ b/mps/manual/html/_sources/design/bt.txt
@@ -1,6 +1,709 @@
+.. _design-bt:
+
+
.. index::
pair: bit tables; design
-.. _design-bt:
-.. include:: ../../converted/bt.rst
+Bit tables
+==========
+
+.. mps:prefix:: design.mps.bt
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This is the design of the Bit Tables module. A Bit Table is a
+linear array of bits. A Bit Table of length *n* is indexed using an
+integer from 0 up to (but not including) *n*. Each bit in a Bit Table
+can hold either the value 0 (aka :c:macro:`FALSE`) or 1 (aka :c:macro:`TRUE`). A
+variety of operations are provided including: set, reset, and
+retrieve, individual bits; set and reset a contiguous range of bits;
+search for a contiguous range of reset bits; making a "negative image"
+copy of a range.
+
+:mps:tag:`readership` MPS developers.
+
+
+Definitions
+-----------
+
+:mps:tag:`def.set` **Set**
+
+ Used as a verb meaning to assign the value 1 or :c:macro:`TRUE` to a bit.
+ Used descriptively to denote a bit containing the value 1. Note 1
+ and :c:macro:`TRUE` are synonyms in MPS C code (see
+ design.mps.type(0).bool.value).
+
+:mps:tag:`def.reset` **Reset**
+
+ Used as a verb meaning to assign the value 0 or :c:macro:`FALSE` to a
+ bit. Used descriptively to denote a bit containing the value 0.
+ Note 0 and :c:macro:`FALSE` are synonyms in MPS C code (see
+ design.mps.type(0).bool.value).
+
+.. note::
+
+ Consider using "fill/empty" or "mark/clear" instead of
+ "set/reset", set/reset is probably a hangover from drj's z80
+ hacking days -- drj 1999-04-26
+
+:mps:tag:`def.bt` **Bit Table**
+
+ A Bit Table is a mapping from [0, *n*) to {0,1} for some *n*,
+ represented as a linear array of bits.
+
+ _`..def.bt.justify`: They are called *bit tables* because a single
+ bit is used to encode whether the image of a particular integer
+ under the map is 0 or 1.
+
+:mps:tag:`def.range` **Range**
+
+ A contiguous sequence of bits in a Bit Table. Ranges are typically
+ specified as a *base*--*limit* pair where the range includes the
+ position specified by the base, but excludes that specified by the
+ limit. The mathematical interval notation for half-open intervals,
+ [*base*, *limit*), is used.
+
+
+
+Requirements
+------------
+
+:mps:tag:`req.bit` The storage for a Bit Table of *n* bits shall take no more
+than a small constant addition to the storage required for *n* bits.
+_`..req.bit.why`: This is so that clients can make some predictions
+about how much storage their algorithms use. A small constant is
+allowed over the minimal for two reasons: inevitable implementation
+overheads (such as only being able to allocate storage in multiples of
+32 bits), extra storage for robustness or speed (such as signature and
+length fields).
+
+:mps:tag:`req.create` A means to create Bit Tables. :mps:tag:`req.create.why` Obvious.
+
+:mps:tag:`req.destroy` A means to destroy Bit Tables. _`.req.destroy.why`
+Obvious.
+
+:mps:tag:`req.ops` The following operations shall be supported:
+
+* :mps:tag:`req.ops.get` **Get**. Get the value of a bit at a specified
+ index.
+
+* :mps:tag:`req.ops.set` **Set**. Set a bit at a specified index.
+
+* :mps:tag:`req.ops.reset` **Reset**. Reset a bit at a specified index.
+
+:mps:tag:`req.ops.minimal.why` Get, Set, Reset, are the minimal operations.
+All possible mappings can be created and inspected using these
+operations.
+
+* :mps:tag:`req.ops.set.range` **SetRange**. Set a range of bits.
+ :mps:tag:`req.ops.set.range.why` It's expected that clients will often want
+ to set a range of bits; providing this operation allows the
+ implementation of the BT module to make the operation efficient.
+
+* :mps:tag:`req.ops.reset.range` **ResetRange**. Reset a range of
+ bits. :mps:tag:`req.ops.reset.range.why` as for SetRange, see
+ :mps:ref:`.req.ops.set.range.why`.
+
+* :mps:tag:`req.ops.test.range.set` **IsSetRange**. Test whether a range
+ of bits are all set. :mps:tag:`req.ops.test.range.set.why` Mostly
+ for checking. For example, often clients will know that a range they
+ are about to reset is currently all set, they can use this operation
+ to assert that fact.
+
+* :mps:tag:`req.ops.test.range.reset` **IsResetRange**. Test whether a
+ range of bits are all reset. _`.req.ops.test.range.reset.why`
+ As for IsSetRange, see :mps:ref:`.req.ops.test.range.set.why`.
+
+* :mps:tag:`req.ops.find` Find a range (which we'll denote [*i*, *j*)) of at
+ least *L* reset bits that lies in a specified subrange of the entire
+ Bit Table. Various find operations are required according to the
+ (additional) properties of the required range:
+
+ * :mps:tag:`req.ops.find.short.low` **FindShortResetRange**. Of all
+ candidate ranges, find the range with least *j* (find the leftmost
+ range that has at least *L* reset bits and return just enough of
+ that). :mps:tag:`req.ops.find.short.low.why` Required by client and VM
+ arenas to allocate segments. The arenas implement definite
+ placement policies (such as lowest addressed segment first) so
+ they need the lowest (or highest) range that will do. It's not
+ currently useful to allocate segments larger than the requested
+ size, so finding a short range is sufficient.
+
+ * :mps:tag:`req.ops.find.short.high` **FindShortResetRangeHigh**. Of all
+ candidate ranges, find the range with greatest *i* (find the
+ rightmost range that has at least *L* reset bits and return just
+ enough of that). :mps:tag:`req.ops.find.short.high.why` Required by arenas
+ to implement a specific segment placement policy (highest
+ addressed segment first).
+
+ * :mps:tag:`req.ops.find.long.low` **FindLongResetRange**. Of all candidate
+ ranges, identify the ranges with least *i* and of those find the
+ one with greatest *j* (find the leftmost range that has at least
+ *L* reset bits and return all of it). _`.req.ops.find.long.low.why`
+ Required by the mark and sweep Pool Classes (AMS, AWL, LO) for
+ allocating objects (filling a buffer). It's more efficient to fill
+ a buffer with as much memory as is conveniently possible. There's
+ no strong reason to find the lowest range but it's bound to have
+ some beneficial (small) cache effect and makes the algorithm more
+ predictable.
+
+ * :mps:tag:`req.ops.find.long.high` **FindLongResetRangeHigh**. Provided,
+ but not required, see :mps:ref:`.non-req.ops.find.long.high`.
+
+* :mps:tag:`req.ops.copy` Copy a range of bits from one Bit Table to another
+ Bit Table. Various copy operations are required:
+
+ * :mps:tag:`req.ops.copy.simple` Copy a range of bits from one Bit Table to
+ the same position in another Bit Table.
+ :mps:tag:`req.ops.copy.simple.why` Required to support copying of the
+ tables for the "low" segment during segment merging and splitting,
+ for pools using tables (for example, ``PoolClassAMS``).
+
+ * :mps:tag:`req.ops.copy.offset` Copy a range of bits from one Bit Table to
+ an offset position in another Bit Table.
+ :mps:tag:`req.ops.copy.offset.why` Required to support copying of the
+ tables for the "high" segment during segment merging and
+ splitting, for pools which support this (currently none, as of
+ 2000-01-17).
+
+ * :mps:tag:`req.ops.copy.invert` Copy a range of bits from one Bit Table to
+ the same position in another Bit Table inverting all the bits in
+ the target copy. :mps:tag:`req.ops.copy.invert.why` Required by colour
+ manipulation code in ``PoolClassAMS`` and ``PoolClassLO``.
+
+:mps:tag:`req.speed` Operations shall take no more than a few memory
+operations per bit manipulated. :mps:tag:`req.speed.why` Any slower
+would be gratuitous.
+
+:mps:tag:`req.speed.fast` The following operations shall be very fast:
+
+* :mps:tag:`req.speed.fast.find.short` FindShortResRange (the
+ operation used to meet :mps:ref:`.req.ops.find.short.low`)
+ FindShortResRangeHigh (the operation used to meet
+ :mps:ref:`.req.ops.find.short.high`).
+
+ :mps:tag:`req.speed.fast.find.short.why` These two are used by the client
+ arena (design.mps.arena.client) and the VM arena
+ (design.mps.arena.vm) for finding segments in page tables. The
+ operation will be used sufficiently often that its speed will
+ noticeably affect the overall speed of the MPS. They will be called
+ with a length equal to the number of pages in a segment. Typical
+ values of this length depend on the pool classes used and their
+ configuration, but we can expect length to be small (1 to 16)
+ usually. We can expect the Bit Table to be populated densely where
+ it is populated at all, that is set bits will tend to be clustered
+ together in subranges.
+
+* :mps:tag:`req.speed.fast.find.long` FindLongResRange (the operation
+ used to meet :mps:ref:`.req.ops.find.long.low`)
+
+ :mps:tag:`req.speed.fast.find.long.why` Used in the allocator for
+ ``PoolClassAWL`` (design.mps.poolawl(1)), ``PoolClassAMS``
+ (design.mps.poolams(2)), ``PoolClassEPVM`` (design.mps.poolepvm(0)).
+ Of these AWL and EPVM have speed requirements. For AWL the length of
+ range to be found will be the length of a Dylan table in words.
+ According to mail.tony.1999-05-05.11-36(0), only
+ objects are allocated in AWL (though not all objects
+ are allocated in AWL), and the mean length of an
+ object is 486 Words. No data for EPVM alas.
+
+:mps:tag:`req.speed.fast.other.why` We might expect mark and sweep pools to
+make use of Bit Tables, the MPS has general requirements to support
+efficient mark and sweep pools, so that imposes general speed
+requirements on Bit Tables.
+
+
+Non requirements
+----------------
+
+The following are not requirements but the current design could
+support them with little modification or does support them. Often they
+used to be requirements, but are no longer, or were added
+speculatively or experimentally but aren't currently used.
+
+* :mps:tag:`non-req.ops.test.range.same` **RangesSame**. Test whether two
+ ranges that occupy the same positions in different Bit Tables are
+ the same. This used to be required by ``PoolClassAMS``, but is no
+ longer. Currently (1999-05-04) the functionality still exists.
+
+* :mps:tag:`non-req.ops.find.long.high` **FindLongResetRangeHigh**. (see
+ :mps:ref:`.req.ops.find`) Of all candidate ranges, identify the ranges with
+ greatest *j* and of those find the one with least *i* (find the
+ rightmost range that has at least *L* reset bits and return all of
+ it). Provided for symmetry but only currently used by the BT tests
+ and ``cbstest.c``.
+
+
+Background
+----------
+
+:mps:tag:`background` Originally Bit Tables were used and implemented
+by ``PoolClassLO`` (design.mps.poollo). It was
+decided to lift them out into a separate module when designing the
+Pool to manage Dylan Weak Tables which is also a mark and sweep pool
+and will make use of Bit Tables (see design.mps.poolawl).
+:mps:tag:`background.analysis` analysis.mps.bt(0) contains
+some of the analysis of the design decisions that were and were not
+made in this document.
+
+
+Clients
+-------
+
+:mps:tag:`clients` Bit Tables are used throughout the MPS but the important
+uses are in the client and VM arenas (design.mps.arena.client(0) and
+design.mps.arena.vm(1)) a bit table is used to record whether each
+page is free or not; several pool classes (``PoolClassLO``,
+``PoolClassEPVM``, ``PoolClassAMS``) use bit tables to record which
+locations are free and also to store colour.
+
+
+Overview
+--------
+
+:mps:tag:`over` Mostly, the design is as simple as possible. The significant
+complications are iteration (see :mps:ref:`.iteration` below) and searching
+(see :mps:ref:`.fun.find-res-range` below) because both of these are required
+to be fast.
+
+
+Interface
+---------
+
+.. c:type:: Word *BT
+
+:mps:tag:`if.representation.abstract` A Bit Table is represented by the type
+:c:type:`BT`.
+
+:mps:tag:`if.declare` The module declares a type :c:type:`BT` and a prototype for
+each of the functions below. The type is declared in impl.h.mpmtypes,
+the prototypes are declared in impl.h.mpm. Some of the functions are
+in fact implemented as macros in the usual way
+(doc.mps.ref-man.if-conv(0).macro.std).
+
+:mps:tag:`if.general.index` Many of the functions specified below take
+indexes. If otherwise unspecified an index must be in the interval [0,
+*n*) (note, up to, but not including, *n*) where *n* is the number of
+bits in the relevant Bit Table (as passed to the :c:func:`BTCreate()`
+function).
+
+:mps:tag:`if.general.range` Where a range is specified by two indexes (*base*
+and *limit*), the index *base*, which specifies the beginning of the
+range, must be in the interval [0, *n*), and the index *limit*, which
+specifies the end of the range, must be in the interval [1, *n*] (note
+can be *n*), and *base* must be strictly less than *limit* (empty
+ranges are not allowed). Sometimes *i* and *j* are used instead of
+*base* and *limit*.
+
+.. c:function:: Res BTCreate(BT *btReturn, Arena arena, Count n)
+
+:mps:tag:`if.create` Attempts to create a table of length ``n`` in the arena
+control pool, putting the table in ``*btReturn``. Returns ``ResOK`` if
+and only if the table is created OK. The initial values of the bits in
+the table are undefined (so the client should probably call
+:c:func:`BTResRange()` on the entire range before using the :c:type:`BT`). Meets
+:mps:ref:`.req.create`.
+
+.. c:function:: void BTDestroy(BT t, Arena arena, Count n)
+
+:mps:tag:`if.destroy` Destroys the table ``t``, which must have been created
+with :c:func:`BTCreate()`. The value of argument ``n`` must be same as the
+value of the argument passed to :c:func:`BTCreate()`. Meets
+:mps:ref:`.req.destroy`.
+
+.. c:function:: size_t BTSize(Count n)
+
+:mps:tag:`if.size` ``BTSize(n)`` returns the number of bytes needed for a Bit
+Table of ``n`` bits. :c:func:`BTSize()` is a macro, but ``(BTSize)(n)`` will
+assert if ``n`` exceeds ``COUNT_MAX - MPS_WORD_WIDTH + 1``. This is
+used by clients that allocate storage for the :c:type:`BT` themselves.
+Before :c:func:`BTCreate()` and :c:func:`BTDestroy()` were implemented that was the
+only way to allocate a Bit Table, but is now deprecated.
+
+.. c:function:: int BTGet(BT t, Index i)
+
+:mps:tag:`if.get` ``BTGet(t, i)`` returns the ``i``-th bit of the table ``t``
+(that is, the image of ``i`` under the mapping). Meets
+:mps:ref:`.req.ops.get`.
+
+.. c:function:: void BTSet(BT t, Index i)
+
+:mps:tag:`if.set` ``BTSet(t, i)`` sets the ``i``-th bit of the table ``t`` (to
+1). ``BTGet(t, i)`` will now return 1. Meets :mps:ref:`.req.ops.set`.
+
+.. c:function:: void BTRes(BT t, Index i)
+
+:mps:tag:`if.res` ``BTRes(t, i)`` resets the ``i``-th bit of the table ``t``
+(to 0). ``BTGet(t, i)`` will now return 0. Meets :mps:ref:`.req.ops.reset`.
+
+.. c:function:: void BTSetRange(BT t, Index base, Index limit)
+
+:mps:tag:`if.set-range` ``BTSetRange(t, base, limit)`` sets the range of bits
+[``base``, ``limit``) in the table ``t``. ``BTGet(t, x)`` will now
+return 1 for ``base`` ≤ ``x`` < ``limit``. Meets
+:mps:ref:`.req.ops.test.range.set`.
+
+.. c:function:: void BTResRange(BT t, Index base, Index limit)
+
+:mps:tag:`if.res-range` ``BTResRange(t, base, limit)`` resets the range of
+bits [``base``, ``limit``) in the table ``t``. ``BTGet(t, x)`` will
+now return 0 for ``base`` ≤ ``x`` < ``limit``. Meets
+:mps:ref:`.req.ops.test.range.reset`.
+
+.. c:function:: Bool BTIsSetRange(BT bt, Index base, Index limit)
+
+:mps:tag:`if.test.range.set` Returns :c:macro:`TRUE` if all the bits in the range
+[``base``, ``limit``) are set, :c:macro:`FALSE` otherwise. Meets
+:mps:ref:`.req.ops.test.range.set`.
+
+.. c:function:: Bool BTIsResRange(BT bt, Index base, Index limit)
+
+:mps:tag:`if.test.range.reset` Returns :c:macro:`TRUE` if all the bits in the range
+[``base``, ``limit``) are reset, :c:macro:`FALSE` otherwise. Meets
+:mps:ref:`.req.ops.test.range.reset`.
+
+``Bool BTRangesSame(BT BTx, BT BTy, Index base, Index limit);``
+
+:mps:tag:`if.test.range.same` returns :c:macro:`TRUE` if ``BTGet(BTx,i)`` equals
+``BTGet(BTy,i)`` for ``i`` in [``base``, ``limit``), and :c:macro:`FALSE`
+otherwise. Meets :mps:ref:`.non-req.ops.test.range.same`.
+
+:mps:tag:`if.find.general` There are four functions (below) to find reset
+ranges. All the functions have the same prototype (for symmetry)::
+
+ Bool find(Index *baseReturn, Index *limitReturn,
+ BT bt,
+ Index searchBase, Index searchLimit,
+ Count length);
+
+where ``bt`` is the Bit Table in which to search. ``searchBase`` and
+``searchLimit`` specify a subset of the Bit Table to use, the
+functions will only find ranges that are subsets of [``searchBase``,
+``searchLimit``) (when set, ``*baseReturn`` will never be less than
+``searchBase`` and ``*limitReturn`` will never be greater than
+``searchLimit``). ``searchBase`` and ``searchLimit`` specify a range
+that must conform to the general range requirements for a range [*i*,
+*j*), as per :mps:ref:`.if.general.range` modified appropriately. ``length``
+is the number of contiguous reset bits to find; it must not be bigger
+than ``searchLimit - searchBase`` (that would be silly). If a suitable
+range cannot be found the function returns :c:macro:`FALSE` (0) and leaves
+``*baseReturn`` and ``*limitReturn`` untouched. If a suitable range is
+found then the function returns the range's base in ``*baseReturn``
+and its limit in ``*limitReturn`` and returns :c:macro:`TRUE` (1).
+
+.. c:function:: Bool BTFindShortResRange(Index *baseReturn, Index *limitReturn, BT bt, Index searchBase, Index searchLimit, Count length)
+
+:mps:tag:`if.find-short-res-range` Finds a range of reset bits in the table,
+starting at ``searchBase`` and working upwards. This function is
+intended to meet :mps:ref:`.req.ops.find.short.low` so it will find the
+leftmost range that will do, and never finds a range longer than the
+requested length (the intention is that it will not waste time
+looking).
+
+.. c:function:: Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn, BT bt, Index searchBase, Index searchLimit, Count length)
+
+:mps:tag:`if.find-short-res-range-high` Finds a range of reset bits in the
+table, starting at ``searchLimit`` and working downwards. This
+function is intended to meet :mps:ref:`.req.ops.find.short.high` so it will
+find the rightmost range that will do, and never finds a range longer
+than the requested length.
+
+.. c:function:: Bool BTFindLongResRange(Index *baseReturn, Index *limitReturn, BT bt, Index searchBase, Index searchLimit, Count length)
+
+:mps:tag:`if.find-long-res-range` Finds a range of reset bits in the table,
+starting at ``searchBase`` and working upwards. This function is
+intended to meet :mps:ref:`.req.ops.find.long.low` so it will find the
+leftmost range that will do and returns all of that range (which can
+be longer than the requested length).
+
+.. c:function:: Bool BTFindLongResRangeHigh(Index *baseReturn, Index *limitReturn, BT bt, Index searchBase, Index searchLimit, Count length)
+
+:mps:tag:`if.find-long-res-range-high` Finds a range of reset bits in the
+table, starting at ``searchLimit`` and working downwards. This
+function is intended to meet :mps:ref:`.req.ops.find.long.high` so it will
+find the rightmost range that will do and returns all that range
+(which can be longer than the requested length).
+
+.. c:function:: void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit)
+
+:mps:tag:`if.copy-range` Overwrites the ``i``-th bit of ``toBT`` with the
+``i``-th bit of ``fromBT``, for all ``i`` in [``base``, ``limit``).
+Meets :mps:ref:`.req.ops.copy.simple`.
+
+.. c:function:: void BTCopyOffsetRange(BT fromBT, BT toBT, Index fromBase, Index fromLimit, Index toBase, Index toLimit)
+
+:mps:tag:`if.copy-offset-range` Overwrites the ``i``-th bit of ``toBT`` with
+the ``j``-th bit of ``fromBT``, for all ``i`` in [``toBase``,
+``toLimit``) and corresponding ``j`` in [``fromBase``, ``fromLimit``).
+Each of these ranges must be the same size. This might be
+significantly less efficient than :c:func:`BTCopyRange()`. Meets
+:mps:ref:`.req.ops.copy.offset`.
+
+.. c:function:: void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit)
+
+:mps:tag:`if.copy-invert-range` Overwrites the ``i``-th bit of ``toBT`` with
+the inverse of the ``i``-th bit of ``fromBT``, for all ``i`` in
+[``base``, ``limit``). Meets :mps:ref:`.req.ops.copy.invert`.
+
+
+Detailed design
+---------------
+
+
+Data structures
+...............
+
+:mps:tag:`datastructure` Bit Tables will be represented as (a pointer to) an
+array of :c:type:`Word`. A plain array is used instead of the more usual
+design convention of implementing an abstract data type as a structure
+with a signature (see guide.impl.c.adt(0)).
+:mps:tag:`datastructure.words.justify` The type :c:type:`Word` is used as it will
+probably map to the object that can be most efficiently accessed on
+any particular platform. :mps:tag:`datastructure.non-adt.justify` The usual
+abstract data type convention was not followed because (i) The initial
+design (drj) was lazy, (ii) Bit Tables are more likely to come in
+convenient powers of two with the extra one or two words overhead.
+However, the loss of checking is severe. Perhaps it would be better to
+use the usual abstract data type style.
+
+
+Functions
+.........
+
+:mps:tag:`fun.size` :c:func:`BTSize()`. Since a Bit Table is an array of :c:type:`Word`, the
+size of a Bit Table of *n* bits is simply the number of words that it
+takes to store *n* bits times the number of bytes in a word. This is
+``ceiling(n/MPS_WORD_WIDTH)*sizeof(Word).`` :mps:tag:`fun.size.justify` Since
+there can be at most ``MPS_WORD_WIDTH - 1`` unused bits in the entire
+table, this satisfies :mps:ref:`.req.bit`.
+
+:mps:tag:`index` The designs for the following functions use a decomposition
+of a bit-index, ``i``, into two parts, ``iw``, ``ib``.
+
+* :mps:tag:`index.word` ``iw`` is the "word-index" which is the index into the
+ word array of the word that contains the bit referred to by the
+ bit-index. ``iw = i / MPS_WORD_WIDTH``. Since :c:macro:`MPS_WORD_WIDTH` is
+ a power of two, this is the same as ``iw = i >> MPS_WORD_SHIFT``.
+ The latter expression is used in the code. :mps:tag:`index.word.justify` The
+ compiler is more likely to generate good code without the divide.
+
+* :mps:tag:`index.sub-word` ``ib`` is the "sub-word-index" which is the index
+ of the bit referred to by the bit-index in the above word. ``ib = i
+ % MPS_WORD_WIDTH``. Since :c:macro:`MPS_WORD_WIDTH` is a power of two, this
+ is the same as ``ib = i & ~((Word)-1<>5) + (i&31);
+ }
+
+.. c:function:: ACT_ON_RANGE(Index base, Index limit, single_action, bits_action, word_action)
+.. c:function:: ACT_ON_RANGE_HIGH(Index base, Index limit, single_action, bits_action, word_action)
+
+:mps:tag:`iteration` Many of the following functions involve iteration over
+ranges in a Bit Table. This is performed on whole words rather than
+individual bits, whenever possible (to improve speed). This is
+implemented internally by the macros :c:func:`ACT_ON_RANGE()` and
+:c:func:`ACT_ON_RANGE_HIGH()` for iterating over the range forwards and
+backwards respectively. These macros do not form part of the interface
+of the module, but are used extensively in the implementation. The
+macros are often used even when speed is not an issue because it
+simplifies the implementation and makes it more uniform. The iteration
+macros take the parameters ``base``, ``limit``, ``single_action``,
+``bits_action``, and ``word_action``:
+
+* ``base`` and ``limit`` are of type :c:type:`Index` and define the range of
+ the iteration.
+
+* ``single_action`` is the name of a macro which will be used for
+ iterating over bits in the table individually. This macro must take
+ a single :c:type:`Index` parameter corresponding to the index for the bit.
+ The expansion of the macro must not contain ``break`` or
+ ``continue`` because it will be called from within a loop from the
+ expansion of :c:func:`ACT_ON_RANGE()`.
+
+* ``bits_action`` is the name of a macro which will be used for
+ iterating over part-words. This macro must take parameters
+ ``wordIndex``, ``base``, ``limit`` where ``wordIndex`` is the index
+ into the array of words, and ``base`` and ``limit`` define a range
+ of bits within the indexed word.
+
+* ``word_action`` is the name of a macro which will be used for
+ iterating over whole-words. This macro must take the single
+ parameter ``wordIndex`` which is the index of the whole-word in the
+ array. The expansion of the macro must not contain ``break`` or
+ ``continue`` because it will be called from within a loop from the
+ expansion of :c:func:`ACT_ON_RANGE()`.
+
+:mps:tag:`iteration.exit` The expansion of the ``single_action``,
+``bits_action``, and ``word_action`` macros is allowed to contain
+``return`` or ``goto`` to terminate the iteration early. This is used
+by the test (:mps:ref:`.fun.test.range.set`) and find (:mps:ref:`.fun.find`)
+operations.
+
+:mps:tag:`iteration.small` If the range is sufficiently small only the
+``single_action`` macro will be used, as this is more efficient in
+practice. The choice of what constitutes a small range is made
+entirely on the basis of experimental performance results (and
+currently, 1999-04-27, a "small range" is 6 bits or fewer. See
+change.mps.epcore.brisling.160181 for some justification). Otherwise
+(for a bigger range) ``bits_action`` is used on the part words at
+either end of the range (or the whole of the range it if it fits in a
+single word), and ``word_action`` is used on the words that comprise
+the inner portion of the range.
+
+The implementation of :c:func:`ACT_ON_RANGE()` (and :c:func:`ACT_ON_RANGE_HIGH()`) is
+simple enough. It decides which macros it should invoke and invokes
+them. ``single_action`` and ``word_action`` are invoked inside loops.
+
+:mps:tag:`fun.get` :c:func:`BTGet()`. The bit-index will be converted in the usual
+way, see :mps:ref:`.index`. The relevant :c:type:`Word` will be read out of the Bit
+Table and shifted right by the sub-:c:type:`Word` index (this brings the
+relevant bit down to the least significant bit of the :c:type:`Word`), the
+:c:type:`Word` will then be masked with 1, producing the answer.
+
+:mps:tag:`fun.set` :c:func:`BTSet()`.
+
+:mps:tag:`fun.res` :c:func:`BTRes()`.
+
+In both :c:func:`BTSet()` and :c:func:`BTRes()` a mask is constructed by shifting 1
+left by the sub-word-index (see :mps:ref:`.index`). For :c:func:`BTSet()` the mask is
+or-ed into the relevant word (thereby setting a single bit). For
+:c:func:`BTRes()` the mask is inverted and and-ed into the relevant word
+(thereby resetting a single bit).
+
+:mps:tag:`fun.set-range` :c:func:`BTSetRange()`. :c:func:`ACT_ON_RANGE()` (see :mps:ref:`.iteration`
+above) is used with macros that set a single bit (using :c:func:`BTSet()`),
+set a range of bits in a word, and set a whole word.
+
+:mps:tag:`fun.res-range` :c:func:`BTResRange()` This is implemented similarly to
+:c:func:`BTSetRange()` (:mps:ref:`.fun.set-range`) except using :c:func:`BTRes()` and reverse
+bit-masking logic.
+
+:mps:tag:`fun.test.range.set` :c:func:`BTIsSetRange()`. :c:func:`ACT_ON_RANGE()` (see
+:mps:ref:`.iteration` above) is used with macros that test whether all the
+relevant bits are set; if some of the relevant bits are not set then
+``return FALSE`` is used to terminate the iteration early and return
+from the :c:func:`BTIsSetRange()` function. If the iteration completes then
+:c:macro:`TRUE` is returned.
+
+:mps:tag:`fun.test.range.reset` :c:func:`BTIsResRange()`. As for :c:func:`BTIsSetRange()`
+(:mps:ref:`.fun.test.range.set` above) but testing whether the bits are reset.
+
+:mps:tag:`fun.test.range.same` :c:func:`BTRangesSame()`. As for :c:func:`BTIsSetRange()`
+(:mps:ref:`.fun.test.range.set` above) but testing whether corresponding
+ranges in the two Bit Tables are the same. Note there are no speed
+requirements, but :c:func:`ACT_ON_RANGE()` is used for simplicity and
+uniformity.
+
+:mps:tag:`fun.find` The four external find functions (:c:func:`BTFindShortResRange()`,
+:c:func:`BTFindShortResRangeHigh()`, :c:func:`BTFindLongResRange()`,
+:c:func:`BTFindLongResRangeHigh()`) simply call through to one of the two
+internal functions: :c:func:`BTFindResRange()` and :c:func:`BTFindResRangeHigh()`.
+
+.. c:function:: Bool BTFindResRange(Index *baseReturn, Index *limitReturn, BT bt, Index searchBase, Index searchLimit, Count minLength, Count maxLength)
+.. c:function:: Bool BTFindResRangeHigh(Index *baseReturn, Index *limitReturn, BT bt, Index searchBase, Index searchLimit, Count minLength, Count maxLength)
+
+There are two length parameters, one specifying the minimum length of
+the range to be found, the other the maximum length. For
+:c:func:`BTFindShort()` and :c:func:`BTFindShortHigh()`, ``maxLength`` is equal to
+``minLength`` when passed; for :c:func:`BTFindLong()` and :c:func:`BTFindLongHigh()`,
+``maxLength` is equal to the maximum possible range, namely
+``searchLimit - searchBase``.
+
+:mps:tag:`fun.find-res-range` :c:func:`BTFindResRange()`. Iterate within the search
+boundaries, identifying candidate ranges by searching for a reset bit.
+The :ref:`Boyer–Moore algorithm ` is used (it's particularly
+easy to implement when there are only two symbols, 0 and 1, in the
+alphabet). For each candidate range, iterate backwards over the bits
+from the end of the range towards the beginning. If a set bit is
+found, this candidate has failed and a new candidate range is
+selected. If when scanning for the set bit a range of reset bits was
+found before finding the set bit, then this (small) range of reset
+bits is used as the start of the next candidate. Additionally the end
+of this small range of reset bits (the end of the failed candidate
+range) is remembered so that we don't have to iterate over this range
+again. But if no reset bits were found in the candidate range, then
+iterate again (starting from the end of the failed candidate) to look
+for one. If during the backwards search no set bit is found, then we
+have found a sufficiently large range of reset bits; now extend the
+valid range as far as possible up to the maximum length by iterating
+forwards up to the maximum limit looking for a set bit. The iterations
+make use of the :c:func:`ACT_ON_RANGE()` and :c:func:`ACT_ON_RANGE_HIGH()` macros,
+which can use ``goto`` to effect an early termination of the iteration
+when a set/reset (as appropriate) bit is found. The macro
+:c:func:`ACTION_FIND_SET_BIT()` is used in the iterations. It efficiently
+finds the first (that is, with lowest index or weight) set bit in a
+word or subword.
+
+:mps:tag:`fun.find-res-range.improve` Various other performance improvements
+have been suggested in the past, including some from
+request.epcore.170534. Here is a list of potential improvements which
+all sound plausible, but which have not led to performance
+improvements in practice:
+
+* :mps:tag:`fun.find-res-range.improve.step.partial` When the top index in a
+ candidate range fails, skip partial words as well as whole words,
+ using, for example, lookup tables.
+
+* :mps:tag:`fun.find-res-range.improve.lookup` When testing a candidate run,
+ examine multiple bits at once (for example, 8), using lookup tables
+ for (for example) index of first set bit, index of last set bit,
+ number of reset bits, length of maximum run of reset bits.
+
+:mps:tag:`fun.find-res-range-high` :c:func:`BTFindResRangeHigh()`. Exactly the same
+algorithm as in :c:func:`BTFindResRange()` (see :mps:ref:`.fun.find-res-range` above),
+but moving over the table in the opposite direction.
+
+:mps:tag:`fun.copy-simple-range` :c:func:`BTCopyRange()`. Uses :c:func:`ACT_ON_RANGE()` (see
+:mps:ref:`.iteration` above) with the obvious implementation. Should be fast.
+
+:mps:tag:`fun.copy-offset-range` :c:func:`BTCopyOffsetRange()`. Uses a simple
+iteration loop, reading bits with :c:func:`BTGet()` and setting them with
+:c:func:`BTSet()`. Doesn't use :c:func:`ACT_ON_RANGE()` because the two ranges will
+not, in general, be similarly word-aligned.
+
+:mps:tag:`fun.copy-invert-range` :c:func:`BTCopyInvertRange()`. Uses :c:func:`ACT_ON_RANGE()`
+(see :mps:ref:`.iteration` above) with the obvious implementation. Should be
+fast---although there are no speed requirements.
+
+
+Testing
+-------
+
+:mps:tag:`test` The following tests are available or have been used during
+development.
+
+:mps:tag:`test.btcv` ``btcv.c``. This is supposed to be a coverage test,
+intended to execute all of the module's code in at least some minimal
+way.
+
+:mps:tag:`test.cbstest` ``cbstest.c``. This was written as a test of the
+:c:macro:`CBS` module (design.mps.cbs(2)). It compares the functional
+operation of a :c:macro:`CBS` with that of a :c:type:`BT` so is a good functional
+test of either module.
+
+:mps:tag:`test.mmqa.120` MMQA_test_function!210.c. This is used because it has
+a fair amount of segment allocation and freeing so exercises the arena
+code that uses Bit Tables.
+
+:mps:tag:`test.bttest` ``bttest.c``. This is an interactive test that can be
+used to exercise some of the :c:type:`BT` functionality by hand.
+
+:mps:tag:`test.dylan` It is possible to modify Dylan so that it uses Bit
+Tables more extensively. See change.mps.epcore.brisling.160181 TEST1
+and TEST2.
+
+
diff --git a/mps/manual/html/_sources/design/buffer.txt b/mps/manual/html/_sources/design/buffer.txt
new file mode 100644
index 00000000000..feaa3142a41
--- /dev/null
+++ b/mps/manual/html/_sources/design/buffer.txt
@@ -0,0 +1,698 @@
+.. _design-buffer:
+
+
+.. index::
+ pair: buffers; design
+
+
+Allocation buffers and allocation points
+========================================
+
+.. mps:prefix:: design.mps.buffer
+
+
+Introduction
+------------
+
+:mps:tag:`scope` This document describes the design of allocation buffers
+and allocation points.
+
+:mps:tag:`purpose` The purpose of this document is to record design
+decisions made concerning allocation buffers and allocation points and
+justify those decisions in terms of requirements.
+
+:mps:tag:`readership` The document is intended for reading by any MPS
+developer.
+
+
+Glossary
+--------
+
+trapped
+
+ :mps:tag:`def.trapped` The buffer is in a state such that the MPS gets
+ to know about the next use of that buffer.
+
+
+Source
+------
+
+:mps:tag:`source.mail` Much of the juicy stuff about buffers is only
+floating around in mail discussions. You might like to try searching
+the archives if you can't find what you want here.
+
+.. note::
+
+ Mail archives are only accessible to Ravenbrook staff. RHSK
+ 2006-06-09.
+
+:mps:tag:`source.synchronize` For a discussion of the synchronization
+issues:
+
+* `mail.richard.1995-05-19.17-10 `_
+* `mail.ptw.1995-05-19.19-15 `_
+* `mail.richard.1995-05-24.10-18 `_
+
+.. note::
+
+ I believe that the sequence for flip in PTW's message is
+ incorrect. The operations should be in the other order. DRJ.
+
+:mps:tag:`source.interface` For a description of the buffer interface in C
+prototypes:
+
+* `mail.richard.1997-04-28.09-25(0) `_
+
+:mps:tag:`source.qa` Discussions with QA were useful in pinning down the
+semantics and understanding of some obscure but important boundary
+cases. See the thread starting
+`mail.richard.tucker.1997-05-12.09-45(0)
+`_ with subject "notes on
+our allocation points discussion":
+
+* `mail.richard.tucker.1997-05-12.09-45 `_
+* `mail.ptw.1997-05-12.12-46(1) `_
+* `mail.richard.1997-05-12.13-15 `_
+* `mail.richard.1997-05-12.13-28 `_
+* `mail.ptw.1997-05-13.15-15 `_
+* `mail.sheep.1997-05-14.11-52 `_
+* `mail.rit.1997-05-15.09-19 `_
+* `mail.ptw.1997-05-15.21-22 `_
+* `mail.ptw.1997-05-15.21-35 `_
+* `mail.rit.1997-05-16.08-02 `_
+* `mail.rit.1997-05-16.08-42 `_
+* `mail.ptw.1997-05-16.12-36 `_
+* `mail.ptw.1997-05-16.12-47 `_
+* `mail.richard.1997-05-19.15-46 `_
+* `mail.richard.1997-05-19.15-56 `_
+* `mail.ptw.1997-05-20.20-47 `_
+
+
+
+Requirements
+------------
+
+:mps:tag:`req.fast` Allocation must be very fast.
+
+:mps:tag:`req.thread-safe` Must run safely in a multi-threaded environment.
+
+:mps:tag:`req.no-synch` Must avoid the use of thread-synchronization.
+(:mps:ref:`.req.fast`)
+
+:mps:tag:`req.manual` Support manual memory management.
+
+:mps:tag:`req.exact` Support exact collectors.
+
+:mps:tag:`req.ambig` Support ambiguous collectors.
+
+:mps:tag:`req.count` Must record (approximately) the amount of allocation (in bytes).
+
+.. note::
+
+ Actually not a requirement any more, but once was put forward as a
+ Dylan requirement. Bits of the code still reflect this
+ requirement. See request.dylan.170554.
+
+
+Classes
+-------
+
+:mps:tag:`class.hierarchy` The :c:type:`Buffer` data structure is designed to be
+subclassable (see design.mps.protocol).
+
+:mps:tag:`class.hierarchy.buffer` The basic buffer class (:c:type:`BufferClass`)
+supports basic allocation-point buffering, and is appropriate for
+those manual pools which don't use segments (:mps:ref:`.req.manual`). The
+:c:type:`Buffer` class doesn't support reference ranks (that is, the buffers
+have ``RankSetEMPTY``). Clients may use :c:type:`BufferClass` directly, or
+create their own subclasses (see :mps:ref:`.subclassing`).
+
+:mps:tag:`class.hierarchy.segbuf` Class :c:type:`SegBufClass` is also provided for
+the use of pools which additionally need to associate buffers with
+segments. :c:type:`SegBufClass` is a subclass of :c:type:`BufferClass`. Manual
+pools may find it convenient to use :c:type:`SegBufClass`, but it is
+primarily intended for automatic pools (:mps:ref:`.req.exact`, :mps:ref:`.req.ambig`).
+An instance of :c:type:`SegBufClass` may be attached to a region of memory
+that lies within a single segment. The segment is associated with the
+buffer, and may be accessed with the :c:func:`BufferSeg()` function.
+:c:type:`SegBufClass` also supports references at any rank set. Hence this
+class or one of its subclasses should be used by all automatic pools
+(with the possible exception of leaf pools). The rank sets of buffers
+and the segments they are attached to must match. Clients may use
+:c:type:`SegBufClass` directly, or create their own subclasses (see
+:mps:ref:`.subclassing`).
+
+:mps:tag:`class.hierarchy.rankbuf` Class :c:type:`RankBufClass` is also provided
+as a subclass of :c:type:`SegBufClass`. The only way in which this differs
+from its superclass is that the rankset of a :c:type:`RankBufClass` is set
+during initialization to the singleton rank passed as an additional
+parameter to :c:func:`BufferCreate()`. Instances of :c:type:`RankBufClass` are of
+the same type as instances of :c:type:`SegBufClass`, that is, ``SegBuf``.
+Clients may use :c:type:`RankBufClass` directly, or create their own
+subclasses (see :mps:ref:`.subclassing`).
+
+:mps:tag:`class.create` The buffer creation functions (:c:func:`BufferCreate()`
+and :c:func:`BufferCreateV()`) take a ``class`` parameter, which determines
+the class of buffer to be created.
+
+:mps:tag:`class.choice` Pools which support buffered allocation should
+specify a default class for buffers. This class will be used when a
+buffer is created in the normal fashion by MPS clients (for example by
+a call to :c:func:`mps_ap_create()`). Pools specify the default class by
+means of the ``bufferClass`` field in the pool class object. This
+should be a pointer to a function of type :c:type:`PoolBufferClassMethod`.
+The normal class "Ensure" function (for example
+:c:func:`EnsureBufferClass()`) has the appropriate type.
+
+:mps:tag:`subclassing` Pools may create their own subclasses of the standard
+buffer classes. This is sometimes useful if the pool needs to add an
+extra field to the buffer. The convenience macro
+:c:func:`DEFINE_BUFFER_CLASS()` may be used to define subclasses of buffer
+classes. See design.mps.protocol.int.define-special.
+
+:mps:tag:`replay` To work with the allocation replayer (see
+design.mps.telemetry.replayer), the buffer class has to emit an event
+for each call to an external interface, containing all the parameters
+passed by the user. If a new event type is required to carry this
+information, the replayer (impl.c.eventrep) must then be extended to
+recreate the call.
+
+:mps:tag:`replay.pool-buffer` The replayer must also be updated if the
+association of buffer class to pool or the buffer class hierarchy is
+changed.
+
+:mps:tag:`class.method` Buffer classes provide the following methods (these
+should not be confused with the pool class methods related to the
+buffer protocol, described in :mps:ref:`.method`):
+
+.. c:type:: Res (*BufferInitMethod)(Buffer buffer, Pool pool, ArgList args)
+
+:mps:tag:`class.method.init` :c:func:`init()` is a class-specific initialization
+method called from :c:func:`BufferInit()`. It receives the keyword arguments
+passed to to :c:func:`BufferInit()`. Client-defined methods must call their
+superclass method (via a next-method call) before performing any
+class-specific behaviour. :mps:tag:`replay.init` The :c:func:`init()` method
+should emit a ``BufferInit`` event (if there aren't any extra
+parameters, `` = ""``).
+
+.. c:type:: void (*BufferFinishMethod)(Buffer buffer)
+
+:mps:tag:`class.method.finish` :c:func:`finish()` is a class-specific finish
+method called from :c:func:`BufferFinish()`. Client-defined methods must
+call their superclass method (via a next-method call) after performing
+any class-specific behaviour.
+
+.. c:type:: void (*BufferAttachMethod)(Buffer buffer, Addr base, Addr limit, Addr init, Size size)
+
+:mps:tag:`class.method.attach` :c:func:`attach()` is a class-specific method
+called whenever a buffer is attached to memory, via
+:c:func:`BufferAttach()`. Client-defined methods must call their superclass
+method (via a next-method call) before performing any class-specific
+behaviour.
+
+.. c:type:: void (*BufferDetachMethod)(Buffer buffer)
+
+:mps:tag:`class.method.detach` :c:func:`detach()` is a class-specific method
+called whenever a buffer is detached from memory, via
+:c:func:`BufferDetach()`. Client-defined methods must call their superclass
+method (via a next-method call) after performing any class-specific
+behaviour.
+
+.. c:type:: Seg (*BufferSegMethod)(Buffer buffer)
+
+:mps:tag:`class.method.seg` :c:func:`seg()` is a class-specific accessor method
+which returns the segment attached to a buffer (or :c:macro:`NULL` if there
+isn't one). It is called from :c:func:`BufferSeg()`. Clients should not need
+to define their own methods for this.
+
+.. c:type:: RankSet (*BufferRankSetMethod)(Buffer buffer)
+
+:mps:tag:`class.method.rankSet` :c:func:`rankSet()` is a class-specific accessor
+method which returns the rank set of a buffer. It is called from
+:c:func:`BufferRankSet()`. Clients should not need to define their own
+methods for this.
+
+.. c:type:: void (*BufferSetRankSetMethod)(Buffer buffer, RankSet rankSet)
+
+:mps:tag:`class.method.setRankSet` :c:func:`setRankSet()` is a class-specific
+setter method which sets the rank set of a buffer. It is called from
+:c:func:`BufferSetRankSet()`. Clients should not need to define their own
+methods for this.
+
+.. c:type:: Res (*BufferDescribeMethod)(Buffer buffer, mps_lib_FILE *stream)
+
+:mps:tag:`class.method.describe` :c:func:`describe()` is a class-specific method
+called to describe a buffer, via BufferDescribe. Client-defined
+methods must call their superclass method (via a next-method call)
+before describing any class-specific state.
+
+
+Logging
+-------
+
+:mps:tag:`logging.control` Buffers have a separate control for whether they
+are logged or not, this is because they are particularly high volume.
+This is a Boolean flag (``bufferLogging``) in the :c:type:`ArenaStruct`.
+
+
+Measurement
+-----------
+
+:mps:tag:`count` Counting the allocation volume is done by maintaining two
+fields in the buffer struct:
+
+:mps:tag:`count.fields` ``fillSize``, ``emptySize``.
+
+:mps:tag:`count.monotonic` both of these fields are monotonically
+increasing.
+
+:mps:tag:`count.fillsize` ``fillSize`` is an accumulated total of the size
+of all the fills (as a result of calling the :c:type:`PoolClass`
+:c:func:`BufferFill()` method) that happen on the buffer.
+
+:mps:tag:`count.emptysize` ``emptySize`` is an accumulated total of the size of
+all the empties than happen on the buffer (which are notified to the
+pool using the :c:type:`PoolClass` :c:func:`BufferEmpty()` method).
+
+:mps:tag:`count.generic` These fields are maintained by the generic buffer
+code in :c:func:`BufferAttach()` and :c:func:`BufferDetach()`.
+
+:mps:tag:`count.other` Similar count fields are maintained in the pool and
+the arena. They are maintained on an internal (buffers used internally
+by the MPS) and external (buffers used for mutator allocation points)
+basis. The fields are also updated by the buffer code. The fields are:
+
+- in the pool: ``fillMutatorSize``, ``fillInternalSize``,
+ ``emptyMutatorSize``, and ``emptyInternalSize`` (4 fields);
+- in the arena, ``fillMutatorSize``, ``fillInternalSize``,
+ ``emptyMutatorSize``, ``emptyInternalSize``, and
+ ``allocMutatorSize`` (5 fields).
+
+:mps:tag:`count.alloc.how` The amount of allocation in the buffer just
+after an empty is ``fillSize - emptySize``. At other times this
+computation will include space that the buffer has the use of (between
+base and init) but which may not get allocated in (because the
+remaining space may be too large for the next reserve so some or all
+of it may get emptied). The arena field ``allocMutatorSize`` is
+incremented by the allocated size (between base and init)
+whenever a buffer is detached. Symmetrically this field is decremented
+by by the pre-allocated size (between base and init) whenever
+a buffer is attached. The overall count is asymptotically correct.
+
+:mps:tag:`count.type` All the count fields are type double.
+
+:mps:tag:`count.type.justify` This is because double is the type most likely
+to give us enough precision. Because of the lack of genuine
+requirements the type isn't so important. It's nice to have it more
+precise than long. Which double usually is.
+
+
+Notes from the whiteboard
+-------------------------
+
+Requirements
+
+- atomic update of words
+- guarantee order of reads and write to certain memory locations.
+
+Flip
+
+- limit:=0
+- record init for scanner
+
+Commit
+
+- init:=alloc
+- if(limit = 0) ...
+- L written only by MM
+- A written only by client (except during synchronized MM op)
+- I ditto
+- I read by MM during flip
+
+States
+
+- busy
+- ready
+- trapped
+- reset
+
+.. note::
+
+ There are many more states. DRJ.
+
+Misc
+
+- During buffer ops all field values can change. Might trash perfectly
+ good ("valid"?) object if pool isn't careful.
+
+
+Synchronization
+---------------
+
+Buffers provide a loose form of synchronization between the mutator
+and the collector.
+
+The crucial synchronization issues are between the operation the pool
+performs on flip and the mutator's commit operation.
+
+Commit
+
+- read init
+- write init
+- Memory Barrier
+- read ``limit``
+
+Flip
+
+- write ``limit``
+- Memory Barrier
+- read init
+
+Commit consists of two parts. The first is the update to init.
+This is a declaration that the new object just before init is now
+correctly formatted and can be scanned. The second is a check to see
+if the buffer has been "tripped". The ordering of the two parts is
+crucial.
+
+Note that the declaration that the object is correctly formatted is
+independent of whether the buffer has been tripped or not. In
+particular a pool can scan up to the init pointer (including the newly
+declared object) whether or not the pool will cause the commit to
+fail. In the case where the pool scans the object, but then causes the
+commit to fail (and presumably the allocation to occur somewhere
+else), the pool will have scanned a "dead" object, but this is just
+another example of conservatism in the general sense.
+
+Not that the read of init in the Flip sequence can in fact be
+arbitrarily delayed (as long as it is read before a buffered segment
+is scanned).
+
+On processors with Relaxed Memory Order (such as the DEC Alpha),
+Memory Barriers will need to be placed at the points indicated.
+
+::
+
+ * DESIGN
+ *
+ * design.mps.buffer.
+ *
+ * An allocation buffer is an interface to a pool which provides
+ * very fast allocation, and defers the need for synchronization in
+ * a multi-threaded environment.
+ *
+ * Pools which contain formatted objects must be synchronized so
+ * that the pool can know when an object is valid. Allocation from
+ * such pools is done in two stages: reserve and commit. The client
+ * first reserves memory, then initializes it, then commits.
+ * Committing the memory declares that it contains a valid formatted
+ * object. Under certain conditions, some pools may cause the
+ * commit operation to fail. (See the documentation for the pool.)
+ * Failure to commit indicates that the whole allocation failed and
+ * must be restarted. When using a pool which introduces the
+ * possibility of commit failing, the allocation sequence could look
+ * something like this:
+ *
+ * do {
+ * res = BufferReserve(&p, buffer, size);
+ * if(res != ResOK) return res; // allocation fails, reason res
+ * initialize(p); // p now points at valid object
+ * } while(!BufferCommit(buffer, p, size));
+ *
+ * Pools which do not contain formatted objects can use a one-step
+ * allocation as usual. Effectively any random rubbish counts as a
+ * "valid object" to such pools.
+ *
+ * An allocation buffer is an area of memory which is pre-allocated
+ * from a pool, plus a buffer descriptor, which contains, inter
+ * alia, four pointers: base, init, alloc, and limit. Base points
+ * to the base address of the area, limit to the last address plus
+ * one. Init points to the first uninitialized address in the
+ * buffer, and alloc points to the first unallocated address.
+ *
+ * L . - - - - - . ^
+ * | | Higher addresses -'
+ * | junk |
+ * | | the "busy" state, after Reserve
+ * A |-----------|
+ * | uninit |
+ * I |-----------|
+ * | init |
+ * | | Lower addresses -.
+ * B `-----------' v
+ *
+ * L . - - - - - . ^
+ * | | Higher addresses -'
+ * | junk |
+ * | | the "ready" state, after Commit
+ * A=I |-----------|
+ * | |
+ * | |
+ * | init |
+ * | | Lower addresses -.
+ * B `-----------' v
+ *
+ * Access to these pointers is restricted in order to allow
+ * synchronization between the pool and the client. The client may
+ * only write to init and alloc, but in a restricted and atomic way
+ * detailed below. The pool may read the contents of the buffer
+ * descriptor at _any_ time. During calls to the fill and trip
+ * methods, the pool may update any or all of the fields
+ * in the buffer descriptor. The pool may update the limit at _any_
+ * time.
+ *
+ * Access to buffers by these methods is not synchronized. If a buffer
+ * is to be used by more than one thread then it is the client's
+ * responsibility to ensure exclusive access. It is recommended that
+ * a buffer be used by only a single thread.
+ *
+ * [Only one thread may use a buffer at once, unless the client
+ * places a mutual exclusion around the buffer access in the usual
+ * way. In such cases it is usually better to create one buffer for
+ * each thread.]
+ *
+ * Here are pseudo-code descriptions of the reserve and commit
+ * operations. These may be implemented in-line by the client.
+ * Note that the client is responsible for ensuring that the size
+ * (and therefore the alloc and init pointers) are aligned according
+ * to the buffer's alignment.
+ *
+ * Reserve(buf, size) ; size must be aligned to pool
+ * if buf->limit - buf->alloc >= size then
+ * buf->alloc +=size ; must be atomic update
+ * p = buf->init
+ * else
+ * res = BufferFill(&p, buf, size) ; buf contents may change
+ *
+ * Commit(buf, p, size)
+ * buf->init = buf->alloc ; must be atomic update
+ * if buf->limit == 0 then
+ * res = BufferTrip(buf, p, size) ; buf contents may change
+ * else
+ * res = True
+ * (returns True on successful commit)
+ *
+ * The pool must allocate the buffer descriptor and initialize it by
+ * calling BufferInit. The descriptor this creates will fall
+ * through to the fill method on the first allocation. In general,
+ * pools should not assign resources to the buffer until the first
+ * allocation, since the buffer may never be used.
+ *
+ * The pool may update the base, init, alloc, and limit fields when
+ * the fallback methods are called. In addition, the pool may set
+ * the limit to zero at any time. The effect of this is either:
+ *
+ * 1. cause the _next_ allocation in the buffer to fall through to
+ * the buffer fill method, and allow the buffer to be flushed
+ * and relocated;
+ *
+ * 2. cause the buffer trip method to be called if the client was
+ * between reserve and commit.
+ *
+ * A buffer may not be relocated under other circumstances because
+ * there is a race between updating the descriptor and the client
+ * allocation sequence.
+
+
+Interface
+---------
+
+.. c:function:: Res BufferCreate(Buffer *bufferReturn, BufferClass class, Pool pool, Bool isMutator, ArgList args)
+
+:mps:tag:`method.create` Create an allocation buffer in a pool. The buffer
+is created in the "ready" state.
+
+A buffer structure is allocated from the space control pool and
+partially initialized (in particularly neither the signature nor the
+serial field are initialized). The pool class's :c:func:`bufferCreate()`
+method is then called. This method can update (some undefined subset
+of) the fields of the structure; it should return with the buffer in
+the "ready" state (or fail). The remainder of the initialization then
+occurs.
+
+If and only if successful then a valid buffer is returned.
+
+.. c:function:: void BufferDestroy(Buffer buffer)
+
+:mps:tag:`method.destroy` Free a buffer descriptor. The buffer must be in
+the "ready" state, that is, not between a Reserve and Commit.
+Allocation in the area of memory to which the descriptor refers must
+cease after :c:func:`BufferDestroy()` is called.
+
+Destroying an allocation buffer does not affect objects which have
+been allocated, it just frees resources associated with the buffer
+itself.
+
+The pool class's :c:func:`bufferDestroy()` method is called and then the
+buffer structure is uninitialized and freed.
+
+.. c:function:: BufferCheck(Buffer buffer)
+
+:mps:tag:`method.check` The check method is straightforward, the non-trivial dependencies checked are:
+
+- The ordering constraints between base, init, alloc, and limit.
+- The alignment constraints on base, init, alloc, and limit.
+- That the buffer's rank is identical to the segment's rank.
+
+.. c:function:: void BufferAttach(Buffer buffer, Addr base, Addr limit, Addr init, Size size)
+
+:mps:tag:`method.attach` Set the base, init, alloc, and limit fields so that
+the buffer is ready to start allocating in area of memory. The alloc
+field is set to ``init + size``.
+
+:mps:tag:`method.attach.unbusy` :c:func:`BufferAttach()` must only be applied to
+buffers that are not busy.
+
+.. c:function:: void BufferDetach(Buffer buffer, Pool pool)
+
+:mps:tag:`method.detach` Set the seg, base, init, alloc, and limit fields to
+zero, so that the next reserve request will call the fill method.
+
+:mps:tag:`method.detach.unbusy` :c:func:`BufferDetach()` must only be applied to
+buffers that are not busy.
+
+.. c:function:: Bool BufferIsReset(Buffer buffer)
+
+:mps:tag:`method.isreset` Returns :c:macro:`TRUE` if and only if the buffer is in the
+reset state, that is, with base, init, alloc, and limit all set to
+zero.
+
+.. c:function:: Bool BufferIsReady(Buffer buffer)
+
+:mps:tag:`method.isready` Returns :c:macro:`TRUE` if and only if the buffer is not
+between a reserve and commit. The result is only reliable if the
+client is not currently using the buffer, since it may update the
+alloc and init pointers asynchronously.
+
+.. c:function:: mps_ap_t (BufferAP)(Buffer buffer)
+
+Returns the :c:type:`APStruct` substructure of a buffer.
+
+.. c:function:: Buffer BufferOfAP(mps_ap_t ap)
+
+:mps:tag:`method.ofap` Return the buffer which owns an :c:type:`APStruct`.
+
+:mps:tag:`method.ofap.thread-safe` :c:func:`BufferOfAP()` must be thread safe (see
+impl.c.mpsi.thread-safety). This is achieved simply because the
+underlying operation involved is simply a subtraction.
+
+.. c:function:: Arena BufferArena(Buffer buffer)
+
+:mps:tag:`method.arena` Returns the arena which owns a buffer.
+
+:mps:tag:`method.arena.thread-safe` :c:func:`BufferArena()` must be thread safe
+(see impl.c.mpsi.thread-safety). This is achieved simple because the
+underlying operation is a read of shared-non-mutable data (see
+design.mps.thread-safety).
+
+.. c:function:: Pool BufferPool(Buffer buffer)
+
+Returns the pool to which a buffer is attached.
+
+.. c:function:: Res BufferReserve(Addr *pReturn, Buffer buffer, Size size, Bool withReservoirPermit)
+
+:mps:tag:`method.reserve` Reserves memory from an allocation buffer.
+
+This is a provided version of the reserve procedure described above.
+The size must be aligned according to the buffer alignment. If
+successful, ``ResOK`` is returned and ``*pReturn`` is updated with a
+pointer to the reserved memory. Otherwise ``*pReturn`` is not touched.
+The reserved memory is not guaranteed to have any particular contents.
+The memory must be initialized with a valid object (according to the
+pool to which the buffer belongs) and then passed to the
+:c:func:`BufferCommit()` method (see below). ``BufferReserve(0`` may not be
+applied twice to a buffer without a :c:func:`BufferCommit()` in-between. In
+other words, Reserve/Commit pairs do not nest.
+
+.. c:function:: Res BufferFill(Addr *pReturn, Buffer buffer, Size size, Bool withReservoirPermit)
+
+:mps:tag:`method.fill` Refills an empty buffer. If there is not enough space
+in a buffer to allocate in-line, :c:func:`BufferFill()` must be called to
+"refill" the buffer.
+
+.. c:function:: Bool BufferCommit(Buffer buffer, Addr p, Size size)
+
+:mps:tag:`method.commit` Commit memory previously reserved.
+
+:c:func:`BufferCommit()` notifies the pool that memory which has been
+previously reserved (see above) has been initialized with a valid
+object (according to the pool to which the buffer belongs). The
+pointer ``p`` must be the same as that returned by
+:c:func:`BufferReserve()`, and the size must match the size passed to
+:c:func:`BufferReserve()`.
+
+:c:func:`BufferCommit()` may not be applied twice to a buffer without a
+reserve in between. In other words, objects must be reserved,
+initialized, then committed only once.
+
+Commit returns :c:macro:`TRUE` if successful, :c:macro:`FALSE` otherwise. If commit
+fails and returns :c:macro:`FALSE`, the client may try to allocate again by
+going back to the reserve stage, and may not use the memory at ``p``
+again for any purpose.
+
+Some classes of pool may cause commit to fail under rare
+circumstances.
+
+.. c:function:: BufferTrip(Buffer buffer, Addr p, Size size)
+
+:mps:tag:`method.trip` Act on a tripped buffer. The pool which owns a buffer
+may asynchronously set the buffer limit to zero in order to get
+control over the buffer. If this occurs after a :c:func:`BufferReserve()`
+(but before the corresponding commit), then the :c:func:`BufferCommit()`
+method calls :c:func:`BufferTrip()` and the :c:func:`BufferCommit()` method
+returns with the return value of :c:func:`BufferTrip()`.
+
+:mps:tag:`method.trip.precondition` At the time trip is called, from
+:c:func:`BufferCommit()`, the following are true:
+
+- :mps:tag:`method.trip.precondition.limit` ``limit == 0``
+- :mps:tag:`method.trip.precondition.init` ``init == alloc``
+- :mps:tag:`method.trip.precondition.p` ``p + size == alloc``
+
+
+Diagrams
+--------
+
+Here are a number of diagrams showing how buffers behave. In general,
+the horizontal axis corresponds to mutator action (reserve, commit)
+and the vertical axis corresponds to collector action. I'm not sure
+which of the diagrams are the same as each other, and which are best
+or most complete when they are different, but they all attempt to show
+essentially the same information. It's very difficult to get all the
+details in. These diagrams were drawn by Richard Brooksby, Richard
+Tucker, Gavin Matthews, and others in April 1997. In general, the
+later diagrams are, I suspect, more correct, complete and useful than
+the earlier ones. I have put them all here for the record. Richard
+Tucker, 1998-02-09.
+
+Buffer Diagram:
+Buffer States
+
+Buffer States (3-column)
+Buffer States (4-column)
+Buffer States (gavinised)
+Buffer States (interleaved)
+Buffer States (richardized)
+
+[missing diagrams]
+
+
diff --git a/mps/manual/html/_sources/design/cbs.txt b/mps/manual/html/_sources/design/cbs.txt
deleted file mode 100644
index 0956be703a0..00000000000
--- a/mps/manual/html/_sources/design/cbs.txt
+++ /dev/null
@@ -1,695 +0,0 @@
-.. sources:
-
- ``_
-
-
-.. mps:prefix:: design.mps.cbs
-
-Coalescing block structure
-==========================
-
-
-Introduction
-------------
-
-:mps:tag:`intro` This is the design for :mps:ref:`impl.c.cbs`, which
-implements a data structure for the management of non-intersecting
-memory ranges, with eager coalescence.
-
-:mps:tag:`readership` This document is intended for any MM developer.
-
-:mps:tag:`source` :mps:ref:`design.mps.poolmv2`, :mps:ref:`design.mps.poolmvff`.
-
-:mps:tag:`overview` The "coalescing block structure" is a set of
-addresses (or a subset of address space), with provision for efficient
-management of contiguous ranges, including insertion and deletion,
-high level communication with the client about the size of contiguous
-ranges, and detection of protocol violations.
-
-
-History
--------
-
-:mps:tag:`hist.0` This document was derived from the outline in
-:mps:ref:`design.mps.poolmv2(2)`. Written by Gavin Matthews
-1998-05-01.
-
-:mps:tag:`hist.1` Updated by Gavin Matthews 1998-07-22 in response to
-approval comments in :mps:ref:`change.epcore.anchovy.160040` There is
-too much fragmentation in trapping memory.
-
-:mps:tag:`hist.2` Updated by Gavin Matthews (as part of
-:mps:ref:`change.epcore.brisling.160158`: MVFF cannot be instantiated
-with 4-byte alignment) to document new alignment restrictions.
-
-:mps:tag:`hist.3` Converted from MMInfo database design document.
-Richard Brooksby, 2002-06-07.
-
-:mps:tag:`hist.4` Converted to reStructuredText. Gareth Rees,
-2013-04-14.
-
-
-Definitions
------------
-
-:mps:tag:`def.range` A (contiguous) range of addresses is a semi-open
-interval on address space.
-
-:mps:tag:`def.isolated` A contiguous range is isolated with respect to
-some property it has, if adjacent elements do not have that property.
-
-:mps:tag:`def.interesting` A block is interesting if it is of at least
-the minimum interesting size specified by the client.
-
-
-Requirements
-------------
-
-:mps:tag:`req.set` Must maintain a set of addresses.
-
-:mps:tag:`req.fast` Common operations must have a low amortized cost.
-
-:mps:tag:`req.add` Must be able to add address ranges to the set.
-
-:mps:tag:`req.remove` Must be able to remove address ranges from the set.
-
-:mps:tag:`req.size` Must report concisely to the client when isolated
-contiguous ranges of at least a certain size appear and disappear.
-
-:mps:tag:`req.iterate` Must support the iteration of all isolated
-contiguous ranges. This will not be a common operation.
-
-:mps:tag:`req.protocol` Must detect protocol violations.
-
-:mps:tag:`req.debug` Must support debugging of client code.
-
-:mps:tag:`req.small` Must have a small space overhead for the storage
-of typical subsets of address space and not have abysmal overhead for
-the storage of any subset of address space.
-
-:mps:tag:`req.align` Must support an alignment (the alignment of all
-addresses specifying ranges) of down to ``sizeof(void *)`` without
-losing memory.
-
-
-Interface
----------
-
-:mps:tag:`header` CBS is used through :mps:ref:`impl.h.cbs`.
-
-
-External types
-..............
-
-.. c:type:: typedef struct CBSStruct CBSStruct, *CBS;
-
-:mps:tag:`type.cbs` :c:type:`CBS` is the main datastructure for
-manipulating a CBS. It is intended that a :c:type:`CBSStruct` be
-embedded in another structure. No convenience functions are provided
-for the allocation or deallocation of the CBS.
-
-.. c:type:: typedef struct CBSBlockStruct CBSBlockStruct, *CBSBlock;
-
-:mps:tag:`type.cbs.block` :c:type:`CBSBlock` is the data-structure
-that represents an isolated contiguous range held by the CBS. It is
-returned by the new and delete methods described below.
-
-:mps:tag:`type.cbs.method` The following methods are provided as
-callbacks to advise the client of certain events. The implementation
-of these functions should not cause any CBS function to be called on
-the same CBS. In this respect, the CBS module is not re-entrant.
-
-.. c:type:: typedef void (*CBSChangeSizeMethod)(CBS cbs, CBSBlock block, Size oldSize, SizeNewSize);
-
-:mps:tag:`type.cbs.change.size.method` :c:type:`CBSChangeSizeMethod`
-is the function pointer type, four instances of which are optionally
-registered via CBSInit.
-
-These callbacks are invoked under :c:func:`CBSInsert`,
-:c:func:`CBSDelete`, or :c:func:`CBSSetMinSize` in certain
-circumstances. Unless otherwise stated, ``oldSize`` and ``newSize``
-will both be non-zero, and different. The accessors
-:c:func:`CBSBlockBase`, :c:func:`CBSBlockLimit`, and
-:c:func:`CBSBlockSize` may be called from within these callbacks,
-except within the delete callback when ``newSize`` is zero. See
-:mps:ref:`.impl.callback` for implementation details.
-
-.. c:type:: typedef Bool (*CBSIterateMethod)(CBS cbs, CBSBlock block, void *closureP, unsigned long closureS);
-
-:mps:tag:`type.cbs.iterate.method` :c:type:`CBSIterateMethod` is a
-function pointer type for a client method invoked by the CBS module
-for every isolated contiguous range in address order, when passed to
-the :c:func:`CBSIterate` or :c:func:`CBSIterateLarge` functions. The
-function returns a boolean indicating whether to continue with the
-iteration.
-
-
-External functions
-..................
-
-.. c:function:: Res CBSInit(Arena arena, CBS cbs, CBSChangeSizeMethod new, CBSChangeSizeMethod delete, CBSChangeSizeMethod grow, CBSChangeSizeMethod shrink, Size minSize, Align alignment, Bool mayUseInline)
-
-:mps:tag:`function.cbs.init` :c:func:`CBSInit` is the function that
-initialises the CBS structure. It performs allocation in the supplied
-arena. Four methods are passed in as function pointers (see
-:mps:ref:`.type.*` above), any of which may be ``NULL``. It receives a
-minimum size, which is used when determining whether to call the
-optional methods. The ``mayUseInline`` Boolean indicates whether the
-CBS may use the memory in the ranges as a low-memory fallback (see
-:mps:ref:`.impl.low-mem`). The alignment indicates the alignment of
-ranges to be maintained. An initialised CBS contains no ranges.
-
-:mps:tag:`function.cbs.init.may-use-inline` If ``mayUseInline`` is
-set, then ``alignment`` must be at least ``sizeof(void *)``. In this
-mode, the CBS will never fail to insert or delete ranges, even if
-memory for control structures becomes short. Note that, in such cases,
-the CBS may defer notification of new/grow events, but will report
-available blocks in :c:func:`CBSFindFirst` and :c:func:`CBSFindLast`.
-Such low memory conditions will be rare and transitory. See
-:mps:ref:`.align` for more details.
-
-.. c:function:: void CBSFinish(CBS cbs)
-
-:mps:tag:`function.cbs.finish` :c:func:`CBSFinish` is the function
-that finishes the CBS structure and discards any other resources
-associated with the CBS.
-
-.. c:function:: Res CBSInsert(CBS cbs, Addr base, Addr limit)
-
-:mps:tag:`function.cbs.insert` :c:func:`CBSInsert` is the function
-used to add a contiguous range specified by ``[base,limit)`` to the
-CBS. If any part of the range is already in the CBS, then
-:c:macro:`ResFAIL` is returned, and the CBS is unchanged. This
-function may cause allocation; if this allocation fails, and any
-contingency mechanism fails, then :c:macro:`ResMEMORY` is returned,
-and the CBS is unchanged.
-
-:mps:tag:`function.cbs.insert.callback` :c:func:`CBSInsert` will invoke callbacks as follows:
-
-* ``new``: when a new block is created that is interesting. ``oldSize == 0; newSize >= minSize``.
-
-* ``new``: when an uninteresting block coalesces to become interesting. ``0 < oldSize < minSize <= newSize``.
-
-* ``delete``: when two interesting blocks are coalesced. ``grow`` will also be invoked in this case on the larger of the two blocks. ``newSize == 0; oldSize >= minSize``.
-
-* ``grow``: when an interesting block grows in size. ``minSize <= oldSize < newSize``.
-
-.. c:function:: Res CBSDelete(CBS cbs, Addr base, Addr limit)
-
-:mps:tag:`function.cbs.delete` :c:func:`CBSDelete` is the function
-used to remove a contiguous range specified by ``[base,limit)`` from
-the CBS. If any part of the range is not in the CBS, then
-:c:macro:`ResFAIL` is returned, and the CBS is unchanged. This
-function may cause allocation; if this allocation fails, and any
-contingency mechanism fails, then :c:macro:`ResMEMORY` is returned,
-and the CBS is unchanged.
-
-:mps:tag:`function.cbs.delete.callback` :c:func:`CBSDelete` will
-invoke callbacks as follows:
-
-* ``delete``: when an interesting block is entirely removed. ``newSize == 0; oldSize >= minSize``.
-* ``delete``: when an interesting block becomes uninteresting. ``0 < newSize < minSize <= oldSize``.
-* ``new``: when a block is split into two blocks, both of which are interesting. ``shrink`` will also be invoked in this case on the larger of the two blocks. ``oldSize == 0; newSize >= minSize``.
-* ``shrink``: when an interesting block shrinks in size, but remains interesting. ``minSize <= newSize < oldSize``.
-
-.. c:function:: void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP, unsigned long closureS)
-
-:mps:tag:`function.cbs.iterate` :c:func:`CBSIterate` is the function
-used to iterate all isolated contiguous ranges in a CBS. It receives a
-pointer, unsigned long closure pair to pass on to the iterator method,
-and an iterator method to invoke on every range in address order. If
-the iterator method returns ``FALSE``, then the iteration is
-terminated.
-
-.. c:function:: void CBSIterateLarge(CBS cbs, CBSIterateMethod iterate, void *closureP, unsigned long closureS)
-
-:mps:tag:`function.cbs.iterate.large` :c:func:`CBSIterateLarge` is the
-function used to iterate all isolated contiguous ranges of size
-greater than or equal to the client indicated minimum size in a CBS.
-It receives a pointer, unsigned long closure pair to pass on to the
-iterator method, and an iterator method to invoke on every large range
-in address order. If the iterator method returns ``FALSE``, then the
-iteration is terminated.
-
-.. c:function:: void CBSSetMinSize(CBS cbs, Size minSize)
-
-:mps:tag:`function.cbs.set.min-size` :c:func:`CBSSetMinSize` is the
-function used to change the minimum size of interest in a CBS. This
-minimum size is used to determine whether to invoke the client
-callbacks from :c:func:`CBSInsert` and :c:func:`CBSDelete`. This
-function will invoke either the ``new`` or ``delete`` callback for all
-blocks that are (in the semi-open interval) between the old and new
-values. ``oldSize`` and ``newSize`` will be the same in these cases.
-
-.. c:function:: Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)
-
-:mps:tag:`function.cbs.describe` :c:func:`CBSDescribe` is a function
-that prints a textual representation of the CBS to the given stream,
-indicating the contiguous ranges in order, as well as the structure of
-the underlying splay tree implementation. It is provided for debugging
-purposes only.
-
-.. c:function:: Addr CBSBlockBase(CBSBlock block)
-
-:mps:tag:`function.cbs.block.base` The :c:func:`CBSBlockBase` function
-returns the base of the range represented by the :c:type:`CBSBlock`.
-This function may not be called from the delete callback when the
-block is being deleted entirely.
-
-.. note::
-
- The value of the base of a particular :c:type:`CBSBlock` is not
- guaranteed to remain constant across calls to :c:func:`CBSDelete`
- and :c:func:`CBSInsert`, regardless of whether a callback is
- invoked.
-
-.. c:function:: Addr CBSBlockLimit(CBSBlock block)
-
-:mps:tag:`function.cbs.block.limit` The :c:func:`CBSBlockLimit`
-function returns the limit of the range represented by the
-:c:type:`CBSBlock`. This function may not be called from the delete
-callback when the block is being deleted entirely.
-
-.. note::
-
- The value of the limit of a particular :c:type:`CBSBlock` is not
- guaranteed to remain constant across calls to :c:func:`CBSDelete`
- and :c:func:`CBSInsert`, regardless of whether a callback is
- invoked.
-
-.. c:function:: Size CBSBlockSize(CBSBlock block)
-
-:mps:tag:`function.cbs.block.size` The :c:func:`CBSBlockSize` function
-returns the size of the range represented by the :c:type:`CBSBlock`.
-This function may not be called from the ``delete`` callback when the
-block is being deleted entirely.
-
-.. note::
-
- The value of the size of a particular :c:type:`CBSBlock` is not
- guaranteed to remain constant across calls to :c:func:`CBSDelete`
- and :c:func:`CBSInsert`, regardless of whether a callback is
- invoked.
-
-.. c:function:: Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream)
-
-:mps:tag:`function.cbs.block.describe` The :c:func:`CBSBlockDescribe`
-function prints a textual representation of the :c:type:`CBSBlock` to
-the given stream. It is provided for debugging purposes only.
-
-.. c:function:: Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, CBS cbs, Size size, CBSFindDelete findDelete)
-
-:mps:tag:`function.cbs.find.first` The :c:func:`CBSFindFirst` function
-locates the first block (in address order) within the CBS of at least
-the specified size, and returns its range. If there are no such
-blocks, it returns ``FALSE``. It optionally deletes the top, bottom,
-or all of the found range, depending on the ``findDelete`` argument
-(this saves a separate call to :c:func:`CBSDelete`, and uses the
-knowledge of exactly where we found the range), which must come from
-this enumeration::
-
- enum {
- CBSFindDeleteNONE, /* don't delete after finding */
- CBSFindDeleteLOW, /* delete precise size from low end */
- CBSFindDeleteHIGH, /* delete precise size from high end */
- CBSFindDeleteENTIRE /* delete entire range */
- };
-
-.. c:function:: Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, CBS cbs, Size size, CBSFindDelete findDelete)
-
-:mps:tag:`function.cbs.find.last` The :c:func:`CBSFindLast` function
-locates the last block (in address order) within the CBS of at least
-the specified size, and returns its range. If there are no such
-blocks, it returns ``FALSE``. Like :c:func:`CBSFindFirst`, it
-optionally deletes the range.
-
-.. c:function:: Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, CBS cbs, CBSFindDelete findDelete)
-
-:mps:tag:`function.cbs.find.largest` The :c:func:`CBSFindLargest`
-function locates the largest block within the CBS, and returns its
-range. If there are no blocks, it returns ``FALSE``. Like
-:c:func:`CBSFindFirst`, it optionally deletes the range (specifying
-``CBSFindDeleteLOW`` or ``CBSFindDeleteHIGH`` has the same effect as
-``CBSFindDeleteENTIRE``).
-
-
-Alignment
----------
-
-:mps:tag:`align` When ``mayUseInline`` is specified to permit inline
-data structures and hence avoid losing memory in low memory
-situations, the alignments that the CBS supports are constrained by
-three requirements:
-
-- The smallest possible range (namely one that is the alignment in
- size) must be large enough to contain a single ``void *`` pointer (see
- :mps:ref:`.impl.low-mem.inline.grain`);
-
-- Any larger range (namely one that is at least twice the alignment in
- size) must be large enough to contain two ``void *`` pointers (see
- :mps:ref:`.impl.low-mem.inline.block`);
-
-- It must be valid on all platforms to access a ``void *`` pointer
- stored at the start of an aligned range.
-
-All alignments that meet these requirements are aligned to
-``sizeof(void *)``, so we take that as the minimum alignment.
-
-
-Implementation
---------------
-
-:mps:tag:`impl` Note that this section is concerned with describing
-various aspects of the implementation. It does not form part of the
-interface definition.
-
-
-Size change callback protocol
-.............................
-
-:mps:tag:`impl.callback` The size change callback protocol concerns
-the mechanism for informing the client of the appearance and
-disappearance of interesting ranges. The intention is that each range
-has an identity (represented by the :c:type:`CBSBlock`). When blocks
-are split, the larger fragment retains the identity. When blocks are
-merged, the new block has the identity of the larger fragment.
-
-:mps:tag:`impl.callback.delete` Consider the case when the minimum
-size is ``minSize``, and :c:func:`CBSDelete` is called to remove a
-range of size ``middle``. The two (possibly non-existant) neighbouring
-ranges have (possibly zero) sizes ``left`` and ``right``. ``middle`` is part
-of the :c:type:`CBSBlock` ``middleBlock``.
-
-:mps:tag:`impl.callback.delete.delete` The ``delete`` callback will be
-called in this case if and only if::
-
- left + middle + right >= minSize && left < minSize && right < minSize
-
-That is, the combined range is interesting, but neither remaining
-fragment is. It will be called with the following parameters:
-
-* ``block``: ``middleBlock``
-* ``oldSize``: ``left + middle + right``
-* ``newSize``: ``left >= right ? left : right``
-
-:mps:tag:`impl.callback.delete.new` The ``new`` callback will be
-called in this case if and only if::
-
- left >= minSize && right >= minSize
-
-That is, both remaining fragments are interesting. It will be called
-with the following parameters:
-
-* ``block``: a new block
-* ``oldSize``: ``0``
-* ``newSize``: ``left >= right ? right : left``
-
-:mps:tag:`impl.callback.delete.shrink` The shrink callback will be
-called in this case if and only if::
-
- left + middle + right >= minSize && (left >= minSize || right >= minSize)
-
-That is, at least one of the remaining fragments is still interesting. It will be called with the following parameters:
-
-* ``block``: ``middleBlock``
-* ``oldSize``: ``left + middle + right``
-* ``newSize``: ``left >= right ? left : right``
-
-:mps:tag:`impl.callback.insert` Consider the case when the minimum
-size is ``minSize``, and :c:func:`CBSInsert` is called to add a range
-of size ``middle``. The two (possibly non-existant) neighbouring
-blocks are ``leftBlock`` and ``rightBlock``, and have (possibly zero)
-sizes ``left`` and ``right``.
-
-:mps:tag:`impl.callback.insert.delete` The ``delete`` callback will be
-called in this case if and only if:
-
- left >= minSize && right >= minSize
-
-That is, both neighbours were interesting. It will be called with the
-following parameters:
-
-* ``block``: ``left >= right ? rightBlock : leftBlock``
-* ``oldSize``: ``left >= right ? right : left``
-* ``newSize``: ``0``
-
-:mps:tag:`impl.callback.insert.new` The ``new`` callback will be
-called in this case if and only if:
-
- left + middle + right >= minSize && left < minSize && right < minSize
-
-That is, the combined block is interesting, but neither neighbour was.
-It will be called with the following parameters:
-
-* ``block``: ``left >= right ? leftBlock : rightBlock``
-* ``oldSize``: ``left >= right ? left : right``
-* ``newSize``: ``left + middle + right``
-
-:mps:tag:`impl.callback.insert.grow` The ``grow`` callback will be
-called in this case if and only if::
-
- left + middle + right >= minSize && (left >= minSize || right >= minSize)
-
-That is, at least one of the neighbours was interesting. It will be
-called with the following parameters:
-
-* ``block``: ``left >= right ? leftBlock : rightBlock``
-* ``oldSize``: ``left >= right ? left : right``
-* ``newSize``: ``left + middle + right``
-
-
-Splay tree
-..........
-
-:mps:tag:`impl.splay` The CBS is principally implemented using a splay
-tree (see :mps:ref:`design.mps.splay`). Each splay tree node is
-embedded in a CBSBlock that represents a semi-open address range. The
-key passed for comparison is the base of another range.
-
-:mps:tag:`impl.splay.fast-find` :c:func:`CBSFindFirst` and
-:c:func:`CBSFindLast` use the update/refresh facility of splay trees
-to store, in each :c:type:`CBSBlock`, an accurate summary of the
-maximum block size in the tree rooted at the corresponding splay node.
-This allows rapid location of the first or last suitable block, and
-very rapid failure if there is no suitable block.
-
-:mps:tag:`impl.find-largest` :c:func:`CBSFindLargest` simply finds out
-the size of the largest block in the CBS from the root of the tree
-(using :c:func:`SplayRoot`), and does :c:func:`SplayFindFirst` for a
-block of that size. This is O(log(*n*)) in the size of the free list,
-so it's about the best you can do without maintaining a separate
-priority queue, just to do :c:func:`CBSFindLargest`. Except when the
-emergency lists (see :mps:ref:`.impl.low-mem`) are in use, they are
-also searched.
-
-
-Low memory behaviour
-....................
-
-:mps:tag:`impl.low-mem` Low memory situations cause problems when the
-CBS tries to allocate a new :c:type:`CBSBlock` structure for a new
-isolated range as a result of either :c:func:`CBSInsert` or
-:c:func:`CBSDelete`, and there is insufficient memory to allocation
-the :c:type:`CBSBlock` structure:
-
-:mps:tag:`impl.low-mem.no-inline` If ``mayUseInline`` is ``FALSE``,
-then the range is not added to the CBS, and the call to
-:c:func:`CBSInsert` or :c:func:`CBSDelete` returns ``ResMEMORY``.
-
-:mps:tag:`impl.low-mem.inline` If ``mayUseInline`` is ``TRUE``:
-
-:mps:tag:`impl.low-mem.inline.block` If the range is large enough to
-contain an inline block descriptor consisting of two pointers, then it
-is kept on an emergency block list. The CBS will eagerly attempt to
-add this block back into the splay tree during subsequent calls to
-:c:func:`CBSInsert` and :c:func:`CBSDelete`. The CBS will also keep
-its emergency block list in address order, and will coalesce this list
-eagerly. Some performance degradation will be seen when the emergency
-block list is in use. Ranges on this emergency block list will not be
-made available to the CBS's client via callbacks. :c:func:`CBSIterate`
-and :c:func:`CBSIterateLarge` will not iterate over ranges on this
-list.
-
-:mps:tag:`impl.low-mem.inline.block.structure` The two pointers stored
-are to the next such block (or ``NULL``), and to the limit of the
-block, in that order.
-
-:mps:tag:`impl.low-mem.inline.grain` Otherwise, the range must be
-large enough to contain an inline grain descriptor consisting of one
-pointer, then it is kept on an emergency grain list. The CBS will
-eagerly attempt to add this grain back into either the splay tree or
-the emergency block list during subsequent calls to
-:c:func:`CBSInsert` and :c:func:`CBSDelete`. The CBS will also keep
-its emergency grain list in address order. Some performance
-degradation will be seen when the emergency grain list is in use.
-Ranges on this emergency grain list will not be made available to the
-CBS's client via callbacks. :c:func:`CBSIterate` and
-:c:func:`CBSIterateLarge` will not iterate over ranges on this list.
-
-:mps:tag:`impl.low-mem.inline.grain.structure` The pointer stored is
-to the next such grain, or ``NULL``.
-
-
-The CBS block
-.............
-
-:mps:tag:`impl.cbs.block` The block contains a base-limit pair and a
-splay tree node.
-
-:mps:tag:`impl.cbs.block.special` The base and limit may be equal if
-the block is halfway through being deleted.
-
-:mps:tag:`impl.cbs.block.special.just` This conflates values and
-status, but is justified because block size is very important.
-
-
-Testing
--------
-
-:mps:tag:`test` The following testing will be performed on this module:
-
-:mps:tag:`test.cbstest` There is a stress test for this module in
-:mps:ref:`impl.c.cbstest`. This allocates a large block of memory and
-then simulates the allocation and deallocation of ranges within this
-block using both a :c:type:`CBS` and a :c:type:`BT`. It makes both
-valid and invalid requests, and compares the :c:type:`CBS` response to
-the correct behaviour as determined by the :c:type:`BT`. It also
-iterates the ranges in the :c:type:`CBS`, comparing them to the
-:c:type:`BT`. It also invokes the :c:func:`CBSDescribe` method, but
-makes no automatic test of the resulting output. It does not currently
-test the callbacks.
-
-:mps:tag:`test.pool` Several pools (currently :ref:`pool-mvt` and
-:ref:`pool-mvff`) are implemented on top of a CBS. These pool are
-subject to testing in development, QA, and are/will be heavily
-exercised by customers.
-
-
-Notes for future development
-----------------------------
-
-:mps:tag:`future.not-splay` The initial implementation of CBSs is
-based on splay trees. It could be revised to use any other data
-structure that meets the requirements (especially
-:mps:ref:`.req.fast`).
-
-:mps:tag:`future.hybrid` It would be possible to attenuate the problem
-of :mps:ref:`.risk.overhead` (below) by using a single word bit set to
-represent the membership in a (possibly aligned) word-width of grains.
-This might be used for block sizes less than a word-width of grains,
-converting them when they reach all free in the bit set. Note that
-this would make coalescence slightly less eager, by up to
-``(word-width - 1)``.
-
-
-Risks
------
-
-:mps:tag:`risk.overhead` Clients should note that the current
-implementation of CBSs has a space overhead proportional to the number
-of isolated contiguous ranges. [Four words per range.] If the CBS
-contains every other grain in an area, then the overhead will be large
-compared to the size of that area. [Four words per two grains.] See
-:mps:ref:`.future.hybrid` for a suggestion to solve this problem. An
-alternative solution is to use CBSs only for managing long ranges.
-
-
-Proposed hybrid implementation
-------------------------------
-
-.. note::
-
- The following relates to a pending re-design and does not yet
- relate to any working source version. GavinM 1998-09-25
-
-The CBS system provides its services by combining the services
-provided by three subsidiary CBS modules:
-
-- ``CBSST`` -- Splay Tree: Based on out-of-line splay trees; must
- allocate to insert isolated, which may therefore fail.
-
-- ``CBSBL`` -- Block List: Based on a singly-linked list of variable
- sized ranges with inline descriptors; ranges must be at least large
- enough to store the inline descriptor.
-
-- ``CBSGL`` -- Grain List: Based on a singly-linked list of fixed size
- ranges with inline descriptors; the ranges must be the alignment of
- the CBS.
-
-The three sub-modules have a lot in common. Although their methods are
-not invoked via a dispatcher, they have been given consistent
-interfaces, and consistent internal appearance, to aid maintenance.
-
-Methods supported by sub-modules (not all sub-modules support all
-methods):
-
-- ``MergeRange`` -- Finds any ranges in the specific CBS adjacent to
- the supplied one. If there are any, it extends the ranges, possibly
- deleting one of them. This cannot fail, but should return ``FALSE``
- if there is an intersection between the supplied range and a range
- in the specific CBS.
-
-- ``InsertIsolatedRange`` -- Adds a range to the specific CBS that is
- not adjacent to any range already in there. Depending on the
- specific CBS, this may be able to fail for allocation reasons, in
- which case it should return ``FALSE``. It should :c:func:`AVER` if
- the range is adjacent to or intersects with a range already there.
-
-- ``RemoveAdjacentRanges`` -- Finds and removes from the specific CBS
- any ranges that are adjacent to the supplied range. Should return
- ``FALSE`` if the supplied range intersects with any ranges already
- there.
-
-- ``DeleteRange`` -- Finds and deletes the supplied range from the
- specific CBS. Returns a tri-state result:
-
- - ``Success`` -- The range was successfully deleted. This may have
- involved the creation of a new range, which should be done via
- ``CBSInsertIsolatedRange``.
-
- - ``ProtocolError`` -- Either some non-trivial strict subset of the
- supplied range was in the specific CBS, or a range adjacent to the
- supplied range was in the specific CBS. Either of these indicates
- a protocol error.
-
- - ``NoIntersection`` -- The supplied range was not found in the CBS.
- This may or not be a protocol error, depending on the invocation
- context.
-
-- ``FindFirst`` -- Returns the first (in address order) range in the
- specific CBS that is at least as large as the supplied size, or
- ``FALSE`` if there is no such range.
-
-- ``FindFirstBefore`` -- As ``FindFirst``, but only finds ranges prior
- to the supplied address.
-
-- ``FindLast`` -- As ``FindFirst``, but finds the last such range in
- address order.
-
-- ``FindLastAfter`` -- ``FindLast`` equivalent of ``FindFirstBefore``.
-
-- ``Init`` -- Initialise the control structure embedded in the CBS.
-
-- ``Finish`` -- Finish the control structure embedded in the CBS.
-
-- ``InlineDescriptorSize`` -- Returns the aligned size of the inline descriptor.
-
-- ``Check`` -- Checks the control structure embedded in the CBS.
-
-The CBS supplies the following utilities:
-
-- ``CBSAlignment`` -- Returns the alignment of the CBS.
-
-- ``CBSMayUseInline`` -- Returns whether the CBS may use the memory in
- the ranges stored.
-
-- ``CBSInsertIsolatedRange`` -- Wrapper for ``CBS*InsertIsolatedRange``.
-
-Internally, the ``CBS*`` sub-modules each have an internal structure
-``CBS*Block`` that represents an isolated range within the module. It
-supports the following methods (for sub-module internal use):
-
-- ``BlockBase`` -- Returns the base of the associated range;
-- ``BlockLimit``
-- ``BlockRange``
-- ``BlockSize``
diff --git a/mps/manual/html/_sources/design/check.txt b/mps/manual/html/_sources/design/check.txt
index 024f8b2809a..8e7a121b38b 100644
--- a/mps/manual/html/_sources/design/check.txt
+++ b/mps/manual/html/_sources/design/check.txt
@@ -1,6 +1,109 @@
+.. _design-check:
+
+
.. index::
pair: checking; design
-.. _design-check:
-.. include:: ../../converted/check.rst
+Checking
+========
+
+.. mps:prefix:: design.mps.check
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This documents the design of structure checking within the
+MPS.
+
+:mps:tag:`readership` MPS developers.
+
+
+Implementation
+--------------
+
+:mps:tag:`level` There are three levels of checking:
+
+1. :mps:tag:`level.sig` The lowest level checks only that the
+ structure has a valid ``Signature`` (see
+ design.mps.sig).
+
+2. :mps:tag:`level.shallow` Shallow checking checks all local fields
+ (including signature) and also checks the signatures of any parent
+ or child structures.
+
+3. :mps:tag:`level.deep` Deep checking checks all local fields
+ (including signatures), the signatures of any parent structures,
+ and does full recursive checking on any child structures.
+
+:mps:tag:`level.control` Control over the levels of checking is via the
+definition of at most one of the macros :c:macro:`TARGET_CHECK_SHALLOW`
+(which if defined gives :mps:ref:`.level.shallow`), :c:macro:`TARGET_CHECK_DEEP`
+(which if defined gives :mps:ref:`.level.deep`). If neither macro is defined
+then :mps:ref:`.level.sig` is used. These macros are not intended to be
+manipulated directly by developers, they should use the interface in
+impl.h.target.
+
+:mps:tag:`order` Because deep checking (:mps:ref:`.level.deep`) uses unchecked
+recursion, it is important that child relationships are acyclic
+(:mps:ref:`.macro.down`).
+
+:mps:tag:`fun` Every abstract data type which is a structure pointer should
+have a function ``Check`` which takes a pointer of type
+```` and returns a :c:type:`Bool`. It should check all fields in
+order, using one of the macros in :mps:ref:`.macro`, or document why not.
+
+:mps:tag:`fun.omit` The only fields which should be omitted from a check
+function are those for which there is no meaningful check (for
+example, an unlimited unsigned integer with no relation to other
+fields).
+
+:mps:tag:`fun.return` Although the function returns a :c:type:`Bool`, if the assert
+handler returns (or there is no assert handler), then this is taken to
+mean "ignore and continue", and the check function hence returns
+:c:macro:`TRUE`.
+
+:mps:tag:`macro` Checking is implemented by invoking four macros in
+impl.h.assert:
+
+.. c:function:: CHECKS(type, val)
+
+:mps:tag:`macro.sig` ``CHECKS(type, val)`` checks the signature only, and
+should be called precisely on ``type`` and the received object
+pointer.
+
+.. c:function:: CHECKL(cond)
+
+:mps:tag:`macro.local` ``CHECKL(cond)`` checks a local field (depending on
+level; see :mps:ref:`.level`), and should be called on each local field that
+is not an abstract data type structure pointer itself (apart from
+the signature), with an appropriate normally-true test condition.
+
+.. c:function:: CHECKU(type, val)
+
+:mps:tag:`macro.up` ``CHECKU(type, val)`` checks a parent abstract data
+type structure pointer, performing at most signature checks
+(depending on level; see :mps:ref:`.level`). It should be called with the
+parent type and pointer.
+
+.. c:function:: CHECKD(type, val)
+
+:mps:tag:`macro.down` ``CHECKD(type, val)`` checks a child abstract data
+type structure pointer, possibly invoking ``Check`` (depending
+on level; see :mps:ref:`.level`). It should be called with the child type
+and pointer.
+
+:mps:tag:`full-type` :c:func:`CHECKS()`, :c:func:`CHECKD()`, :c:func:`CHECKU()`, all operate
+only on fully fledged types. This means the type has to provide a
+function ``Bool TypeCheck(Type type)`` where ``Type`` is substituted
+for the name of the type (for example, :c:func:`PoolCheck()`), and the
+expression ``obj->sig`` must be a valid value of type :c:type:`Sig` whenever
+``obj`` is a valid value of type ``Type``.
+
+:mps:tag:`type.no-sig` This tag is to be referenced in implementations
+whenever the form ``CHECKL(ThingCheck(thing))`` is used instead of
+``CHECK{U,D}(Thing, thing)`` because ``Thing`` is not a fully fledged
+type (:mps:ref:`.full-type`).
+
+
diff --git a/mps/manual/html/_sources/design/class-interface.txt b/mps/manual/html/_sources/design/class-interface.txt
index e7be02d9418..8e317c93e21 100644
--- a/mps/manual/html/_sources/design/class-interface.txt
+++ b/mps/manual/html/_sources/design/class-interface.txt
@@ -1,6 +1,261 @@
+.. _design-class-interface:
+
+
.. index::
pair: class interface; design
-.. _design-class-interface:
-.. include:: ../../converted/class-interface.rst
+Pool class interface
+====================
+
+.. mps:prefix:: design.mps.class-interface
+
+
+Introduction
+-------------
+
+:mps:tag:`intro` This document describes the interface and protocols between
+the MPM and the pool class implementations.
+
+.. note::
+
+ This document should be merged into design.mps.pool. Pekka P.
+ Pirinen, 1999-07-20.
+
+
+Methods
+-------
+
+:mps:tag:`methods` These methods are provided by pool classes as part of the
+:c:type:`PoolClass` object (see impl.h.mpmst.class). They form the interface
+which allows the MPM to treat pools in a uniform manner.
+
+The following description is based on the definition of the
+:c:type:`PoolClassStruct` (impl.h.mpmst.class).
+
+If a class is not required to provide a certain method then it should
+set the appropriate ``PoolNo*`` method for that method. It is not
+acceptable to use :c:macro:`NULL`.
+
+.. note::
+
+ There are also some ``PoolTriv*`` methods. David Jones, 1997-08-19.
+
+:mps:tag:`method.name` The name field should be a short, pithy, cryptic name
+for the pool class. Examples are "AMC", "MV".
+
+The ``size`` field is the size of the pool instance structure. For the
+``Foo`` :c:type:`PoolClass` this can reasonably be expected to be
+``sizeof(FooStruct)``.
+
+The ``offset`` field is the offset into the pool instance structure of
+the generic :c:type:`PoolStruct`. Typically this field is called
+``poolStruct``, so something like ``offsetof(FooStruct, poolStruct)``
+is typical. If possible, arrange for this to be zero.
+
+The ``init`` field is the class's init method. This method is called
+via the generic function :c:func:`PoolInit()`, which is in turn called by
+:c:func:`PoolCreate()`. The generic function allocates the pool's structure
+(using the size and offset information), initializes the
+:c:type:`PoolStruct` (generic part) then calls the ``init`` method to do any
+class-specific initialization. Typically this means initializing the
+fields in the class instance structure. If ``init`` returns a non-OK
+result code the instance structure will be deallocated and the code
+returned to the caller of :c:func:`PoolInit()`` or :c:func:`PoolCreate()`. Note that
+the :c:type:`PoolStruct` isn't made fully valid until :c:func:`PoolInit()` returns.
+
+The ``finish`` field is the class's finish method. This method is
+called via the generic function :c:func:`PoolFinish()`, which is in turn
+called by :c:func:`PoolDestroy()`. It is expected to finalise the pool
+instance structure and release any resources allocated to the pool, it
+is expected to release the memory associated with the pool instance
+structure. Note that the pool is valid when it is passed to
+``finish``. The :c:type:`PoolStruct` (generic part) is finished off when the
+class's ``finish`` method returns.
+
+The ``alloc`` field is the class's allocation method. This method is
+called via the generic function :c:func:`PoolAlloc()`. It is expected to
+return a pointer to a fresh (that is, not overlapping with any other
+live object) object of the required size. Failure to allocate should
+be indicated by returning an appropriate Error code, and in such a
+case, ``*pReturn`` should not be updated. Classes are not required to
+provide this method, but they should provide at least one of ``alloc``
+and ``bufferCreate``.
+
+.. note::
+
+ There is no ``bufferCreate``. Gareth Rees, 2013-04-14.
+
+The ``free_`` field is the class's free method. This is intended
+primarily for manual style pools. this method is called via the
+generic function :c:func:`PoolFree()`. The parameters to this method are
+required to correspond to a previous allocation request (possibly via
+a buffer). It is an assertion by the client that the indicated object
+is no longer required and the resources associated with it can be
+recycled. Pools are not required to provide this method.
+
+The ``bufferInit`` field is the class's buffer initialization method.
+It is called by the generic function :c:func:`BufferCreate()`, which allocates
+the buffer descriptor and initializes the generic fields. The pool may
+optionally adjust these fields or fill in extra values when
+``bufferInit`` is called, but often pools set ``bufferInit`` to
+:c:func:`PoolTrivBufferInit()` because they don't need to do any. If
+``bufferInit`` returns a result code other than ``ResOK``, the buffer
+structure is deallocated and the code is returned to the called of
+:c:func:`BufferCreate()`. Note that the :c:type:`BufferStruct` isn't fully valid
+until :c:func:`BufferCreate()` returns.
+
+The ``bufferFinish`` field is the class's buffer finishing method. It
+is called by the the generic function :c:func:`BufferDestroy()`. The pool is
+expected to detach the buffer from any memory and prepare the buffer
+for destruction. The class is expected to release the resources
+associated with the buffer structure, and any unreserved memory in the
+buffer may be recycled. It is illegal for a buffer to be destroyed
+when there are pending allocations on it (that is, an allocation has
+been reserved, but not committed) and this is checked in the generic
+function. This method should be provided if and only if
+``bufferCreate`` is provided. [there is no ``bufferCreate`` -- drj
+1997-08-19]
+
+The ``condemn`` field is used to condemn a pool. This method is called
+via the generic function :c:func:`PoolCondemn()`. The class is expected to
+condemn a subset (possible the whole set) of objects it manages and
+participate in a global trace to determine liveness. The class should
+register the refsig of the condemned set with the trace using
+:c:func:`TraceCondemn()`. The class should expect fix requests (via the fix
+method below) during a global trace. Classes are not required to
+provide this method, but it is expected that automatic style classes
+will. This interface is expected to change in the future.
+
+.. note::
+
+ ``condemn`` now takes an action and a segment and should condemn
+ the segment (turn it white) if it corresponds to the
+ interpretation of the action. David Jones, 1997-08-19.
+
+ It is now called ``whiten``. David Jones, 1998-02-02.
+
+The ``mark`` field is used to mark an entire pool. This method is
+called via the generic function :c:func:`PoolMark()`. The class should
+consider all of its objects, except any set that has been condemned in
+this trace, to be marked, that is ready for scanning. The class should
+arrange that any appropriate invariants are preserved possibly by the
+Protection interface. Classes are not required to provide this method,
+and not doing so indicates that all instances of this class will have
+no fixable or traceable references in them.
+
+.. note::
+
+ ``mark`` is no longer present: ``grey`` turns an entire segment
+ grey. David Jones, 1997-08-19.
+
+The ``scan`` field is used to perform scanning. This method is called
+via the generic function :c:func:`PoolScan()`. The class should scan the
+segment specified. It should scan all the known live (marked, that is,
+those objects on which fix has been called) on the segment and
+accumulate a summary of *all* the objects on the segment. This means
+that mark and sweep pools may have to jump through hoops a little bit
+(see design.mps.poolasm.summary for a pedagogical example). Classes
+are not required to provide this method, and not doing so indicates
+that all instances of this class will have no fixable or traceable
+reference in them.
+
+.. note::
+
+ The ``scan`` method now takes an extra return parameter which
+ classes should use to indicate whether they scanned all objects in
+ segment or not. Classes should return summary only of object they
+ scanned. Caller of this method (:c:func:`TraceScan()`) is responsible
+ for updating summaries correctly when not a total scan. Hence no
+ jumping through hoops required. David Jones, 1998-01-30.
+
+The ``fix`` field is used to perform fixing. This method is called via
+the generic function :c:func:`TraceFix()`. It indicates that the specified
+reference has been found and the class should consider the object
+live. There is provision for adjusting the value of the reference (to
+allow for classes that move objects). Classes are not required to
+provide this method, and not doing so indicates that the class is not
+automatic style (ie it does not use global tracing to determine
+liveness).
+
+The ``reclaim`` field is used to reclaim memory. This method is called
+via the generic function :c:func:`PoolReclaim()`. It indicates that the trace
+has fixed all references to reachable objects.
+
+.. note::
+
+ Actually it indicates that any remaining white objects have now
+ been proved unreachable, hence are dead. David Jones, 1997-08-19.
+
+The class should consider objects that have been condemned and not
+fixed in this trace to be dead and may reclaim the resources
+associated with them. Classes are not required to provide this method.
+
+.. note::
+
+ ``reclaim`` is now called on each segment. David Jones,
+ 1997-08-19.
+
+The ``access`` field is used to indicate client access. This method is
+called via the generic functions :c:func:`SpaceAccess()` and
+:c:func:`PoolAccess()`. It indicates that the client has attempted to access
+the specified region, but has been denied and the request trapped due
+to a protection state. The class should perform any work necessary to
+remove the protection whilst still preserving appropriate invariants
+(typically this will be scanning work). Classes are not required to
+provide this method, and not doing so indicates they never protect any
+memory managed by the pool.
+
+.. note::
+
+ ``access`` is no longer present. David Jones, 1997-08-19.
+
+:mps:tag:`method.act` ``act`` is called when the MPM has decided to execute
+an action that the class declared. The Class should arrange execution
+of the associated work (usually by beginning an incremental trace).
+
+:mps:tag:`method.walk` ``walk`` is used by the heap walker. ``walk`` is only
+required to be implemented by classes which specify the AttrFMT
+attribute (formatted pools). The ``walk`` method should apply the
+passed in function (along with its closure variables (which are also
+passed in) and the object format) to all *black* objects in the
+segment. Padding objects may or may not be included in the walk at the
+classes discretion, in any case in will be the responsibility of the
+client to do something sensible with padding objects.
+
+.. note::
+
+ What about broken hearts? David Jones, 1998-01-30.
+
+The ``describe`` field is used to print out a description of a pool.
+This method is called via the generic function :c:func:`PoolDescribe()`. The
+class should emit an textual description of the pool's contents onto
+the specified stream. Each line should begin with two spaces. Classes
+are not required to provide this method.
+
+
+Events
+------
+
+:mps:tag:`replay` To work with the allocation replayer (see
+design.mps.telemetry.replayer), the pool has to emit an event for each
+call to an external interface, containing all the parameters passed by
+the user. If a new event type is required to carry this information,
+the replayer (impl.c.eventrep) must then be extended to recreate the
+call.
+
+:mps:tag:`replay.Init` In particular, the ``init`` method should emit a
+``PoolInit`` event with all the pool parameters.
+
+
+Text
+-----
+
+:mps:tag:`alloc.size` The pool class implementation defines the meaning of
+the "size" parameter to the ``alloc`` and ``free`` methods. It may not
+actually correspond to a number of bytes of memory.
+
+:mps:tag:`alloc.size.align` In particular, the class may allow an unaligned
+size to be passed.
+
+
diff --git a/mps/manual/html/_sources/design/collection.txt b/mps/manual/html/_sources/design/collection.txt
index ba882faa0d2..fae198acf86 100644
--- a/mps/manual/html/_sources/design/collection.txt
+++ b/mps/manual/html/_sources/design/collection.txt
@@ -1,6 +1,390 @@
+.. _design-collection:
+
+
.. index::
pair: collection framework; design
-.. _design-collection:
-.. include:: ../../converted/collection.rst
+Collection framework
+====================
+
+.. mps:prefix:: design.mps.collection
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document describes the Collection Framework. It's a
+framework for implementing garbage collection techniques and
+integrating them into a system of collectors that all cooperate in
+recycling garbage.
+
+
+Overview
+--------
+
+:mps:tag:`framework` MPS provides a framework that allows the integration of
+many different types of GC strategies and provides many of the basic
+services that those strategies use.
+
+:mps:tag:`framework.cover` The framework subsumes most major GC strategies
+and allows many efficient techniques, like in-line allocation or
+software barriers.
+
+:mps:tag:`framework.overhead` The overhead due to cooperation is low.
+
+.. note::
+
+ But not non-existent. Can we say something useful about it?
+
+:mps:tag:`framework.benefits` The ability to combine collectors contributes
+significantly to the flexibility of the system. The reduction in code
+duplication contributes to reliability and integrity. The services of
+the framework make it easier to write new MM strategies and
+collectors.
+
+:mps:tag:`framework.mpm` The Collection Framework is merely a part of the
+structure of the MPM. See design.mps.architecture and design.mps.arch
+for the big picture.
+
+.. note::
+
+ Those two documents should be combined into one. Pekka P. Pirinen,
+ 1998-01-15.
+
+Other notable components that the MPM manages to integrate into a
+single framework are manually-managed memory and finalization services
+(see design.mps.finalize).
+
+.. note::
+
+ A document describing the design of manually-managed memory is
+ missing. Pekka P. Pirinen, 1998-01-15.
+
+:mps:tag:`see-also` This document assumes basic familiarity with the ideas
+of pool (see design.mps.arch.pools) and segment (see
+design.mps.seg.over).
+
+
+Collection abstractions
+-----------------------
+
+Colours, scanning and fixing
+............................
+
+:mps:tag:`state` The framework knows about the three colours of the
+tri-state abstraction and free blocks. Recording the state of each
+object is the responsibility of the pool, but the framework gets told
+about changes in the states and keeps track of colours in each
+segment. Specifically, it records whether a segment might contain
+white, grey and black objects with respect to each active trace (see
+:mps:ref:`.tracer`)
+
+.. note::
+
+ Black not currently implemented. Pekka P. Pirinen, 1998-01-04.
+
+(A segment might contain objects of all colours at once, or none.)
+This information is approximate, because when an object changes
+colour, or dies, it usually is too expensive to determine if it was
+the last object of its former colour.
+
+:mps:tag:`state.transitions` The possible state transitions are as follows::
+
+ free ---alloc--> black (or grey) or white or none
+ none --condemn-> white
+ none --refine--> grey
+ grey ---scan---> black
+ white ----fix---> grey (or black)
+ black --revert--> grey
+ white --reclaim-> free
+ black --reclaim-> none
+
+:mps:tag:`none-is-black` Outside of a trace, objects don't really have
+colour, but technically, the colour is black. Objects are only
+allocated grey or white during a trace, and by the time the trace has
+finished, they are either dead or black, like the other surviving
+objects. We might then reuse the colour field for another trace, so
+it's convenient to set the colour to black when allocating outside a
+trace. This means that refining the foundation
+(analysis.tracer.phase.condemn.refine), actually turns black segments
+grey, rather than vice versa, but the principle is the same.
+
+:mps:tag:`scan-fix` "Scanning" an object means applying the "fix" function
+to all references in that object. Fixing is the generic name for the
+operation that takes a reference to a white object and makes it
+non-white (usually grey, but black is a possibility, and so is
+changing the reference as we do for weak references). Typical examples
+of fix methods are copying the object into to-space or setting its
+mark bit.
+
+:mps:tag:`cooperation` The separation of scanning and fixing is what allows
+different GC techniques to cooperate. The scanning is done by a method
+on the pool that the scanned object resides in, and the fixing is done
+by a method on the pool that the reference points to.
+
+:mps:tag:`scan-all` Pools provide a method to scan all the grey objects in a
+segment.
+
+
+Reference sets
+..............
+
+:mps:tag:`refsets` The cost of scanning can be significantly reduced by
+storing remembered sets. We have chosen a very compact and efficient
+implementation, called reference sets, or refsets for short (see
+idea.remember).
+
+.. note::
+
+ design.mps.refset is empty! Perhaps some of this should go there.
+ Pekka P. Pirinen, 1998-02-19.
+
+This makes the cost of maintaining them low, so we maintain them for
+all references out of all scannable segments.
+
+:mps:tag:`refsets.approx` You might describe refsets as summaries of all
+references out of an area of memory, so they are only approximations
+of remembered sets. When a refset indicates that an interesting
+reference might be present in a segment, we still have to scan the
+segment to find it.
+
+:mps:tag:`refsets.scan` The refset information is collected during scanning.
+The scan state protocol provides a way for the pool and the format
+scan methods to cooperate in this, and to pass this information to the
+tracer module which checks it and updates the segment (see
+design.mps.scan).
+
+.. note::
+
+ Actually, there's very little doc there. Pekka P. Pirinen,
+ 1998-02-17.
+
+:mps:tag:`refsets.maintain` The MPS tries to maintain the refset information
+when it moves or changes object.
+
+:mps:tag:`refsets.pollution` Ambiguous references and pointers outside the
+arena will introduce spurious zones into the refsets. We put up with
+this to keep the scanning costs down. Consistency checks on refsets
+have to take this into account.
+
+:mps:tag:`refsets.write-barrier` A write-barrier are needed to keep the
+mutator from invalidating the refsets when writing to a segment. We
+need one on any scannable segment whose refset is not a superset of
+the mutator's (and that the mutator can see). If we know what the
+mutator is writing and whether it's a reference, we can just add that
+reference to the refset (figuring out whether anything can be removed
+from the refset is too expensive). If we don't know or if we cannot
+afford to keep the barrier up, the framework can union the mutator's
+refset to the segment's refset.
+
+:mps:tag:`refset.mutator` The mutator's refset could be computed during root
+scanning in the usual way, and then kept up to date by using a
+read-barrier. It's not a problem that the mutator can create new
+pointers out of nothing behind the read-barrier, as they won't be real
+references. However, this is probably not cost-effective, since it
+would cause lots of barrier hits. We'd need a read-barrier on every
+scannable segment whose refset is not a subset of the mutator's (and
+that the mutator can see). So instead we approximate the mutator's
+refset with the universal refset.
+
+
+The tracer
+----------
+
+:mps:tag:`tracer` The tracer is an engine for implementing multiple garbage
+collection processes. Each process (called a "trace") proceeds
+independently of the others through five phases as described in
+analysis.tracer. The following sections describe how the action of
+each phase fits into the framework. See design.mps.trace for details
+
+.. note::
+
+ No, there's not much there, either. Possibly some of this section
+ should go there. Pekka P. Pirinen, 1998-02-18.
+
+:mps:tag:`combine` The tracer can also combine several traces for some
+actions, like scanning a segment or a root. The methods the tracer
+calls to do the work get an argument that tells them which traces they
+are expected to act for.
+
+.. note::
+
+ Extend this.
+
+:mps:tag:`trace.begin` Traces are started by external request, usually from
+a client function or an action (see design.mps.action).
+
+:mps:tag:`trace.progress` The tracer gets time slices from the arena to work
+on a given trace.
+
+.. note::
+
+ This is just a provisional arrangement, in lieu of real progress
+ control. Pekka P. Pirinen, 1998-02-18.
+
+In each slice, it selects a small amount of work to do, based on the
+state of the trace, and does it, using facilities provided by the
+pools. .trace.scan: A typical unit of work is to scan a single
+segment. The tracer can choose to do this for multiple traces at once,
+provided the segment is grey for more than one trace.
+
+:mps:tag:`trace.barrier` Barrier hits might also cause a need to scan :mps:a
+segment (see :mps:ref:`.hw-barriers.hit`). Again, the tracer can
+:mps:choose to combine traces, when it does this.
+
+:mps:tag:`mutator-colour` The framework keeps track of the colour of the
+mutator separately for each trace.
+
+
+The condemn phase
+.................
+
+:mps:tag:`phase.condemn` The agent that creates the trace (see
+:mps:ref:`.trace.begin`) determines the condemned set and colours it white.
+The tracer then examines the refsets on all scannable segments, and if
+it can deduce some segment cannot refer to the white set, it's
+immediately coloured black, otherwise the pool is asked to grey any
+objects in the segment that might need to be scanned (in copying
+pools, this is typically the whole segment).
+
+:mps:tag:`phase.condemn.zones` To get the maximum benefit from the refsets,
+we try to arrange that the zones are a minimal superset (for example,
+generations uniquely occupy zones) and a maximal subset (there's
+nothing else in the zone) of the condemned set. This needs to be
+arranged at allocation time (or when copying during collection, which
+is much like allocation)
+
+.. note::
+
+ Soon, this will be handled by segment loci, see design.mps.locus.
+
+:mps:tag:`phase.condemn.mutator` At this point, the mutator might reference
+any objects, that is, it is grey. Allocation can be in any colour,
+most commonly white.
+
+.. note::
+
+ More could be said about this.
+
+
+The grey mutator phase
+......................
+
+:mps:tag:`phase.grey-mutator` Grey segments are chosen according to some
+sort of progress control and scanned by the pool to make them black.
+Eventually, the tracer will decide to flip or it runs out of grey
+segments, and proceeds to the next phase.
+
+.. note::
+
+ Currently, this phase has not been implemented; all traces flip
+ immediately after condemn. Pekka P. Pirinen, 1998-02-18.
+
+:mps:tag:`phase.grey-mutator.copy` At this stage, we don't want to copy
+condemned objects, because we would need an additional barrier to keep
+the mutator's view of the heap consistent (see
+analysis.async-gc.copied.pointers-and-new-copy).
+
+:mps:tag:`phase.grey-mutator.ambig` This is a good time to get all ambiguous
+scanning out of the way, because we usually can't do any after the
+flip and because it doesn't cause any copying.
+
+.. note::
+
+ Write a detailed explanation of this some day.
+
+
+The flip phase
+..............
+
+:mps:tag:`phase.flip` The roots (see design.mps.root) are scanned. This has
+to be an atomic action as far as the mutator is concerned, so all
+threads are suspended for the duration.
+
+:mps:tag:`phase.flip.mutator` After this, the mutator is black: if we use a
+strong barrier (analysis.async-gc.strong), this means it cannot refer
+to white objects. Allocation will be in black (could be grey as well,
+but there's no point to it).
+
+
+The black mutator phase
+.......................
+
+:mps:tag:`phase.black-mutator` Grey segments are chosen according to some
+sort of progress control and scanned by the pool to make them black.
+Eventually, the tracer runs out of segments that are grey for this
+trace, and proceeds to the next phase.
+
+:mps:tag:`phase.black-mutator.copy` At this stage white objects can be
+relocated, because the mutator cannot see them (as long as a strong
+barrier is used, as we must do for a copying collection, see
+analysis.async-gc.copied.pointers).
+
+
+The reclaim phase
+.................
+
+:mps:tag:`phase.reclaim` The tracer finds the remaining white segments and
+asks the pool to reclaim any white objects in them.
+
+:mps:tag:`phase.reclaim.barrier` Once a trace has started reclaiming
+objects, the others shouldn't try to scan any objects that are white
+for it, because they might have dangling pointers in them.
+
+.. note::
+
+ Needs cross-reference to document that is yet to be written.
+
+ Currently, we reclaim atomically, but it could be incremental, or
+ even overlapped with a new trace on the same condemned set.
+ Pekka P. Pirinen, 1997-12-31.
+
+
+Barriers
+--------
+
+.. note::
+
+ An introduction and a discussion of general principles should go
+ here. This is a completely undesigned area.
+
+
+Hardware barriers
+.................
+
+:mps:tag:`hw-barriers` Hardware barrier services cannot, by their very
+nature, be independently provided to each trace. A segment is either
+protected or not, and we have to set the protection on a segment if
+any trace needs a hardware barrier on it.
+
+:mps:tag:`hw-barriers.supported` The framework currently supports
+segment-oriented Appel-Ellis-Li barriers
+(analysis.async-gc.barrier.appel-ellis-li), and write-barriers for
+keeping the refsets up-to-date. It would not be hard to add Steele
+barriers (analysis.async-gc.barrier.steele.scalable).
+
+:mps:tag:`hw-barriers.hit` When a barrier hit happens, the arena determines
+which segment it was on. The segment colour info is used to determine
+whether it had trace barriers on it, and if so, the appropriate
+barrier action is performed, using the methods of the owning pool. If
+the segment was write-protected, its refset is unioned with the refset
+of the mutator.
+
+.. note:: In practice this is ``RefSetUNIV``.
+
+:mps:tag:`hw-barriers.hit.multiple` Fortunately, if we get a barrier hit on
+a segment with multiple trace barriers on it, we can scan it for all
+the traces that it had a barrier for.
+
+.. note:: Needs link to unwritten section under :mps:ref:`.combine`.
+
+
+Software barriers
+.................
+
+.. note::
+
+ Write something about software barriers.
+
+
diff --git a/mps/manual/html/_sources/design/config.txt b/mps/manual/html/_sources/design/config.txt
index 9958ebcbced..116d3616a35 100644
--- a/mps/manual/html/_sources/design/config.txt
+++ b/mps/manual/html/_sources/design/config.txt
@@ -1,6 +1,542 @@
+.. _design-config:
+
+
.. index::
pair: configuration; design
-.. _design-config:
-.. include:: ../../converted/config.rst
+MPS Configuration
+=================
+
+.. mps:prefix:: design.mps.config
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document describes how the `Memory Pool System
+`_ source code is configured so
+that it can target different architectures, operating systems, build
+environments, varieties, and products.
+
+
+
+Requirements
+------------
+
+:mps:tag:`req.import` The MPS must be simple to include in third-party projects.
+
+:mps:tag:`req.arch` Allow architecture specific configurations of the MPS, so
+that we can vary the MPS according to the target architecture.
+
+:mps:tag:`req.os` Allow operating system specific configurations of the MPS,
+so that we can vary the MPS according to the target OS.
+
+:mps:tag:`req.builder` Allow build environment specific configurations of the
+MPS, so that we can vary the MPS according to the compiler, etc.
+
+:mps:tag:`req.var` Allow configurations with different amounts of
+instrumentation (assertions, metering, etc.).
+
+:mps:tag:`req.impact` The configuration system should have a minimal effect on
+maintainability of the implementation.
+
+:mps:tag:`req.port` The system should be easy to port across platforms.
+
+:mps:tag:`req.maint` Maintenance of the configuration and build system should
+not consume much developer time.
+
+
+Retired requirements
+....................
+
+:mps:tag:`req.prod` Allow product specific configurations of the MPS, so that
+we can build variants of the MPS for use in different products. This
+requirement has been retired on 2012-09-03 as part of work on the
+variety-reform_ branch. Client-specific customisation of the MPS will
+be handled in source control, while the MPS source remains generic, to
+reduce costs and increase reliability. See [RB_2012-09-13]_.
+
+.. _variety-reform: /project/mps/branch/2012-08-15/variety-reform
+
+
+Definitions
+-----------
+
+:mps:tag:`def.platform` A *platform* is a combination of an architecture
+(:mps:ref:`.def.arch`), an operating system (:mps:ref:`.def.os`), and a builder
+(:mps:ref:`.def.builder`). The set of supported platforms is maintained in the
+`Platforms section of "Building the Memory Pool System"
+<../manual/html/guide/build.html#platforms>`_.
+
+:mps:tag:`def.arch` An *architecture* is processor type with associated calling
+conventions and other binary interface stuff these days often called the
+`ABI `_.
+Most importantly for the MPS it determines the layout of the register
+file, thread context, and thread stack.
+
+:mps:tag:`def.os` An *operating system* is the interface to external resources.
+Most importantly for the MPS it determines the low level interface to
+virtual memory (if any) and threading.
+
+:mps:tag:`def.builder` A *builder* is the tools (C compiler, etc.) used to make
+the target (:mps:ref:`.def.target`). The MPS minimises use of compiler-specific
+extensions, but this is handy for suppressing warnings, inlining hints,
+etc.
+
+:mps:tag:`def.var` A *variety* determines things like the amount of debugging,
+internal consistency checking, annotation, etc. In modern IDEs this
+called a "build configuration" and the usual default is to have two:
+"debug" and "release". The MPS predates this convention, but the concept
+is the same.
+
+:mps:tag:`def.prod` A *product* is the intended product into which the MPS will
+fit, e.g. ScriptWorks, Dylan, etc. We no longer maintain this concept
+as a dimension of configuration since :mps:ref:`.req.prod` has been retired.
+
+:mps:tag:`def.target` The *target* is the result of the build.
+
+
+Overview
+--------
+
+:mps:tag:`import.source` The MPS can be simply included in client products as
+source code. Since `version 1.110`_ we made it possible to simply
+include the file ``mps.c`` in a client's build process, without
+requiring a separate build of the MPS or linking a library. This is
+described `section 2.3.1, "Compiling for production" of the MPS manual
+<../manual/html/guide/build.html#compiling-for-production>`_.
+
+.. _`version 1.110`: http://www.ravenbrook.com/project/mps/version/1.110/
+
+:mps:tag:`no-gen` No generated code or external tools are required. On most
+platforms the only tool is the C compiler. On 64-bit Windows we require
+the assembler since Microsoft withdrew in-line assembler from their C
+compiler.
+
+:mps:tag:`no-spaghetti` Several of the MPS team have worked on some extremely
+messy code bases which used a great number of ``#ifdef`` statements.
+These quickly became very expensive to maintain and develop. The
+general rule in the MPS is "no ``#ifdefs``". Instead, platform-specific
+code is kept in separate source files and selected by carefully controlled
+``#ifdefs``, such as in `mps.c <../code/mps.c>`_.
+
+:mps:tag:`min-dep` Dependency on a particular configuration should be
+minimized and localized when developing code. This is enshrined in the
+general rules for implementation [ref?] that are enforced by MPS
+development procedures including code review and inspection.
+
+
+The build system
+----------------
+
+Abstract build function
+.......................
+
+:mps:tag:`build.fun` The MPS implementation assumes only a simple "build
+function" that takes a set of sources, possibly in several languages,
+compiles them with a set of predefined preprocessor symbols, and links
+the result with a set of libraries to form the target::
+
+ target := build(, , )
+
+:mps:tag:`build.sep` Separate compilation and linkage can be seen as a
+memoization of this function, and is not strictly necessary for the
+build. Indeed, since `version 1.110` we found that modern compilers
+are quite happy to compile the whole MPS in one go :mps:ref:`.import.source`.
+
+:mps:tag:`build.cc` A consequence of this approach is that it should always
+be possible to build a complete target with a single UNIX command line
+calling the compiler driver (usually "cc" or "gcc"), for example::
+
+ cc -o main -DCONFIG_VAR_DF foo.c bar.c baz.s -lz
+
+:mps:tag:`build.defs` The "defs" are the set of preprocessor macros which are to be
+predefined when compiling the module sources::
+
+ CONFIG_VAR_
+
+The variety-codes are the letter code that appears after "variety." in
+the tag of the relevant variety document (see variety.*) converted to
+upper case. Currently (2012-09-03):
+
+:mps:tag:`var.hot` :c:macro:`HOT`
+
+ Intended for release in products. Optimised, reduced internal
+ checking, especially on the critical path [RB_2012-09-07]_.
+
+:mps:tag:`var.cool` :c:macro:`COOL`
+
+ Intended for use during development. Moderately thorough internal
+ consistency checking. Reduced optimisation to allow for
+ single-stepping.
+
+:mps:tag:`var.rash` :c:macro:`RASH`
+
+ No internal checking at all. Slight performance improvement over
+ :mps:ref:`.var.hot` at the cost of early detection of memory management
+ bugs. We do not advise use of this variety, as memory management
+ bugs tend to be extremely expensive to deal with.
+
+:mps:tag:`var.diag` :c:macro:`DIAG` (deprecated)
+
+ This variety does some client-specific analysis and produces some
+ specialised diagnostic output, and is not intended for general use.
+ It will be phased out of the open sources.
+
+:mps:tag:`default.hot` If no :c:macro:`CONFIG_VAR` is present, :c:macro:`HOT` is assumed in
+`config.h`_.
+
+:mps:tag:`build.srcs` The "srcs" are the set of sources that must be
+compiled in order to build the target. The set of sources may vary
+depending on the configuration. For example, different sets of sources
+may be required to build different architectures.
+
+.. note::
+
+ This is a dependency between the makefile (or whatever) and the
+ module configuration in `config.h`_.
+
+:mps:tag:`build.libs` The "libs" are the set of libraries to which the
+compiled sources must be linked in order to build the target. For
+example, when building a test program, it might include the ANSI C
+library and an operating system interface library.
+
+
+File Structure
+..............
+
+:mps:tag:`file.dir` The MPS source code is arranged in a single directory
+called "code" containing all the sources for the whole family of
+targets.
+
+:mps:tag:`file.base` The names of sources must be unique in the first eight
+characters in order to conform to FAT filesystem naming restrictions.
+(Do not scoff -- this has been an important requirement as recently as
+2012!)
+
+:mps:tag:`file.ext` The extension may be up to three characters and directly
+indicates the source language.
+
+:mps:tag:`file.platform` Platform-specific files include the platform code
+in their name. See :mps:ref:`.mod.impls`.
+
+
+Modules and naming
+..................
+
+:mps:tag:`mod.unique` Each module has an identifier which is unique within the MPS.
+
+:mps:tag:`mod.impls` Each module has one or more implementations which may be
+in any language supported by the relevant build environment.
+
+:mps:tag:`mod.primary` The primary implementation of a module is written in
+target-independent ANSI C in a source file with the same name as the
+module.
+
+:mps:tag:`mod.an` Where there are platform-specific implementations and an
+inferior portable ANSI C fallback implementation, "an" is used in
+place of the platform code.
+
+:mps:tag:`mod.secondary` The names of other implementations should begin
+with the same prefix (the module id or a shortened version of it) and
+be suffixed with on or more target parameter codes (defined below). In
+particular, the names of assembly language sources must include the
+target parameter code for the relevant architecture.
+
+:mps:tag:`mod.example` For example, the stack scanner is defined in `ss.h
+<../code/ss.h>`_ (which is platform-independent). It has some
+platform-independent C in `ss.c <../code/ss.c>`_ and, for example,
+`ssw3i6mv.c <../code/ssw3i6mv.c>`_ is specific to Windows on the x64
+architecture built with Microsoft Visual C.
+
+
+Build system rationale
+......................
+
+:mps:tag:`build.rat` This simple design makes it possible to build the MPS
+using many different tools. Microsoft Visual C and other graphical
+development tools do not support much in the way of generated sources,
+staged building, or other such stuff. The Visual C and Xcode "project"
+files correspond closely to a closure of the build function
+(:mps:ref:`.build.fun`). The simplicity of the build function has also made it
+easy to set up builds using NMAKE (DOS), MPW (Macintosh), and to get the
+MPS up and running on other platforms such as FreeBSD and Linux in very
+little time. The cost of maintaining the build systems on these various
+platforms is also reduced to a minimum, allowing the MPS developers to
+concentrate on primary development. The source code is kept simple and
+straightforward. When looking at MPS sources you can tell exactly what
+is going to be generated with very little context. The sources are not
+munged beyond the standard ANSI C preprocessor.
+
+:mps:tag:`build.port` The portability requirement (:mps:ref:`.req.port`) implies that
+the build system must use only standard tools that will be available on
+all conceivable target platforms. Experience of development
+environments on the Macintosh (Metrowerks Codewarrior) and Windows NT
+(Visual C++) indicates that we cannot assume much sophistication in the
+use of file structure by development environments. The best that we can
+hope for is the ability to combine a fixed list of source files,
+libraries, and predefined preprocessor symbols into a single target.
+
+:mps:tag:`build.maint` The maintainability requirement (:mps:ref:`.req.maint`) implies
+that we don't spend time trying to develop a set of tools to support
+anything more complicated than the simple build function described
+above. The effort in constructing and maintaining a portable system of
+this kind is considerable. Such efforts failed in the Electronic
+Publishing division of Harlequin.
+
+
+Implementation
+--------------
+
+:mps:tag:`impl` The two implementation files `config.h`_ and `mpstd.h`_ can be
+seen as preprocessor programs which "accept" build parameters and "emit"
+configuration parameters (:mps:ref:`.fig.impl`). The build parameters are
+defined either by the builder (in the case of target detection) or by
+the build function (in the case of selecting the variety).
+
+:mps:tag:`fig.impl`
+
+=========================== ============== ===========================================
+Build parameters Source file Configuration parameters
+=========================== ============== ===========================================
+:c:macro:`CONFIG_VAR_HOT` ⟶ ``config.h`` ⟶ :c:macro:`MPS_ASSERT_STRING`, etc.
+``_WIN32`` ⟶ ``mpstd.h`` ⟶ :c:macro:`MPS_OS_W3`, etc.
+=========================== ============== ===========================================
+
+:mps:tag:`impl.dep` No source code, other than the directives in `config.h`_
+and `mpstd.h`_, should depend on any build parameters. That is,
+identifers beginning "CONFIG\_" should only appear in impl.h.config.
+Code may depend on configuration parameters in certain, limited ways, as
+defined below (:mps:ref:`.conf`).
+
+.. _`config.h`: <../code/config.h>
+.. _`mpstd.h`: <../code/mpstd.h>
+
+
+Target platform detection
+.........................
+
+:mps:tag:`pf` The target platform is "detected" by the preprocessor directives in
+`mpstd.h`_.
+
+:mps:tag:`pf.form` This file consists of sets of directives of the form::
+
+ #elif
+ #define MPS_PF_
+ #define MPS_OS_
+ #define MPS_ARCH_
+ #define MPS_BUILD_
+ #define MPS_T_WORD
+ #define MPS_T_ULONGEST
+ #define MPS_WORD_SHIFT
+ #define MPS_PF_ALIGN
+
+:mps:tag:`pf.detect` The conjunction of builder predefinitions is a constant
+expression which detects the target platform. It is a logical AND of
+expressions which look for preprocessor symbols defined by the build
+environment to indicate the target. These must be accompanied by a
+reference to the build tool documentation from which the symbols came.
+For example::
+
+ /* "Predefined Macros" from "Visual Studio 2010" on MSDN
+ * . */
+
+ #elif defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86)
+
+:mps:tag:`pf.codes` The declarations of the platform, operating system,
+architecture, and builder codes define preprocessor macros corresponding
+the the target detected (:mps:ref:`.pf.detect`). For example::
+
+ #define MPS_PF_W3I3MV
+ #define MPS_OS_W3
+ #define MPS_ARCH_I3
+ #define MPS_BUILD_MV
+
+:mps:tag:`pf.word` The declaration of :c:macro:`MPS_T_WORD` defines the unsigned
+integral type which corresponds, on the detected target, to the
+machine word. It is used to defined the MPS Word type
+(design.mps.type.word). For example::
+
+ #define MPS_T_WORD unsigned long
+
+We avoid using ``typedef`` here because `mpstd.h`_ could potentially
+be included in assembly language source code.
+
+:mps:tag:`pf.word-width` The declaration of :c:macro:`MPS_WORD_WIDTH` defines the
+number of bits in the type defined by :c:macro:`MPS_T_WORD` (:mps:ref:`.pf.word`) on the
+target. For example::
+
+ #define MPS_WORD_WIDTH 32
+
+:mps:tag:`pf.word-shift` The declaration of :c:macro:`MPS_WORD_SHIFT` defines the log
+to the base 2 of :c:macro:`MPS_WORD_WIDTH`. For example::
+
+ #define MPS_WORD_SHIFT 5
+
+:mps:tag:`pf.pf-align` The declaration of :c:macro:`MPS_PF_ALIGN` defines the minimum
+alignment which must be used for a memory block to permit any normal
+processor memory access. In other words, it is the maximum alignment
+required by the processor for normal memory access. For example::
+
+ #define MPS_PF_ALIGN 4
+
+:mps:tag:`pf.ulongest` The declaration of :c:macro:`MPS_T_ULONGEST` defines the
+longest available unsigned integer type on the platform. This is
+usually just ``unsigned long`` but under Microsoft C on 64-bit Windows
+``unsigned long`` is just 32-bits (curse them!) For example::
+
+ #define MPS_T_ULONGEST unsigned __int64
+
+:mps:tag:`pf.pf-string` The declaration of :c:macro:`MPS_PF_STRING` defines a string
+that is used to identify the target platform in `version.c
+<../code/version.c>`_. For example::
+
+ #define MPS_PF_STRING "w3i6mv"
+
+
+Target varieties
+................
+
+:mps:tag:`var` The target variety is handled by preprocessor directives in
+impl.h.config.
+
+:mps:tag:`var.form` The file contains sets of directives of the form::
+
+ #if defined(CONFIG_VAR_COOL)
+ #define CONFIG_ASSERT
+ #define CONFIG_ASSERT_ALL
+ #define CONFIG_STATS
+
+:mps:tag:`var.detect` The configured variety is one of the variety
+preprocessor definitions passed to the build function
+(:mps:ref:`.build.defs`), for example, :c:macro:`CONFIG_VAR_COOL`. These are
+decoupled in order to keep the number of supported varieties small,
+controlling each feature (for example, assertions) by a single
+preprocessor definition, and maintaining flexibility about which
+features are enabled in each variety.
+
+:mps:tag:`var.symbols` The directives should define whatever symbols are
+necessary to control featrues. These symbols parameterize other parts
+of the code, such as the declaration of assertions, etc. The symbols
+should all begin with the prefix :c:macro:`CONFIG_`.
+
+
+Source code configuration
+-------------------------
+
+:mps:tag:`conf` This section describes how the configuration may affect the
+source code of the MPS.
+
+:mps:tag:`conf.limit` The form of dependency allowed is carefully limited to
+ensure that code remains maintainable and portable (:mps:ref:`.req.impact`).
+
+:mps:tag:`conf.min` The dependency of code on configuration parameters should
+be kept to a minimum in order to keep the system maintainable
+(:mps:ref:`.req.impact`).
+
+
+Configuration Parameters
+........................
+
+:mps:tag:`conf.params` The compilation of a module is parameterized by::
+
+ MPS_ARCH_
+ MPS_OS_
+ MPS_BUILDER_
+ MPS_PF_
+
+
+Abstract and Concrete Module Interfaces
+.......................................
+
+:mps:tag:`abs.caller` Basic principle: the caller musn't be affected by
+configuration of a module. This reduces complexity and dependency of
+configuration. All callers use the same abstract interface. Caller
+code does not change.
+
+:mps:tag:`abs.interface` Abstract interface includes:
+
+- method definitions (logical function prototypes which may be macro methods)
+- names of types
+- names of constants
+- names of structures and fields which form part of the interface, and
+ possibly their types, depending on the protocol defined
+- the protocols
+
+:mps:tag:`abs.rule` The abstract interface to a module may not be altered by a
+configuration parameter. However, the concrete interface may vary.
+
+For example, this isn't allowed, because there is a change in the interface::
+
+ #if defined(PROT_FOO)
+ void ProtSpong(Foo foo, Bar bar);
+ #else
+ int ProtSpong(Bar bar, Foo foo);
+ #endif
+
+This example shows how::
+
+ #ifdef PROTECTION
+ void ProtSync(Space space);
+ /* more decls. */
+ #else /* PROTECTION not */
+ #define ProtSync(space) NOOP
+ /* more decls. */
+ #endif /* PROTECTION */
+
+or::
+
+ #if defined(PROT_FOO)
+ typedef struct ProtStruct {
+ int foo;
+ } ProtStruct;
+ #define ProtSpong(prot) X((prot)->foo)
+ #elif defined(PROT_BAR)
+ typedef struct ProtStruct {
+ float bar;
+ } ProtStruct;
+ #define ProtSpong(prot) Y((prot)->bar)
+ #else
+ #error "No PROT_* configured."
+ #endif
+
+Configuration parameters may not be used to vary implementations in C files.
+For example, this sort of thing::
+
+ int map(void *base, size_t size)
+ {
+ #if defined(MPS_OS_W3)
+ VirtualAlloc(foo, bar, base, size);
+ #elif defined(MPS_OS_SU)
+ mmap(base, size, frob);
+ #else
+ #error "No implementation of map."
+ #endif
+ }
+
+This violates :mps:ref:`.no-spaghetti`.
+
+
+To document
+-----------
+- What about constants in config.h?
+- Update files to refer to this design document.
+- Explain the role of ``mps.c``
+- Reference to ``build.txt``
+- Procedures for adding an architecture, etc.
+- Reduce duplication in this document (especially after
+ `Configuration Parameters`_ which looks like it's been pasted in from
+ elsewhere.)
+
+
+References
+----------
+
+.. [RB_2012-09-07] Richard Brooksby. Ravenbrook Limited. 2012-09-07. "`The critical path through the MPS `__".
+
+.. [RB_2012-09-13] Richard Brooksby. Ravenbrook Limited. 2013-09-13. "`The Configura CET custom mainline `__".
+
+.. [PP_2005-03-01] Pekka Pirinen. Global Graphics. 2005-03-01. "`MPS platforms `__".
+
+
diff --git a/mps/manual/html/_sources/design/critical-path.txt b/mps/manual/html/_sources/design/critical-path.txt
index 8bf3f0c5c44..26830c82baf 100644
--- a/mps/manual/html/_sources/design/critical-path.txt
+++ b/mps/manual/html/_sources/design/critical-path.txt
@@ -1,8 +1,364 @@
+.. _design-critical-path:
+
+
.. index::
single: critical path
single: path; critical
single: Memory Pool System; critical path
-.. _design-critical-path:
-.. include:: ../../converted/critical-path.rst
+The critical path through the MPS
+=================================
+
+ single: critical path
+ single: path; critical
+ single: Memory Pool System; critical path
+
+
+Introduction
+------------
+The critical path is a key concept in the design of the `Memory Pool
+System `_. Code on the critical
+path is usually executed more than any other code in the process. A
+change of just one instruction on the critical path can make as much as
+a 1% difference in overall run-time. A lot of the design of the MPS is
+arranged around making the critical path as short and fast as possible.
+This document describes the critical path and explains some of that
+design, with reference to more detailed documents.
+
+
+What makes the critical path critical
+-------------------------------------
+In order to determine which object can be recycled, the garbage
+collector has to frequently examine a very large number of pointers in
+the program's objects. It does this by scanning_ memory, both
+allocated objects and roots (such as the thread stacks).
+
+This means that the scanning functions must loop over pretty much *every
+word in memory* sooner or later. The MPS takes great pains to avoid
+scanning memory which does not need scanning, but to get good
+performance, scanning must be highly optimised.
+
+What's more, the scanning functions apply an operation called "fix" to
+every pointer (or potential pointer) that they find in the objects in
+memory. Fixing also attempts to eliminate uninteresting pointers as
+fast as possible, but it has to do some work on every object that is
+being considered for recycling, and that can be a large proportion of
+the objects in existence. The path through fixing must also be highly
+optimised, especially in the early stages.
+
+
+How the MPS avoids scanning and fixing
+--------------------------------------
+This is just a brief overview of how the MPS is designed to reduce
+unnecessary scanning and fixing.
+
+Firstly, the MPS must occasionally decide which objects to try to
+recycle. It does this using various facts it knows about the objects,
+primarily their age and whether they've survived previous attempts at
+recycling them. It then `"condemns"`_ a large number of objects
+at once, and each of these objects must be "preserved" by fixing
+references to them.
+
+When the MPS condemns objects it chooses sets of objects in a small set
+of "zones" in memory (preferably a single zone). The zone of an object
+can be determined extremely quickly from its address, without looking at
+the object or any other data structure.
+
+The MPS arranges that objects which will probably die at the same time
+are in the same zones.
+
+The MPS allocates in "segments". Each segment is of the order of one
+"tract" of memory (generally the same as the operating system page
+size, usually 4KiB or 8KiB) but may be larger if there are large
+objects inside. The MPS maintains a "summary" of the zones pointed to
+by all the pointers in a segment from previous scans.
+
+So, once the MPS has decided what to condemn, it can quickly eliminate
+all segments which definitely do not point to anything in those zones.
+This avoids a large amount of scanning. It is an implementation of a
+`remembered set`_, though it is unlike that in most other GCs.
+
+In addition, the fix operation can quickly ignore pointers to the wrong
+zones. This is called the "zone check" and is a BIBOP_ technique.
+
+Even if a pointer passes the zone check, it may still not point to a
+segment containing condemned objects. The next stage of the fix
+operation is to look up the segment pointed to by the pointer and see if
+it was condemned. This is a fast lookup.
+
+After that, each pool class must decide whether the pointer is to a
+condemned object and do something to preserve it. This code is still
+critical. The MPS will have tried to condemn objects that are dead, but
+those objects are still likely to be in segments with other objects that
+must be preserved. The pool class fix method must quickly distinguish
+between them.
+
+Furthermore, many objects will be preserved at least once in their
+lifetime, so even the code that preserves an object needs to be highly
+efficient. (Programs in languages like ML might not preserve 95% of
+their objects even once, but many other programs will preserve nearly
+all of theirs many times.)
+
+
+Where to find the critical path
+-------------------------------
+Very briefly, the critical path consists of five stages:
+
+1. The scanner, which iterates over pointers in objects. The MPS has
+ several internal scanners, but the most important ones will be format
+ scanners in client code registered through :c:func:`mps_format_create()`
+ functions.
+
+ .. note::
+
+ There needs to be a chapter in the manual explaining how to
+ write a good scanner. Then that could be linked from here.
+
+2. The first-stage fix, which filters out pointers inline in the
+ scanner. This is implemented in :c:func:`MPS_FIX()` macros in
+ mps.h_.
+
+.. _mps.h: ../code/mps.h
+
+3. The second-stage fix, which filters out pointers using general
+ information about segments. This is ``_mps_fix2`` in
+ `trace.c <../code/trace.c>`_.
+
+4. The third-stage fix, which filters out pointers using pool-specific
+ information. Implemented in pool class functions called :c:func:`AMCFix()`,
+ :c:func:`LOFix()`, etc. in pool*.c.
+
+5. Preserving the object, which might entail
+
+ - marking_ it to prevent it being recycled; and/or
+
+ - copying_ it and updating the original pointer (or just
+ updating the pointer, if the object has previously been
+ copied); and/or
+
+ - adding it to a queue of objects to be scanned later, if it
+ contains pointers.
+
+ Found in or near the pool class fix functions.
+
+
+The format scanner
+------------------
+The critical path starts when a format scan method is called. That is a
+call from the MPS to a client function of type :c:type:`mps_fmt_scan_t`
+registered with one of the :c:func:`mps_format_create()` functions in mps.h_.
+
+Here is an example of part of a format scanner for scanning contiguous
+runs of pointers, from `fmtdy.c <../code/fmtdy.c>`_, the scanner for the `Open Dylan`_
+runtime::
+
+ static mps_res_t dylan_scan_contig(mps_ss_t mps_ss,
+ mps_addr_t *base, mps_addr_t *limit)
+ {
+ mps_res_t res;
+ mps_addr_t *p; /* reference cursor */
+ mps_addr_t r; /* reference to be fixed */
+
+ MPS_SCAN_BEGIN(mps_ss) {
+ p = base;
+ loop: if(p >= limit) goto out;
+ r = *p++;
+ if(((mps_word_t)r&3) != 0) /* pointers tagged with 0 */
+ goto loop; /* not a pointer */
+ if(!MPS_FIX1(mps_ss, r)) goto loop;
+ res = MPS_FIX2(mps_ss, p-1);
+ if(res == MPS_RES_OK) goto loop;
+ return res;
+ out: assert(p == limit);
+ } MPS_SCAN_END(mps_ss);
+
+ return MPS_RES_OK;
+ }
+
+(To help with understanding optimisation of this code, it's written in
+a pseudo-assembler style, with one line roughly corresponding to each
+instruction of an idealized intermediate code.)
+
+The MPS C interface provides macros to try to help optimise this code.
+The ``mps_ss`` object is a "scan state" and contains data that is used
+to eliminate uninteresting pointers now, and record information which
+will be used to reduce scanning in future by maintaining the
+remembered set.
+
+The macros :c:func:`MPS_SCAN_BEGIN()` and :c:func:`MPS_SCAN_END()` load key data
+from the scan state into local variables, and hopefully into processor
+registers. This avoids aliasing values that we know won't change when
+calls are made to ``_mps_fix2`` later, and so allows the compiler to
+keep the scan loop small and avoid unnecessary memory references.
+
+This scanner knows that words not ending in 0b00 aren't pointers to
+objects, so it eliminates them straight away. This is a kind of
+`reference tag`_ chosen by the client for its object representation.
+
+Next, the pointer is tested using :c:func:`MPS_FIX1()`. This performs fast
+tests on the pointer without using any other memory. In particular, it
+does the "zone check" described in section 3. If a pointer fails these
+tests, it isn't interesting and can be skipped. It is very important
+to proceed to the next pointer as fast as possible in this case.
+
+Having passed these tests, we need to fix the pointer using other data
+in memory, and possibly call the MPS to preserve the object. This is
+what :c:func:`MPS_FIX2()` does. The important distinction here is that
+:c:func:`MPS_FIX2()` can fail and return an error code, which must be
+propagated without ado by returning from the scanner. Separating
+:c:func:`MPS_FIX1()` from :c:func:`MPS_FIX2()` helps keep the error handling code
+away from the tight loop with the zone check.
+
+``MPS_FIX*``, the macro/inline part of the fix operation, are referred
+to as "fix stage 1" or "the first stage fix" in other documents and
+comments.
+
+If these inline checks pass, ``_mps_fix2`` is called. If the MPS has
+been built as a separate object file or library, this is where the
+function call out of the scan loop happens. Since version 1.110 of the
+MPS, we encourage clients to compile the MPS in the same translation
+unit as their format code, so that the compiler can be intelligent
+about inlining parts of ``_mps_fix2`` in the format scanner. The
+instructions for doing this are in `Building the Memory Pool System
+<../manual/build.txt>`_, part of the manual.
+
+
+The second stage fix in the MPM
+-------------------------------
+If a pointer gets past the first-stage fix filters, it is passed to
+``_mps_fix2``, the "second stage fix". The second stage can filter out
+yet more pointers using information about segments before it has to
+consult the pool class.
+
+The first test applied is the "tract test". The MPS looks up the tract
+containing the address in the tract table, which is a simple linear
+table indexed by the address shifted -- a kind of flat page table.
+
+Note that if the arena has been extended, the tract table becomes less
+simple, and this test may involved looking in more than one table.
+This will cause a considerable slow-down in garbage collection
+scanning. This is the reason that it's important to give a good
+estimate of the amount of address space you will ever occupy with
+objects when you initialize the arena.
+
+The pointer might not even be in the arena (and so not in any tract).
+The first stage fix doesn't guarantee it. So we eliminate any pointers
+not in the arena at this stage.
+
+If the pointer is in an allocated tract, then the table also contains
+a cache of the "white set" -- the set of garbage collection traces for
+which the tract is "interesting". If a tract isn't interesting, then
+we know that it contains no condemned objects, and we can filter out
+the pointer.
+
+If the tract is interesting them it's part of a segment containing
+objects that have been condemned. The MPM can't know anything about
+the internal layout of the segment, so at this point we dispatch to
+the third stage fix.
+
+This dispatch is slightly subtle. We have a cache of the function to
+dispatch to in the scan state, which has recently been looked at and
+is with luck still in the processor cache. The reason there is a
+dispatch at all is to allow for a fast changeover to emergency garbage
+collection, or overriding of garbage collection with extra operations.
+Those are beyond the scope of this document. Normally, ``ss->fix``
+points at :c:func:`PoolFix()`, and we rely somewhat on modern processor
+`branch target prediction
+`_).
+:c:func:`PoolFix()` is passed the pool, which is fetched from the tract
+table entry, and that should be in the cache.
+
+:c:func:`PoolFix()` itself dispatches to the pool class. Normally, a
+dispatch to a pool class would indirect through the pool class object.
+That would be a double indirection from the tract, so instead we have
+a cache of the pool's fix method in the pool object. This also allows
+a pool class to vary its fix method per pool instance, a fact that is
+exploited to optimize fixing in the AMC Pool depending on what kind of
+object format it is managing.
+
+
+The third stage fix in the pool class
+-------------------------------------
+The final stage of fixing is entirely dependent on the pool class. The
+MPM can't, in general, know how the objects within a pool are arranged,
+so this is pool class specific code.
+
+Furthermore, the pool class must make decisions based on the "reference
+rank" of the pointer. If a pointer is ambiguous (``RankAMBIG``) then it
+can't be changed, so even a copying pool class can't move an object.
+On the other hand, if the pointer is weak (``RankWEAK``) then the pool fix
+method shouldn't preserve the object at all, even if it's condemned.
+
+The exact details of the logic that the pool fix must implement in
+order to co-operate with the MPM and other pools are beyond the scope
+of this document, which is about the critical path. Since it is on
+the critical path, it's important that whatever the pool fix does is
+simple and fast and returns to scanning as soon as possible.
+
+The first step, though, is to further filter out pointers which aren't
+to objects, if that's its policy. Then, it may preserve the object,
+according to its policy, and possibly ensure that the object gets
+scanned at some point in the future, if it contains more pointers.
+
+If the object is moved to preserve it (for instance, if the pool class
+implements a copying GC), or was already moved when fixing a previous
+reference to it, the reference being fixed must be updated (this is
+the origin of the term "fix").
+
+As a simple example, :c:func:`LOFix()` is the pool fix method for the Leaf
+Only pool class. It implements a marking garbage collector, and does
+not have to worry about scanning preserved objects because it is used
+to store objects that don't contain pointers. (It is used in compiler
+run-time systems to store binary data such as character strings, thus
+avoiding any scanning, decoding, or remembered set overhead for them.)
+
+:c:func:`LOFix()` filters any ambiguous pointers that aren't aligned, since
+they can't point to objects it allocated. Otherwise it subtracts the
+segment base address and shifts the result to get an index into a mark
+bit table. If the object wasn't marked and the pointer is weak, then
+it sets the pointer to zero, since the object is about to be recycled.
+Otherwise, the mark bit is set, which preserves the object from
+recycling when `LOReclaim` is called later on. `LOFix` illustrates
+about the minimum and most efficient thing a pool fix method can do.
+
+
+Other considerations
+--------------------
+So far this document has described the ways in which the garbage
+collector is designed around optimising the critical path. There are a
+few other things that the MPS does that are important.
+
+Firstly, inlining is very important. The first stage fix is inlined
+into the format scanner by being implemented in macros in
+mps.h_. And to get even better inlining, `we
+recommend <../manual/build.txt>`_ that the whole MPS is compiled in a
+single translation unit with the client format and that strong global
+optimisation is applied.
+
+Secondly, we are very careful with code annotations on the critical
+path. Assertions, statistics, and telemetry are all disabled on the
+critical path in "hot" (production) builds. (In fact, it's because the
+critical path is critical that we can afford to leave annotations
+switched on elsewhere.)
+
+Last, but by no means least, we pay a lot of brainpower and measurement
+to the critical path, and are very very careful about changing it. Code
+review around the critical path is especially vigilant.
+
+And we write long documents about it.
+
+
+References
+----------
+.. [MMRef] "The Memory Management Reference"; .
+.. _scanning: http://www.memorymanagement.org/glossary/s.html#scan
+.. _marking: http://www.memorymanagement.org/glossary/m.html#marking
+.. _copying: http://www.memorymanagement.org/glossary/c.html#copying.garbage.collection
+.. _`"condemns"`: http://www.memorymanagement.org/glossary/c.html#condemned.set
+.. _BIBOP: http://www.memorymanagement.org/glossary/b.html#bibop
+.. _`remembered set`: http://www.memorymanagement.org/glossary/r.html#remembered.set
+.. _`reference tag`: http://www.memorymanagement.org/glossary/t.html#tag
+.. _`Open Dylan`: http://opendylan.org/
+
+
diff --git a/mps/manual/html/_sources/design/diag.txt b/mps/manual/html/_sources/design/diag.txt
new file mode 100644
index 00000000000..4c8a16a1137
--- /dev/null
+++ b/mps/manual/html/_sources/design/diag.txt
@@ -0,0 +1,290 @@
+.. _design-diag:
+
+
+.. index::
+ pair: diagnostic feedback; design
+
+
+Diagnostic feedback
+===================
+
+.. mps:prefix:: design.mps.diag
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document describes how to use the diagnostic feedback
+mechanism in the Memory Pool System.
+
+:mps:tag:`sources` Initially abased on [RHSK_2007-04-13]_ and [RHSK_2007-04-18]_.
+
+
+Overview
+--------
+
+Diagnostic feedback is information created by the MPS diagnostic
+system for the purpose of helping MPS programmers client-code
+programmers.
+
+Such a piece of information is called "a diagnostic". (See also
+:mps:ref:`.parts`.)
+
+A diagnostic is not intended to be end-user readable (or visible), or
+machine-parseable.
+
+A diagnostic is not intended to be stable from one release to the
+next: it may be modified or removed at any time.
+
+
+Requirements
+------------
+
+MPS diagnostic feedback code must do these things:
+
+- calculate, store, and propagate data;
+- collate, synthesise, and format it into a human-useful diagnostic;
+- control (for example, filter) output of diagnostics;
+- use a channel to get the diagnostic out.
+
+Note: the knowledge/code/logic for constructing the human-useful
+message is kept inside normal MPS source code. This means it is always
+in-sync with changes to the MPS. This also means that any external
+utilities used to display the messages do not need to understand, or
+keep in sync with, the details of what's going inside the MPS.
+
+
+Usage
+-----
+
+To run the MPS and get diagnostic output from it:
+
+1. Use a variety with diagnostics compiled-in. Currently, that means
+ variety.di. See ``config.h``.
+
+2. Check that the diagnostics you require are generated, by looking in
+ MPS source for invocations of the appropriate macro (for example,
+ :c:func:`DIAG_SINGLEF()`).
+
+3. Check that the diagnostics you require will be output, by looking
+ at the diagnostic filter rules in ``diag.c``.
+
+4. Run the MPS and client in an environment that supports the channel
+ used (for example, at a command-line if using :c:func:`WriteF()`).
+
+
+What is a diagnostic?
+.....................
+
+A diagnostic has three parts:
+
+1. a trigger condition, that causes this diagnostic to be emitted;
+2. a text tag (for example, "TraceStart") which is the name of this
+ diagnostic; and
+3. a paragraph of human-useful text.
+
+A diagnostic is emitted by the MPS at a certain point in time when a
+certain event happens.
+
+Diagnostics are not nested. Every diagnostic must have a tag. Each
+diagnostic should have a unique tag (uniqueness is just to help the
+humans; the diagnostic system does not care).
+
+The paragraph of text can be many lines long. It usually explains what
+event caused the diagnostic to be emitted, and commonly also includes
+the output of some :c:func:`Describe()` methods for various relevant
+objects. (For example, the ``TraceStart`` diagnostic might call, and
+include the output generated by, the :c:func:`TraceDescribe()` method).
+
+How do I control (filter) which diagnostics I see?
+..................................................
+
+All diagnostics are emitted and then filtered according to the
+"diagnostic filter rules".
+
+The first level of control is filtering by tag. (For example, only
+show ``TraceStart`` diagnostics).
+
+The second level of control is filtering by paragraph content. (For
+example, only show ``TraceStart`` diagnostics where the trace is
+started because a nursery generation is full).
+
+The third level of control is filtering by line content. (For example,
+only show lines containing the word ``whiteSet``).
+
+See ``diag.c`` for details.
+
+Note: the entire filtering mechanism can be turned off, so that
+diagnostics go immediately to ``mps_lib_get_stdout(0``, with no
+buffering or filtering See impl.c.diag.filter-disable.
+
+
+How to write a diagnostic
+-------------------------
+
+Improve stateless Describe methods where possible
+.................................................
+
+Where possible, don't put clever code into an event-triggered
+diagnostic: put it into a stateless :c:func:`Describe()` method instead, and
+then call that method when emitting your diagnostic.
+
+For example::
+
+ FooDescribe(Foo foo, mps_lib_FILE *stream)
+ {
+ /* show value of new "quux" field */
+ WriteF(stream, "Foo: $P { quux: $U }\n", foo, foo->quux);
+ }
+
+ FooWibble(Foo foo)
+ {
+ ...
+ DIAG_FIRSTF(( "FooWibble", "Wibbling foo $P", foo, NULL));
+ DIAG( FooDescribe(foo, DIAG_STREAM); );
+ DIAG_END("FooWibble");
+ ...
+ }
+
+This is much better, because other people can use your human-useful
+output in their diagnostics, or 'live' in a debugger.
+
+
+Use the output macros
+.....................
+
+For a simple diagnostic, use :c:func:`DIAG_SINGLEF()`. This begins the tag,
+puts text into the paragraph, and ends the tag immediately.
+
+For a more complex diagnostic, the first call must be
+:c:func:`DIAG_FIRSTF()`, which begins a diag tag.
+
+While a tag is current, you can add text to the diagnostic's paragraph
+using :c:func:`DIAG_MOREF()`, and ``WriteF( DIAG_STREAM, ... )``.
+
+.. note::
+
+ :c:macro:`DIAG_STREAM` is not a real standard C library stream. If you
+ want stream-level access, you may use :c:func:`Stream_fputc()` and
+ :c:func:`Stream_fputs()`.
+
+End the tag by calling :c:macro:`DIAG_END`.
+
+
+Compile away in non-diag varieties; no side effects
+...................................................
+
+Wrap non-output code with the :c:func:`DIAG()` and :c:func:`DIAG_DECL()` macros,
+to make sure that non-diag varieties do not execute
+diagnostic-generating code.
+
+For complex diagnostic-generating code, it may be cleaner to move it
+into a separate local function. Put ``_diag`` on the end of the function
+name (for example, :c:func:`TraceStart_diag()`).
+
+Obviously, diagnostic-generating code must have no side effects.
+
+
+Choosing tags
+.............
+
+Tags should be valid C identifiers. Unless you know of a good reason
+why not. (Not currently checked).
+
+There's no formal scheme for tag naming, but make it helpful and
+informally hierarchical, for example, ``TraceBegin``, ``TraceStart``,
+``TraceEnd``, and so on, not ``BeginTrace``, ``EndTrace``.
+
+
+Writing good paragraph text
+...........................
+
+IMPORTANT: Make your diagnostics easy to understand! Other people will
+read your diagnostics! Make them clear and helpful. Do not make them
+terse and cryptic. If you use symbols, print a key in the diagnostic.
+(If you don't want to see this the screen clutter, then you can always
+add a filter rule to your personal rule set to filter it out).
+
+
+Maintaining helpful filter rules
+................................
+
+If you add a noisy diagnostic, add a rule to the default ruleset to
+turn it off.
+
+
+How the MPS diagnostic system works
+-----------------------------------
+
+Channels
+........
+
+The recommended channel is :c:func:`WriteF()` to standard output.
+
+Other possible of future channels might be:
+
+- :c:func:`printf()`;
+- a new type (yet to be defined) of ``mps_message``;
+- squirt them into the telemetry-log-events system;
+- telnet.
+
+Currently, only :c:func:`printf()` and :c:func:`WriteF()` are supported. See the
+:c:macro:`DIAG_WITH_` macros in ``mpm.h``.
+
+You can also use a debugger to call :c:func:`Describe()` methods directly,
+from within the debugger.
+
+Note: it is unfortunate that choice of channel may (for some channels)
+also dictate the form of the code that synthesises the message. (For
+example, :c:func:`WriteF()` style parameter-expansion is not possible when
+using the :c:func:`printf()` channel, because there is no way to get
+:c:func:`WriteF()` to produce its output into a string). This is just a
+technical hitch; logically, the code that synthesises a diagnostic
+message should not care which channel will be used to transmit it out
+of the MPS.
+
+
+Parts of the MPS diagnostic system
+..................................
+
+:mps:tag:`parts` The following facilities are considered part of the MPS
+diagnostic system:
+
+- the :c:func:`Describe()` methods.
+- the :c:macro:`DIAG` macros (:c:macro:`DIAG`, :c:macro:`DIAG_DECL`, ``DIAG_*F``, and so on);
+- the :c:macro:`STATISTIC` macros (see ``mpm.h``);
+- the :c:macro:`METER` macros and meter subsystem.
+
+
+Related systems
+...............
+
+The MPS diagnostic system is separate from the following other MPS
+systems:
+
+- The telemetry-log-events system. This emits much more data, in a
+ less human-readable form, requires MPS-aware external tools, and is
+ more stable from release to release). In non-diagnostic telemetry
+ varieties, the telemetry-log-events system emits events that log all
+ normal MPS actions. In diagnostic telemetry varieties, it may emit
+ additional events containing diagnostic information. Additionally,
+ the telemetry-log-events stream might in future be available as a
+ channel for emitting human-readable text diagnostics. See also
+ design.mps.telemetry.
+
+- The MPS message system. This is present in all varieties, and
+ manages asynchronous communication from the MPS to the client
+ program). However, the MPS message system might in future also be
+ available as a channel for emitting diagnostics. See also
+ design.mps.message.
+
+
+
+References
+----------
+
+.. [RHSK_2007-04-13] Richard Kistruck. 2007-04-13. "`diagnostic feedback from the MPS `_".
+
+.. [RHSK_2007-04-18] Richard Kistruck. 2007-04-18. "`Diverse types of diagnostic feedback `_".
+
+
diff --git a/mps/manual/html/_sources/design/finalize.txt b/mps/manual/html/_sources/design/finalize.txt
index 9cd0521e392..01fbc83f1ab 100644
--- a/mps/manual/html/_sources/design/finalize.txt
+++ b/mps/manual/html/_sources/design/finalize.txt
@@ -1,6 +1,120 @@
+.. _design-finalize:
+
+
.. index::
pair: finalization; design
-.. _design-finalize:
-.. include:: ../../converted/finalize.rst
+Finalization
+============
+
+.. mps:prefix:: design.mps.finalize
+
+
+Overview
+--------
+
+:mps:tag:`overview` Finalization is implemented internally using the
+Guardian Pool Class (design.mps.poolmrg). Objects can be registered
+for finalization using an interface function (called
+:c:func:`mps_finalize()`). Notification of finalization is given to the client
+via the messaging interface. ``PoolClassMRG`` (design.mps.poolmrg)
+implements a Message Class which implements the finalization messages.
+
+
+Requirements
+------------
+
+:mps:tag:`req` Historically only Dylan had requirements for finalization,
+see req.dylan.fun.final. Now (2003-02-19) Configura have requirements
+for finalization. Happily they are very similar.
+
+
+Architecture
+------------
+
+External interface
+..................
+
+:mps:tag:`if.register` :c:func:`mps_finalize()` increases the number of times that
+an object has been registered for finalization by one. The object must
+have been allocated from the arena (space). Any finalization messages
+that are created for this object will appear on the arena's message
+queue. The MPS will attempt to finalize the object that number of
+times.
+
+:mps:tag:`if.deregister` :c:func:`mps_definalize()` reduces the number of times that
+the object located at ``obj`` has been registered for finalization by
+one. It is an error to definalize an object that has not been
+registered for finalization.
+
+:mps:tag:`if.deregister.not` At the moment (1997-08-20) :c:func:`mps_definalize()`
+is not implemented.
+
+:mps:tag:`if.get-ref` :c:func:`mps_message_finalization_ref()` returns the reference
+to the finalized object stored in the finalization message.
+
+
+Implementation
+--------------
+
+:mps:tag:`int.over` Registering an object for finalization corresponds to
+allocating a reference of rank FINAL to that object. This reference is
+allocated in a guardian object in a pool of ``PoolClassMRG`` (see
+design.mps.poolmrg).
+
+:mps:tag:`int.arena.struct` The MRG pool used for managing final references
+is kept in the Arena (Space), referred to as the "final pool".
+
+:mps:tag:`int.arena.lazy` The pool is lazily created. It will not be created
+until the first object is registered for finalization.
+
+:mps:tag:`int.arena.flag` There is a flag in the Arena that indicates
+whether the final pool has been created yet or not.
+
+.. c:function:: Res ArenaFinalize(Arena arena, Ref addr)
+
+:mps:tag:`int.finalize.create` Creates the final pool if it has not been
+created yet.
+
+:mps:tag:`int.finalize.alloc` Allocates a guardian in the final pool.
+
+:mps:tag:`int.finalize.write` Writes a reference to the object into the
+guardian object.
+
+:mps:tag:`int.finalize.all` That's all.
+
+:mps:tag:`int.finalize.error` If either the creation of the pool or the
+allocation of the object fails then the error will be reported back to
+the caller.
+
+:mps:tag:`int.finalize.error.no-unwind` This function does not need to do
+any unwinding in the error cases because the creation of the pool is
+not something that needs to be undone.
+
+:mps:tag:`int.arena-destroy.empty` :c:func:`ArenaDestroy()` empties the message
+queue by calling :c:func:`MessageEmpty()`.
+
+:mps:tag:`int.arena-destroy.final-pool` If the final pool has been created
+then :c:func:`ArenaDestroy()` destroys the final pool.
+
+:mps:tag:`access` :c:func:`mps_message_finalization_ref()` needs to access the
+finalization message to retrieve the reference and then write it to
+where the client asks. This must be done carefully, in order to avoid
+breaking the invariants or creating a hidden root.
+
+:mps:tag:`access.invariants` We protect the invariants by using special
+routines :c:func:`ArenaRead()` and :c:func:`ArenaPoke()` to read and write the
+reference. This works as long as there's no write-barrier collection.
+
+.. note::
+
+ Instead of :c:func:`ArenaPoke()`, we could put in an :c:func:`ArenaWrite()`
+ that would be identical to :c:func:`ArenaPoke()`, except that it would
+ :c:func:`AVER()` the invariant (or it can just :c:func:`AVER()` that there are
+ no busy traces unflipped). When we get write-barrier collection,
+ we could change it to do the real thing, but in the absence of a
+ write-barrier, it's functionally identical to :c:func:`ArenaPoke()`.
+ Pekka P. Pirinen, 1997-12-09.
+
+
diff --git a/mps/manual/html/_sources/design/fix.txt b/mps/manual/html/_sources/design/fix.txt
index 2d11b05a35f..9b2b059bc0a 100644
--- a/mps/manual/html/_sources/design/fix.txt
+++ b/mps/manual/html/_sources/design/fix.txt
@@ -1,6 +1,56 @@
+.. _design-fix:
+
+
.. index::
pair: fix function; design
-.. _design-fix:
-.. include:: ../../converted/fix.rst
+The generic fix function
+========================
+
+.. mps:prefix:: design.mps.fix
+
+
+Introduction
+-------------
+
+:mps:tag:`intro` Fix is the interface through which the existence of
+references are communicated from the MPS client to the MPS. The
+interface also allows the value of such references to be changed (this
+is necessary in order to implement a moving memory manager).
+
+
+Architecture
+-------------
+
+:mps:tag:`protocol.was-marked` The :c:type:`ScanState` has a :c:type:`Bool`
+``wasMarked`` field. This is used for finalization.
+
+:mps:tag:`protocol.was-marked.set` All pool-specific fix methods must set
+the ``wasMarked`` field in the :c:type:`ScanState` that they are passed.
+
+:mps:tag:`protocol.was-marked.meaning` If the pool-specific fix method sets
+the ``wasMarked`` field to :c:macro:`FALSE` it is indicating the object
+referred to by the ref (the one that it is supposed to be fixing) has
+not previously been marked (ie, this is the first reference to this
+object that has been fixed), and that the object was white (in
+condemned space).
+
+:mps:tag:`protocol.was-marked.conservative` It is always okay to set the
+``wasMarked`` field to :c:macro:`TRUE`.
+
+:mps:tag:`protocol.was-marked.finalizable` The MRG pool (design.mps.poolmrg)
+uses the value of the ``wasMarked`` field to determine whether an
+object is finalizable.
+
+
+Implementation
+---------------
+
+:mps:tag:`fix.nailed` In a copying collection, a non-ambiguous fix to a
+broken heart should be snapped out *even if* there is a ``RankAMBIG``
+ref to same object (that is, if the broken heart is nailed); the
+``RankAMBIG`` reference must either be stale (no longer in existence)
+or bogus.
+
+
diff --git a/mps/manual/html/_sources/design/guide.hex.trans.txt b/mps/manual/html/_sources/design/guide.hex.trans.txt
index 3c877c5ad08..5f31fb48d26 100644
--- a/mps/manual/html/_sources/design/guide.hex.trans.txt
+++ b/mps/manual/html/_sources/design/guide.hex.trans.txt
@@ -1,6 +1,102 @@
+.. _design-guide.hex.trans:
+
+
.. index::
pair: hexadecimal; transliterating
-.. _design-guide.hex.trans:
-.. include:: ../../converted/guide.hex.trans.rst
+Transliterating the alphabet into hexadecimal
+=============================================
+
+.. mps:prefix:: guide.hex.trans
+
+
+Introduction
+------------
+
+:mps:tag:`scope` This document explains how to represent the alphabet as
+hexadecimal digits.
+
+:mps:tag:`readership` This document is intended for anyone devising
+arbitrary constants which may appear in hex-dumps.
+
+:mps:tag:`sources` This transliteration was supplied by RichardK in
+mail.richardk.1997-04-07.13-44.
+
+
+Transliteration
+---------------
+
+:mps:tag:`forward` The chosen transliteration is as follows::
+
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ
+ ABCDEF9811C7340BC6520F3812
+
+:mps:tag:`backward` The backwards transliteration is as follows::
+
+ 0 OU
+ 1 IJY
+ 2 TZ
+ 3 MW
+ 4 N
+ 5 S
+ 6 R
+ 7 L
+ 8 HX
+ 9 G
+ A A
+ B BP
+ C CKQ
+ D D
+ E E
+ F FV
+
+:mps:tag:`pad` If padding is required (to fill a hex constant length), you
+should use 9's, because G is rare and can usually be inferred from
+context.
+
+:mps:tag:`punc` There is no formal scheme for spaces, or punctuation. It is
+suggested that you use 9 (as :mps:ref:`.pad`).
+
+
+Justification
+--------------
+
+:mps:tag:`letters` The hexadecimal letters (A-F) are all formed by
+similarity of sound. B and P sound similar, as do F and V, and C, K, &
+Q can all sound similar.
+
+:mps:tag:`numbers` The numbers (0-9) are all formed by similarity of shape
+(but see :mps:ref:`.trans.t`). Nevertheless, 1=IJY retains some similarity of
+sound.
+
+:mps:tag:`trans.t` T is an exception to :mps:ref:`.numbers`, but is such a common
+letter that it deserves it.
+
+
+Notes
+-----
+
+:mps:tag:`change` This transliteration differs from the old transliteration
+used for signatures (see design.mps.sig(0)), as follows: J:6->1;
+L:1->7; N:9->4; R:4->6; W:8->3; X:5->8; Y:E->I.
+
+:mps:tag:`problem.mw` There is a known problem that M and W are both common,
+map to the same digit (3), and are hard to distinguish in context.
+
+:mps:tag:`find.c` It is possible to find all 8-digit hexadecimal constants
+and how many times they're used in C files, using the following Perl
+script::
+
+ perl5 -n -e 'BEGIN { %C=(); } if(/0x([0-9A-Fa-f]{8})/) { $C{$1} = +[] if(
+ !defined($C{$1})); push(@{$C{$1}}, $ARGV); } END { foreach $H (sort(keys(%C)))
+ { printf "%3d %s %s\n", scalar(@{$C{$H}}), $H, join(", ", @{@C{$H}}); } }' *.c
+ *.h
+
+:mps:tag:`comment` It is a good idea to add a comment to any constant
+declaration indicating the English version and which letters were
+selected (by capitalisation), e.g.::
+
+ #define SpaceSig ((Sig)0x5195BACE) /* SIGnature SPACE */
+
+
diff --git a/mps/manual/html/_sources/design/guide.impl.c.format.txt b/mps/manual/html/_sources/design/guide.impl.c.format.txt
new file mode 100644
index 00000000000..89dad45e73b
--- /dev/null
+++ b/mps/manual/html/_sources/design/guide.impl.c.format.txt
@@ -0,0 +1,427 @@
+.. _design-guide.impl.c.format:
+
+
+.. index::
+ pair: C language; formatting guide
+ pair: C language formatting; guide
+
+
+C Style -- formatting
+=====================
+
+.. mps:prefix:: guide.impl.c.format
+ pair: C language; formatting guide
+ pair: C language formatting; guide
+
+
+Introduction
+------------
+
+:mps:tag:`scope` This document describes the Ravenbrook conventions for the
+general format of C source code in the MPS.
+
+:mps:tag:`readership` This document is intended for anyone working on or with the
+C source code.
+
+
+General Formatting Conventions
+------------------------------
+
+Line Width
+..........
+
+:mps:tag:`width` Lines should be no wider than 72 characters. :mps:tag:`width.why` Many
+people use 80 column terminal windows so that multiple windows can be
+placed side by side. Restricting lines to 72 characters allows line
+numbering to be used (in vi for example) and also allows diffs to be
+displayed without overflowing the terminal.
+
+White Space
+...........
+
+:mps:tag:`space.notab` No tab characters should appear in the source files.
+Ordinary spaces should be used to indent and format the sources.
+:mps:tag:`space.notab.why` Tab characters are displayed differently on different
+platforms, and sometimes translated back and forth, destroying layout
+information.
+
+:mps:tag:`space.punct` There should always be whitespace after commas and
+semicolons and similar punctuation.
+
+:mps:tag:`space.op` Put white space around operators in expressions, except when
+removing it would make the expression clearer by binding certain
+sub-expressions more tightly. For example::
+
+ foo = x + y*z;
+
+:mps:tag:`space.control` One space between the keyword, ``switch``, ``while``,
+``for`` and the following paren. :mps:tag:`space.control.why` This distinguishes
+control statements lexically from function calls, making it easier to
+distinguish them visually and when searching with tools like grep.
+
+:mps:tag:`space.function.not` No space between a function name and the following
+paren beginning its argument list.
+
+Sections and Paragraphs
+.......................
+
+:mps:tag:`section` Source files can be thought of as breaking down into
+"sections" and "paragraphs". A section might be the leader comment of a
+file, the imports, or a set of declarations which are related.
+
+:mps:tag:`section.space` Precede sections by two blank lines (except the first
+one in the file, which should be the leader comment in any case).
+
+:mps:tag:`section.comment` Each section should start with a banner comment (see
+.comment.banner) describing what the section contains.
+
+:mps:tag:`para` Within sections, code often breaks down into natural units called
+"paragraphs". A paragraph might be a set of strongly related
+declarations (Init and Finish, for example), or a few lines of code
+which it makes sense to consider together (the assignment of fields into
+a structure, for example).
+
+:mps:tag:`para.space` Precede paragraphs by a single blank line.
+
+Statements
+..........
+
+:mps:tag:`statement.one` Generally only have at most one statement per line. In
+particular the following are deprecated::
+
+ if (thing) return;
+
+ a=0; b=0;
+
+ case 0: f = inRampMode ? AMCGen0RampmodeFrequency : AMCGen0Frequency;
+
+:mps:tag:`statement.one.why` Debuggers can often only place breakpoints on lines,
+not expressions or statements within a line. The ``if (thing) return;`` is
+a particularly important case, if thing is a reasonably rare return
+condition then you might want to breakpoint it in a debugger session.
+Annoying because ``if (thing) return;`` is quite compact and pleasing
+otherwise.
+
+Indentation
+...........
+
+:mps:tag:`indent` Indent the body of a block by two spaces. For formatting
+purposes, the "body of a block" means:
+
+- statements between braces,
+- a single statement following a lone ``if``;
+- statements in a switch body; see .switch.
+
+(:mps:tag:`indent.logical` The aim is to group what we think of as logical
+blocks, even though they may not exactly match how "block" is used in
+the definition of C syntax).
+
+Some examples::
+
+ if (res != ResOK) {
+ SegFinish(&span->segStruct);
+ PoolFreeP(MV->spanPool, span, sizeof(SpanStruct));
+ return res;
+ }
+
+ if (res != ResOK)
+ goto error;
+
+ if (j == block->base) {
+ if (j+step == block->limit) {
+ if (block->thing)
+ putc('@', stream);
+ }
+ } else if (j+step == block->limit) {
+ putc(']', stream);
+ pop_bracket();
+ } else {
+ putc('.', stream);
+ }
+
+ switch (c) {
+ case 'A':
+ c = 'A';
+ p += 1;
+ break;
+ }
+
+:mps:tag:`indent.goto-label` Place each goto-label on a line of its own,
+outdented to the same level as the surrounding block. Then indent the
+non-label part of the statement normally.
+
+::
+
+ result foo(void)
+ {
+ statement();
+ if (error)
+ goto foo;
+ statement();
+ return OK;
+
+ foo:
+ unwind();
+ return ERROR;
+ }
+
+:mps:tag:`indent.case-label` Outdent case- and default-labels in a switch
+statement in the same way as :mps:ref:`.indent.goto-label`. See :mps:ref:`.switch`.
+
+:mps:tag:`indent.cont` If an expression or statement won't fit on a single line,
+indent the continuation lines by two spaces, apart from the following
+exception:
+
+:mps:tag:`indent.cont.parens` if you break a statement inside a parameter list or
+other parenthesized expression, indent so that the continuation lines up
+just after the open parenthesis. For example::
+
+ PoolClassInit(&PoolClassMVStruct,
+ "MV", init, finish, allocP, freeP,
+ NULL, NULL, describe, isValid);
+
+:mps:tag:`indent.cont.expr` Note that when breaking an expression it is clearer
+to place the operator at the start of the continuation line::
+
+ CHECKL(AddrAdd((Addr)chunk->pageTableMapped,
+ BTSize(chunk->pageTablePages))
+ <= AddrAdd(chunk->base, chunk->ullageSize));
+
+This is particularly useful in long conditional expressions that use &&
+and ||. For example::
+
+ } while(trace->state != TraceFINISHED
+ && (trace->emergency || traceWorkClock(trace) < pollEnd));
+
+:mps:tag:`indent.hint` Usually, it is possible to determine the correct
+indentation for a line by looking to see if the previous line ends with
+a semicolon. If it does, indent to the same amount, otherwise indent by
+two more spaces. The main exceptions are lines starting with a close
+brace, goto-labels, and line-breaks between parentheses.
+
+Positioning of Braces
+.....................
+
+:mps:tag:`brace.otb` Use the "One True Brace" (or OTB) style. This places the
+open brace after the control word or expression, separated by a space,
+and when there is an else, places that after the close brace. For
+example::
+
+ if(isBase) {
+ new->base = limit;
+ new->limit = block->limit;
+ block->limit = base;
+ new->next = block->next;
+ block->next = new;
+ } else {
+ new->base = block->base;
+ new->limit = base;
+ block->base = limit;
+ new->next = block;
+ *prev = new;
+ }
+
+The same applies to struct, enum, union.
+
+:mps:tag:`brace.otb.function.not` OTB is never used for function definitions.
+
+:mps:tag:`brace.always` Braces are always required after ``if``, ``else``, ``switch``,
+``while``, ``do``, and ``for``.
+
+:mps:tag:`brace.always.except` Except that a lone ``if`` with no ``else`` is allowed
+to drop its braces when its body is a single simple statement. Typically
+this will be a ``goto`` or an assignment. For example::
+
+ if (res != ResOK)
+ goto failStart;
+
+Note in particular that an ``if`` with an ``else`` must have braces on both
+paths.
+
+Switch Statements
+.................
+
+:mps:tag:`switch` format switch statements like this::
+
+ switch (action) {
+ case WIBBLE:
+ case WOBBLE:
+ {
+ int angle;
+ err = move(plate, action, &angle);
+ }
+ break;
+
+ case QUIET:
+ drop();
+ /* fall-through */
+
+ case QUIESCENT:
+ err = 0;
+ break;
+
+ default:
+ NOTREACHED;
+ break;
+ }
+
+The component rules that result in this style are:
+
+:mps:tag:`switch.break` The last line of every case-clause body must be an
+unconditional jump statement (usually ``break``, but may be ``goto``,
+``continue``, or ``return``), or if a fall-through is intended, the comment
+``/* fall-through */``. (Note: if the unconditional jump should never be
+taken, because of previous conditional jumps, use :c:macro:`NOTREACHED` on the
+line before it). This rule is to prevent accidental fall-throughs, even
+if someone makes a editing mistake that causes a conditional jump to be
+missed.
+
+:mps:tag:`switch.default` It is usually a good idea to have a default-clause,
+even if all it contains is :c:macro:`NOTREACHED` and ``break``. Remember that
+:c:macro:`NOTREACHED` doesn't stop the process in all build varieties.
+
+
+Formatting Comments
+...................
+
+:mps:tag:`comment` There are three types of comments: banners, paragraph
+comments, and columnar comments.
+
+:mps:tag:`comment.banner` Banner comments come at the start of sections. A banner
+comment consists of a heading usually composed of a symbol, an em-dash
+(--) and an short explanation, followed by English text which is
+formatted using conventional text documentation guidelines (see
+guide.text). The open and close comment tokens (``/*`` and ``*/``) are
+placed at the top and bottom of a column of asterisks. The text is
+separated from the asterisks by one space. Place a blank line between
+the banner comment and the section it comments. For example::
+
+ /* BlockStruct -- Block descriptor
+ *
+ * The pool maintains a descriptor structure for each
+ * contiguous allocated block of memory it manages.
+ * The descriptor is on a simple linked-list of such
+ * descriptors, which is in ascending order of address.
+ */
+
+ typedef struct BlockStruct {
+
+:mps:tag:`comment.para` Paragraph comments come at the start of paragraphs in the
+code. A paragraph comment consists of formatted English text, with each
+line wrapped by the open and close comment tokens (``/*`` and ``*/``).
+(This avoids problems when cutting and pasting comments.) For example::
+
+ /* If the freed area is in the base sentinel then insert */
+ /* the new descriptor after it, otherwise insert before. */
+ if(isBase) {
+
+:mps:tag:`comment.para.precede` Paragraph comments, even one-liners, precede the
+code to which they apply.
+
+:mps:tag:`comment.column` Columnar comments appear in a column to the right of
+the code. They should be used sparingly, since they clutter the code and
+make it hard to edit. Use them on variable declarations and structure,
+union, or enum declarations. They should start at least at column 32
+(counting from 0, that is, on a tab-stop), and should be terse
+descriptive text. Abandon English sentence structure if this makes the
+comment clearer. Don't write more than one line. Here's an example::
+
+ typedef struct PoolMVStruct {
+ Pool blockPool; /* for block descriptors */
+ Pool spanPool; /* for span descriptors */
+ size_t extendBy; /* size to extend pool by */
+ size_t avgSize; /* estimate of allocation size */
+ size_t maxSize; /* estimate of maximum size */
+ Addr space; /* total free space in pool */
+ Addr lost; /* lost when free can't allocate */
+ struct SpanStruct *spans; /* span chain */
+ } PoolMVStruct;
+
+Macros
+......
+
+:mps:tag:`macro.careful` Macros in C are a real horror bag, be extra careful.
+There's lots that could go here, but proper coverage probably deserves a
+separate document. Which isn't written yet.
+
+:mps:tag:`macro.general` Do try and follow the other formatting conventions for
+code in macro definitions.
+
+:mps:tag:`macro.backslash` Backslashes used for continuation lines in macro
+definitions should be put on the right somewhere where they will be less
+in the way. Example::
+
+ #define RAMP_RELATION(X) \
+ X(RampOUTSIDE, "outside ramp") \
+ X(RampBEGIN, "begin ramp") \
+ X(RampRAMPING, "ramping") \
+ X(RampFINISH, "finish ramp") \
+ X(RampCOLLECTING, "collecting ramp")
+
+
+History
+-------
+
+- 2007-06-04 DRJ_ Adopted from Harlequin MMinfo version and edited.
+
+- 2007-06-04 DRJ_ Changed .width from 80 to 72. Banned space between
+ ``if`` and ``(``. Required braces on almost everything. Clarified that
+ paragraph comments precede the code.
+
+- 2007-06-13 RHSK_ Removed .brace.block, because MPS source always
+ uses .brace.otb. Remove .indent.elseif because it is obvious (ahem) and
+ showing an example is sufficient. New rules for .switch.*: current MPS
+ practice is a mess, so lay down a neat new law.
+
+- 2007-06-27 RHSK_ Added :mps:ref:`.space.function.not`.
+
+- 2007-07-17 DRJ_ Added .macro.\*
+
+- 2012-09-26 RB_ Converted to Markdown and reversed inconsistent
+ switch "law".
+
+.. _DRJ: http://www.ravenbrook.com/consultants/drj
+.. _RHSK: http://www.ravenbrook.com/consultants/rhsk
+.. _RB: http://www.ravenbrook.com/consultants/rb
+
+
+Copyright and License
+---------------------
+
+This document is copyright © 2002-2012 [Ravenbrook
+Limited](http://www.ravenbrook.com/). All rights reserved. This is an
+open source license. Contact Ravenbrook for commercial licensing
+options.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Redistributions in any form must be accompanied by information on
+ how to obtain complete source code for this software and any
+ accompanying software that uses this software. The source code must
+ either be included in the distribution or be available for no more
+ than the cost of distribution plus a nominal fee, and must be freely
+ redistributable under reasonable conditions. For an executable file,
+ complete source code means the source code for all modules it
+ contains. It does not include source code for modules or files that
+ typically accompany the major components of the operating system on
+ which the executable file runs.
+
+**This software is provided by the copyright holders and contributors
+"as is" and any express or implied warranties, including, but not
+limited to, the implied warranties of merchantability, fitness for a
+particular purpose, or non-infringement, are disclaimed. In no event
+shall the copyright holders and contributors be liable for any direct,
+indirect, incidental, special, exemplary, or consequential damages
+(including, but not limited to, procurement of substitute goods or
+services; loss of use, data, or profits; or business interruption)
+however caused and on any theory of liability, whether in contract,
+strict liability, or tort (including negligence or otherwise) arising in
+any way out of the use of this software, even if advised of the
+possibility of such damage.**
diff --git a/mps/manual/html/_sources/design/index.txt b/mps/manual/html/_sources/design/index.txt
index ce234220b78..a0c98237228 100644
--- a/mps/manual/html/_sources/design/index.txt
+++ b/mps/manual/html/_sources/design/index.txt
@@ -9,6 +9,7 @@ Design
config
critical-path
guide.hex.trans
+ guide.impl.c.format
keyword-arguments
ring
sig
diff --git a/mps/manual/html/_sources/design/interface-c.txt b/mps/manual/html/_sources/design/interface-c.txt
new file mode 100644
index 00000000000..b8db5831226
--- /dev/null
+++ b/mps/manual/html/_sources/design/interface-c.txt
@@ -0,0 +1,331 @@
+.. _design-interface-c:
+
+
+.. index::
+ pair: C interface; design
+
+
+C interface design
+==================
+
+.. mps:prefix:: design.mps.interface.c
+
+
+Introduction
+------------
+
+:mps:tag:`scope` This document is the design for the Memory Pool System
+(MPS) interface to the C Language, impl.h.mps.
+
+:mps:tag:`bg` See mail.richard.1996-07-24.10-57.
+
+
+Analysis
+--------
+
+Goals
+.....
+
+:mps:tag:`goal.c` The file impl.h.mps is the C external interface to the
+MPS. It is the default interface between client code written in C and
+the MPS. :mps:tag:`goal.cpp` impl.h.mps is not specifically designed to be
+an interface to C++, but should be usable from C++.
+
+
+Requirements
+............
+
+:mps:tag:`req` The interface must provide an interface from client code
+written in C to the functionality of the MPS required by the product
+(see req.product), Dylan (req.dylan), and the Core RIP (req.epcore).
+
+``mps.h`` may not include internal MPS header files (such as
+``pool.h``).
+
+It is essential that the interface cope well with change, in order to
+avoid restricting possible future MPS developments. This means that
+the interface must be "open ended" in its definitions. This accounts
+for some of the apparently tortuous methods of doing things
+(``mps_fmt_A_t``, for example). The requirement is that the MPS should
+be able to add new functionality, or alter the implementation of
+existing functionality, without affecting existing client code. A
+stronger requirement is that the MPS should be able to change without
+*recompiling* client code. This is not always possible.
+
+.. note::
+
+ `.naming.global` was presumably done in response to unwritten
+ requirements regarding the use of the name spaces in C, perhaps
+ these:
+
+ - :mps:tag:`req.name.iso` The interface shall not conflict in terms of
+ naming with any interfaces specified by ISO C and all reasonable
+ future versions.
+
+ - :mps:tag:`req.name.general` The interface shall use a documented and
+ reasonably small portion of the namespace so that clients can
+ interoperate easily.
+
+ David Jones, 1998-10-01.
+
+
+Architecture
+------------
+
+:mps:tag:`fig.arch` The architecture of the MPS Interface
+
+[missing figure]
+
+Just behind ``mps.h`` is the file ``mpsi.c``, the "MPS interface
+layer" which does the job of converting types and checking parameters
+before calling through to the MPS proper, using internal MPS methods.
+
+
+General conventions
+-------------------
+
+:mps:tag:`naming` The external interface names should adhere to the
+documented interface conventions; these are found in
+doc.mps.ref-man.if-conv(0).naming. They are paraphrased/recreated
+here.
+
+:mps:tag:`naming.unixy` The external interface does not follow the same
+naming conventions as the internal code. The interface is designed to
+resemble a more conventional C, Unix, or Posix naming convention.
+
+:mps:tag:`naming.case` Identifiers are in lower case, except
+non-function-like macros, which are in upper case.
+
+:mps:tag:`naming.global` All publicised identifiers are
+prefixed ``mps_`` or :c:macro:`MPS_`.
+
+:mps:tag:`naming.all` All identifiers defined by the MPS
+should begin ``mps_`` or :c:macro:`MPS_` or ``_mps_``.
+
+:mps:tag:`naming.type` Types are suffixed ``_t``.
+
+:mps:tag:`naming.struct` Structure types and tags are suffixed ``_s``.
+
+:mps:tag:`naming.union` Unions types and tags are suffixed ``_u``.
+
+:mps:tag:`naming.scope` The naming conventions apply to all identifiers (see
+ISO C §6.1.2); this includes names of functions, variables, types
+(through typedef), structure and union tags, enumeration members,
+structure and union members, macros, macro parameters, labels.
+
+:mps:tag:`naming.scope.labels` labels (for ``goto`` statements) should be
+rare, only in special block macros and probably not even then.
+
+.. note::
+
+ This principle is not adhered to in the source code, which uses
+ ``goto`` for handling error cases. Gareth Rees, 2013-05-27.
+
+:mps:tag:`naming.scope.other` The naming convention would also extend to
+enumeration types and parameters in functions prototypes but both of
+those are prohibited from having names in an interface file.
+
+:mps:tag:`type.gen` The interface defines memory addresses as ``void *`` and
+sizes as ``size_t`` for compatibility with standard C (in particular,
+with :c:func:`malloc()`). These types must be binary compatible with the
+internal types :c:type:`Addr` and :c:type:`Size` respectively. Note that this
+restricts the definitions of the internal types :c:type:`Addr` and :c:type:`Size`
+when the MPS is interfaced with C, but does not restrict the MPS in
+general.
+
+:mps:tag:`type.opaque` Opaque types are defined as pointers to structures
+which are never defined. These types are cast to the corresponding
+internal types in ``mpsi.c``.
+
+:mps:tag:`type.trans` Some transparent structures are defined. The client is
+expected to read these, or poke about in them, under restrictions
+which should be documented. The most important is probably the
+allocation point (:c:type:`mps_ap_s`) which is part of allocation buffers.
+The transparent structures must be binary compatible with
+corresponding internal structures. For example, the fields of
+:c:type:`mps_ap_s` must correspond with :c:type:`APStruct` internally. This is
+checked by ``mpsi.c`` in :c:func:`mps_check()`.
+
+:mps:tag:`type.pseudo` Some pseudo-opaque structures are defined. These only
+exist so that code can be inlined using macros. The client code
+shouldn't mess with them. The most important case of this is the scan
+state (:c:type:`mps_ss_s`) which is accessed by the in-line scanning macros,
+``MPS_SCAN_*`` and ``MPS_FIX*``.
+
+:mps:tag:`type.enum` There should be no enumeration types in the interface.
+Note that enum specifiers (to declare integer constants) are fine as
+long as no type is declared. See guide.impl.c.misc.enum.type.
+
+:mps:tag:`type.fun` Whenever function types or derived function types (such
+as pointer to function) are declared a prototype should be used and
+the parameters to the function should not be named. This includes the
+case where you are declaring the prototype for an interface function.
+
+:mps:tag:`type.fun.example` So use::
+
+ extern mps_res_t mps_alloc(mps_addr_t *, mps_pool_t, size_t, ...);
+
+rather than::
+
+ extern mps_res_t mps_alloc(mps_addr_t *addr_return, mps_pool_t pool , size_t size, ...);
+
+and::
+
+ typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t);
+
+rather than::
+
+ typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t object);
+
+See guide.impl.c.misc.prototype.parameters.
+
+
+Checking
+--------
+
+:mps:tag:`check.space` When the arena needs to be recovered from a parameter
+it is check using ``AVERT(Foo, foo)`` before any attempt to call
+``FooArena(foo)``. The macro :c:func:`AVERT()` in impl.h.assert performs
+simple thread-safe checking of ``foo``, so it can be called outside of
+:c:func:`ArenaEnter()` and :c:func:`ArenaLeave()`.
+
+:mps:tag:`check.types` We use definitions of types in both our external
+interface and our internal code, and we want to make sure that they
+are compatible. (The external interface changes less often and hides
+more information.) At first, we were just checking their sizes, which
+wasn't very good, but I've come up with some macros which check the
+assignment compatibility of the types too. This is a sufficiently
+useful trick that I thought I'd send it round. It may be useful in
+other places where types and structures need to be checked for
+compatibility at compile time.
+
+These macros don't generate warnings on the compilers I've tried.
+
+.. c:function:: COMPATLVALUE(lvalue1, lvalue2)
+
+This macro checks the assignment compatibility of two lvalues. It uses
+:c:func:`sizeof()` to ensure that the assignments have no effect. ::
+
+ #define COMPATLVALUE(lv1, lv2) \
+ ((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE)
+
+.. c:function:: COMPATTYPE(type1, type2)
+
+This macro checks that two types are assignment-compatible and equal
+in size. The hack here is that it generates an lvalue for each type by
+casting zero to a pointer to the type. The use of :c:func:`sizeof()` avoids
+the undefined behaviour that would otherwise result from dereferencing
+a null pointer. ::
+
+ #define COMPATTYPE(t1, t2) \
+ (sizeof(t1) == sizeof(t2) && \
+ COMPATLVALUE(*((t1 *)0), *((t2 *)0)))
+
+.. c:function:: COMPATFIELDAPPROX(structure1, field1, structure2, field2)
+
+This macro checks that the offset and size of two fields in two
+structure types are the same. ::
+
+ #define COMPATFIELDAPPROX(s1, f1, s2, f2) \
+ (sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \
+ offsetof(s1, f1) == offsetof(s2, f2))
+
+.. c:function:: COMPATFIELD(structure1, field1, structure2, field2)
+
+This macro checks the offset, size, and assignment-compatibility of
+two fields in two structure types. ::
+
+ #define COMPATFIELD(s1, f1, s2, f2) \
+ (COMPATFIELDAPPROX(s1, f1, s2, f2) && \
+ COMPATLVALUE(((s1 *)0)->f1, ((s2 *)0)->f2))
+
+
+Binary compatibility issues
+---------------------------
+
+As in, "Enumeration types are not allowed" (see
+mail.richard.1995-09-08.09-28).
+
+There are two main aspects to run-time compatibility: binary interface
+and protocol. The binary interface is all the information needed to
+correctly use the library, and includes external symbol linkage,
+calling conventions, type representation compatibility, structure
+layouts, etc. The protocol is how the library is actually used by the
+client code -- whether this is called before that -- and determines
+the semantic correctness of the client with respect to the library.
+
+The binary interface is determined completely by the header file and
+the target. The header file specifies the external names and the
+types, and the target platform specifies calling conventions and type
+representation. There is therefore a many-to-one mapping between the
+header file version and the binary interface.
+
+The protocol is determined by the implementation of the library.
+
+
+Constraints
+-----------
+
+:mps:tag:`cons` The MPS C Interface constrains the MPS in order to provide
+useful memory management services to a C or C++ program.
+
+:mps:tag:`cons.addr` The interface constrains the MPS address type, Addr
+(design.mps.type.addr), to being the same as C's generic pointer type,
+``void *``, so that the MPS can manage C objects in the natural way.
+
+:mps:tag:`pun.addr` We pun the type of :c:type:`mps_addr_t` (which is ``void *``)
+into :c:type:`Addr` (an incomplete type, see design.mps.type.addr). This
+happens in the call to the scan state's fix function, for example.
+
+:mps:tag:`cons.size` The interface constrains the MPS size type, :c:type:`Size`
+(design.mps.type.size), to being the same as C's size type,
+``size_t``, so that the MPS can manage C objects in the natural way.
+
+:mps:tag:`pun.size` We pun the type of ``size_t`` in mps.h into :c:type:`Size` in
+the MPM, as an argument to the format methods. We assume this works.
+
+:mps:tag:`cons.word` The MPS assumes that :c:type:`Word` (design.mps.type.word)
+and :c:type:`Addr` (design.mps.type.addr) are the same size, and the
+interface constrains :c:type:`Word` to being the same size as C's generic
+pointer type, ``void *``.
+
+
+Notes
+-----
+
+The file ``mpstd.h`` is the MPS target detection header. It decodes
+preprocessor symbols which are predefined by build environments in
+order to determine the target platform, and then defines uniform
+symbols, such as :c:macro:`MPS_ARCH_I3`, for use internally by the MPS.
+
+There is a design document for the mps interface,
+design.mps.interface, but it was written before we had the idea of
+having a C interface layer. It is quite relevant, though, and could be
+updated. We should use it during the review.
+
+All exported identifiers and file names should begin with ``mps_`` or
+:c:macro:`MPS_` so that they don't clash with other systems.
+
+We should probably have a specialized set of rules and a special
+checklist for this interface.
+
+:mps:tag:`fmt.extend` This paragraph should be an explanation of why
+``mps_fmt_A_t`` is so called. The underlying reason is future
+extensibility.
+
+:mps:tag:`thread-safety` Most calls through this interface lock the space
+and therefore make the MPM single-threaded. In order to do this they
+must recover the space from their parameters. Methods such as
+:c:func:`ThreadSpace()` must therefore be callable when the space is *not*
+locked. These methods are tagged with the tag of this note.
+
+:mps:tag:`lock-free` Certain functions inside the MPM are thread-safe and do
+not need to be serialized by using locks. They are marked with the tag
+of this note.
+
+:mps:tag:`form` Almost all functions in this implementation simply cast
+their arguments to the equivalent internal types, and cast results
+back to the external type, where necessary. Only exceptions are noted
+in comments.
+
+
diff --git a/mps/manual/html/_sources/design/io.txt b/mps/manual/html/_sources/design/io.txt
new file mode 100644
index 00000000000..d5cecd5b936
--- /dev/null
+++ b/mps/manual/html/_sources/design/io.txt
@@ -0,0 +1,407 @@
+.. _design-io:
+
+
+.. index::
+ pair: I/O subsystem; design
+
+
+I/O subsystem
+=============
+
+.. mps:prefix:: design.mps.io
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document is the design of the MPS I/O Subsystem, a
+part of the plinth.
+
+:mps:tag:`readership` This document is intended for MPS developers.
+
+
+Background
+----------
+
+:mps:tag:`bg` This design is partly based on the design of the Internet User
+Datagram Protocol (UDP). Mainly I used this to make sure I hadn't left
+out anything which we might need.
+
+
+Purpose
+-------
+
+:mps:tag:`purpose` The purpose of the MPS I/O Subsystem is to provide a
+means to measure, debug, control, and test a memory manager build
+using the MPS.
+
+:mps:tag:`purpose.measure` Measurement consists of emitting data which can
+be collected and analysed in order to improve the attributes of
+application program, quite possibly by adjusting parameters of the
+memory manager (see overview.mps.usage).
+
+:mps:tag:`purpose.control` Control means adjusting the behaviour of the MM
+dynamically. For example, one might want to adjust a parameter in
+order to observe the effect, then transfer that adjustment to the
+client application later.
+
+:mps:tag:`purpose.test` Test output can be used to ensure that the memory
+manager is behaving as expected in response to certain inputs.
+
+
+Requirements
+------------
+
+General
+.......
+
+:mps:tag:`req.fun.non-hosted` The MPM must be a host-independent system.
+
+:mps:tag:`req.attr.host` It should be easy for the client to set up the MPM
+for a particular host (such as a washing machine).
+
+Functional
+..........
+
+:mps:tag:`req.fun.measure` The subsystem must allow the MPS to transmit
+quantitative measurement data to an external tool so that the system
+can be tuned.
+
+:mps:tag:`req.fun.debug` The subsystem must allow the MPS to transmit
+qualitative information about its operation to an external tool so
+that the system can be debugged.
+
+:mps:tag:`req.fun.control` The subsystem must allow the MPS to receive
+control information from an external tool so that the system can be
+adjusted while it is running.
+
+:mps:tag:`req.dc.env.no-net` The subsystem should operate in environments
+where there is no networking available.
+
+:mps:tag:`req.dc.env.no-fs` The subsystem should operate in environments
+where there is no filesystem available.
+
+
+Architecture
+------------
+
+:mps:tag:`arch.diagram` I/O Architecture Diagram
+
+[missing diagram]
+
+:mps:tag:`arch.int` The I/O Interface is a C function call interface by
+which the MPM sends and receives "messages" to and from the hosted I/O
+module.
+
+:mps:tag:`arch.module` The modules are part of the MPS but not part of the
+freestanding core system (see design.mps.exec-env). The I/O module is
+responsible for transmitting those messages to the external tools, and
+for receiving messages from external tools and passing them to the
+MPM.
+
+:mps:tag:`arch.module.example` For example, the "file implementation" might
+just send/write telemetry messages into a file so that they can be
+received/read later by an off-line measurement tool.
+
+:mps:tag:`arch.external` The I/O Interface is part of interface to the
+freestanding core system (see design.mps.exec-env). This is so that
+the MPS can be deployed in a freestanding environment, with a special
+I/O module. For example, if the MPS is used in a washing machine the
+I/O module could communicate by writing output to the seven-segment
+display.
+
+
+Example configurations
+......................
+
+:mps:tag:`example.telnet` This shows the I/O subsystem communicating with a
+telnet client over a TCP/IP connection. In this case, the I/O
+subsystem is translating the I/O Interface into an interactive text
+protocol so that the user of the telnet client can talk to the MM.
+
+[missing diagram]
+
+:mps:tag:`example.file` This shows the I/O subsystem dumping measurement
+data into a file which is later read and analysed. In this case the
+I/O subsystem is simply writing out binary in a format which can be
+decoded.
+
+[missing diagram]
+
+:mps:tag:`example.serial` This shows the I/O subsystem communicating with a
+graphical analysis tool over a serial link. This could be useful for a
+developer who has two machines in close proximity and no networking
+support.
+
+:mps:tag:`example.local` In this example the application is talking directly
+to the I/O subsystem. This is useful when the application is a
+reflective development environment (such as MLWorks) which wants to
+observe its own behaviour.
+
+[missing diagram]
+
+
+Interface
+---------
+
+:mps:tag:`if.msg` The I/O interface is oriented around opaque binary
+"messages" which the I/O module must pass between the MPM and external
+tools. The I/O module need not understand or interpret the contents of
+those messages.
+
+:mps:tag:`if.msg.opaque` The messages are opaque in order to minimize the
+dependency of the I/O module on the message internals. It should be
+possible for clients to implement their own I/O modules for unusual
+environments. We do not want to reveal the internal structure of our
+data to the clients. Nor do we want to burden them with the details of
+our protocols. We'd also like their code to be independent of ours, so
+that we can expand or change the protocols without requiring them to
+modify their modules.
+
+:mps:tag:`if.msg.dgram` Neither the MPM nor the external tools should assume
+that the messages will be delivered in finite time, exactly once, or
+in order. This will allow the I/O modules to be implemented using
+unreliable transport layers such as the Internet User Datagram Protocl
+(UDP). It will also give the I/O module the freedom to drop
+information rather than block on a congested network, or stop the
+memory manager when the disk is full, or similar events which really
+shouldn't cause the memory manager to stop working. The protocols we
+need to implement at the high level can be design to be robust against
+lossage without much difficulty.
+
+
+I/O module state
+................
+
+:mps:tag:`if.state` The I/O module may have some internal state to preserve.
+The I/O Interface defines a type for this state, :c:type:`mps_io_t`, a
+pointer to an incomplete structure :c:type:`mps_io_s`. The I/O module is at
+liberty to define this structure.
+
+
+Message types
+.............
+
+:mps:tag:`if.type` The I/O module must be able to deliver messages of
+several different types. It will probably choose to send them to
+different destinations based on their type: telemetry to the
+measurement tool, debugging output to the debugger, etc. ::
+
+ typedef int mps_io_type_t;
+ enum {
+ MPS_IO_TYPE_TELEMETRY,
+ MPS_IO_TYPE_DEBUG
+ };
+
+
+Limits
+......
+
+:mps:tag:`if.message-max` The interface will define an unsigned integral
+constant :c:macro:`MPS_IO_MESSAGE_MAX` which will be the maximum size of
+messages that the MPM will pass to :c:func:`mps_io_send()` (:mps:ref:`.if.send`) and
+the maximum size it will expect to receive from :c:func:`mps_io_receive()`.
+
+
+Interface set-up and tear-down
+..............................
+
+:mps:tag:`if.create` The MPM will call :c:func:`mps_io_create()` to set up the I/O
+module. On success, this function should return :c:macro:`MPS_RES_OK`. It may
+also initialize a "state" value which will be passed to subsequent
+calls through the interface.
+
+:mps:tag:`if.destroy` The MPM will call :c:func:`mps_io_destroy()` to tear down
+the I/O module, after which it guarantees that the state value will
+not be used again. The ``state`` parameter is the state previously
+returned by :c:func:`mps_io_create()` (:mps:ref:`.if.create`).
+
+Message send and receive
+........................
+
+.. c:function:: extern mps_res_t mps_io_send(mps_io_t state, mps_io_type_t type, void *message, size_t size)
+
+:mps:tag:`if.send` The MPM will call :c:func:`mps_io_send()` when it wishes to
+send a message to a destination. The ``state`` parameter is the state
+previously returned by :c:func:`mps_io_create()` (:mps:ref:`.if.create`). The
+``type`` parameter is the type (:mps:ref:`.if.type`) of the message. The
+``message`` parameter is a pointer to a buffer containing the message,
+and ``size`` is the length of that message, in bytes. The I/O module
+must make an effort to deliver the message to the destination, but is
+not expected to guarantee delivery. The function should return
+:c:macro:`MPS_RES_IO` only if a serious error occurs that should cause the
+MPM to return with an error to the client application. Failure to
+deliver the message does not count.
+
+.. note::
+
+ Should there be a timeout parameter? What are the timing
+ constraints? :c:func:`mps_io_send()` shouldn't block.
+
+.. c:function:: extern mps_res_t mps_io_receive(mps_io_t state, void **buffer_o, size_t *size_o)
+
+:mps:tag:`if.receive` The MPM will call :c:func:`mps_io_receive()` when it wants
+to see if a message has been sent to it. The ``state`` parameter is
+the state previously returned by :c:func:`mps_io_create()` (:mps:ref:`.if.create`).
+The ``buffer_o`` parameter is a pointer to a value which should be
+updated with a pointer to a buffer containing the message received.
+The ``size_o`` parameter is a pointer to a value which should be
+updated with the length of the message received. If there is no
+message ready for receipt, the length returned should be zero.
+
+.. note::
+
+ Should we be able to receive truncated messages? How can this be
+ done neatly?
+
+
+I/O module implementations
+--------------------------
+
+Routeing
+........
+
+The I/O module must decide where to send the various messages. A
+file-based implementation could put them in different files based on
+their types. A network-based implementation must decide how to address
+the messages. In either case, any configuration must either be
+statically compiled into the module, or else read from some external
+source such as a configuration file.
+
+
+Notes
+-----
+
+The external tools should be able to reconstruct stuff from partial
+info. For example, you come across a fragment of an old log containing
+just a few old messages. What can you do with it?
+
+Here's some completely untested code which might do the job for UDP.
+::
+
+ #include "mpsio.h"
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ typedef struct mps_io_s {
+ int sock;
+ struct sockaddr_in mine;
+ struct sockaddr_in telemetry;
+ struct sockaddr_in debugging;
+ } mps_io_s;
+
+ static mps_bool_t inited = 0;
+ static mps_io_s state;
+
+
+ mps_res_t mps_io_create(mps_io_t *mps_io_o)
+ {
+ int sock, r;
+
+ if(inited)
+ return MPS_RES_LIMIT;
+
+ state.mine = /* setup somehow from config */;
+ state.telemetry = /* setup something from config */;
+ state.debugging = /* setup something from config */;
+
+ /* Make a socket through which to communicate. */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if(sock == -1) return MPS_RES_IO;
+
+ /* Set socket to non-blocking mode. */
+ r = fcntl(sock, F_SETFL, O_NDELAY);
+ if(r == -1) return MPS_RES_IO;
+
+ /* Bind the socket to some UDP port so that we can receive messages. */
+ r = bind(sock, (struct sockaddr *)&state.mine, sizeof(state.mine));
+ if(r == -1) return MPS_RES_IO;
+
+ state.sock = sock;
+
+ inited = 1;
+
+ *mps_io_o = &state;
+ return MPS_RES_OK;
+ }
+
+
+ void mps_io_destroy(mps_io_t mps_io)
+ {
+ assert(mps_io == &state);
+ assert(inited);
+
+ (void)close(state.sock);
+
+ inited = 0;
+ }
+
+
+ mps_res_t mps_io_send(mps_io_t mps_io, mps_type_t type,
+ void *message, size_t size)
+ {
+ struct sockaddr *toaddr;
+
+ assert(mps_io == &state);
+ assert(inited);
+
+ switch(type) {
+ MPS_IO_TYPE_TELEMETRY:
+ toaddr = (struct sockaddr *)&state.telemetry;
+ break;
+
+ MPS_IO_TYPE_DEBUGGING:
+ toaddr = (struct sockaddr *)&state.debugging;
+ break;
+
+ default:
+ assert(0);
+ return MPS_RES_UNIMPL;
+ }
+
+ (void)sendto(state.sock, message, size, 0, toaddr, sizeof(*toaddr));
+
+ return MPS_RES_OK;
+ }
+
+
+ mps_res_t mps_io_receive(mps_io_t mps_io,
+ void **message_o, size_t **size_o)
+ {
+ int r;
+ static char buffer[MPS_IO_MESSAGE_MAX];
+
+ assert(mps_io == &state);
+ assert(inited);
+
+ r = recvfrom(state.sock, buffer, sizeof(buffer), 0, NULL, NULL);
+ if(r == -1)
+ switch(errno) {
+ /* Ignore interrupted system calls, and failures due to lack */
+ /* of resources (they might go away.) */
+ case EINTR: case ENOMEM: case ENOSR:
+ r = 0;
+ break;
+
+ default:
+ return MPS_RES_IO;
+ }
+
+ *message_o = buffer;
+ *size_o = r;
+ return MPS_RES_OK;
+ }
+
+
+Attachments
+-----------
+
+"O Architecture Diagram"
+"O Configuration Diagrams"
+
+
diff --git a/mps/manual/html/_sources/design/keyword-arguments.txt b/mps/manual/html/_sources/design/keyword-arguments.txt
index eb21b41d92a..179ba64fde9 100644
--- a/mps/manual/html/_sources/design/keyword-arguments.txt
+++ b/mps/manual/html/_sources/design/keyword-arguments.txt
@@ -1,6 +1,148 @@
+.. _design-keyword-arguments:
+
+
.. index::
pair: keyword arguments; design
-.. _design-keyword-arguments:
-.. include:: ../../converted/keyword-arguments.rst
+Keyword arguments in the MPS
+============================
+
+
+
+Introduction
+------------
+Up to version 1.111, the `Memory Pool System
+`_ used varags to pass arguments
+to arena and pool classes, because the general MPS interface can't
+specify what arguments those classes might need in C prototypes. This
+mechanism was error-prone and did not allow for any optional arguments,
+meaning that the client had to specify or predict esoteric tuning
+parameters.
+
+Starting with version 1.112, the MPS uses an idiom for keyword arguments.
+
+
+Overview
+--------
+The basic design is not specific to the MPS. The keyword argument list is
+passed as an array of argument structures which look like this::
+
+ typedef struct mps_key_s *mps_key_t;
+ typedef struct mps_arg_s {
+ mps_key_t key;
+ union {
+ int i;
+ char c;
+ void *p;
+ size_t size;
+ /* etc. */
+ } val;
+ } mps_arg_s;
+
+The argument list is assembled and passed like this::
+
+ mps_arg_s args[3];
+ args[0].key = MPS_KEY_MIN_SIZE;
+ args[0].val.size = 32;
+ args[1].key = MPS_KEY_MAX_SIZE;
+ args[1].val.size = 1024;
+ args[2].key = MPS_KEY_ARGS_END;
+ mps_pool_create_k(&pool, some_pool_class(), args);
+
+This can be written quite concisely in C99::
+
+ mps_pool_create_k(&pool, some_pool_class(),
+ (mps_arg_s []){{MPS_KEY_MIN_SIZE, {.size = 32}},
+ {MPS_KEY_MAX_SIZE, {.size = 1024}},
+ {MPS_KEY_ARGS_END}});
+
+The arguments that are recognised and used by the function are removed
+from the array (and the subsequent arguments moved up) so that if they
+are all consumed the array has :c:macro:`MPS_KEY_ARGS_END` in slot zero on
+return. This can be checked by the caller.
+
+- It's not a static error to pass excess arguments. This makes it easy to
+ substitute one pool or arena class for another (which might ignore some
+ arguments). The caller can check that ``args[0].key`` is
+ :c:macro:`MPS_KEY_ARGS_END` if desired.
+
+- NULL is not a valid argument list. This is in line with general MPS
+ design principles to avoid accidental omissions. For convenience, we
+ provide ``mps_args_none`` as a static empty argument list.
+
+- NULL is not a valid argument key. This is in line with general MPS
+ design principles to avoid accidental omissions. Every key points to
+ a structure with a signature that can be checked. This makes it virtually
+ impossible to get an argument list with bad keys or that is unterminated
+ past MPS checking.
+
+
+Internals
+---------
+Internally, keys are static constant structures which are signed and contain
+a checking method for the argument, like this::
+
+ typedef struct mps_arg_s *Arg;
+ typedef struct mps_key_s {
+ Sig sig; /* Always KeySig */
+ const char *name;
+ Bool check(Arg arg);
+ } KeyStruct;
+
+They are mostly declared in the modules that consume them, except for a few
+common keys. Declarations look like::
+
+ const KeyStruct _mps_key_extend_by = {KeySig, "extend_by", ArgCheckSize};
+
+but ``arg.h`` provides a macro for this::
+
+ ARG_DEFINE_KEY(extend_by, Size);
+
+We define keys as static structures (rather than, say, an enum) because:
+
+- The set of keys can be extended indefinitely.
+- The set of keys can be extended by indepdently linked modules.
+- The structure contents allow strong checking of argument lists.
+
+In the MPS Interface, we declare keys like this::
+
+ extern const struct mps_key_s _mps_key_extend_by;
+ #define MPS_KEY_EXTEND_BY (&_mps_key_extend_by)
+
+The underscore on the symbol requests that client code doesn't reference
+it, but instead uses the macro. This gives us adaptability to change the
+design and replace keys with, say, magic numbers.
+
+
+The varargs legacy
+------------------
+For backward compatibility, varargs to arena and pool creation are
+converted into keyword arguments by position, using a method in the
+arena or pool class. For example::
+
+ static void MVVarargs(ArgStruct args[], va_list varargs)
+ {
+ args[0].key = MPS_KEY_EXTEND_BY;
+ args[0].val.size = va_arg(varargs, Size);
+ args[1].key = MPS_KEY_MEAN_SIZE;
+ args[1].val.size = va_arg(varargs, Size);
+ args[2].key = MPS_KEY_MAX_SIZE;
+ args[2].val.size = va_arg(varargs, Size);
+ args[3].key = MPS_KEY_ARGS_END;
+ AVER(ArgListCheck(args));
+ }
+
+This leaves the main body of code, and any future code, free to just
+handle keyword arguments only.
+
+The use of varargs is deprecated in the manual and the interface and these
+methods can be deleted at some point in the future.
+
+
+References
+----------
+
+.. [RB_2012-05-24] Richard Brooksby. Ravenbrook Limited. 2012-05-24. "`Keyword and optional arguments `__".
+
+
diff --git a/mps/manual/html/_sources/design/lib.txt b/mps/manual/html/_sources/design/lib.txt
new file mode 100644
index 00000000000..e176f8f6995
--- /dev/null
+++ b/mps/manual/html/_sources/design/lib.txt
@@ -0,0 +1,102 @@
+.. _design-lib:
+
+
+.. index::
+ pair: library interface; design
+
+
+Library interface
+=================
+
+.. mps:prefix:: design.mps.lib
+
+
+Introduction
+------------
+
+:mps:tag:`intro` This document is the design of the MPS Library Interface, a
+part of the plinth.
+
+:mps:tag:`readership` Any MPS developer. Any clients that are prepared to
+read this in order to get documentation.
+
+
+Goals
+-----
+
+:mps:tag:`goal` The goals of the MPS library interface are:
+
+:mps:tag:`goal.host` To control the dependency of the MPS on the hosted ISO
+C library so that the core MPS remains freestanding (see
+design.mps.exec-env).
+
+:mps:tag:`goal.free` To allow the core MPS convenient access to ISO C
+functionality that is provided on freestanding platforms (see
+design.mps.exec-env.std.com.free).
+
+
+Description
+-----------
+
+Overview
+........
+
+:mps:tag:`overview.access` The core MPS needs to access functionality that
+could be provided by an ISO C hosted environment.
+
+:mps:tag:`overview.hosted` The core MPS must not make direct use of any
+facilities in the hosted environment (design.mps.exec-env). However,
+it is sensible to make use of them when the MPS is deployed in a
+hosted environment.
+
+:mps:tag:`overview.hosted.indirect` The core MPS does not make any direct
+use of hosted ISO C library facilities. Instead, it indirects through
+the MPS Library Interface, impl.h.mpslib.
+
+:mps:tag:`overview.free` The core MPS can make direct use of freestanding
+ISO C library facilities and does not need to include any of the
+header files ````, ````, and ``