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
RevLine 
[6be0cf9]1#include "state.h"
[a2b2761]2
[73abe95]3#include <stdlib.hfa>
[385c130]4
5//general purpouse includes
6#include "tools.h"
7
8//platform abstraction includes
9#include "allocate-pool.h"
10
11//gc internal includes
[4ef8fb3]12#include "collector.h"
[385c130]13#include "globals.h"
14#include "memory_pool.h"
15#include "object_header.h"
[4ef8fb3]16#include "tools/worklist.h"
[d67a9a1]17
[385c130]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
[46f1d20]23#ifndef NDEBUG
[385c130]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
[1b5c81ed]28static gc_state s;
29
[385c130]30gc_state* gc_get_state()
31{
[df4aea7]32 if(!s.is_initialized) ctor(&s);
[385c130]33 return &s;
34}
35
[df4aea7]36void ctor(gc_state *const this)
[385c130]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;
[df4aea7]43 ctor(&this->pools_table);
[385c130]44
45 gc_allocate_pool(this);
46
47 this->is_initialized = true;
48}
[d67a9a1]49
[16cfd8c]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)
[df4aea7]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
[16cfd8c]66bool gc_is_in_to_space(const gc_state* const this, const void* const address)
[df4aea7]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{
[76af36f]78 volatile int stage = 0;
[df4aea7]79 intptr_t target = ((intptr_t)member);
80 if(!gc_is_in_heap(state, member)) return NULL;
[76af36f]81 stage++;
[df4aea7]82
83 gc_memory_pool* pool = gc_pool_of(member);
[76af36f]84 stage++;
[df4aea7]85 gc_pool_object_iterator it = gc_pool_iterator_for(pool, member);
[76af36f]86 stage++;
[16cfd8c]87 gc_pool_object_iterator end = end(pool);
[76af36f]88 stage++;
[df4aea7]89
90 while(it != end)
91 {
92 gc_object_header* object = *it;
[76af36f]93 check(object);
94 check( is_valid(object) );
[df4aea7]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 }
[76af36f]103 stage++;
[df4aea7]104 ++it;
105 }
106
[46f1d20]107 checkf( (int) 0, "is_in_heap() and iterator_for() return inconsistent data");
[df4aea7]108 abort();
109 return NULL;
110}
111
[16cfd8c]112void* gc_try_allocate(gc_state* const this, size_t size)
[385c130]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
[16cfd8c]127void gc_allocate_pool(gc_state *const this)
[385c130]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));
[24bc651]133 this->to_space = (gc_memory_pool*)(pal_allocPool(POOL_SIZE_BYTES, 1));
[385c130]134
[24bc651]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 };
[385c130]137
138 this->total_space += gc_pool_size_used(this->from_space);
139
[df4aea7]140 push_back(&this->pools_table, this->from_space);
141 push_back(&this->pools_table, this->to_space);
[385c130]142}
143
[16cfd8c]144void gc_collect(gc_state* const this)
[385c130]145{
146 // DEBUG("collecting");
147 // DEBUG("previous usage " << this->used_space << " / " << this->total_space);
148
149 worklist_t worklist;
[df4aea7]150 ctor(&worklist);
[385c130]151 gc_state_sweep_roots(this, &worklist);
152
153 while(!empty(&worklist))
154 {
[df4aea7]155 intptr_t* ref = back(&worklist);
[385c130]156 pop_back(&worklist);
[df4aea7]157 gc_process_reference((void**)ref, &worklist);
[385c130]158 }
[df4aea7]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
[16cfd8c]167 if(gc_needs_collect(this)) gc_allocate_pool(this);
[385c130]168
169 // DEBUG("done");
[df4aea7]170 dtor(&worklist);
[385c130]171}
[df4aea7]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
[46f1d20]186 #ifndef NDEBUG
[df4aea7]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
[46f1d20]261#ifndef NDEBUG
[df4aea7]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
[46f1d20]275 gcpointer_t* ptr = object->root_chain;
[df4aea7]276 while(ptr)
277 {
[46f1d20]278 check(gc_get_object_ptr( (void*)ptr->ptr ) == object);
279 ptr = ptr->next;
[df4aea7]280 }
281 }
282
[76af36f]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));
[df4aea7]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 {
[46f1d20]300 void** potential_ref = (void**)pool->start_p;
301 while(potential_ref < (void**)pool->free_p)
[df4aea7]302 {
[16cfd8c]303 check(!gc_is_in_heap(this, *potential_ref));
[df4aea7]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.