1 # Copyright (C) 2001-2004, Parrot Foundation.
6 docs/memory_internals.pod - Memory Internals
10 This document tries to explain the internals of the Parrot memory subsystem,
11 and the data structures related to memory management and garbage collection.
15 All allocated items are managed in memory pools. Memory pools hold collections
16 of similar items, items of the same data type and usually of the same size.
17 These can be roughly divided into two kinds: pools holding fixed sized items
18 and pools holding variable sized items.
20 A pool is organized as a linked list of big chunks, called I<Arenas>. Each
21 Arena holds and manages a set number of items of a single size and shape.
23 =head2 Abbreviations used here
29 Garbage collector. A garbage collector is a system that finds memory objects
30 that are not being used by the system, and frees them automatically. Garbage
31 collection is broken into two distinct phases: the I<mark phase> that searches
32 for unreferenced objects, and the I<sweep phase> that frees all dead objects.
36 Dead object detection, a deprecated term that refers to the I<mark phase>
37 of the garbage collector.
41 By scanning through all the interpreter's registers, stacks and the processor
42 stack, all objects that are detected by the garbage collector are marked as
43 alive. Objects in all pools not alive at the end of the mark phase are
44 considered dead and are collected.
46 See F<docs/pdds/pdd09_gc.pod> for details about the garbage collector system.
48 =head1 Top down: the interpreter
50 A overall layout of the interpreter's memory management looks like so:
52 typedef struct Interp {
54 struct Arenas *arena_base;
58 All object-like things that get allocated during the execution of parrot
59 bytecode are managed from the C<arena_base> member of the interpreter
64 C<struct Arenas> holds pointers to a variety of different kinds of managed
65 memory. A simplification looks similar to this:
67 typedef struct Arenas {
68 struct Memory_Pool *memory_pool;
70 struct Small_Object_Pool * header_pool;
71 struct Small_Object_Pool ** sized_pools;
74 C<memory_pool> and C<header_pool> are variable and fixed sized pool pointers
75 respectively. These are just two examples, there are other C<Memory_Pool>s
76 and C<Small_Object_Pool>s in the Parrot system. Pools of type
77 C<struct Memory_Pool> are for variable-size objects, such as constant string
78 buffers. Pools of type C<struct Small_Object_Pool> are for fixed-size objects
79 such as headers or PMCs.
81 =head1 Fixed sized items
83 Fixed-size items are either objects by themselves, like a C<PMC>, or are
84 header structures of variable-sized objects like C<STRING>. The general
85 object of this kind is a buffer-like object, which consists of a
86 C<Buffer> or a C<PObj> header at the beginning connected to a variable-sized
87 memory block for data.
89 Buffer-like objects of the same size are maintained in the list of
90 C<sized_pools>, which manage objects of the same size in one slot.
92 Every garbage collector must supply 4 function pointers: an initialization
93 routine, a de-initialization routine, a function to initialize a new memory
94 pool, and a function to initiate a garbage collection run. Every pool also
95 requires the garbage collector to supply 4 additional function pointers: a
96 function to allocate a new arena for the pool, a function to find more items
97 (possibly through running the garbage collector, or allocating objects
98 otherwise), a function to add an unused item to the free list, and a function
99 to retrieve a new free item from the pool.
101 Every pool maintains a list of unused items within the pool, called the
102 C<free_list> When there is need for a new object it is taken off the free
103 list, and when it stops being used, it will be put back on the free list
104 again. GC mark determines which objects are not being used, and GC sweep
105 adds those unused items back to the free list.
107 If the free list is empty then a GC run could be initiated. This may be
108 able to find some dead objects and free them up for immediate reuse.
109 However, if there are no objects that can be immediately recycled, a new
110 arena will be allocated.
112 Arenas, which contain the fixed-sized items used by Parrot, are never returned
113 to the operating system, even if they are empty. In the future, this behavior
114 may change, however. Variable-sized buffers may be returned when they are no
117 =head2 General structure of a buffer-like item
119 struct parrot_object_t {
125 This does not totally reflect the current implementation, but is the spirit of
126 the abstraction of current objects. The C<UnionVal cache> field is a C<union>
127 that contains a variety of pointer and data configurations. The flags field
128 may contain a series of flags which indicate the type, status, configuration,
129 and special requirements of each item. Buffers, C<PMC>s, and C<PObj>s all
130 have these basic fields in common, although they also contain a variety of
131 other data fields, depending on type.
133 =head2 GC-related PObj flags
135 Only three flags need to be checked during a mark run: C<PObj_live_FLAG>,
136 C<PObj_on_free_list_FLAG>, and C<PObj_is_special_PMC_FLAG>. Normally these
137 flags are stored in C<PObj-E<gt>flags>, meaning that each PMC must be accessed
140 An alternative approach is to store the GC-Flags together somewhere, such as
141 in the individual arenas, as a packed array of bits. This approach, called
142 cardmarking, should be indicated by defining the preprocessor variable
143 C<ARENA_GC_FLAGS> to 1.
145 {{ ARENA_GC_FLAGS (nee ARENA_DOD_FLAGS) seems to have been deprecated or
146 changed without concomitant update to this document. Someone should figure out
147 what this macro used to be and whether it's still relevant. -cotto }}
149 F<pobj.h> provides macros to facilitate referencing individual object flags:
150 C<gc_flag_SET>, C<gc_flag_CLEAR> and C<gc_flag_TEST>. They make up a portable
151 way of manipulating the GC-relevant object flags.
153 =head1 Variable sized items
155 Variable-sized items do not exist by themselves, they are always preceded by
156 a buffer structure that contains information about them. These buffer
157 structures are described above, and the C<UnionVal cache> item typically
158 points to the memory block that contains the data. The variable-sized data
159 items are managed in two different pools: the C<memory_pool>, which contains
160 a general mish-mash of data types, and the C<constant_string_pool> which
161 contains immutable string buffers used by programs running on Parrot.
163 Here, different memory allocation schemes jump in:
167 A C<memory_pool> gets allocated in big blocks, namely a C<Memory_Block>.
168 When some part is needed, e.g. to store a string, this part is carved out of
169 the memory block, until this block is used up. If no more space is available in
170 this memory block, a special copying garbage collection (GC) is started.
171 This copies all living items of all used memory blocks into one new block,
172 which holds thereafter only used items tightly packed together.
174 The old memory blocks, containing sparse unused parts and used parts already
175 copied to the new place, are then unused altogether and get C<free()>ed
176 thereafter. When GC doesn't provide enough free space needed for a new item,
177 a new block is added to the memory pool.
179 This also implies that buffers are moved around during their life. Users of
180 these buffers are therefore not allowed to hold pointers to buffers over pieces
181 of code that might trigger a GC run, like C<Parrot_allocate()> or
182 C<Parrot_str_compare()>.
184 =head2 Defragmenting allocator
186 An alternative to the above is to use a memory allocator, which is as fast as
187 the above and does reuse C<free()>ed items in a memory-conserving way.
188 Actually, the malloc implementations in some systems' F<libc> efficiently
189 provide this, such as the glibc malloc based on Doug Lea's allocator.
191 Using this allocator, all variable sized items are just allocated via a plain
192 C<malloc()> call, or resized with C<realloc()>, and after they lose their
193 existence (ie when the mark phase detects that the managing buffer header is no
194 longer in use) they are C<free()>ed. That's all. The underlying allocator
195 collects these pieces, coalesces them if possible to form bigger pieces, and
196 then puts them on free lists, sorted by size. Eventually, when a new
197 allocation request arrives, it may give them back to Parrot.
199 So here, the variable length C<memory_pool> is unused. You can consider this
200 pool to live inside the allocator. Buffers allocated this way don't move
201 around, except when reallocated, of course.
203 The F<Configure.pl> option C<--gc> allows one to use either method.
205 =head2 Buffer_Tail and COW
207 Both implementations have the same problem to solve: C<STRING>s that get
208 copied, or parts of strings as the result of a substr() call, do not allocate
209 new space in the memory pool to hold this string or part of string. They just
210 use a C<new_string_header()> and set up a pointer (C<strstart>) pointing
211 somewhere into the original string and remember the used length there in
214 This is all OK, as long as the original and the lazy copy of the string are not
215 modified. So that's well-known and called COW (copy on write). We don't have
216 to make a copy of the buffer until one of the copies tries to modify it. In
217 practice, strings often get copied from place to place but do not often get
218 modified, so this optimization saves us a lot of time.
220 Now, during GC (or freeing buffers) the problem arises: to whom does this
221 string belong? You shouldn't copy the same string to different places, thus
222 rendering COW to a noop, nor are you allowed to free this same string more then
223 once. Both allocation schemes therefore use a part of the allocated string to
226 Copying GC uses a C<Buffer_Tail> after the end of the actual variable length
227 string and marks such COW strings with C<TAIL_moved> and stores the new address
228 in the buffer header, so other users of this string can be updated to reuse the
229 same string (RT#47764 one or all other users?).
231 The C<malloc()>/C<free()> approach stores a refcount at C<bufstart>. During the
232 mark phase all dead users increment the refcount, living users set it to an
233 huge value. When freeing the buffer, the string is only freed if the refcount
236 =head1 Simplified Figure
239 +------------------<---| Arenas |<-----------+
242 | +------+ +-----------+ | +=============+
243 | | S0 |<---| Registers |<--)--| Interpreter |
244 | +------+ +-----------+ | +=============+
246 | | +------+ +----------+
248 | Blk 1 |--)-->+----------+ +--------------+ +---------+
249 +-------+ | | Buffer 1 | | OnestringAno | | Block 1 |
250 | Blk 2 | | +----------+ | therstring.. | +---------+
251 +-------+ | | Buffer 2 | | ..String... |<--| Block 2 |
252 | . | | +----------+ +--------------+ +---------+
253 +-------+ | | ... | ^ ^ | ... |
254 Small Obj | +----------+ | | +---------+
255 Pool +-->| Buffer N |--------+----+ Memory Pool
259 Now consider that the I<Interpreter> shall be a C<PMC> living in C<Buffer X>
260 of the underlying interpreter and is currently running F<perldoc
261 docs/memory_internals.pod>, and then redo this figure, with all the blanks
266 mark_sweep.[ch], src/gc/pools.c, resources.[ch], res_lea.c, src/gc/api.c,
267 string.[ch], pobj.h. Other garbage collector implementations may use separate
272 To minimize this bugs section - please patch this document and keep it up to
277 Leopold Tötsch C<lt@toetsch.at>