https://github.com/Unipisa/CMM
Raw File
Tip revision: 0e186db83a043dcfe9c666dd4c90f9e8d1b9234e authored by Giuseppe Attardi on 27 October 1994, 11:26:20 UTC
1.1 -
Tip revision: 0e186db
CMMguide.tex
\documentstyle[11pt,fullpage]{posso}
\def\theenumi{\alph{enumi}}
\def\labelenumi{(\alph{enumi})}
\markright{Formal Spec for POSSO Memory Management (15 September 1994)}
\pagestyle{myheadings}
\begin{document}
\begin{verbatim}
POSSO FILE HEADER
type:     FORMAL SPECIFICATION (C++ library)
title:    POSSO Customisable Memory Management (CMM)
date:     15 September 1994
author:   Tito Flagella and Giuseppe Attardi
email:    tito@di.unipi.it
address:  Dipartimento di Informatica,
          Universita' di Pisa,
          Corso Italia 40, I-56125 Pisa
          Italy
\end{verbatim}

\section{Summary of changes from previous version}
\begin{itemize}
\item significant rewrite to provide multiple heaps as described in the
USENIX C++ paper;
\item eliminated GC header for objects;
\item the space for tables is recycled;
\item the collector consists of just two files cmm.H, cmm.C.
\end{itemize}

\subsection {Known Shortcomings}
\begin{itemize}
\item Heap Zone programming still undocumented
\item Multiple inheritance not yet supported
\item Finalization Protocol missing
\end{itemize}

\section {Introduction}

This is the POSSO specification for Customisable Memory Management (CMM).
CMM is a \verb|C++| Memory Management facility, aiming to
allow full integration between coexisting different memory
management techniques.  Refer to [Attardi 93] for a detailed paper on CMM.

This document is intended as a brief reference guide to the use
of CMM.  CMM can be used at two levels: the user level, and the
programmer level.  The user will usually look at CMM as a library of
garbage collecting algorithms.  CMM provides the user with facilities to
define a \verb|C++| class as ``garbage collected'' and to define the 
particular garbage collector for that class.

\section {The User Interface}

Memory in the CMM consists of several heaps of various kinds, called {\em
HeapZones}.  Each kind of HeapZone is implemented as a {\tt C++} class and
provides a specific allocation and reclamation policy.  For instance, one
HeapZone may perform memory management through a two space stop-and-copy
collector, another HeapZone may work with a LIFO discipline, and a third may
implement a generational garbage collector.  Each HeapZone is a collection of
not necessarily contiguous memory chunks.

Classes whose objects are to be dynamically allocated and subject to garbage
collection are called {\em dynamic\/} classes.  Their instances are called {\em
dynamic\/} objects.  A dynamic object is allocated inside a single HeapZone.
The CMM user interface provides constructs to specify in which HeapZone to
allocate objects.


A dynamic class must derived from the class {\tt GcObject} provided by the CMM.
The default collector calls the method {\tt traverse} on dynamic objects to
identify their internal pointers to other dynamic objects.  Users have to
provide {\tt traverse} methods for each class whose data members contain
pointers to dynamic objects.  {\tt traverse} must be defined according to some
well defined rules (given below), because it implements the interface between
the CMM and user defined dynamic objects.  The following is the function
prototype for {\tt traverse}:
\begin{verbatim}
void traverse()
\end{verbatim}
The {\tt HeapZone} argument is present because the same objects can be
traversed from garbage collectors of different zones.

Final users of CMM need not care about this
parameter since they can just follow a few simple rules to define the
{\tt traverse} member function.  These rules ensure that superclasses or
class objects contained in the class are correctly handled.  The
following example illustrates these rules, then we explain what the rules are.
Suppose the following dynamic classes were defined:
\begin{verbatim}
class BigNum : public GcObject
{
  long data;
  BigNum *next;                         // Rule (a) applies
  void traverse();
}

class monomial : BigNum                 // Rule (c) applies
{
  PowerProduct pp;                      // Rule (b) applies
  void traverse();
}
\end{verbatim}
Since a {\tt BigNum} stores a pointer to GCable object in
{\tt next} this has to be followed by {\tt traverse}, thus we obtain the
traversal function:

\begin{verbatim}
void BigNum::traverse()
{
  CmmHeap::heap->scavenge(next);             // Applying rule (a)
}
\end{verbatim}
Because {\tt monomial} inherits from {\tt BigNum}, the method {\tt
traverse} for this base class must be invoked; finally, since a {\tt
monomial} contains a {\tt BigNum} in {\tt pp}, this object must be
traversed as well:

\begin{verbatim}
void monomial::traverse()
{
  BigNum::traverse();               // Appling rule (c)
  pp.traverse();                    // Applying rule (b)
}
\end{verbatim}

In summary the rules are:

