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