Pool classes
| author | Richard Brooksby |
| copyright | See Copyright and License. |
| date | 1997-08-19 |
| index terms | pair: pool classes; design |
| revision | //info.ravenbrook.com/project/mps/custom/cet/branch/2018-06-28/monitor/design/pool.txt#2 |
| status | incomplete design |
| tag | design.mps.pool |
Introduction
.intro: This document describes the interface and protocols between the MPM and the pool classes.
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", "MV".
.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.
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.
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:
- .method.inst.finish: The finish method (design.mps.protocol.inst.method.finish) must finish the outer structure and then call its superclass method via the NextMethod() macro (thus calling PoolAbsFinish() which finishes the generic structure).
- .method.inst.describe: The describe method (design.mps.protocol.inst.method.describe) should print a description of the pool. Each line should begin with two spaces. Classes are not required to provide this method.
typedef 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).
typedef 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().
typedef 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).
typedef 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).
typedef 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().
typedef 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 must be 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 the BufferFill().
typedef void (*PoolBufferEmptyMethod)(Pool pool, Buffer buffer, Addr init, Addr limit)
.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). This method must be provided if and only if bufferFill is provided. This method is called by the generic function BufferDetach().
typedef Res (*PoolAccessMethod)(Pool pool, Seg seg, Addr addr, AccessSet mode, MutatorContext context)
.method.access: The access method indicates that the client program attempted to access the address addr, but has been denied due to a protection fault. The mode indicates whether the client program was trying to read (AccessREAD) or write (AccessWRITE) the address. If this can't be determined, mode is AccessREAD | AccessWRITE. The pool should perform any work necessary to remove the protection whilst still preserving appropriate invariants (this might scanning the region containing addr). Pool classes are not required to provide this method, and not doing so indicates they never protect any memory managed by the pool. This method is called via the generic function PoolAccess().
typedef Res (*PoolWhitenMethod)(Pool pool, Trace trace, Seg seg)
.method.whiten: The whiten method requests that the pool to condemn (a subset of, but typically all) the objects in the segment seg for the trace trace. That is, prepare them for participation in the trace to determine their liveness. The pool should expect fix requests (.method.fix) during the trace and a reclaim request (.method.reclaim) at the end of the trace. Pool classes that automatically reclaim dead objects must provide this method, and must additionally set the AttrGC attribute. This method is called via the generic function PoolWhiten().
typedef void (*PoolGreyMethod)(Pool pool, Trace trace, Seg seg)
.method.grey: The grey method requires the pool to colour the objects in the segment seg grey for the trace trace (excepting objects that were already condemned for this trace). That is, make them ready for scanning by the trace trace. The pool must arrange that any appropriate invariants are preserved, possibly by using the protection interface (see design.mps.prot). Pool 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.
typedef void (*PoolBlackenMethod)(Pool pool, TraceSet traceSet, Seg seg)
.method.blacken: The blacken method is called if it is known that the segment seg cannot refer to the white set for any of the traces in traceSet. The pool must blacken all grey objects in the segment for those traces. Pool 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. This method is called via the generic function PoolBlacken().
typedef Res (*PoolScanMethod)(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
.method.scan: The scan method requires that the pool scan all the grey objects on the segment seg, passing the scan state ss to FormatScan. The pool may additionally accumulate a summary of all the objects on the segment. If it succeeds in accumulating such a summary it must indicate that it has done so by setting the *totalReturn parameter to TRUE. Otherwise it must set *totalReturn to FALSE. Pool 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. This method is called via the generic function PoolScan().
typedef Res (*PoolFixMethod)(Pool pool, ScanState ss, Seg seg, Ref *refIO)
.method.fix: The fix method indicates that the reference *refIO has been discovered at rank ss->rank by the traces in ss->traces, and the pool must handle this discovery according to the fix protocol (design.mps.fix). If the pool moves the object, it must update *refIO to refer to the new location of the object. If the pool determines that the referenced object died (for example, because the highest-ranking references to the object were weak), it must update *refIO to NULL. Pool classes that automatically reclaim dead objects must provide this method, and must additionally set the AttrGC attribute. Pool classes that may move objects must also set the AttrMOVINGGC attribute. The fix method is on the critical path (see design.mps.critical-path) and so must be fast. This method is called via the function TraceFix().
.method.fixEmergency: The fixEmergency method is used to perform fixing in "emergency" situations. Its specification is identical to the fix method, but it must complete its work without allocating memory (perhaps by using some approximation, or by running more slowly). Pool classes must provide this method if and only if they provide the fix method. If the fix method does not need to allocate memory, then it is acceptable for fix and fixEmergency to be the same.
typedef void (*PoolReclaimMethod)(Pool pool, Trace trace, Seg seg)
.method.reclaim: The reclaim method indicates that any remaining white objects in the segment seg have now been proved unreachable by the trace trace, and so are dead. The pool should reclaim the resources associated with the dead objects. Pool classes are not required to provide this method. If they do, they must set the AttrGC attribute. This method is called via the generic function PoolReclaim().
typedef void (*PoolWalkMethod)(Pool pool, Seg seg, FormattedObjectsVisitor f, void *v, size_t s)
.method.walk: The walk method must call the visitor function f (along with its closure parameters v and s and the appropriate object format) once for each of the black objects in the segment seg. Padding objects may or may not be included in the walk, at the pool's discretion: it is the responsibility of the client program to handle them. Forwarding objects must not be included in the walk. Pool classes need not provide this method. If they do, they must set the AttrFMT attribute. This method is called by the heap walker mps_arena_formatted_objects_walk().
typedef 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().
Document history
Copyright and License
Copyright © 2013-2016 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:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- 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.
- 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.