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,75 +1,66 @@
#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_top(NULL),
callstack_bottom(NULL), callstack_bottom(NULL),
datastack(0), datastack(0),
retainstack(0), retainstack(0),
callstack_save(0), callstack_save(0),
datastack_seg(new segment(datastack_size,false)), datastack_seg(new segment(datastack_size, false)),
retainstack_seg(new segment(retainstack_size,false)), retainstack_seg(new segment(retainstack_size, false)),
callstack_seg(new segment(callstack_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;
} }
} }
} }
@ -77,29 +68,26 @@ void context::scrub_stacks(gc_info *info, cell index)
{ {
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_;
@ -108,30 +96,22 @@ void factor_vm::init_contexts(cell datastack_size_, cell retainstack_size_, cell
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; delete *iter;
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,
callstack_size);
}
else
{
new_context = unused_contexts.back(); new_context = unused_contexts.back();
unused_contexts.pop_back(); unused_contexts.pop_back();
} }
@ -144,48 +124,41 @@ context *factor_vm::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();
@ -196,154 +169,124 @@ cell factor_vm::begin_callback(cell quot_)
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() void factor_vm::primitive_current_callback() {
{
ctx->push(tag_fixnum(callback_ids.back())); ctx->push(tag_fixnum(callback_ids.back()));
} }
void factor_vm::primitive_context_object() void factor_vm::primitive_context_object() {
{
fixnum n = untag_fixnum(ctx->peek()); fixnum n = untag_fixnum(ctx->peek());
ctx->replace(ctx->context_objects[n]); ctx->replace(ctx->context_objects[n]);
} }
void factor_vm::primitive_set_context_object() void factor_vm::primitive_set_context_object() {
{
fixnum n = untag_fixnum(ctx->pop()); fixnum n = untag_fixnum(ctx->pop());
cell value = ctx->pop(); cell value = ctx->pop();
ctx->context_objects[n] = value; ctx->context_objects[n] = value;
} }
void factor_vm::primitive_context_object_for() void factor_vm::primitive_context_object_for() {
{ context* other_ctx = (context*)pinned_alien_offset(ctx->pop());
context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
fixnum n = untag_fixnum(ctx->peek()); fixnum n = untag_fixnum(ctx->peek());
ctx->replace(other_ctx->context_objects[n]); 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);
{
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
return false_object; return false_object;
} } else
else
return array; 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() void factor_vm::primitive_datastack_for() {
{ context* other_ctx = (context*)pinned_alien_offset(ctx->peek());
context *other_ctx = (context *)pinned_alien_offset(ctx->peek());
ctx->replace(datastack_to_array(other_ctx)); ctx->replace(datastack_to_array(other_ctx));
} }
cell factor_vm::retainstack_to_array(context *ctx) cell factor_vm::retainstack_to_array(context* ctx) {
{ cell array = stack_to_array(ctx->retainstack_seg->start, ctx->retainstack);
cell array = stack_to_array(ctx->retainstack_seg->start,ctx->retainstack); if (array == false_object) {
if(array == false_object) general_error(ERROR_RETAINSTACK_UNDERFLOW, false_object, false_object);
{
general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object);
return false_object; return false_object;
} } else
else
return array; return array;
} }
void factor_vm::primitive_retainstack() void factor_vm::primitive_retainstack() {
{
ctx->push(retainstack_to_array(ctx)); ctx->push(retainstack_to_array(ctx));
} }
void factor_vm::primitive_retainstack_for() void factor_vm::primitive_retainstack_for() {
{ context* other_ctx = (context*)pinned_alien_offset(ctx->peek());
context *other_ctx = (context *)pinned_alien_offset(ctx->peek());
ctx->replace(retainstack_to_array(other_ctx)); 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 = (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) / sizeof(cell); fixnum current_height =
if(current_height - height != saved_height) (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) /
sizeof(cell);
if (current_height - height != saved_height)
ctx->push(false_object); ctx->push(false_object);
else 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); ctx->push(false_object);
return; return;
} }
@ -352,11 +295,10 @@ void factor_vm::primitive_check_datastack()
} }
} }
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
@ -20,8 +19,8 @@ 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;
@ -32,9 +31,9 @@ struct context {
/* 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 */
@ -49,36 +48,28 @@ struct context {
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);
} }