VM: Refactor callbacks to Factor style
parent
22eed89484
commit
7aae3c04ce
|
@ -1,26 +1,20 @@
|
|||
#include "master.hpp"
|
||||
|
||||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
callback_heap::callback_heap(cell size, factor_vm *parent_) :
|
||||
seg(new segment(size,true)),
|
||||
here(seg->start),
|
||||
parent(parent_) {}
|
||||
callback_heap::callback_heap(cell size, factor_vm* parent_)
|
||||
: seg(new segment(size, true)), here(seg->start), parent(parent_) {}
|
||||
|
||||
callback_heap::~callback_heap()
|
||||
{
|
||||
callback_heap::~callback_heap() {
|
||||
delete seg;
|
||||
seg = NULL;
|
||||
}
|
||||
|
||||
void factor_vm::init_callbacks(cell size)
|
||||
{
|
||||
callbacks = new callback_heap(size,this);
|
||||
void factor_vm::init_callbacks(cell size) {
|
||||
callbacks = new callback_heap(size, this);
|
||||
}
|
||||
|
||||
bool callback_heap::setup_seh_p()
|
||||
{
|
||||
bool callback_heap::setup_seh_p() {
|
||||
#if defined(WINDOWS) && defined(FACTOR_X86)
|
||||
return true;
|
||||
#else
|
||||
|
@ -28,8 +22,7 @@ bool callback_heap::setup_seh_p()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool callback_heap::return_takes_param_p()
|
||||
{
|
||||
bool callback_heap::return_takes_param_p() {
|
||||
#if defined(FACTOR_X86) || defined(FACTOR_AMD64)
|
||||
return true;
|
||||
#else
|
||||
|
@ -37,71 +30,69 @@ bool callback_heap::return_takes_param_p()
|
|||
#endif
|
||||
}
|
||||
|
||||
instruction_operand callback_heap::callback_operand(code_block *stub, cell index)
|
||||
{
|
||||
instruction_operand callback_heap::callback_operand(code_block* stub,
|
||||
cell index) {
|
||||
tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
|
||||
tagged<byte_array> relocation_template(array_nth(code_template.untagged(),0));
|
||||
tagged<byte_array> relocation_template(
|
||||
array_nth(code_template.untagged(), 0));
|
||||
|
||||
relocation_entry entry(relocation_template->data<relocation_entry>()[index]);
|
||||
return instruction_operand(entry,stub,0);
|
||||
return instruction_operand(entry, stub, 0);
|
||||
}
|
||||
|
||||
void callback_heap::store_callback_operand(code_block *stub, cell index)
|
||||
{
|
||||
parent->store_external_address(callback_operand(stub,index));
|
||||
void callback_heap::store_callback_operand(code_block* stub, cell index) {
|
||||
parent->store_external_address(callback_operand(stub, index));
|
||||
}
|
||||
|
||||
void callback_heap::store_callback_operand(code_block *stub, cell index, cell value)
|
||||
{
|
||||
callback_operand(stub,index).store_value(value);
|
||||
void callback_heap::store_callback_operand(code_block* stub, cell index,
|
||||
cell value) {
|
||||
callback_operand(stub, index).store_value(value);
|
||||
}
|
||||
|
||||
void callback_heap::update(code_block *stub)
|
||||
{
|
||||
store_callback_operand(stub,setup_seh_p() ? 2 : 1,(cell)callback_entry_point(stub));
|
||||
void callback_heap::update(code_block* stub) {
|
||||
store_callback_operand(stub, setup_seh_p() ? 2 : 1,
|
||||
(cell) callback_entry_point(stub));
|
||||
stub->flush_icache();
|
||||
}
|
||||
|
||||
code_block *callback_heap::add(cell owner, cell return_rewind)
|
||||
{
|
||||
code_block* callback_heap::add(cell owner, cell return_rewind) {
|
||||
tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
|
||||
tagged<byte_array> insns(array_nth(code_template.untagged(),1));
|
||||
tagged<byte_array> insns(array_nth(code_template.untagged(), 1));
|
||||
cell size = array_capacity(insns.untagged());
|
||||
|
||||
cell bump = align(size + sizeof(code_block),data_alignment);
|
||||
if(here + bump > seg->end) fatal_error("Out of callback space",0);
|
||||
cell bump = align(size + sizeof(code_block), data_alignment);
|
||||
if (here + bump > seg->end)
|
||||
fatal_error("Out of callback space", 0);
|
||||
|
||||
free_heap_block *free_block = (free_heap_block *)here;
|
||||
free_heap_block* free_block = (free_heap_block*)here;
|
||||
free_block->make_free(bump);
|
||||
here += bump;
|
||||
|
||||
code_block *stub = (code_block *)free_block;
|
||||
code_block* stub = (code_block*)free_block;
|
||||
stub->owner = owner;
|
||||
stub->parameters = false_object;
|
||||
stub->relocation = false_object;
|
||||
|
||||
memcpy(stub->entry_point(),insns->data<void>(),size);
|
||||
memcpy(stub->entry_point(), insns->data<void>(), size);
|
||||
|
||||
/* Store VM pointer */
|
||||
store_callback_operand(stub,0,(cell)parent);
|
||||
store_callback_operand(stub, 0, (cell) parent);
|
||||
|
||||
cell index;
|
||||
|
||||
if(setup_seh_p())
|
||||
{
|
||||
store_callback_operand(stub,1);
|
||||
if (setup_seh_p()) {
|
||||
store_callback_operand(stub, 1);
|
||||
index = 1;
|
||||
}
|
||||
else
|
||||
} else
|
||||
index = 0;
|
||||
|
||||
/* Store VM pointer */
|
||||
store_callback_operand(stub,index + 2,(cell)parent);
|
||||
store_callback_operand(stub, index + 2, (cell) parent);
|
||||
|
||||
/* On x86, the RET instruction takes an argument which depends on
|
||||
the callback's calling convention */
|
||||
if(return_takes_param_p())
|
||||
store_callback_operand(stub,index + 3,return_rewind);
|
||||
if (return_takes_param_p())
|
||||
store_callback_operand(stub, index + 3, return_rewind);
|
||||
|
||||
update(stub);
|
||||
|
||||
|
@ -109,31 +100,27 @@ code_block *callback_heap::add(cell owner, cell return_rewind)
|
|||
}
|
||||
|
||||
struct callback_updater {
|
||||
callback_heap *callbacks;
|
||||
callback_heap* callbacks;
|
||||
|
||||
explicit callback_updater(callback_heap *callbacks_) : callbacks(callbacks_) {}
|
||||
explicit callback_updater(callback_heap* callbacks_)
|
||||
: callbacks(callbacks_) {}
|
||||
|
||||
void operator()(code_block *stub)
|
||||
{
|
||||
callbacks->update(stub);
|
||||
}
|
||||
void operator()(code_block* stub) { callbacks->update(stub); }
|
||||
};
|
||||
|
||||
void callback_heap::update()
|
||||
{
|
||||
void callback_heap::update() {
|
||||
callback_updater updater(this);
|
||||
each_callback(updater);
|
||||
}
|
||||
|
||||
/* Allocates memory */
|
||||
void factor_vm::primitive_callback()
|
||||
{
|
||||
void factor_vm::primitive_callback() {
|
||||
cell return_rewind = to_cell(ctx->pop());
|
||||
tagged<word> w(ctx->pop());
|
||||
|
||||
w.untag_check(this);
|
||||
|
||||
void* func = callbacks->add(w.value(),return_rewind)->entry_point();
|
||||
void* func = callbacks->add(w.value(), return_rewind)->entry_point();
|
||||
CODE_TO_FUNCTION_POINTER_CALLBACK(this, func);
|
||||
ctx->push(allot_alien(func));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
/* The callback heap is used to store the machine code that alien-callbacks
|
||||
actually jump to when C code invokes them.
|
||||
|
@ -25,42 +24,38 @@ saving the image will deallocate any code heap entries that were only reachable
|
|||
from the callback heap in the previous session when the image was saved. */
|
||||
|
||||
struct callback_heap {
|
||||
segment *seg;
|
||||
segment* seg;
|
||||
cell here;
|
||||
factor_vm *parent;
|
||||
factor_vm* parent;
|
||||
|
||||
explicit callback_heap(cell size, factor_vm *parent);
|
||||
explicit callback_heap(cell size, factor_vm* parent);
|
||||
~callback_heap();
|
||||
|
||||
void *callback_entry_point(code_block *stub)
|
||||
{
|
||||
word *w = (word *)UNTAG(stub->owner);
|
||||
void* callback_entry_point(code_block* stub) {
|
||||
word* w = (word*)UNTAG(stub->owner);
|
||||
return w->entry_point;
|
||||
}
|
||||
|
||||
bool setup_seh_p();
|
||||
bool return_takes_param_p();
|
||||
instruction_operand callback_operand(code_block *stub, cell index);
|
||||
void store_callback_operand(code_block *stub, cell index);
|
||||
void store_callback_operand(code_block *stub, cell index, cell value);
|
||||
instruction_operand callback_operand(code_block* stub, cell index);
|
||||
void store_callback_operand(code_block* stub, cell index);
|
||||
void store_callback_operand(code_block* stub, cell index, cell value);
|
||||
|
||||
void update(code_block *stub);
|
||||
void update(code_block* stub);
|
||||
|
||||
code_block *add(cell owner, cell return_rewind);
|
||||
code_block* add(cell owner, cell return_rewind);
|
||||
|
||||
void update();
|
||||
|
||||
code_block *next(code_block *stub)
|
||||
{
|
||||
return (code_block *)((cell)stub + stub->size());
|
||||
code_block* next(code_block* stub) {
|
||||
return (code_block*)((cell) stub + stub->size());
|
||||
}
|
||||
|
||||
template<typename Iterator> void each_callback(Iterator &iter)
|
||||
{
|
||||
code_block *scan = (code_block *)seg->start;
|
||||
code_block *end = (code_block *)here;
|
||||
while(scan < end)
|
||||
{
|
||||
template <typename Iterator> void each_callback(Iterator& iter) {
|
||||
code_block* scan = (code_block*)seg->start;
|
||||
code_block* end = (code_block*)here;
|
||||
while (scan < end) {
|
||||
iter(scan);
|
||||
scan = next(scan);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue