From 5b2f351f01e37bc3d31fbbc13c1cc12d1db2ba70 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 11 Feb 2008 10:21:41 -0700 Subject: [PATCH] adapt compile.cpp to new compiler --- makefile | 7 +- src/assembler.h | 177 +++ src/compile.cpp | 1939 +++++++++++------------- src/compiler.cpp | 3672 +++++++++++++++------------------------------ src/compiler.h | 176 +-- src/compiler2.cpp | 1482 ------------------ src/compiler2.h | 98 -- src/heap.cpp | 2 +- src/x86.cpp | 4 + 9 files changed, 2277 insertions(+), 5280 deletions(-) create mode 100644 src/assembler.h delete mode 100644 src/compiler2.cpp delete mode 100644 src/compiler2.h diff --git a/makefile b/makefile index e4d31bfe01..d82fd03411 100644 --- a/makefile +++ b/makefile @@ -151,7 +151,9 @@ vm-depends = \ $(src)/jnienv.h \ $(src)/machine.h \ $(src)/util.h \ - $(src)/zone.h + $(src)/zone.h \ + $(src)/assembler.h \ + $(src)/compiler.h vm-sources = \ $(src)/$(system).cpp \ @@ -162,7 +164,8 @@ vm-sources = \ $(src)/$(process).cpp \ $(src)/builtin.cpp \ $(src)/jnienv.cpp \ - $(src)/process.cpp + $(src)/process.cpp \ + $(src)/$(asm).cpp vm-asm-sources = $(src)/$(asm).S diff --git a/src/assembler.h b/src/assembler.h new file mode 100644 index 0000000000..a8e85c0388 --- /dev/null +++ b/src/assembler.h @@ -0,0 +1,177 @@ +#ifndef ASSEMBLER_H +#define ASSEMBLER_H + +#include "system.h" +#include "zone.h" + +namespace vm { + +enum Operation { + Return +}; + +enum UnaryOperation { + Call, + Push, + JumpIfLess, + JumpIfGreater, + JumpIfLessOrEqual, + JumpIfGreaterOrEqual, + JumpIfEqual, + JumpIfNotEqual, + Jump, + Negate +}; + +enum BinaryOperation { + LoadAddress, + Move, + Store1, + Store2, + Store4, + Store8, + Load1, + Load2, + Load2z, + Load4, + Load8, + Load4To8, + Compare, + Add, + Subtract, + Multiply, + Divide, + Remainder, + ShiftLeft, + ShiftRight, + UnsignedShiftRight, + And, + Or, + Xor +}; + +enum OperandType { + Constant, + Address, + Register, + Memory +}; + +const int NoRegister = -1; +const int AnyRegister = -2; + +class Promise { + public: + virtual ~Promise() { } + + virtual int64_t value() = 0; + virtual bool resolved() = 0; +}; + +class ResolvedPromise: public Promise { + public: + ResolvedPromise(int64_t value): value_(value) { } + + virtual int64_t value() { + return value_; + } + + virtual bool resolved() { + return true; + } + + int64_t value_; +}; + +class TraceHandler { + public: + virtual ~TraceHandler() { } + + virtual void handleTrace(Promise* address) = 0; +}; + +class Assembler { + public: + class Operand { }; + + class Constant: public Operand { + public: + Constant(Promise* value): value(value) { } + + Promise* value; + }; + + class Address: public Operand { + public: + Address(Promise* address): address(address) { } + + Promise* address; + }; + + class Register: public Operand { + public: + Register(int low, int high = NoRegister): low(low), high(high) { } + + int low; + int high; + }; + + class Memory: public Operand { + public: + Memory(int base, int offset, int index = NoRegister, unsigned scale = 0, + TraceHandler* traceHandler = 0): + base(base), offset(offset), index(index), scale(scale), + traceHandler(traceHandler) + { } + + int base; + int offset; + int index; + unsigned scale; + TraceHandler* traceHandler; + }; + + virtual ~Assembler() { } + + virtual unsigned registerCount() = 0; + + virtual int base() = 0; + virtual int stack() = 0; + virtual int thread() = 0; + virtual int returnLow() = 0; + virtual int returnHigh() = 0; + + virtual unsigned argumentRegisterCount() = 0; + virtual int argumentRegister(unsigned index) = 0; + + virtual int stackSyncRegister(unsigned index) = 0; + + virtual void getTargets(UnaryOperation op, unsigned size, + Register* a) = 0; + + virtual void getTargets(BinaryOperation op, unsigned size, + Register* a, Register* b) = 0; + + virtual void apply(Operation op) = 0; + + virtual void apply(UnaryOperation op, unsigned size, OperandType type, + Operand* operand) = 0; + + virtual void apply(BinaryOperation op, unsigned size, OperandType aType, + Operand* a, OperandType bType, Operand* b) = 0; + + virtual void writeTo(uint8_t* dst) = 0; + + virtual unsigned length() = 0; + + virtual void updateCall(void* returnAddress, void* newTarget) = 0; + + virtual void dispose() = 0; +}; + +Assembler* +makeAssembler(System* system, Allocator* allocator, Zone* zone); + +} // namespace vm + +#endif//ASSEMBLER_H diff --git a/src/compile.cpp b/src/compile.cpp index 91fe83ce81..2673f1b4cd 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2,7 +2,8 @@ #include "util.h" #include "vector.h" #include "process.h" -#include "compiler.h" +#include "assembler.h" +#include "compiler2.h" #include "x86.h" using namespace vm; @@ -272,7 +273,7 @@ class PoolElement { class Context; -class TraceElement: public Compiler::TraceHandler { +class TraceElement: public TraceHandler { public: TraceElement(Context* context, object target, bool virtualCall, TraceElement* next): @@ -297,76 +298,6 @@ class TraceElement: public Compiler::TraceHandler { uintptr_t map[0]; }; -inline Stack* -push(Compiler* c, Stack* s, Operand* v) -{ - if (BytesPerWord == 8) { - return c->push8(s, v); - } else { - return c->push4(s, v); - } -} - -inline Stack* -pop(Compiler* c, Stack* s, Operand* v) -{ - if (BytesPerWord == 8) { - return c->pop8(s, v); - } else { - return c->pop4(s, v); - } -} - -inline void -mov(Compiler* c, Operand* src, Operand* dst) -{ - if (BytesPerWord == 8) { - c->mov8(src, dst); - } else { - c->mov4(src, dst); - } -} - -inline Operand* -result(Compiler* c) -{ - if (BytesPerWord == 8) { - return c->result8(); - } else { - return c->result4(); - } -} - -inline void -returnW(Compiler* c, Operand* v) -{ - if (BytesPerWord == 8) { - c->return8(v); - } else { - c->return4(v); - } -} - -inline void -cmp(Compiler* c, Operand* src, Operand* dst) -{ - if (BytesPerWord == 8) { - c->cmp8(src, dst); - } else { - c->cmp4(src, dst); - } -} - -inline void -and_(Compiler* c, Operand* src, Operand* dst) -{ - if (BytesPerWord == 8) { - c->and8(src, dst); - } else { - c->and4(src, dst); - } -} - enum Event { PushEvent, PopEvent, @@ -394,13 +325,6 @@ frameSize(MyThread* t, object method) return localSize(t, method) + codeMaxStack(t, methodCode(t, method)); } -unsigned -stackMapSizeInWords(MyThread* t, object method) -{ - return ceiling(codeMaxStack(t, methodCode(t, method)), BitsPerWord) - * BytesPerWord; -} - unsigned frameMapSizeInWords(MyThread* t, object method) { @@ -431,7 +355,7 @@ class Context { public: class MyProtector: public Thread::Protector { public: - MyProtector(Context* c): Protector(c->t), c(c) { } + MyProtector(Context* c): Protector(c->thread), c(c) { } virtual void visit(Heap::Visitor* v) { v->visit(&(c->method)); @@ -448,11 +372,13 @@ class Context { Context* c; }; - Context(MyThread* t, object method, uint8_t* indirectCaller): - t(t), + Context(MyThread* t, object method, void* indirection): + thread(t), zone(t->m->system, t->m->heap, false, 16 * 1024), - c(makeCompiler(t->m->system, t->m->heap, &zone, indirectCaller)), + assembler(makeAssembler(t->m->system, t->m->heap, &zone)), + compiler(makeCompiler(t->m->system, assembler, &zone)), method(method), + indirection(indirection), objectPool(0), traceLog(0), visitTable(makeVisitTable(t, &zone, method)), @@ -462,10 +388,12 @@ class Context { { } Context(MyThread* t): - t(t), + thread(t), zone(t->m->system, t->m->heap, false, LikelyPageSizeInBytes), - c(makeCompiler(t->m->system, t->m->heap, &zone, 0)), + assembler(makeAssembler(t->m->system, t->m->heap, &zone)), + compiler(0), method(0), + indirection(0), objectPool(0), traceLog(0), visitTable(0), @@ -475,13 +403,16 @@ class Context { { } ~Context() { - c->dispose(); + compiler->dispose(); + assembler->dispose(); } - MyThread* t; + MyThread* thread; Zone zone; - Compiler* c; + Assembler* assembler; + Compiler* compiler; object method; + void* indirection; PoolElement* objectPool; TraceElement* traceLog; uint16_t* visitTable; @@ -492,32 +423,37 @@ class Context { class Frame { public: - Frame(Context* context, uintptr_t* stackMap): + enum StackType { + Integer, + Long, + Object + }; + + Frame(Context* context, uint8_t* stackMap): context(context), - t(context->t), - c(context->c), - stack(0), + t(context->thread), + c(context->compiler), stackMap(stackMap), ip(0), sp(localSize()), level(0) { - memset(stackMap, 0, - stackMapSizeInWords(t, context->method) * BytesPerWord); + memset(stackMap, 0, codeMaxStack(t, methodCode(t, context->method))); } - Frame(Frame* f, uintptr_t* stackMap): + Frame(Frame* f, uint8_t* stackMap): context(f->context), - t(context->t), - c(context->c), - stack(f->stack), + t(context->thread), + c(context->compiler), stackMap(stackMap), ip(f->ip), sp(f->sp), level(f->level + 1) { - memcpy(stackMap, f->stackMap, - stackMapSizeInWords(t, context->method) * BytesPerWord); + c->pushState(); + + memcpy(stackMap, f->stackMap, codeMaxStack + (t, methodCode(t, context->method))); if (level > 1) { context->eventLog.append(PushEvent); @@ -526,16 +462,18 @@ class Frame { ~Frame() { if (level > 1 and t->exception == 0) { + c->popState(); + context->eventLog.append(PopEvent); } } - Operand* append(object o) { + Compiler::Operand* append(object o) { Promise* p = c->poolAppend(0); context->objectPool = new (context->zone.allocate(sizeof(PoolElement))) PoolElement(o, p, context->objectPool); - return c->absolute(p); + return c->address(p); } unsigned localSize() { @@ -550,53 +488,51 @@ class Frame { return localSize() + stackSize(); } - void mark(unsigned index) { + void set(unsigned index, uint8_t type) { assert(t, index < frameSize()); - context->eventLog.append(MarkEvent); - context->eventLog.append2(index); + if (type == Object) { + context->eventLog.append(MarkEvent); + context->eventLog.append2(index); + } else { + context->eventLog.append(ClearEvent); + context->eventLog.append2(index); + } int si = index - localSize(); if (si >= 0) { - markBit(stackMap, si); + stackMap[si] = type; } } - void clear(unsigned index) { - assert(t, index < frameSize()); - - context->eventLog.append(ClearEvent); - context->eventLog.append2(index); - - int si = index - localSize(); - if (si >= 0) { - clearBit(stackMap, si); - } - } - - unsigned get(unsigned index) { + uint8_t get(unsigned index) { assert(t, index < frameSize()); int si = index - localSize(); assert(t, si >= 0); - return getBit(stackMap, si); + return stackMap[si]; } void pushedInt() { assert(t, sp + 1 <= frameSize()); - assert(t, get(sp) == 0); - ++ sp; + set(sp++, Integer); + } + + void pushedLong() { + assert(t, sp + 2 <= frameSize()); + set(sp++, Long); + set(sp++, Long); } void pushedObject() { assert(t, sp + 1 <= frameSize()); - mark(sp++); + set(sp++, Object); } void popped(unsigned count) { assert(t, sp >= count); assert(t, sp - count >= localSize()); while (count) { - clear(-- sp); + set(--sp, Integer); -- count; } } @@ -604,55 +540,57 @@ class Frame { void poppedInt() { assert(t, sp >= 1); assert(t, sp - 1 >= localSize()); - assert(t, get(sp - 1) == 0); + assert(t, get(sp - 1) == Integer); -- sp; } + void poppedLong() { + assert(t, sp >= 1); + assert(t, sp - 2 >= localSize()); + assert(t, get(sp - 1) == Long); + assert(t, get(sp - 2) == Long); + sp -= 2; + } + void poppedObject() { assert(t, sp >= 1); assert(t, sp - 1 >= localSize()); - assert(t, get(sp - 1) != 0); - clear(-- sp); + assert(t, get(sp - 1) == Object); + set(--sp, Integer); } void storedInt(unsigned index) { assert(t, index < localSize()); - clear(index); + set(index, Integer); + } + + void storedLong(unsigned index) { + assert(t, index + 1 < localSize()); + set(index, Long); + set(index + 1, Long); } void storedObject(unsigned index) { assert(t, index < localSize()); - mark(index); + set(index, Object); } void dupped() { assert(t, sp + 1 <= frameSize()); assert(t, sp - 1 >= localSize()); - if (get(sp - 1)) { - mark(sp); - } - ++ sp; + set(sp++, get(sp - 1)); } void duppedX1() { assert(t, sp + 1 <= frameSize()); assert(t, sp - 2 >= localSize()); - unsigned b2 = get(sp - 2); - unsigned b1 = get(sp - 1); + uint8_t b2 = get(sp - 2); + uint8_t b1 = get(sp - 1); - if (b2) { - mark(sp - 1); - } else { - clear(sp - 1); - } - - if (b1) { - mark(sp - 2); - mark(sp); - } else { - clear(sp - 2); - } + set(sp - 1, b2); + set(sp - 2, b1); + set(sp , b1); ++ sp; } @@ -661,28 +599,14 @@ class Frame { assert(t, sp + 1 <= frameSize()); assert(t, sp - 3 >= localSize()); - unsigned b3 = get(sp - 3); - unsigned b2 = get(sp - 2); - unsigned b1 = get(sp - 1); + uint8_t b3 = get(sp - 3); + uint8_t b2 = get(sp - 2); + uint8_t b1 = get(sp - 1); - if (b3) { - mark(sp - 2); - } else { - clear(sp - 2); - } - - if (b2) { - mark(sp - 1); - } else { - clear(sp - 1); - } - - if (b1) { - mark(sp - 3); - mark(sp); - } else { - clear(sp - 3); - } + set(sp - 2, b3); + set(sp - 1, b2); + set(sp - 3, b1); + set(sp , b1); ++ sp; } @@ -691,16 +615,11 @@ class Frame { assert(t, sp + 2 <= frameSize()); assert(t, sp - 2 >= localSize()); - unsigned b2 = get(sp - 2); - unsigned b1 = get(sp - 1); + uint8_t b2 = get(sp - 2); + uint8_t b1 = get(sp - 1); - if (b2) { - mark(sp); - } - - if (b1) { - mark(sp + 1); - } + set(sp, b2); + set(sp + 1, b1); sp += 2; } @@ -709,29 +628,15 @@ class Frame { assert(t, sp + 2 <= frameSize()); assert(t, sp - 3 >= localSize()); - unsigned b3 = get(sp - 3); - unsigned b2 = get(sp - 2); - unsigned b1 = get(sp - 1); + uint8_t b3 = get(sp - 3); + uint8_t b2 = get(sp - 2); + uint8_t b1 = get(sp - 1); - if (b3) { - mark(sp - 1); - } else { - clear(sp - 1); - } - - if (b2) { - mark(sp - 3); - mark(sp); - } else { - clear(sp - 3); - } - - if (b1) { - mark(sp - 2); - mark(sp + 1); - } else { - clear(sp - 2); - } + set(sp - 1, b3); + set(sp - 3, b2); + set(sp , b2); + set(sp - 2, b1); + set(sp + 1, b1); sp += 2; } @@ -740,36 +645,17 @@ class Frame { assert(t, sp + 2 <= frameSize()); assert(t, sp - 4 >= localSize()); - unsigned b4 = get(sp - 4); - unsigned b3 = get(sp - 3); - unsigned b2 = get(sp - 2); - unsigned b1 = get(sp - 1); + uint8_t b4 = get(sp - 4); + uint8_t b3 = get(sp - 3); + uint8_t b2 = get(sp - 2); + uint8_t b1 = get(sp - 1); - if (b4) { - mark(sp - 2); - } else { - clear(sp - 2); - } - - if (b3) { - mark(sp - 1); - } else { - clear(sp - 1); - } - - if (b2) { - mark(sp - 4); - mark(sp); - } else { - clear(sp - 4); - } - - if (b1) { - mark(sp - 3); - mark(sp + 1); - } else { - clear(sp - 3); - } + set(sp - 2, b4); + set(sp - 1, b3); + set(sp - 4, b2); + set(sp , b2); + set(sp - 3, b1); + set(sp + 1, b1); sp += 2; } @@ -777,21 +663,13 @@ class Frame { void swapped() { assert(t, sp - 2 >= localSize()); - bool savedBit = get(sp - 1); - if (get(sp - 2)) { - mark(sp - 1); - } else { - clear(sp - 1); - } + uint8_t saved = get(sp - 1); - if (savedBit) { - mark(sp - 2); - } else { - clear(sp - 2); - } + set(sp - 1, get(sp - 2)); + set(sp - 2, saved); } - Operand* machineIp(unsigned logicalIp) { + Compiler::Operand* machineIp(unsigned logicalIp) { return c->promiseConstant(c->machineIp(logicalIp)); } @@ -805,184 +683,103 @@ class Frame { this->ip = ip; } - void topIntToLong() { - dup(); - if (BytesPerWord == 4) { - c->mov4To8(c->stack(stack, 0), c->stack(stack, 0)); - } - } - - void topLongToInt() { - mov(c, c->stack(stack, 0), c->stack(stack, 1)); - stack = c->pop(stack, 1); - poppedInt(); - } - - void pushInt(Operand* o) { - stack = push(c, stack, o); + void pushInt(Compiler::Operand* o) { + c->push(o); pushedInt(); } - void pushInt1(Operand* o) { - stack = c->push1(stack, o); + void pushAddress(Compiler::Operand* o) { + c->push(o); pushedInt(); } - void pushInt2(Operand* o) { - stack = c->push2(stack, o); - pushedInt(); - } - - void pushInt2z(Operand* o) { - stack = c->push2z(stack, o); - pushedInt(); - } - - void pushInt4(Operand* o) { - stack = c->push4(stack, o); - pushedInt(); - } - - void pushAddress(Operand* o) { - stack = push(c, stack, o); - pushedInt(); - } - - void pushObject(Operand* o) { - stack = push(c, stack, o); + void pushObject(Compiler::Operand* o) { + c->push(o); pushedObject(); } void pushObject() { - stack = c->pushed(stack, 1); + c->push(1); pushedObject(); } - void pushLong(Operand* o) { + void pushLong(Compiler::Operand* o) { if (BytesPerWord == 8) { - stack = c->push(stack, 1); + c->push(1); } - stack = c->push8(stack, o); + c->push(o); - pushedInt(); - pushedInt(); + pushedLong(); } void pop(unsigned count) { popped(count); - stack = c->pop(stack, count); + c->pop(count); } - Operand* topInt() { - assert(t, sp >= 1); - assert(t, sp - 1 >= localSize()); - assert(t, get(sp - 1) == 0); - return c->stack(stack, 0); - } - - Operand* topLong() { - assert(t, sp >= 2); - assert(t, sp - 2 >= localSize()); - assert(t, get(sp - 1) == 0); - assert(t, get(sp - 2) == 0); - return c->stack(stack, 0); - } - - Operand* topObject() { - assert(t, sp >= 1); - assert(t, sp - 1 >= localSize()); - assert(t, get(sp - 1) != 0); - return c->stack(stack, 0); - } - - Operand* popInt() { - Operand* tmp = c->temporary(); - popInt(tmp); - return tmp; - } - - Operand* popInt4() { - Operand* tmp = c->temporary(); - popInt4(tmp); - return tmp; - } - - Operand* popLong() { - Operand* tmp = c->temporary(); - popLong(tmp); - return tmp; - } - - Operand* popObject() { - Operand* tmp = c->temporary(); - popObject(tmp); - return tmp; - } - - void popInt(Operand* o) { - stack = ::pop(c, stack, o); + Compiler::Operand* popInt() { poppedInt(); + return c->pop(); } - void popInt4(Operand* o) { - stack = c->pop4(stack, o); - poppedInt(); + Compiler::Operand* popLong() { + poppedLong(); + return c->pop(); } - void popLong(Operand* o) { - stack = c->pop8(stack, o); - if (BytesPerWord == 8) { - stack = c->pop(stack, 1); - } - - poppedInt(); - poppedInt(); - } - - void popObject(Operand* o) { - stack = ::pop(c, stack, o); + Compiler::Operand* popObject() { poppedObject(); + return c->pop(); } void loadInt(unsigned index) { assert(t, index < localSize()); - pushInt(c->memory(c->base(), localOffset(t, index, context->method))); + pushInt + (c->load4(c->memory(c->base(), localOffset(t, index, context->method)))); } void loadLong(unsigned index) { - assert(t, index < static_cast - (localSize() - 1)); - pushLong(c->memory(c->base(), localOffset(t, index + 1, context->method))); + assert(t, index < static_cast(localSize() - 1)); + pushLong + (c->load8 + (c->memory(c->base(), localOffset(t, index + 1, context->method)))); } void loadObject(unsigned index) { assert(t, index < localSize()); - pushObject(c->memory(c->base(), localOffset(t, index, context->method))); + pushObject + (c->load + (c->memory(c->base(), localOffset(t, index, context->method)))); } void storeInt(unsigned index) { - popInt(c->memory(c->base(), localOffset(t, index, context->method))); + c->store4 + (popInt(), c->memory(c->base(), localOffset(t, index, context->method))); storedInt(index); } void storeLong(unsigned index) { - popLong(c->memory(c->base(), localOffset(t, index + 1, context->method))); - storedInt(index); - storedInt(index + 1); + c->store8 + (popLong(), c->memory + (c->base(), localOffset(t, index + 1, context->method))); + storedLong(index); } void storeObject(unsigned index) { - popObject(c->memory(c->base(), localOffset(t, index, context->method))); + c->store + (popObject(), c->memory + (c->base(), localOffset(t, index, context->method))); storedObject(index); } void storeObjectOrAddress(unsigned index) { - stack = ::pop - (c, stack, c->memory(c->base(), localOffset(t, index, context->method))); + c->store + (c->pop(), c->memory + (c->base(), localOffset(t, index, context->method))); assert(t, sp >= 1); assert(t, sp - 1 >= localSize()); - if (get(sp - 1)) { + if (get(sp - 1) == Object) { storedObject(index); } else { storedInt(index); @@ -992,65 +789,122 @@ class Frame { } void dup() { - stack = push(c, stack, c->stack(stack, 0)); + Compiler::Operand* s0 = c->pop(); + + c->push(s0); + c->push(s0); + dupped(); } void dupX1() { - stack = push(c, stack, c->stack(stack, 0)); - mov(c, c->stack(stack, 2), c->stack(stack, 1)); - mov(c, c->stack(stack, 0), c->stack(stack, 2)); + Compiler::Operand* s0 = c->pop(); + Compiler::Operand* s1 = c->pop(); + + c->push(s0); + c->push(s1); + c->push(s0); duppedX1(); } void dupX2() { - stack = push(c, stack, c->stack(stack, 0)); - mov(c, c->stack(stack, 2), c->stack(stack, 1)); - mov(c, c->stack(stack, 3), c->stack(stack, 2)); - mov(c, c->stack(stack, 0), c->stack(stack, 3)); + Compiler::Operand* s0 = c->pop(); + Compiler::Operand* s1 = c->pop(); + + if (get(sp - 2) == Long) { + c->push(s0); + c->push(s1); + c->push(s0); + } else { + Compiler::Operand* s2 = c->pop(); + + c->push(s0); + c->push(s2); + c->push(s1); + c->push(s0); + } duppedX2(); } void dup2() { - stack = push(c, stack, c->stack(stack, 1)); - stack = push(c, stack, c->stack(stack, 1)); + Compiler::Operand* s0 = c->pop(); + + if (get(sp - 1) == Long) { + c->push(s0); + c->push(s0); + } else { + Compiler::Operand* s1 = c->pop(); + + c->push(s1); + c->push(s0); + c->push(s1); + c->push(s0); + } dupped2(); } void dup2X1() { - stack = push(c, stack, c->stack(stack, 1)); - stack = push(c, stack, c->stack(stack, 1)); - mov(c, c->stack(stack, 4), c->stack(stack, 2)); - mov(c, c->stack(stack, 1), c->stack(stack, 4)); - mov(c, c->stack(stack, 0), c->stack(stack, 3)); + Compiler::Operand* s0 = c->pop(); + Compiler::Operand* s1 = c->pop(); + + if (get(sp - 1) == Long) { + c->push(s0); + c->push(s1); + c->push(s0); + } else { + Compiler::Operand* s2 = c->pop(); + + c->push(s1); + c->push(s0); + c->push(s2); + c->push(s1); + c->push(s0); + } dupped2X1(); } void dup2X2() { - stack = push(c, stack, c->stack(stack, 1)); - stack = push(c, stack, c->stack(stack, 1)); - mov(c, c->stack(stack, 5), c->stack(stack, 3)); - mov(c, c->stack(stack, 4), c->stack(stack, 2)); - mov(c, c->stack(stack, 1), c->stack(stack, 5)); - mov(c, c->stack(stack, 0), c->stack(stack, 4)); + Compiler::Operand* s0 = c->pop(); + Compiler::Operand* s1 = c->pop(); + + if (get(sp - 1) == Long) { + if (get(sp - 3) == Long) { + c->push(s0); + c->push(s1); + c->push(s0); + } else { + Compiler::Operand* s2 = c->pop(); + + c->push(s0); + c->push(s2); + c->push(s1); + c->push(s0); + } + } else { + Compiler::Operand* s2 = c->pop(); + Compiler::Operand* s3 = c->pop(); + + c->push(s1); + c->push(s0); + c->push(s3); + c->push(s2); + c->push(s1); + c->push(s0); + } dupped2X2(); } void swap() { - Operand* s0 = c->stack(stack, 0); - Operand* s1 = c->stack(stack, 1); - Operand* tmp = c->temporary(); + Compiler::Operand* s0 = c->pop(); + Compiler::Operand* s1 = c->pop(); - mov(c, s0, tmp); - mov(c, s1, s0); - mov(c, tmp, s1); - - c->release(tmp); + c->push(s0); + c->push(s1); swapped(); } @@ -1071,8 +925,7 @@ class Frame { Context* context; MyThread* t; Compiler* c; - Stack* stack; - uintptr_t* stackMap; + uint8_t* stackMap; unsigned ip; unsigned sp; unsigned level; @@ -1524,38 +1377,27 @@ checkCast(MyThread* t, object class_, object o) } } -void -pushReturnValue(MyThread* t, Frame* frame, unsigned code) +unsigned +resultSize(MyThread* t, unsigned code) { - Compiler* c = frame->c; - switch (code) { case ByteField: case BooleanField: case CharField: case ShortField: case FloatField: - case IntField: { - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); - } break; + case IntField: + return 4; - case ObjectField: { - Operand* result = ::result(c); - frame->pushObject(result); - c->release(result); - } break; + case ObjectField: + return BytesPerWord; case LongField: - case DoubleField: { - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); - } break; + case DoubleField: + return 8; case VoidField: - break; + return 0; default: abort(t); @@ -1567,15 +1409,21 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) { Compiler* c = frame->c; - c->alignedCall + Compiler::Operand* result = c->call (c->constant (reinterpret_cast (&singletonBody(t, methodCompiled(t, target), 0))), - frame->trace(target, false)); + 0, + Compiler::Aligned, + frame->trace(target, false), + resultSize(t, methodReturnCode(t, target)), + 0); - frame->pop(methodParameterFootprint(t, target)); + c->pop(methodParameterFootprint(t, target)); - pushReturnValue(t, frame, methodReturnCode(t, target)); + if (methodReturnCode(t, target) != VoidField) { + c->push(result); + } } void @@ -1585,7 +1433,7 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) object method = frame->context->method; if (methodFlags(t, method) & ACC_SYNCHRONIZED) { - Operand* lock; + Compiler::Operand* lock; if (methodFlags(t, method) & ACC_STATIC) { lock = frame->append(methodClass(t, method)); } else { @@ -1593,10 +1441,12 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) (c->base(), localOffset(t, savedTargetIndex(t, method), method)); } - c->indirectCall - (c->constant(function), - frame->trace(0, false), - 2, c->thread(), lock); + c->call(c->constant(function), + frame->context->indirection, + 0, + frame->trace(0, false), + 0, + 2, c->thread(), lock); } } @@ -1612,9 +1462,9 @@ handleEntrance(MyThread* t, Frame* frame) // save 'this' pointer in case it is overwritten. unsigned index = savedTargetIndex(t, method); - mov(c, c->memory(c->base(), localOffset(t, 0, method)), - c->memory(c->base(), localOffset(t, index, method))); - frame->mark(index); + c->store(c->memory(c->base(), localOffset(t, 0, method)), + c->memory(c->base(), localOffset(t, index, method))); + frame->set(index, Frame::Object); } handleMonitorEvent @@ -1631,7 +1481,8 @@ handleExit(MyThread* t, Frame* frame) void compile(MyThread* t, Frame* initialFrame, unsigned ip) { - uintptr_t stackMap[stackMapSizeInWords(t, initialFrame->context->method)]; + uint8_t stackMap + [codeMaxStack(t, methodCode(t, initialFrame->context->method))]; Frame myFrame(initialFrame, stackMap); Frame* frame = &myFrame; Compiler* c = frame->c; @@ -1663,25 +1514,28 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case iaload: case laload: case saload: { - Operand* index = frame->popInt4(); - Operand* array = frame->popObject(); + Compiler::Operand* index = frame->popInt(); + Compiler::Operand* array = frame->popObject(); if (CheckArrayBounds) { - Operand* load = c->label(); - Operand* throw_ = c->label(); + Compiler::Operand* load = c->label(); + Compiler::Operand* throw_ = c->label(); - c->cmp4(c->constant(0), index); + c->cmp(c->constant(0), index); c->jl(throw_); - c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), - index); + c->cmp(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), + index); c->jl(load); c->mark(throw_); - c->indirectCallNoReturn + c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), + context->indirection, + Compiler::NoReturn, frame->trace(0, false), + 0, 3, c->thread(), array, index); c->mark(load); @@ -1690,34 +1544,31 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (instruction) { case aaload: frame->pushObject - (c->memory(array, ArrayBody, index, BytesPerWord)); + (c->load(c->memory(array, ArrayBody, index, BytesPerWord))); break; case faload: case iaload: - frame->pushInt4(c->memory(array, ArrayBody, index, 4)); + frame->pushInt(c->load4(c->memory(array, ArrayBody, index, 4))); break; case baload: - frame->pushInt1(c->memory(array, ArrayBody, index, 1)); + frame->pushInt(c->load1(c->memory(array, ArrayBody, index, 1))); break; case caload: - frame->pushInt2z(c->memory(array, ArrayBody, index, 2)); + frame->pushInt(c->load2z(c->memory(array, ArrayBody, index, 2))); break; case daload: case laload: - frame->pushLong(c->memory(array, ArrayBody, index, 8)); + frame->pushLong(c->load8(c->memory(array, ArrayBody, index, 8))); break; case saload: - frame->pushInt2(c->memory(array, ArrayBody, index, 2)); + frame->pushInt(c->load2(c->memory(array, ArrayBody, index, 2))); break; } - - c->release(index); - c->release(array); } break; case aastore: @@ -1728,7 +1579,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case iastore: case lastore: case sastore: { - Operand* value; + Compiler::Operand* value; if (instruction == dastore or instruction == lastore) { value = frame->popLong(); } else if (instruction == aastore) { @@ -1737,25 +1588,28 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) value = frame->popInt(); } - Operand* index = frame->popInt4(); - Operand* array = frame->popObject(); + Compiler::Operand* index = frame->popInt(); + Compiler::Operand* array = frame->popObject(); if (CheckArrayBounds) { - Operand* store = c->label(); - Operand* throw_ = c->label(); + Compiler::Operand* store = c->label(); + Compiler::Operand* throw_ = c->label(); - c->cmp4(c->constant(0), index); + c->cmp(c->constant(0), index); c->jl(throw_); - c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), - index); + c->cmp(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), + index); c->jl(store); c->mark(throw_); - c->indirectCallNoReturn + c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), + context->indirection, + Compiler::NoReturn, frame->trace(0, false), + 0, 3, c->thread(), array, index); c->mark(store); @@ -1763,38 +1617,37 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (instruction) { case aastore: { - c->shl4(c->constant(log(BytesPerWord)), index); - c->add4(c->constant(ArrayBody), index); - - c->indirectCall + c->call (c->constant(reinterpret_cast(setMaybeNull)), + context->indirection, + 0, frame->trace(0, false), - 4, c->thread(), array, index, value); + 0, + 4, c->thread(), array, + c->add(c->constant(ArrayBody), + c->shl(c->constant(log(BytesPerWord)), index)), + value); } break; case fastore: case iastore: - c->mov4(value, c->memory(array, ArrayBody, index, 4)); + c->store4(value, c->memory(array, ArrayBody, index, 4)); break; case bastore: - c->mov1(value, c->memory(array, ArrayBody, index, 1)); + c->store1(value, c->memory(array, ArrayBody, index, 1)); break; case castore: case sastore: - c->mov2(value, c->memory(array, ArrayBody, index, 2)); + c->store2(value, c->memory(array, ArrayBody, index, 2)); break; case dastore: case lastore: - c->mov8(value, c->memory(array, ArrayBody, index, 8)); + c->store8(value, c->memory(array, ArrayBody, index, 8)); break; } - - c->release(value); - c->release(index); - c->release(array); } break; case aconst_null: @@ -1827,44 +1680,45 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Operand* nonnegative = c->label(); + Compiler::Operand* nonnegative = c->label(); - Operand* length = frame->popInt4(); - c->cmp4(c->constant(0), length); + Compiler::Operand* length = frame->popInt(); + c->cmp(c->constant(0), length); c->jge(nonnegative); - c->indirectCallNoReturn + c->push(length); + c->push(c->thread()); + + c->call (c->constant(reinterpret_cast(throwNegativeArraySize)), + context->indirection, + Compiler::NoReturn, frame->trace(0, false), + 0, 2, c->thread(), length); c->mark(nonnegative); - c->indirectCall - (c->constant(reinterpret_cast(makeBlankObjectArray)), - frame->trace(0, false), - 3, c->thread(), frame->append(class_), length); - - Operand* result = ::result(c); - - c->release(length); - - frame->pushObject(result); - c->release(result); + frame->pushObject + (c->call + (c->constant(reinterpret_cast(makeBlankObjectArray)), + context->indirection, + 0, + frame->trace(0, false), + BytesPerWord, + 3, c->thread(), frame->append(class_), length)); } break; case areturn: { handleExit(t, frame); - Operand* result = frame->popObject(); - returnW(c, result); - c->release(result); + c->return_(frame->popObject()); } return; case arraylength: { - Operand* array = frame->popObject(); - frame->pushInt4 - (c->memory(array, ArrayLength, 0, 1, frame->trace(0, false))); - c->release(array); + frame->pushInt + (c->load + (c->memory + (frame->popObject(), ArrayLength, 0, 1, frame->trace(0, false)))); } break; case astore: @@ -1888,12 +1742,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case athrow: { - Operand* e = frame->popObject(); - c->indirectCallNoReturn + c->call (c->constant(reinterpret_cast(throw_)), + context->indirection, + Compiler::NoReturn, frame->trace(0, false), - 2, c->thread(), e); - c->release(e); + 0, + 2, c->thread(), frame->popObject()); } return; case bipush: @@ -1907,173 +1762,121 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Operand* instance = frame->topObject(); + Compiler::Operand* instance = c->peek(0); - Operand* classOperand = frame->append(class_); - - c->indirectCall + c->call (c->constant(reinterpret_cast(checkCast)), + context->indirection, + 0, frame->trace(0, false), - 3, c->thread(), classOperand, instance); + 0, + 3, c->thread(), frame->append(class_), instance); } break; case d2f: { - Operand* a = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(doubleToFloat)), 2, 0, a); - c->release(a); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(doubleToFloat)), + 0, 0, 0, 4, 1, frame->popLong())); } break; case d2i: { - Operand* a = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(doubleToInt)), 2, 0, a); - c->release(a); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(doubleToInt)), + 0, 0, 0, 4, 1, frame->popLong())); } break; case d2l: { - Operand* a = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(doubleToLong)), 2, 0, a); - c->release(a); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(doubleToLong)), + 0, 0, 0, 8, 1, frame->popLong())); } break; case dadd: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(addDouble)), 4, 0, a, 0, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(doubleToInt)), + 0, 0, 0, 8, 2, a, b)); } break; case dcmpg: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(compareDoublesG)), - 4, 0, a, 0, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(compareDoublesG)), + 0, 0, 0, 4, 2, a, b)); } break; case dcmpl: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); - c->directCall - (c->constant(reinterpret_cast(compareDoublesL)), - 4, 0, a, 0, b); - c->release(a); - c->release(b); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(compareDoublesL)), + 0, 0, 0, 4, 2, a, b)); } break; case dconst_0: - frame->pushLong(c->constant(doubleToBits(0.0))); + frame->pushLong(c->constant8(doubleToBits(0.0))); break; case dconst_1: - frame->pushLong(c->constant(doubleToBits(1.0))); + frame->pushLong(c->constant8(doubleToBits(1.0))); break; case ddiv: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(divideDouble)), - 4, 0, a, 0, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(divideDouble)), + 0, 0, 0, 8, 2, a, b)); } break; case dmul: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(multiplyDouble)), - 4, 0, a, 0, b); - c->release(a); - c->release(b); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + + frame->pushLong + (c->call + (c->constant(reinterpret_cast(multiplyDouble)), + 0, 0, 0, 8, 2, a, b)); } break; case dneg: { - Operand* a = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(negateDouble)), 2, 0, a); - c->release(a); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(negateDouble)), + 0, 0, 0, 8, 1, frame->popLong())); } break; case vm::drem: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(moduloDouble)), 4, 0, a, 0, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(moduloDouble)), + 0, 0, 0, 8, 2, a, b)); } break; case dsub: { - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(subtractDouble)), - 4, 0, a, 0, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(subtractDouble)), + 0, 0, 0, 8, 2, a, b)); } break; case dup: @@ -2101,81 +1904,54 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case f2d: { - Operand* a = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(floatToDouble)), 1, a); - c->release(a); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(floatToDouble)), + 0, 0, 0, 8, 1, frame->popInt())); } break; case f2i: { - Operand* a = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(floatToInt)), 1, a); - c->release(a); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(floatToInt)), + 0, 0, 0, 4, 1, frame->popInt())); } break; case f2l: { - Operand* a = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(floatToLong)), 1, a); - c->release(a); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(floatToLong)), + 0, 0, 0, 8, 1, frame->popInt())); } break; case fadd: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(addFloat)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(addFloat)), + 0, 0, 0, 4, 2, a, b)); } break; case fcmpg: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(compareFloatsG)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(compareFloatsG)), + 0, 0, 0, 4, 2, a, b)); } break; case fcmpl: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(compareFloatsL)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(compareFloatsL)), + 0, 0, 0, 4, 2, a, b)); } break; case fconst_0: @@ -2191,71 +1967,50 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case fdiv: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(divideFloat)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(divideFloat)), + 0, 0, 0, 4, 2, a, b)); } break; case fmul: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(multiplyFloat)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(multiplyFloat)), + 0, 0, 0, 4, 2, a, b)); } break; case fneg: { - Operand* a = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(negateFloat)), 1, a); - c->release(a); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(negateFloat)), + 0, 0, 0, 4, 1, frame->popInt())); } break; case vm::frem: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(moduloFloat)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(moduloFloat)), + 0, 0, 0, 4, 2, a, b)); } break; case fsub: { - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(subtractFloat)), 2, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(subtractFloat)), + 0, 0, 0, 4, 2, a, b)); } break; case getfield: @@ -2265,12 +2020,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Operand* table; + Compiler::Operand* table; if (instruction == getstatic) { - c->indirectCall + c->call (c->constant(reinterpret_cast(tryInitClass)), + context->indirection, + 0, frame->trace(0, false), + 0, 2, c->thread(), frame->append(fieldClass(t, field))); table = frame->append(classStaticTable(t, fieldClass(t, field))); @@ -2286,44 +2044,40 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - frame->pushInt1 - (c->memory(table, fieldOffset(t, field), 0, 1, trace)); + frame->pushInt + (c->load1(c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case CharField: - frame->pushInt2z - (c->memory(table, fieldOffset(t, field), 0, 1, trace)); + frame->pushInt + (c->load2z(c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case ShortField: - frame->pushInt2 - (c->memory(table, fieldOffset(t, field), 0, 1, trace)); + frame->pushInt + (c->load2(c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case FloatField: case IntField: - frame->pushInt4 - (c->memory(table, fieldOffset(t, field), 0, 1, trace)); + frame->pushInt + (c->load4(c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case DoubleField: case LongField: frame->pushLong - (c->memory(table, fieldOffset(t, field), 0, 1, trace)); + (c->load8(c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case ObjectField: frame->pushObject - (c->memory(table, fieldOffset(t, field), 0, 1, trace)); + (c->load(c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; default: abort(t); } - - if (instruction == getfield) { - c->release(table); - } } break; case goto_: { @@ -2343,58 +2097,45 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case i2b: { - Operand* top = frame->topInt(); - c->mov1ToW(top, top); + frame->pushInt(c->load1(frame->popInt())); } break; case i2c: { - Operand* top = frame->topInt(); - c->mov2zToW(top, top); + frame->pushInt(c->load2z(frame->popInt())); } break; case i2d: { - Operand* a = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(intToDouble)), 1, a); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); - c->release(a); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(intToDouble)), + 0, 0, 0, 8, 1, frame->popInt())); } break; case i2f: { - Operand* a = frame->popInt(); - - c->directCall - (c->constant(reinterpret_cast(intToFloat)), 1, a); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); - c->release(a); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(intToFloat)), + 0, 0, 0, 4, 1, frame->popInt())); } break; case i2l: - frame->topIntToLong(); + frame->pushLong(c->load4To8(frame->popInt())); break; case i2s: { - Operand* top = frame->topInt(); - c->mov2ToW(top, top); + frame->pushInt(c->load2(frame->popInt())); } break; case iadd: { - Operand* a = frame->popInt(); - c->add4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->add(a, b)); } break; case iand: { - Operand* a = frame->popInt(); - c->and4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->and_(a, b)); } break; case iconst_m1: @@ -2426,9 +2167,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case idiv: { - Operand* a = frame->popInt(); - c->div4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->div(a, b)); } break; case if_acmpeq: @@ -2436,13 +2177,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - Operand* a = frame->popObject(); - Operand* b = frame->popObject(); - cmp(c, a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popObject(); + Compiler::Operand* b = frame->popObject(); + Compiler::Operand* target = frame->machineIp(newIp); - Operand* target = frame->machineIp(newIp); + c->cmp(a, b); if (instruction == if_acmpeq) { c->je(target); } else { @@ -2462,13 +2201,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - Operand* a = frame->popInt(); - Operand* b = frame->popInt(); - c->cmp4(a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + Compiler::Operand* target = frame->machineIp(newIp); - Operand* target = frame->machineIp(newIp); + c->cmp(a, b); switch (instruction) { case if_icmpeq: c->je(target); @@ -2503,11 +2240,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - Operand* a = frame->popInt(); - c->cmp4(c->constant(0), a); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* target = frame->machineIp(newIp); - Operand* target = frame->machineIp(newIp); + c->cmp(c->constant(0), a); switch (instruction) { case ifeq: c->je(target); @@ -2538,11 +2274,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - Operand* a = frame->popObject(); - cmp(c, c->constant(0), a); - c->release(a); + Compiler::Operand* a = frame->popObject(); + Compiler::Operand* target = frame->machineIp(newIp); - Operand* target = frame->machineIp(newIp); + c->cmp(c->constant(0), a); if (instruction == ifnull) { c->je(target); } else { @@ -2557,8 +2292,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint8_t index = codeBody(t, code, ip++); int8_t count = codeBody(t, code, ip++); - c->add4(c->constant(count), - c->memory(c->base(), localOffset(t, index, context->method))); + Compiler::Operand* a = c->memory + (c->base(), localOffset(t, index, context->method)); + + c->store(c->add(c->constant(count), a), a); } break; case iload: @@ -2587,13 +2324,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case imul: { - Operand* a = frame->popInt(); - c->mul4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->mul(a, b)); } break; case ineg: { - c->neg4(frame->topInt()); + frame->pushInt(c->neg(frame->popInt())); } break; case instanceof: { @@ -2602,18 +2339,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Operand* instance = frame->popObject(); - - Operand* classOperand = frame->append(class_); - - c->directCall + frame->pushInt + (c->call (c->constant(reinterpret_cast(instanceOf)), - 3, c->thread(), classOperand, instance); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); - c->release(instance); + 0, 0, 0, 4, + 3, c->thread(), frame->append(class_), frame->popObject())); } break; case invokeinterface: { @@ -2627,20 +2357,27 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) unsigned instance = parameterFootprint - 1; - c->indirectCall + Compiler::Operand* result = c->call + (c->call (c->constant (reinterpret_cast(findInterfaceMethodFromInstance)), + context->indirection, + 0, frame->trace(0, false), + BytesPerWord, 3, c->thread(), frame->append(target), - c->stack(frame->stack, instance)); - - Operand* result = ::result(c); - c->call(result, frame->trace(target, true)); - c->release(result); + c->peek(instance)), + 0, + 0, + frame->trace(target, true), + resultSize(t, methodReturnCode(t, target)), + 0); frame->pop(parameterFootprint); - pushReturnValue(t, frame, methodReturnCode(t, target)); + if (methodReturnCode(t, target) != VoidField) { + c->push(result); + } } break; case invokespecial: { @@ -2676,51 +2413,54 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) unsigned offset = ClassVtable + (methodOffset(t, target) * BytesPerWord); - Operand* instance = c->stack(frame->stack, parameterFootprint - 1); - Operand* class_ = c->temporary(); - - mov(c, c->memory(instance, 0, 0, 1, frame->trace(0, false)), class_); - and_(c, c->constant(PointerMask), class_); + Compiler::Operand* instance = c->peek(parameterFootprint - 1); - c->call(c->memory(class_, offset, 0, 1), frame->trace(target, true)); - - c->release(class_); + Compiler::Operand* result = c->call + (c->memory + (c->and_ + (c->constant(PointerMask), c->memory + (instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1), + 0, + 0, + frame->trace(0, true), + resultSize(t, methodReturnCode(t, target)), + 0); frame->pop(parameterFootprint); - pushReturnValue(t, frame, methodReturnCode(t, target)); + if (methodReturnCode(t, target) != VoidField) { + c->push(result); + } } break; case ior: { - Operand* a = frame->popInt(); - c->or4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->or_(a, b)); } break; case irem: { - Operand* a = frame->popInt(); - c->rem4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->rem(a, b)); } break; case ireturn: case freturn: { handleExit(t, frame); - Operand* a = frame->popInt(); - c->return4(a); - c->release(a); + c->return_(frame->popInt()); } return; case ishl: { - Operand* a = frame->popInt(); - c->shl4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->shl(a, b)); } break; case ishr: { - Operand* a = frame->popInt(); - c->shr4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->shr(a, b)); } break; case istore: @@ -2749,21 +2489,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case isub: { - Operand* a = frame->popInt(); - c->sub4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->sub(a, b)); } break; case iushr: { - Operand* a = frame->popInt(); - c->ushr4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->ushr(a, b)); } break; case ixor: { - Operand* a = frame->popInt(); - c->xor4(a, frame->topInt()); - c->release(a); + Compiler::Operand* a = frame->popInt(); + Compiler::Operand* b = frame->popInt(); + frame->pushInt(c->xor_(a, b)); } break; case jsr: @@ -2790,59 +2530,54 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case l2i: - frame->topLongToInt(); + frame->pushInt(c->load4(frame->popLong())); break; case ladd: { - Operand* a = frame->popLong(); - c->add8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->add(a, b)); } break; case land: { - Operand* a = frame->popLong(); - c->and8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->and_(a, b)); } break; case lcmp: { - Operand* next = c->label(); - Operand* less = c->label(); - Operand* greater = c->label(); + Compiler::Operand* next = c->label(); + Compiler::Operand* less = c->label(); + Compiler::Operand* greater = c->label(); - Operand* a = frame->popLong(); - Operand* b = frame->popLong(); - Operand* result = c->temporary(); - - c->cmp8(a, b); - c->release(a); - c->release(b); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + c->cmp(a, b); c->jl(less); c->jg(greater); - c->mov4(c->constant(0), result); + c->push(c->constant(0)); c->jmp(next); c->mark(less); - c->mov4(c->constant(-1), result); + c->push(c->constant(-1)); c->jmp(next); c->mark(greater); - c->mov4(c->constant(1), result); + c->push(c->constant(1)); c->mark(next); - frame->pushInt(result); - c->release(result); + frame->pushedInt(); } break; case lconst_0: - frame->pushLong(c->constant(0)); + frame->pushLong(c->constant8(0)); break; case lconst_1: - frame->pushLong(c->constant(1)); + frame->pushLong(c->constant8(1)); break; case ldc: @@ -2881,13 +2616,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint64_t v; memcpy(&v, &singletonValue(t, pool, index - 1), 8); - frame->pushLong(c->constant(v)); + frame->pushLong(c->constant8(v)); } break; case ldiv_: { - Operand* a = frame->popLong(); - c->div8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->div(a, b)); } break; case lload: @@ -2916,13 +2651,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case lmul: { - Operand* a = frame->popLong(); - c->mul8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->mul(a, b)); } break; case lneg: - c->neg8(frame->topLong()); + frame->pushLong(c->neg(frame->popLong())); break; case lookupswitch: { @@ -2930,17 +2665,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) ip = (ip + 3) & ~3; // pad to four byte boundary - Operand* key = frame->popInt4(); + Compiler::Operand* key = frame->popInt(); uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); - Operand* default_ = c->absolute + Compiler::Operand* default_ = c->address (c->poolAppendPromise(c->machineIp(defaultIp))); int32_t pairCount = codeReadInt32(t, code, ip); - Operand* start = 0; + Compiler::Operand* start = 0; uint32_t ipTable[pairCount]; for (int32_t i = 0; i < pairCount; ++i) { unsigned index = ip + (i * 8); @@ -2958,15 +2693,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } assert(t, start); - c->directCall - (c->constant(reinterpret_cast(lookUpAddress)), - 4, key, start, c->constant(pairCount), default_); - - Operand* result = ::result(c); - c->jmp(result); - c->release(result); - - c->release(key); + c->jmp + (c->call + (c->constant(reinterpret_cast(lookUpAddress)), + 0, 0, 0, BytesPerWord, + 4, key, start, c->constant(pairCount), default_)); for (int32_t i = 0; i < pairCount; ++i) { compile(t, frame, ipTable[i]); @@ -2977,35 +2708,33 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case lor: { - Operand* a = frame->popLong(); - c->or8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->or_(a, b)); } break; case lrem: { - Operand* a = frame->popLong(); - c->rem8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->rem(a, b)); } break; case lreturn: case dreturn: { handleExit(t, frame); - Operand* a = frame->popLong(); - c->return8(a); - c->release(a); + c->return_(frame->popLong()); } return; case lshl: { - Operand* a = frame->popInt(); - c->shl8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->shl(a, b)); } break; case lshr: { - Operand* a = frame->popInt(); - c->shr8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->shr(a, b)); } break; case lstore: @@ -3034,39 +2763,35 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case lsub: { - Operand* a = frame->popLong(); - c->sub8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->sub(a, b)); } break; case lushr: { - Operand* a = frame->popInt(); - c->ushr8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->ushr(a, b)); } break; case lxor: { - Operand* a = frame->popLong(); - c->xor8(a, frame->topLong()); - c->release(a); + Compiler::Operand* a = frame->popLong(); + Compiler::Operand* b = frame->popLong(); + frame->pushLong(c->xor_(a, b)); } break; case monitorenter: { - Operand* a = frame->popObject(); - c->indirectCall + c->call (c->constant(reinterpret_cast(acquireMonitorForObject)), - frame->trace(0, false), - 2, c->thread(), a); - c->release(a); + context->indirection, + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case monitorexit: { - Operand* a = frame->popObject(); - c->indirectCall + c->call (c->constant(reinterpret_cast(releaseMonitorForObject)), - frame->trace(0, false), - 2, c->thread(), a); - c->release(a); + context->indirection, + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case multianewarray: { @@ -3077,22 +2802,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (UNLIKELY(t->exception)) return; PROTECT(t, class_); - Operand* stack = c->temporary(); - mov(c, c->stack(), stack); - - c->indirectCall + Compiler::Operand* result = c->call (c->constant(reinterpret_cast(makeMultidimensionalArray)), + context->indirection, + 0, frame->trace(0, false), - 4, c->thread(), frame->append(class_), stack, + BytesPerWord, + 4, c->thread(), frame->append(class_), c->load(c->stack()), c->constant(dimensions)); - - c->release(stack); - - Operand* result = ::result(c); frame->pop(dimensions); frame->pushObject(result); - c->release(result); } break; case new_: { @@ -3102,35 +2822,42 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (UNLIKELY(t->exception)) return; if (classVmFlags(t, class_) & WeakReferenceFlag) { - c->indirectCall - (c->constant(reinterpret_cast(makeNewWeakReference)), - frame->trace(0, false), - 2, c->thread(), frame->append(class_)); + frame->pushObject + (c->call + (c->constant(reinterpret_cast(makeNewWeakReference)), + context->indirection, + 0, + frame->trace(0, false), + BytesPerWord, + 2, c->thread(), frame->append(class_))); } else { - c->indirectCall - (c->constant(reinterpret_cast(makeNew)), - frame->trace(0, false), - 2, c->thread(), frame->append(class_)); + frame->pushObject + (c->call + (c->constant(reinterpret_cast(makeNew)), + context->indirection, + 0, + frame->trace(0, false), + BytesPerWord, + 2, c->thread(), frame->append(class_))); } - - Operand* result = ::result(c); - frame->pushObject(result); - c->release(result); } break; case newarray: { uint8_t type = codeBody(t, code, ip++); - Operand* nonnegative = c->label(); + Compiler::Operand* nonnegative = c->label(); - Operand* length = frame->popInt4(); - c->cmp4(c->constant(0), length); + Compiler::Operand* length = frame->popInt(); + c->cmp(c->constant(0), length); c->jge(nonnegative); - c->indirectCallNoReturn + c->call (c->constant(reinterpret_cast(throwNegativeArraySize)), + context->indirection, + Compiler::NoReturn, frame->trace(0, false), + 0, 2, c->thread(), length); c->mark(nonnegative); @@ -3172,18 +2899,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) default: abort(t); } - c->indirectCall - (c->constant(reinterpret_cast(makeBlankArray)), - frame->trace(0, false), - 3, c->thread(), c->constant(reinterpret_cast(constructor)), - length); - - Operand* result = ::result(c); - - c->release(length); - - frame->pushObject(result); - c->release(result); + frame->pushObject + (c->call + (c->constant(reinterpret_cast(makeBlankArray)), + context->indirection, + 0, + frame->trace(0, false), + BytesPerWord, + 2, c->thread(), c->constant(reinterpret_cast(constructor)), + length)); } break; case nop: break; @@ -3206,15 +2930,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object staticTable = 0; if (instruction == putstatic) { - c->indirectCall + c->call (c->constant(reinterpret_cast(tryInitClass)), + context->indirection, + 0, frame->trace(0, false), + 0, 2, c->thread(), frame->append(fieldClass(t, field))); staticTable = classStaticTable(t, fieldClass(t, field)); } - Operand* value; + Compiler::Operand* value; switch (fieldCode(t, field)) { case ByteField: case BooleanField: @@ -3237,7 +2964,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) default: abort(t); } - Operand* table; + Compiler::Operand* table; if (instruction == putstatic) { table = frame->append(staticTable); @@ -3253,44 +2980,43 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - c->mov1(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store1(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case CharField: case ShortField: - c->mov2(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store2(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case FloatField: case IntField: - c->mov4(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store4(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case DoubleField: case LongField: - c->mov8(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store8(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case ObjectField: if (instruction == putfield) { - c->indirectCall + c->call (c->constant(reinterpret_cast(setMaybeNull)), + context->indirection, + 0, frame->trace(0, false), + 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } else { - c->directCall + c->call (c->constant(reinterpret_cast(set)), + 0, 0, 0, 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } break; default: abort(t); } - - if (instruction == putfield) { - c->release(table); - } - c->release(value); } break; case ret: @@ -3302,8 +3028,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case return_: handleExit(t, frame); - c->epilogue(); - c->ret(); + c->return_(0); return; case sipush: @@ -3320,7 +3045,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) ip = (ip + 3) & ~3; // pad to four byte boundary - Operand* key = frame->popInt4(); + Compiler::Operand* key = frame->popInt(); uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); @@ -3328,7 +3053,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) int32_t bottom = codeReadInt32(t, code, ip); int32_t top = codeReadInt32(t, code, ip); - Operand* start = 0; + Compiler::Operand* start = 0; uint32_t ipTable[top - bottom + 1]; for (int32_t i = 0; i < top - bottom + 1; ++i) { unsigned index = ip + (i * 4); @@ -3344,22 +3069,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } assert(t, start); - Operand* defaultCase = c->label(); + Compiler::Operand* defaultCase = c->label(); - c->cmp4(c->constant(bottom), key); + c->cmp(c->constant(bottom), key); c->jl(defaultCase); - c->cmp4(c->constant(top), key); + c->cmp(c->constant(top), key); c->jg(defaultCase); - c->sub4(c->constant(bottom), key); + c->sub(c->constant(bottom), key); c->jmp(c->memory(start, 0, key, BytesPerWord)); c->mark(defaultCase); c->jmp(frame->machineIp(defaultIp)); - c->release(key); - for (int32_t i = 0; i < top - bottom + 1; ++i) { compile(t, frame, ipTable[i]); if (UNLIKELY(t->exception)) return; @@ -3382,8 +3105,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint16_t index = codeReadInt16(t, code, ip); uint16_t count = codeReadInt16(t, code, ip); - c->add4(c->constant(count), - c->memory(c->base(), localOffset(t, index, context->method))); + Compiler::Operand* a = c->memory + (c->base(), localOffset(t, index, context->method)); + + c->store(c->add(c->constant(count), a), a); } break; case iload: { @@ -3445,13 +3170,13 @@ updateExceptionHandlerTable(MyThread* t, Compiler* c, object code, (t, newTable, i); exceptionHandlerStart(newHandler) - = c->machineIp(exceptionHandlerStart(oldHandler))->value(c) - start; + = c->machineIp(exceptionHandlerStart(oldHandler))->value() - start; exceptionHandlerEnd(newHandler) - = c->machineIp(exceptionHandlerEnd(oldHandler))->value(c) - start; + = c->machineIp(exceptionHandlerEnd(oldHandler))->value() - start; exceptionHandlerIp(newHandler) - = c->machineIp(exceptionHandlerIp(oldHandler))->value(c) - start; + = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; exceptionHandlerCatchType(newHandler) = exceptionHandlerCatchType(oldHandler); @@ -3477,7 +3202,7 @@ updateLineNumberTable(MyThread* t, Compiler* c, object code, LineNumber* newLine = lineNumberTableBody(t, newTable, i); lineNumberIp(newLine) - = c->machineIp(lineNumberIp(oldLine))->value(c) - start; + = c->machineIp(lineNumberIp(oldLine))->value() - start; lineNumberLine(newLine) = lineNumberLine(oldLine); } @@ -3668,11 +3393,9 @@ Allocator* codeAllocator(MyThread* t); object -finish(MyThread* t, Context* context, const char* name) +allocateCode(MyThread* t, unsigned codeSizeInBytes) { - Compiler* c = context->c; - - unsigned count = ceiling(c->codeSize() + c->poolSize(), BytesPerWord); + unsigned count = ceiling(codeSizeInBytes, BytesPerWord); unsigned size = count + singletonMaskSize(count); object result = allocate3 (t, codeAllocator(t), Machine::ImmortalAllocation, @@ -3680,71 +3403,88 @@ finish(MyThread* t, Context* context, const char* name) initSingleton(t, result, size, true); mark(t, result, 0); singletonMask(t, result)[0] = 1; + return result; +} + +object +finish(MyThread* t, Assembler* a, const char* name) +{ + object result = allocateCode(t, a->length()); + uint8_t* start = reinterpret_cast(&singletonValue(t, result, 0)); + + a->writeTo(start); + + logCompile(start, a->length(), 0, name, 0); + + return result; +} + +object +finish(MyThread* t, Context* context) +{ + Compiler* c = context->compiler; + + unsigned codeSize = c->compile(); + object result = allocateCode(t, codeSize + c->poolSize()); uint8_t* start = reinterpret_cast(&singletonValue(t, result, 0)); c->writeTo(start); - if (context->method) { - PROTECT(t, result); + PROTECT(t, result); - unsigned mapSize = frameMapSizeInWords(t, context->method); + unsigned mapSize = frameMapSizeInWords(t, context->method); - for (TraceElement* p = context->traceLog; p; p = p->next) { - object node = makeTraceNode - (t, p->address->value(c), 0, context->method, p->target, - p->virtualCall, mapSize, false); + for (TraceElement* p = context->traceLog; p; p = p->next) { + object node = makeTraceNode + (t, p->address->value(), 0, context->method, p->target, + p->virtualCall, mapSize, false); - if (mapSize) { - memcpy(&traceNodeMap(t, node, 0), p->map, mapSize * BytesPerWord); - } - - insertTraceNode(t, node); + if (mapSize) { + memcpy(&traceNodeMap(t, node, 0), p->map, mapSize * BytesPerWord); } - for (PoolElement* p = context->objectPool; p; p = p->next) { - intptr_t offset = p->address->value(c) - - reinterpret_cast(start); + insertTraceNode(t, node); + } - singletonMarkObject(t, result, offset / BytesPerWord); + for (PoolElement* p = context->objectPool; p; p = p->next) { + intptr_t offset = p->address->value() + - reinterpret_cast(start); - set(t, result, SingletonBody + offset, p->value); - } + singletonMarkObject(t, result, offset / BytesPerWord); - updateExceptionHandlerTable(t, c, methodCode(t, context->method), - reinterpret_cast(start)); + set(t, result, SingletonBody + offset, p->value); + } - updateLineNumberTable(t, c, methodCode(t, context->method), - reinterpret_cast(start)); + updateExceptionHandlerTable(t, c, methodCode(t, context->method), + reinterpret_cast(start)); - if (Verbose) { - logCompile - (start, c->codeSize(), - reinterpret_cast - (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - reinterpret_cast - (&byteArrayBody(t, methodName(t, context->method), 0)), - reinterpret_cast - (&byteArrayBody(t, methodSpec(t, context->method), 0))); - } + updateLineNumberTable(t, c, methodCode(t, context->method), + reinterpret_cast(start)); - // for debugging: - if (false and - strcmp - (reinterpret_cast - (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Misc") == 0 and - strcmp - (reinterpret_cast - (&byteArrayBody(t, methodName(t, context->method), 0)), - "main") == 0) - { - asm("int3"); - } - } else { - if (Verbose) { - logCompile(start, c->codeSize(), 0, name, 0); - } + if (Verbose) { + logCompile + (start, codeSize, + reinterpret_cast + (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), + reinterpret_cast + (&byteArrayBody(t, methodName(t, context->method), 0)), + reinterpret_cast + (&byteArrayBody(t, methodSpec(t, context->method), 0))); + } + + // for debugging: + if (false and + strcmp + (reinterpret_cast + (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), + "Misc") == 0 and + strcmp + (reinterpret_cast + (&byteArrayBody(t, methodName(t, context->method), 0)), + "main") == 0) + { + asm("int3"); } return result; @@ -3753,25 +3493,23 @@ finish(MyThread* t, Context* context, const char* name) object compile(MyThread* t, Context* context) { - Compiler* c = context->c; + Compiler* c = context->compiler; // fprintf(stderr, "compiling %s.%s%s\n", // &byteArrayBody(t, className(t, methodClass(t, context->method)), 0), // &byteArrayBody(t, methodName(t, context->method), 0), // &byteArrayBody(t, methodSpec(t, context->method), 0)); - c->prologue(); - unsigned footprint = methodParameterFootprint(t, context->method); unsigned locals = localSize(t, context->method); - c->reserve(locals - footprint); + c->init(codeLength(t, methodCode(t, context->method)), locals - footprint); - uintptr_t stackMap[stackMapSizeInWords(t, context->method)]; + uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))]; Frame frame(context, stackMap); unsigned index = 0; if ((methodFlags(t, context->method) & ACC_STATIC) == 0) { - frame.mark(index++); + frame.set(index++, Frame::Object); } for (MethodSpecIterator it @@ -3782,16 +3520,17 @@ compile(MyThread* t, Context* context) switch (*it.next()) { case 'L': case '[': - frame.mark(index++); + frame.set(index++, Frame::Object); break; case 'J': case 'D': - index += 2; + frame.set(index++, Frame::Long); + frame.set(index++, Frame::Long); break; default: - ++ index; + frame.set(index++, Frame::Integer); break; } } @@ -3823,7 +3562,7 @@ compile(MyThread* t, Context* context) visited[i] = true; progress = true; - uintptr_t stackMap[stackMapSizeInWords(t, context->method)]; + uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))]; Frame frame2(&frame, stackMap); uintptr_t* roots = context->rootTable @@ -3831,9 +3570,9 @@ compile(MyThread* t, Context* context) for (unsigned i = 0; i < localSize(t, context->method); ++ i) { if (getBit(roots, i)) { - frame2.mark(i); + frame2.set(i, Frame::Object); } else { - frame2.clear(i); + frame2.set(i, Frame::Integer); } } @@ -3843,7 +3582,7 @@ compile(MyThread* t, Context* context) i < codeMaxStack(t, methodCode(t, context->method)); ++i) { - frame2.clear(localSize(t, context->method) + i); + frame2.set(localSize(t, context->method) + i, Frame::Integer); } compile(t, &frame2, exceptionHandlerIp(eh)); @@ -3859,7 +3598,7 @@ compile(MyThread* t, Context* context) updateTraceElements(t, context, 0, 0); - return finish(t, context, 0); + return finish(t, context); } void @@ -3887,7 +3626,7 @@ compileMethod2(MyThread* t) } else { if (not traceNodeVirtualCall(t, node)) { Context context(t); - context.c->updateCall + context.assembler->updateCall (reinterpret_cast(traceNodeAddress(t, node)), &singletonValue(t, methodCompiled(t, target), 0)); } @@ -4183,39 +3922,60 @@ visitStack(MyThread* t, Heap::Visitor* v) } } -object -compileDefault(MyThread* t, Context* context) +void +saveStackAndBase(MyThread* t, Assembler* a) { - Compiler* c = context->c; + Assembler::Register base(a->base()); + Assembler::Memory baseDst(a->thread(), difference(&(t->base), t)); + a->apply(Move, BytesPerWord, Register, &base, Memory, &baseDst); - mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); - mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); + Assembler::Register stack(a->stack()); + Assembler::Memory stackDst(a->thread(), difference(&(t->base), t)); + a->apply(Move, BytesPerWord, Register, &stack, Memory, &stackDst); +} - c->directCall - (c->constant(reinterpret_cast(compileMethod)), - 1, c->thread()); +void +pushThread(MyThread*, Assembler* a) +{ + Assembler::Register thread(a->thread()); - Operand* result = ::result(c); - c->jmp(result); - c->release(result); - - return finish(t, context, "default"); + if (a->argumentRegisterCount()) { + Assembler::Register arg(a->argumentRegister(0)); + a->apply(Move, BytesPerWord, Register, &thread, Register, &arg); + } else { + a->apply(Push, BytesPerWord, Register, &thread); + } } object -compileNative(MyThread* t, Context* context) +compileDefault(MyThread* t, Assembler* a) { - Compiler* c = context->c; - - mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); - mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); - - c->directCall - (c->constant(reinterpret_cast(invokeNative)), 1, c->thread()); + saveStackAndBase(t, a); + pushThread(t, a); - c->ret(); + ResolvedPromise promise(reinterpret_cast(compileMethod)); + Assembler::Constant proc(&promise); + a->apply(Call, BytesPerWord, Constant, &proc); - return finish(t, context, "native"); + Assembler::Register result(a->returnLow()); + a->apply(Jump, BytesPerWord, Register, &result); + + return finish(t, a, "default"); +} + +object +compileNative(MyThread* t, Assembler* a) +{ + saveStackAndBase(t, a); + pushThread(t, a); + + ResolvedPromise promise(reinterpret_cast(invokeNative)); + Assembler::Constant proc(&promise); + a->apply(Call, BytesPerWord, Constant, &proc); + + a->apply(Return); + + return finish(t, a, "native"); } class ArgumentList { @@ -4438,7 +4198,7 @@ class MyProcessor: public Processor { object getDefaultCompiled(MyThread* t) { if (defaultCompiled == 0) { Context context(t); - defaultCompiled = compileDefault(t, &context); + defaultCompiled = compileDefault(t, context.assembler); } return defaultCompiled; } @@ -4446,7 +4206,7 @@ class MyProcessor: public Processor { object getNativeCompiled(MyThread* t) { if (nativeCompiled == 0) { Context context(t); - nativeCompiled = compileNative(t, &context); + nativeCompiled = compileNative(t, context.assembler); } return nativeCompiled; } @@ -4706,20 +4466,21 @@ processor(MyThread* t) p->addressTable = makeArray(t, 128, true); Context context(t); - Compiler* c = context.c; + Assembler* a = context.assembler; - mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); - mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); + saveStackAndBase(t, a); - c->jmp(c->indirectTarget()); + Assembler::Register proc(a->returnLow()); + a->apply(Jump, BytesPerWord, Register, &proc); - p->indirectCallerSize = c->codeSize(); + p->indirectCallerSize = a->length(); p->indirectCaller = static_cast (p->codeAllocator.allocate(p->indirectCallerSize)); - c->writeTo(p->indirectCaller); + a->writeTo(p->indirectCaller); if (Verbose) { - logCompile(p->indirectCaller, c->codeSize(), 0, "indirect caller", 0); + logCompile + (p->indirectCaller, p->indirectCallerSize, 0, "indirect caller", 0); } p->segFaultHandler.m = t->m; diff --git a/src/compiler.cpp b/src/compiler.cpp index 7323668644..76e2a206d3 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1,2880 +1,1552 @@ -#include "compiler.h" -#include "vector.h" -#include "zone.h" +#include "compiler2.h" +#include "assembler.h" using namespace vm; namespace { -enum Register { - NoRegister = -1, - rax = 0, - rcx = 1, - rdx = 2, - rbx = 3, - rsp = 4, - rbp = 5, - rsi = 6, - rdi = 7, - r8 = 8, - r9 = 9, - r10 = 10, - r11 = 11, - r12 = 12, - r13 = 13, - r14 = 14, - r15 = 15, -}; - -const bool Verbose = false; - -const unsigned RegisterCount = BytesPerWord * 2; -const unsigned GprParameterCount = 6; - class Context; class MyOperand; -class AddressOperand; -class ImmediateOperand; -class AbsoluteOperand; -class RegisterOperand; -class MemoryOperand; -class CodePromise; -class MyPromise; -class RegisterReference; +class ConstantValue; +class AddressValue; +class RegisterValue; +class MemoryValue; +class Event; -int64_t FORCE_ALIGN -divideLong(int64_t a, int64_t b) -{ - return a / b; -} +enum SyncType { + SyncForCall, + SyncForJump +}; -int64_t FORCE_ALIGN -moduloLong(int64_t a, int64_t b) -{ - return a % b; -} - -inline bool -isInt8(intptr_t v) -{ - return v == static_cast(v); -} - -inline bool -isInt32(intptr_t v) -{ - return v == static_cast(v); -} - -class RegisterNode { +class Value { public: - RegisterNode(Register value, RegisterNode* next): - value(value), next(next) + virtual ~Value() { } + + virtual bool equals(Value*) { return false; } + virtual bool equals(RegisterValue*) { return false; } + + virtual void preserve(Context*) { } + virtual void acquire(Context*, MyOperand*) { } + virtual void release(Context*, MyOperand*) { } + + virtual RegisterValue* toRegister(Context*, unsigned size) = 0; + + virtual void asAssemblerOperand(Context*, + OperandType* type, + Assembler::Operand** operand) = 0; +}; + +class MyOperand: public Compiler::Operand { + public: + MyOperand(unsigned size, Value* value): + size(size), event(0), value(value), target(0), index(0), next(0) { } - - Register value; - RegisterNode* next; -}; - -class Task { - public: - Task(Task* next): next(next) { } - - virtual ~Task() { } - - virtual void run(Context*, unsigned) = 0; - - Task* next; -}; - -class Event { - public: - Event(Event* next): next(next), task(0) { - if (next) { - count = next->count + 1; - } else { - count = 1; - } - } - - virtual ~Event() { } - - virtual void run(Context*) { } - - Event* next; - Task* task; - unsigned count; -}; - -class Segment { - public: - Segment(int logicalIp, Event* event): - logicalIp(logicalIp), offset(-1), event(event) - { } - - int logicalIp; - int offset; + + unsigned size; Event* event; + Value* value; + Value* target; + unsigned index; + MyOperand* next; }; -class MyStack: public Stack { +class State { public: - MyStack(MyOperand* value, int index, MyStack* next): - value(value), index(index), next(next) + State(State* s): + stack(s ? s->stack : 0), + next(s) { } - MyOperand* value; - int index; - MyStack* next; + MyOperand* stack; + State* next; }; -class RegisterData { +class LogicalInstruction { public: - RegisterData(): reserved(false) { } + unsigned visits; + Event* firstEvent; + Event* lastEvent; + unsigned machineOffset; + int predecessor; +}; +class RegisterElement { + public: bool reserved; + MyOperand* operand; +}; + +class ConstantPoolNode { + public: + ConstantPoolNode(Promise* promise): promise(promise), next(0) { } + + Promise* promise; + ConstantPoolNode* next; +}; + +class Junction { + public: + Junction(unsigned logicalIp, Junction* next): + logicalIp(logicalIp), + next(next) + { } + + unsigned logicalIp; + Junction* next; }; class Context { public: - Context(System* s, Allocator* allocator, Zone* zone, void* indirectCaller): - s(s), - constantPool(s, allocator, BytesPerWord * 32), - plan(s, allocator, 1024), - code(s, allocator, 1024), + Context(System* system, Assembler* assembler, Zone* zone): + system(system), + assembler(assembler), zone(zone), - indirectCaller(reinterpret_cast(indirectCaller)), - segmentTable(0), - reserved(0), - codeLength(-1) + logicalIp(-1), + state(new (zone->allocate(sizeof(State))) State(0)), + event(0), + logicalCode(0), + logicalCodeLength(0), + stackOffset(0), + registers(static_cast + (zone->allocate + (sizeof(RegisterElement) * assembler->registerCount()))), + firstConstant(0), + lastConstant(0), + constantCount(0), + junctions(0), + machineCode(0) { - plan.appendAddress(new (zone->allocate(sizeof(Segment))) Segment - (-1, new (zone->allocate(sizeof(Event))) Event(0))); - - registers[rsp].reserved = true; - registers[rbp].reserved = true; - registers[rbx].reserved = true; + memset(registers, 0, sizeof(RegisterElement) * assembler->registerCount()); + + registers[assembler->base()].reserved = true; + registers[assembler->stack()].reserved = true; + registers[assembler->thread()].reserved = true; } - void dispose() { - plan.dispose(); - code.dispose(); - constantPool.dispose(); - } - - System* s; - Vector constantPool; - Vector plan; - Vector code; + System* system; + Assembler* assembler; Zone* zone; - intptr_t indirectCaller; - Segment** segmentTable; - unsigned reserved; - int codeLength; - RegisterData registers[RegisterCount]; + int logicalIp; + State* state; + Event* event; + LogicalInstruction* logicalCode; + unsigned logicalCodeLength; + unsigned stackOffset; + RegisterElement* registers; + ConstantPoolNode* firstConstant; + ConstantPoolNode* lastConstant; + unsigned constantCount; + Junction* junctions; + uint8_t* machineCode; }; inline void NO_RETURN abort(Context* c) { - abort(c->s); + abort(c->system); } #ifndef NDEBUG inline void assert(Context* c, bool v) { - assert(c->s, v); + assert(c->system, v); } #endif // not NDEBUG inline void expect(Context* c, bool v) { - expect(c->s, v); + expect(c->system, v); } -class MyPromise: public Promise { - public: - virtual intptr_t value(Compiler*); - - virtual intptr_t value(Context*) = 0; - - virtual bool resolved(Context*) = 0; -}; - -class ResolvedPromise: public MyPromise { - public: - ResolvedPromise(intptr_t value): value_(value) { } - - virtual intptr_t value(Context*) { - return value_; - } - - virtual bool resolved(Context*) { - return true; - } - - intptr_t value_; -}; - -ResolvedPromise* -resolved(Context* c, intptr_t value) +void +apply(Context* c, UnaryOperation op, unsigned size, Value* a) { - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); + OperandType type; + Assembler::Operand* operand; + a->asAssemblerOperand(c, &type, &operand); + + c->assembler->apply(op, size, type, operand); } -class PoolPromise: public MyPromise { - public: - PoolPromise(intptr_t key): key(key) { } +void +apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b) +{ + OperandType aType; + Assembler::Operand* aOperand; + a->asAssemblerOperand(c, &aType, &aOperand); - virtual intptr_t value(Context* c) { - if (resolved(c)) { - return reinterpret_cast(c->code.data + c->codeLength + key); + OperandType bType; + Assembler::Operand* bOperand; + b->asAssemblerOperand(c, &bType, &bOperand); + + c->assembler->apply(op, size, aType, aOperand, bType, bOperand); +} + +class PoolPromise: public Promise { + public: + PoolPromise(Context* c, int key): c(c), key(key) { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast + (c->machineCode + c->assembler->length() + key); } abort(c); } - virtual bool resolved(Context* c) { - return c->codeLength >= 0; + virtual bool resolved() { + return c->machineCode != 0; } - intptr_t key; + Context* c; + int key; }; -class CodePromise: public MyPromise { +class CodePromise: public Promise { public: - CodePromise(): - offset(-1) - { } + CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { } - virtual intptr_t value(Context* c) { - if (resolved(c)) { - return reinterpret_cast(c->code.data + offset); + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast(c->machineCode + offset); } abort(c); } - virtual bool resolved(Context*) { - return offset >= 0; + virtual bool resolved() { + return c->machineCode != 0 and offset >= 0; } - intptr_t offset; + Context* c; + int offset; + CodePromise* next; }; -class IpPromise: public MyPromise { +class IpPromise: public Promise { public: - IpPromise(intptr_t logicalIp): + IpPromise(Context* c, int logicalIp): + c(c), logicalIp(logicalIp) { } - virtual intptr_t value(Context* c) { - if (resolved(c)) { - unsigned bottom = 0; - unsigned top = c->plan.length() / BytesPerWord; - for (unsigned span = top - bottom; span; span = top - bottom) { - unsigned middle = bottom + (span / 2); - Segment* s = c->segmentTable[middle]; - - if (logicalIp == s->logicalIp) { - return reinterpret_cast(c->code.data + s->offset); - } else if (logicalIp < s->logicalIp) { - top = middle; - } else if (logicalIp > s->logicalIp) { - bottom = middle + 1; - } - } + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast + (c->machineCode + c->logicalCode[logicalIp].machineOffset); } abort(c); } - virtual bool resolved(Context* c) { - return c->codeLength >= 0; + virtual bool resolved() { + return c->machineCode != 0; } - intptr_t logicalIp; + Context* c; + int logicalIp; }; -AddressOperand* -address(Context* c, MyPromise* p); +RegisterValue* +freeRegister(Context* c, unsigned size); -ImmediateOperand* -immediate(Context* c, int64_t v); - -AbsoluteOperand* -absolute(Context* c, MyPromise* v); - -RegisterOperand* -register_(Context* c, RegisterReference*); - -RegisterOperand* -register_(Context* c, Register = NoRegister, Register = NoRegister); - -MemoryOperand* -memory(Context* c, MyOperand* base, int displacement, - MyOperand* index, unsigned scale, Compiler::TraceHandler* traceHandler); - -class MyOperand: public Operand { +class ConstantValue: public Value { public: - enum Operation { - push1, - push2, - push2z, - push4, - push8, - pop4, - pop8, - call, - alignedCall, - ret, - mov1, - mov2, - mov4, - mov8, - mov1ToW, - mov2ToW, - mov2zToW, - mov4To8, - cmp4, - cmp8, - jl, - jg, - jle, - jge, - je, - jne, - jmp, - add4, - add8, - sub4, - sub8, - mul4, - mul8, - div4, - div8, - rem4, - rem8, - shl4, - shl8, - shr4, - shr8, - ushr4, - ushr8, - and4, - and8, - or4, - or8, - xor4, - xor8, - neg4, - neg8, - addc, - subb - }; + ConstantValue(Promise* value): value(value) { } - static const Operation push = (BytesPerWord == 8 ? push8 : push4); - static const Operation pop = (BytesPerWord == 8 ? pop8 : pop4); - static const Operation mov = (BytesPerWord == 8 ? mov8 : mov4); - static const Operation cmp = (BytesPerWord == 8 ? cmp8 : cmp4); - static const Operation add = (BytesPerWord == 8 ? add8 : add4); - static const Operation sub = (BytesPerWord == 8 ? sub8 : sub4); - static const Operation mul = (BytesPerWord == 8 ? mul8 : mul4); - static const Operation neg = (BytesPerWord == 8 ? neg8 : neg4); + virtual RegisterValue* toRegister(Context* c, unsigned size); - virtual ~MyOperand() { } + virtual void asAssemblerOperand(Context*, + OperandType* type, + Assembler::Operand** operand) + { + *type = Constant; + *operand = &value; + } - virtual Register asRegister(Context* c) { abort(c); } + Assembler::Constant value; +}; - virtual RegisterNode* dependencies(Context*, RegisterNode* next) - { return next; } +ConstantValue* +constant(Context* c, Promise* value) +{ + return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); +} - virtual void release(Context*) { /* ignore */ } +ConstantValue* +constant(Context* c, int64_t value) +{ + return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value)); +} - virtual void setLabelValue(Context* c, MyPromise*) { abort(c); } +class AddressValue: public Value { + public: + AddressValue(Promise* address): address(address) { } - virtual void apply(Context*, Operation) = 0; + virtual RegisterValue* toRegister(Context* c, unsigned size); - virtual void apply(Context*, Operation, MyOperand*) = 0; + virtual void asAssemblerOperand(Context*, + OperandType* type, + Assembler::Operand** operand) + { + *type = Address; + *operand = &address; + } - virtual void accept(Context* c, Operation, RegisterOperand*) = 0; + Assembler::Address address; +}; - virtual void accept(Context* c, Operation, ImmediateOperand*) = 0; +AddressValue* +address(Context* c, Promise* address) +{ + return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address); +} - virtual void accept(Context* c, Operation, AddressOperand*) = 0; +void preserve(Context* c, int reg); - virtual void accept(Context* c, Operation, AbsoluteOperand*) = 0; +class RegisterValue: public Value { + public: + RegisterValue(int low, int high): register_(low, high) { } - virtual void accept(Context* c, Operation, MemoryOperand*) = 0; + virtual bool equals(Value* o) { return o->equals(this); } + + virtual bool equals(RegisterValue* o) { + return o->register_.low == register_.low + and o->register_.high == register_.high; + } + + virtual void preserve(Context* c) { + ::preserve(c, register_.low); + if (register_.high >= 0) ::preserve(c, register_.high); + } + + virtual void acquire(Context* c, MyOperand* a) { + preserve(c); + c->registers[register_.low].operand = a; + if (register_.high >= 0) c->registers[register_.high].operand = a; + } + + virtual void release(Context* c, MyOperand* a UNUSED) { + assert(c, a == c->registers[register_.low].operand); + + c->registers[register_.low].operand = 0; + if (register_.high >= 0) c->registers[register_.high].operand = 0; + } + + virtual RegisterValue* toRegister(Context*, unsigned) { + return this; + } + + virtual void asAssemblerOperand(Context*, + OperandType* type, + Assembler::Operand** operand) + { + *type = Register; + *operand = ®ister_; + } + + Assembler::Register register_; +}; + +RegisterValue* +register_(Context* c, int low, int high = NoRegister) +{ + return new (c->zone->allocate(sizeof(RegisterValue))) + RegisterValue(low, high); +} + +class MemoryValue: public Value { + public: + MemoryValue(int base, int offset, int index, unsigned scale, + TraceHandler* traceHandler): + value(base, offset, index, scale, traceHandler) + { } + + virtual RegisterValue* toRegister(Context* c, unsigned size) { + RegisterValue* v = freeRegister(c, size); + apply(c, Move, size, this, v); + return v; + } + + virtual int base(Context*) { + return value.base; + } + + virtual int index(Context*) { + return value.index; + } + + virtual void asAssemblerOperand(Context* c, + OperandType* type, + Assembler::Operand** operand) + { + value.base = base(c); + value.index = index(c); + *type = Memory; + *operand = &value; + } + + Assembler::Memory value; +}; + +MemoryValue* +memory(Context* c, int base, int offset, int index, unsigned scale, + TraceHandler* traceHandler) +{ + return new (c->zone->allocate(sizeof(MemoryValue))) + MemoryValue(base, offset, index, scale, traceHandler); +} + +int +toRegister(Context* c, MyOperand* a) +{ + assert(c, a->size == BytesPerWord); + + return a->value->toRegister(c, a->size)->register_.low; +} + +class AbstractMemoryValue: public MemoryValue { + public: + AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, + unsigned scale, TraceHandler* traceHandler): + MemoryValue(NoRegister, offset, NoRegister, scale, traceHandler), + base_(base), index_(index) + { } + + virtual int base(Context* c) { + return ::toRegister(c, base_); + } + + virtual int index(Context* c) { + return index_ ? ::toRegister(c, base_) : NoRegister; + } + + MyOperand* base_; + MyOperand* index_; +}; + +AbstractMemoryValue* +memory(Context* c, MyOperand* base, int offset, MyOperand* index, + unsigned scale, TraceHandler* traceHandler) +{ + return new (c->zone->allocate(sizeof(AbstractMemoryValue))) + AbstractMemoryValue(base, offset, index, scale, traceHandler); +} + +class Event { + public: + Event(Context* c): next(0), stack(c->state->stack), promises(0) { + if (c->event) { + c->event->next = this; + } + + if (c->logicalCode[c->logicalIp].firstEvent == 0) { + c->logicalCode[c->logicalIp].firstEvent = this; + } + + c->event = this; + } + + Event(Event* next): next(next) { } + + virtual ~Event() { } + + virtual Value* target(Context* c, MyOperand* value) = 0; + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) = 0; + virtual void compile(Context* c) = 0; + + Event* next; + MyOperand* stack; + CodePromise* promises; +}; + +class ArgumentEvent: public Event { + public: + ArgumentEvent(Context* c, MyOperand* a, unsigned index): + Event(c), a(a), index(index) + { } + + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == a); + + if (index < c->assembler->argumentRegisterCount()) { + return register_(c, c->assembler->argumentRegister(index)); + } else { + return memory(c, c->assembler->base(), + (v->index + c->stackOffset) * BytesPerWord, + NoRegister, 0, 0); + } + } + + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == a); + a = new_; + new_->target = old->target; + } + + virtual void compile(Context* c) { + a->value->release(c, a); + a->target->preserve(c); + + if (not a->target->equals(a->value)) { + apply(c, Move, a->size, a->value, a->target); + } + } + + MyOperand* a; + unsigned index; }; void -acquire(Context* c, Register v) +appendArgument(Context* c, MyOperand* value, unsigned index) { - assert(c, not c->registers[v].reserved); - if (Verbose) { - fprintf(stderr, "acquire %d\n", v); - } - c->registers[v].reserved = true; + new (c->zone->allocate(sizeof(ArgumentEvent))) + ArgumentEvent(c, value, index); } -Register -acquire(Context* c) +class ReturnEvent: public Event { + public: + ReturnEvent(Context* c, MyOperand* a): + Event(c), a(a) + { } + + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == a); + + return register_(c, c->assembler->returnLow(), c->assembler->returnHigh()); + } + + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == a); + a = new_; + a->target = old->target; + } + + virtual void compile(Context* c) { + a->value->release(c, a); + + if (not a->target->equals(a->value)) { + apply(c, Move, a->size, a->value, a->target); + } + c->assembler->apply(Return); + } + + MyOperand* a; +}; + +void +appendReturn(Context* c, MyOperand* value) { - // we don't yet support using r9-r15 - for (int i = 8/*RegisterCount*/ - 1; i >= 0; --i) { + new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, value); +} + +class SyncForCallEvent: public Event { + public: + SyncForCallEvent(Context* c, MyOperand* src, MyOperand* dst): + Event(c), src(src), dst(dst) + { } + + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == src); + + return memory(c, c->assembler->base(), + (v->index + c->stackOffset) * BytesPerWord, + NoRegister, 0, 0); + } + + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == src); + src = new_; + src->target = old->target; + } + + virtual void compile(Context* c) { + src->value->release(c, src); + + if (not src->target->equals(src->value)) { + apply(c, Move, src->size, src->value, src->target); + } + } + + MyOperand* src; + MyOperand* dst; +}; + +void +appendSyncForCall(Context* c, MyOperand* src, MyOperand* dst) +{ + new (c->zone->allocate(sizeof(SyncForCallEvent))) + SyncForCallEvent(c, src, dst); +} + +class SyncForJumpEvent: public Event { + public: + SyncForJumpEvent(Context* c, MyOperand* src, MyOperand* dst): + Event(c), src(src), dst(dst) + { } + + SyncForJumpEvent(Event* next, MyOperand* src, MyOperand* dst): + Event(next), src(src), dst(dst) + { } + + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == src); + + if (BytesPerWord == 4 and v->size == 8) { + return register_(c, c->assembler->stackSyncRegister(v->index), + c->assembler->stackSyncRegister(v->index + 4)); + } else { + return register_(c, c->assembler->stackSyncRegister(v->index)); + } + } + + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == src); + src = new_; + src->target = old->target; + } + + virtual void compile(Context* c) { + src->value->release(c, src); + src->target->acquire(c, dst); + + if (not src->target->equals(src->value)) { + apply(c, Move, src->size, src->value, src->target); + } + + dst->value = src->target; + } + + MyOperand* src; + MyOperand* dst; +}; + +void +appendSyncForJump(Context* c, MyOperand* src, MyOperand* dst) +{ + new (c->zone->allocate(sizeof(SyncForJumpEvent))) + SyncForJumpEvent(c, src, dst); +} + +class CallEvent: public Event { + public: + CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags, + TraceHandler* traceHandler, MyOperand* result, + unsigned stackOffset): + Event(c), + address(address), + indirection(indirection), + flags(flags), + traceHandler(traceHandler), + result(result), + stackOffset(stackOffset) + { } + + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == address); + + if (indirection) { + return register_ + (c, c->assembler->returnLow(), c->assembler->returnHigh()); + } else { + return 0; + } + } + + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == address); + address = new_; + } + + virtual void compile(Context* c) { + address->value->release(c, address); + + if (result->event) { + result->value = register_ + (c, c->assembler->returnLow(), c->assembler->returnHigh()); + result->value->acquire(c, result); + } + + apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()), + memory(c, c->assembler->base(), stackOffset * BytesPerWord, + NoRegister, 0, 0)); + + if (indirection) { + if (not address->target->equals(address->value)) { + apply(c, Move, address->size, address->value, address->target); + } + apply(c, Call, BytesPerWord, + constant(c, reinterpret_cast(indirection))); + } else { + apply(c, Call, address->size, address->value); + } + } + + MyOperand* address; + void* indirection; + unsigned flags; + TraceHandler* traceHandler; + MyOperand* result; + unsigned stackOffset; +}; + +void +appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, + TraceHandler* traceHandler, MyOperand* result, + unsigned stackOffset) +{ + new (c->zone->allocate(sizeof(CallEvent))) + CallEvent(c, address, indirection, flags, traceHandler, result, + stackOffset); +} + +int +freeRegister(Context* c) +{ + for (unsigned i = 0; i < c->assembler->registerCount(); ++i) { + if ((not c->registers[i].reserved) + and c->registers[i].operand == 0) + { + return i; + } + } + + for (unsigned i = 0; i < c->assembler->registerCount(); ++i) { if (not c->registers[i].reserved) { - acquire(c, static_cast(i)); - return static_cast(i); + return i; } } abort(c); } -void -release(Context* c, Register v) +RegisterValue* +freeRegister(Context* c, unsigned size) { - assert(c, c->registers[v].reserved); - if (Verbose) { - fprintf(stderr, "release %d\n", v); + if (BytesPerWord == 4 and size == 8) { + return register_(c, freeRegister(c), freeRegister(c)); + } else { + return register_(c, freeRegister(c)); } - c->registers[v].reserved = false; } -class RegisterReference { +class MoveEvent: public Event { public: - RegisterReference(Register value = NoRegister, Register high = NoRegister): - value_(value), defaultValue(value), high_(high), defaultHigh(high), - acquired(true) + MoveEvent(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst): + Event(c), type(type), src(src), dst(dst) { } - void acquire(Context* c) { - if (defaultValue != NoRegister) { - ::acquire(c, defaultValue); - } + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == src); - if (defaultHigh != NoRegister) { - ::acquire(c, defaultHigh); - } - - value_ = defaultValue; - high_ = defaultHigh; - - acquired = true; + return v->event->target(c, dst); } - void release(Context* c) { - assert(c, acquired); - - if (value_ != NoRegister) { - ::release(c, value_); - } - - if (high_ != NoRegister) { - ::release(c, high_); - } - - value_ = NoRegister; - high_ = NoRegister; - - acquired = false; + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == src); + src = new_; + src->target = old->target; } - Register value(Context* c) { - assert(c, acquired); - if (value_ == NoRegister) { - value_ = ::acquire(c); + virtual void compile(Context* c) { + if (src->target == 0) { + src->target = freeRegister(c, src->size); } - return value_; + + src->value->release(c, src); + src->target->acquire(c, dst); + + apply(c, type, src->size, src->value, src->target); + + dst->value = src->target; } - Register high(Context* c) { - assert(c, acquired); - if (high_ == NoRegister) { - high_ = ::acquire(c); - } - return high_; - } - - Register value_; - Register defaultValue; - Register high_; - Register defaultHigh; - bool acquired; + BinaryOperation type; + MyOperand* src; + MyOperand* dst; }; -class RegisterOperand: public MyOperand { +void +appendMove(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst) +{ + new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, src, dst); +} + +class CompareEvent: public Event { public: - RegisterOperand(RegisterReference* reference): - reference(reference) + CompareEvent(Context* c, MyOperand* a, MyOperand* b): + Event(c), a(a), b(b) { } - Register value(Context* c) { - return reference->value(c); + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == a or v == b); + + return 0; } - Register high(Context* c) { - return reference->high(c); - } - - virtual Register asRegister(Context* c) { - return value(c); - } - - virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { - return new (c->zone->allocate(sizeof(RegisterNode))) - RegisterNode(value(c), next); - } - - virtual void release(Context* c) { - reference->release(c); - } - - virtual void apply(Context*, Operation); - - virtual void apply(Context* c, Operation op, MyOperand* operand) { - operand->accept(c, op, this); - } - - virtual void accept(Context*, Operation, RegisterOperand*); - virtual void accept(Context*, Operation, ImmediateOperand*); - virtual void accept(Context*, Operation, AddressOperand*); - virtual void accept(Context*, Operation, AbsoluteOperand*); - virtual void accept(Context*, Operation, MemoryOperand*); - - RegisterReference* reference; -}; - -class ImmediateOperand: public MyOperand { - public: - ImmediateOperand(int64_t value): - value(value) - { } - - virtual void apply(Context* c, Operation op); - - virtual void apply(Context* c, Operation op, MyOperand* operand) { - operand->accept(c, op, this); - } - - virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); } - virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); } - virtual void accept(Context* c, Operation, AddressOperand*) { abort(c); } - virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); } - virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); } - - int64_t value; -}; - -class AddressOperand: public MyOperand { - public: - AddressOperand(MyPromise* promise): - promise(promise) - { } - - virtual Register asRegister(Context* c); - - virtual void setLabelValue(Context*, MyPromise*); - - virtual void apply(Context*, Operation); - virtual void apply(Context* c, Operation op, MyOperand* operand) { - operand->accept(c, op, this); - } - - virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); } - virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); } - virtual void accept(Context* c, Operation, AddressOperand*) { abort(c); } - virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); } - virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); } - - MyPromise* promise; -}; - -class AbsoluteOperand: public MyOperand { - public: - AbsoluteOperand(MyPromise* promise): - promise(promise) - { } - - virtual Register asRegister(Context* c); - - virtual void apply(Context*, Operation); - - virtual void apply(Context* c, Operation op, MyOperand* operand) { - operand->accept(c, op, this); - } - - virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); } - virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); } - virtual void accept(Context* c, Operation, AddressOperand*) { abort(c); } - virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); } - virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); } - - MyPromise* promise; -}; - -class MemoryOperand: public MyOperand { - public: - MemoryOperand(MyOperand* base, int displacement, MyOperand* index, - unsigned scale, Compiler::TraceHandler* traceHandler): - base(base), - displacement(displacement), - index(index), - scale(scale), - traceHandler(traceHandler) - { } - - MemoryOperand* high(Context* c) { - return memory - (c, base, displacement + BytesPerWord, index, scale, traceHandler); - } - - virtual Register asRegister(Context*); - - virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { - next = base->dependencies(c, next); - if (index) { - return index->dependencies(c, next); + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + if (old == a) { + a = new_; + a->target = old->target; } else { - return next; + assert(c, old == b); + b = new_; + b->target = old->target; } } - virtual void apply(Context*, Operation); + virtual void compile(Context* c) { + a->value->release(c, a); + b->value->release(c, b); - virtual void apply(Context* c, Operation op, MyOperand* operand) { - operand->accept(c, op, this); + apply(c, Compare, a->size, a->value, b->value); } - virtual void accept(Context*, Operation, RegisterOperand*); - virtual void accept(Context*, Operation, ImmediateOperand*); - virtual void accept(Context* c, Operation, AddressOperand*) { abort(c); } - virtual void accept(Context*, Operation, AbsoluteOperand*); - virtual void accept(Context*, Operation, MemoryOperand*); - - MyOperand* base; - int displacement; - MyOperand* index; - unsigned scale; - Compiler::TraceHandler* traceHandler; -}; - -class CodePromiseTask: public Task { - public: - CodePromiseTask(CodePromise* promise, Task* next): - Task(next), promise(promise) - { } - - virtual void run(Context* c UNUSED, unsigned offset) { - promise->offset = offset; - } - - CodePromise* promise; -}; - -AddressOperand* -address(Context* c, MyPromise* p) -{ - return new (c->zone->allocate(sizeof(AddressOperand))) AddressOperand(p); -} - -ImmediateOperand* -immediate(Context* c, int64_t v) -{ - return new (c->zone->allocate(sizeof(ImmediateOperand))) - ImmediateOperand(v); -} - -AbsoluteOperand* -absolute(Context* c, MyPromise* v) -{ - return new (c->zone->allocate(sizeof(AbsoluteOperand))) AbsoluteOperand(v); -} - -RegisterOperand* -register_(Context* c, RegisterReference* r) -{ - return new (c->zone->allocate(sizeof(RegisterOperand))) - RegisterOperand(r); -} - -RegisterOperand* -register_(Context* c, Register v, Register h) -{ - RegisterReference* r = new (c->zone->allocate(sizeof(RegisterReference))) - RegisterReference(v, h); - return register_(c, r); -} - -MemoryOperand* -memory(Context* c, MyOperand* base, int displacement, - MyOperand* index, unsigned scale, Compiler::TraceHandler* traceHandler) -{ - return new (c->zone->allocate(sizeof(MemoryOperand))) - MemoryOperand(base, displacement, index, scale, traceHandler); -} - -RegisterOperand* -temporary(Context* c) -{ - return register_(c, acquire(c)); -} - -RegisterOperand* -temporary(Context* c, Register v) -{ - acquire(c, v); - return register_(c, v); -} - -RegisterOperand* -temporary(Context* c, Register v, Register h) -{ - acquire(c, v); - acquire(c, h); - return register_(c, v, h); -} - -Segment* -currentSegment(Context* c) -{ - Segment* s; c->plan.get(c->plan.length() - BytesPerWord, &s, BytesPerWord); - return s; -} - -Promise* -machineIp(Context* c) -{ - CodePromise* p = new (c->zone->allocate(sizeof(CodePromise))) CodePromise(); - - Segment* s = currentSegment(c); - s->event->task = new (c->zone->allocate(sizeof(CodePromiseTask))) - CodePromiseTask(p, s->event->task); - - return p; -} - -void -apply(Context* c, MyOperand::Operation op) -{ - switch (op) { - case MyOperand::ret: - c->code.append(0xc3); - break; - - default: abort(c); - } -} - -class OpEvent: public Event { - public: - OpEvent(MyOperand::Operation op, Event* next): - Event(next), op(op) - { } - - virtual void run(Context* c) { - apply(c, op); - } - - MyOperand::Operation op; -}; - -class UnaryOpEvent: public Event { - public: - UnaryOpEvent(MyOperand::Operation op, Operand* operand, Event* next): - Event(next), - op(op), - operand(static_cast(operand)) - { } - - virtual void run(Context* c) { - if (Verbose) { - fprintf(stderr, "unary %d\n", op); - } - operand->apply(c, op); - } - - MyOperand::Operation op; - MyOperand* operand; -}; - -class BinaryOpEvent: public Event { - public: - BinaryOpEvent(MyOperand::Operation op, Operand* a, Operand* b, - Event* next): - Event(next), - op(op), - a(static_cast(a)), - b(static_cast(b)) - { } - - virtual void run(Context* c) { - if (Verbose) { - fprintf(stderr, "binary %d\n", op); - } - a->apply(c, op, b); - } - - MyOperand::Operation op; - MyOperand* a; + MyOperand* a; MyOperand* b; }; -class AcquireEvent: public Event { +void +appendCompare(Context* c, MyOperand* a, MyOperand* b) +{ + new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, a, b); +} + +class BranchEvent: public Event { public: - AcquireEvent(RegisterOperand* operand, Event* next): - Event(next), - operand(operand) + BranchEvent(Context* c, UnaryOperation type, MyOperand* address): + Event(c), type(type), address(address) { } - virtual void run(Context* c) { - if (Verbose) { - fprintf(stderr, "acquire register\n"); - } - operand->reference->acquire(c); + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == address); + + return 0; } - RegisterOperand* operand; + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == address); + address = new_; + address->target = old->target; + } + + virtual void compile(Context* c) { + address->value->release(c, address); + + apply(c, type, address->size, address->value); + } + + UnaryOperation type; + MyOperand* address; }; -class ReleaseEvent: public Event { +void +appendBranch(Context* c, UnaryOperation type, MyOperand* address) +{ + new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); +} + +class JumpEvent: public Event { public: - ReleaseEvent(Operand* operand, Event* next): - Event(next), - operand(static_cast(operand)) + JumpEvent(Context* c, MyOperand* address): + Event(c), + address(address) { } - virtual void run(Context* c) { - if (Verbose) { - fprintf(stderr, "release register\n"); - } - operand->release(c); + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == address); + + return 0; } - MyOperand* operand; -}; + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == address); + address = new_; + } + virtual void compile(Context* c) { + address->value->release(c, address); -class Movement { - public: - MyOperand* source; - Register destination; - RegisterNode* dependencies; + apply(c, Jump, address->size, address->value); + } + + MyOperand* address; + unsigned stackOffset; + bool alignCall; + TraceHandler* traceHandler; }; void -push(Context* c, Movement* table, unsigned size) +appendJump(Context* c, MyOperand* address) { - int pushed[size]; - unsigned pushIndex = 0; - for (unsigned i = 0; i < size; ++i) { - Movement* mi = table + i; - for (unsigned j = i + 1; j < size; ++j) { - Movement* mj = table + j; - for (RegisterNode* d = mj->dependencies; d; d = d->next) { - if (mi->destination == d->value) { - mi->source->apply(c, MyOperand::push); - pushed[pushIndex++] = i; - goto loop; - } - } - } - - mi->source->apply - (c, MyOperand::mov, register_(c, mi->destination)); - loop:; - } - - for (int i = pushIndex - 1; i >= 0; --i) { - register_(c, table[pushed[i]].destination)->apply - (c, MyOperand::pop); - } + new (c->zone->allocate(sizeof(BranchEvent))) JumpEvent(c, address); } -Register -gpRegister(Context* c, unsigned index) -{ - switch (index) { - case 0: - return rdi; - case 1: - return rsi; - case 2: - return rdx; - case 3: - return rcx; - case 4: - return r8; - case 5: - return r9; - default: - abort(c); - } -} - -class ArgumentEvent: public Event { +class CombineEvent: public Event { public: - ArgumentEvent(MyOperand** arguments, unsigned count, Event* next): - Event(next), - arguments(arguments), - count(count) + CombineEvent(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b, + MyOperand* result): + Event(c), type(type), a(a), b(b), result(result) { } - virtual void run(Context* c) { - if (BytesPerWord == 8) { - const unsigned size = min(count, GprParameterCount); - Movement moveTable[size]; + virtual Value* target(Context* c, MyOperand* v) { + Assembler::Register ar(NoRegister); + Assembler::Register br(NoRegister); + c->assembler->getTargets(type, v->size, &ar, &br); - for (int i = count - 1; i >= 0; --i) { - if (static_cast(i) < GprParameterCount) { - Movement* m = moveTable + (size - i - 1); - m->source = arguments[i]; - m->destination = gpRegister(c, i); - m->dependencies = arguments[i]->dependencies(c, 0); - } else { - arguments[i]->apply(c, MyOperand::push8); - } + if (v == a) { + if (ar.low == NoRegister) { + return 0; + } else { + return register_(c, ar.low, ar.high); } - - push(c, moveTable, size); } else { - for (int i = count - 1; i >= 0; --i) { - if (i > 0 and arguments[i - 1] == 0) { - arguments[i]->apply(c, MyOperand::push8); - -- i; - } else { - arguments[i]->apply(c, MyOperand::push4); - } + assert(c, v == b); + + if (br.low == NoRegister) { + return result->event->target(c, result); + } else { + return register_(c, br.low, br.high); } } } - MyOperand** arguments; - unsigned count; + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + if (old == a) { + a = new_; + a->target = old->target; + } else { + assert(c, old == b); + b = new_; + b->target = old->target; + } + } + + virtual void compile(Context* c) { + a->value->release(c, a); + b->value->release(c, b); + b->value->acquire(c, result); + + if (a->target and not a->target->equals(a->value)) { + apply(c, Move, a->size, a->value, a->target); + } + if (b->target and not b->target->equals(b->value)) { + apply(c, Move, b->size, b->value, b->target); + } + + apply(c, type, a->size, a->value, b->value); + + result->value = b->value; + } + + BinaryOperation type; + MyOperand* a; + MyOperand* b; + MyOperand* result; }; void -appendOperation(Context* c, MyOperand::Operation op) +appendCombine(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b, + MyOperand* result) { - Segment* s = currentSegment(c); - s->event = new (c->zone->allocate(sizeof(OpEvent))) - OpEvent(op, s->event); + new (c->zone->allocate(sizeof(CombineEvent))) + CombineEvent(c, type, a, b, result); } -void -appendOperation(Context* c, MyOperand::Operation op, Operand* operand) -{ - Segment* s = currentSegment(c); - s->event = new (c->zone->allocate(sizeof(UnaryOpEvent))) - UnaryOpEvent(op, operand, s->event); -} +class TranslateEvent: public Event { + public: + TranslateEvent(Context* c, UnaryOperation type, MyOperand* a, + MyOperand* result): + Event(c), type(type), a(a), result(result) + { } -void -appendOperation(Context* c, MyOperand::Operation op, Operand* a, Operand* b) -{ - Segment* s = currentSegment(c); - s->event = new (c->zone->allocate(sizeof(BinaryOpEvent))) - BinaryOpEvent(op, a, b, s->event); -} - -void -appendAcquire(Context* c, RegisterOperand* operand) -{ - Segment* s = currentSegment(c); - s->event = new (c->zone->allocate(sizeof(AcquireEvent))) - AcquireEvent(operand, s->event); -} - -void -appendRelease(Context* c, Operand* operand) -{ - Segment* s = currentSegment(c); - s->event = new (c->zone->allocate(sizeof(ReleaseEvent))) - ReleaseEvent(operand, s->event); -} - -void -appendArgumentEvent(Context* c, MyOperand** arguments, unsigned count) -{ - Segment* s = currentSegment(c); - s->event = new (c->zone->allocate(sizeof(ArgumentEvent))) - ArgumentEvent(arguments, count, s->event); -} - -void -logStack(Context* c, MyStack* stack) -{ - fprintf(stderr, "ip %3d: ", currentSegment(c)->logicalIp); - - if (stack) { - fprintf(stderr, " %d", - static_cast(stack->value)->displacement); - } - - for (MyStack* s = stack; s; s = s->next) { - fprintf(stderr, "*"); - } - - fprintf(stderr, "\n"); -} - -MyStack* -pushed(Context* c, MyStack* stack) -{ - int index = (stack ? stack->index + 1 : 0); - - MyOperand* value = memory - (c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1, - 0); - - stack = new (c->zone->allocate(sizeof(MyStack))) - MyStack(value, index, stack); - - if (Verbose) { - logStack(c, stack); - } - - return stack; -} - -MyStack* -push(Context* c, MyStack* stack, MyOperand::Operation op, MyOperand* v) -{ - appendOperation(c, op, v); - - if (BytesPerWord == 4 and op == MyOperand::push8) { - stack = pushed(c, stack); - } - return pushed(c, stack); -} - -MyStack* -pop(Context* c, MyStack* stack, int count) -{ - appendOperation - (c, MyOperand::add, - immediate(c, count * BytesPerWord), - register_(c, rsp)); - - while (count) { - -- count; - assert(c, count >= 0); - stack = stack->next; - } - - if (Verbose) { - logStack(c, stack); - } - - return stack; -} - -MyStack* -pop(Context* c, MyStack* stack, MyOperand::Operation op, MyOperand* dst) -{ - appendOperation(c, op, dst); - - if (BytesPerWord == 4 and op == MyOperand::pop8) { - stack = stack->next; - } - - if (Verbose) { - logStack(c, stack->next); - } - - return stack->next; -} - -void -pushArguments(Context* c, unsigned count, va_list list) -{ - MyOperand** arguments = static_cast - (c->zone->allocate(count * BytesPerWord)); - - unsigned index = 0; - for (unsigned i = 0; i < count; ++i) { - if (BytesPerWord == 8) { - arguments[index] = va_arg(list, MyOperand*); - if (arguments[index]) { - ++ index; - } - } else { - arguments[index++] = va_arg(list, MyOperand*); - } - } - - appendArgumentEvent(c, arguments, index); -} - -unsigned -argumentFootprint(unsigned count) -{ - if (BytesPerWord == 8) { - if (count > GprParameterCount) { - return (count - GprParameterCount) * BytesPerWord; - } else { - return 0; - } - } else { - return count * BytesPerWord; - } -} - -void -rex(Context* c) -{ - if (BytesPerWord == 8) { - c->code.append(0x48); - } -} - -void -encode(Context* c, uint8_t* instruction, unsigned length, int a, Register b, - int32_t displacement, int index, unsigned scale) -{ - c->code.append(instruction, length); - - uint8_t width; - if (displacement == 0 and b != rbp) { - width = 0; - } else if (isInt8(displacement)) { - width = 0x40; - } else { - width = 0x80; - } - - if (index == -1) { - c->code.append(width | (a << 3) | b); - if (b == rsp) { - c->code.append(0x24); - } - } else { - assert(c, b != rsp); - c->code.append(width | (a << 3) | 4); - c->code.append((log(scale) << 6) | (index << 3) | b); - } - - if (displacement == 0 and b != rbp) { - // do nothing - } else if (isInt8(displacement)) { - c->code.append(displacement); - } else { - c->code.append4(displacement); - } -} - -void -encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex) -{ - Register r = b->base->asRegister(c); - int index = b->index ? b->index->asRegister(c) : -1; - - if (b->traceHandler and c->codeLength >= 0) { - b->traceHandler->handleTrace - (resolved(c, reinterpret_cast - (c->code.data + c->code.length()))); - } - - if (rex) { - ::rex(c); - } - encode(c, &instruction, 1, a, r, b->displacement, index, b->scale); -} - -void -encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex) -{ - Register r = b->base->asRegister(c); - int index = b->index ? b->index->asRegister(c) : -1; - - if (b->traceHandler and c->codeLength >= 0) { - b->traceHandler->handleTrace - (resolved(c, reinterpret_cast - (c->code.data + c->code.length()))); - } - - if (rex) { - ::rex(c); - } - uint8_t i[2] = { instruction >> 8, instruction & 0xff }; - encode(c, i, 2, a, r, b->displacement, index, b->scale); -} - -void -RegisterOperand::apply(Context* c, Operation op) -{ - switch (op) { - case call: { - c->code.append(0xff); - c->code.append(0xd0 | value(c)); - } break; - - case jmp: - c->code.append(0xff); - c->code.append(0xe0 | value(c)); - break; - - case pop4: - case pop8: - if (BytesPerWord == 4 and op == pop8) { - apply(c, pop); - register_(c, high(c))->apply(c, pop); - } else { - c->code.append(0x58 | value(c)); - if (BytesPerWord == 8 and op == pop4) { - accept(c, mov4To8, this); - } - } - break; - - case push4: - case push8: - if (BytesPerWord == 4 and op == push8) { - register_(c, high(c))->apply(c, push); - apply(c, push); - } else { - c->code.append(0x50 | value(c)); - } - break; - - case neg4: - case neg8: - assert(c, BytesPerWord == 8 or op == neg4); // todo - - rex(c); - c->code.append(0xf7); - c->code.append(0xd8 | value(c)); - break; - - default: abort(c); - } -} - -void -RegisterOperand::accept(Context* c, Operation op, - RegisterOperand* operand) -{ - switch (op) { - case add: - rex(c); - c->code.append(0x01); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case cmp4: - case cmp8: - if (BytesPerWord == 4 and op == cmp8) { - register_(c, high(c))->accept - (c, cmp, register_(c, operand->high(c))); - - // if the high order bits are equal, we compare the low order - // bits; otherwise, we jump past that comparison - c->code.append(0x0f); - c->code.append(0x85); // jne - c->code.append4(2); - - accept(c, cmp, operand); - } else { - if (op == cmp8) rex(c); - c->code.append(0x39); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - } - break; - - case mov4: - case mov8: - if (BytesPerWord == 4 and op == mov8) { - accept(c, mov, operand); + virtual Value* target(Context* c, MyOperand* v) { + assert(c, v == a); - register_(c, high(c))->accept - (c, mov, register_(c, operand->high(c))); - } else if (value(c) != operand->value(c)) { - rex(c); - c->code.append(0x89); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - } - break; + Assembler::Register r(NoRegister); + c->assembler->getTargets(type, v->size, &r); - case mov1ToW: - c->code.append(0xbe); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case mov2ToW: - c->code.append(0xbf); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case mov2zToW: - c->code.append(0xb7); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case mov4To8: - assert(c, BytesPerWord == 8); - rex(c); - c->code.append(0x63); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case mul4: - case mul8: - assert(c, BytesPerWord == 8 or op == mul4); // todo - - rex(c); - c->code.append(0x0f); - c->code.append(0xaf); - c->code.append(0xc0 | (value(c) << 3) | operand->value(c)); - break; - - case xor4: - rex(c); - c->code.append(0x31); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - default: abort(c); - } -} - -void -RegisterOperand::accept(Context* c, Operation op, - ImmediateOperand* operand) -{ - switch (op) { - case add4: - case add8: - assert(c, BytesPerWord == 8 or op == add4); // todo - - if (operand->value) { - rex(c); - if (isInt8(operand->value)) { - c->code.append(0x83); - c->code.append(0xc0 | value(c)); - c->code.append(operand->value); - } else if (isInt32(operand->value)) { - c->code.append(0x81); - c->code.append(0xc0 | value(c)); - c->code.append4(operand->value); - } else { - abort(c); - } - } - break; - - case addc: - if (isInt8(operand->value)) { - c->code.append(0x83); - c->code.append(0xd0 | value(c)); - c->code.append(operand->value); + if (r.low == NoRegister) { + return result->event->target(c, result); } else { - abort(c); + return register_(c, r.low, r.high); } - break; - - case and4: - case and8: - assert(c, BytesPerWord == 8 or op == and4); // todo - - rex(c); - if (isInt8(operand->value)) { - c->code.append(0x83); - c->code.append(0xe0 | value(c)); - c->code.append(operand->value); - } else { - assert(c, isInt32(operand->value)); - - c->code.append(0x81); - c->code.append(0xe0 | value(c)); - c->code.append(operand->value); - } - break; - - case cmp4: - case cmp8: { - assert(c, BytesPerWord == 8 or op == cmp4); // todo - - if (op == cmp8) rex(c); - if (isInt8(operand->value)) { - c->code.append(0x83); - c->code.append(0xf8 | value(c)); - c->code.append(operand->value); - } else { - assert(c, isInt32(operand->value)); - - c->code.append(0x81); - c->code.append(0xf8 | value(c)); - c->code.append4(operand->value); - } - } break; - - case mov4: - case mov8: { - assert(c, BytesPerWord == 8 or op == mov4); // todo - - rex(c); - c->code.append(0xb8 | value(c)); - c->code.appendAddress(operand->value); - } break; - - case shl4: - case shl8: { - assert(c, BytesPerWord == 8 or op == shl4); // todo - - if (operand->value) { - rex(c); - if (operand->value == 1) { - c->code.append(0xd1); - c->code.append(0xe0 | value(c)); - } else { - assert(c, isInt8(operand->value)); - - c->code.append(0xc1); - c->code.append(0xe0 | value(c)); - c->code.append(operand->value); - } - } - } break; - - case sub4: - case sub8: { - assert(c, BytesPerWord == 8 or op == sub4); // todo - - if (operand->value) { - rex(c); - if (isInt8(operand->value)) { - c->code.append(0x83); - c->code.append(0xe8 | value(c)); - c->code.append(operand->value); - } else if (isInt32(operand->value)) { - c->code.append(0x81); - c->code.append(0xe8 | value(c)); - c->code.append4(operand->value); - } else { - abort(c); - } - } - } break; - - default: abort(c); } -} -ImmediateOperand* -value(Context* c, AddressOperand* operand) -{ - if (c->codeLength >= 0 and operand->promise->resolved(c)) { - return immediate(c, operand->promise->value(c)); - } else { - return immediate(c, 0); + virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { + assert(c, old == a); + a = new_; + a->target = old->target; } -} + + virtual void compile(Context* c) { + result->value->acquire(c, result); + + apply(c, type, a->size, a->value); + + result->value = a->value; + } + + UnaryOperation type; + MyOperand* a; + MyOperand* result; +}; void -RegisterOperand::accept(Context* c, Operation op, - AddressOperand* operand) +appendTranslate(Context* c, UnaryOperation type, MyOperand* a, + MyOperand* result) { - switch (op) { - case mov: { - accept(c, op, ::value(c, operand)); - } break; - - default: abort(c); - } + new (c->zone->allocate(sizeof(TranslateEvent))) + TranslateEvent(c, type, a, result); } -void -RegisterOperand::accept(Context* c, Operation op, - MemoryOperand* operand) +RegisterValue* +ConstantValue::toRegister(Context* c, unsigned size) { - switch (op) { - case cmp4: - case cmp8: - assert(c, BytesPerWord == 8 or op == cmp4); // todo - - encode(c, 0x3b, value(c), operand, true); - break; - - case mov4: - case mov8: - if (BytesPerWord == 4 and op == mov8) { - accept(c, mov, operand); - - register_(c, high(c))->accept(c, mov, operand->high(c)); - } else if (BytesPerWord == 8 and op == mov4) { - encode(c, 0x63, value(c), operand, true); - } else { - encode(c, 0x8b, value(c), operand, true); - } - break; - - case mov1ToW: - encode2(c, 0x0fbe, value(c), operand, true); - break; - - case mov2ToW: - encode2(c, 0x0fbf, value(c), operand, true); - break; - - case mov2zToW: - encode2(c, 0x0fb7, value(c), operand, true); - break; - - case mov4To8: - assert(c, BytesPerWord == 8); // todo - - encode(c, 0x63, value(c), operand, true); - break; - - case mul4: - case mul8: - assert(c, BytesPerWord == 8 or op == mul4); // todo - - encode2(c, 0x0faf, value(c), operand, true); - break; - - default: abort(c); - } + RegisterValue* v = freeRegister(c, size); + apply(c, Move, size, this, v); + return v; } -ImmediateOperand* -value(Context* c, AbsoluteOperand* operand) +RegisterValue* +AddressValue::toRegister(Context* c, unsigned size) { - if (c->codeLength >= 0 and operand->promise->resolved(c)) { - return immediate(c, operand->promise->value(c)); - } else { - return immediate(c, 0); - } -} - -void -RegisterOperand::accept(Context* c, Operation op, - AbsoluteOperand* operand) -{ - switch (op) { - case cmp4: - case cmp8: { - assert(c, BytesPerWord == 8 or op == cmp4); // todo - - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, ::value(c, operand)); - accept(c, cmp, memory(c, tmp, 0, 0, 1, 0)); - tmp->release(c); - } break; - - case mov4: - case mov8: { - assert(c, BytesPerWord == 8 or op == mov4); // todo - - accept(c, mov, ::value(c, operand)); - accept(c, mov, memory(c, this, 0, 0, 1, 0)); - } break; - - default: abort(c); - } -} - -void -unconditional(Context* c, unsigned jump, AddressOperand* operand) -{ - intptr_t v; - if (c->codeLength >= 0 and operand->promise->resolved(c)) { - uint8_t* instruction = c->code.data + c->code.length(); - v = reinterpret_cast(operand->promise->value(c)) - - instruction - 5; - } else { - v = 0; - } - - expect(c, isInt32(v)); - - c->code.append(jump); - c->code.append4(v); -} - -void -conditional(Context* c, unsigned condition, AddressOperand* operand) -{ - intptr_t v; - if (c->codeLength >= 0 and operand->promise->resolved(c)) { - uint8_t* instruction = c->code.data + c->code.length(); - v = reinterpret_cast(operand->promise->value(c)) - - instruction - 6; - } else { - v = 0; - } - - expect(c, isInt32(v)); - - c->code.append(0x0f); - c->code.append(condition); - c->code.append4(v); -} - -void -AddressOperand::setLabelValue(Context*, MyPromise* p) -{ - promise = p; -} - -void -AddressOperand::apply(Context* c, Operation op) -{ - switch (op) { - case alignedCall: { - while ((c->code.length() + 1) % 4) { - c->code.append(0x90); - } - apply(c, call); - } break; - - case call: { - unconditional(c, 0xe8, this); - } break; - - case jmp: - unconditional(c, 0xe9, this); - break; - - case je: - conditional(c, 0x84, this); - break; - - case jne: - conditional(c, 0x85, this); - break; - - case jg: - conditional(c, 0x8f, this); - break; - - case jge: - conditional(c, 0x8d, this); - break; - - - case jl: - conditional(c, 0x8c, this); - break; - - case jle: - conditional(c, 0x8e, this); - break; - - case push4: - case push8: { - assert(c, BytesPerWord == 8 or op == push4); // todo - - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, this); - tmp->apply(c, push); - tmp->release(c); - } break; - - default: abort(c); - } -} - -Register -AddressOperand::asRegister(Context* c) -{ - intptr_t v; - if (c->codeLength >= 0) { - v = promise->value(c); - } else { - v = 0; - } - - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, immediate(c, v)); - Register r = tmp->value(c); - tmp->release(c); - return r; -} - -void -ImmediateOperand::apply(Context* c, Operation op) -{ - switch (op) { - case alignedCall: - case call: - case jmp: - address(c, resolved(c, value))->apply(c, op); - break; - - case push4: - case push8: - if (BytesPerWord == 4 and op == push8) { - immediate(c, (value >> 32) & 0xFFFFFFFF)->apply - (c, push); - immediate(c, (value ) & 0xFFFFFFFF)->apply - (c, push); - } else { - if (isInt8(value)) { - c->code.append(0x6a); - c->code.append(value); - } else if (isInt32(value)) { - c->code.append(0x68); - c->code.append4(value); - } else { - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, this); - tmp->apply(c, push); - tmp->release(c); - } - } - break; - - default: abort(c); - } -} - -Register -AbsoluteOperand::asRegister(Context* c) -{ - RegisterOperand* tmp = temporary(c); - tmp->accept(c, MyOperand::mov, this); - Register v = tmp->value(c); - tmp->release(c); + RegisterValue* v = freeRegister(c, size); + apply(c, Move, size, this, v); return v; } void -absoluteApply(Context* c, MyOperand::Operation op, - AbsoluteOperand* operand) +preserve(Context* c, int reg) { - RegisterOperand* tmp = temporary(c); - tmp->accept(c, MyOperand::mov, value(c, operand)); - memory(c, tmp, 0, 0, 1, 0)->apply(c, op); - tmp->release(c); -} + MyOperand* a = c->registers[reg].operand; + if (a) { + MemoryValue* dst = memory + (c, c->assembler->base(), (a->index + c->stackOffset) * BytesPerWord, + -1, 0, 0); -void -AbsoluteOperand::apply(Context* c, Operation op) -{ - switch (op) { - case push: - absoluteApply(c, op, this); - break; + apply(c, Move, a->size, a->value, dst); - default: abort(c); + a->value = dst; + c->registers[reg].operand = 0; } } -Register -MemoryOperand::asRegister(Context* c) +MyOperand* +operand(Context* c, unsigned size, Value* value = 0) { - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, this); - Register v = tmp->value(c); - tmp->release(c); - return v; + return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(size, value); } void -MemoryOperand::apply(Context* c, Operation op) +pushState(Context* c) { - switch (op) { - case call: - encode(c, 0xff, 2, this, false); - break; - - case jmp: - encode(c, 0xff, 4, this, false); - break; - - case neg4: - case neg8: - if (BytesPerWord == 4 and op == neg8) { - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - - MemoryOperand* low = this; - MemoryOperand* high = this->high(c); - - ax->accept(c, mov, low); - dx->accept(c, mov, high); - - ax->apply(c, neg); - dx->accept(c, addc, immediate(c, 0)); - dx->apply(c, neg); - - low->accept(c, mov, ax); - high->accept(c, mov, dx); - - ax->release(c); - dx->release(c); - } else { - encode(c, 0xf7, 3, this, true); - } - break; - - case pop4: - case pop8: - if (BytesPerWord == 4 and op == pop8) { - MemoryOperand* low = this; - MemoryOperand* high = this->high(c); - - low->apply(c, pop); - high->apply(c, pop); - } else if (BytesPerWord == 8 and op == pop4) { - abort(c); - } else { - encode(c, 0x8f, 0, this, false); - } - break; - - case push4: - case push8: - if (BytesPerWord == 4 and op == push8) { - MemoryOperand* low = this; - MemoryOperand* high = this->high(c); - - high->apply(c, push); - low->apply(c, push); - } else if (BytesPerWord == 8 and op == push4) { - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov4, this); - tmp->apply(c, op); - tmp->release(c); - } else { - encode(c, 0xff, 6, this, false); - } - break; - - case push1: - case push2: - case push2z: { - RegisterOperand* tmp = temporary(c); - switch (op) { - case push1: - tmp->accept(c, mov1ToW, this); - break; - - case push2: - tmp->accept(c, mov2ToW, this); - break; - - case push2z: - tmp->accept(c, mov2zToW, this); - break; - - default: abort(c); - } - tmp->apply(c, push); - tmp->release(c); - } break; - - default: abort(c); - } + c->state = new (c->zone->allocate(sizeof(State))) + State(c->state); } void -MemoryOperand::accept(Context* c, Operation op, RegisterOperand* operand) +popState(Context* c) { - switch (op) { - case and4: - case and8: - if (BytesPerWord == 4 and op == and8) { - accept(c, and4, operand); - high(c)->accept(c, and4, register_(c, operand->high(c))); + c->state = new (c->zone->allocate(sizeof(State))) + State(c->state->next); +} + +void +push(Context* c, MyOperand* o) +{ + static_cast(o)->next = c->state->stack; + c->state->stack = static_cast(o); +} + +MyOperand* +pop(Context* c) +{ + MyOperand* o = c->state->stack; + c->state->stack = o->next; + return o; +} + +void +syncStack(Context* c, SyncType type) +{ + MyOperand* top = 0; + MyOperand* new_ = 0; + for (MyOperand* old = c->state->stack; old; old = old->next) { + MyOperand* n = operand(c, old->size, 0); + if (new_) { + new_->next = n; } else { - encode(c, 0x21, operand->value(c), this, true); + top = n; } - break; - - case add4: - case add8: - if (BytesPerWord == 4 and op == add8) { - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - - ax->accept(c, mov, operand); - dx->accept(c, mov, register_(c, operand->high(c))); - - accept(c, add, ax); - high(c)->accept(c, addc, dx); - - ax->release(c); - dx->release(c); - } else { - encode(c, 0x01, operand->value(c), this, true); - } - break; - - case addc: - encode(c, 0x11, operand->value(c), this, true); - break; - - case div4: - case div8: - if (BytesPerWord == 4 and op == div8) { - RegisterOperand* axdx = temporary(c, rax, rdx); - - operand->apply(c, push8); - apply(c, push8); - immediate(c, reinterpret_cast(divideLong))->apply - (c, call); - register_(c, rsp)->accept - (c, add, immediate(c, 16)); - accept(c, mov8, axdx); - - axdx->release(c); - } else { - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - ax->accept(c, mov, this); - - rex(c); - c->code.append(0x99); - rex(c); - c->code.append(0xf7); - c->code.append(0xf8 | operand->value(c)); - - accept(c, mov, ax); - - ax->release(c); - dx->release(c); - } - break; - - case mov4: - case mov8: - if (BytesPerWord == 4 and op == mov8) { - accept(c, mov, operand); - - high(c)->accept - (c, mov, register_(c, operand->high(c))); - } else if (BytesPerWord == 8 and op == mov4) { - encode(c, 0x89, operand->value(c), this, false); - } else { - encode(c, 0x89, operand->value(c), this, true); - } - break; - - case mov1: - if (BytesPerWord == 8) { - if (operand->value(c) > rbx) { - encode2(c, 0x4088, operand->value(c), this, false); - } else { - encode(c, 0x88, operand->value(c), this, false); - } - } else { - if (operand->value(c) > rbx) { - RegisterOperand* ax = temporary(c, rax); - ax->accept(c, mov, operand); - accept(c, mov1, register_(c, rax)); - ax->release(c); - } else { - encode(c, 0x88, operand->value(c), this, false); - } - } - break; - - case mov2: - encode2(c, 0x6689, operand->value(c), this, false); - break; - - case mov4To8: - assert(c, BytesPerWord == 8); - encode(c, 0x89, operand->value(c), this, false); - break; - - case mul4: - case mul8: - if (BytesPerWord == 4 and op == mul8) { - RegisterOperand* tmp = temporary(c, rcx); - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - - RegisterOperand* lowSrc = operand; - RegisterOperand* highSrc = register_(c, operand->high(c)); - - MemoryOperand* lowDst = this; - MemoryOperand* highDst = this->high(c); + new_ = n; + new_->index = old->index; - tmp->accept(c, mov, highSrc); - tmp->accept(c, mul, lowDst); - ax->accept(c, mov, highDst); - ax->accept(c, mul, lowSrc); - tmp->accept(c, add, ax); - ax->accept(c, mov, lowDst); - - // mul lowSrc,%eax - c->code.append(0xf7); - c->code.append(0xe8 | lowSrc->value(c)); - - dx->accept(c, add, tmp); - - lowDst->accept(c, mov, ax); - highDst->accept(c, mov, dx); - - tmp->release(c); - ax->release(c); - dx->release(c); + if (type == SyncForCall) { + appendSyncForCall(c, old, new_); } else { - RegisterOperand* tmp = temporary(c); - - tmp->accept(c, mov, this); - tmp->accept(c, mul, operand); - accept(c, mov, tmp); - - tmp->release(c); + appendSyncForJump(c, old, new_); } - break; - - case or4: - case or8: - if (BytesPerWord == 4 and op == or8) { - accept(c, or4, operand); - high(c)->accept(c, or4, register_(c, operand->high(c))); - } else { - encode(c, 0x09, operand->value(c), this, true); - } - break; - - case rem4: - case rem8: - if (BytesPerWord == 4 and op == rem8) { - RegisterOperand* axdx = temporary(c, rax, rdx); - - operand->apply(c, push8); - apply(c, push8); - immediate(c, reinterpret_cast(moduloLong))->apply - (c, call); - register_(c, rsp)->accept - (c, add, immediate(c, 16)); - accept(c, mov8, axdx); - - axdx->release(c); - } else { - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - ax->accept(c, mov, this); - - rex(c); - c->code.append(0x99); - rex(c); - c->code.append(0xf7); - c->code.append(0xf8 | operand->value(c)); - - accept(c, mov, dx); - - ax->release(c); - dx->release(c); - } - break; - - case shl4: - case shl8: { - if (BytesPerWord == 4 and op == shl8) { - RegisterOperand* count = temporary(c, rcx); - RegisterOperand* low = temporary(c); - RegisterOperand* high = temporary(c); - - count->accept(c, mov, operand); - low->accept(c, mov, this); - high->accept(c, mov, this->high(c)); - - // shld - c->code.append(0x0f); - c->code.append(0xa5); - c->code.append(0xc0 | (low->value(c) << 3) | high->value(c)); - - // shl - c->code.append(0xd3); - c->code.append(0xe0 | low->value(c)); - - count->accept(c, cmp, immediate(c, 32)); - c->code.append(0x0f); - c->code.append(0x8c); // jl - c->code.append4(2 + 2); - - high->accept(c, mov, low); // 2 bytes - low->accept(c, xor4, low); // 2 bytes - - this->accept(c, mov, low); - this->high(c)->accept(c, mov, high); - - high->release(c); - low->release(c); - count->release(c); - } else { - RegisterOperand* cx = temporary(c, rcx); - cx->accept(c, mov, operand); - encode(c, 0xd3, 4, this, true); - cx->release(c); - } - } break; - - case shr4: - case shr8: { - if (BytesPerWord == 4 and op == shr8) { - RegisterOperand* count = temporary(c, rcx); - RegisterOperand* low = temporary(c); - RegisterOperand* high = temporary(c); - - count->accept(c, mov, operand); - low->accept(c, mov, this); - high->accept(c, mov, this->high(c)); - - // shrd - c->code.append(0x0f); - c->code.append(0xad); - c->code.append(0xc0 | (high->value(c) << 3) | low->value(c)); - - // sar - c->code.append(0xd3); - c->code.append(0xf8 | high->value(c)); - - count->accept(c, cmp, immediate(c, 32)); - c->code.append(0x0f); - c->code.append(0x8c); // jl - c->code.append4(2 + 3); - - low->accept(c, mov, high); // 2 bytes - // sar 31,high - c->code.append(0xc1); - c->code.append(0xf8 | high->value(c)); - c->code.append(31); - - this->accept(c, mov, low); - this->high(c)->accept(c, mov, high); - - high->release(c); - low->release(c); - count->release(c); - } else { - RegisterOperand* cx = temporary(c, rcx); - cx->accept(c, mov, operand); - encode(c, 0xd3, 7, this, true); - cx->release(c); - } - } break; - - case ushr4: - case ushr8: { - if (BytesPerWord == 4 and op == ushr8) { - RegisterOperand* count = temporary(c, rcx); - RegisterOperand* low = temporary(c); - RegisterOperand* high = temporary(c); - - count->accept(c, mov, operand); - low->accept(c, mov, this); - high->accept(c, mov, this->high(c)); - - // shld - c->code.append(0x0f); - c->code.append(0xa5); - c->code.append(0xc0 | (high->value(c) << 3) | low->value(c)); - - // shl - c->code.append(0xd3); - c->code.append(0xe8 | high->value(c)); - - count->accept(c, cmp, immediate(c, 32)); - c->code.append(0x0f); - c->code.append(0x8c); // jl - c->code.append4(2 + 2); - - low->accept(c, mov, high); // 2 bytes - high->accept(c, xor4, high); // 2 bytes - - this->accept(c, mov, low); - this->high(c)->accept(c, mov, high); - - high->release(c); - low->release(c); - count->release(c); - } else { - RegisterOperand* cx = temporary(c, rcx); - cx->accept(c, mov, operand); - encode(c, 0xd3, 5, this, true); - cx->release(c); - } - } break; - - case sub4: - case sub8: - if (BytesPerWord == 4 and op == sub8) { - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - - ax->accept(c, mov, operand); - dx->accept(c, mov, register_(c, operand->high(c))); - - accept(c, sub, ax); - high(c)->accept(c, subb, dx); - - ax->release(c); - dx->release(c); - } else { - encode(c, 0x29, operand->value(c), this, true); - } - break; - - case subb: - encode(c, 0x19, operand->value(c), this, true); - break; - - case xor4: - case xor8: { - if (BytesPerWord == 4 and op == xor8) { - accept(c, xor4, operand); - high(c)->accept(c, xor4, register_(c, operand->high(c))); - } else { - encode(c, 0x31, operand->value(c), this, true); - } - } break; - - default: abort(c); } + + c->state->stack = top; } void -MemoryOperand::accept(Context* c, Operation op, - ImmediateOperand* operand) +updateJunctions(Context* c) { - switch (op) { - case add4: - case add8: { - assert(c, BytesPerWord == 8 or op == add4); // todo + for (Junction* j = c->junctions; j; j = j->next) { + LogicalInstruction* i = c->logicalCode + j->logicalIp; - unsigned i = (isInt8(operand->value) ? 0x83 : 0x81); + if (i->predecessor >= 0) { + LogicalInstruction* p = c->logicalCode + i->predecessor; - encode(c, i, 0, this, true); - if (isInt8(operand->value)) { - c->code.append(operand->value); - } else if (isInt32(operand->value)) { - c->code.append4(operand->value); - } else { - abort(c); - } - } break; + MyOperand* new_ = 0; + for (MyOperand* old = i->firstEvent->stack; old; old = old->next) { + MyOperand* n = operand(c, old->size, 0); + if (new_) new_->next = n; + new_ = n; + new_->index = old->index; - case mov4: - case mov8: { - assert(c, isInt32(operand->value)); // todo - assert(c, BytesPerWord == 8 or op == mov4); // todo - - encode(c, 0xc7, 0, this, true); - c->code.append4(operand->value); - } break; - - default: abort(c); - } -} - -void -MemoryOperand::accept(Context* c, Operation op, - AbsoluteOperand* operand) -{ - RegisterOperand* tmp = temporary(c); - - tmp->accept(c, mov, operand); - accept(c, op, tmp); - - tmp->release(c); -} - -void -MemoryOperand::accept(Context* c, Operation op, - MemoryOperand* operand) -{ - switch (op) { - case mov1ToW: - case mov2ToW: - case mov2zToW: - case mov4To8: { - if (BytesPerWord == 4 and op == mov4To8) { - RegisterOperand* ax = temporary(c, rax); - RegisterOperand* dx = temporary(c, rdx); - - ax->accept(c, mov4, operand); - c->code.append(0x99); // cdq - accept(c, mov8, register_(c, rax, rdx)); - - ax->release(c); - dx->release(c); - } else { - RegisterOperand* tmp = temporary(c); - tmp->accept(c, op, operand); - accept(c, mov, tmp); - tmp->release(c); - } - } break; - - case mov4: - case mov8: - case and4: { - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, operand); - accept(c, op, tmp); - tmp->release(c); - } break; - - default: abort(c); - } -} - -int -compareSegmentPointers(const void* a, const void* b) -{ - return (*static_cast(a))->logicalIp - - (*static_cast(b))->logicalIp; -} - -void -writeCode(Context* c) -{ - unsigned tableSize = (c->plan.length() / BytesPerWord); - - if (c->codeLength < 0) { - c->segmentTable = static_cast - (c->zone->allocate(c->plan.length())); - - for (unsigned i = 0; i < tableSize; ++i) { - c->plan.get(i * BytesPerWord, c->segmentTable + i, BytesPerWord); - } - - qsort(c->segmentTable, tableSize, BytesPerWord, compareSegmentPointers); - } - - for (unsigned i = 0; i < tableSize; ++i) { - Segment* s = c->segmentTable[i]; - if (Verbose) { - fprintf(stderr, "\nip %d\n", s->logicalIp); - } - - if (c->codeLength >= 0) { - assert(c, s->offset == static_cast(c->code.length())); - } else { - s->offset = c->code.length(); - } - - Event* events[s->event->count]; - unsigned ei = s->event->count; - for (Event* e = s->event; e; e = e->next) { - events[--ei] = e; - } - - for (unsigned ei = 0; ei < s->event->count; ++ei) { - if (Verbose and ei) { - fprintf(stderr, "address %p\n", c->code.data + c->code.length()); - } - - events[ei]->run(c); - - if (c->codeLength < 0) { - for (Task* t = events[ei]->task; t; t = t->next) { - t->run(c, c->code.length()); + if (old->event) { + old->event->replace(c, old, new_); } + + p->lastEvent = p->lastEvent->next = new + (c->zone->allocate(sizeof(SyncForJumpEvent))) + SyncForJumpEvent(p->lastEvent->next, old, new_); } } } +} - c->codeLength = pad(c->code.length()); +void +compile(Context* c) +{ + for (Event* e = c->logicalCode[0].firstEvent; e; e = e->next) { + e->compile(c); + } } class MyCompiler: public Compiler { public: - MyCompiler(System* s, Allocator* allocator, Zone* zone, - void* indirectCaller): - c(s, allocator, zone, indirectCaller) + MyCompiler(System* s, Assembler* assembler, Zone* zone): + c(s, assembler, zone) { } + virtual void pushState() { + ::pushState(&c); + } + + virtual void popState() { + ::pushState(&c); + } + + virtual void init(unsigned logicalCodeLength, unsigned stackOffset) { + c.logicalCodeLength = logicalCodeLength; + c.stackOffset = stackOffset; + c.logicalCode = static_cast + (c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength)); + memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength); + } + + virtual void visitLogicalIp(unsigned logicalIp) { + if ((++ c.logicalCode[logicalIp].visits) == 1) { + c.junctions = new (c.zone->allocate(sizeof(Junction))) + Junction(logicalIp, c.junctions); + } + } + + virtual void startLogicalIp(unsigned logicalIp) { + if (c.logicalIp >= 0) { + c.logicalCode[c.logicalIp].lastEvent = c.event; + } + + c.logicalIp = logicalIp; + } + virtual Promise* machineIp(unsigned logicalIp) { - return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(logicalIp); + return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp); } - virtual Promise* poolAppend(intptr_t v) { - return poolAppendPromise(resolved(&c, v)); + virtual Promise* poolAppend(intptr_t value) { + return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value)); } - virtual Promise* poolAppendPromise(Promise* v) { + virtual Promise* poolAppendPromise(Promise* value) { Promise* p = new (c.zone->allocate(sizeof(PoolPromise))) - PoolPromise(c.constantPool.length()); - c.constantPool.appendAddress(v); + PoolPromise(&c, c.constantCount); + + ConstantPoolNode* constant + = new (c.zone->allocate(sizeof(ConstantPoolNode))) + ConstantPoolNode(value); + + if (c.firstConstant) { + c.lastConstant->next = constant; + } else { + c.firstConstant = constant; + } + c.lastConstant = constant; + ++ c.constantCount; + return p; } - virtual Operand* constant(int64_t v) { - return immediate(&c, v); + virtual Operand* constant(int64_t value) { + return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value)); } - virtual Operand* promiseConstant(Promise* p) { - return address(&c, static_cast(p)); + virtual Operand* constant8(int64_t value) { + return promiseConstant8(new (c.zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value)); } - virtual Operand* absolute(Promise* p) { - return ::absolute(&c, static_cast(p)); + virtual Operand* promiseConstant(Promise* value) { + return operand(&c, BytesPerWord, ::constant(&c, value)); } - virtual Stack* push(Stack* s, unsigned count) { - appendOperation - (&c, MyOperand::sub, - immediate(&c, count * BytesPerWord), - register_(&c, rsp)); - - return pushed(s, count); + virtual Operand* promiseConstant8(Promise* value) { + return operand(&c, 8, ::constant(&c, value)); } - virtual Stack* pushed(Stack* s, unsigned count) { - MyStack* stack = static_cast(s); - while (count) { - -- count; - stack = ::pushed(&c, stack); - } - return stack; + virtual Operand* address(Promise* address) { + return operand(&c, BytesPerWord, ::address(&c, address)); } - virtual Stack* push1(Stack* s, Operand* v) { - return ::push(&c, static_cast(s), MyOperand::push1, - static_cast(v)); - } - - virtual Stack* push2(Stack* s, Operand* v) { - return ::push(&c, static_cast(s), MyOperand::push2, - static_cast(v)); - } - - virtual Stack* push2z(Stack* s, Operand* v) { - return ::push(&c, static_cast(s), MyOperand::push2z, - static_cast(v)); - } - - virtual Stack* push4(Stack* s, Operand* v) { - return ::push(&c, static_cast(s), MyOperand::push4, - static_cast(v)); - } - - virtual Stack* push8(Stack* s, Operand* v) { - return ::push(&c, static_cast(s), MyOperand::push8, - static_cast(v)); - } - - virtual Operand* stack(Stack* s, unsigned index) { - MyStack* stack = static_cast(s); - - while (index) { - -- index; - stack = stack->next; - } - - return stack->value; - } - - virtual Stack* pop(Stack* s, unsigned count) { - return ::pop(&c, static_cast(s), count); - } - - virtual Stack* pop4(Stack* s, Operand* dst) { - return ::pop(&c, static_cast(s), MyOperand::pop4, - static_cast(dst)); - } - - virtual Stack* pop8(Stack* s, Operand* dst) { - return ::pop(&c, static_cast(s), MyOperand::pop8, - static_cast(dst)); + virtual Operand* memory(Operand* base, + int displacement = 0, + Operand* index = 0, + unsigned scale = 1, + TraceHandler* traceHandler = 0) + { + return operand + (&c, BytesPerWord, ::memory + (&c, static_cast(base), displacement, + static_cast(index), scale, traceHandler)); } virtual Operand* stack() { - return register_(&c, rsp); + return operand(&c, BytesPerWord, register_(&c, c.assembler->stack())); } virtual Operand* base() { - return register_(&c, rbp); + return operand(&c, BytesPerWord, register_(&c, c.assembler->base())); } virtual Operand* thread() { - return register_(&c, rbx); - } - - virtual Operand* indirectTarget() { - return register_(&c, rax); - } - - virtual Operand* temporary() { - RegisterOperand* r = register_(&c); - appendAcquire(&c, r); - return r; - } - - virtual void release(Operand* v) { - appendRelease(&c, v); + return operand(&c, BytesPerWord, register_(&c, c.assembler->thread())); } virtual Operand* label() { - return address(&c, 0); + return operand(&c, BytesPerWord, ::constant(&c, static_cast(0))); } Promise* machineIp() { - CodePromise* p = new (c.zone->allocate(sizeof(CodePromise))) CodePromise(); - - Segment* s = currentSegment(&c); - s->event->task = new (c.zone->allocate(sizeof(CodePromiseTask))) - CodePromiseTask(p, s->event->task); - - return p; + return c.event->promises = new (c.zone->allocate(sizeof(CodePromise))) + CodePromise(&c, c.event->promises); } virtual void mark(Operand* label) { - static_cast(label)->setLabelValue - (&c, static_cast(machineIp())); + static_cast(static_cast(label)->value)->value + = machineIp(); } - virtual void indirectCall - (Operand* address, TraceHandler* traceHandler, unsigned argumentCount, ...) + virtual void push(Operand* value) { + ::push(&c, static_cast(value)); + } + + virtual Operand* pop() { + return ::pop(&c); + } + + virtual void push(unsigned count) { + for (unsigned i = 0; i < count; ++i) ::push(&c, 0); + } + + virtual void pop(unsigned count) { + for (unsigned i = 0; i < count; ++i) ::pop(&c); + } + + virtual Operand* peek(unsigned index) { + MyOperand* a = c.state->stack; + for (; index; --index) a = a->next; + return a; + } + + virtual Operand* call(Operand* address, + void* indirection, + unsigned flags, + TraceHandler* traceHandler, + unsigned resultSize, + unsigned argumentCount, + ...) { va_list a; va_start(a, argumentCount); - pushArguments(&c, argumentCount, a); + + unsigned footprint = 0; + for (unsigned i = 0; i < argumentCount; ++i) { + MyOperand* o = va_arg(a, MyOperand*); + footprint += o->size; + appendArgument(&c, o, i); + } + va_end(a); - appendOperation - (&c, MyOperand::mov, address, register_(&c, rax)); - call(immediate(&c, c.indirectCaller), traceHandler); + syncStack(&c, SyncForCall); - appendOperation - (&c, MyOperand::add, - immediate(&c, argumentFootprint(argumentCount)), - register_(&c, rsp)); + unsigned stackOffset = c.stackOffset + c.state->stack->index + + (footprint > c.assembler->argumentRegisterCount() ? + footprint - c.assembler->argumentRegisterCount() : 0); + + MyOperand* result = operand(&c, resultSize, 0); + appendCall(&c, static_cast(address), indirection, flags, + traceHandler, result, stackOffset); + return result; } - virtual void indirectCallNoReturn - (Operand* address, TraceHandler* traceHandler, unsigned argumentCount, ...) - { - va_list a; va_start(a, argumentCount); - pushArguments(&c, argumentCount, a); - va_end(a); - - appendOperation - (&c, MyOperand::mov, address, register_(&c, rax)); - - call(immediate(&c, c.indirectCaller), traceHandler); + virtual void return_(Operand* value) { + appendReturn(&c, static_cast(value)); } - virtual void directCall - (Operand* address, unsigned argumentCount, ...) - { - va_list a; va_start(a, argumentCount); - pushArguments(&c, argumentCount, a); - va_end(a); - - call(address, 0); - - appendOperation - (&c, MyOperand::add, - immediate(&c, argumentFootprint(argumentCount)), - register_(&c, rsp)); + virtual void store(Operand* src, Operand* dst) { + appendMove(&c, Move, static_cast(src), + static_cast(dst)); } - virtual Operand* result4() { - RegisterOperand* r = register_(&c, rax); - appendAcquire(&c, r); - return r; + virtual void store1(Operand* src, Operand* dst) { + appendMove(&c, Store1, static_cast(src), + static_cast(dst)); } - virtual Operand* result8() { - if (BytesPerWord == 8) { - return result4(); - } else { - RegisterOperand* r = register_(&c, rax, rdx); - appendAcquire(&c, r); - return r; - } + virtual void store2(Operand* src, Operand* dst) { + appendMove(&c, Store2, static_cast(src), + static_cast(dst)); } - virtual void return4(Operand* v) { - appendOperation(&c, MyOperand::mov, v, register_(&c, rax)); - epilogue(); - ret(); + virtual void store4(Operand* src, Operand* dst) { + appendMove(&c, Store4, static_cast(src), + static_cast(dst)); } - virtual void return8(Operand* v) { - if (BytesPerWord == 8) { - return4(v); - } else { - appendOperation(&c, MyOperand::mov8, v, register_(&c, rax, rdx)); - epilogue(); - ret(); - } + virtual void store8(Operand* src, Operand* dst) { + appendMove(&c, Store8, static_cast(src), + static_cast(dst)); } - virtual void call(Operand* v, TraceHandler* traceHandler) { - appendOperation(&c, MyOperand::call, v); - if (traceHandler) { - traceHandler->handleTrace(machineIp()); - } + virtual Operand* load(Operand* src) { + MyOperand* dst = operand(&c, BytesPerWord); + appendMove(&c, Move, static_cast(src), dst); + return dst; } - virtual void alignedCall(Operand* v, TraceHandler* traceHandler) { - appendOperation(&c, MyOperand::alignedCall, v); - if (traceHandler) { - traceHandler->handleTrace(machineIp()); - } + virtual Operand* load1(Operand* src) { + MyOperand* dst = operand(&c, BytesPerWord); + appendMove(&c, Load1, static_cast(src), dst); + return dst; } - virtual void ret() { - appendOperation(&c, MyOperand::ret); + virtual Operand* load2(Operand* src) { + MyOperand* dst = operand(&c, BytesPerWord); + appendMove(&c, Load2, static_cast(src), dst); + return dst; } - virtual void mov1(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov1, src, dst); + virtual Operand* load2z(Operand* src) { + MyOperand* dst = operand(&c, BytesPerWord); + appendMove(&c, Load2z, static_cast(src), dst); + return dst; } - virtual void mov2(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov2, src, dst); + virtual Operand* load4(Operand* src) { + MyOperand* dst = operand(&c, BytesPerWord); + appendMove(&c, Load4, static_cast(src), dst); + return dst; } - virtual void mov4(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov4, src, dst); + virtual Operand* load8(Operand* src) { + MyOperand* dst = operand(&c, 8); + appendMove(&c, Load8, static_cast(src), dst); + return dst; } - virtual void mov8(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov8, src, dst); + virtual Operand* load4To8(Operand* src) { + MyOperand* dst = operand(&c, 8); + appendMove(&c, Load4To8, static_cast(src), dst); + return dst; } - virtual void mov1ToW(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov1ToW, src, dst); + virtual void cmp(Operand* a, Operand* b) { + appendCompare(&c, static_cast(a), static_cast(b)); } - virtual void mov2ToW(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov2ToW, src, dst); + virtual void jl(Operand* address) { + syncStack(&c, SyncForJump); + + appendBranch(&c, JumpIfLess, static_cast(address)); } - virtual void mov2zToW(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov2zToW, src, dst); + virtual void jg(Operand* address) { + syncStack(&c, SyncForJump); + + appendBranch(&c, JumpIfGreater, static_cast(address)); } - virtual void mov4To8(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov4To8, src, dst); + virtual void jle(Operand* address) { + syncStack(&c, SyncForJump); + + appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); } - virtual void cmp4(Operand* subtrahend, Operand* minuend) { - appendOperation(&c, MyOperand::cmp4, subtrahend, minuend); + virtual void jge(Operand* address) { + syncStack(&c, SyncForJump); + + appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); } - virtual void cmp8(Operand* subtrahend, Operand* minuend) { - appendOperation(&c, MyOperand::cmp8, subtrahend, minuend); + virtual void je(Operand* address) { + syncStack(&c, SyncForJump); + + appendBranch(&c, JumpIfEqual, static_cast(address)); } - virtual void jl(Operand* v) { - appendOperation(&c, MyOperand::jl, v); + virtual void jne(Operand* address) { + syncStack(&c, SyncForJump); + + appendBranch(&c, JumpIfNotEqual, static_cast(address)); } - virtual void jg(Operand* v) { - appendOperation(&c, MyOperand::jg, v); + virtual void jmp(Operand* address) { + syncStack(&c, SyncForJump); + + appendJump(&c, static_cast(address)); } - virtual void jle(Operand* v) { - appendOperation(&c, MyOperand::jle, v); + virtual Operand* add(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Add, static_cast(a), + static_cast(b), result); + return result; } - virtual void jge(Operand* v) { - appendOperation(&c, MyOperand::jge, v); + virtual Operand* sub(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Subtract, static_cast(a), + static_cast(b), result); + return result; } - virtual void je(Operand* v) { - appendOperation(&c, MyOperand::je, v); + virtual Operand* mul(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Multiply, static_cast(a), + static_cast(b), result); + return result; } - virtual void jne(Operand* v) { - appendOperation(&c, MyOperand::jne, v); + virtual Operand* div(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Divide, static_cast(a), + static_cast(b), result); + return result; } - virtual void jmp(Operand* v) { - appendOperation(&c, MyOperand::jmp, v); + virtual Operand* rem(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Remainder, static_cast(a), + static_cast(b), result); + return result; } - virtual void add4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::add4, v, dst); + virtual Operand* shl(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, ShiftLeft, static_cast(a), + static_cast(b), result); + return result; } - virtual void add8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::add8, v, dst); + virtual Operand* shr(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, ShiftRight, static_cast(a), + static_cast(b), result); + return result; } - virtual void sub4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::sub4, v, dst); + virtual Operand* ushr(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, UnsignedShiftRight, static_cast(a), + static_cast(b), result); + return result; } - virtual void sub8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::sub8, v, dst); + virtual Operand* and_(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, And, static_cast(a), + static_cast(b), result); + return result; } - virtual void mul4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::mul4, v, dst); + virtual Operand* or_(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Or, static_cast(a), + static_cast(b), result); + return result; } - virtual void mul8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::mul8, v, dst); + virtual Operand* xor_(Operand* a, Operand* b) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendCombine(&c, Xor, static_cast(a), + static_cast(b), result); + return result; } - virtual void div4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::div4, v, dst); + virtual Operand* neg(Operand* a) { + MyOperand* result = operand(&c, static_cast(a)->size); + appendTranslate(&c, Negate, static_cast(a), result); + return result; } - virtual void div8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::div8, v, dst); - } - - virtual void rem4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::rem4, v, dst); - } - - virtual void rem8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::rem8, v, dst); - } - - virtual void shl4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::shl4, v, dst); - } - - virtual void shl8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::shl8, v, dst); - } - - virtual void shr4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::shr4, v, dst); - } - - virtual void shr8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::shr8, v, dst); - } - - virtual void ushr4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::ushr4, v, dst); - } - - virtual void ushr8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::ushr8, v, dst); - } - - virtual void and4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::and4, v, dst); - } - - virtual void and8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::and8, v, dst); - } - - virtual void or4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::or4, v, dst); - } - - virtual void or8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::or8, v, dst); - } - - virtual void xor4(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::xor4, v, dst); - } - - virtual void xor8(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::xor8, v, dst); - } - - virtual void neg4(Operand* v) { - appendOperation(&c, MyOperand::neg4, v); - } - - virtual void neg8(Operand* v) { - appendOperation(&c, MyOperand::neg8, v); - } - - virtual Operand* memory(Operand* base, int displacement, - Operand* index, unsigned scale, - TraceHandler* trace) - { - return ::memory(&c, static_cast(base), displacement, - static_cast(index), scale, trace); - } - - virtual void prologue() { - appendOperation(&c, MyOperand::push, register_(&c, rbp)); - appendOperation - (&c, MyOperand::mov, register_(&c, rsp), register_(&c, rbp)); - } - - virtual void reserve(unsigned size) { - appendOperation - (&c, MyOperand::sub, immediate(&c, size * BytesPerWord), - register_(&c, rsp)); - - c.reserved = size; - } - - virtual void epilogue() { - appendOperation - (&c, MyOperand::mov, register_(&c, rbp), register_(&c, rsp)); - appendOperation(&c, MyOperand::pop, register_(&c, rbp)); - } - - virtual void startLogicalIp(unsigned ip) { - c.plan.appendAddress - (new (c.zone->allocate(sizeof(Segment))) - Segment(ip, new (c.zone->allocate(sizeof(Event))) Event(0))); - } - - virtual unsigned codeSize() { - if (c.codeLength < 0) { - assert(&c, c.code.length() == 0); - writeCode(&c); - } - return c.codeLength; + virtual unsigned compile() { + updateJunctions(&c); + ::compile(&c); + return c.assembler->length(); } virtual unsigned poolSize() { - return c.constantPool.length(); + return c.constantCount; } - virtual void writeTo(uint8_t* out) { - c.code.wrap(out, codeSize()); - writeCode(&c); + virtual void writeTo(uint8_t* dst) { + c.machineCode = dst; + c.assembler->writeTo(dst); - for (unsigned i = 0; i < c.constantPool.length(); i += BytesPerWord) { - Promise* p; c.constantPool.get(i, &p, BytesPerWord); - *reinterpret_cast(out + codeSize() + i) = p->value(this); + int i = 0; + for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) { + *reinterpret_cast(dst + c.assembler->length() + (i++)) + = n->promise->value(); } } - virtual void updateCall(void* returnAddress, void* newTarget) { - uint8_t* instruction = static_cast(returnAddress) - 5; - assert(&c, *instruction == 0xE8); - assert(&c, reinterpret_cast(instruction + 1) % 4 == 0); - - int32_t v = static_cast(newTarget) - - static_cast(returnAddress); - memcpy(instruction + 1, &v, 4); - } - virtual void dispose() { - c.dispose(); + // ignore } Context c; }; -intptr_t -MyPromise::value(Compiler* compiler) -{ - return value(&(static_cast(compiler)->c)); -} - } // namespace namespace vm { Compiler* -makeCompiler(System* system, Allocator* allocator, Zone* zone, - void* indirectCaller) +makeCompiler(System* system, Assembler* assembler, Zone* zone) { return new (zone->allocate(sizeof(MyCompiler))) - MyCompiler(system, allocator, zone, indirectCaller); + MyCompiler(system, assembler, zone); } -} // namespace v +} // namespace vm diff --git a/src/compiler.h b/src/compiler.h index 6aa129b325..9778544e4f 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -3,146 +3,106 @@ #include "system.h" #include "zone.h" +#include "assembler.h" namespace vm { -class Operand { }; - -class Stack { }; - -class Compiler; - -class Promise { - public: - virtual ~Promise() { } - - virtual intptr_t value(Compiler*) = 0; -}; - class Compiler { public: - class TraceHandler { - public: - virtual ~TraceHandler() { } + static const unsigned Aligned = 1 << 0; + static const unsigned NoReturn = 1 << 1; - virtual void handleTrace(Promise* address) = 0; - }; + class Operand { }; virtual ~Compiler() { } + virtual void pushState() = 0; + virtual void popState() = 0; + + virtual void init(unsigned logicalCodeSize, unsigned localFootprint) = 0; + + virtual void visitLogicalIp(unsigned logicalIp) = 0; + virtual void startLogicalIp(unsigned logicalIp) = 0; + virtual Promise* machineIp(unsigned logicalIp) = 0; - virtual Promise* poolAppend(intptr_t) = 0; - virtual Promise* poolAppendPromise(Promise*) = 0; + virtual Promise* poolAppend(intptr_t value) = 0; + virtual Promise* poolAppendPromise(Promise* value) = 0; - virtual Operand* constant(int64_t) = 0; - virtual Operand* promiseConstant(Promise*) = 0; - virtual Operand* absolute(Promise*) = 0; + virtual Operand* constant(intptr_t value) = 0; + virtual Operand* constant8(int64_t value) = 0; + virtual Operand* promiseConstant(Promise* value) = 0; + virtual Operand* promiseConstant8(Promise* value) = 0; + virtual Operand* address(Promise* address) = 0; virtual Operand* memory(Operand* base, int displacement = 0, Operand* index = 0, unsigned scale = 1, TraceHandler* traceHandler = 0) = 0; - virtual Operand* stack() = 0; virtual Operand* base() = 0; virtual Operand* thread() = 0; - virtual Operand* indirectTarget() = 0; - virtual Operand* temporary() = 0; - virtual Operand* result4() = 0; - virtual Operand* result8() = 0; - virtual void release(Operand*) = 0; virtual Operand* label() = 0; - virtual void mark(Operand*) = 0; + virtual void mark(Operand* label) = 0; - virtual void indirectCall - (Operand* address, TraceHandler* traceHandler, - unsigned argumentCount, ...) = 0; - virtual void indirectCallNoReturn - (Operand* address, TraceHandler* traceHandler, - unsigned argumentCount, ...) = 0; - virtual void directCall - (Operand* address, unsigned argumentCount, ...) = 0; + virtual void push(Operand* value) = 0; + virtual Operand* pop() = 0; + virtual void push(unsigned count) = 0; + virtual void pop(unsigned count) = 0; + virtual Operand* peek(unsigned index) = 0; - virtual void call(Operand*, TraceHandler*) = 0; - virtual void alignedCall(Operand*, TraceHandler*) = 0; - virtual void return4(Operand*) = 0; - virtual void return8(Operand*) = 0; - virtual void ret() = 0; + virtual Operand* call(Operand* address, + void* indirection, + unsigned flags, + TraceHandler* traceHandler, + unsigned resultSize, + unsigned argumentCount, + ...) = 0; + virtual void return_(Operand* value) = 0; - virtual Stack* push(Stack*, unsigned count) = 0; - virtual Stack* pushed(Stack*, unsigned count) = 0; - virtual Stack* pop(Stack*, unsigned count) = 0; - virtual Operand* stack(Stack*, unsigned) = 0; + virtual void store(Operand* src, Operand* dst) = 0; + virtual void store1(Operand* src, Operand* dst) = 0; + virtual void store2(Operand* src, Operand* dst) = 0; + virtual void store4(Operand* src, Operand* dst) = 0; + virtual void store8(Operand* src, Operand* dst) = 0; + virtual Operand* load(Operand* src) = 0; + virtual Operand* load1(Operand* src) = 0; + virtual Operand* load2(Operand* src) = 0; + virtual Operand* load2z(Operand* src) = 0; + virtual Operand* load4(Operand* src) = 0; + virtual Operand* load8(Operand* src) = 0; + virtual Operand* load4To8(Operand* src) = 0; + virtual void cmp(Operand* a, Operand* b) = 0; + virtual void jl(Operand* address) = 0; + virtual void jg(Operand* address) = 0; + virtual void jle(Operand* address) = 0; + virtual void jge(Operand* address) = 0; + virtual void je(Operand* address) = 0; + virtual void jne(Operand* address) = 0; + virtual void jmp(Operand* address) = 0; + virtual Operand* add(Operand* a, Operand* b) = 0; + virtual Operand* sub(Operand* a, Operand* b) = 0; + virtual Operand* mul(Operand* a, Operand* b) = 0; + virtual Operand* div(Operand* a, Operand* b) = 0; + virtual Operand* rem(Operand* a, Operand* b) = 0; + virtual Operand* shl(Operand* a, Operand* b) = 0; + virtual Operand* shr(Operand* a, Operand* b) = 0; + virtual Operand* ushr(Operand* a, Operand* b) = 0; + virtual Operand* and_(Operand* a, Operand* b) = 0; + virtual Operand* or_(Operand* a, Operand* b) = 0; + virtual Operand* xor_(Operand* a, Operand* b) = 0; + virtual Operand* neg(Operand* a) = 0; - virtual Stack* push1(Stack*, Operand*) = 0; - virtual Stack* push2(Stack*, Operand*) = 0; - virtual Stack* push2z(Stack*, Operand*) = 0; - virtual Stack* push4(Stack*, Operand*) = 0; - virtual Stack* push8(Stack*, Operand*) = 0; - virtual Stack* pop4(Stack*, Operand*) = 0; - virtual Stack* pop8(Stack*, Operand*) = 0; - virtual void mov1(Operand* src, Operand* dst) = 0; - virtual void mov2(Operand* src, Operand* dst) = 0; - virtual void mov4(Operand* src, Operand* dst) = 0; - virtual void mov8(Operand* src, Operand* dst) = 0; - virtual void mov1ToW(Operand* src, Operand* dst) = 0; - virtual void mov2ToW(Operand* src, Operand* dst) = 0; - virtual void mov2zToW(Operand* src, Operand* dst) = 0; - virtual void mov4To8(Operand* src, Operand* dst) = 0; - virtual void cmp4(Operand* subtrahend, Operand* minuend) = 0; - virtual void cmp8(Operand* subtrahend, Operand* minuend) = 0; - virtual void jl(Operand*) = 0; - virtual void jg(Operand*) = 0; - virtual void jle(Operand*) = 0; - virtual void jge(Operand*) = 0; - virtual void je(Operand*) = 0; - virtual void jne(Operand*) = 0; - virtual void jmp(Operand*) = 0; - virtual void add4(Operand* v, Operand* dst) = 0; - virtual void add8(Operand* v, Operand* dst) = 0; - virtual void sub4(Operand* v, Operand* dst) = 0; - virtual void sub8(Operand* v, Operand* dst) = 0; - virtual void mul4(Operand* v, Operand* dst) = 0; - virtual void mul8(Operand* v, Operand* dst) = 0; - virtual void div4(Operand* v, Operand* dst) = 0; - virtual void div8(Operand* v, Operand* dst) = 0; - virtual void rem4(Operand* v, Operand* dst) = 0; - virtual void rem8(Operand* v, Operand* dst) = 0; - virtual void shl4(Operand* v, Operand* dst) = 0; - virtual void shl8(Operand* v, Operand* dst) = 0; - virtual void shr4(Operand* v, Operand* dst) = 0; - virtual void shr8(Operand* v, Operand* dst) = 0; - virtual void ushr4(Operand* v, Operand* dst) = 0; - virtual void ushr8(Operand* v, Operand* dst) = 0; - virtual void and4(Operand* v, Operand* dst) = 0; - virtual void and8(Operand* v, Operand* dst) = 0; - virtual void or4(Operand* v, Operand* dst) = 0; - virtual void or8(Operand* v, Operand* dst) = 0; - virtual void xor4(Operand* v, Operand* dst) = 0; - virtual void xor8(Operand* v, Operand* dst) = 0; - virtual void neg4(Operand*) = 0; - virtual void neg8(Operand*) = 0; - - virtual void prologue() = 0; - virtual void reserve(unsigned size) = 0; - virtual void epilogue() = 0; - - virtual void startLogicalIp(unsigned) = 0; - - virtual unsigned codeSize() = 0; + virtual unsigned compile() = 0; virtual unsigned poolSize() = 0; - virtual void writeTo(uint8_t*) = 0; - - virtual void updateCall(void* returnAddress, void* newTarget) = 0; + virtual void writeTo(uint8_t* dst) = 0; virtual void dispose() = 0; }; Compiler* -makeCompiler(System* system, Allocator* allocator, Zone* zone, - void* indirectCaller); +makeCompiler(System* system, Assembler* assembler, Zone* zone); } // namespace vm diff --git a/src/compiler2.cpp b/src/compiler2.cpp deleted file mode 100644 index af7a486c5e..0000000000 --- a/src/compiler2.cpp +++ /dev/null @@ -1,1482 +0,0 @@ -#include "compiler2.h" -#include "assembler.h" - -using namespace vm; - -namespace { - -class Context; -class MyOperand; -class ConstantValue; -class AddressValue; -class RegisterValue; -class MemoryValue; -class Event; - -enum SyncType { - SyncForCall, - SyncForJump -}; - -class Value { - public: - virtual ~Value() { } - - virtual bool equals(Value*) { return false; } - virtual bool equals(RegisterValue*) { return false; } - - virtual void preserve(Context*) { } - virtual void acquire(Context*, MyOperand*) { } - virtual void release(Context*, MyOperand*) { } - - virtual RegisterValue* toRegister(Context*, unsigned size) = 0; - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) = 0; -}; - -class MyOperand: public Compiler::Operand { - public: - MyOperand(unsigned size, Value* value): - size(size), event(0), value(value), target(0), index(0), next(0) - { } - - unsigned size; - Event* event; - Value* value; - Value* target; - unsigned index; - MyOperand* next; -}; - -class State { - public: - State(State* s): - stack(s ? s->stack : 0), - next(s) - { } - - MyOperand* stack; - State* next; -}; - -class LogicalInstruction { - public: - unsigned visits; - Event* firstEvent; - Event* lastEvent; - unsigned machineOffset; - int predecessor; -}; - -class RegisterElement { - public: - bool reserved; - MyOperand* operand; -}; - -class ConstantPoolNode { - public: - ConstantPoolNode(Promise* promise): promise(promise), next(0) { } - - Promise* promise; - ConstantPoolNode* next; -}; - -class Junction { - public: - Junction(unsigned logicalIp, Junction* next): - logicalIp(logicalIp), - next(next) - { } - - unsigned logicalIp; - Junction* next; -}; - -class Context { - public: - Context(System* system, Assembler* assembler, Zone* zone): - system(system), - assembler(assembler), - zone(zone), - logicalIp(-1), - state(new (zone->allocate(sizeof(State))) State(0)), - event(0), - logicalCode(0), - logicalCodeLength(0), - stackOffset(0), - registers(static_cast - (zone->allocate - (sizeof(RegisterElement) * assembler->registerCount()))), - firstConstant(0), - lastConstant(0), - constantCount(0), - junctions(0), - machineCode(0) - { - memset(registers, 0, sizeof(RegisterElement) * assembler->registerCount()); - - registers[assembler->base()].reserved = true; - registers[assembler->stack()].reserved = true; - registers[assembler->thread()].reserved = true; - } - - System* system; - Assembler* assembler; - Zone* zone; - int logicalIp; - State* state; - Event* event; - LogicalInstruction* logicalCode; - unsigned logicalCodeLength; - unsigned stackOffset; - RegisterElement* registers; - ConstantPoolNode* firstConstant; - ConstantPoolNode* lastConstant; - unsigned constantCount; - Junction* junctions; - uint8_t* machineCode; -}; - -inline void NO_RETURN -abort(Context* c) -{ - abort(c->system); -} - -#ifndef NDEBUG -inline void -assert(Context* c, bool v) -{ - assert(c->system, v); -} -#endif // not NDEBUG - -inline void -expect(Context* c, bool v) -{ - expect(c->system, v); -} - -void -apply(Context* c, UnaryOperation op, unsigned size, Value* a) -{ - OperandType type; - Assembler::Operand* operand; - a->asAssemblerOperand(c, &type, &operand); - - c->assembler->apply(op, size, type, operand); -} - -void -apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b) -{ - OperandType aType; - Assembler::Operand* aOperand; - a->asAssemblerOperand(c, &aType, &aOperand); - - OperandType bType; - Assembler::Operand* bOperand; - b->asAssemblerOperand(c, &bType, &bOperand); - - c->assembler->apply(op, size, aType, aOperand, bType, bOperand); -} - -class ResolvedPromise: public Promise { - public: - ResolvedPromise(int64_t value): value_(value) { } - - virtual int64_t value() { - return value_; - } - - virtual bool resolved() { - return true; - } - - int64_t value_; -}; - -class PoolPromise: public Promise { - public: - PoolPromise(Context* c, int key): c(c), key(key) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + c->assembler->length() + key); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0; - } - - Context* c; - int key; -}; - -class CodePromise: public Promise { - public: - CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->machineCode + offset); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0 and offset >= 0; - } - - Context* c; - int offset; - CodePromise* next; -}; - -class IpPromise: public Promise { - public: - IpPromise(Context* c, int logicalIp): - c(c), - logicalIp(logicalIp) - { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + c->logicalCode[logicalIp].machineOffset); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0; - } - - Context* c; - int logicalIp; -}; - -RegisterValue* -freeRegister(Context* c, unsigned size); - -class ConstantValue: public Value { - public: - ConstantValue(Promise* value): value(value) { } - - virtual RegisterValue* toRegister(Context* c, unsigned size); - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Constant; - *operand = &value; - } - - Assembler::Constant value; -}; - -ConstantValue* -constant(Context* c, Promise* value) -{ - return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); -} - -class AddressValue: public Value { - public: - AddressValue(Promise* address): address(address) { } - - virtual RegisterValue* toRegister(Context* c, unsigned size); - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Address; - *operand = &address; - } - - Assembler::Address address; -}; - -AddressValue* -address(Context* c, Promise* address) -{ - return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address); -} - -void preserve(Context* c, int reg); - -class RegisterValue: public Value { - public: - RegisterValue(int low, int high): register_(low, high) { } - - virtual bool equals(Value* o) { return o->equals(this); } - - virtual bool equals(RegisterValue* o) { - return o->register_.low == register_.low - and o->register_.high == register_.high; - } - - virtual void preserve(Context* c) { - ::preserve(c, register_.low); - if (register_.high >= 0) ::preserve(c, register_.high); - } - - virtual void acquire(Context* c, MyOperand* a) { - preserve(c); - c->registers[register_.low].operand = a; - if (register_.high >= 0) c->registers[register_.high].operand = a; - } - - virtual void release(Context* c, MyOperand* a UNUSED) { - assert(c, a == c->registers[register_.low].operand); - - c->registers[register_.low].operand = 0; - if (register_.high >= 0) c->registers[register_.high].operand = 0; - } - - virtual RegisterValue* toRegister(Context*, unsigned) { - return this; - } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Register; - *operand = ®ister_; - } - - Assembler::Register register_; -}; - -RegisterValue* -register_(Context* c, int low, int high = NoRegister) -{ - return new (c->zone->allocate(sizeof(RegisterValue))) - RegisterValue(low, high); -} - -class MemoryValue: public Value { - public: - MemoryValue(int base, int offset, int index, unsigned scale, - TraceHandler* traceHandler): - value(base, offset, index, scale, traceHandler) - { } - - virtual RegisterValue* toRegister(Context* c, unsigned size) { - RegisterValue* v = freeRegister(c, size); - apply(c, Move, size, this, v); - return v; - } - - virtual int base(Context*) { - return value.base; - } - - virtual int index(Context*) { - return value.index; - } - - virtual void asAssemblerOperand(Context* c, - OperandType* type, - Assembler::Operand** operand) - { - value.base = base(c); - value.index = index(c); - *type = Memory; - *operand = &value; - } - - Assembler::Memory value; -}; - -MemoryValue* -memory(Context* c, int base, int offset, int index, unsigned scale, - TraceHandler* traceHandler) -{ - return new (c->zone->allocate(sizeof(MemoryValue))) - MemoryValue(base, offset, index, scale, traceHandler); -} - -int -toRegister(Context* c, MyOperand* a) -{ - assert(c, a->size == BytesPerWord); - - return a->value->toRegister(c, a->size)->register_.low; -} - -class AbstractMemoryValue: public MemoryValue { - public: - AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, - unsigned scale, TraceHandler* traceHandler): - MemoryValue(NoRegister, offset, NoRegister, scale, traceHandler), - base_(base), index_(index) - { } - - virtual int base(Context* c) { - return ::toRegister(c, base_); - } - - virtual int index(Context* c) { - return index_ ? ::toRegister(c, base_) : NoRegister; - } - - MyOperand* base_; - MyOperand* index_; -}; - -AbstractMemoryValue* -memory(Context* c, MyOperand* base, int offset, MyOperand* index, - unsigned scale, TraceHandler* traceHandler) -{ - return new (c->zone->allocate(sizeof(AbstractMemoryValue))) - AbstractMemoryValue(base, offset, index, scale, traceHandler); -} - -class Event { - public: - Event(Context* c): next(0), stack(c->state->stack), promises(0) { - if (c->event) { - c->event->next = this; - } - - if (c->logicalCode[c->logicalIp].firstEvent == 0) { - c->logicalCode[c->logicalIp].firstEvent = this; - } - - c->event = this; - } - - Event(Event* next): next(next) { } - - virtual ~Event() { } - - virtual Value* target(Context* c, MyOperand* value) = 0; - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) = 0; - virtual void compile(Context* c) = 0; - - Event* next; - MyOperand* stack; - CodePromise* promises; -}; - -class ArgumentEvent: public Event { - public: - ArgumentEvent(Context* c, MyOperand* a, unsigned index): - Event(c), a(a), index(index) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == a); - - if (index < c->assembler->argumentRegisterCount()) { - return register_(c, c->assembler->argumentRegister(index)); - } else { - return memory(c, c->assembler->base(), - (v->index + c->stackOffset) * BytesPerWord, - NoRegister, 0, 0); - } - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == a); - a = new_; - new_->target = old->target; - } - - virtual void compile(Context* c) { - a->value->release(c, a); - a->target->preserve(c); - - if (not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); - } - } - - MyOperand* a; - unsigned index; -}; - -void -appendArgument(Context* c, MyOperand* value, unsigned index) -{ - new (c->zone->allocate(sizeof(ArgumentEvent))) - ArgumentEvent(c, value, index); -} - -class ReturnEvent: public Event { - public: - ReturnEvent(Context* c, MyOperand* a): - Event(c), a(a) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == a); - - return register_(c, c->assembler->returnLow(), c->assembler->returnHigh()); - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == a); - a = new_; - a->target = old->target; - } - - virtual void compile(Context* c) { - a->value->release(c, a); - - if (not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); - } - c->assembler->apply(Return); - } - - MyOperand* a; -}; - -void -appendReturn(Context* c, MyOperand* value) -{ - new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, value); -} - -class SyncForCallEvent: public Event { - public: - SyncForCallEvent(Context* c, MyOperand* src, MyOperand* dst): - Event(c), src(src), dst(dst) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == src); - - return memory(c, c->assembler->base(), - (v->index + c->stackOffset) * BytesPerWord, - NoRegister, 0, 0); - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == src); - src = new_; - src->target = old->target; - } - - virtual void compile(Context* c) { - src->value->release(c, src); - - if (not src->target->equals(src->value)) { - apply(c, Move, src->size, src->value, src->target); - } - } - - MyOperand* src; - MyOperand* dst; -}; - -void -appendSyncForCall(Context* c, MyOperand* src, MyOperand* dst) -{ - new (c->zone->allocate(sizeof(SyncForCallEvent))) - SyncForCallEvent(c, src, dst); -} - -class SyncForJumpEvent: public Event { - public: - SyncForJumpEvent(Context* c, MyOperand* src, MyOperand* dst): - Event(c), src(src), dst(dst) - { } - - SyncForJumpEvent(Event* next, MyOperand* src, MyOperand* dst): - Event(next), src(src), dst(dst) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == src); - - if (BytesPerWord == 4 and v->size == 8) { - return register_(c, c->assembler->stackSyncRegister(v->index), - c->assembler->stackSyncRegister(v->index + 4)); - } else { - return register_(c, c->assembler->stackSyncRegister(v->index)); - } - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == src); - src = new_; - src->target = old->target; - } - - virtual void compile(Context* c) { - src->value->release(c, src); - src->target->acquire(c, dst); - - if (not src->target->equals(src->value)) { - apply(c, Move, src->size, src->value, src->target); - } - - dst->value = src->target; - } - - MyOperand* src; - MyOperand* dst; -}; - -void -appendSyncForJump(Context* c, MyOperand* src, MyOperand* dst) -{ - new (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(c, src, dst); -} - -class CallEvent: public Event { - public: - CallEvent(Context* c, MyOperand* address, MyOperand* result, - unsigned stackOffset, bool alignCall, - TraceHandler* traceHandler): - Event(c), - address(address), - result(result), - stackOffset(stackOffset), - alignCall(alignCall), - traceHandler(traceHandler) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == address); - - return 0; - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == address); - address = new_; - } - - virtual void compile(Context* c) { - address->value->release(c, address); - - if (result->event) { - result->value = register_ - (c, c->assembler->returnLow(), c->assembler->returnHigh()); - result->value->acquire(c, result); - } - - apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()), - memory(c, c->assembler->base(), stackOffset * BytesPerWord, - NoRegister, 0, 0)); - - apply(c, Call, address->size, address->value); - } - - MyOperand* address; - MyOperand* result; - unsigned stackOffset; - bool alignCall; - TraceHandler* traceHandler; -}; - -void -appendCall(Context* c, MyOperand* address, MyOperand* result, - unsigned stackOffset, bool alignCall, - TraceHandler* traceHandler) -{ - new (c->zone->allocate(sizeof(CallEvent))) - CallEvent(c, address, result, stackOffset, alignCall, traceHandler); -} - -int -freeRegister(Context* c) -{ - for (unsigned i = 0; i < c->assembler->registerCount(); ++i) { - if ((not c->registers[i].reserved) - and c->registers[i].operand == 0) - { - return i; - } - } - - for (unsigned i = 0; i < c->assembler->registerCount(); ++i) { - if (not c->registers[i].reserved) { - return i; - } - } - - abort(c); -} - -RegisterValue* -freeRegister(Context* c, unsigned size) -{ - if (BytesPerWord == 4 and size == 8) { - return register_(c, freeRegister(c), freeRegister(c)); - } else { - return register_(c, freeRegister(c)); - } -} - -class MoveEvent: public Event { - public: - MoveEvent(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst): - Event(c), type(type), src(src), dst(dst) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == src); - - return v->event->target(c, dst); - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == src); - src = new_; - src->target = old->target; - } - - virtual void compile(Context* c) { - if (src->target == 0) { - src->target = freeRegister(c, src->size); - } - - src->value->release(c, src); - src->target->acquire(c, dst); - - apply(c, type, src->size, src->value, src->target); - - dst->value = src->target; - } - - BinaryOperation type; - MyOperand* src; - MyOperand* dst; -}; - -void -appendMove(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst) -{ - new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, src, dst); -} - -class BranchEvent: public Event { - public: - BranchEvent(Context* c, UnaryOperation type, MyOperand* a, MyOperand* b, - MyOperand* address): - Event(c), type(type), a(a), b(b), address(address) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == a or v == b); - - return 0; - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - if (old == a) { - a = new_; - a->target = old->target; - } else { - assert(c, old == b); - b = new_; - b->target = old->target; - } - } - - virtual void compile(Context* c) { - a->value->release(c, a); - b->value->release(c, b); - address->value->release(c, address); - - apply(c, Compare, a->size, a->value, b->value); - apply(c, type, address->size, address->value); - } - - UnaryOperation type; - MyOperand* a; - MyOperand* b; - MyOperand* address; -}; - -void -appendBranch(Context* c, UnaryOperation type, MyOperand* a, MyOperand* b, - MyOperand* address) -{ - new (c->zone->allocate(sizeof(BranchEvent))) - BranchEvent(c, type, a, b, address); -} - -class JumpEvent: public Event { - public: - JumpEvent(Context* c, MyOperand* address): - Event(c), - address(address) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == address); - - return 0; - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == address); - address = new_; - } - - virtual void compile(Context* c) { - address->value->release(c, address); - - apply(c, Jump, address->size, address->value); - } - - MyOperand* address; - unsigned stackOffset; - bool alignCall; - TraceHandler* traceHandler; -}; - -void -appendJump(Context* c, MyOperand* address) -{ - new (c->zone->allocate(sizeof(BranchEvent))) JumpEvent(c, address); -} - -class CombineEvent: public Event { - public: - CombineEvent(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b, - MyOperand* result): - Event(c), type(type), a(a), b(b), result(result) - { } - - virtual Value* target(Context* c, MyOperand* v) { - Assembler::Register ar(NoRegister, NoRegister); - Assembler::Register br(NoRegister, NoRegister); - c->assembler->getTargets(type, v->size, &ar, &br); - - if (v == a) { - if (ar.low == NoRegister) { - return 0; - } else { - return register_(c, ar.low, ar.high); - } - } else { - assert(c, v == b); - - if (br.low == NoRegister) { - return result->event->target(c, result); - } else { - return register_(c, br.low, br.high); - } - } - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - if (old == a) { - a = new_; - a->target = old->target; - } else { - assert(c, old == b); - b = new_; - b->target = old->target; - } - } - - virtual void compile(Context* c) { - a->value->release(c, a); - b->value->release(c, b); - b->value->acquire(c, result); - - if (a->target and not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); - } - if (b->target and not b->target->equals(b->value)) { - apply(c, Move, b->size, b->value, b->target); - } - - apply(c, type, a->size, a->value, b->value); - - result->value = b->value; - } - - BinaryOperation type; - MyOperand* a; - MyOperand* b; - MyOperand* result; -}; - -void -appendCombine(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b, - MyOperand* result) -{ - new (c->zone->allocate(sizeof(CombineEvent))) - CombineEvent(c, type, a, b, result); -} - -class TranslateEvent: public Event { - public: - TranslateEvent(Context* c, UnaryOperation type, MyOperand* a, - MyOperand* result): - Event(c), type(type), a(a), result(result) - { } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == a); - - Assembler::Register r(NoRegister, NoRegister); - c->assembler->getTargets(type, v->size, &r); - - if (r.low == NoRegister) { - return result->event->target(c, result); - } else { - return register_(c, r.low, r.high); - } - } - - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == a); - a = new_; - a->target = old->target; - } - - virtual void compile(Context* c) { - result->value->acquire(c, result); - - apply(c, type, a->size, a->value); - - result->value = a->value; - } - - UnaryOperation type; - MyOperand* a; - MyOperand* result; -}; - -void -appendTranslate(Context* c, UnaryOperation type, MyOperand* a, - MyOperand* result) -{ - new (c->zone->allocate(sizeof(TranslateEvent))) - TranslateEvent(c, type, a, result); -} - -RegisterValue* -ConstantValue::toRegister(Context* c, unsigned size) -{ - RegisterValue* v = freeRegister(c, size); - apply(c, Move, size, this, v); - return v; -} - -RegisterValue* -AddressValue::toRegister(Context* c, unsigned size) -{ - RegisterValue* v = freeRegister(c, size); - apply(c, Move, size, this, v); - return v; -} - -void -preserve(Context* c, int reg) -{ - MyOperand* a = c->registers[reg].operand; - if (a) { - MemoryValue* dst = memory - (c, c->assembler->base(), (a->index + c->stackOffset) * BytesPerWord, - -1, 0, 0); - - apply(c, Move, a->size, a->value, dst); - - a->value = dst; - c->registers[reg].operand = 0; - } -} - -MyOperand* -operand(Context* c, unsigned size, Value* value = 0) -{ - return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(size, value); -} - -void -pushState(Context* c) -{ - c->state = new (c->zone->allocate(sizeof(State))) - State(c->state); -} - -void -popState(Context* c) -{ - c->state = new (c->zone->allocate(sizeof(State))) - State(c->state->next); -} - -void -push(Context* c, MyOperand* o) -{ - static_cast(o)->next = c->state->stack; - c->state->stack = static_cast(o); -} - -MyOperand* -pop(Context* c) -{ - MyOperand* o = c->state->stack; - c->state->stack = o->next; - return o; -} - -void -syncStack(Context* c, SyncType type) -{ - MyOperand* top = 0; - MyOperand* new_ = 0; - for (MyOperand* old = c->state->stack; old; old = old->next) { - MyOperand* n = operand(c, old->size, 0); - if (new_) { - new_->next = n; - } else { - top = n; - } - new_ = n; - new_->index = old->index; - - if (type == SyncForCall) { - appendSyncForCall(c, old, new_); - } else { - appendSyncForJump(c, old, new_); - } - } - - c->state->stack = top; -} - -void -updateJunctions(Context* c) -{ - for (Junction* j = c->junctions; j; j = j->next) { - LogicalInstruction* i = c->logicalCode + j->logicalIp; - - if (i->predecessor >= 0) { - LogicalInstruction* p = c->logicalCode + i->predecessor; - - MyOperand* new_ = 0; - for (MyOperand* old = i->firstEvent->stack; old; old = old->next) { - MyOperand* n = operand(c, old->size, 0); - if (new_) new_->next = n; - new_ = n; - new_->index = old->index; - - if (old->event) { - old->event->replace(c, old, new_); - } - - p->lastEvent = p->lastEvent->next = new - (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(p->lastEvent->next, old, new_); - } - } - } -} - -void -compile(Context* c) -{ - for (Event* e = c->logicalCode[0].firstEvent; e; e = e->next) { - e->compile(c); - } -} - -class MyCompiler: public Compiler { - public: - MyCompiler(System* s, Assembler* assembler, Zone* zone): - c(s, assembler, zone) - { } - - virtual void pushState() { - ::pushState(&c); - } - - virtual void popState() { - ::pushState(&c); - } - - virtual void init(unsigned logicalCodeLength, unsigned stackOffset) { - c.logicalCodeLength = logicalCodeLength; - c.stackOffset = stackOffset; - c.logicalCode = static_cast - (c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength)); - memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength); - } - - virtual void visitLogicalIp(unsigned logicalIp) { - if ((++ c.logicalCode[logicalIp].visits) == 1) { - c.junctions = new (c.zone->allocate(sizeof(Junction))) - Junction(logicalIp, c.junctions); - } - } - - virtual void startLogicalIp(unsigned logicalIp) { - if (c.logicalIp >= 0) { - c.logicalCode[c.logicalIp].lastEvent = c.event; - } - - c.logicalIp = logicalIp; - } - - virtual Promise* machineIp(unsigned logicalIp) { - return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp); - } - - virtual Promise* poolAppend(intptr_t value) { - return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); - } - - virtual Promise* poolAppendPromise(Promise* value) { - Promise* p = new (c.zone->allocate(sizeof(PoolPromise))) - PoolPromise(&c, c.constantCount); - - ConstantPoolNode* constant - = new (c.zone->allocate(sizeof(ConstantPoolNode))) - ConstantPoolNode(value); - - if (c.firstConstant) { - c.lastConstant->next = constant; - } else { - c.firstConstant = constant; - } - c.lastConstant = constant; - ++ c.constantCount; - - return p; - } - - virtual Operand* constant(int64_t value) { - return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); - } - - virtual Operand* promiseConstant(Promise* value) { - return operand(&c, 0, ::constant(&c, value)); - } - - virtual Operand* address(Promise* address) { - return operand(&c, 0, ::address(&c, address)); - } - - virtual Operand* memory(Operand* base, - int displacement = 0, - Operand* index = 0, - unsigned scale = 1, - TraceHandler* traceHandler = 0) - { - return operand - (&c, 0, ::memory - (&c, static_cast(base), displacement, - static_cast(index), scale, traceHandler)); - } - - virtual Operand* stack() { - return operand(&c, BytesPerWord, register_(&c, c.assembler->stack())); - } - - virtual Operand* base() { - return operand(&c, BytesPerWord, register_(&c, c.assembler->base())); - } - - virtual Operand* thread() { - return operand(&c, BytesPerWord, register_(&c, c.assembler->thread())); - } - - virtual Operand* label() { - return operand(&c, BytesPerWord, ::constant(&c, 0)); - } - - Promise* machineIp() { - return c.event->promises = new (c.zone->allocate(sizeof(CodePromise))) - CodePromise(&c, c.event->promises); - } - - virtual void mark(Operand* label) { - static_cast(static_cast(label)->value)->value - = machineIp(); - } - - virtual void push(Operand* value) { - ::push(&c, static_cast(value)); - } - - virtual Operand* pop() { - return ::pop(&c); - } - - virtual void push(unsigned count) { - for (unsigned i = 0; i < count; ++i) ::push(&c, 0); - } - - virtual void pop(unsigned count) { - for (unsigned i = 0; i < count; ++i) ::pop(&c); - } - - virtual Operand* call(Operand* address, - unsigned resultSize = 4, - unsigned argumentFootprint = 0, - bool alignCall = false, - TraceHandler* traceHandler = 0) - { - for (unsigned i = 0; i < argumentFootprint; ++i) { - MyOperand* a = ::pop(&c); - appendArgument(&c, a, i); - if (BytesPerWord == 4 and a->size == 8) { - ++ i; - } - } - - syncStack(&c, SyncForCall); - - unsigned stackOffset = c.stackOffset + c.state->stack->index - + (argumentFootprint > c.assembler->argumentRegisterCount() ? - argumentFootprint - c.assembler->argumentRegisterCount() : 0); - - MyOperand* result = operand(&c, resultSize, 0); - appendCall(&c, static_cast(address), result, stackOffset, - alignCall, traceHandler); - return result; - } - - virtual void return_(Operand* value) { - appendReturn(&c, static_cast(value)); - } - - virtual void store1(Operand* src, Operand* dst) { - appendMove(&c, Store1, static_cast(src), - static_cast(dst)); - } - - virtual void store2(Operand* src, Operand* dst) { - appendMove(&c, Store2, static_cast(src), - static_cast(dst)); - } - - virtual void store4(Operand* src, Operand* dst) { - appendMove(&c, Store4, static_cast(src), - static_cast(dst)); - } - - virtual void store8(Operand* src, Operand* dst) { - appendMove(&c, Store8, static_cast(src), - static_cast(dst)); - } - - virtual Operand* load1(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load1, static_cast(src), dst); - return dst; - } - - virtual Operand* load2(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load2, static_cast(src), dst); - return dst; - } - - virtual Operand* load2z(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load2z, static_cast(src), dst); - return dst; - } - - virtual Operand* load4(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load4, static_cast(src), dst); - return dst; - } - - virtual Operand* load8(Operand* src) { - MyOperand* dst = operand(&c, 8); - appendMove(&c, Load8, static_cast(src), dst); - return dst; - } - - virtual void jl(Operand* a, Operand* b, Operand* address) { - syncStack(&c, SyncForJump); - - appendBranch(&c, JumpIfLess, static_cast(a), - static_cast(b), static_cast(address)); - } - - virtual void jg(Operand* a, Operand* b, Operand* address) { - syncStack(&c, SyncForJump); - - appendBranch(&c, JumpIfGreater, static_cast(a), - static_cast(b), static_cast(address)); - } - - virtual void jle(Operand* a, Operand* b, Operand* address) { - syncStack(&c, SyncForJump); - - appendBranch(&c, JumpIfLessOrEqual, static_cast(a), - static_cast(b), static_cast(address)); - } - - virtual void jge(Operand* a, Operand* b, Operand* address) { - syncStack(&c, SyncForJump); - - appendBranch(&c, JumpIfGreaterOrEqual, static_cast(a), - static_cast(b), static_cast(address)); - } - - virtual void je(Operand* a, Operand* b, Operand* address) { - syncStack(&c, SyncForJump); - - appendBranch(&c, JumpIfEqual, static_cast(a), - static_cast(b), static_cast(address)); - } - - virtual void jne(Operand* a, Operand* b, Operand* address) { - syncStack(&c, SyncForJump); - - appendBranch(&c, JumpIfNotEqual, static_cast(a), - static_cast(b), static_cast(address)); - } - - virtual void jmp(Operand* address) { - syncStack(&c, SyncForJump); - - appendJump(&c, static_cast(address)); - } - - virtual Operand* add(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Add, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* sub(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Subtract, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* mul(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Multiply, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* div(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Divide, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* rem(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Remainder, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* shl(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, ShiftLeft, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* shr(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, ShiftRight, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* ushr(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, UnsignedShiftRight, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* and_(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, And, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* or_(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Or, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* xor_(Operand* a, Operand* b) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendCombine(&c, Xor, static_cast(a), - static_cast(b), result); - return result; - } - - virtual Operand* neg(Operand* a) { - MyOperand* result = operand(&c, static_cast(a)->size); - appendTranslate(&c, Negate, static_cast(a), result); - return result; - } - - virtual unsigned compile() { - updateJunctions(&c); - ::compile(&c); - return c.assembler->length(); - } - - virtual unsigned poolSize() { - return c.constantCount; - } - - virtual void writeTo(uint8_t* dst) { - c.machineCode = dst; - c.assembler->writeTo(dst); - - int i = 0; - for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) { - *reinterpret_cast(dst + c.assembler->length() + (i++)) - = n->promise->value(); - } - } - - virtual void dispose() { - // ignore - } - - Context c; -}; - -} // namespace - -namespace vm { - -Compiler* -makeCompiler(System* system, Assembler* assembler, Zone* zone) -{ - return new (zone->allocate(sizeof(MyCompiler))) - MyCompiler(system, assembler, zone); -} - -} // namespace vm diff --git a/src/compiler2.h b/src/compiler2.h deleted file mode 100644 index 3847877889..0000000000 --- a/src/compiler2.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef COMPILER_H -#define COMPILER_H - -#include "system.h" -#include "zone.h" -#include "assembler.h" - -namespace vm { - -class Compiler { - public: - class Operand { }; - - virtual ~Compiler() { } - - virtual void pushState() = 0; - virtual void popState() = 0; - - virtual void init(unsigned logicalCodeSize, unsigned localFootprint) = 0; - - virtual void visitLogicalIp(unsigned logicalIp) = 0; - virtual void startLogicalIp(unsigned logicalIp) = 0; - - virtual Promise* machineIp(unsigned logicalIp) = 0; - - virtual Promise* poolAppend(intptr_t value) = 0; - virtual Promise* poolAppendPromise(Promise* value) = 0; - - virtual Operand* constant(int64_t value) = 0; - virtual Operand* promiseConstant(Promise* value) = 0; - virtual Operand* address(Promise* address) = 0; - virtual Operand* memory(Operand* base, - int displacement = 0, - Operand* index = 0, - unsigned scale = 1, - TraceHandler* traceHandler = 0) = 0; - virtual Operand* stack() = 0; - virtual Operand* base() = 0; - virtual Operand* thread() = 0; - - virtual Operand* label() = 0; - virtual void mark(Operand* label) = 0; - - virtual void push(Operand* value) = 0; - virtual Operand* pop() = 0; - virtual void push(unsigned count) = 0; - virtual void pop(unsigned count) = 0; - - virtual Operand* call(Operand* address, - unsigned resultSize = 4, - unsigned argumentCount = 0, - bool aligned = false, - TraceHandler* traceHandler = 0) = 0; - virtual void return_(Operand* value) = 0; - - virtual void store1(Operand* src, Operand* dst) = 0; - virtual void store2(Operand* src, Operand* dst) = 0; - virtual void store4(Operand* src, Operand* dst) = 0; - virtual void store8(Operand* src, Operand* dst) = 0; - virtual Operand* load1(Operand* src) = 0; - virtual Operand* load2(Operand* src) = 0; - virtual Operand* load2z(Operand* src) = 0; - virtual Operand* load4(Operand* src) = 0; - virtual Operand* load8(Operand* src) = 0; - virtual void jl(Operand* a, Operand* b, Operand* address) = 0; - virtual void jg(Operand* a, Operand* b, Operand* address) = 0; - virtual void jle(Operand* a, Operand* b, Operand* address) = 0; - virtual void jge(Operand* a, Operand* b, Operand* address) = 0; - virtual void je(Operand* a, Operand* b, Operand* address) = 0; - virtual void jne(Operand* a, Operand* b, Operand* address) = 0; - virtual void jmp(Operand* address) = 0; - virtual Operand* add(Operand* a, Operand* b) = 0; - virtual Operand* sub(Operand* a, Operand* b) = 0; - virtual Operand* mul(Operand* a, Operand* b) = 0; - virtual Operand* div(Operand* a, Operand* b) = 0; - virtual Operand* rem(Operand* a, Operand* b) = 0; - virtual Operand* shl(Operand* a, Operand* b) = 0; - virtual Operand* shr(Operand* a, Operand* b) = 0; - virtual Operand* ushr(Operand* a, Operand* b) = 0; - virtual Operand* and_(Operand* a, Operand* b) = 0; - virtual Operand* or_(Operand* a, Operand* b) = 0; - virtual Operand* xor_(Operand* a, Operand* b) = 0; - virtual Operand* neg(Operand* a) = 0; - - virtual unsigned compile() = 0; - virtual unsigned poolSize() = 0; - virtual void writeTo(uint8_t* dst) = 0; - - virtual void dispose() = 0; -}; - -Compiler* -makeCompiler(System* system, Allocator* allocator, Zone* zone, - void* indirectCaller); - -} // namespace vm - -#endif//COMPILER_H diff --git a/src/heap.cpp b/src/heap.cpp index ea067585ea..88ff7adf05 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -19,7 +19,7 @@ const unsigned InitialTenuredFixieCeilingInBytes = 4 * 1024 * 1024; const unsigned LowMemoryPaddingInBytes = 1024 * 1024; -const bool Verbose = false; +const bool Verbose = true; const bool Verbose2 = false; const bool Debug = false; const bool DebugFixies = false; diff --git a/src/x86.cpp b/src/x86.cpp index 79fdd0ad6c..61bf79860a 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -165,6 +165,10 @@ class MyAssembler: public Assembler { memcpy(instruction + 1, &v, 4); } + virtual void dispose() { + code.dispose(); + } + System* s; Vector code; Task* tasks;