source: tests/zombies/gc_no_raii/src/internal/state.c @ 154672d

Last change on this file since 154672d was 87b9332, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Moved 'examples/' to 'tests/zombies/'.

  • 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.