VM: Refactor contexts to Factor style

db4
Erik Charlebois 2013-05-11 21:53:18 -04:00
parent 2bed6f6a25
commit 2a5126e49a
2 changed files with 248 additions and 315 deletions

View File

@ -1,365 +1,307 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
context::context(cell datastack_size, cell retainstack_size, cell callstack_size) : context::context(cell datastack_size, cell retainstack_size,
callstack_top(NULL), cell callstack_size)
callstack_bottom(NULL), : callstack_top(NULL),
datastack(0), callstack_bottom(NULL),
retainstack(0), datastack(0),
callstack_save(0), retainstack(0),
datastack_seg(new segment(datastack_size,false)), callstack_save(0),
retainstack_seg(new segment(retainstack_size,false)), datastack_seg(new segment(datastack_size, false)),
callstack_seg(new segment(callstack_size,false)) retainstack_seg(new segment(retainstack_size, false)),
{ callstack_seg(new segment(callstack_size, false)) {
reset(); reset();
} }
void context::reset_datastack() void context::reset_datastack() {
{ datastack = datastack_seg->start - sizeof(cell);
datastack = datastack_seg->start - sizeof(cell);
} }
void context::reset_retainstack() void context::reset_retainstack() {
{ retainstack = retainstack_seg->start - sizeof(cell);
retainstack = retainstack_seg->start - sizeof(cell);
} }
void context::reset_callstack() void context::reset_callstack() {
{ callstack_top = callstack_bottom = CALLSTACK_BOTTOM(this);
callstack_top = callstack_bottom = CALLSTACK_BOTTOM(this);
} }
void context::reset_context_objects() void context::reset_context_objects() {
{ memset_cell(context_objects, false_object,
memset_cell(context_objects,false_object,context_object_count * sizeof(cell)); context_object_count * sizeof(cell));
} }
void context::reset() void context::reset() {
{ reset_datastack();
reset_datastack(); reset_retainstack();
reset_retainstack(); reset_callstack();
reset_callstack(); reset_context_objects();
reset_context_objects();
} }
void context::fix_stacks() void context::fix_stacks() {
{ if (datastack + sizeof(cell) < datastack_seg->start ||
if(datastack + sizeof(cell) < datastack_seg->start datastack + stack_reserved >= datastack_seg->end)
|| datastack + stack_reserved >= datastack_seg->end) reset_datastack();
reset_datastack();
if(retainstack + sizeof(cell) < retainstack_seg->start if (retainstack + sizeof(cell) < retainstack_seg->start ||
|| retainstack + stack_reserved >= retainstack_seg->end) retainstack + stack_reserved >= retainstack_seg->end)
reset_retainstack(); reset_retainstack();
} }
void context::scrub_stacks(gc_info *info, cell index) void context::scrub_stacks(gc_info* info, cell index) {
{ u8* bitmap = info->gc_info_bitmap();
u8 *bitmap = info->gc_info_bitmap();
{ {
cell base = info->callsite_scrub_d(index); cell base = info->callsite_scrub_d(index);
for(cell loc = 0; loc < info->scrub_d_count; loc++) for (cell loc = 0; loc < info->scrub_d_count; loc++) {
{ if (bitmap_p(bitmap, base + loc)) {
if(bitmap_p(bitmap,base + loc))
{
#ifdef DEBUG_GC_MAPS #ifdef DEBUG_GC_MAPS
std::cout << "scrubbing datastack location " << loc << std::endl; std::cout << "scrubbing datastack location " << loc << std::endl;
#endif #endif
*((cell *)datastack - loc) = 0; *((cell*)datastack - loc) = 0;
} }
} }
} }
{ {
cell base = info->callsite_scrub_r(index); cell base = info->callsite_scrub_r(index);
for(cell loc = 0; loc < info->scrub_r_count; loc++) for (cell loc = 0; loc < info->scrub_r_count; loc++) {
{ if (bitmap_p(bitmap, base + loc)) {
if(bitmap_p(bitmap,base + loc))
{
#ifdef DEBUG_GC_MAPS #ifdef DEBUG_GC_MAPS
std::cout << "scrubbing retainstack location " << loc << std::endl; std::cout << "scrubbing retainstack location " << loc << std::endl;
#endif #endif
*((cell *)retainstack - loc) = 0; *((cell*)retainstack - loc) = 0;
} }
} }
} }
} }
context::~context() context::~context() {
{ delete datastack_seg;
delete datastack_seg; delete retainstack_seg;
delete retainstack_seg; delete callstack_seg;
delete callstack_seg;
} }
/* called on startup */ /* called on startup */
void factor_vm::init_contexts(cell datastack_size_, cell retainstack_size_, cell callstack_size_) void factor_vm::init_contexts(cell datastack_size_, cell retainstack_size_,
{ cell callstack_size_) {
datastack_size = datastack_size_; datastack_size = datastack_size_;
retainstack_size = retainstack_size_; retainstack_size = retainstack_size_;
callstack_size = callstack_size_; callstack_size = callstack_size_;
ctx = NULL; ctx = NULL;
spare_ctx = new_context(); spare_ctx = new_context();
} }
void factor_vm::delete_contexts() void factor_vm::delete_contexts() {
{ FACTOR_ASSERT(!ctx);
FACTOR_ASSERT(!ctx); std::list<context*>::const_iterator iter = unused_contexts.begin();
std::list<context *>::const_iterator iter = unused_contexts.begin(); std::list<context*>::const_iterator end = unused_contexts.end();
std::list<context *>::const_iterator end = unused_contexts.end(); while (iter != end) {
while(iter != end) delete *iter;
{ iter++;
delete *iter; }
iter++;
}
} }
context *factor_vm::new_context() context* factor_vm::new_context() {
{ context* new_context;
context *new_context;
if(unused_contexts.empty()) if (unused_contexts.empty()) {
{ new_context = new context(datastack_size, retainstack_size, callstack_size);
new_context = new context(datastack_size, } else {
retainstack_size, new_context = unused_contexts.back();
callstack_size); unused_contexts.pop_back();
} }
else
{
new_context = unused_contexts.back();
unused_contexts.pop_back();
}
new_context->reset(); new_context->reset();
active_contexts.insert(new_context); active_contexts.insert(new_context);
return new_context; return new_context;
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::init_context(context *ctx) void factor_vm::init_context(context* ctx) {
{ ctx->context_objects[OBJ_CONTEXT] = allot_alien(ctx);
ctx->context_objects[OBJ_CONTEXT] = allot_alien(ctx);
} }
/* Allocates memory */ /* Allocates memory */
context *new_context(factor_vm *parent) context* new_context(factor_vm* parent) {
{ context* new_context = parent->new_context();
context *new_context = parent->new_context(); parent->init_context(new_context);
parent->init_context(new_context); return new_context;
return new_context;
} }
void factor_vm::delete_context(context *old_context) void factor_vm::delete_context(context* old_context) {
{ unused_contexts.push_back(old_context);
unused_contexts.push_back(old_context); active_contexts.erase(old_context);
active_contexts.erase(old_context);
while(unused_contexts.size() > 10) while (unused_contexts.size() > 10) {
{ context* stale_context = unused_contexts.front();
context *stale_context = unused_contexts.front(); unused_contexts.pop_front();
unused_contexts.pop_front(); delete stale_context;
delete stale_context; }
}
} }
VM_C_API void delete_context(factor_vm *parent, context *old_context) VM_C_API void delete_context(factor_vm* parent, context* old_context) {
{ parent->delete_context(old_context);
parent->delete_context(old_context);
} }
/* Allocates memory */ /* Allocates memory */
VM_C_API void reset_context(factor_vm *parent, context *ctx) VM_C_API void reset_context(factor_vm* parent, context* ctx) {
{ ctx->reset();
ctx->reset(); parent->init_context(ctx);
parent->init_context(ctx);
} }
/* Allocates memory */ /* Allocates memory */
cell factor_vm::begin_callback(cell quot_) cell factor_vm::begin_callback(cell quot_) {
{ data_root<object> quot(quot_, this);
data_root<object> quot(quot_,this);
ctx->reset(); ctx->reset();
spare_ctx = new_context(); spare_ctx = new_context();
callback_ids.push_back(callback_id++); callback_ids.push_back(callback_id++);
init_context(ctx); init_context(ctx);
return quot.value(); return quot.value();
} }
cell begin_callback(factor_vm *parent, cell quot) cell begin_callback(factor_vm* parent, cell quot) {
{ return parent->begin_callback(quot);
return parent->begin_callback(quot);
} }
void factor_vm::end_callback() void factor_vm::end_callback() {
{ callback_ids.pop_back();
callback_ids.pop_back(); delete_context(ctx);
delete_context(ctx);
} }
void end_callback(factor_vm *parent) void end_callback(factor_vm* parent) { parent->end_callback(); }
{
parent->end_callback(); void factor_vm::primitive_current_callback() {
ctx->push(tag_fixnum(callback_ids.back()));
} }
void factor_vm::primitive_current_callback() void factor_vm::primitive_context_object() {
{ fixnum n = untag_fixnum(ctx->peek());
ctx->push(tag_fixnum(callback_ids.back())); ctx->replace(ctx->context_objects[n]);
} }
void factor_vm::primitive_context_object() void factor_vm::primitive_set_context_object() {
{ fixnum n = untag_fixnum(ctx->pop());
fixnum n = untag_fixnum(ctx->peek()); cell value = ctx->pop();
ctx->replace(ctx->context_objects[n]); ctx->context_objects[n] = value;
} }
void factor_vm::primitive_set_context_object() void factor_vm::primitive_context_object_for() {
{ context* other_ctx = (context*)pinned_alien_offset(ctx->pop());
fixnum n = untag_fixnum(ctx->pop()); fixnum n = untag_fixnum(ctx->peek());
cell value = ctx->pop(); ctx->replace(other_ctx->context_objects[n]);
ctx->context_objects[n] = value;
}
void factor_vm::primitive_context_object_for()
{
context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
fixnum n = untag_fixnum(ctx->peek());
ctx->replace(other_ctx->context_objects[n]);
} }
/* Allocates memory */ /* Allocates memory */
cell factor_vm::stack_to_array(cell bottom, cell top) cell factor_vm::stack_to_array(cell bottom, cell top) {
{ fixnum depth = (fixnum)(top - bottom + sizeof(cell));
fixnum depth = (fixnum)(top - bottom + sizeof(cell));
if(depth < 0) if (depth < 0)
return false_object; return false_object;
else else {
{ array* a = allot_uninitialized_array<array>(depth / sizeof(cell));
array *a = allot_uninitialized_array<array>(depth / sizeof(cell)); memcpy(a + 1, (void*)bottom, depth);
memcpy(a + 1,(void*)bottom,depth); return tag<array>(a);
return tag<array>(a); }
}
} }
cell factor_vm::datastack_to_array(context *ctx) cell factor_vm::datastack_to_array(context* ctx) {
{ cell array = stack_to_array(ctx->datastack_seg->start, ctx->datastack);
cell array = stack_to_array(ctx->datastack_seg->start,ctx->datastack); if (array == false_object) {
if(array == false_object) general_error(ERROR_DATASTACK_UNDERFLOW, false_object, false_object);
{ return false_object;
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object); } else
return false_object; return array;
}
else
return array;
} }
void factor_vm::primitive_datastack() void factor_vm::primitive_datastack() { ctx->push(datastack_to_array(ctx)); }
{
ctx->push(datastack_to_array(ctx)); void factor_vm::primitive_datastack_for() {
context* other_ctx = (context*)pinned_alien_offset(ctx->peek());
ctx->replace(datastack_to_array(other_ctx));
} }
void factor_vm::primitive_datastack_for() cell factor_vm::retainstack_to_array(context* ctx) {
{ cell array = stack_to_array(ctx->retainstack_seg->start, ctx->retainstack);
context *other_ctx = (context *)pinned_alien_offset(ctx->peek()); if (array == false_object) {
ctx->replace(datastack_to_array(other_ctx)); general_error(ERROR_RETAINSTACK_UNDERFLOW, false_object, false_object);
return false_object;
} else
return array;
} }
cell factor_vm::retainstack_to_array(context *ctx) void factor_vm::primitive_retainstack() {
{ ctx->push(retainstack_to_array(ctx));
cell array = stack_to_array(ctx->retainstack_seg->start,ctx->retainstack);
if(array == false_object)
{
general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object);
return false_object;
}
else
return array;
} }
void factor_vm::primitive_retainstack() void factor_vm::primitive_retainstack_for() {
{ context* other_ctx = (context*)pinned_alien_offset(ctx->peek());
ctx->push(retainstack_to_array(ctx)); ctx->replace(retainstack_to_array(other_ctx));
}
void factor_vm::primitive_retainstack_for()
{
context *other_ctx = (context *)pinned_alien_offset(ctx->peek());
ctx->replace(retainstack_to_array(other_ctx));
} }
/* returns pointer to top of stack */ /* returns pointer to top of stack */
cell factor_vm::array_to_stack(array *array, cell bottom) cell factor_vm::array_to_stack(array* array, cell bottom) {
{ cell depth = array_capacity(array) * sizeof(cell);
cell depth = array_capacity(array) * sizeof(cell); memcpy((void*)bottom, array + 1, depth);
memcpy((void*)bottom,array + 1,depth); return bottom + depth - sizeof(cell);
return bottom + depth - sizeof(cell);
} }
void factor_vm::set_datastack(context *ctx, array *array) void factor_vm::set_datastack(context* ctx, array* array) {
{ ctx->datastack = array_to_stack(array, ctx->datastack_seg->start);
ctx->datastack = array_to_stack(array,ctx->datastack_seg->start);
} }
void factor_vm::primitive_set_datastack() void factor_vm::primitive_set_datastack() {
{ set_datastack(ctx, untag_check<array>(ctx->pop()));
set_datastack(ctx,untag_check<array>(ctx->pop()));
} }
void factor_vm::set_retainstack(context *ctx, array *array) void factor_vm::set_retainstack(context* ctx, array* array) {
{ ctx->retainstack = array_to_stack(array, ctx->retainstack_seg->start);
ctx->retainstack = array_to_stack(array,ctx->retainstack_seg->start);
} }
void factor_vm::primitive_set_retainstack() void factor_vm::primitive_set_retainstack() {
{ set_retainstack(ctx, untag_check<array>(ctx->pop()));
set_retainstack(ctx,untag_check<array>(ctx->pop()));
} }
/* Used to implement call( */ /* Used to implement call( */
void factor_vm::primitive_check_datastack() void factor_vm::primitive_check_datastack() {
{ fixnum out = to_fixnum(ctx->pop());
fixnum out = to_fixnum(ctx->pop()); fixnum in = to_fixnum(ctx->pop());
fixnum in = to_fixnum(ctx->pop()); fixnum height = out - in;
fixnum height = out - in; array* saved_datastack = untag_check<array>(ctx->pop());
array *saved_datastack = untag_check<array>(ctx->pop()); fixnum saved_height = array_capacity(saved_datastack);
fixnum saved_height = array_capacity(saved_datastack); fixnum current_height =
fixnum current_height = (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) / sizeof(cell); (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) /
if(current_height - height != saved_height) sizeof(cell);
ctx->push(false_object); if (current_height - height != saved_height)
else ctx->push(false_object);
{ else {
cell *ds_bot = (cell *)ctx->datastack_seg->start; cell* ds_bot = (cell*)ctx->datastack_seg->start;
for(fixnum i = 0; i < saved_height - in; i++) for (fixnum i = 0; i < saved_height - in; i++) {
{ if (ds_bot[i] != array_nth(saved_datastack, i)) {
if(ds_bot[i] != array_nth(saved_datastack,i)) ctx->push(false_object);
{ return;
ctx->push(false_object); }
return; }
} ctx->push(true_object);
} }
ctx->push(true_object);
}
} }
void factor_vm::primitive_load_locals() void factor_vm::primitive_load_locals() {
{ fixnum count = untag_fixnum(ctx->pop());
fixnum count = untag_fixnum(ctx->pop()); memcpy((cell*)(ctx->retainstack + sizeof(cell)),
memcpy((cell *)(ctx->retainstack + sizeof(cell)), (cell*)(ctx->datastack - sizeof(cell) * (count - 1)),
(cell *)(ctx->datastack - sizeof(cell) * (count - 1)), sizeof(cell) * count);
sizeof(cell) * count); ctx->datastack -= sizeof(cell) * count;
ctx->datastack -= sizeof(cell) * count; ctx->retainstack += sizeof(cell) * count;
ctx->retainstack += sizeof(cell) * count;
} }
} }

