Permalink
Browse files

Implement interpreter loop rather than indirect jumps

  • Loading branch information...
tadeuzagallo committed May 4, 2016
1 parent eed60f1 commit 1e4989ccf6d76a13c888a122be8c9b1f79ce99e3
Showing with 72 additions and 165 deletions.
  1. +71 −10 compiler/interpreter.S
  2. +1 −155 compiler/vm.cc
View
@@ -12,7 +12,7 @@
.macro skip
mov $0, %rax
lea (BYTECODE, %rax, 8), BYTECODE
jmp *(BYTECODE)
jmp _loop
.endmacro
.macro unmask
@@ -29,7 +29,7 @@
pop %r15
.endmacro
.globl _execute
.globl _execute
_execute:
push %rbp
push BYTECODE
@@ -39,9 +39,54 @@ _execute:
mov %rdi, BYTECODE
mov %rsi, STRINGS
mov %rdx, VM
jmp *(BYTECODE)
.globl _op_exit
_loop:
mov (BYTECODE), %rax // 0..10
lea (%rip), %rdi
lea 0x7(%rdi, %rax, 8), %rdi
jmp *%rdi
jmp _op_ret
nop
nop
nop
jmp _op_bind
nop
nop
nop
jmp _op_push
nop
nop
nop
jmp _op_call
nop
nop
nop
jmp _op_jz
nop
nop
nop
jmp _op_jmp
nop
nop
nop
jmp _op_create_closure
nop
nop
nop
jmp _op_load_string
nop
nop
nop
jmp _op_push_arg
nop
nop
nop
jmp _op_lookup
nop
nop
nop
jmp _op_exit
_op_exit:
mov %rbp, %rsp
pop VM
@@ -50,13 +95,11 @@ _op_exit:
pop %rbp
ret
.globl _op_push
_op_push:
read $1, %rdi
push %rdi
skip $2
.globl _op_lookup
_op_lookup:
mov VM, %rdi
read $1, %rsi
@@ -65,22 +108,22 @@ _op_lookup:
push %rax
skip $2
.globl _op_call
_op_call:
// pop the callee from the stack
pop %r8
// setup args
read $1, %rdi //argc
lea (%rsp, %rdi, 8), %rsi // argv
mov %rsp, %rsi // argv just live in the stack
mov VM, %rdx
// setup callee
pop %r8
unmask %r8
ccall *%r8
push %rax
skip $2
.globl _op_load_string
_op_load_string:
read $1, %rdi
mov (STRINGS, %rdi, 8), %rdi
@@ -89,3 +132,21 @@ _op_load_string:
ror $8, %rdi
push %rdi
skip $2
_op_create_closure:
hlt
_op_bind:
hlt
_op_jz:
hlt
_op_jmp:
hlt
_op_ret:
hlt
_op_push_arg:
hlt
View
@@ -5,12 +5,6 @@
#include <cassert>
extern "C" void op_push();
extern "C" void op_lookup();
extern "C" void op_call();
extern "C" void op_load_string();
extern "C" void op_exit();
namespace ceos {
extern "C" void execute(
@@ -64,7 +58,7 @@ uint64_t prepareClosure(unsigned argc, Value *args, Value fnAddress, VM *vm) {
loadFunctions();
break;
case Section::Text:
run();
::ceos::execute(m_bytecode + pc, m_stringTable.data(), this);
return;
default:
std::cerr << "Unknown section: `0x0" << std::hex << section << "`\n";
@@ -113,154 +107,6 @@ uint64_t prepareClosure(unsigned argc, Value *args, Value fnAddress, VM *vm) {
}
}
void VM::run() {
inflate();
::ceos::execute(m_bytecode + pc, m_stringTable.data(), this);
}
void VM::inflate() {
auto _pc = pc;
while (true) {
auto opcode = (int)read<uint64_t>();
if (pc > length) {
break;
}
#define LINK(opcode, argc) \
case Opcode:: opcode : \
*((uint64_t *)(m_bytecode + pc - 8)) = (uint64_t)op_##opcode; \
pc += argc * sizeof(uint64_t); \
break;
switch (opcode) {
LINK(push, 1)
LINK(lookup, 1)
LINK(call, 1)
LINK(load_string, 1)
LINK(exit, 0)
//LINK(bind, 0)
default:
std::cerr << "Unhandled opcode: " << Opcode::typeName(static_cast<Opcode::Type>(opcode)) << "\n";
throw;
}
}
pc = _pc;
}
//while (true) {
//auto opcode = read<int>();
//if (pc > length) {
//return;
//}
//switch (opcode) {
//case Opcode::push: {
//auto value = read<int>();
//stack_push(value);
//break;
//}
//case Opcode::call: {
//auto nargs = read<unsigned>();
//Value fn_address = stack_pop();
//stack_push(pc);
//stack_push(nargs);
//stack_push(ebp);
//ebp = esp;
//if (fn_address.isClosure()) {
//auto closure = fn_address.asClosure();
//m_scope = m_scope->create(closure->scope);
//for (unsigned i = 0; i < nargs; i++) {
//m_scope->set(closure->fn->arg(i), arg(i));
//}
//pc = closure->fn->offset;
//break;
//} else {
//m_scope = m_scope->create();
//Builtin fn = fn_address.asBuiltin();
//Value ret = fn(*this, nargs);
//stack_push(ret);
//}
//}
//case Opcode::ret: {
//Value ret = stack_pop();
//esp = ebp;
//ebp = stack_pop().asInt();
//unsigned nargs = stack_pop().asInt();
//auto ret_addr = stack_pop().asInt();
//esp -= nargs;
//stack_push(ret);
//pc = ret_addr;
//m_scope = m_scope->restore();
//break;
//}
//case Opcode::load_string: {
//auto stringID = read<int>();
//stack_push(Value(&m_stringTable[stringID]));
//break;
//}
//case Opcode::lookup: {
//auto id = read<int>();
//auto name = m_stringTable[id];
//auto value = m_scope->get(name);
//if (value.isUndefined()) {
//std::cerr << "Symbol not found: " << name << "\n";
//throw;
//}
//stack_push(value);
//break;
//}
//case Opcode::jmp: {
//auto target = read<int>();
//pc += target;
//break;
//}
//case Opcode::jz: {
//auto target = read<int>();
//int value = stack_pop().asInt();
//if (value == 0) {
//pc += target;
//}
//break;
//}
//case Opcode::push_arg: {
//auto index = read<int>();
//stack_push(arg(index));
//break;
//}
//case Opcode::create_closure: {
//auto fnID = read<int>();
//auto closure = new Closure();
//trackAllocation(closure, sizeof(Closure));
//closure->fn = &m_userFunctions[fnID];
//closure->scope = m_scope;
//stack_push(Value(closure));
//break;
//}
//case Opcode::bind: {
//auto address = stack_pop();
//auto closure = address.asClosure();
//m_scope->set(closure->fn->name(this), address);
//break;
//}
//default:
//std::cerr << "Unhandled opcode: " << Opcode::typeName(static_cast<Opcode::Type>(opcode)) << "\n";
//throw;
//}
//}
void VM::trackAllocation(void *ptr, size_t size) {
heapSize += size;

0 comments on commit 1e4989c

Please sign in to comment.