2009-05-02 05:04:19 -04:00
|
|
|
#include "master.hpp"
|
|
|
|
|
2009-05-04 02:46:13 -04:00
|
|
|
namespace factor
|
|
|
|
{
|
|
|
|
|
2009-10-16 05:37:27 -04:00
|
|
|
code_heap::code_heap(bool secure_gc, cell size) : heap(secure_gc,size,true) {}
|
2009-10-06 02:42:17 -04:00
|
|
|
|
2009-10-06 05:36:34 -04:00
|
|
|
void code_heap::write_barrier(code_block *compiled)
|
|
|
|
{
|
2009-10-09 00:10:32 -04:00
|
|
|
points_to_nursery.insert(compiled);
|
|
|
|
points_to_aging.insert(compiled);
|
2009-10-06 05:36:34 -04:00
|
|
|
}
|
|
|
|
|
2009-10-16 03:55:02 -04:00
|
|
|
void code_heap::clear_remembered_set()
|
|
|
|
{
|
|
|
|
points_to_nursery.clear();
|
|
|
|
points_to_aging.clear();
|
|
|
|
}
|
|
|
|
|
2009-10-06 06:52:45 -04:00
|
|
|
bool code_heap::needs_fixup_p(code_block *compiled)
|
|
|
|
{
|
|
|
|
return needs_fixup.count(compiled) > 0;
|
|
|
|
}
|
|
|
|
|
2009-10-06 05:36:34 -04:00
|
|
|
void code_heap::code_heap_free(code_block *compiled)
|
|
|
|
{
|
2009-10-09 00:10:32 -04:00
|
|
|
points_to_nursery.erase(compiled);
|
|
|
|
points_to_aging.erase(compiled);
|
2009-10-06 06:52:45 -04:00
|
|
|
needs_fixup.erase(compiled);
|
2009-10-06 05:36:34 -04:00
|
|
|
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
|
|
|
{
|
2009-09-25 21:32:00 -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
|
|
|
{
|
2009-08-17 16:37:09 -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
|
|
|
|
2009-10-18 21:26:21 -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 {
|
2009-10-18 21:31:59 -04:00
|
|
|
factor_vm *parent;
|
2009-10-06 02:42:17 -04:00
|
|
|
|
2009-10-18 21:31:59 -04:00
|
|
|
explicit word_updater(factor_vm *parent_) : parent(parent_) {}
|
2009-10-06 02:42:17 -04:00
|
|
|
void operator()(code_block *compiled)
|
|
|
|
{
|
2009-10-18 21:31:59 -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
|
|
|
{
|
2009-10-03 09:47:05 -04:00
|
|
|
word_updater updater(this);
|
|
|
|
iterate_code_heap(updater);
|
2009-08-17 16:37:08 -04:00
|
|
|
}
|
|
|
|
|
2009-10-19 03:21:11 -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)
|
|
|
|
{
|
|
|
|
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()(heap_block *block)
|
|
|
|
{
|
|
|
|
parent->relocate_code_block((code_block *)block);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void factor_vm::relocate_code_heap()
|
|
|
|
{
|
|
|
|
code_heap_relocator relocator(this);
|
|
|
|
code->sweep_heap(relocator);
|
|
|
|
}
|
|
|
|
|
2009-09-27 14:42:18 -04:00
|
|
|
void factor_vm::primitive_modify_code_heap()
|
2009-05-02 05:04:19 -04:00
|
|
|
{
|
2009-08-17 16:37:09 -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++)
|
|
|
|
{
|
2009-08-17 16:37:09 -04:00
|
|
|
gc_root<array> pair(array_nth(alist.untagged(),i),this);
|
2009-05-02 05:04:19 -04:00
|
|
|
|
2009-08-17 16:37:09 -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:
|
2009-05-04 08:00:06 -04:00
|
|
|
{
|
|
|
|
array *compiled_data = data.as<array>().untagged();
|
2009-10-06 07:25:07 -04:00
|
|
|
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);
|
2009-05-04 08:00:06 -04:00
|
|
|
|
|
|
|
code_block *compiled = add_code_block(
|
|
|
|
WORD_TYPE,
|
|
|
|
code,
|
|
|
|
labels,
|
2009-10-06 07:25:07 -04:00
|
|
|
owner,
|
2009-05-04 08:00:06 -04:00
|
|
|
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 */
|
2009-09-27 14:42:18 -04:00
|
|
|
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;
|
2009-09-25 21:32:00 -04:00
|
|
|
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-10-16 05:33:35 -04:00
|
|
|
code_block *code_heap::forward_code_block(code_block *compiled)
|
2009-05-02 05:04:19 -04:00
|
|
|
{
|
2009-10-19 03:21:11 -04:00
|
|
|
return (code_block *)state->forward_block(compiled);
|
2009-05-02 05:04:19 -04:00
|
|
|
}
|
|
|
|
|
2009-10-16 05:33:35 -04:00
|
|
|
struct callframe_forwarder {
|
2009-10-18 21:31:59 -04:00
|
|
|
factor_vm *parent;
|
2009-05-02 05:04:19 -04:00
|
|
|
|
2009-10-18 21:31:59 -04:00
|
|
|
explicit callframe_forwarder(factor_vm *parent_) : parent(parent_) {}
|
2009-10-03 09:47:05 -04:00
|
|
|
|
|
|
|
void operator()(stack_frame *frame)
|
|
|
|
{
|
2009-10-18 21:31:59 -04:00
|
|
|
cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
|
2009-10-16 05:33:35 -04:00
|
|
|
|
2009-10-18 21:31:59 -04:00
|
|
|
code_block *forwarded = parent->code->forward_code_block(parent->frame_code(frame));
|
2009-10-03 09:47:05 -04:00
|
|
|
frame->xt = forwarded->xt();
|
2009-10-16 05:33:35 -04:00
|
|
|
|
2009-10-18 21:31:59 -04:00
|
|
|
FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
|
2009-10-03 09:47:05 -04:00
|
|
|
}
|
|
|
|
};
|
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
|
|
|
|
2009-10-18 21:26:21 -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
|
|
|
{
|
2009-05-02 21:47:29 -04:00
|
|
|
case WORD_TYPE:
|
2009-05-04 08:00:06 -04:00
|
|
|
{
|
|
|
|
word *w = untag<word>(obj);
|
|
|
|
|
|
|
|
if(w->code)
|
2009-10-16 05:33:35 -04:00
|
|
|
w->code = code->forward_code_block(w->code);
|
2009-05-04 08:00:06 -04:00
|
|
|
if(w->profiling)
|
2009-10-16 05:33:35 -04:00
|
|
|
w->profiling = code->forward_code_block(w->profiling);
|
|
|
|
|
|
|
|
update_word_xt(obj);
|
2009-05-04 08:00:06 -04:00
|
|
|
}
|
2009-05-02 21:47:29 -04:00
|
|
|
break;
|
|
|
|
case QUOTATION_TYPE:
|
2009-05-04 08:00:06 -04:00
|
|
|
{
|
|
|
|
quotation *quot = untag<quotation>(obj);
|
2009-05-02 05:04:19 -04:00
|
|
|
|
2009-05-12 04:09:15 -04:00
|
|
|
if(quot->code)
|
2009-10-16 05:33:35 -04:00
|
|
|
{
|
|
|
|
quot->code = code->forward_code_block(quot->code);
|
|
|
|
set_quot_xt(quot,quot->code);
|
|
|
|
}
|
2009-05-04 08:00:06 -04:00
|
|
|
}
|
2009-05-02 21:47:29 -04:00
|
|
|
break;
|
|
|
|
case CALLSTACK_TYPE:
|
2009-05-04 08:00:06 -04:00
|
|
|
{
|
|
|
|
callstack *stack = untag<callstack>(obj);
|
2009-10-16 05:33:35 -04:00
|
|
|
callframe_forwarder forwarder(this);
|
2009-10-03 09:47:05 -04:00
|
|
|
iterate_callstack_object(stack,forwarder);
|
2009-05-04 08:00:06 -04:00
|
|
|
}
|
2009-05-02 21:47:29 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2009-05-02 05:04:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-13 01:58:54 -04:00
|
|
|
end_scan();
|
2009-05-02 05:04:19 -04:00
|
|
|
}
|
|
|
|
|
2009-10-16 05:33:35 -04:00
|
|
|
void factor_vm::forward_context_xts()
|
2009-05-02 05:04:19 -04:00
|
|
|
{
|
2009-10-16 12:39:22 -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
|
|
|
|
2009-10-16 12:39:22 -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
|
|
|
{
|
2009-10-16 12:39:22 -04:00
|
|
|
stub->compiled = code->forward_code_block(stub->compiled);
|
|
|
|
callbacks->update(stub);
|
2009-05-02 05:04:19 -04:00
|
|
|
}
|
2009-10-16 12:39:22 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
void factor_vm::forward_callback_xts()
|
|
|
|
{
|
|
|
|
callback_forwarder forwarder(code,callbacks);
|
|
|
|
callbacks->iterate(forwarder);
|
2009-05-02 05:04:19 -04:00
|
|
|
}
|
|
|
|
|
2009-10-16 05:33:35 -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();
|
2009-10-16 05:33:35 -04:00
|
|
|
forward_object_xts();
|
2009-10-16 12:39:22 -04:00
|
|
|
if(trace_contexts_p)
|
|
|
|
{
|
|
|
|
forward_context_xts();
|
|
|
|
forward_callback_xts();
|
|
|
|
}
|
2009-10-19 03:21:11 -04:00
|
|
|
|
|
|
|
code_heap_relocator relocator(this);
|
|
|
|
iterate_code_heap(relocator);
|
2009-05-02 05:04:19 -04:00
|
|
|
}
|
2009-05-04 02:46:13 -04:00
|
|
|
|
2009-10-06 07:25:07 -04:00
|
|
|
struct stack_trace_stripper {
|
|
|
|
explicit stack_trace_stripper() {}
|
|
|
|
|
|
|
|
void operator()(code_block *compiled)
|
|
|
|
{
|
2009-10-18 21:26:21 -04:00
|
|
|
compiled->owner = false_object;
|
2009-10-06 07:25:07 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void factor_vm::primitive_strip_stack_traces()
|
|
|
|
{
|
|
|
|
stack_trace_stripper stripper;
|
|
|
|
iterate_code_heap(stripper);
|
|
|
|
}
|
|
|
|
|
2009-05-04 02:46:13 -04:00
|
|
|
}
|