1This README provides an overview of the precise GC interface used by
2Racket. The header files "gc2.h" and "gc2_dump.h" provide additional
3API documentation.
4
5GC Interface
6------------
7
8The GC interface for Racket is designed to support precise collection
9with both moving and non-moving collectors. Generational and
10incremental collectors must rely on hardware-based memory protection
11for their implementation (to detect writes into old objects, etc.).
12
13As a general rule, all pointers to collectable objects reference the
14beginning of the object (i.e., the pointer is never into the interior
15of the object). The exception is that a pointer may reference the
16interior of an "Interior" object, but Racket allocates such objects
17infrequently, and only as relatively large objects.
18
19All allocated memory must be longword-aligned. For architectures where
20`double' values must be 8-byte aligned, the GC must provide 8-byte
21aligned memory in response to an allocation request for a memory size
22divisible by 8. Except for atomic memory, allocated objects must be
23completely initialized with 0s.
24
25Memory locations that hold pointers to collectable objects can also
26hold pointers to non-collectable memory. They may also contain a
27"fixnum" integer, where the lowest bit is set (so it could never be
28confused with a longword-aligned pointer). Thus, the collector must
29distinguish between longword-aligned pointers into collected memory
30regions and all other pointers.
31
32At any point when the allocator/collector is invoked, Racket will
33have set the GC_variable_stack variable to indicate a chain of local
34pointer variables on the stack (i.e., both the chain of record and the
35pointer variables themselves are on the stack). The GC_variable_stack
36global points to a value of the form
37
38 struct {
39 void *next_frame;
40 intptr_t frame_size;
41 void **pointers[...];
42 }
43
44where the size of `pointers' is indicated by `frame_size'. Each
45element of `pointers' is usually the address of a pointer of the
46stack. It can also be 0, in which case the next `pointers' element is
47an integer, and the following `pointers' element is a pointer to an
48array of the indicated size. (The three `pointers' slots contribute 3
49towards the value of `frame_size'.)
50
51The `next_frame' field in the structure gives the address of the next
52frame on the stack, and so on. The garbage collector should follow the
53chain of frames, adjusting pointers for copying collection, until it
54reaches a frame that is the same as the value returned by
55GC_get_thread_stack_base() (which is supplied by Racket).
56
57More generally, GC_mark_variable_stack() can be used to GC a stack
58that has been copied into the heap. See below for more details.
59
60Marking and Moving Objects
61--------------------------
62
63Cooperation between the garbage collector's movement of objects and
64Racket's view of object shapes (pointers versus non-pointers) is
65mediated by "mark" and "fixup" functions:
66
67 * The "mark" pass traverses objects in the heap, potentially moving
68 them and adjusting references.
69
70 * An optional extra "fixup" pass further adjusts references to moved
71 objects.
72
73The mark and fixup steps are exposed by gcMARK and gcFIXUP macros that
74are provided by the collector. In addition, the collector provides a
75GC_resolve operation, which converts an object's old address to a new
76one in the case that the object is being moved; given an object's new
77address GC_resolve returns the same address. A GC_is_marked operation
78reports whether an object at its old address has been marked; it works
79only on old addresses.
80
81Normally, the mark function for an object is called only when the
82object is first marked in a given GC pass. With generational
83collection, the mark function can be called for an old-generation
84object if it potentially changed since a previous collection; still,
85the mark function will be called only once during that collection, so
86it's as if the object were in the new generation. With incremental
87collection, however, a macro procedure can be called due to changes
88even if the object is already incrementally marked as an
89old-generaiton object. The GC_current_mode() function reports the
90current mode for a given call to the marking function.
91
92Memory Kinds
93------------
94
95Racket allocates the following kinds of memory objects:
96
97 * Tagged - The object starts with a `short' integer containing the
98 tag, but the tag will always be less than 256. After requesting
99 memory from the GC, Racket installs the tag before performing any
100 other memory operation. Racket provides three functions for each tag:
101
102 o an operation for obtaining the value's size in words (not
103 bytes!);
104
105 o an operation for marking pointers within the object; and
106
107 o an operation for another fixup pass.
108
109 The mark and fixup procedures use the gcMARK and gcFIXUP macros
110 provided by the collector. The mark and fixup operations also
111 return the size of the object, like the size procedure, unless
112 GC_NO_SIZE_NEEDED_FROM_PROCS is defined.
113
114 * Atomic - The allocated object contains no pointers to other
115 allocated objects.
116
117 * Atomic Tagged - Like a tagged object, but the mark and fixup
118 procedures are no-ops.
119
120 * Array - The allocated object is an array of pointers to other
121 allocated objects.
122
123 * Pair - specialization of Tagged to pairs.
124
125 * Interior Array - Like array objects, but pointers to the object can
126 reference its interior, rather than just the start of the object,
127 and the object never moves. Such pointers will always be
128 longword-aligned. Racket allocates interior objects infrequently,
129 and only as relatively large objects.
130
131 * Weak Box - The object has the following initial structure:
132
133 struct {
134 short tag;
135 short filler_used_for_hashing;
136 void *val;
137 }
138
139 Racket reads the `tag' and `val' fields, and both reads and
140 writes the `filler_used_for_hashing' field. Racket also provides
141 the value to be used for `tag', via GC_init_type_tags(). The reason
142 this structure is implemented by the collector is to handle the
143 special behavior of the weak link.
144
145 Racket can change `val' at any time; when a collection happens,
146 if the object in `val' is collectable and is collected, then `val'
147 is zeroed. The `val' pointer must be updated by the collector if
148 the object it refers to is moved by the collector, but it does not
149 otherwise keep an object from being collected.
150
151 The interface for creating weak boxes is
152
153 void *GC_malloc_weak_box(void *p, void **secondary, int soffset);
154
155 If the `secondary' argument is not NULL, it points to an auxiliary
156 address that should be zeroed (by the collector) whenever `val' is
157 zeroed. To allow zeroing in the interior of an allocated pointer,
158 the zero-out address is determined by `secondary + soffset'. The
159 memory referenced by `secondary' is kept live as long as it isn't
160 zeroed by its registration in the weak box, but when the content of
161 `secondary + soffset' is zeroed, the `secondary' pointer in the
162 weak box should also be zeroed.
163
164 * Late Weak Box - A weak box that holds onto its reference until
165 level-2 finalizers are queued (see below). Late weak boxes are
166 created with GC_malloc_late_weak_box().
167
168 * Weak Array - The object has the following structure:
169
170 struct {
171 intptr_t gc_private[4];
172 intptr_t array[...];
173 }
174
175 The gc_private array contains collector-private values that are
176 neither read nor written by Racket. The array field is an array
177 of weak pointers to collectable objects. See GC_malloc_weak_array()
178 in gc2.h for more details.
179
180 * Ephemeron - The object has the following initial structure:
181
182 struct {
183 short tag;
184 short filler_used_for_hashing;
185 void *key;
186 void *val;
187 }
188
189 See "Weak Box" above. The difference for an ephemeron is that
190 the ephemeron must hold `val' strongly as long as the wealy-held
191 `key' is accessible --- where `val' itself isn't traced unless
192 both the ephemeron and `key' are reachable. (In particular,
193 a reference from `val' to `key' doesn't prevent collection of
194 `key'.)
195
196 * Immobile box - a longword-sized box that can contain a reference to
197 a collectable object, but it not itself collectable or movable. An
198 immobile box lets Racket refer to a collectable object (through
199 one indirection) from memory that is not traversed by the
200 collector.
201
202 The GC_malloc_immobile_box() function creates an immobile box with
203 an initial value:
204
205 void **GC_malloc_immobile_box(void *p);
206
207 Immobile boxes must be explicitly freed with the
208 GC_free_immobile_box() function:
209
210 void GC_free_immobile_box(void **b);
211
212Of course, an implementation of the collector may collapse any of
213these categories internally.
214
215Finalization
216------------
217
218The finalization interface is
219
220 void GC_set_finalizer(void *p, int tagged, int level,
221 GC_finalization_proc f, void *data,
222 GC_finalization_proc *oldf, void **olddata);
223
224This function installs a finalizer to be queued for invocation when
225`p' would otherwise be collected. All ready finalizers should be
226called at the end of a collection. (A finalization can trigger calls
227back to the collector, but such a collection will not run more
228finalizers.) The `p' argument must normally point to the beginning of
229a tagged (including atomic or pair) object; that is, `tagged' is
230currently required to be non-zero.
231
232The `level' argument refers to an ordering of finalizers. It can be 1,
2332, or 3. During a collection, level 1 finalizers are queued first,
234then all objects queued for finalization are marked as live and
235traversed. Next, level 2 finalizers are queued in the same way. Thus,
236if a level 1 object refers to a level 2 object, the level 1 object
237will be queued for finalization, and only sometime after the finalizer
238is run and the object is again no longer referenced can the level 2
239object be finalized. Finally, level 3 finalizers are queued.
240
241The `f' and `data' arguments define the finalizer closure to be called
242for `p'. If a finalizer is already installed for `p', it is replaced,
243and `oldf' and `olddata' are filled with the old closure. If `f' is
244NULL, any existing finalizer is removed and no new one is
245installed. The single-callback rule applies across level 1 and level
2462 finalizers (but scheme_register_finalizer(), etc., in "salloc.c" can
247merge them).
248
249The `p' object isn't actually collected when a finalizer is queued,
250since the finalizer will receive `p' as an argument. Weak references
251are cleared after level 1 fnalizers are queued, while "late weak box"
252references are cleared after level 2 finalizers are clear.
253
254Functions versus Macros
255-----------------------
256
257Any function in the defined interface can be implemented as a
258macro. Indeed, gcMARK() and gcFIXUP() are expected to be
259macros.
260
261Due to the way that the Racket and GRacket code is generated for
262precise collection, the header file gc2.h must allow multiple
263inclusion in two different phases. If the pre-processor symbol
264GC2_JUST_MACROS is defined, then the header should only define
265macros. If GC2_JUST_MACROS is not defined, then the header should
266define all typedefs, function proptypes, and macros.
267