]> gitweb.factorcode.org Git - factor.git/blob - vm/full_collector.cpp
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / vm / full_collector.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 full_collector::full_collector(factor_vm *myvm_) :
7         copying_collector<tenured_space,full_policy>(
8                 myvm_,
9                 &myvm_->gc_stats.full_stats,
10                 myvm_->data->tenured,
11                 full_policy(myvm_)) {}
12
13 struct stack_frame_marker {
14         factor_vm *myvm;
15         full_collector *collector;
16
17         explicit stack_frame_marker(full_collector *collector_) :
18                 myvm(collector_->myvm), collector(collector_) {}
19
20         void operator()(stack_frame *frame)
21         {
22                 collector->mark_code_block(myvm->frame_code(frame));
23         }
24 };
25
26 /* Mark code blocks executing in currently active stack frames. */
27 void full_collector::mark_active_blocks()
28 {
29         stack_frame_marker marker(this);
30         myvm->iterate_active_frames(marker);
31 }
32
33 void full_collector::mark_object_code_block(object *obj)
34 {
35         switch(obj->h.hi_tag())
36         {
37         case WORD_TYPE:
38                 {
39                         word *w = (word *)obj;
40                         if(w->code)
41                                 mark_code_block(w->code);
42                         if(w->profiling)
43                                 mark_code_block(w->profiling);
44                         break;
45                 }
46         case QUOTATION_TYPE:
47                 {
48                         quotation *q = (quotation *)obj;
49                         if(q->code)
50                                 mark_code_block(q->code);
51                         break;
52                 }
53         case CALLSTACK_TYPE:
54                 {
55                         callstack *stack = (callstack *)obj;
56                         stack_frame_marker marker(this);
57                         myvm->iterate_callstack_object(stack,marker);
58                         break;
59                 }
60         }
61 }
62
63 struct callback_tracer {
64         full_collector *collector;
65
66         callback_tracer(full_collector *collector_) : collector(collector_) {}
67         
68         void operator()(callback *stub)
69         {
70                 collector->mark_code_block(stub->compiled);
71         }
72 };
73
74 void full_collector::trace_callbacks()
75 {
76         callback_tracer tracer(this);
77         myvm->callbacks->iterate(tracer);
78 }
79
80 /* Trace all literals referenced from a code block. Only for aging and nursery collections */
81 void full_collector::trace_literal_references(code_block *compiled)
82 {
83         this->trace_handle(&compiled->owner);
84         this->trace_handle(&compiled->literals);
85         this->trace_handle(&compiled->relocation);
86 }
87
88 /* Mark all literals referenced from a word XT. Only for tenured
89 collections */
90 void full_collector::mark_code_block(code_block *compiled)
91 {
92         this->code->mark_block(compiled);
93         trace_literal_references(compiled);
94 }
95
96 void full_collector::cheneys_algorithm()
97 {
98         while(scan && scan < target->here)
99         {
100                 object *obj = (object *)scan;
101                 this->trace_slots(obj);
102                 this->mark_object_code_block(obj);
103                 scan = target->next_object_after(this->myvm,scan);
104         }
105 }
106
107 /* After growing the heap, we have to perform a full relocation to update
108 references to card and deck arrays. */
109 struct big_code_heap_updater {
110         factor_vm *myvm;
111
112         big_code_heap_updater(factor_vm *myvm_) : myvm(myvm_) {}
113
114         void operator()(heap_block *block)
115         {
116                 myvm->relocate_code_block((code_block *)block);
117         }
118 };
119
120 /* After a full GC that did not grow the heap, we have to update references
121 to literals and other words. */
122 struct small_code_heap_updater {
123         factor_vm *myvm;
124
125         small_code_heap_updater(factor_vm *myvm_) : myvm(myvm_) {}
126
127         void operator()(heap_block *block)
128         {
129                 myvm->update_code_block_for_full_gc((code_block *)block);
130         }
131 };
132
133 void factor_vm::collect_full_impl(bool trace_contexts_p)
134 {
135         full_collector collector(this);
136
137         collector.trace_roots();
138         if(trace_contexts_p)
139         {
140                 collector.trace_contexts();
141                 collector.mark_active_blocks();
142                 collector.trace_callbacks();
143         }
144
145         collector.cheneys_algorithm();
146
147         reset_generation(data->aging);
148         nursery.here = nursery.start;
149 }
150
151 /* In both cases, compact code heap before updating code blocks so that
152 XTs are correct after */
153
154 void factor_vm::big_code_heap_update()
155 {
156         big_code_heap_updater updater(this);
157         code->free_unmarked(updater);
158         code->clear_remembered_set();
159 }
160
161 void factor_vm::collect_growing_heap(cell requested_bytes,
162         bool trace_contexts_p,
163         bool compact_code_heap_p)
164 {
165         /* Grow the data heap and copy all live objects to the new heap. */
166         data_heap *old = data;
167         set_data_heap(data->grow(requested_bytes));
168         collect_full_impl(trace_contexts_p);
169         delete old;
170
171         if(compact_code_heap_p) compact_code_heap(trace_contexts_p);
172
173         big_code_heap_update();
174 }
175
176 void factor_vm::small_code_heap_update()
177 {
178         small_code_heap_updater updater(this);
179         code->free_unmarked(updater);
180         code->clear_remembered_set();
181 }
182
183 void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
184 {
185         /* Copy all live objects to the tenured semispace. */
186         std::swap(data->tenured,data->tenured_semispace);
187         reset_generation(data->tenured);
188         collect_full_impl(trace_contexts_p);
189
190         if(compact_code_heap_p)
191         {
192                 compact_code_heap(trace_contexts_p);
193                 big_code_heap_update();
194         }
195         else
196                 small_code_heap_update();
197 }
198
199 }