Liberty Eiffel provides two garbage collector implementations.
Most core libraries are also well equipped to minimize memory requirements in the case that no GC is used.
The native GC is generated at the same time as the rest of the code, allowing efficient use of the memory by splitting it in chunks of known size.
See this paper for details.
From the source code:
The `mark_stack_and_registers' C function is called by the Garbage Collector (GC) of SmartEiffel. It has to be customized for some systems, but also for some C compilers. This file provides some definitions in the end and has to be completed for systems which need specific work.
On some architectures, addresses increase as the stack grows; or, conversely, addresses decrease as the stack grows. A C compiler may be clever enough to hide some root object inside registers. Unfortunately all registers are not always accessible via the C `setjmp' function!
Thus, in order to be able to use the GC on your architecture/C-compiler, you have to provide the correct `mark_stack_and_registers' function.
What is the `mark_stack_and_registers' function supposed to do? The `mark_stack_and_registers' function is supposed to notify the GC with all the possible roots one can find in the C stack and registers by calling the `gc_mark' function. A root is an object which must not be collected. The SmartEiffel GC already knows about some root objects like once function results or manifest strings. The `mark_stack_and_registers' function has to notify the other possible roots. Obviously, one can find in the C stack any kind of adresses, but the `gc_mark' function is clever enough to determine if the passed pointer is an Eiffel object or not. When the passed pointer reaches some Eiffel object, this object as well as its descendant(s) are automatically marked as un-collectable.
In order to provide the most appropriate `mark_stack_and_registers' function, the very first question is to know about the way the C stack is managed (addresses of the stack may increase or decrease as the C stack grows). The DEFAULT BEHAVIOUR FOR UNKNOWN SYSTEMS is to consider ADDRESSES DECREASE AS THE STACK GROWS, as it's the most common case. The global C variable `stack_bottom' is set with some pointer which is supposed to be the bottom of the stack (this variable is automatically initialized in the C main function). Note: using the current stack pointer inside `mark_stack_and_registers', it is quite obvious to determine if addresses increase or not as the C stack grows. Note2: on some systems, the stack is not in contiguous addresses. In such case, `mark_stack_and_registers' has to go through all the stack fragments.
Some roots may be stored only in registers and not in the C stack. In order to reach the registers as well, the first attempt is to use setjmp, in the hope that setjmp will save registers in the stack! Note: this technique do not work on processors using windows registers (such as sparc processors).
The Boehm-Demers-Weiser conservative collector is also supported. The minimal required version is currently 7.2.
The missing parts are:
- a lot of testing (esp. dynamic arrays, weak references, agents)
- total GC cycle at the end of the program (Eiffel requires that all the objects are disposed at exit, and some programs or libraries rely on that behaviour, usually for checks — is it important?)
- Liberty does not make use of the parallel or incremental collectors