]> gitweb.factorcode.org Git - factor.git/blob - vm/code_heap.cpp
Moved PRIMITIVE and PRIMITIVE_FORWARDs to primitives.[ch]pp
[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 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 /* Push the free space and total size of the code heap */
110 void factor_vm::primitive_code_room()
111 {
112         cell used, total_free, max_free;
113         code->heap_usage(&used,&total_free,&max_free);
114         dpush(tag_fixnum(code->seg->size / 1024));
115         dpush(tag_fixnum(used / 1024));
116         dpush(tag_fixnum(total_free / 1024));
117         dpush(tag_fixnum(max_free / 1024));
118 }
119
120 code_block *factor_vm::forward_xt(code_block *compiled)
121 {
122         return (code_block *)forwarding[compiled];
123 }
124
125 void factor_vm::forward_frame_xt(stack_frame *frame)
126 {
127         cell offset = (cell)FRAME_RETURN_ADDRESS(frame) - (cell)frame_code(frame);
128         code_block *forwarded = forward_xt(frame_code(frame));
129         frame->xt = forwarded->xt();
130         FRAME_RETURN_ADDRESS(frame) = (void *)((cell)forwarded + offset);
131 }
132
133 void forward_frame_xt(stack_frame *frame,factor_vm *myvm)
134 {
135         return myvm->forward_frame_xt(frame);
136 }
137
138 void factor_vm::forward_object_xts()
139 {
140         begin_scan();
141
142         cell obj;
143
144         while((obj = next_object()) != F)
145         {
146                 switch(tagged<object>(obj).type())
147                 {
148                 case WORD_TYPE:
149                         {
150                                 word *w = untag<word>(obj);
151
152                                 if(w->code)
153                                         w->code = forward_xt(w->code);
154                                 if(w->profiling)
155                                         w->profiling = forward_xt(w->profiling);
156                         }
157                         break;
158                 case QUOTATION_TYPE:
159                         {
160                                 quotation *quot = untag<quotation>(obj);
161
162                                 if(quot->code)
163                                         quot->code = forward_xt(quot->code);
164                         }
165                         break;
166                 case CALLSTACK_TYPE:
167                         {
168                                 callstack *stack = untag<callstack>(obj);
169                                 iterate_callstack_object(stack,factor::forward_frame_xt);
170                         }
171                         break;
172                 default:
173                         break;
174                 }
175         }
176
177         end_scan();
178 }
179
180 /* Set the XT fields now that the heap has been compacted */
181 void factor_vm::fixup_object_xts()
182 {
183         begin_scan();
184
185         cell obj;
186
187         while((obj = next_object()) != F)
188         {
189                 switch(tagged<object>(obj).type())
190                 {
191                 case WORD_TYPE:
192                         update_word_xt(obj);
193                         break;
194                 case QUOTATION_TYPE:
195                         {
196                                 quotation *quot = untag<quotation>(obj);
197                                 if(quot->code)
198                                         set_quot_xt(quot,quot->code);
199                                 break;
200                         }
201                 default:
202                         break;
203                 }
204         }
205
206         end_scan();
207 }
208
209 /* Move all free space to the end of the code heap. This is not very efficient,
210 since it makes several passes over the code and data heaps, but we only ever
211 do this before saving a deployed image and exiting, so performaance is not
212 critical here */
213 void factor_vm::compact_code_heap()
214 {
215         /* Free all unreachable code blocks */
216         gc();
217
218         /* Figure out where the code heap blocks are going to end up */
219         cell size = code->compute_heap_forwarding(forwarding);
220
221         /* Update word and quotation code pointers */
222         forward_object_xts();
223
224         /* Actually perform the compaction */
225         code->compact_heap(forwarding);
226
227         /* Update word and quotation XTs */
228         fixup_object_xts();
229
230         /* Now update the free list; there will be a single free block at
231         the end */
232         code->build_free_list(size);
233 }
234
235 }