]> gitweb.factorcode.org Git - factor.git/blob - vm/code_heap.cpp
vm: working on making heap more generic
[factor.git] / vm / code_heap.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 code_heap::code_heap(bool secure_gc, cell size) :
7         heap<heap_block,code_heap_layout>(secure_gc,size,true) {}
8
9 void code_heap::write_barrier(code_block *compiled)
10 {
11         points_to_nursery.insert(compiled);
12         points_to_aging.insert(compiled);
13 }
14
15 void code_heap::clear_remembered_set()
16 {
17         points_to_nursery.clear();
18         points_to_aging.clear();
19 }
20
21 bool code_heap::needs_fixup_p(code_block *compiled)
22 {
23         return needs_fixup.count(compiled) > 0;
24 }
25
26 void code_heap::code_heap_free(code_block *compiled)
27 {
28         points_to_nursery.erase(compiled);
29         points_to_aging.erase(compiled);
30         needs_fixup.erase(compiled);
31         heap_free(compiled);
32 }
33
34 /* Allocate a code heap during startup */
35 void factor_vm::init_code_heap(cell size)
36 {
37         code = new code_heap(secure_gc,size);
38 }
39
40 bool factor_vm::in_code_heap_p(cell ptr)
41 {
42         return (ptr >= code->seg->start && ptr <= code->seg->end);
43 }
44
45 /* Compile a word definition with the non-optimizing compiler. Allocates memory */
46 void factor_vm::jit_compile_word(cell word_, cell def_, bool relocate)
47 {
48         gc_root<word> word(word_,this);
49         gc_root<quotation> def(def_,this);
50
51         jit_compile(def.value(),relocate);
52
53         word->code = def->code;
54
55         if(to_boolean(word->pic_def)) jit_compile(word->pic_def,relocate);
56         if(to_boolean(word->pic_tail_def)) jit_compile(word->pic_tail_def,relocate);
57 }
58
59 struct word_updater {
60         factor_vm *parent;
61
62         explicit word_updater(factor_vm *parent_) : parent(parent_) {}
63         void operator()(code_block *compiled, cell size)
64         {
65                 parent->update_word_references(compiled);
66         }
67 };
68
69 /* Update pointers to words referenced from all code blocks. Only after
70 defining a new word. */
71 void factor_vm::update_code_heap_words()
72 {
73         word_updater updater(this);
74         iterate_code_heap(updater);
75 }
76
77 /* After a full GC that did not grow the heap, we have to update references
78 to literals and other words. */
79 struct word_and_literal_code_heap_updater {
80         factor_vm *parent;
81
82         word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
83
84         void operator()(heap_block *block, cell size)
85         {
86                 parent->update_code_block_words_and_literals((code_block *)block);
87         }
88 };
89
90 void factor_vm::update_code_heap_words_and_literals()
91 {
92         word_and_literal_code_heap_updater updater(this);
93         code->sweep_heap(updater);
94 }
95
96 /* After growing the heap, we have to perform a full relocation to update
97 references to card and deck arrays. */
98 struct code_heap_relocator {
99         factor_vm *parent;
100
101         code_heap_relocator(factor_vm *parent_) : parent(parent_) {}
102
103         void operator()(code_block *block, cell size)
104         {
105                 parent->relocate_code_block(block);
106         }
107 };
108
109 void factor_vm::relocate_code_heap()
110 {
111         code_heap_relocator relocator(this);
112         code_heap_iterator<code_heap_relocator> iter(relocator);
113         code->sweep_heap(iter);
114 }
115
116 void factor_vm::primitive_modify_code_heap()
117 {
118         gc_root<array> alist(dpop(),this);
119
120         cell count = array_capacity(alist.untagged());
121
122         if(count == 0)
123                 return;
124
125         cell i;
126         for(i = 0; i < count; i++)
127         {
128                 gc_root<array> pair(array_nth(alist.untagged(),i),this);
129
130                 gc_root<word> word(array_nth(pair.untagged(),0),this);
131                 gc_root<object> data(array_nth(pair.untagged(),1),this);
132
133                 switch(data.type())
134                 {
135                 case QUOTATION_TYPE:
136                         jit_compile_word(word.value(),data.value(),false);
137                         break;
138                 case ARRAY_TYPE:
139                         {
140                                 array *compiled_data = data.as<array>().untagged();
141                                 cell owner = array_nth(compiled_data,0);
142                                 cell literals = array_nth(compiled_data,1);
143                                 cell relocation = array_nth(compiled_data,2);
144                                 cell labels = array_nth(compiled_data,3);
145                                 cell code = array_nth(compiled_data,4);
146
147                                 code_block *compiled = add_code_block(
148                                         code_block_optimized,
149                                         code,
150                                         labels,
151                                         owner,
152                                         relocation,
153                                         literals);
154
155                                 word->code = compiled;
156                         }
157                         break;
158                 default:
159                         critical_error("Expected a quotation or an array",data.value());
160                         break;
161                 }
162
163                 update_word_xt(word.value());
164         }
165
166         update_code_heap_words();
167 }
168
169 /* Push the free space and total size of the code heap */
170 void factor_vm::primitive_code_room()
171 {
172         cell used, total_free, max_free;
173         code->heap_usage(&used,&total_free,&max_free);
174         dpush(tag_fixnum(code->seg->size / 1024));
175         dpush(tag_fixnum(used / 1024));
176         dpush(tag_fixnum(total_free / 1024));
177         dpush(tag_fixnum(max_free / 1024));
178 }
179
180 code_block *code_heap::forward_code_block(code_block *compiled)
181 {
182         return (code_block *)state->forward_block(compiled);
183 }
184
185 struct callframe_forwarder {
186         factor_vm *parent;
187
188         explicit callframe_forwarder(factor_vm *parent_) : parent(parent_) {}
189
190         void operator()(stack_frame *frame)
191         {
192                 cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
193
194                 code_block *forwarded = parent->code->forward_code_block(parent->frame_code(frame));
195                 frame->xt = forwarded->xt();
196
197                 FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
198         }
199 };
200
201 void factor_vm::forward_object_xts()
202 {
203         begin_scan();
204
205         cell obj;
206
207         while(to_boolean(obj = next_object()))
208         {
209                 switch(tagged<object>(obj).type())
210                 {
211                 case WORD_TYPE:
212                         {
213                                 word *w = untag<word>(obj);
214
215                                 if(w->code)
216                                         w->code = code->forward_code_block(w->code);
217                                 if(w->profiling)
218                                         w->profiling = code->forward_code_block(w->profiling);
219
220                                 update_word_xt(obj);
221                         }
222                         break;
223                 case QUOTATION_TYPE:
224                         {
225                                 quotation *quot = untag<quotation>(obj);
226
227                                 if(quot->code)
228                                 {
229                                         quot->code = code->forward_code_block(quot->code);
230                                         set_quot_xt(quot,quot->code);
231                                 }
232                         }
233                         break;
234                 case CALLSTACK_TYPE:
235                         {
236                                 callstack *stack = untag<callstack>(obj);
237                                 callframe_forwarder forwarder(this);
238                                 iterate_callstack_object(stack,forwarder);
239                         }
240                         break;
241                 default:
242                         break;
243                 }
244         }
245
246         end_scan();
247 }
248
249 void factor_vm::forward_context_xts()
250 {
251         callframe_forwarder forwarder(this);
252         iterate_active_frames(forwarder);
253 }
254
255 struct callback_forwarder {
256         code_heap *code;
257         callback_heap *callbacks;
258
259         callback_forwarder(code_heap *code_, callback_heap *callbacks_) :
260                 code(code_), callbacks(callbacks_) {}
261
262         void operator()(callback *stub)
263         {
264                 stub->compiled = code->forward_code_block(stub->compiled);
265                 callbacks->update(stub);
266         }
267 };
268
269 void factor_vm::forward_callback_xts()
270 {
271         callback_forwarder forwarder(code,callbacks);
272         callbacks->iterate(forwarder);
273 }
274
275 /* Move all free space to the end of the code heap. Live blocks must be marked
276 on entry to this function. XTs in code blocks must be updated after this
277 function returns. */
278 void factor_vm::compact_code_heap(bool trace_contexts_p)
279 {
280         /* Figure out where blocks are going to go */
281         code->state->compute_forwarding();
282
283         /* Update references to the code heap from the data heap */
284         forward_object_xts();
285         if(trace_contexts_p)
286         {
287                 forward_context_xts();
288                 forward_callback_xts();
289         }
290
291         /* Move code blocks and update references amongst them (this requires
292         that the data heap is up to date since relocation looks up object XTs) */
293         code_heap_relocator relocator(this);
294         code_heap_iterator<code_heap_relocator> iter(relocator);
295         code->compact_heap(iter);
296 }
297
298 struct stack_trace_stripper {
299         explicit stack_trace_stripper() {}
300
301         void operator()(code_block *compiled, cell size)
302         {
303                 compiled->owner = false_object;
304         }
305 };
306
307 void factor_vm::primitive_strip_stack_traces()
308 {
309         stack_trace_stripper stripper;
310         iterate_code_heap(stripper);
311 }
312
313 }