source: src/examples/gc_no_raii/src/internal/state.c @ 16cfd8c

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 16cfd8c was 16cfd8c, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

1 error left

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