From 55b956916fe6449f3188846c7cee29a188c5eb4b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 8 Dec 2007 16:22:13 -0700 Subject: [PATCH] initial sketch of JIT compiler --- src/compile2.cpp | 2 +- src/compiler.cpp | 368 +++++++++++++++++++++++++++++++++++++++++++++++ src/compiler.h | 2 - 3 files changed, 369 insertions(+), 3 deletions(-) create mode 100644 src/compiler.cpp diff --git a/src/compile2.cpp b/src/compile2.cpp index 0892c380ea..4b302db6d9 100644 --- a/src/compile2.cpp +++ b/src/compile2.cpp @@ -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); diff --git a/src/compiler.cpp b/src/compiler.cpp new file mode 100644 index 0000000000..6cfdc0e106 --- /dev/null +++ b/src/compiler.cpp @@ -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(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(v)->call(a); + return operands.push(Register(rax)); + } + + virtual Operand* alignedCall(Operand* v) { + flushStack(); + static_cast(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(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(src)->mov(a, static_cast(dst)); + } + + virtual void cmp(Operand* subtrahend, Operand* minuend) { + static_cast(subtrahend)->mov + (a, static_cast(minuend)); + } + + virtual void jl(Operand* v) { + static_cast(v)->jl(a); + } + + virtual void jg(Operand* v) { + static_cast(v)->jg(a); + } + + virtual void jle(Operand* v) { + static_cast(v)->jle(a); + } + + virtual void jge(Operand* v) { + static_cast(v)->jge(a); + } + + virtual void je(Operand* v) { + static_cast(v)->je(a); + } + + virtual void jne(Operand* v) { + static_cast(v)->jne(a); + } + + virtual void jmp(Operand* v) { + static_cast(v)->jmp(a); + } + + virtual void add(Operand* v, Operand* dst) { + static_cast(v)->add(a, static_cast(dst)); + } + + virtual void sub(Operand* v, Operand* dst) { + static_cast(v)->sub(a, static_cast(dst)); + } + + virtual void mul(Operand* v, Operand* dst) { + static_cast(v)->mul(a, static_cast(dst)); + } + + virtual void div(Operand* v, Operand* dst) { + static_cast(v)->div(a, static_cast(dst)); + } + + virtual void rem(Operand* v, Operand* dst) { + static_cast(v)->rem(a, static_cast(dst)); + } + + virtual void shl(Operand* v, Operand* dst) { + static_cast(v)->shl(a, static_cast(dst)); + } + + virtual void shr(Operand* v, Operand* dst) { + static_cast(v)->shr(a, static_cast(dst)); + } + + virtual void ushr(Operand* v, Operand* dst) { + static_cast(v)->ushr(a, static_cast(dst)); + } + + virtual void and_(Operand* v, Operand* dst) { + static_cast(v)->and_(a, static_cast(dst)); + } + + virtual void or_(Operand* v, Operand* dst) { + static_cast(v)->or_(a, static_cast(dst)); + } + + virtual void xor_(Operand* v, Operand* dst) { + static_cast(v)->xor_(a, static_cast(dst)); + } + + virtual void neg(Operand* v) { + static_cast(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 diff --git a/src/compiler.h b/src/compiler.h index 565c10b256..579df891c9 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -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;