]> gitweb.factorcode.org Git - factor.git/blob - vm/code_heap.cpp
Dev checkpoint
[factor.git] / vm / code_heap.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Allocate a code heap during startup */
7 void factorvm::init_code_heap(cell size)
8 {
9         new_heap(&code,size);
10 }
11
12
13 bool factorvm::in_code_heap_p(cell ptr)
14 {
15         return (ptr >= code.seg->start && ptr <= code.seg->end);
16 }
17
18 bool in_code_heap_p(cell ptr)
19 {
20         return vm->in_code_heap_p(ptr); // used by os specific signal handlers
21 }
22
23 /* Compile a word definition with the non-optimizing compiler. Allocates memory */
24 void factorvm::jit_compile_word(cell word_, cell def_, bool relocate)
25 {
26         gc_root<word> word(word_,this);
27         gc_root<quotation> def(def_,this);
28
29         jit_compile(def.value(),relocate);
30
31         word->code = def->code;
32
33         if(word->pic_def != F) jit_compile(word->pic_def,relocate);
34         if(word->pic_tail_def != F) jit_compile(word->pic_tail_def,relocate);
35 }
36
37
38 /* Apply a function to every code block */
39 void factorvm::iterate_code_heap(code_heap_iterator iter)
40 {
41         heap_block *scan = first_block(&code);
42
43         while(scan)
44         {
45                 if(scan->status != B_FREE)
46                         iter((code_block *)scan,this);
47                 scan = next_block(&code,scan);
48         }
49 }
50
51
52 /* Copy literals referenced from all code blocks to newspace. Only for
53 aging and nursery collections */
54 void factorvm::copy_code_heap_roots()
55 {
56         iterate_code_heap(factor::copy_literal_references);
57 }
58
59
60 /* Update pointers to words referenced from all code blocks. Only after
61 defining a new word. */
62 void factorvm::update_code_heap_words()
63 {
64         iterate_code_heap(factor::update_word_references);
65 }
66
67
68 inline void factorvm::vmprim_modify_code_heap()
69 {
70         gc_root<array> alist(dpop(),this);
71
72         cell count = array_capacity(alist.untagged());
73
74         if(count == 0)
75                 return;
76
77         cell i;
78         for(i = 0; i < count; i++)
79         {
80                 gc_root<array> pair(array_nth(alist.untagged(),i),this);
81
82                 gc_root<word> word(array_nth(pair.untagged(),0),this);
83                 gc_root<object> data(array_nth(pair.untagged(),1),this);
84
85                 switch(data.type())
86                 {
87                 case QUOTATION_TYPE:
88                         jit_compile_word(word.value(),data.value(),false);
89                         break;
90                 case ARRAY_TYPE:
91                         {
92                                 array *compiled_data = data.as<array>().untagged();
93                                 cell literals = array_nth(compiled_data,0);
94                                 cell relocation = array_nth(compiled_data,1);
95                                 cell labels = array_nth(compiled_data,2);
96                                 cell code = array_nth(compiled_data,3);
97
98                                 code_block *compiled = add_code_block(
99                                         WORD_TYPE,
100                                         code,
101                                         labels,
102                                         relocation,
103                                         literals);
104
105                                 word->code = compiled;
106                         }
107                         break;
108                 default:
109                         critical_error("Expected a quotation or an array",data.value());
110                         break;
111                 }
112
113                 update_word_xt(word.value());
114         }
115
116         update_code_heap_words();
117 }
118
119 PRIMITIVE(modify_code_heap)
120 {
121         PRIMITIVE_GETVM()->vmprim_modify_code_heap();
122 }
123
124 /* Push the free space and total size of the code heap */
125 inline void factorvm::vmprim_code_room()
126 {
127         cell used, total_free, max_free;
128         heap_usage(&code,&used,&total_free,&max_free);
129         dpush(tag_fixnum(code.seg->size / 1024));
130         dpush(tag_fixnum(used / 1024));
131         dpush(tag_fixnum(total_free / 1024));
132         dpush(tag_fixnum(max_free / 1024));
133 }
134
135 PRIMITIVE(code_room)
136 {
137         PRIMITIVE_GETVM()->vmprim_code_room();
138 }
139
140
141 code_block *factorvm::forward_xt(code_block *compiled)
142 {
143         return (code_block *)forwarding[compiled];
144 }
145
146
147 void factorvm::forward_frame_xt(stack_frame *frame)
148 {
149         cell offset = (cell)FRAME_RETURN_ADDRESS(frame) - (cell)frame_code(frame);
150         code_block *forwarded = forward_xt(frame_code(frame));
151         frame->xt = forwarded->xt();
152         FRAME_RETURN_ADDRESS(frame) = (void *)((cell)forwarded + offset);
153 }
154
155 void forward_frame_xt(stack_frame *frame,factorvm *myvm)
156 {
157         return myvm->forward_frame_xt(frame);
158 }
159
160 void factorvm::forward_object_xts()
161 {
162         begin_scan();
163
164         cell obj;
165
166         while((obj = next_object()) != F)
167         {
168                 switch(tagged<object>(obj).type())
169                 {
170                 case WORD_TYPE:
171                         {
172                                 word *w = untag<word>(obj);
173
174                                 if(w->code)
175                                         w->code = forward_xt(w->code);
176                                 if(w->profiling)
177                                         w->profiling = forward_xt(w->profiling);
178                         }
179                         break;
180                 case QUOTATION_TYPE:
181                         {
182                                 quotation *quot = untag<quotation>(obj);
183
184                                 if(quot->code)
185                                         quot->code = forward_xt(quot->code);
186                         }
187                         break;
188                 case CALLSTACK_TYPE:
189                         {
190                                 callstack *stack = untag<callstack>(obj);
191                                 iterate_callstack_object(stack,factor::forward_frame_xt);
192                         }
193                         break;
194                 default:
195                         break;
196                 }
197         }
198
199         end_scan();
200 }
201
202
203 /* Set the XT fields now that the heap has been compacted */
204 void factorvm::fixup_object_xts()
205 {
206         begin_scan();
207
208         cell obj;
209
210         while((obj = next_object()) != F)
211         {
212                 switch(tagged<object>(obj).type())
213                 {
214                 case WORD_TYPE:
215                         update_word_xt(obj);
216                         break;
217                 case QUOTATION_TYPE:
218                         {
219                                 quotation *quot = untag<quotation>(obj);
220                                 if(quot->code)
221                                         set_quot_xt(quot,quot->code);
222                                 break;
223                         }
224                 default:
225                         break;
226                 }
227         }
228
229         end_scan();
230 }
231
232
233 /* Move all free space to the end of the code heap. This is not very efficient,
234 since it makes several passes over the code and data heaps, but we only ever
235 do this before saving a deployed image and exiting, so performaance is not
236 critical here */
237 void factorvm::compact_code_heap()
238 {
239         /* Free all unreachable code blocks */
240         gc();
241
242         /* Figure out where the code heap blocks are going to end up */
243         cell size = compute_heap_forwarding(&code, forwarding);
244
245         /* Update word and quotation code pointers */
246         forward_object_xts();
247
248         /* Actually perform the compaction */
249         compact_heap(&code,forwarding);
250
251         /* Update word and quotation XTs */
252         fixup_object_xts();
253
254         /* Now update the free list; there will be a single free block at
255         the end */
256         build_free_list(&code,size);
257 }
258
259 }