22. Pool classes

22.1. Introduction

.intro: This document describes the interface and protocols between the MPM and the pool classes.

22.2. Classes and structures

.class: Each pool belongs to a pool class.

.class.name: Each pool class has a short, pithy, cryptic name for the pool class. It should start with "A" (for “automatic”) if memory is managed by the garbage collector, and "M" (for “manual”) if memory is managed by alloc/free. For example, “AMC”, “MVFF”.

.class.protocol: Pool classes use the protocol mechanisms (see design.mps.protocol) to implement class initialization and inheritance.

.class.structure: Each pool class has an associated class structure, which is a C object of type PoolClass. This is initialized and accessed via the CLASS() macro, for example CLASS(MRGPool) initializes and accesses the class structure for the MRG pool class.

.struct.outer: The outer structure of a pool belonging to the ABC pool class is a C object of type ABCPoolStruct, which is a typedef for struct PoolABCStruct.

.stuct.outer.sig: It is good practice to put the signature for the outer structure at the end (of the structure). This is because there’s already one at the beginning (in the generic structure), so putting it at the end gives some extra fencepost checking.

.struct.generic: The generic structure of a pool is a C object of type PoolStruct (found embedded in the outer structure), which is a typedef for struct PoolStruct.

22.3. Fields

.field: These fields are provided by pool classes as part of the PoolClass object (see .class.structure). They form part of the interface which allows the MPM to treat pools in a uniform manner.

.field.name: The name field must be the pool class name (.class.name).

.field.size: The size field is the size of the pool instance structure. For the PoolABC class this can reasonably be expected to be sizeof(PoolABCStruct).

.field.attr: The attr field must be a bitset of pool class attributes. See design.mps.type.attr.

.field.alignShift: The alignShift field is the SizeLog2 of the pool’s alignment. It is computed and initialised when a pool is created. Mark-and-sweep pool classes use it to compute the number of grains in a segment, which is the number of bits need in the segment’s mark and alloc bit tables.

.field.format: The format field is used to refer to the object format. The object format is passed to the pool during pool creation.

22.4. Methods

.method: These methods are provided by pool classes as part of the PoolClass object (see .class.structure). They form part of the interface which allows the MPM to treat pools in a uniform manner.

.method.unused: If a pool class is not required to provide a certain method, the class should assign the appropriate PoolNo method (which asserts) for that method to ensure that erroneous calls are detected. It is not acceptable to use NULL.

.method.trivial: If a pool class if required to provide a certain method, but the class provides no special behaviour in this case, it should assign the appropriate PoolTriv method, which does nothing.

.method.inst: Pool classes may implement the generic instance methods (see design.mps.protocol.inst.method). In particular:

void (*PoolVarargsMethod)(ArgStruct args[], va_list varargs)

.method.varargs: The varargs field decodes the variable arguments to the deprecated function mps_pool_create() and converts them to a list of keyword arguments (see design.mps.keyword-arguments).

Res (*PoolInitMethod)(Pool pool, Arena arena, PoolClass klass, ArgList args)

.method.init: The init method must call its superclass method via the NextMethod() macro (thus calling PoolAbsInit() which initializes the generic structure), and then initialize the outer structure. It is called via the generic function PoolInit().

Res (*PoolAllocMethod)(Addr *pReturn, Pool pool, Size size)

.method.alloc: The alloc method manually allocates a block of at least size bytes. It should update *pReturn with a pointer to a fresh (that is, not overlapping with any other live object) object of the required size. Failure to allocate must be indicated by returning an appropriate error code, and in such a case, *pReturn must not be updated. Pool classes are not required to provide this method. It is called via the generic function PoolAlloc().

.method.alloc.size.align: A pool class may allow an unaligned size (rounding it up to the pool’s alignment).

void (*PoolFreeMethod)(Pool pool, Addr old, Size size)

.method.free: The free method manually frees a block. The parameters are required to correspond to a previous allocation request (possibly via a buffer, not necessarily via PoolAlloc()). It is an assertion by the client that the indicated object is no longer required and the resources associated with it can be recycled. Pool classes are not required to provide this method. It is called via the generic function PoolFree().

.method.free.size.align: A pool class may allow an unaligned size (rounding it up to the pool’s alignment).

BufferClass (*PoolBufferClassMethod)(void)

.method.bufferClass: The bufferClass method returns the class of buffers used by the pool. Pool classes are not required to provide this method. It is called via the generic function PoolDefaultBufferClass().

Res (*PoolBufferFillMethod)(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size size)

.method.bufferFill: The bufferFill method should allocate a region of least size bytes of memory for attaching to buffer. The buffer is in the “reset” state (see design.mps.buffer.reset). If successful, it must update *baseReturn and *limitReturn to the base and limit of the allocated region and return ResOK. Otherwise it must leave *baseReturn and *limitReturn unchanged and return a non-OK result code. Pool classes are not required to provide this method. This method is called by BufferFill().

void (*PoolBufferEmptyMethod)(Pool pool, Buffer buffer)

.method.bufferEmpty: The bufferEmpty method indicates that the client program has finished with the unused part of the buffer (the part between init and limit). The buffer is in the “ready” state (see design.mps.buffer.ready). This method must be provided if and only if bufferFill is provided. This method is called by the generic function BufferDetach().

Size (*PoolSizeMethod)(Pool pool)

.method.totalSize: The totalSize method must return the total memory allocated from the arena and managed by the pool. This method is called by the generic function PoolTotalSize().

.method.freeSize: The freeSize method must return the free memory allocated from the arena and managed by the pool, but not in use by the client program. This method is called by the generic function PoolFreeSize().