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