mirror of
https://github.com/corda/corda.git
synced 2025-01-22 12:28:11 +00:00
initial sketch of JIT compiler
This commit is contained in:
parent
22edd2e6a4
commit
55b956916f
@ -2834,7 +2834,7 @@ compile(MyThread* t, Compiler* c, object method)
|
||||
|
||||
unsigned footprint = methodParameterFootprint(t, method);
|
||||
unsigned locals = codeMaxLocals(t, code);
|
||||
c->reserve(locals > footprint ? locals - footprint : 0);
|
||||
c->sub(c->constant((locals - footprint) * BytesPerWord), c->stack());
|
||||
|
||||
Buffer objectPool(t->m->system, 256);
|
||||
Buffer traceLog(t->m->system, 1024);
|
||||
|
368
src/compiler.cpp
Normal file
368
src/compiler.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
#include "compiler.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
class MyPromise: public Promise {
|
||||
public:
|
||||
MyPromise(int value): resolved(false), value_(value) { }
|
||||
|
||||
virtual unsigned value(System* s) {
|
||||
assert(s, resolved);
|
||||
return value_;
|
||||
}
|
||||
|
||||
bool resolved;
|
||||
int value_;
|
||||
};
|
||||
|
||||
class MyCompiler: public Compiler {
|
||||
public:
|
||||
MyCompiler(System* s, void* indirectCaller):
|
||||
s(s), indirectCaller(reinterpret_cast<intptr_t>(indirectCaller))
|
||||
{ }
|
||||
|
||||
virtual Promise* poolOffset() {
|
||||
return promises.push(PoolPromise(constantPool.length() / BytesPerWord));
|
||||
}
|
||||
|
||||
virtual Promise* codeOffset() {
|
||||
return promises.push(CodePromise(code.length()));
|
||||
}
|
||||
|
||||
virtual Operand* poolAppend(Operand* v) {
|
||||
Operand* r = operands.push
|
||||
(PoolEntry(constantPool.length() / BytesPerWord));
|
||||
constantPool.push(v);
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual Operand* constant(intptr_t v) {
|
||||
return operands.push(Constant(v));
|
||||
}
|
||||
|
||||
virtual void push(Operand* v) {
|
||||
stack_.push(v);
|
||||
}
|
||||
|
||||
virtual void push2(Operand* v) {
|
||||
stack_.push(v);
|
||||
stack_.push(0);
|
||||
}
|
||||
|
||||
virtual Operand* stack(unsigned index) {
|
||||
return stack_.peek(stack.size() - index - 1);
|
||||
}
|
||||
|
||||
virtual Operand* stack2(unsigned index) {
|
||||
return stack_.peek(stack.size() - index - 1);
|
||||
}
|
||||
|
||||
virtual Operand* pop() {
|
||||
return stack_.pop();
|
||||
}
|
||||
|
||||
virtual Operand* pop2() {
|
||||
stack_.pop();
|
||||
return stack_.pop();
|
||||
}
|
||||
|
||||
virtual void pop(Operand* dst) {
|
||||
mov(stack_.pop(), dst);
|
||||
}
|
||||
|
||||
virtual void pop2(Operand* dst) {
|
||||
stack_.pop();
|
||||
mov(stack_.pop(), dst);
|
||||
}
|
||||
|
||||
virtual Operand* stack() {
|
||||
flushStack();
|
||||
return operands.push(Register(rsp));
|
||||
}
|
||||
|
||||
virtual Operand* base() {
|
||||
return operands.push(Register(rbp));
|
||||
}
|
||||
|
||||
virtual Operand* thread() {
|
||||
return operands.push(Register(rbx));
|
||||
}
|
||||
|
||||
virtual Operand* indirectTarget() {
|
||||
return operands.push(Register(rax));
|
||||
}
|
||||
|
||||
virtual Operand* temporary() {
|
||||
return registerPool.pop();
|
||||
}
|
||||
|
||||
virtual void release(Operand* v) {
|
||||
return registerPool.push(v);
|
||||
}
|
||||
|
||||
virtual Operand* label() {
|
||||
return operands.push(Label());
|
||||
}
|
||||
|
||||
virtual void mark(Operand* label) {
|
||||
setLabelValue(s, label, codeOffset());
|
||||
}
|
||||
|
||||
virtual Operand* call(Operand* v) {
|
||||
flushStack();
|
||||
static_cast<MyOperand*>(v)->call(a);
|
||||
return operands.push(Register(rax));
|
||||
}
|
||||
|
||||
virtual Operand* alignedCall(Operand* v) {
|
||||
flushStack();
|
||||
static_cast<MyOperand*>(v)->alignedCall(a);
|
||||
return operands.push(Register(rax));
|
||||
}
|
||||
|
||||
virtual Operand* indirectCall
|
||||
(Operand* address, unsigned argumentCount, ...)
|
||||
{
|
||||
va_list a; va_start(a, argumentCount);
|
||||
pushArguments(argumentCount, a);
|
||||
va_end(a);
|
||||
|
||||
mov(address, operands.push(Register(rax)));
|
||||
constant(indirectCaller)->call(a);
|
||||
|
||||
popArguments(argumentCount);
|
||||
}
|
||||
|
||||
virtual Operand* indirectCallNoReturn
|
||||
(Operand* address, unsigned argumentCount, ...)
|
||||
{
|
||||
va_list a; va_start(a, argumentCount);
|
||||
pushArguments(argumentCount, a);
|
||||
va_end(a);
|
||||
|
||||
mov(address, operands.push(Register(rax)));
|
||||
constant(indirectCaller)->call(a);
|
||||
}
|
||||
|
||||
virtual Operand* directCall
|
||||
(Operand* address, unsigned argumentCount, ...)
|
||||
{
|
||||
va_list a; va_start(a, argumentCount);
|
||||
pushArguments(argumentCount, a);
|
||||
va_end(a);
|
||||
|
||||
static_cast<MyOperand*>(address)->call(a);
|
||||
|
||||
popArguments(argumentCount);
|
||||
}
|
||||
|
||||
virtual void return_(Operand* v) {
|
||||
mov(v, operands.push(Register(rax)));
|
||||
a->ret();
|
||||
}
|
||||
|
||||
virtual void ret() {
|
||||
a->ret();
|
||||
}
|
||||
|
||||
virtual void mov(Operand* src, Operand* dst) {
|
||||
static_cast<MyOperand>(src)->mov(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void cmp(Operand* subtrahend, Operand* minuend) {
|
||||
static_cast<MyOperand>(subtrahend)->mov
|
||||
(a, static_cast<MyOperand>(minuend));
|
||||
}
|
||||
|
||||
virtual void jl(Operand* v) {
|
||||
static_cast<MyOperand>(v)->jl(a);
|
||||
}
|
||||
|
||||
virtual void jg(Operand* v) {
|
||||
static_cast<MyOperand>(v)->jg(a);
|
||||
}
|
||||
|
||||
virtual void jle(Operand* v) {
|
||||
static_cast<MyOperand>(v)->jle(a);
|
||||
}
|
||||
|
||||
virtual void jge(Operand* v) {
|
||||
static_cast<MyOperand>(v)->jge(a);
|
||||
}
|
||||
|
||||
virtual void je(Operand* v) {
|
||||
static_cast<MyOperand>(v)->je(a);
|
||||
}
|
||||
|
||||
virtual void jne(Operand* v) {
|
||||
static_cast<MyOperand>(v)->jne(a);
|
||||
}
|
||||
|
||||
virtual void jmp(Operand* v) {
|
||||
static_cast<MyOperand>(v)->jmp(a);
|
||||
}
|
||||
|
||||
virtual void add(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->add(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void sub(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->sub(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void mul(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->mul(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void div(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->div(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void rem(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->rem(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void shl(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->shl(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void shr(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->shr(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void ushr(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->ushr(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void and_(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->and_(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void or_(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->or_(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void xor_(Operand* v, Operand* dst) {
|
||||
static_cast<MyOperand>(v)->xor_(a, static_cast<MyOperand>(dst));
|
||||
}
|
||||
|
||||
virtual void neg(Operand* v) {
|
||||
static_cast<MyOperand>(v)->neg(a);
|
||||
}
|
||||
|
||||
virtual Operand* memory(Operand* base) {
|
||||
return operands.push(Memory(base, 0, 0, 1));
|
||||
}
|
||||
|
||||
virtual Operand* memory(Operand* base, unsigned displacement) {
|
||||
return operands.push(Memory(base, displacement, 0, 1));
|
||||
}
|
||||
|
||||
virtual Operand* memory(Operand* base, unsigned displacement,
|
||||
Operand* index, unsigned scale)
|
||||
{
|
||||
return operands.push(Memory(base, displacement, index, scale));
|
||||
}
|
||||
|
||||
virtual Operand* select1(Operand* v) {
|
||||
return operands.push(Selection(S1Selection, v));
|
||||
}
|
||||
|
||||
virtual Operand* select2(Operand* v) {
|
||||
return operands.push(Selection(S2Selection, v));
|
||||
}
|
||||
|
||||
virtual Operand* select2z(Operand* v) {
|
||||
return operands.push(Selection(Z2Selection, v));
|
||||
}
|
||||
|
||||
virtual Operand* select4(Operand* v) {
|
||||
return operands.push(Selection(S4Selection, v));
|
||||
}
|
||||
|
||||
virtual Operand* select8(Operand* v) {
|
||||
return operands.push(Selection(S8Selection, v));
|
||||
}
|
||||
|
||||
virtual void prologue() {
|
||||
a->push(rbp);
|
||||
a->mov(rsp, rbp);
|
||||
}
|
||||
|
||||
virtual void epilogue() {
|
||||
a->mov(rbp, rsp);
|
||||
a->pop(rbp);
|
||||
}
|
||||
|
||||
virtual void startLogicalIp(unsigned v) {
|
||||
ipTable.append(IpMapping(v, code.length()));
|
||||
}
|
||||
|
||||
virtual Operand* logicalIp(unsigned v) {
|
||||
return operands.push(Label(promises.push(IpPromise(v))));
|
||||
}
|
||||
|
||||
virtual unsigned logicalIpToOffset(unsigned ip) {
|
||||
unsigned bottom = 0;
|
||||
unsigned top = ipTable.size();
|
||||
for (unsigned span = top - bottom; span; span = top - bottom) {
|
||||
unsigned middle = bottom + (span / 2);
|
||||
IpMapping* mapping = ipTable.get(middle);
|
||||
|
||||
if (ip == mapping->ip) {
|
||||
return mapping->offset;
|
||||
} else if (ip < mapping->ip) {
|
||||
top = middle;
|
||||
} else if (ip > mapping->ip) {
|
||||
bottom = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
abort(s);
|
||||
}
|
||||
|
||||
virtual unsigned size() {
|
||||
return code.length();
|
||||
}
|
||||
|
||||
virtual void writeTo(void* out) {
|
||||
// todo
|
||||
}
|
||||
|
||||
virtual void updateCall(void* returnAddress, void* newTarget);
|
||||
|
||||
virtual void dispose() {
|
||||
promises.dispose();
|
||||
constantPool.dispose();
|
||||
registerPool.dispose();
|
||||
ipTable.dispose();
|
||||
operands.dispose();
|
||||
code.dispose();
|
||||
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
System* s;
|
||||
Stack code;
|
||||
Stack operands;
|
||||
Stack ipTable;
|
||||
Stack constantPool;
|
||||
Stack registerPool;
|
||||
Stack promises;
|
||||
intptr_t indirectCaller;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Compiler*
|
||||
makeCompiler(System* system, void* indirectCaller)
|
||||
{
|
||||
return new (system->allocate(sizeof(MyCompiler)))
|
||||
MyCompiler(system, indirectCaller);
|
||||
}
|
||||
|
||||
} // namespace vm
|
@ -89,8 +89,6 @@ class Compiler {
|
||||
virtual Operand* select4(Operand*) = 0;
|
||||
virtual Operand* select8(Operand*) = 0;
|
||||
|
||||
virtual void reserve(unsigned) = 0;
|
||||
|
||||
virtual void prologue() = 0;
|
||||
virtual void epilogue() = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user