source: src/examples/gc_no_raii/src/internal/state.c@ 1b5c81ed

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 1b5c81ed was 1b5c81ed, checked in by Thierry Delisle <tdelisle@…>, 9 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.