View File

@ -1,5 +1,4 @@
namespace factor namespace factor {
{
// Context object count and identifiers must be kept in sync with: // Context object count and identifiers must be kept in sync with:
// core/kernel/kernel.factor // core/kernel/kernel.factor
@ -7,78 +6,70 @@ namespace factor
static const cell context_object_count = 10; static const cell context_object_count = 10;
enum context_object { enum context_object {
OBJ_NAMESTACK, OBJ_NAMESTACK,
OBJ_CATCHSTACK, OBJ_CATCHSTACK,
OBJ_CONTEXT, OBJ_CONTEXT,
OBJ_IN_CALLBACK_P, OBJ_IN_CALLBACK_P,
}; };
static const cell stack_reserved = 1024; static const cell stack_reserved = 1024;
struct context { struct context {
// First 4 fields accessed directly by compiler. See basis/vm/vm.factor // First 4 fields accessed directly by compiler. See basis/vm/vm.factor
/* Factor callstack pointers */ /* Factor callstack pointers */
void *callstack_top; void* callstack_top;
void *callstack_bottom; void* callstack_bottom;
/* current datastack top pointer */ /* current datastack top pointer */
cell datastack; cell datastack;
/* current retain stack top pointer */ /* current retain stack top pointer */
cell retainstack; cell retainstack;
/* C callstack pointer */ /* C callstack pointer */
cell callstack_save; cell callstack_save;
segment *datastack_seg; segment* datastack_seg;
segment *retainstack_seg; segment* retainstack_seg;
segment *callstack_seg; segment* callstack_seg;
/* context-specific special objects, accessed by context-object and /* context-specific special objects, accessed by context-object and
set-context-object primitives */ set-context-object primitives */
cell context_objects[context_object_count]; cell context_objects[context_object_count];
context(cell datastack_size, cell retainstack_size, cell callstack_size); context(cell datastack_size, cell retainstack_size, cell callstack_size);
~context(); ~context();
void reset_datastack(); void reset_datastack();
void reset_retainstack(); void reset_retainstack();
void reset_callstack(); void reset_callstack();
void reset_context_objects(); void reset_context_objects();
void reset(); void reset();
void fix_stacks(); void fix_stacks();
void scrub_stacks(gc_info *info, cell index); void scrub_stacks(gc_info* info, cell index);
cell peek() cell peek() { return *(cell*)datastack; }
{
return *(cell *)datastack;
}
void replace(cell tagged) void replace(cell tagged) { *(cell*)datastack = tagged; }
{
*(cell *)datastack = tagged;
}
cell pop() cell pop() {
{ cell value = peek();
cell value = peek(); datastack -= sizeof(cell);
datastack -= sizeof(cell); return value;
return value; }
}
void push(cell tagged) void push(cell tagged) {
{ datastack += sizeof(cell);
datastack += sizeof(cell); replace(tagged);
replace(tagged); }
}
}; };
VM_C_API context *new_context(factor_vm *parent); VM_C_API context* new_context(factor_vm* parent);
VM_C_API void delete_context(factor_vm *parent, context *old_context); VM_C_API void delete_context(factor_vm* parent, context* old_context);
VM_C_API void reset_context(factor_vm *parent, context *ctx); VM_C_API void reset_context(factor_vm* parent, context* ctx);
VM_C_API cell begin_callback(factor_vm *parent, cell quot); VM_C_API cell begin_callback(factor_vm* parent, cell quot);
VM_C_API void end_callback(factor_vm *parent); VM_C_API void end_callback(factor_vm* parent);
} }