factor/vm/code_heap.cpp

265 lines
5.6 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 *myvm;
explicit word_updater(factor_vm *myvm_) : myvm(myvm_) {}
void operator()(code_block *compiled)
{
myvm->update_word_references(compiled);
}
};
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
}
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 *)forwarding[compiled];
2009-05-02 05:04:19 -04:00
}
struct callframe_forwarder {
factor_vm *myvm;
2009-05-02 05:04:19 -04:00
explicit callframe_forwarder(factor_vm *myvm_) : myvm(myvm_) {}
void operator()(stack_frame *frame)
{
cell offset = (cell)FRAME_RETURN_ADDRESS(frame,myvm) - (cell)frame->xt;
code_block *forwarded = myvm->code->forward_code_block(myvm->frame_code(frame));
frame->xt = forwarded->xt();
FRAME_RETURN_ADDRESS(frame,myvm) = (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
{
2009-10-06 02:42:17 -04:00
code->compact_heap();
forward_object_xts();
if(trace_contexts_p)
{
forward_context_xts();
forward_callback_xts();
}
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)
{
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
}