]> gitweb.factorcode.org Git - factor.git/blob - vm/code_heap.cpp
Merge branch 'master' of git://factorcode.org/git/factor
[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)
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 void factor_vm::primitive_modify_code_heap()
77 {
78         gc_root<array> alist(dpop(),this);
79
80         cell count = array_capacity(alist.untagged());
81
82         if(count == 0)
83                 return;
84
85         cell i;
86         for(i = 0; i < count; i++)
87         {
88                 gc_root<array> pair(array_nth(alist.untagged(),i),this);
89
90                 gc_root<word> word(array_nth(pair.untagged(),0),this);
91                 gc_root<object> data(array_nth(pair.untagged(),1),this);
92
93                 switch(data.type())
94                 {
95                 case QUOTATION_TYPE:
96                         jit_compile_word(word.value(),data.value(),false);
97                         break;
98                 case ARRAY_TYPE:
99                         {
100                                 array *compiled_data = data.as<array>().untagged();
101                                 cell owner = array_nth(compiled_data,0);
102                                 cell literals = array_nth(compiled_data,1);
103                                 cell relocation = array_nth(compiled_data,2);
104                                 cell labels = array_nth(compiled_data,3);
105                                 cell code = array_nth(compiled_data,4);
106
107                                 code_block *compiled = add_code_block(
108                                         WORD_TYPE,
109                                         code,
110                                         labels,
111                                         owner,
112                                         relocation,
113                                         literals);
114
115                                 word->code = compiled;
116                         }
117                         break;
118                 default:
119                         critical_error("Expected a quotation or an array",data.value());
120                         break;
121                 }
122
123                 update_word_xt(word.value());
124         }
125
126         update_code_heap_words();
127 }
128
129 /* Push the free space and total size of the code heap */
130 void factor_vm::primitive_code_room()
131 {
132         cell used, total_free, max_free;
133         code->heap_usage(&used,&total_free,&max_free);
134         dpush(tag_fixnum(code->seg->size / 1024));
135         dpush(tag_fixnum(used / 1024));
136         dpush(tag_fixnum(total_free / 1024));
137         dpush(tag_fixnum(max_free / 1024));
138 }
139
140 code_block *code_heap::forward_code_block(code_block *compiled)
141 {
142         return (code_block *)forwarding[compiled];
143 }
144
145 struct callframe_forwarder {
146         factor_vm *parent;
147
148         explicit callframe_forwarder(factor_vm *parent_) : parent(parent_) {}
149
150         void operator()(stack_frame *frame)
151         {
152                 cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
153
154                 code_block *forwarded = parent->code->forward_code_block(parent->frame_code(frame));
155                 frame->xt = forwarded->xt();
156
157                 FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
158         }
159 };
160
161 void factor_vm::forward_object_xts()
162 {
163         begin_scan();
164
165         cell obj;
166
167         while(to_boolean(obj = next_object()))
168         {
169                 switch(tagged<object>(obj).type())
170                 {
171                 case WORD_TYPE:
172                         {
173                                 word *w = untag<word>(obj);
174
175                                 if(w->code)
176                                         w->code = code->forward_code_block(w->code);
177                                 if(w->profiling)
178                                         w->profiling = code->forward_code_block(w->profiling);
179
180                                 update_word_xt(obj);
181                         }
182                         break;
183                 case QUOTATION_TYPE:
184                         {
185                                 quotation *quot = untag<quotation>(obj);
186
187                                 if(quot->code)
188                                 {
189                                         quot->code = code->forward_code_block(quot->code);
190                                         set_quot_xt(quot,quot->code);
191                                 }
192                         }
193                         break;
194                 case CALLSTACK_TYPE:
195                         {
196                                 callstack *stack = untag<callstack>(obj);
197                                 callframe_forwarder forwarder(this);
198                                 iterate_callstack_object(stack,forwarder);
199                         }
200                         break;
201                 default:
202                         break;
203                 }
204         }
205
206         end_scan();
207 }
208
209 void factor_vm::forward_context_xts()
210 {
211         callframe_forwarder forwarder(this);
212         iterate_active_frames(forwarder);
213 }
214
215 struct callback_forwarder {
216         code_heap *code;
217         callback_heap *callbacks;
218
219         callback_forwarder(code_heap *code_, callback_heap *callbacks_) :
220                 code(code_), callbacks(callbacks_) {}
221
222         void operator()(callback *stub)
223         {
224                 stub->compiled = code->forward_code_block(stub->compiled);
225                 callbacks->update(stub);
226         }
227 };
228
229 void factor_vm::forward_callback_xts()
230 {
231         callback_forwarder forwarder(code,callbacks);
232         callbacks->iterate(forwarder);
233 }
234
235 /* Move all free space to the end of the code heap. Live blocks must be marked
236 on entry to this function. XTs in code blocks must be updated after this
237 function returns. */
238 void factor_vm::compact_code_heap(bool trace_contexts_p)
239 {
240         code->compact_heap();
241         forward_object_xts();
242         if(trace_contexts_p)
243         {
244                 forward_context_xts();
245                 forward_callback_xts();
246         }
247 }
248
249 struct stack_trace_stripper {
250         explicit stack_trace_stripper() {}
251
252         void operator()(code_block *compiled)
253         {
254                 compiled->owner = false_object;
255         }
256 };
257
258 void factor_vm::primitive_strip_stack_traces()
259 {
260         stack_trace_stripper stripper;
261         iterate_code_heap(stripper);
262 }
263
264 }