factor/vm/code_heap.cpp

267 lines
5.7 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
{
2009-10-07 09:33:54 -04:00
code_heap::code_heap(bool secure_gc, cell size) : heap(secure_gc,size) {}
2009-10-06 02:42:17 -04:00
void code_heap::write_barrier(code_block *compiled)
{
2009-10-07 09:33:54 -04:00
remembered_set[compiled] = nursery_gen;
youngest_referenced_generation = nursery_gen;
}
bool code_heap::needs_fixup_p(code_block *compiled)
{
return needs_fixup.count(compiled) > 0;
}
void code_heap::code_heap_free(code_block *compiled)
{
remembered_set.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);
code->youngest_referenced_generation = nursery_gen;
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(word->pic_def != F) jit_compile(word->pic_def,relocate);
if(word->pic_tail_def != F) 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));
}
2009-09-23 14:05:46 -04:00
code_block *factor_vm::forward_xt(code_block *compiled)
2009-05-02 05:04:19 -04:00
{
2009-10-06 02:42:17 -04:00
return (code_block *)code->forwarding[compiled];
2009-05-02 05:04:19 -04:00
}
struct xt_forwarder {
factor_vm *myvm;
2009-05-02 05:04:19 -04:00
explicit xt_forwarder(factor_vm *myvm_) : myvm(myvm_) {}
void operator()(stack_frame *frame)
{
cell offset = (cell)FRAME_RETURN_ADDRESS(frame,myvm) - (cell)myvm->frame_code(frame);
code_block *forwarded = myvm->forward_xt(myvm->frame_code(frame));
frame->xt = forwarded->xt();
FRAME_RETURN_ADDRESS(frame,myvm) = (void *)((cell)forwarded + 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((obj = next_object()) != F)
{
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 = forward_xt(w->code);
if(w->profiling)
w->profiling = forward_xt(w->profiling);
}
break;
case QUOTATION_TYPE:
{
quotation *quot = untag<quotation>(obj);
2009-05-02 05:04:19 -04:00
if(quot->code)
quot->code = forward_xt(quot->code);
}
break;
case CALLSTACK_TYPE:
{
callstack *stack = untag<callstack>(obj);
xt_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
}
/* Set the XT fields now that the heap has been compacted */
2009-09-23 14:05:46 -04:00
void factor_vm::fixup_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((obj = next_object()) != F)
{
2009-05-04 05:50:24 -04:00
switch(tagged<object>(obj).type())
2009-05-02 05:04:19 -04:00
{
case WORD_TYPE:
update_word_xt(obj);
break;
case QUOTATION_TYPE:
{
quotation *quot = untag<quotation>(obj);
if(quot->code)
set_quot_xt(quot,quot->code);
break;
}
default:
break;
2009-05-02 05:04:19 -04:00
}
}
end_scan();
2009-05-02 05:04:19 -04:00
}
/* Move all free space to the end of the code heap. This is not very efficient,
since it makes several passes over the code and data heaps, but we only ever
do this before saving a deployed image and exiting, so performaance is not
critical here */
2009-09-23 14:05:46 -04:00
void factor_vm::compact_code_heap()
2009-05-02 05:04:19 -04:00
{
/* Free all unreachable code blocks, don't trace contexts */
2009-10-07 09:33:54 -04:00
garbage_collection(tenured_gen,false,false,0);
2009-05-02 05:04:19 -04:00
/* Figure out where the code heap blocks are going to end up */
2009-10-06 02:42:17 -04:00
cell size = code->compute_heap_forwarding();
2009-05-02 05:04:19 -04:00
/* Update word and quotation code pointers */
forward_object_xts();
/* Actually perform the compaction */
2009-10-06 02:42:17 -04:00
code->compact_heap();
2009-05-02 05:04:19 -04:00
/* Update word and quotation XTs */
fixup_object_xts();
/* Now update the free list; there will be a single free block at
the end */
code->build_free_list(size);
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 = F;
}
};
void factor_vm::primitive_strip_stack_traces()
{
stack_trace_stripper stripper;
iterate_code_heap(stripper);
}
2009-05-04 02:46:13 -04:00
}