]> 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 *parent_) :
7         copying_collector<tenured_space,full_policy>(
8                 parent_,
9                 &parent_->gc_stats.full_stats,
10                 parent_->data->tenured,
11                 full_policy(parent_)) {}
12
13 struct stack_frame_marker {
14         factor_vm *parent;
15         full_collector *collector;
16
17         explicit stack_frame_marker(full_collector *collector_) :
18                 parent(collector_->parent), collector(collector_) {}
19
20         void operator()(stack_frame *frame)
21         {
22                 collector->mark_code_block(parent->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         parent->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                         parent->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         parent->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->parent,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 *parent;
111
112         big_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
113
114         void operator()(heap_block *block)
115         {
116                 parent->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 *parent;
124
125         small_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
126
127         void operator()(heap_block *block)
128         {
129                 parent->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         code->state->clear_mark_bits();
138
139         collector.trace_roots();
140         if(trace_contexts_p)
141         {
142                 collector.trace_contexts();
143                 collector.mark_active_blocks();
144                 collector.trace_callbacks();
145         }
146
147         collector.cheneys_algorithm();
148
149         reset_generation(data->aging);
150         nursery.here = nursery.start;
151 }
152
153 void factor_vm::collect_growing_heap(cell requested_bytes,
154         bool trace_contexts_p,
155         bool compact_code_heap_p)
156 {
157         /* Grow the data heap and copy all live objects to the new heap. */
158         data_heap *old = data;
159         set_data_heap(data->grow(requested_bytes));
160         collect_full_impl(trace_contexts_p);
161         delete old;
162
163         if(compact_code_heap_p)
164         {
165                 compact_code_heap(trace_contexts_p);
166                 big_code_heap_updater updater(this);
167                 iterate_code_heap(updater);
168         }
169         else
170         {
171                 big_code_heap_updater updater(this);
172                 code->free_unmarked(updater);
173         }
174
175         code->clear_remembered_set();
176 }
177
178 void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
179 {
180         /* Copy all live objects to the tenured semispace. */
181         std::swap(data->tenured,data->tenured_semispace);
182         reset_generation(data->tenured);
183         collect_full_impl(trace_contexts_p);
184
185         if(compact_code_heap_p)
186         {
187                 compact_code_heap(trace_contexts_p);
188                 big_code_heap_updater updater(this);
189                 iterate_code_heap(updater);
190         }
191         else
192         {
193                 small_code_heap_updater updater(this);
194                 code->free_unmarked(updater);
195         }
196
197         code->clear_remembered_set();
198 }
199
200 }