6 code_heap::code_heap(cell size)
8 if(size > (1L << (sizeof(cell) * 8 - 6))) fatal_error("Heap too large",size);
9 seg = new segment(align_page(size),true);
10 if(!seg) fatal_error("Out of memory in heap allocator",size);
11 allocator = new free_list_allocator<heap_block>(seg->start,size);
14 code_heap::~code_heap()
22 void code_heap::write_barrier(code_block *compiled)
24 points_to_nursery.insert(compiled);
25 points_to_aging.insert(compiled);
28 void code_heap::clear_remembered_set()
30 points_to_nursery.clear();
31 points_to_aging.clear();
34 bool code_heap::needs_fixup_p(code_block *compiled)
36 return needs_fixup.count(compiled) > 0;
39 bool code_heap::marked_p(heap_block *compiled)
41 return allocator->state.marked_p(compiled);
44 void code_heap::set_marked_p(code_block *compiled)
46 allocator->state.set_marked_p(compiled);
49 void code_heap::clear_mark_bits()
51 allocator->state.clear_mark_bits();
54 void code_heap::code_heap_free(code_block *compiled)
56 points_to_nursery.erase(compiled);
57 points_to_aging.erase(compiled);
58 needs_fixup.erase(compiled);
59 allocator->free(compiled);
62 /* Allocate a code heap during startup */
63 void factor_vm::init_code_heap(cell size)
65 code = new code_heap(size);
68 bool factor_vm::in_code_heap_p(cell ptr)
70 return (ptr >= code->seg->start && ptr <= code->seg->end);
73 /* Compile a word definition with the non-optimizing compiler. Allocates memory */
74 void factor_vm::jit_compile_word(cell word_, cell def_, bool relocate)
76 gc_root<word> word(word_,this);
77 gc_root<quotation> def(def_,this);
79 jit_compile(def.value(),relocate);
81 word->code = def->code;
83 if(to_boolean(word->pic_def)) jit_compile(word->pic_def,relocate);
84 if(to_boolean(word->pic_tail_def)) jit_compile(word->pic_tail_def,relocate);
90 explicit word_updater(factor_vm *parent_) : parent(parent_) {}
91 void operator()(code_block *compiled, cell size)
93 parent->update_word_references(compiled);
97 /* Update pointers to words referenced from all code blocks. Only after
98 defining a new word. */
99 void factor_vm::update_code_heap_words()
101 word_updater updater(this);
102 iterate_code_heap(updater);
105 /* After a full GC that did not grow the heap, we have to update references
106 to literals and other words. */
107 struct word_and_literal_code_heap_updater {
110 word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
112 void operator()(heap_block *block, cell size)
114 parent->update_code_block_words_and_literals((code_block *)block);
118 void factor_vm::update_code_heap_words_and_literals()
120 word_and_literal_code_heap_updater updater(this);
121 code->allocator->sweep(updater);
124 /* After growing the heap, we have to perform a full relocation to update
125 references to card and deck arrays. */
126 struct code_heap_relocator {
129 code_heap_relocator(factor_vm *parent_) : parent(parent_) {}
131 void operator()(code_block *block, cell size)
133 parent->relocate_code_block(block);
137 void factor_vm::relocate_code_heap()
139 code_heap_relocator relocator(this);
140 code_heap_iterator<code_heap_relocator> iter(relocator);
141 code->allocator->sweep(iter);
144 void factor_vm::primitive_modify_code_heap()
146 gc_root<array> alist(dpop(),this);
148 cell count = array_capacity(alist.untagged());
154 for(i = 0; i < count; i++)
156 gc_root<array> pair(array_nth(alist.untagged(),i),this);
158 gc_root<word> word(array_nth(pair.untagged(),0),this);
159 gc_root<object> data(array_nth(pair.untagged(),1),this);
164 jit_compile_word(word.value(),data.value(),false);
168 array *compiled_data = data.as<array>().untagged();
169 cell owner = array_nth(compiled_data,0);
170 cell literals = array_nth(compiled_data,1);
171 cell relocation = array_nth(compiled_data,2);
172 cell labels = array_nth(compiled_data,3);
173 cell code = array_nth(compiled_data,4);
175 code_block *compiled = add_code_block(
176 code_block_optimized,
183 word->code = compiled;
187 critical_error("Expected a quotation or an array",data.value());
191 update_word_xt(word.value());
194 update_code_heap_words();
197 /* Push the free space and total size of the code heap */
198 void factor_vm::primitive_code_room()
200 cell used, total_free, max_free;
201 code->allocator->usage(&used,&total_free,&max_free);
202 dpush(tag_fixnum(code->seg->size / 1024));
203 dpush(tag_fixnum(used / 1024));
204 dpush(tag_fixnum(total_free / 1024));
205 dpush(tag_fixnum(max_free / 1024));
208 code_block *code_heap::forward_code_block(code_block *compiled)
210 return (code_block *)allocator->state.forward_block(compiled);
213 struct callframe_forwarder {
216 explicit callframe_forwarder(factor_vm *parent_) : parent(parent_) {}
218 void operator()(stack_frame *frame)
220 cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
222 code_block *forwarded = parent->code->forward_code_block(parent->frame_code(frame));
223 frame->xt = forwarded->xt();
225 FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
229 void factor_vm::forward_object_xts()
235 while(to_boolean(obj = next_object()))
237 switch(tagged<object>(obj).type())
241 word *w = untag<word>(obj);
244 w->code = code->forward_code_block(w->code);
246 w->profiling = code->forward_code_block(w->profiling);
253 quotation *quot = untag<quotation>(obj);
257 quot->code = code->forward_code_block(quot->code);
258 set_quot_xt(quot,quot->code);
264 callstack *stack = untag<callstack>(obj);
265 callframe_forwarder forwarder(this);
266 iterate_callstack_object(stack,forwarder);
277 void factor_vm::forward_context_xts()
279 callframe_forwarder forwarder(this);
280 iterate_active_frames(forwarder);
283 struct callback_forwarder {
285 callback_heap *callbacks;
287 callback_forwarder(code_heap *code_, callback_heap *callbacks_) :
288 code(code_), callbacks(callbacks_) {}
290 void operator()(callback *stub)
292 stub->compiled = code->forward_code_block(stub->compiled);
293 callbacks->update(stub);
297 void factor_vm::forward_callback_xts()
299 callback_forwarder forwarder(code,callbacks);
300 callbacks->iterate(forwarder);
303 /* Move all free space to the end of the code heap. Live blocks must be marked
304 on entry to this function. XTs in code blocks must be updated after this
306 void factor_vm::compact_code_heap(bool trace_contexts_p)
308 /* Figure out where blocks are going to go */
309 code->allocator->state.compute_forwarding();
311 /* Update references to the code heap from the data heap */
312 forward_object_xts();
315 forward_context_xts();
316 forward_callback_xts();
319 /* Move code blocks and update references amongst them (this requires
320 that the data heap is up to date since relocation looks up object XTs) */
321 code_heap_relocator relocator(this);
322 code_heap_iterator<code_heap_relocator> iter(relocator);
323 code->allocator->compact(iter);
326 struct stack_trace_stripper {
327 explicit stack_trace_stripper() {}
329 void operator()(code_block *compiled, cell size)
331 compiled->owner = false_object;
335 void factor_vm::primitive_strip_stack_traces()
337 stack_trace_stripper stripper;
338 iterate_code_heap(stripper);