2 Copyright (C) 2001-2009, Parrot Foundation.
7 src/gc/gc_inf.c - A demonstration of an infinite memory garbage collector
11 This code implements an example of a bare-bones "infinite memory" garbage
12 collector. This is a learning tool only to demonstrate how to implement the
13 GC API in a new core. DO NOT USE THIS CORE ANYWHERE FOR ANY REASON.
15 Because this core never frees memory, some functionality is missing and some
16 tests will fail: Tests for timely destruction, tests involving IO that is
17 not manually flushed (the GC never calls the destroy VTABLE, so things never
18 get flushed/closed automatically), etc. This is by design and should not be
19 considered a "bug" or an "error". It is just a fact of life for such a
22 To enable this core, change the settings in include/parrot/settings.h. Set
24 PARROT_GC_SUBSYSEM == 3
26 to activate this core.
32 #include "parrot/parrot.h"
33 #include "gc_private.h"
35 /* HEADERIZER HFILE: src/gc/gc_private.h */
37 /* HEADERIZER BEGIN: static */
38 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
40 static void gc_inf_add_free_object(SHIM_INTERP
,
41 ARGMOD(Fixed_Size_Pool
*pool
),
43 __attribute__nonnull__(2)
44 __attribute__nonnull__(3)
47 static void gc_inf_alloc_objects(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
))
48 __attribute__nonnull__(2)
51 PARROT_CANNOT_RETURN_NULL
52 static void * gc_inf_get_free_object(SHIM_INTERP
,
53 ARGMOD(Fixed_Size_Pool
*pool
))
54 __attribute__nonnull__(2)
57 static void gc_inf_mark_and_sweep(SHIM_INTERP
, UINTVAL flags
);
58 static void gc_inf_more_traceable_objects(SHIM_INTERP
,
59 ARGMOD(Fixed_Size_Pool
*pool
))
60 __attribute__nonnull__(2)
63 static void gc_inf_pool_init(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
))
64 __attribute__nonnull__(2)
67 #define ASSERT_ARGS_gc_inf_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
68 PARROT_ASSERT_ARG(pool) \
69 , PARROT_ASSERT_ARG(to_add))
70 #define ASSERT_ARGS_gc_inf_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
71 PARROT_ASSERT_ARG(pool))
72 #define ASSERT_ARGS_gc_inf_get_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
73 PARROT_ASSERT_ARG(pool))
74 #define ASSERT_ARGS_gc_inf_mark_and_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
75 #define ASSERT_ARGS_gc_inf_more_traceable_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
76 PARROT_ASSERT_ARG(pool))
77 #define ASSERT_ARGS_gc_inf_pool_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
78 PARROT_ASSERT_ARG(pool))
79 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
80 /* HEADERIZER END: static */
88 =item C<static void gc_inf_mark_and_sweep(PARROT_INTERP, UINTVAL flags)>
90 This function would perform a GC run, if we needed to. Luckily we have
93 This function is called from the GC API function C<Parrot_gc_mark_and_sweep>.
95 Flags can be a combination of these values:
106 gc_inf_mark_and_sweep(SHIM_INTERP
, UINTVAL flags
)
108 ASSERT_ARGS(gc_inf_mark_and_sweep
)
114 =item C<static void gc_inf_add_free_object(PARROT_INTERP, Fixed_Size_Pool *pool,
117 Manually frees a chunk of memory. Normally this would return the memory
118 to the free list of the pool, but in this case we just return it to the
121 This function is called from places like C<Parrot_gc_free_pmc_header> and
122 related manual freeing functions. Some cores will also use it internally to
123 add items to the freelist from a freshly allocated arena.
130 gc_inf_add_free_object(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
),
133 ASSERT_ARGS(gc_inf_add_free_object
)
140 =item C<static void * gc_inf_get_free_object(PARROT_INTERP, Fixed_Size_Pool
143 Gets a new object from the pool. Each pool specifies an object size in
144 C<pool->object_size> so we can use that number to make the allocation. For
145 GCs that manage their own memory through the use of arenas or similar
146 structures, we can use this basic algorithm here:
148 1) Check if we have any items on the free list and allocate one from there
150 2) Do a GC run to try and free up new items, and allocate a newly freed
151 item if one becomes available
152 3) Allocate a new arena from the OS and allocate a new item from there.
154 This function is called from GC API functions like
155 C<Parrot_Gc_get_new_pmc_header>
161 PARROT_CANNOT_RETURN_NULL
163 gc_inf_get_free_object(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
))
165 ASSERT_ARGS(gc_inf_get_free_object
)
166 return calloc(pool
->object_size
, 1);
171 =item C<static void gc_inf_alloc_objects(PARROT_INTERP, Fixed_Size_Pool *pool)>
173 Allocates a new arena of objects from the system. This function is only
174 really used internally by the core, the API functions don't need to call
175 it directly. However, this function is necessary because we may have
176 different behaviors for certain pools, so we can't allocate for all of them
177 in the same way. We will need to have a new "alloc_objects" function
178 for each special case pool.
185 gc_inf_alloc_objects(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
))
187 ASSERT_ARGS(gc_inf_alloc_objects
)
193 =item C<static void gc_inf_more_traceable_objects(PARROT_INTERP, Fixed_Size_Pool
196 Would normally try to find new traceable objects by first running a GC sweep
197 and then allocating a new arena from the system. Neither of these are
198 necessary in the infinite memory collector.
200 This function is only used internally to the core, and is not called directly
201 from the GC API. Different pools may have special requirements so multiple
202 "more_traceable_objects" functions may need to be written and used.
209 gc_inf_more_traceable_objects(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
))
211 ASSERT_ARGS(gc_inf_more_traceable_objects
)
217 =item C<static void gc_inf_pool_init(PARROT_INTERP, Fixed_Size_Pool *pool)>
219 Initializes the function pointers in a new pool. When a new pool is created
220 we assign several function pointers to it for managing memory in the pool.
221 In this way we can treat different pools differently if they have special
222 management needs. In general all PObj-like pools are treated the same.
224 This function is mostly called from the function C<initialize_fixed_size_pools>
225 in F<src/gc/mark_sweep.c> at Parrot startup.
232 gc_inf_pool_init(SHIM_INTERP
, ARGMOD(Fixed_Size_Pool
*pool
))
234 ASSERT_ARGS(gc_inf_pool_init
)
235 pool
->add_free_object
= gc_inf_add_free_object
;
236 pool
->get_free_object
= gc_inf_get_free_object
;
237 pool
->alloc_objects
= gc_inf_alloc_objects
;
238 pool
->more_objects
= gc_inf_more_traceable_objects
;
243 =item C<void Parrot_gc_inf_init(PARROT_INTERP)>
245 Initializes the infinite memory collector. Installs the necessary function
246 pointers into the Memory_Pools structure. The two most important are the
247 C<mark_and_sweep> and C<pool_init> functions. C<finalize_gc_system> function
248 will be called at Parrot exit and will shut down the GC system if things
249 need to be flushed/closed/deactivated/freed/etc. It can be set to NULL if no
250 finalization is necessary.
257 Parrot_gc_inf_init(PARROT_INTERP
)
259 ASSERT_ARGS(Parrot_gc_inf_init
)
261 interp
->gc_sys
->do_gc_mark
= gc_inf_mark_and_sweep
;
262 interp
->gc_sys
->finalize_gc_system
= NULL
;
263 interp
->gc_sys
->init_pool
= gc_inf_pool_init
;
277 * c-file-style: "parrot"
279 * vim: expandtab shiftwidth=4: