]> gitweb.factorcode.org Git - factor.git/blob - vm/full_collector.cpp
Merge branch 'master' of git://factorcode.org/git/factor into no_literal_table
[factor.git] / vm / full_collector.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 inline static code_block_visitor<code_workhorse> make_code_visitor(factor_vm *parent)
7 {
8         return code_block_visitor<code_workhorse>(parent,code_workhorse(parent));
9 }
10
11 full_collector::full_collector(factor_vm *parent_) :
12         collector<tenured_space,full_policy>(
13                 parent_,
14                 parent_->data->tenured,
15                 full_policy(parent_)),
16         code_visitor(make_code_visitor(parent_)) {}
17
18 void full_collector::trace_code_block(code_block *compiled)
19 {
20         data_visitor.visit_code_block_objects(compiled);
21         data_visitor.visit_embedded_literals(compiled);
22         code_visitor.visit_embedded_code_pointers(compiled);
23 }
24
25 void full_collector::trace_context_code_blocks()
26 {
27         code_visitor.visit_context_code_blocks();
28 }
29
30 void full_collector::trace_callback_code_blocks()
31 {
32         code_visitor.visit_callback_code_blocks();
33 }
34
35 void full_collector::trace_object_code_block(object *obj)
36 {
37         code_visitor.visit_object_code_block(obj);
38 }
39
40 /* After a sweep, invalidate any code heap roots which are not marked,
41 so that if a block makes a tail call to a generic word, and the PIC
42 compiler triggers a GC, and the caller block gets gets GCd as a result,
43 the PIC code won't try to overwrite the call site */
44 void factor_vm::update_code_roots_for_sweep()
45 {
46         std::vector<code_root *>::const_iterator iter = code_roots.begin();
47         std::vector<code_root *>::const_iterator end = code_roots.end();
48
49         mark_bits<code_block> *state = &code->allocator->state;
50
51         for(; iter < end; iter++)
52         {
53                 code_root *root = *iter;
54                 code_block *block = (code_block *)(root->value & -block_granularity);
55                 if(root->valid && !state->marked_p(block))
56                         root->valid = false;
57         }
58 }
59
60 /* After a compaction, invalidate any code heap roots which are not
61 marked as above, and also slide the valid roots up so that call sites
62 can be updated correctly. */
63 void factor_vm::update_code_roots_for_compaction()
64 {
65         std::vector<code_root *>::const_iterator iter = code_roots.begin();
66         std::vector<code_root *>::const_iterator end = code_roots.end();
67
68         mark_bits<code_block> *state = &code->allocator->state;
69
70         for(; iter < end; iter++)
71         {
72                 code_root *root = *iter;
73                 code_block *block = (code_block *)(root->value & -block_granularity);
74
75                 /* Offset of return address within 16-byte allocation line */
76                 cell offset = root->value - (cell)block;
77
78                 if(root->valid && state->marked_p((code_block *)root->value))
79                 {
80                         block = state->forward_block(block);
81                         root->value = (cell)block + offset;
82                 }
83                 else
84                         root->valid = false;
85         }
86 }
87
88 void factor_vm::collect_mark_impl(bool trace_contexts_p)
89 {
90         full_collector collector(this);
91
92         mark_stack.clear();
93
94         code->clear_mark_bits();
95         data->tenured->clear_mark_bits();
96
97         collector.trace_roots();
98         if(trace_contexts_p)
99         {
100                 collector.trace_contexts();
101                 collector.trace_context_code_blocks();
102                 collector.trace_callback_code_blocks();
103         }
104
105         while(!mark_stack.empty())
106         {
107                 cell ptr = mark_stack.back();
108                 mark_stack.pop_back();
109
110                 if(ptr & 1)
111                 {
112                         code_block *compiled = (code_block *)(ptr - 1);
113                         collector.trace_code_block(compiled);
114                 }
115                 else
116                 {
117                         object *obj = (object *)ptr;
118                         collector.trace_object(obj);
119                         collector.trace_object_code_block(obj);
120                 }
121         }
122
123         data->reset_generation(data->tenured);
124         data->reset_generation(data->aging);
125         data->reset_generation(&nursery);
126         code->clear_remembered_set();
127 }
128
129 void factor_vm::collect_sweep_impl()
130 {
131         current_gc->event->started_data_sweep();
132         data->tenured->sweep();
133         current_gc->event->ended_data_sweep();
134
135         update_code_roots_for_sweep();
136
137         current_gc->event->started_code_sweep();
138         code->allocator->sweep();
139         current_gc->event->ended_code_sweep();
140 }
141
142 void factor_vm::collect_full(bool trace_contexts_p)
143 {
144         collect_mark_impl(trace_contexts_p);
145         collect_sweep_impl();
146         if(data->low_memory_p())
147         {
148                 current_gc->op = collect_compact_op;
149                 current_gc->event->op = collect_compact_op;
150                 collect_compact_impl(trace_contexts_p);
151         }
152         flush_icache(code->seg->start,code->seg->size);
153 }
154
155 void factor_vm::collect_compact(bool trace_contexts_p)
156 {
157         collect_mark_impl(trace_contexts_p);
158         collect_compact_impl(trace_contexts_p);
159         flush_icache(code->seg->start,code->seg->size);
160 }
161
162 void factor_vm::collect_growing_heap(cell requested_bytes, bool trace_contexts_p)
163 {
164         /* Grow the data heap and copy all live objects to the new heap. */
165         data_heap *old = data;
166         set_data_heap(data->grow(requested_bytes));
167         collect_mark_impl(trace_contexts_p);
168         collect_compact_code_impl(trace_contexts_p);
169         flush_icache(code->seg->start,code->seg->size);
170         delete old;
171 }
172
173 }