\begin{enumerate}
\item for a class containing a pointer to a dynamic object, say \verb|class C {
DynObj* x; }|, the method \verb|C::traverse| must contain \verb|DefaultHeap::heap->scavenge(x)|
\item for a class containing an instance of a dynamic object, say \verb|class C
{ DynObj x; }|, the method \verb|C::traverse| must contain \verb|x.traverse()|
\item for a class derived from another dynamic class, say \verb|class C:DynBase
{...}|, the method \verb|C::traverse| must contain
\verb|DynBase::traverse()|.
\end{enumerate}

Preprocessing [Edelson 92] or compiler support [Samples 92] could be
adopted to reduce hand coding from the user and risks of subtle errors
in programs. We do not address these issues here since within POSSO
the burden of following the above rules has been considered affordable.


\subsection{Dynamic Objects}

When creating a dynamic object one must specify in which HeapZone to
allocate it. The parameter {\tt zone} can be supplied in the standard
\verb|C++| placement syntax for the {\tt new} operator:
\begin{verbatim}
p = new(zone) Person(name, age); 
\end{verbatim}
If the user does not specify any HeapZone, the default HeapZone {\tt
heap} is used:
\begin{verbatim}
p = new Person(name, age);
\end{verbatim}
which is equivalent to:
\begin{verbatim}
p = new(heap) Person(name, age);
\end{verbatim}
where {\tt heap} is a global 
variable initialised to the system HeapZone, but can be set by the 
user to any other HeapZone.

When creating a dynamic object, the 
programmer can dynamically decide where to allocate the memory. 
Consider the following example:

\begin{verbatim}
class Person : public GcObject
{
...
};

Person *obj;
HeapZone *other;
....
if ( /* I prefer Heap */ )
   obj = new Person(arg);
else obj = new(other) Person(arg);
\end{verbatim}


\subsection{Dynamic Variable Sized Objects}

To support variable sized objects, the class {\tt GcVarObject} is
available.  This is a derived class from {\tt GcObject}, providing a
different operator {\tt new} with an extra parameter for the size of
the object.  Classes derived from {\tt GcVarObject} are called {\it
dynamic variable sized classes\/}.  The following example illustrates
their use:

\begin{verbatim}
class container : public GcVarObject
{
  int header;
  int table[1];  // size of this array is determined upon object creation
};

container *obj;

ExtraSize = 256 * sizeof(int);

obj = new(ExtraSize) container; // this object is created in the default zone

HeapZone *other;
obj = new(ExtraSize, other) container; // this object is created in zone other
\end{verbatim}
The object created, \verb|obj|, now has room for a table of 256 integers.

\subsubsection*{Warning}

Note that variable sized dynamic classes must be used more carefully than
normal classes.  In particular, the variable sized field must be the last data
field in the class (and all data members must have the same accessibility),
local variables must never be of variable size, and other classes must not be
derived from a variable sized class.  In fact, the compiler does not know about
the extra memory allocated so that extra memory may be lost or overwritten
if any of the above rules is broken.

Despite these restrictions there are some cases in which the use of such
classes cannot be avoided. The usual way to achieve this effect in \verb|C++|
is to allocate dynamically the extra size in the object's constructor, but in
this way the extra memory allocated would be neither a \verb|C++| object nor
a \verb|GcObject|.

\subsection {Array of GcObjects}

The following class can be used to create arrays of GcObjects
like follows:

\begin{verbatim}
       GcArray<MyClass> MyVector = * new (100) GcArray<MyClass> ;
\end{verbatim}
       
The operator [] can be used to get GcObjects.

\begin{verbatim}
       MyVector[i]->print();
\end{verbatim}
or:
\begin{verbatim}
       MyClass mc = MyVector[3];
\end{verbatim}

\subsection{A sample program}

\begin{verbatim}
#include "HeapStack.H"

class cell : GcObject          // This class is a GC class
{
  int x;

public: 
  cell *next;                  // This field is a pointer to a GC class,
                               // and must be traversed.

  void traverse();   // Because "cell" has internal pointers
                               // traverse must be defined.
};

void cell::traverse()
 { 
   DefaultHeap::heap->scavenge( (GcObject **)&next ); 
                               // traverse scavenge the internal pointer
                               // next to reach other cells.
 }

main()
{
  HeapZone *MyHeap = new BBStack(100);
                               // Create the new Heap zone MyHeap.
                               // Here you can use any of the predefined
                               // heap zones.

  cell *t = new cell;
                               // Create a new cell. 
                               // Because you have not specified an heap zone
                               // with new, the global variable heap is used.
                               // heap is initialized to the Bartlett heap zone.

  t->next = new (MyHeap) cell;
                               // Create another cell, but in MyHeap

  heap = MyHeap;
  t->next->next = new cell;
                               // Setting heap to MyHeap, you can allocate cells
                               // from MyHeap, without specifing it as a parameter
                               // of new.

  heap->collect();
                               // Collecting on MyHeap
  BartlettHeap->collect();
                               // Collecting on the Bartlett zone.

  heap = BartlettHeap;
                               // Reset heap before returning.
}
\end{verbatim}

\section {Heap zones}

