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