source: src/examples/gc_no_raii/src/internal/state.c @ bee4283

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

fixed several compilation errors

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