The CMM programmer interface is for use of implementors of
additional HeapZones. A new zone must be derived from the abstract
class \verb|HeapZone| and must supply definitions for its pure virtual
functions: so the creation of a HeapZone involves writing a garbage
collector (\verb|collect|), the memory allocation strategy (allocator and
reclaimer) and the strategy used by the collector to act on the
internal pointers encountered during traversal (\verb|scavenge|).

This feature of CMM is still under testing. Currently the user must
use one of the predefined HeapZones. The Heap zones currently available
are:

\begin{itemize}
\item{\verb|Bartlett|}

This zone embeds the Bartlett's mostly copying garbage collector [Bartlett 88].
It is predefined in CMM as the default heap zone.
Users are not allowed to create new instances of \verb|Bartlett|.
This zone can be accessed by its name {\tt BartlettHeap}.

\item{\verb|HeapStack|}
\begin{itemize}

\item A HeapStack is created using:
\begin{verbatim}
		new HeapStack(unsigned words);
\end{verbatim}
It is a fixed size stack-like heap zone, implemented as a couple of
containers, one for the ``from space'', and one for the ``to space''.

\item Allocation is done in a stack-like way.

\item Deallocation is done by the garbage collector, compacting the stack.

\item The root set is defined by the user.

\item The garbage collector is a copying collector.
\end{itemize}

\item{\verb|BBStack|}
\begin{itemize}

\item A BBStack is created using:
\begin{verbatim}
		new BBStack(unsigned words);
\end{verbatim}
It is a variable size stack-like heap zone, implemented as a list of
containers. \verb|words| specifies the size of each container.

\item Allocation is implemented in a stack-like way. Any object must be smaller
than the size of each container (\verb|words|).

\item Deallocation is done by the garbage collector, compacting the stack.

\item The root set is defined by the user.

\item The garbage collector is a copying collector.
\end{itemize}

\end{itemize}

\subsection{The root set}

Many heap zones (like BBStack, and HeapStack) require the user to explicitly
register the possible roots.
To support that, the class HeapZone contains an instance of the class RootSet
supporting the following operations:

\begin{verbatim}

void set(GcObject *);
void unset(GcObject *);

void setp(GcObject **);
void unsetp(GcObject **);
\end{verbatim}

\verb|setp| and \verb|unsetp| are used to (un)register pointers
to GC objects as roots.
\verb|set| and \verb|unsetp| are used to (un)register GC objects
as roots.
Consider the following example:

\begin{verbatim}
cell GlobalRoot;			    
					// Define a cell variable

main()
{
  cell *LocalRoot = new cell;		    
					// Define a cell pointer
  HeapStack *MyHeap = new HeapStack(10000); 
					// Create a new heap zone

  MyHeap->roots.setp((GcObject **)&LocalRoot);  
					// Register the pointer as a root

  MyHeap->roots.set(&GlobalRoot);           
					// Register the cell as a root

  LocalRoot->next = new(MyHeap) cell;	
					// Allocates some new cells
  GlobalRoot.next = new(MyHeap) cell;

  MyHeap->collect();			    
					// The collector will identify
					// any allocated cell, starting
					// traversing from cell LocalRoot
					// and GlobalRoot

  MyHeap->roots.unsetp((GcObject **)&LocalRoot);
                                        // Deregister the local root.
}
\end{verbatim}

\section{References}
\begin{description}
\item [{[Bartlett 88]}]	Joel F. Bartlett  ``Compacting garbage collection with
ambiguous roots''  Tech. Rep.  88/2, DEC Western Research Laboratory,
Palo Alto, California, February 1988.
\item [{[Bartlett 89]}]	Joel F. Bartlett  ``Mostly-copying collection picks up generations and {\tt C++}'', 
Tech.  Rep.  TN-12, DEC Western Research Laboratory, Palo Alto,
California, October 1989.
\item [{[Boehm 88]}]	H.-J. Boehm and M. Wiser  ``Garbage collection in an uncooperative
environment'',  Software Practice and Experience, 18(9), 1988, 807-820.
\item [{[Edelson 92]}]	D.R. Edelson  ``Precompiling {\tt C++} for garbage collection'', in {\em Memory Management}, Y. Bekkers and J. Cohen (Eds.), Lecture Notes in Computer
Science, n. 637, Springer-Verlag, 1992, 299-314.
\item [{[Edelson 92b]}]	D.R. Edelson  ``A mark-and-sweep collector for {\tt C++}'',  Proc. of ACM
Conference on Principle of Programming Languages, 1992.
\item [{[Samples 92]}]	A.D. Samples  ``GC-cooperative {\tt C++}'',  Lecture Notes in Computer
Science, n. 637, Springer-Verlag, 1992, 315-329.
\item [{[Wentworth 90]}]	E. P. Wentworth  ``Pitfalls of conservative garbage collection'',  Software
Practice and Experience, 20(7), 1990, 719-727.
\item [{[Wilson 92]}]	P.R. Wilson  ``Uniprocessor garbage collection techniques'', in {\em Memory
Management}, Y. Bekkers and J. Cohen (Eds.), Lecture Notes in Computer
Science, n.  637, Springer-Verlag, 1992, 1-42.
\end{description}

\end{document}
back to top