source: examples/gc_no_raii/src/internal/state.c@ 6f096d2

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 6f096d2 was 73abe95, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Replace extension-less headers with .hfa

  • Property mode set to 100644
File size: 6.6 KB
Line 
1#include "state.h"
2
3#include <stdlib.hfa>
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#ifndef NDEBUG
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 volatile int stage = 0;
79 intptr_t target = ((intptr_t)member);
80 if(!gc_is_in_heap(state, member)) return NULL;
81 stage++;
82
83 gc_memory_pool* pool = gc_pool_of(member);
84 stage++;
85 gc_pool_object_iterator it = gc_pool_iterator_for(pool, member);
86 stage++;
87 gc_pool_object_iterator end = end(pool);
88 stage++;
89
90 while(it != end)
91 {
92 gc_object_header* object = *it;
93 check(object);
94 check( is_valid(object) );
95 {
96 intptr_t start = ((intptr_t)object);
97 intptr_t end = ((intptr_t)start + object->size);
98 if(start < target && end > target)
99 {
100 return object;
101 }
102 }
103 stage++;
104 ++it;
105 }
106
107 checkf( (int) 0, "is_in_heap() and iterator_for() return inconsistent data");
108 abort();
109 return NULL;
110}
111
112void* gc_try_allocate(gc_state* const this, size_t size)
113{
114 gc_memory_pool* pool = this->from_space;
115 while(pool != (gc_memory_pool*)0)
116 {
117 if(gc_pool_size_left(pool) > size)
118 {
119 return gc_pool_allocate(pool, size, true);
120 }
121 pool = pool->next;
122 }
123
124 return (void*)0;
125}
126
127void gc_allocate_pool(gc_state *const this)
128{
129 gc_memory_pool* old_from_space = this->from_space;
130 gc_memory_pool* old_to_space = this->to_space;
131
132 this->from_space = (gc_memory_pool*)(pal_allocPool(POOL_SIZE_BYTES, 1));
133 this->to_space = (gc_memory_pool*)(pal_allocPool(POOL_SIZE_BYTES, 1));
134
135 this->from_space{ POOL_SIZE_BYTES, old_from_space, this->to_space, this->from_code };
136 this->to_space { POOL_SIZE_BYTES, old_to_space, this->from_space, (~this->from_code) & 0x01 };
137
138 this->total_space += gc_pool_size_used(this->from_space);
139
140 push_back(&this->pools_table, this->from_space);
141 push_back(&this->pools_table, this->to_space);
142}
143
144void gc_collect(gc_state* const this)
145{
146 // DEBUG("collecting");
147 // DEBUG("previous usage " << this->used_space << " / " << this->total_space);
148
149 worklist_t worklist;
150 ctor(&worklist);
151 gc_state_sweep_roots(this, &worklist);
152
153 while(!empty(&worklist))
154 {
155 intptr_t* ref = back(&worklist);
156 pop_back(&worklist);
157 gc_process_reference((void**)ref, &worklist);
158 }
159
160 check(gc_state_roots_match(this));
161 check(gc_state_no_from_space_ref(this));
162
163 gc_state_swap(this);
164
165 gc_state_calc_usage(this);
166
167 if(gc_needs_collect(this)) gc_allocate_pool(this);
168
169 // DEBUG("done");
170 dtor(&worklist);
171}
172
173void gc_state_swap(gc_state* const this)
174{
175 swap(&this->from_space, &this->to_space);
176
177 gc_memory_pool* pool = this->to_space;
178 while(pool)
179 {
180 gc_reset_pool(pool);
181 pool = pool->next;
182 }
183
184 this->from_code = (~this->from_code) & 0x01;
185
186 #ifndef NDEBUG
187 {
188 gc_memory_pool* pool = this->from_space;
189 while(pool)
190 {
191 check(gc_pool_is_from_space(pool));
192 pool = pool->next;
193 }
194
195 pool = this->to_space;
196 while(pool)
197 {
198 check(!gc_pool_is_from_space(pool));
199 pool = pool->next;
200 }
201 }
202 #endif
203}
204
205void gc_state_sweep_roots(gc_state* const this, worklist_t* worklist)
206{
207 gc_memory_pool* pool = this->from_space;
208 while(pool)
209 {
210 gc_pool_object_iterator it = begin(pool);
211 gc_pool_object_iterator end = end(pool);
212 for(;it != end; ++it)
213 {
214 gc_object_header* object = *it;
215 if(!object->root_chain) continue;
216
217 gc_copy_object(object);
218
219 gc_scan_object(object->forward, worklist);
220 }
221
222 pool = pool->next;
223 }
224}
225
226void gc_state_clear(gc_state* const this)
227{
228 gc_memory_pool* pool = this->from_space;
229 while(pool)
230 {
231 gc_reset_pool(pool);
232 pool = pool->next;
233 }
234
235 pool = this->to_space;
236 while(pool)
237 {
238 gc_reset_pool(pool);
239 pool = pool->next;
240 }
241}
242
243void gc_state_calc_usage(gc_state* const this)
244{
245 this->total_space = 0;
246 this->used_space = 0;
247
248 gc_memory_pool* pool = this->from_space;
249 while(pool)
250 {
251 size_t size = gc_pool_size_total(pool);
252 size_t used = gc_pool_size_used(pool);
253 check(used <= size);
254 this->total_space += size;
255 this->used_space += used;
256
257 pool = pool->next;
258 }
259}
260
261#ifndef NDEBUG
262 bool gc_state_roots_match(gc_state* const this)
263 {
264 gc_memory_pool* pool = this->to_space;
265 while(pool)
266 {
267 size_t size = 0;
268 gc_pool_object_iterator it = begin(pool);
269 gc_pool_object_iterator end = end(pool);
270 for(;it != end; ++it)
271 {
272 gc_object_header* object = *it;
273 size += object->size;
274
275 gcpointer_t* ptr = object->root_chain;
276 while(ptr)
277 {
278 check(gc_get_object_ptr( (void*)ptr->ptr ) == object);
279 ptr = ptr->next;
280 }
281 }
282
283 checkf(size + gc_pool_size_left(pool) == gc_pool_size_total(pool),
284 (const char*)"expected %lu + %lu == %lu\n",
285 (size_t)size,
286 (size_t)gc_pool_size_left(pool),
287 (size_t)gc_pool_size_total(pool));
288
289 pool = pool->next;
290 }
291
292 return true;
293 }
294
295 bool gc_state_no_from_space_ref(gc_state* const this)
296 {
297 gc_memory_pool* pool = this->to_space;
298 while(pool)
299 {
300 void** potential_ref = (void**)pool->start_p;
301 while(potential_ref < (void**)pool->free_p)
302 {
303 check(!gc_is_in_heap(this, *potential_ref));
304 potential_ref++;
305 }
306
307 pool = pool->next;
308 }
309
310 return true;
311 }
312#endif
Note: See TracBrowser for help on using the repository browser.