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