VM: Refactor code_heap to Factor style

db4
Erik Charlebois 2013-05-11 21:51:54 -04:00
parent d2fe86eb7e
commit 7f56458820
2 changed files with 224 additions and 268 deletions

View File

@ -1,13 +1,13 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
code_heap::code_heap(cell size) code_heap::code_heap(cell size) {
{ if (size > ((u64) 1 << (sizeof(cell) * 8 - 6)))
if(size > ((u64)1 << (sizeof(cell) * 8 - 6))) fatal_error("Heap too large",size); fatal_error("Heap too large", size);
seg = new segment(align_page(size), true); seg = new segment(align_page(size), true);
if(!seg) fatal_error("Out of memory in code_heap constructor",size); if (!seg)
fatal_error("Out of memory in code_heap constructor", size);
cell start = seg->start + getpagesize() + seh_area_size; cell start = seg->start + getpagesize() + seh_area_size;
@ -18,48 +18,38 @@ code_heap::code_heap(cell size)
seh_area = (char*)seg->start + getpagesize(); seh_area = (char*)seg->start + getpagesize();
} }
code_heap::~code_heap() code_heap::~code_heap() {
{
delete allocator; delete allocator;
allocator = NULL; allocator = NULL;
delete seg; delete seg;
seg = NULL; seg = NULL;
} }
void code_heap::write_barrier(code_block *compiled) void code_heap::write_barrier(code_block* compiled) {
{
points_to_nursery.insert(compiled); points_to_nursery.insert(compiled);
points_to_aging.insert(compiled); points_to_aging.insert(compiled);
} }
void code_heap::clear_remembered_set() void code_heap::clear_remembered_set() {
{
points_to_nursery.clear(); points_to_nursery.clear();
points_to_aging.clear(); points_to_aging.clear();
} }
bool code_heap::uninitialized_p(code_block *compiled) bool code_heap::uninitialized_p(code_block* compiled) {
{
return uninitialized_blocks.count(compiled) > 0; return uninitialized_blocks.count(compiled) > 0;
} }
bool code_heap::marked_p(code_block *compiled) bool code_heap::marked_p(code_block* compiled) {
{
return allocator->state.marked_p(compiled); return allocator->state.marked_p(compiled);
} }
void code_heap::set_marked_p(code_block *compiled) void code_heap::set_marked_p(code_block* compiled) {
{
allocator->state.set_marked_p(compiled); allocator->state.set_marked_p(compiled);
} }
void code_heap::clear_mark_bits() void code_heap::clear_mark_bits() { allocator->state.clear_mark_bits(); }
{
allocator->state.clear_mark_bits();
}
void code_heap::free(code_block *compiled) void code_heap::free(code_block* compiled) {
{
FACTOR_ASSERT(!uninitialized_p(compiled)); FACTOR_ASSERT(!uninitialized_p(compiled));
points_to_nursery.erase(compiled); points_to_nursery.erase(compiled);
points_to_aging.erase(compiled); points_to_aging.erase(compiled);
@ -67,13 +57,9 @@ void code_heap::free(code_block *compiled)
allocator->free(compiled); allocator->free(compiled);
} }
void code_heap::flush_icache() void code_heap::flush_icache() { factor::flush_icache(seg->start, seg->size); }
{
factor::flush_icache(seg->start,seg->size);
}
struct clear_free_blocks_from_all_blocks_iterator struct clear_free_blocks_from_all_blocks_iterator {
{
code_heap* code; code_heap* code;
clear_free_blocks_from_all_blocks_iterator(code_heap* code) : code(code) {} clear_free_blocks_from_all_blocks_iterator(code_heap* code) : code(code) {}
@ -88,8 +74,7 @@ struct clear_free_blocks_from_all_blocks_iterator
} }
}; };
void code_heap::sweep() void code_heap::sweep() {
{
clear_free_blocks_from_all_blocks_iterator clearer(this); clear_free_blocks_from_all_blocks_iterator clearer(this);
allocator->sweep(clearer); allocator->sweep(clearer);
#ifdef FACTOR_DEBUG #ifdef FACTOR_DEBUG
@ -100,30 +85,29 @@ void code_heap::sweep()
struct all_blocks_set_verifier { struct all_blocks_set_verifier {
std::set<cell>* all_blocks; std::set<cell>* all_blocks;
all_blocks_set_verifier(std::set<cell> *all_blocks) : all_blocks(all_blocks) {} all_blocks_set_verifier(std::set<cell>* all_blocks)
: all_blocks(all_blocks) {}
void operator()(code_block *block, cell size) void operator()(code_block* block, cell size) {
{
FACTOR_ASSERT(all_blocks->find((cell) block) != all_blocks->end()); FACTOR_ASSERT(all_blocks->find((cell) block) != all_blocks->end());
} }
}; };
void code_heap::verify_all_blocks_set() void code_heap::verify_all_blocks_set() {
{
all_blocks_set_verifier verifier(&all_blocks); all_blocks_set_verifier verifier(&all_blocks);
allocator->iterate(verifier); allocator->iterate(verifier);
} }
code_block *code_heap::code_block_for_address(cell address) code_block* code_heap::code_block_for_address(cell address) {
{ std::set<cell>::const_iterator blocki = all_blocks.upper_bound(address);
std::set<cell>::const_iterator blocki =
all_blocks.upper_bound(address);
FACTOR_ASSERT(blocki != all_blocks.begin()); FACTOR_ASSERT(blocki != all_blocks.begin());
--blocki; --blocki;
code_block* found_block = (code_block*)*blocki; code_block* found_block = (code_block*)*blocki;
FACTOR_ASSERT((cell)found_block->entry_point() <= address FACTOR_ASSERT((cell) found_block->entry_point() <=
/* XXX this isn't valid during fixup. should store the size in the map address /* XXX this isn't valid during fixup. should store the
&& address - (cell)found_block->entry_point() < found_block->size()*/); size in the map
&& address - (cell)found_block->entry_point() <
found_block->size()*/);
return found_block; return found_block;
} }
@ -132,14 +116,12 @@ struct all_blocks_set_inserter {
all_blocks_set_inserter(code_heap* code) : code(code) {} all_blocks_set_inserter(code_heap* code) : code(code) {}
void operator()(code_block *block, cell size) void operator()(code_block* block, cell size) {
{
code->all_blocks.insert((cell) block); code->all_blocks.insert((cell) block);
} }
}; };
void code_heap::initialize_all_blocks_set() void code_heap::initialize_all_blocks_set() {
{
all_blocks.clear(); all_blocks.clear();
all_blocks_set_inserter inserter(this); all_blocks_set_inserter inserter(this);
allocator->iterate(inserter); allocator->iterate(inserter);
@ -149,20 +131,16 @@ void code_heap::initialize_all_blocks_set()
} }
/* Allocate a code heap during startup */ /* Allocate a code heap during startup */
void factor_vm::init_code_heap(cell size) void factor_vm::init_code_heap(cell size) { code = new code_heap(size); }
{
code = new code_heap(size);
}
struct word_updater { struct word_updater {
factor_vm* parent; factor_vm* parent;
bool reset_inline_caches; bool reset_inline_caches;
word_updater(factor_vm *parent_, bool reset_inline_caches_) : word_updater(factor_vm* parent_, bool reset_inline_caches_)
parent(parent_), reset_inline_caches(reset_inline_caches_) {} : parent(parent_), reset_inline_caches(reset_inline_caches_) {}
void operator()(code_block *compiled, cell size) void operator()(code_block* compiled, cell size) {
{
parent->update_word_references(compiled, reset_inline_caches); parent->update_word_references(compiled, reset_inline_caches);
} }
}; };
@ -170,18 +148,18 @@ struct word_updater {
/* Update pointers to words referenced from all code blocks. /* Update pointers to words referenced from all code blocks.
Only needed after redefining an existing word. Only needed after redefining an existing word.
If generic words were redefined, inline caches need to be reset. */ If generic words were redefined, inline caches need to be reset. */
void factor_vm::update_code_heap_words(bool reset_inline_caches) void factor_vm::update_code_heap_words(bool reset_inline_caches) {
{
word_updater updater(this, reset_inline_caches); word_updater updater(this, reset_inline_caches);
each_code_block(updater); each_code_block(updater);
} }
/* Fix up new words only. /* Fix up new words only.
Fast path for compilation units that only define new words. */ Fast path for compilation units that only define new words. */
void factor_vm::initialize_code_blocks() void factor_vm::initialize_code_blocks() {
{ std::map<code_block*, cell>::const_iterator iter =
std::map<code_block *, cell>::const_iterator iter = code->uninitialized_blocks.begin(); code->uninitialized_blocks.begin();
std::map<code_block *, cell>::const_iterator end = code->uninitialized_blocks.end(); std::map<code_block*, cell>::const_iterator end =
code->uninitialized_blocks.end();
for (; iter != end; iter++) for (; iter != end; iter++)
initialize_code_block(iter->first, iter->second); initialize_code_block(iter->first, iter->second);
@ -190,8 +168,7 @@ void factor_vm::initialize_code_blocks()
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_modify_code_heap() void factor_vm::primitive_modify_code_heap() {
{
bool reset_inline_caches = to_boolean(ctx->pop()); bool reset_inline_caches = to_boolean(ctx->pop());
bool update_existing_words = to_boolean(ctx->pop()); bool update_existing_words = to_boolean(ctx->pop());
data_root<array> alist(ctx->pop(), this); data_root<array> alist(ctx->pop(), this);
@ -201,20 +178,17 @@ void factor_vm::primitive_modify_code_heap()
if (count == 0) if (count == 0)
return; return;
for(cell i = 0; i < count; i++) for (cell i = 0; i < count; i++) {
{
data_root<array> pair(array_nth(alist.untagged(), i), this); data_root<array> pair(array_nth(alist.untagged(), i), this);
data_root<word> word(array_nth(pair.untagged(), 0), this); data_root<word> word(array_nth(pair.untagged(), 0), this);
data_root<object> data(array_nth(pair.untagged(), 1), this); data_root<object> data(array_nth(pair.untagged(), 1), this);
switch(data.type()) switch (data.type()) {
{
case QUOTATION_TYPE: case QUOTATION_TYPE:
jit_compile_word(word.value(), data.value(), false); jit_compile_word(word.value(), data.value(), false);
break; break;
case ARRAY_TYPE: case ARRAY_TYPE: {
{
array* compiled_data = data.as<array>().untagged(); array* compiled_data = data.as<array>().untagged();
cell parameters = array_nth(compiled_data, 0); cell parameters = array_nth(compiled_data, 0);
cell literals = array_nth(compiled_data, 1); cell literals = array_nth(compiled_data, 1);
@ -223,19 +197,12 @@ void factor_vm::primitive_modify_code_heap()
cell code = array_nth(compiled_data, 4); cell code = array_nth(compiled_data, 4);
cell frame_size = untag_fixnum(array_nth(compiled_data, 5)); cell frame_size = untag_fixnum(array_nth(compiled_data, 5));
code_block *compiled = add_code_block( code_block* compiled =
code_block_optimized, add_code_block(code_block_optimized, code, labels, word.value(),
code, relocation, parameters, literals, frame_size);
labels,
word.value(),
relocation,
parameters,
literals,
frame_size);
word->entry_point = compiled->entry_point(); word->entry_point = compiled->entry_point();
} } break;
break;
default: default:
critical_error("Expected a quotation or an array", data.value()); critical_error("Expected a quotation or an array", data.value());
break; break;
@ -248,8 +215,7 @@ void factor_vm::primitive_modify_code_heap()
initialize_code_blocks(); initialize_code_blocks();
} }
code_heap_room factor_vm::code_room() code_heap_room factor_vm::code_room() {
{
code_heap_room room; code_heap_room room;
room.size = code->allocator->size; room.size = code->allocator->size;
@ -262,8 +228,7 @@ code_heap_room factor_vm::code_room()
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_code_room() void factor_vm::primitive_code_room() {
{
code_heap_room room = code_room(); code_heap_room room = code_room();
ctx->push(tag<byte_array>(byte_array_from_value(&room))); ctx->push(tag<byte_array>(byte_array_from_value(&room)));
} }
@ -271,14 +236,12 @@ void factor_vm::primitive_code_room()
struct stack_trace_stripper { struct stack_trace_stripper {
explicit stack_trace_stripper() {} explicit stack_trace_stripper() {}
void operator()(code_block *compiled, cell size) void operator()(code_block* compiled, cell size) {
{
compiled->owner = false_object; compiled->owner = false_object;
} }
}; };
void factor_vm::primitive_strip_stack_traces() void factor_vm::primitive_strip_stack_traces() {
{
stack_trace_stripper stripper; stack_trace_stripper stripper;
each_code_block(stripper); each_code_block(stripper);
} }
@ -286,8 +249,7 @@ void factor_vm::primitive_strip_stack_traces()
struct code_block_accumulator { struct code_block_accumulator {
std::vector<cell> objects; std::vector<cell> objects;
void operator()(code_block *compiled, cell size) void operator()(code_block* compiled, cell size) {
{
objects.push_back(compiled->owner); objects.push_back(compiled->owner);
objects.push_back(compiled->parameters); objects.push_back(compiled->parameters);
objects.push_back(compiled->relocation); objects.push_back(compiled->relocation);
@ -309,17 +271,13 @@ struct code_block_accumulator {
}; };
/* Allocates memory */ /* Allocates memory */
cell factor_vm::code_blocks() cell factor_vm::code_blocks() {
{
code_block_accumulator accum; code_block_accumulator accum;
each_code_block(accum); each_code_block(accum);
return std_vector_to_array(accum.objects); return std_vector_to_array(accum.objects);
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_code_blocks() void factor_vm::primitive_code_blocks() { ctx->push(code_blocks()); }
{
ctx->push(code_blocks());
}
} }

View File

@ -1,5 +1,4 @@
namespace factor namespace factor {
{
#if defined(WINDOWS) && defined(FACTOR_64) #if defined(WINDOWS) && defined(FACTOR_64)
const cell seh_area_size = 1024; const cell seh_area_size = 1024;
@ -52,8 +51,7 @@ struct code_heap {
code_block* code_block_for_address(cell address); code_block* code_block_for_address(cell address);
bool safepoint_p(cell addr) bool safepoint_p(cell addr) {
{
cell page_mask = ~(getpagesize() - 1); cell page_mask = ~(getpagesize() - 1);
return (addr & page_mask) == (cell) safepoint_page; return (addr & page_mask) == (cell) safepoint_page;
} }