source: src/examples/gc_no_raii/src/internal/state.c @ 4ef8fb3

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 4ef8fb3 was 4ef8fb3, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

fixed compilation of garbage collector

  • Property mode set to 100644
File size: 6.3 KB
Line 
1#include "state.h"
2
3#include <stdlib>
4
5//general purpouse includes
6#include "tools.h"
7
8//platform abstraction includes
9#include "allocate-pool.h"
10
11//gc internal includes
12#include "collector.h"
13#include "globals.h"
14#include "memory_pool.h"
15#include "object_header.h"
16#include "tools/worklist.h"
17
18void gc_state_swap(gc_state *const this);
19void gc_state_sweep_roots(gc_state *const this, worklist_t* worklist);
20void gc_state_clear(gc_state *const this);
21void gc_state_calc_usage(gc_state *const this);
22
23#if DEBUG
24        bool gc_state_roots_match(gc_state *const this);
25        bool gc_state_no_from_space_ref(gc_state *const this);
26#endif
27
28gc_state* gc_get_state()
29{
30        static gc_state s;
31        if(!s.is_initialized) ctor(&s);
32        return &s;
33}
34
35void ctor(gc_state *const this)
36{
37        this->from_code = 0;
38        this->to_space = NULL;
39        this->from_space = NULL;
40        this->total_space = 0;
41        this->used_space = 0;
42        ctor(&this->pools_table);
43
44        gc_allocate_pool(this);
45
46        this->is_initialized = true;
47}
48
49void dtor(gc_state *const this)
50{
51        dtor(&this->pools_table);
52        this->is_initialized = false;
53}
54
55bool gc_is_in_heap(const gc_state* const this, const void* const address)
56{
57        gc_memory_pool* target_pool = gc_pool_of(address);
58
59        gc_memory_pool** first = cbegin(&this->pools_table);
60        gc_memory_pool** last = cend(&this->pools_table);
61        gc_memory_pool** result = find(first, &last, target_pool);
62        return result != last && gc_pool_is_from_space(*result);
63}
64
65bool gc_is_in_to_space(const gc_state* const this, const void* const address)
66{
67        gc_memory_pool* target_pool = gc_pool_of(address);
68
69        gc_memory_pool** first = cbegin(&this->pools_table);
70        gc_memory_pool** last = cend(&this->pools_table);
71        gc_memory_pool** result = find(first, &last, target_pool);
72        return result != last && !gc_pool_is_from_space(*result);
73}
74
75gc_object_header* gc_get_object_for_ref(gc_state* state, void* member)
76{
77        intptr_t target = ((intptr_t)member);
78        if(!gc_is_in_heap(state, member)) return NULL;
79
80        gc_memory_pool* pool = gc_pool_of(member);
81        gc_pool_object_iterator it = gc_pool_iterator_for(pool, member);
82        gc_pool_object_iterator end = end(pool);
83
84        while(it != end)
85        {
86                gc_object_header* object = *it;
87                {
88                        intptr_t start = ((intptr_t)object);
89                        intptr_t end = ((intptr_t)start + object->size);
90                        if(start < target && end > target)
91                        {
92                                return object;
93                        }
94                }
95                ++it;
96        }
97
98        checkf(false, "is_in_heap() and iterator_for() return inconsistent data");
99        abort();
100        return NULL;
101}
102
103void* gc_try_allocate(gc_state* const this, size_t size)
104{
105        gc_memory_pool* pool = this->from_space;
106        while(pool != (gc_memory_pool*)0)
107        {
108                if(gc_pool_size_left(pool) > size)
109                {
110                        return gc_pool_allocate(pool, size, true);
111                }
112                pool = pool->next;
113        }
114
115        return (void*)0;
116}
117
118void gc_allocate_pool(gc_state *const this)
119{
120        gc_memory_pool* old_from_space = this->from_space;
121      gc_memory_pool* old_to_space = this->to_space;
122
123      this->from_space = (gc_memory_pool*)(pal_allocPool(POOL_SIZE_BYTES, 1));
124      this->to_space = (gc_memory_pool*)(pal_allocPool(POOL_SIZE_BYTES, 1));
125
126      ctor(this->from_space, POOL_SIZE_BYTES, old_from_space, this->to_space,   this->from_code);
127      ctor(this->to_space,   POOL_SIZE_BYTES, old_to_space,   this->from_space, (~this->from_code) & 0x01);
128
129        this->total_space += gc_pool_size_used(this->from_space);
130
131        push_back(&this->pools_table, this->from_space);
132        push_back(&this->pools_table, this->to_space);
133}
134
135void gc_collect(gc_state* const this)
136{
137        // DEBUG("collecting");
138        // DEBUG("previous usage " << this->used_space << " / " << this->total_space);
139
140        worklist_t worklist;
141        ctor(&worklist);
142        gc_state_sweep_roots(this, &worklist);
143
144        while(!empty(&worklist))
145        {
146                intptr_t* ref = back(&worklist);
147                pop_back(&worklist);
148                gc_process_reference((void**)ref, &worklist);
149        }
150
151        check(gc_state_roots_match(this));
152        check(gc_state_no_from_space_ref(this));
153
154        gc_state_swap(this);
155
156        gc_state_calc_usage(this);
157
158        if(gc_needs_collect(this)) gc_allocate_pool(this);
159
160        // DEBUG("done");
161        dtor(&worklist);
162}
163
164void gc_state_swap(gc_state* const this)
165{
166        swap(&this->from_space, &this->to_space);
167
168        gc_memory_pool* pool = this->to_space;
169        while(pool)
170        {
171                gc_reset_pool(pool);
172                pool = pool->next;
173        }
174
175        this->from_code = (~this->from_code) & 0x01;
176
177        #if _DEBUG
178                {
179                        gc_memory_pool* pool = this->from_space;
180                        while(pool)
181                        {
182                                check(gc_pool_is_from_space(pool));
183                                pool = pool->next;
184                        }
185
186                        pool = this->to_space;
187                        while(pool)
188                        {
189                                check(!gc_pool_is_from_space(pool));
190                                pool = pool->next;
191                        }
192                }
193        #endif
194}
195
196void gc_state_sweep_roots(gc_state* const this, worklist_t* worklist)
197{
198        gc_memory_pool* pool = this->from_space;
199        while(pool)
200        {
201                gc_pool_object_iterator it = begin(pool);
202                gc_pool_object_iterator end = end(pool);
203                for(;it != end; ++it)
204                {
205                        gc_object_header* object = *it;
206                        if(!object->root_chain) continue;
207
208                        gc_copy_object(object);
209
210                        gc_scan_object(object->forward, worklist);
211                }
212
213                pool = pool->next;
214        }
215}
216
217void gc_state_clear(gc_state* const this)
218{
219        gc_memory_pool* pool = this->from_space;
220        while(pool)
221        {
222                gc_reset_pool(pool);
223                pool = pool->next;
224        }
225
226        pool = this->to_space;
227        while(pool)
228        {
229                gc_reset_pool(pool);
230                pool = pool->next;
231        }
232}
233
234void gc_state_calc_usage(gc_state* const this)
235{
236        this->total_space = 0;
237        this->used_space = 0;
238
239        gc_memory_pool* pool = this->from_space;
240        while(pool)
241        {
242                size_t size = gc_pool_size_total(pool);
243                size_t used = gc_pool_size_used(pool);
244                check(used <= size);
245                this->total_space += size;
246                this->used_space += used;
247
248                pool = pool->next;
249        }
250}
251
252#if _DEBUG
253        bool gc_state_roots_match(gc_state* const this)
254        {
255                gc_memory_pool* pool = this->to_space;
256                while(pool)
257                {
258                        size_t size = 0;
259                        gc_pool_object_iterator it = begin(pool);
260                        gc_pool_object_iterator end = end(pool);
261                        for(;it != end; ++it)
262                        {
263                                gc_object_header* object = *it;
264                                size += object->size;
265
266                                gcpointer_base* ptr = object->root_chain;
267                                while(ptr)
268                                {
269                                        check(get_object_ptr(ptr->m_ptr) == object);
270                                        ptr = ptr->m_next;
271                                }
272                        }
273
274                        check(size + gc_pool_size_used(pool) == gc_pool_size_total(pool));
275
276                        pool = pool->next;
277                }
278
279                return true;
280        }
281
282        bool gc_state_no_from_space_ref(gc_state* const this)
283        {
284                gc_memory_pool* pool = this->to_space;
285                while(pool)
286                {
287                        void** potential_ref = (void**)pool->m_start;
288                        while(potential_ref < (void**)pool->m_free)
289                        {
290                                check(!gc_is_in_heap(this, *potential_ref));
291                                potential_ref++;
292                        }
293
294                        pool = pool->next;
295                }
296
297                return true;
298        }
299#endif
Note: See TracBrowser for help on using the repository browser.