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