factor/vm/code_heap.cpp

313 lines
7.0 KiB
C++
Raw Normal View History

2009-05-02 05:04:19 -04:00
#include "master.hpp"
2009-05-04 02:46:13 -04:00
namespace factor
{
code_heap::code_heap(bool secure_gc, cell size) : heap(secure_gc,size,true) {}
2009-10-06 02:42:17 -04:00
void code_heap::write_barrier(code_block *compiled)
{
points_to_nursery.insert(compiled);
points_to_aging.insert(compiled);
}
2009-10-16 03:55:02 -04:00
void code_heap::clear_remembered_set()
{
points_to_nursery.clear();
points_to_aging.clear();
}
bool code_heap::needs_fixup_p(code_block *compiled)
{
return needs_fixup.count(compiled) > 0;
}
void code_heap::code_heap_free(code_block *compiled)
{
points_to_nursery.erase(compiled);
points_to_aging.erase(compiled);
needs_fixup.erase(compiled);
heap_free(compiled);
}
2009-05-02 05:04:19 -04:00
/* Allocate a code heap during startup */
2009-09-23 14:05:46 -04:00
void factor_vm::init_code_heap(cell size)
2009-05-02 05:04:19 -04:00
{
2009-10-07 09:33:54 -04:00
code = new code_heap(secure_gc,size);
2009-05-02 05:04:19 -04:00
}
2009-09-23 14:05:46 -04:00
bool factor_vm::in_code_heap_p(cell ptr)
2009-05-02 05:04:19 -04:00
{
return (ptr >= code->seg->start && ptr <= code->seg->end);
2009-05-02 05:04:19 -04:00
}
/* Compile a word definition with the non-optimizing compiler. Allocates memory */
2009-09-23 14:05:46 -04:00
void factor_vm::jit_compile_word(cell word_, cell def_, bool relocate)
2009-05-02 05:04:19 -04:00
{
gc_root<word> word(word_,this);
gc_root<quotation> def(def_,this);
2009-05-02 05:04:19 -04:00
2009-05-02 10:19:09 -04:00
jit_compile(def.value(),relocate);
word->code = def->code;
2009-05-02 05:04:19 -04:00
if(to_boolean(word->pic_def)) jit_compile(word->pic_def,relocate);
if(to_boolean(word->pic_tail_def)) jit_compile(word->pic_tail_def,relocate);
2009-05-02 05:04:19 -04:00
}
2009-10-06 02:42:17 -04:00
struct word_updater {
factor_vm *parent;
2009-10-06 02:42:17 -04:00
explicit word_updater(factor_vm *parent_) : parent(parent_) {}
void operator()(code_block *compiled, cell size)
2009-10-06 02:42:17 -04:00
{
parent->update_word_references(compiled);
2009-10-06 02:42:17 -04:00
}
};
2009-05-02 05:04:19 -04:00
/* Update pointers to words referenced from all code blocks. Only after
defining a new word. */
2009-09-23 14:05:46 -04:00
void factor_vm::update_code_heap_words()
2009-08-17 16:37:08 -04:00
{
word_updater updater(this);
iterate_code_heap(updater);
2009-08-17 16:37:08 -04:00
}
/* After a full GC that did not grow the heap, we have to update references
to literals and other words. */
struct word_and_literal_code_heap_updater {
factor_vm *parent;
word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
void operator()(heap_block *block, cell size)
{
parent->update_code_block_words_and_literals((code_block *)block);
}
};
void factor_vm::update_code_heap_words_and_literals()
{
word_and_literal_code_heap_updater updater(this);
code->sweep_heap(updater);
}
/* After growing the heap, we have to perform a full relocation to update
references to card and deck arrays. */
struct code_heap_relocator {
factor_vm *parent;
code_heap_relocator(factor_vm *parent_) : parent(parent_) {}
void operator()(code_block *block, cell size)
{
parent->relocate_code_block(block);
}
};
void factor_vm::relocate_code_heap()
{
code_heap_relocator relocator(this);
code_heap_iterator<code_heap_relocator> iter(relocator);
code->sweep_heap(iter);
}
void factor_vm::primitive_modify_code_heap()
2009-05-02 05:04:19 -04:00
{
gc_root<array> alist(dpop(),this);
2009-05-02 10:19:09 -04:00
2009-05-04 05:50:24 -04:00
cell count = array_capacity(alist.untagged());
2009-05-02 05:04:19 -04:00
if(count == 0)
return;
2009-05-04 05:50:24 -04:00
cell i;
2009-05-02 05:04:19 -04:00
for(i = 0; i < count; i++)
{
gc_root<array> pair(array_nth(alist.untagged(),i),this);
2009-05-02 05:04:19 -04:00
gc_root<word> word(array_nth(pair.untagged(),0),this);
gc_root<object> data(array_nth(pair.untagged(),1),this);
2009-05-02 05:04:19 -04:00
2009-05-02 10:19:09 -04:00
switch(data.type())
2009-05-02 05:04:19 -04:00
{
2009-05-02 10:19:09 -04:00
case QUOTATION_TYPE:
jit_compile_word(word.value(),data.value(),false);
break;
case ARRAY_TYPE:
{
array *compiled_data = data.as<array>().untagged();
cell owner = array_nth(compiled_data,0);
cell literals = array_nth(compiled_data,1);
cell relocation = array_nth(compiled_data,2);
cell labels = array_nth(compiled_data,3);
cell code = array_nth(compiled_data,4);
code_block *compiled = add_code_block(
WORD_TYPE,
code,
labels,
owner,
relocation,
literals);
word->code = compiled;
}
2009-05-02 10:19:09 -04:00
break;
default:
critical_error("Expected a quotation or an array",data.value());
break;
2009-05-02 05:04:19 -04:00
}
2009-05-02 10:19:09 -04:00
update_word_xt(word.value());
2009-05-02 05:04:19 -04:00
}
update_code_heap_words();
}
/* Push the free space and total size of the code heap */
void factor_vm::primitive_code_room()
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
cell used, total_free, max_free;
code->heap_usage(&used,&total_free,&max_free);
dpush(tag_fixnum(code->seg->size / 1024));
2009-05-02 05:04:19 -04:00
dpush(tag_fixnum(used / 1024));
dpush(tag_fixnum(total_free / 1024));
dpush(tag_fixnum(max_free / 1024));
}
code_block *code_heap::forward_code_block(code_block *compiled)
2009-05-02 05:04:19 -04:00
{
return (code_block *)state->forward_block(compiled);
2009-05-02 05:04:19 -04:00
}
struct callframe_forwarder {
factor_vm *parent;
2009-05-02 05:04:19 -04:00
explicit callframe_forwarder(factor_vm *parent_) : parent(parent_) {}
void operator()(stack_frame *frame)
{
cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
code_block *forwarded = parent->code->forward_code_block(parent->frame_code(frame));
frame->xt = forwarded->xt();
FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
}
};
2009-08-17 16:37:08 -04:00
2009-09-23 14:05:46 -04:00
void factor_vm::forward_object_xts()
2009-05-02 05:04:19 -04:00
{
begin_scan();
2009-05-04 05:50:24 -04:00
cell obj;
2009-05-02 05:04:19 -04:00
while(to_boolean(obj = next_object()))
2009-05-02 05:04:19 -04:00
{
2009-05-04 05:50:24 -04:00
switch(tagged<object>(obj).type())
2009-05-02 05:04:19 -04:00
{
case WORD_TYPE:
{
word *w = untag<word>(obj);
if(w->code)
w->code = code->forward_code_block(w->code);
if(w->profiling)
w->profiling = code->forward_code_block(w->profiling);
update_word_xt(obj);
}
break;
case QUOTATION_TYPE:
{
quotation *quot = untag<quotation>(obj);
2009-05-02 05:04:19 -04:00
if(quot->code)
{
quot->code = code->forward_code_block(quot->code);
set_quot_xt(quot,quot->code);
}
}
break;
case CALLSTACK_TYPE:
{
callstack *stack = untag<callstack>(obj);
callframe_forwarder forwarder(this);
iterate_callstack_object(stack,forwarder);
}
break;
default:
break;
2009-05-02 05:04:19 -04:00
}
}
end_scan();
2009-05-02 05:04:19 -04:00
}
void factor_vm::forward_context_xts()
2009-05-02 05:04:19 -04:00
{
callframe_forwarder forwarder(this);
iterate_active_frames(forwarder);
}
struct callback_forwarder {
code_heap *code;
callback_heap *callbacks;
2009-05-02 05:04:19 -04:00
callback_forwarder(code_heap *code_, callback_heap *callbacks_) :
code(code_), callbacks(callbacks_) {}
void operator()(callback *stub)
2009-05-02 05:04:19 -04:00
{
stub->compiled = code->forward_code_block(stub->compiled);
callbacks->update(stub);
2009-05-02 05:04:19 -04:00
}
};
void factor_vm::forward_callback_xts()
{
callback_forwarder forwarder(code,callbacks);
callbacks->iterate(forwarder);
2009-05-02 05:04:19 -04:00
}
/* Move all free space to the end of the code heap. Live blocks must be marked
on entry to this function. XTs in code blocks must be updated after this
function returns. */
void factor_vm::compact_code_heap(bool trace_contexts_p)
2009-05-02 05:04:19 -04:00
{
/* Figure out where blocks are going to go */
code->state->compute_forwarding();
/* Update references to the code heap from the data heap */
forward_object_xts();
if(trace_contexts_p)
{
forward_context_xts();
forward_callback_xts();
}
/* Move code blocks and update references amongst them (this requires
that the data heap is up to date since relocation looks up object XTs) */
code_heap_relocator relocator(this);
code_heap_iterator<code_heap_relocator> iter(relocator);
code->compact_heap(iter);
2009-05-02 05:04:19 -04:00
}
2009-05-04 02:46:13 -04:00
struct stack_trace_stripper {
explicit stack_trace_stripper() {}
void operator()(code_block *compiled, cell size)
{
compiled->owner = false_object;
}
};
void factor_vm::primitive_strip_stack_traces()
{
stack_trace_stripper stripper;
iterate_code_heap(stripper);
}
2009-05-04 02:46:13 -04:00
}