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

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

all implemented files compile

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