From 5b2f351f01e37bc3d31fbbc13c1cc12d1db2ba70 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 11 Feb 2008 10:21:41 -0700 Subject: [PATCH 001/121] 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; From b9fa7179d991c92092fcadf4d871452e73f49b7d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 11 Feb 2008 17:20:32 -0700 Subject: [PATCH 002/121] more work on new compiler; addition now works --- makefile | 2 +- src/assembler.h | 29 ++-- src/compile.cpp | 10 +- src/compiler.cpp | 59 ++++--- src/x86.cpp | 400 +++++++++++++++++++++++++++++++++++++++++++---- test/Misc.java | 202 ++++++++++++------------ 6 files changed, 538 insertions(+), 164 deletions(-) diff --git a/makefile b/makefile index d82fd03411..141c37655b 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -MAKEFLAGS = -s +#MAKEFLAGS = -s name = vm diff --git a/src/assembler.h b/src/assembler.h index a8e85c0388..2bb0e24338 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -10,6 +10,8 @@ enum Operation { Return }; +const unsigned OperationCount = Return + 1; + enum UnaryOperation { Call, Push, @@ -23,19 +25,18 @@ enum UnaryOperation { Negate }; +const unsigned UnaryOperationCount = Negate + 1; + enum BinaryOperation { LoadAddress, - Move, - Store1, - Store2, - Store4, - Store8, - Load1, - Load2, - Load2z, - Load4, - Load8, - Load4To8, + Move1, + Move2, + Move4, + Move8, + Move1ToW, + Move2ToW, + Move2zToW, + Move4To8, Compare, Add, Subtract, @@ -50,6 +51,10 @@ enum BinaryOperation { Xor }; +const BinaryOperation Move = (BytesPerWord == 8 ? Move8 : Move4); + +const unsigned BinaryOperationCount = Xor + 1; + enum OperandType { Constant, Address, @@ -57,6 +62,8 @@ enum OperandType { Memory }; +const unsigned OperandTypeCount = Memory + 1; + const int NoRegister = -1; const int AnyRegister = -2; diff --git a/src/compile.cpp b/src/compile.cpp index 2673f1b4cd..21ffab2b54 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3,7 +3,7 @@ #include "vector.h" #include "process.h" #include "assembler.h" -#include "compiler2.h" +#include "compiler.h" #include "x86.h" using namespace vm; @@ -17,7 +17,7 @@ vmCall(); namespace { -const bool Verbose = false; +const bool Verbose = true; const bool DebugNatives = false; const bool DebugTraces = false; const bool DebugFrameMaps = false; @@ -403,7 +403,7 @@ class Context { { } ~Context() { - compiler->dispose(); + if (compiler) compiler->dispose(); assembler->dispose(); } @@ -3414,7 +3414,9 @@ finish(MyThread* t, Assembler* a, const char* name) a->writeTo(start); - logCompile(start, a->length(), 0, name, 0); + if (Verbose) { + logCompile(start, a->length(), 0, name, 0); + } return result; } diff --git a/src/compiler.cpp b/src/compiler.cpp index 76e2a206d3..a33eb661e8 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1,4 +1,4 @@ -#include "compiler2.h" +#include "compiler.h" #include "assembler.h" using namespace vm; @@ -527,11 +527,14 @@ class ReturnEvent: public Event { } virtual void compile(Context* c) { - a->value->release(c, a); + if (a) { + a->value->release(c, a); - if (not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); + if (not a->target->equals(a->value)) { + apply(c, Move, a->size, a->value, a->target); + } } + c->assembler->apply(Return); } @@ -743,7 +746,11 @@ class MoveEvent: public Event { virtual Value* target(Context* c, MyOperand* v) { assert(c, v == src); - return v->event->target(c, dst); + if (dst->value) { + return dst->value; + } else { + return v->event->target(c, dst); + } } virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { @@ -754,7 +761,11 @@ class MoveEvent: public Event { virtual void compile(Context* c) { if (src->target == 0) { - src->target = freeRegister(c, src->size); + if (dst->value) { + src->target = dst->value; + } else { + src->target = freeRegister(c, src->size); + } } src->value->release(c, src); @@ -1127,8 +1138,14 @@ updateJunctions(Context* c) void compile(Context* c) { - for (Event* e = c->logicalCode[0].firstEvent; e; e = e->next) { - e->compile(c); + for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { + fprintf(stderr, "compile ip %d\n", i); + for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { + fprintf(stderr, "compile ip %d event\n", i); + e->compile(c); + + if (e == c->logicalCode[i].lastEvent) break; + } } } @@ -1320,22 +1337,22 @@ class MyCompiler: public Compiler { } virtual void store1(Operand* src, Operand* dst) { - appendMove(&c, Store1, static_cast(src), + appendMove(&c, Move1, static_cast(src), static_cast(dst)); } virtual void store2(Operand* src, Operand* dst) { - appendMove(&c, Store2, static_cast(src), + appendMove(&c, Move2, static_cast(src), static_cast(dst)); } virtual void store4(Operand* src, Operand* dst) { - appendMove(&c, Store4, static_cast(src), + appendMove(&c, Move4, static_cast(src), static_cast(dst)); } virtual void store8(Operand* src, Operand* dst) { - appendMove(&c, Store8, static_cast(src), + appendMove(&c, Move8, static_cast(src), static_cast(dst)); } @@ -1347,37 +1364,39 @@ class MyCompiler: public Compiler { virtual Operand* load1(Operand* src) { MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load1, static_cast(src), dst); + appendMove(&c, Move1ToW, static_cast(src), dst); return dst; } virtual Operand* load2(Operand* src) { MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load2, static_cast(src), dst); + appendMove(&c, Move2ToW, static_cast(src), dst); return dst; } virtual Operand* load2z(Operand* src) { MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Load2z, static_cast(src), dst); + appendMove(&c, Move2zToW, 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; + if (BytesPerWord == 4) { + return load(src); + } else { + return load4To8(src); + } } virtual Operand* load8(Operand* src) { MyOperand* dst = operand(&c, 8); - appendMove(&c, Load8, static_cast(src), dst); + appendMove(&c, Move8, static_cast(src), dst); return dst; } virtual Operand* load4To8(Operand* src) { MyOperand* dst = operand(&c, 8); - appendMove(&c, Load4To8, static_cast(src), dst); + appendMove(&c, Move4To8, static_cast(src), dst); return dst; } diff --git a/src/x86.cpp b/src/x86.cpp index 61bf79860a..8809e9c650 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -3,9 +3,20 @@ using namespace vm; +#define INDEX1(a, b) ((a) + (BinaryOperationCount * (b))) + +#define CAST1(x) reinterpret_cast(x) + +#define INDEX2(a, b, c) \ + ((a) \ + + (BinaryOperationCount * (b)) \ + + (BinaryOperationCount * OperandTypeCount * (c))) + +#define CAST2(x) reinterpret_cast(x) + namespace { -enum Register { +enum { rax = 0, rcx = 1, rdx = 2, @@ -24,20 +35,355 @@ enum Register { r15 = 15, }; +inline bool +isInt8(intptr_t v) +{ + return v == static_cast(v); +} + +inline bool +isInt32(intptr_t v) +{ + return v == static_cast(v); +} + +class Task; + +class Context { + public: + Context(System* s, Allocator* a, Zone* zone): + s(s), zone(zone), code(s, a, 1024), tasks(0), result(0) + { } + + System* s; + Zone* zone; + Vector code; + Task* tasks; + uint8_t* result; +}; + +inline void NO_RETURN +abort(Context* c) +{ + abort(c->s); +} + +#ifndef NDEBUG +inline void +assert(Context* c, bool v) +{ + assert(c->s, v); +} +#endif // not NDEBUG + +inline void +expect(Context* c, bool v) +{ + expect(c->s, v); +} + +class CodePromise: public Promise { + public: + CodePromise(Context* c, unsigned offset): c(c), offset(offset) { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast(c->result + offset); + } + + abort(c); + } + + virtual bool resolved() { + return c->result != 0; + } + + Context* c; + unsigned offset; +}; + +CodePromise* +codePromise(Context* c, unsigned offset) +{ + return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); +} + class Task { public: Task(Task* next): next(next) { } virtual ~Task() { } - virtual void run(uint8_t* code) = 0; + virtual void run(Context* c) = 0; Task* next; }; +class OffsetTask: public Task { + public: + OffsetTask(Task* next, Promise* promise, int instructionOffset, + unsigned instructionSize): + Task(next), + promise(promise), + instructionOffset(instructionOffset), + instructionSize(instructionSize) + { } + + virtual void run(Context* c) { + uint8_t* instruction = c->result + instructionOffset; + intptr_t v = reinterpret_cast(promise->value()) + - instruction - instructionSize; + + expect(c, isInt32(v)); + + int32_t v4 = v; + memcpy(instruction + instructionSize - 4, &v4, 4); + } + + Promise* promise; + int instructionOffset; + unsigned instructionSize; +}; + +void +appendOffsetTask(Context* c, Promise* promise, int instructionOffset, + unsigned instructionSize) +{ + c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask + (c->tasks, promise, instructionOffset, instructionSize); +} + +void +encode(Context* c, uint8_t* instruction, unsigned length, int a, int 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 +rex(Context* c) +{ + if (BytesPerWord == 8) { + c->code.append(0x48); + } +} + +void +encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex) +{ + if (b->traceHandler) { + b->traceHandler->handleTrace(codePromise(c, c->code.length())); + } + + if (rex) { + ::rex(c); + } + + encode(c, &instruction, 1, a, b->base, b->offset, b->index, b->scale); +} + +void +encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b, + bool rex) +{ + if (b->traceHandler) { + b->traceHandler->handleTrace(codePromise(c, c->code.length())); + } + + if (rex) { + ::rex(c); + } + + uint8_t i[2] = { instruction >> 8, instruction & 0xff }; + encode(c, i, 2, a, b->base, b->offset, b->index, b->scale); +} + +typedef void (*OperationType)(Context*); +OperationType +Operations[OperationCount]; + +typedef void (*UnaryOperationType)(Context*, unsigned, Assembler::Operand*); +UnaryOperationType +UnaryOperations[UnaryOperationCount * OperandTypeCount]; + +typedef void (*BinaryOperationType) +(Context*, unsigned, Assembler::Operand*, Assembler::Operand*); +BinaryOperationType +BinaryOperations[BinaryOperationCount * OperandTypeCount * OperandTypeCount]; + +void +return_(Context* c) +{ + c->code.append(0xc3); +} + +void +unconditional(Context* c, unsigned jump, Assembler::Constant* a) +{ + appendOffsetTask(c, a->value, c->code.length(), 5); + + c->code.append(jump); + c->code.append4(0); +} + +void +conditional(Context* c, unsigned condition, Assembler::Constant* a) +{ + appendOffsetTask(c, a->value, c->code.length(), 6); + + c->code.append(0x0f); + c->code.append(condition); + c->code.append4(0); +} + +void +callC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + unconditional(c, 0xe8, a); +} + +void +jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) +{ + assert(c, size == BytesPerWord); + + c->code.append(0xff); + c->code.append(0xd0 | a->low); +} + +void +moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0xb8 | b->low); + c->code.appendAddress(a->value->value()); +} + +void +moveCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Memory* b) +{ + assert(c, isInt32(a->value->value())); // todo + assert(c, BytesPerWord == 8 or size == 4); // todo + + encode(c, 0xc7, 0, b, true); + c->code.append4(a->value->value()); +} + +void +moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) +{ + if (BytesPerWord == 4 and size == 8) { + moveRM(c, 4, a, b); + + Assembler::Register ah(a->high); + Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); + moveRM(c, 4, &ah, &bh); + } else if (BytesPerWord == 8 and size == 4) { + encode(c, 0x89, a->low, b, false); + } else { + encode(c, 0x89, a->low, b, true); + } +} + +void +moveRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + moveRR(c, 4, a, b); + + Assembler::Register ah(a->low); + Assembler::Register bh(b->low); + moveRR(c, 4, &ah, &bh); + } else { + rex(c); + c->code.append(0x89); + c->code.append(0xc0 | (a->low << 3) | b->low); + } +} + +void +move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) +{ + assert(c, BytesPerWord == 8); // todo + + encode(c, 0x63, b->low, a, true); +} + +void +addRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x01); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + +void +populateTables() +{ + Operations[Return] = return_; + + UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); + UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); + + BinaryOperations[INDEX2(Move4, Constant, Register)] = CAST2(moveCR); + BinaryOperations[INDEX2(Move8, Constant, Register)] = CAST2(moveCR); + BinaryOperations[INDEX2(Move4, Constant, Memory)] = CAST2(moveCM); + BinaryOperations[INDEX2(Move8, Constant, Memory)] = CAST2(moveCM); + BinaryOperations[INDEX2(Move4, Register, Memory)] = CAST2(moveRM); + BinaryOperations[INDEX2(Move8, Register, Memory)] = CAST2(moveRM); + BinaryOperations[INDEX2(Move4, Register, Register)] = CAST2(moveRR); + BinaryOperations[INDEX2(Move8, Register, Register)] = CAST2(moveRR); + BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); + BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); +} + class MyAssembler: public Assembler { public: - MyAssembler(System* s, Allocator* a): s(s), code(s, a, 1024), tasks(0) { } + MyAssembler(System* s, Allocator* a, Zone* zone): c(s, a, zone) { + static bool populated = false; + if (not populated) { + populated = true; + populateTables(); + } + } virtual unsigned registerCount() { return BytesPerWord == 4 ? 8 : 16; @@ -68,7 +414,7 @@ class MyAssembler: public Assembler { } virtual int argumentRegister(unsigned index) { - assert(s, BytesPerWord == 8); + assert(&c, BytesPerWord == 8); switch (index) { case 0: @@ -84,7 +430,7 @@ class MyAssembler: public Assembler { case 5: return r9; default: - abort(s); + abort(&c); } } @@ -101,7 +447,7 @@ class MyAssembler: public Assembler { case 4: return rdi; default: - abort(s); + abort(&c); } } @@ -123,42 +469,40 @@ class MyAssembler: public Assembler { b->high = NoRegister; } - virtual void apply(Operation /*op*/) { - // todo - abort(s); + virtual void apply(Operation op) { + Operations[op](&c); } - virtual void apply(UnaryOperation /*op*/, unsigned /*size*/, - OperandType /*type*/, Operand* /*operand*/) + virtual void apply(UnaryOperation op, unsigned size, + OperandType type, Operand* operand) { - // todo - abort(s); + UnaryOperations[INDEX1(op, type)](&c, size, operand); } - virtual void apply(BinaryOperation /*op*/, unsigned /*size*/, - OperandType /*aType*/, Operand* /*a*/, - OperandType /*bType*/, Operand* /*b*/) + virtual void apply(BinaryOperation op, unsigned size, + OperandType aType, Operand* a, + OperandType bType, Operand* b) { - // todo - abort(s); + BinaryOperations[INDEX2(op, aType, bType)](&c, size, a, b); } virtual void writeTo(uint8_t* dst) { - memcpy(dst, code.data, code.length()); + c.result = dst; + memcpy(dst, c.code.data, c.code.length()); - for (Task* t = tasks; t; t = t->next) { - t->run(dst); + for (Task* t = c.tasks; t; t = t->next) { + t->run(&c); } } virtual unsigned length() { - return code.length(); + return c.code.length(); } virtual void updateCall(void* returnAddress, void* newTarget) { uint8_t* instruction = static_cast(returnAddress) - 5; - assert(s, *instruction == 0xE8); - assert(s, reinterpret_cast(instruction + 1) % 4 == 0); + assert(&c, *instruction == 0xE8); + assert(&c, reinterpret_cast(instruction + 1) % 4 == 0); int32_t v = static_cast(newTarget) - static_cast(returnAddress); @@ -166,12 +510,10 @@ class MyAssembler: public Assembler { } virtual void dispose() { - code.dispose(); + c.code.dispose(); } - System* s; - Vector code; - Task* tasks; + Context c; }; } // namespace @@ -182,7 +524,7 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone) { return new (zone->allocate(sizeof(MyAssembler))) - MyAssembler(system, allocator); + MyAssembler(system, allocator, zone); } } // namespace vm diff --git a/test/Misc.java b/test/Misc.java index f75b38d92c..3565bd4871 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,120 +1,124 @@ public class Misc { - private static int alpha; - private static int beta; - private static byte byte1, byte2, byte3; - private int gamma; +// private static int alpha; +// private static int beta; +// private static byte byte1, byte2, byte3; +// private int gamma; - private String foo(String s) { - return s; - } +// private String foo(String s) { +// return s; +// } - public String bar(String s) { - return s; - } +// public String bar(String s) { +// return s; +// } - private static String baz(String s) { - return s; - } +// private static String baz(String s) { +// return s; +// } - private static void expect(boolean v) { - if (! v) throw new RuntimeException(); - } +// private static void expect(boolean v) { +// if (! v) throw new RuntimeException(); +// } - private synchronized byte sync() { - byte[] array = new byte[123]; - return array[42]; - } +// private synchronized byte sync() { +// byte[] array = new byte[123]; +// return array[42]; +// } - private static synchronized byte syncStatic(boolean throw_) { - byte[] array = new byte[123]; - if (throw_) { - throw new RuntimeException(); - } else { - return array[42]; - } - } +// private static synchronized byte syncStatic(boolean throw_) { +// byte[] array = new byte[123]; +// if (throw_) { +// throw new RuntimeException(); +// } else { +// return array[42]; +// } +// } - public static void putInt(int val, byte[] dst, int offset) { - System.out.println("put " + val); - dst[offset] = (byte)((val >> 24) & 0xff); - dst[offset+1] = (byte)((val >> 16) & 0xff); - dst[offset+2] = (byte)((val >> 8) & 0xff); - dst[offset+3] = (byte)((val ) & 0xff); - } +// public static void putInt(int val, byte[] dst, int offset) { +// System.out.println("put " + val); +// dst[offset] = (byte)((val >> 24) & 0xff); +// dst[offset+1] = (byte)((val >> 16) & 0xff); +// dst[offset+2] = (byte)((val >> 8) & 0xff); +// dst[offset+3] = (byte)((val ) & 0xff); +// } - public static void putLong(long val, byte[] dst, int offset) { - putInt((int)(val >> 32), dst, offset); - putInt((int)val, dst, offset + 4); - } +// public static void putLong(long val, byte[] dst, int offset) { +// putInt((int)(val >> 32), dst, offset); +// putInt((int)val, dst, offset + 4); +// } - public String toString() { - return super.toString(); - } +// public String toString() { +// return super.toString(); +// } public static void main(String[] args) { - byte2 = 0; - expect(byte2 == 0); - - Misc m = new Misc(); - m.toString(); - - expect(Long.valueOf(231L) == 231L); - - long x = 231; - expect((x >> 32) == 0); - expect((x >>> 32) == 0); - expect((x << 32) == 992137445376L); - - long y = -231; - expect((y >> 32) == 0xffffffffffffffffL); - expect((y >>> 32) == 0xffffffffL); - - byte[] array = new byte[8]; - putLong(231, array, 0); - expect((array[0] & 0xff) == 0); - expect((array[1] & 0xff) == 0); - expect((array[2] & 0xff) == 0); - expect((array[3] & 0xff) == 0); - expect((array[4] & 0xff) == 0); - expect((array[5] & 0xff) == 0); - expect((array[6] & 0xff) == 0); - expect((array[7] & 0xff) == 231); - - java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); - buffer.putLong(231); - buffer.flip(); - expect(buffer.getLong() == 231); - - boolean v = Boolean.valueOf("true"); - - ClassLoader.getSystemClassLoader().toString(); - int a = 2; int b = 2; int c = a + b; - String s = "hello"; - m.foo(s); - m.bar(s); - baz(s); +// byte2 = 0; +// expect(byte2 == 0); - m.sync(); - syncStatic(false); - try { - syncStatic(true); - } catch (RuntimeException e) { - e.printStackTrace(); - } +// Misc m = new Misc(); +// m.toString(); - int d = alpha; - beta = 42; - alpha = 43; - int e = beta; - int f = alpha; - m.gamma = 44; +// expect(Long.valueOf(231L) == 231L); - expect(beta == 42); - expect(alpha == 43); - expect(m.gamma == 44); +// long x = 231; +// expect((x >> 32) == 0); +// expect((x >>> 32) == 0); +// expect((x << 32) == 992137445376L); + +// long y = -231; +// expect((y >> 32) == 0xffffffffffffffffL); +// expect((y >>> 32) == 0xffffffffL); + +// byte[] array = new byte[8]; +// putLong(231, array, 0); +// expect((array[0] & 0xff) == 0); +// expect((array[1] & 0xff) == 0); +// expect((array[2] & 0xff) == 0); +// expect((array[3] & 0xff) == 0); +// expect((array[4] & 0xff) == 0); +// expect((array[5] & 0xff) == 0); +// expect((array[6] & 0xff) == 0); +// expect((array[7] & 0xff) == 231); + +// java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); +// buffer.putLong(231); +// buffer.flip(); +// expect(buffer.getLong() == 231); + +// boolean v = Boolean.valueOf("true"); + +// ClassLoader.getSystemClassLoader().toString(); + +// int a = 2; +// int b = 2; +// int c = a + b; + +// String s = "hello"; +// m.foo(s); +// m.bar(s); +// baz(s); + +// m.sync(); +// syncStatic(false); +// try { +// syncStatic(true); +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } + +// int d = alpha; +// beta = 42; +// alpha = 43; +// int e = beta; +// int f = alpha; +// m.gamma = 44; + +// expect(beta == 42); +// expect(alpha == 43); +// expect(m.gamma == 44); } } From fa513beb2fe6f0bd2fd84b84998d63e2680b7df3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 11 Feb 2008 19:06:12 -0700 Subject: [PATCH 003/121] rework compiler interface to explicitly accept a size parameter for each operation where relevant --- src/assembler.h | 11 +- src/compile.cpp | 406 ++++++++++++++++++++++++++--------------------- src/compiler.cpp | 382 +++++++++++++++++++++----------------------- src/compiler.h | 55 +++---- src/x86.cpp | 44 ++++- 5 files changed, 460 insertions(+), 438 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 2bb0e24338..99caacc8a9 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -29,13 +29,8 @@ const unsigned UnaryOperationCount = Negate + 1; enum BinaryOperation { LoadAddress, - Move1, - Move2, - Move4, - Move8, - Move1ToW, - Move2ToW, - Move2zToW, + Move, + MoveZ, Move4To8, Compare, Add, @@ -51,8 +46,6 @@ enum BinaryOperation { Xor }; -const BinaryOperation Move = (BytesPerWord == 8 ? Move8 : Move4); - const unsigned BinaryOperationCount = Xor + 1; enum OperandType { diff --git a/src/compile.cpp b/src/compile.cpp index 21ffab2b54..753fd663c8 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -684,97 +684,111 @@ class Frame { } void pushInt(Compiler::Operand* o) { - c->push(o); + c->push(4, o); pushedInt(); } void pushAddress(Compiler::Operand* o) { - c->push(o); + c->push(BytesPerWord, o); pushedInt(); } void pushObject(Compiler::Operand* o) { - c->push(o); + c->push(BytesPerWord, o); pushedObject(); } void pushObject() { - c->push(1); + c->pushed(1); pushedObject(); } - void pushLong(Compiler::Operand* o) { + void pushLongQuiet(Compiler::Operand* o) { if (BytesPerWord == 8) { - c->push(1); + c->pushed(1); } - c->push(o); + c->push(8, o); + } + void pushLong(Compiler::Operand* o) { + pushLongQuiet(o); pushedLong(); } void pop(unsigned count) { popped(count); - c->pop(count); + c->popped(count); } Compiler::Operand* popInt() { poppedInt(); - return c->pop(); + return c->pop(4); + } + + Compiler::Operand* popLongQuiet() { + Compiler::Operand* r = c->pop(8); + if (BytesPerWord == 8) { + c->popped(1); + } + return r; } Compiler::Operand* popLong() { poppedLong(); - return c->pop(); + return popLongQuiet(); } Compiler::Operand* popObject() { poppedObject(); - return c->pop(); + return c->pop(BytesPerWord); } void loadInt(unsigned index) { assert(t, index < localSize()); pushInt - (c->load4(c->memory(c->base(), localOffset(t, index, context->method)))); + (c->load + (4, c->memory(c->base(), localOffset(t, index, context->method)))); } void loadLong(unsigned index) { assert(t, index < static_cast(localSize() - 1)); pushLong - (c->load8 - (c->memory(c->base(), localOffset(t, index + 1, context->method)))); + (c->load + (8, c->memory(c->base(), localOffset(t, index + 1, context->method)))); } void loadObject(unsigned index) { assert(t, index < localSize()); pushObject (c->load - (c->memory(c->base(), localOffset(t, index, context->method)))); + (BytesPerWord, + c->memory(c->base(), localOffset(t, index, context->method)))); } void storeInt(unsigned index) { - c->store4 - (popInt(), c->memory(c->base(), localOffset(t, index, context->method))); + c->store + (4, popInt(), c->memory + (c->base(), localOffset(t, index, context->method))); storedInt(index); } void storeLong(unsigned index) { - c->store8 - (popLong(), c->memory + c->store + (8, popLong(), c->memory (c->base(), localOffset(t, index + 1, context->method))); storedLong(index); } void storeObject(unsigned index) { c->store - (popObject(), c->memory + (BytesPerWord, popObject(), c->memory (c->base(), localOffset(t, index, context->method))); storedObject(index); } void storeObjectOrAddress(unsigned index) { c->store - (c->pop(), c->memory + (BytesPerWord, c->pop(BytesPerWord), c->memory (c->base(), localOffset(t, index, context->method))); assert(t, sp >= 1); @@ -789,122 +803,131 @@ class Frame { } void dup() { - Compiler::Operand* s0 = c->pop(); + Compiler::Operand* s0 = c->pop(BytesPerWord); - c->push(s0); - c->push(s0); + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s0); dupped(); } void dupX1() { - Compiler::Operand* s0 = c->pop(); - Compiler::Operand* s1 = c->pop(); + Compiler::Operand* s0 = c->pop(BytesPerWord); + Compiler::Operand* s1 = c->pop(BytesPerWord); - c->push(s0); - c->push(s1); - c->push(s0); + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); duppedX1(); } void dupX2() { - Compiler::Operand* s0 = c->pop(); - Compiler::Operand* s1 = c->pop(); + Compiler::Operand* s0 = c->pop(BytesPerWord); if (get(sp - 2) == Long) { - c->push(s0); - c->push(s1); - c->push(s0); - } else { - Compiler::Operand* s2 = c->pop(); + Compiler::Operand* s1 = popLongQuiet(); - c->push(s0); - c->push(s2); - c->push(s1); - c->push(s0); + c->push(BytesPerWord, s0); + pushLongQuiet(s1); + c->push(BytesPerWord, s0); + } else { + Compiler::Operand* s1 = c->pop(BytesPerWord); + Compiler::Operand* s2 = c->pop(BytesPerWord); + + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s2); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } duppedX2(); } void dup2() { - Compiler::Operand* s0 = c->pop(); - if (get(sp - 1) == Long) { - c->push(s0); - c->push(s0); - } else { - Compiler::Operand* s1 = c->pop(); + Compiler::Operand* s0 = popLongQuiet(); - c->push(s1); - c->push(s0); - c->push(s1); - c->push(s0); + pushLongQuiet(s0); + pushLongQuiet(s0); + } else { + Compiler::Operand* s0 = c->pop(BytesPerWord); + Compiler::Operand* s1 = c->pop(BytesPerWord); + + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } dupped2(); } void dup2X1() { - 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(); + Compiler::Operand* s0 = popLongQuiet(); + Compiler::Operand* s1 = c->pop(BytesPerWord); - c->push(s1); - c->push(s0); - c->push(s2); - c->push(s1); - c->push(s0); + pushLongQuiet(s0); + c->push(BytesPerWord, s1); + pushLongQuiet(s0); + } else { + Compiler::Operand* s0 = c->pop(BytesPerWord); + Compiler::Operand* s1 = c->pop(BytesPerWord); + Compiler::Operand* s2 = c->pop(BytesPerWord); + + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s2); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } dupped2X1(); } void dup2X2() { - 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(); + Compiler::Operand* s0 = popLongQuiet(); - c->push(s0); - c->push(s2); - c->push(s1); - c->push(s0); + if (get(sp - 3) == Long) { + Compiler::Operand* s1 = popLongQuiet(); + + pushLongQuiet(s0); + pushLongQuiet(s1); + pushLongQuiet(s0); + } else { + Compiler::Operand* s1 = c->pop(BytesPerWord); + Compiler::Operand* s2 = c->pop(BytesPerWord); + + pushLongQuiet(s0); + c->push(BytesPerWord, s2); + c->push(BytesPerWord, s1); + pushLongQuiet(s0); } } else { - Compiler::Operand* s2 = c->pop(); - Compiler::Operand* s3 = c->pop(); + Compiler::Operand* s0 = c->pop(BytesPerWord); + Compiler::Operand* s1 = c->pop(BytesPerWord); + Compiler::Operand* s2 = c->pop(BytesPerWord); + Compiler::Operand* s3 = c->pop(BytesPerWord); - c->push(s1); - c->push(s0); - c->push(s3); - c->push(s2); - c->push(s1); - c->push(s0); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s3); + c->push(BytesPerWord, s2); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } dupped2X2(); } void swap() { - Compiler::Operand* s0 = c->pop(); - Compiler::Operand* s1 = c->pop(); + Compiler::Operand* s0 = c->pop(BytesPerWord); + Compiler::Operand* s1 = c->pop(BytesPerWord); - c->push(s0); - c->push(s1); + c->push(BytesPerWord, s0); + c->push(BytesPerWord, s1); swapped(); } @@ -1409,6 +1432,8 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) { Compiler* c = frame->c; + unsigned rSize = resultSize(t, methodReturnCode(t, target)); + Compiler::Operand* result = c->call (c->constant (reinterpret_cast @@ -1416,13 +1441,13 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) 0, Compiler::Aligned, frame->trace(target, false), - resultSize(t, methodReturnCode(t, target)), + rSize, 0); - c->pop(methodParameterFootprint(t, target)); + c->popped(methodParameterFootprint(t, target)); - if (methodReturnCode(t, target) != VoidField) { - c->push(result); + if (rSize) { + c->push(rSize, result); } } @@ -1462,7 +1487,8 @@ handleEntrance(MyThread* t, Frame* frame) // save 'this' pointer in case it is overwritten. unsigned index = savedTargetIndex(t, method); - c->store(c->memory(c->base(), localOffset(t, 0, method)), + c->store(BytesPerWord, + c->memory(c->base(), localOffset(t, 0, method)), c->memory(c->base(), localOffset(t, index, method))); frame->set(index, Frame::Object); } @@ -1521,10 +1547,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* load = c->label(); Compiler::Operand* throw_ = c->label(); - c->cmp(c->constant(0), index); + c->cmp(4, c->constant(0), index); c->jl(throw_); - c->cmp(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), + c->cmp(BytesPerWord, + c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), index); c->jl(load); @@ -1544,29 +1571,30 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (instruction) { case aaload: frame->pushObject - (c->load(c->memory(array, ArrayBody, index, BytesPerWord))); + (c->load + (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); break; case faload: case iaload: - frame->pushInt(c->load4(c->memory(array, ArrayBody, index, 4))); + frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); break; case baload: - frame->pushInt(c->load1(c->memory(array, ArrayBody, index, 1))); + frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); break; case caload: - frame->pushInt(c->load2z(c->memory(array, ArrayBody, index, 2))); + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); break; case daload: case laload: - frame->pushLong(c->load8(c->memory(array, ArrayBody, index, 8))); + frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); break; case saload: - frame->pushInt(c->load2(c->memory(array, ArrayBody, index, 2))); + frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); break; } } break; @@ -1595,10 +1623,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* store = c->label(); Compiler::Operand* throw_ = c->label(); - c->cmp(c->constant(0), index); + c->cmp(4, c->constant(0), index); c->jl(throw_); - c->cmp(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), + c->cmp(BytesPerWord, + c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), index); c->jl(store); @@ -1624,28 +1653,28 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->trace(0, false), 0, 4, c->thread(), array, - c->add(c->constant(ArrayBody), - c->shl(c->constant(log(BytesPerWord)), index)), + c->add(4, c->constant(ArrayBody), + c->shl(4, c->constant(log(BytesPerWord)), index)), value); } break; case fastore: case iastore: - c->store4(value, c->memory(array, ArrayBody, index, 4)); + c->store(4, value, c->memory(array, ArrayBody, index, 4)); break; case bastore: - c->store1(value, c->memory(array, ArrayBody, index, 1)); + c->store(1, value, c->memory(array, ArrayBody, index, 1)); break; case castore: case sastore: - c->store2(value, c->memory(array, ArrayBody, index, 2)); + c->store(2, value, c->memory(array, ArrayBody, index, 2)); break; case dastore: case lastore: - c->store8(value, c->memory(array, ArrayBody, index, 8)); + c->store(8, value, c->memory(array, ArrayBody, index, 8)); break; } } break; @@ -1683,12 +1712,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* nonnegative = c->label(); Compiler::Operand* length = frame->popInt(); - c->cmp(c->constant(0), length); + c->cmp(4, c->constant(0), length); c->jge(nonnegative); - c->push(length); - c->push(c->thread()); - c->call (c->constant(reinterpret_cast(throwNegativeArraySize)), context->indirection, @@ -1711,13 +1737,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case areturn: { handleExit(t, frame); - c->return_(frame->popObject()); + c->return_(BytesPerWord, frame->popObject()); } return; case arraylength: { frame->pushInt (c->load - (c->memory + (BytesPerWord, c->memory (frame->popObject(), ArrayLength, 0, 1, frame->trace(0, false)))); } break; @@ -1825,11 +1851,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case dconst_0: - frame->pushLong(c->constant8(doubleToBits(0.0))); + frame->pushLong(c->constant(doubleToBits(0.0))); break; case dconst_1: - frame->pushLong(c->constant8(doubleToBits(1.0))); + frame->pushLong(c->constant(doubleToBits(1.0))); break; case ddiv: { @@ -2045,34 +2071,36 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ByteField: case BooleanField: frame->pushInt - (c->load1(c->memory(table, fieldOffset(t, field), 0, 1, trace))); + (c->load(1, c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case CharField: frame->pushInt - (c->load2z(c->memory(table, fieldOffset(t, field), 0, 1, trace))); + (c->loadz(2, c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case ShortField: frame->pushInt - (c->load2(c->memory(table, fieldOffset(t, field), 0, 1, trace))); + (c->load(2, c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case FloatField: case IntField: frame->pushInt - (c->load4(c->memory(table, fieldOffset(t, field), 0, 1, trace))); + (c->load(4, c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case DoubleField: case LongField: frame->pushLong - (c->load8(c->memory(table, fieldOffset(t, field), 0, 1, trace))); + (c->load(8, c->memory(table, fieldOffset(t, field), 0, 1, trace))); break; case ObjectField: frame->pushObject - (c->load(c->memory(table, fieldOffset(t, field), 0, 1, trace))); + (c->load + (BytesPerWord, c->memory + (table, fieldOffset(t, field), 0, 1, trace))); break; default: @@ -2097,11 +2125,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case i2b: { - frame->pushInt(c->load1(frame->popInt())); + frame->pushInt(c->load(1, frame->popInt())); } break; case i2c: { - frame->pushInt(c->load2z(frame->popInt())); + frame->pushInt(c->loadz(2, frame->popInt())); } break; case i2d: { @@ -2123,19 +2151,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; case i2s: { - frame->pushInt(c->load2(frame->popInt())); + frame->pushInt(c->load(2, frame->popInt())); } break; case iadd: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->add(a, b)); + frame->pushInt(c->add(4, a, b)); } break; case iand: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->and_(a, b)); + frame->pushInt(c->and_(4, a, b)); } break; case iconst_m1: @@ -2169,7 +2197,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case idiv: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->div(a, b)); + frame->pushInt(c->div(4, a, b)); } break; case if_acmpeq: @@ -2181,7 +2209,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* b = frame->popObject(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(a, b); + c->cmp(BytesPerWord, a, b); if (instruction == if_acmpeq) { c->je(target); } else { @@ -2205,7 +2233,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* b = frame->popInt(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(a, b); + c->cmp(4, a, b); switch (instruction) { case if_icmpeq: c->je(target); @@ -2243,7 +2271,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* a = frame->popInt(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(c->constant(0), a); + c->cmp(4, c->constant(0), a); switch (instruction) { case ifeq: c->je(target); @@ -2277,7 +2305,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* a = frame->popObject(); Compiler::Operand* target = frame->machineIp(newIp); - c->cmp(c->constant(0), a); + c->cmp(BytesPerWord, c->constant(0), a); if (instruction == ifnull) { c->je(target); } else { @@ -2295,7 +2323,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* a = c->memory (c->base(), localOffset(t, index, context->method)); - c->store(c->add(c->constant(count), a), a); + c->store(4, c->add(4, c->constant(count), a), a); } break; case iload: @@ -2326,11 +2354,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case imul: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->mul(a, b)); + frame->pushInt(c->mul(4, a, b)); } break; case ineg: { - frame->pushInt(c->neg(frame->popInt())); + frame->pushInt(c->neg(4, frame->popInt())); } break; case instanceof: { @@ -2357,6 +2385,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) unsigned instance = parameterFootprint - 1; + unsigned rSize = resultSize(t, methodReturnCode(t, target)); + Compiler::Operand* result = c->call (c->call (c->constant @@ -2370,13 +2400,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 0, 0, frame->trace(target, true), - resultSize(t, methodReturnCode(t, target)), + rSize, 0); frame->pop(parameterFootprint); - if (methodReturnCode(t, target) != VoidField) { - c->push(result); + if (rSize) { + c->push(rSize, result); } } break; @@ -2415,52 +2445,54 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* instance = c->peek(parameterFootprint - 1); + unsigned rSize = resultSize(t, methodReturnCode(t, target)); + Compiler::Operand* result = c->call (c->memory (c->and_ - (c->constant(PointerMask), c->memory + (4, 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)), + rSize, 0); frame->pop(parameterFootprint); - if (methodReturnCode(t, target) != VoidField) { - c->push(result); + if (rSize) { + c->push(rSize, result); } } break; case ior: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->or_(a, b)); + frame->pushInt(c->or_(4, a, b)); } break; case irem: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->rem(a, b)); + frame->pushInt(c->rem(4, a, b)); } break; case ireturn: case freturn: { handleExit(t, frame); - c->return_(frame->popInt()); + c->return_(4, frame->popInt()); } return; case ishl: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->shl(a, b)); + frame->pushInt(c->shl(4, a, b)); } break; case ishr: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->shr(a, b)); + frame->pushInt(c->shr(4, a, b)); } break; case istore: @@ -2491,19 +2523,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case isub: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->sub(a, b)); + frame->pushInt(c->sub(4, a, b)); } break; case iushr: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->ushr(a, b)); + frame->pushInt(c->ushr(4, a, b)); } break; case ixor: { Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->xor_(a, b)); + frame->pushInt(c->xor_(4, a, b)); } break; case jsr: @@ -2530,19 +2562,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case l2i: - frame->pushInt(c->load4(frame->popLong())); + frame->pushInt(c->load(4, frame->popLong())); break; case ladd: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->add(a, b)); + frame->pushLong(c->add(8, a, b)); } break; case land: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->and_(a, b)); + frame->pushLong(c->and_(8, a, b)); } break; case lcmp: { @@ -2553,19 +2585,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - c->cmp(a, b); + c->cmp(8, a, b); c->jl(less); c->jg(greater); - c->push(c->constant(0)); + c->push(4, c->constant(0)); c->jmp(next); c->mark(less); - c->push(c->constant(-1)); + c->push(4, c->constant(-1)); c->jmp(next); c->mark(greater); - c->push(c->constant(1)); + c->push(4, c->constant(1)); c->mark(next); @@ -2573,11 +2605,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case lconst_0: - frame->pushLong(c->constant8(0)); + frame->pushLong(c->constant(0)); break; case lconst_1: - frame->pushLong(c->constant8(1)); + frame->pushLong(c->constant(1)); break; case ldc: @@ -2616,13 +2648,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint64_t v; memcpy(&v, &singletonValue(t, pool, index - 1), 8); - frame->pushLong(c->constant8(v)); + frame->pushLong(c->constant(v)); } break; case ldiv_: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->div(a, b)); + frame->pushLong(c->div(8, a, b)); } break; case lload: @@ -2653,11 +2685,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lmul: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->mul(a, b)); + frame->pushLong(c->mul(8, a, b)); } break; case lneg: - frame->pushLong(c->neg(frame->popLong())); + frame->pushLong(c->neg(8, frame->popLong())); break; case lookupswitch: { @@ -2710,31 +2742,31 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lor: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->or_(a, b)); + frame->pushLong(c->or_(8, a, b)); } break; case lrem: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->rem(a, b)); + frame->pushLong(c->rem(8, a, b)); } break; case lreturn: case dreturn: { handleExit(t, frame); - c->return_(frame->popLong()); + c->return_(8, frame->popLong()); } return; case lshl: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->shl(a, b)); + frame->pushLong(c->shl(8, a, b)); } break; case lshr: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->shr(a, b)); + frame->pushLong(c->shr(8, a, b)); } break; case lstore: @@ -2765,19 +2797,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lsub: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->sub(a, b)); + frame->pushLong(c->sub(8, a, b)); } break; case lushr: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->ushr(a, b)); + frame->pushLong(c->ushr(8, a, b)); } break; case lxor: { Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->xor_(a, b)); + frame->pushLong(c->xor_(8, a, b)); } break; case monitorenter: { @@ -2808,8 +2840,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 0, frame->trace(0, false), BytesPerWord, - 4, c->thread(), frame->append(class_), c->load(c->stack()), - c->constant(dimensions)); + 4, c->thread(), frame->append(class_), + c->load(BytesPerWord, c->stack()), c->constant(dimensions)); frame->pop(dimensions); frame->pushObject(result); @@ -2849,7 +2881,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* length = frame->popInt(); - c->cmp(c->constant(0), length); + c->cmp(4, c->constant(0), length); c->jge(nonnegative); c->call @@ -2980,22 +3012,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - c->store1(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store + (1, value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case CharField: case ShortField: - c->store2(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store + (2, value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case FloatField: case IntField: - c->store4(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store + (4, value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case DoubleField: case LongField: - c->store8(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); + c->store + (8, value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case ObjectField: @@ -3028,7 +3064,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case return_: handleExit(t, frame); - c->return_(0); + c->return_(0, 0); return; case sipush: @@ -3071,13 +3107,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* defaultCase = c->label(); - c->cmp(c->constant(bottom), key); + c->cmp(4, c->constant(bottom), key); c->jl(defaultCase); - c->cmp(c->constant(top), key); + c->cmp(4, c->constant(top), key); c->jg(defaultCase); - c->sub(c->constant(bottom), key); + c->sub(4, c->constant(bottom), key); c->jmp(c->memory(start, 0, key, BytesPerWord)); c->mark(defaultCase); @@ -3108,7 +3144,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* a = c->memory (c->base(), localOffset(t, index, context->method)); - c->store(c->add(c->constant(count), a), a); + c->store(4, c->add(4, c->constant(count), a), a); } break; case iload: { @@ -3476,7 +3512,7 @@ finish(MyThread* t, Context* context) } // for debugging: - if (false and + if (//false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), diff --git a/src/compiler.cpp b/src/compiler.cpp index a33eb661e8..344d79f6b2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -29,7 +29,7 @@ class Value { virtual void acquire(Context*, MyOperand*) { } virtual void release(Context*, MyOperand*) { } - virtual RegisterValue* toRegister(Context*, unsigned size) = 0; + virtual RegisterValue* toRegister(Context*) = 0; virtual void asAssemblerOperand(Context*, OperandType* type, @@ -38,14 +38,14 @@ class Value { class MyOperand: public Compiler::Operand { public: - MyOperand(unsigned size, Value* value): - size(size), event(0), value(value), target(0), index(0), next(0) + MyOperand(Value* value): + event(0), value(value), target(0), size(0), index(0), next(0) { } - unsigned size; Event* event; Value* value; Value* target; + unsigned size; unsigned index; MyOperand* next; }; @@ -257,7 +257,7 @@ class ConstantValue: public Value { public: ConstantValue(Promise* value): value(value) { } - virtual RegisterValue* toRegister(Context* c, unsigned size); + virtual RegisterValue* toRegister(Context* c); virtual void asAssemblerOperand(Context*, OperandType* type, @@ -287,7 +287,7 @@ class AddressValue: public Value { public: AddressValue(Promise* address): address(address) { } - virtual RegisterValue* toRegister(Context* c, unsigned size); + virtual RegisterValue* toRegister(Context* c); virtual void asAssemblerOperand(Context*, OperandType* type, @@ -337,7 +337,7 @@ class RegisterValue: public Value { if (register_.high >= 0) c->registers[register_.high].operand = 0; } - virtual RegisterValue* toRegister(Context*, unsigned) { + virtual RegisterValue* toRegister(Context*) { return this; } @@ -366,9 +366,9 @@ class MemoryValue: public Value { value(base, offset, index, scale, traceHandler) { } - virtual RegisterValue* toRegister(Context* c, unsigned size) { - RegisterValue* v = freeRegister(c, size); - apply(c, Move, size, this, v); + virtual RegisterValue* toRegister(Context* c) { + RegisterValue* v = freeRegister(c, BytesPerWord); + apply(c, Move, BytesPerWord, this, v); return v; } @@ -404,9 +404,7 @@ memory(Context* c, int base, int offset, int index, unsigned scale, int toRegister(Context* c, MyOperand* a) { - assert(c, a->size == BytesPerWord); - - return a->value->toRegister(c, a->size)->register_.low; + return a->value->toRegister(c)->register_.low; } class AbstractMemoryValue: public MemoryValue { @@ -466,8 +464,8 @@ class Event { class ArgumentEvent: public Event { public: - ArgumentEvent(Context* c, MyOperand* a, unsigned index): - Event(c), a(a), index(index) + ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): + Event(c), size(size), a(a), index(index) { } virtual Value* target(Context* c, MyOperand* v) { @@ -493,25 +491,26 @@ class ArgumentEvent: public Event { a->target->preserve(c); if (not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); + apply(c, Move, size, a->value, a->target); } } + unsigned size; MyOperand* a; unsigned index; }; void -appendArgument(Context* c, MyOperand* value, unsigned index) +appendArgument(Context* c, unsigned size, MyOperand* value, unsigned index) { new (c->zone->allocate(sizeof(ArgumentEvent))) - ArgumentEvent(c, value, index); + ArgumentEvent(c, size, value, index); } class ReturnEvent: public Event { public: - ReturnEvent(Context* c, MyOperand* a): - Event(c), a(a) + ReturnEvent(Context* c, unsigned size, MyOperand* a): + Event(c), size(size), a(a) { } virtual Value* target(Context* c, MyOperand* v) { @@ -531,26 +530,27 @@ class ReturnEvent: public Event { a->value->release(c, a); if (not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); + apply(c, Move, size, a->value, a->target); } } c->assembler->apply(Return); } + unsigned size; MyOperand* a; }; void -appendReturn(Context* c, MyOperand* value) +appendReturn(Context* c, unsigned size, MyOperand* value) { - new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, value); + new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } class SyncForCallEvent: public Event { public: - SyncForCallEvent(Context* c, MyOperand* src, MyOperand* dst): - Event(c), src(src), dst(dst) + SyncForCallEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): + Event(c), size(size), src(src), dst(dst) { } virtual Value* target(Context* c, MyOperand* v) { @@ -571,29 +571,30 @@ class SyncForCallEvent: public Event { src->value->release(c, src); if (not src->target->equals(src->value)) { - apply(c, Move, src->size, src->value, src->target); + apply(c, Move, size, src->value, src->target); } } + unsigned size; MyOperand* src; MyOperand* dst; }; void -appendSyncForCall(Context* c, MyOperand* src, MyOperand* dst) +appendSyncForCall(Context* c, unsigned size, MyOperand* src, MyOperand* dst) { new (c->zone->allocate(sizeof(SyncForCallEvent))) - SyncForCallEvent(c, src, dst); + SyncForCallEvent(c, size, src, dst); } class SyncForJumpEvent: public Event { public: - SyncForJumpEvent(Context* c, MyOperand* src, MyOperand* dst): - Event(c), src(src), dst(dst) + SyncForJumpEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): + Event(c), size(size), src(src), dst(dst) { } - SyncForJumpEvent(Event* next, MyOperand* src, MyOperand* dst): - Event(next), src(src), dst(dst) + SyncForJumpEvent(Event* next, unsigned size, MyOperand* src, MyOperand* dst): + Event(next), size(size), src(src), dst(dst) { } virtual Value* target(Context* c, MyOperand* v) { @@ -618,21 +619,22 @@ class SyncForJumpEvent: public Event { src->target->acquire(c, dst); if (not src->target->equals(src->value)) { - apply(c, Move, src->size, src->value, src->target); + apply(c, Move, size, src->value, src->target); } dst->value = src->target; } + unsigned size; MyOperand* src; MyOperand* dst; }; void -appendSyncForJump(Context* c, MyOperand* src, MyOperand* dst) +appendSyncForJump(Context* c, unsigned size, MyOperand* src, MyOperand* dst) { new (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(c, src, dst); + SyncForJumpEvent(c, size, src, dst); } class CallEvent: public Event { @@ -680,12 +682,12 @@ class CallEvent: public Event { if (indirection) { if (not address->target->equals(address->value)) { - apply(c, Move, address->size, address->value, address->target); + apply(c, Move, BytesPerWord, address->value, address->target); } apply(c, Call, BytesPerWord, constant(c, reinterpret_cast(indirection))); } else { - apply(c, Call, address->size, address->value); + apply(c, Call, BytesPerWord, address->value); } } @@ -739,8 +741,9 @@ freeRegister(Context* c, unsigned size) class MoveEvent: public Event { public: - MoveEvent(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst): - Event(c), type(type), src(src), dst(dst) + MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src, + MyOperand* dst): + Event(c), type(type), size(size), src(src), dst(dst) { } virtual Value* target(Context* c, MyOperand* v) { @@ -764,33 +767,36 @@ class MoveEvent: public Event { if (dst->value) { src->target = dst->value; } else { - src->target = freeRegister(c, src->size); + src->target = freeRegister(c, size); } } src->value->release(c, src); src->target->acquire(c, dst); - apply(c, type, src->size, src->value, src->target); + apply(c, type, size, src->value, src->target); dst->value = src->target; } BinaryOperation type; + unsigned size; MyOperand* src; MyOperand* dst; }; void -appendMove(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst) +appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src, + MyOperand* dst) { - new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, src, dst); + new (c->zone->allocate(sizeof(MoveEvent))) + MoveEvent(c, type, size, src, dst); } class CompareEvent: public Event { public: - CompareEvent(Context* c, MyOperand* a, MyOperand* b): - Event(c), a(a), b(b) + CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): + Event(c), size(size), a(a), b(b) { } virtual Value* target(Context* c, MyOperand* v) { @@ -814,17 +820,18 @@ class CompareEvent: public Event { a->value->release(c, a); b->value->release(c, b); - apply(c, Compare, a->size, a->value, b->value); + apply(c, Compare, size, a->value, b->value); } + unsigned size; MyOperand* a; MyOperand* b; }; void -appendCompare(Context* c, MyOperand* a, MyOperand* b) +appendCompare(Context* c, unsigned size, MyOperand* a, MyOperand* b) { - new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, a, b); + new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, a, b); } class BranchEvent: public Event { @@ -848,7 +855,7 @@ class BranchEvent: public Event { virtual void compile(Context* c) { address->value->release(c, address); - apply(c, type, address->size, address->value); + apply(c, type, BytesPerWord, address->value); } UnaryOperation type; @@ -882,7 +889,7 @@ class JumpEvent: public Event { virtual void compile(Context* c) { address->value->release(c, address); - apply(c, Jump, address->size, address->value); + apply(c, Jump, BytesPerWord, address->value); } MyOperand* address; @@ -899,9 +906,9 @@ appendJump(Context* c, MyOperand* 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) + CombineEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* a, + MyOperand* b, MyOperand* result): + Event(c), type(type), size(size), a(a), b(b), result(result) { } virtual Value* target(Context* c, MyOperand* v) { @@ -943,36 +950,37 @@ class CombineEvent: public Event { b->value->acquire(c, result); if (a->target and not a->target->equals(a->value)) { - apply(c, Move, a->size, a->value, a->target); + apply(c, Move, 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, Move, size, b->value, b->target); } - apply(c, type, a->size, a->value, b->value); + apply(c, type, size, a->value, b->value); result->value = b->value; } BinaryOperation type; + unsigned size; MyOperand* a; MyOperand* b; MyOperand* result; }; void -appendCombine(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b, - MyOperand* result) +appendCombine(Context* c, BinaryOperation type, unsigned size, MyOperand* a, + MyOperand* b, MyOperand* result) { new (c->zone->allocate(sizeof(CombineEvent))) - CombineEvent(c, type, a, b, result); + CombineEvent(c, type, size, a, b, result); } class TranslateEvent: public Event { public: - TranslateEvent(Context* c, UnaryOperation type, MyOperand* a, + TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a, MyOperand* result): - Event(c), type(type), a(a), result(result) + Event(c), type(type), size(size), a(a), result(result) { } virtual Value* target(Context* c, MyOperand* v) { @@ -1003,31 +1011,32 @@ class TranslateEvent: public Event { } UnaryOperation type; + unsigned size; MyOperand* a; MyOperand* result; }; void -appendTranslate(Context* c, UnaryOperation type, MyOperand* a, +appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a, MyOperand* result) { new (c->zone->allocate(sizeof(TranslateEvent))) - TranslateEvent(c, type, a, result); + TranslateEvent(c, type, size, a, result); } RegisterValue* -ConstantValue::toRegister(Context* c, unsigned size) +ConstantValue::toRegister(Context* c) { - RegisterValue* v = freeRegister(c, size); - apply(c, Move, size, this, v); + RegisterValue* v = freeRegister(c, BytesPerWord); + apply(c, Move, BytesPerWord, this, v); return v; } RegisterValue* -AddressValue::toRegister(Context* c, unsigned size) +AddressValue::toRegister(Context* c) { - RegisterValue* v = freeRegister(c, size); - apply(c, Move, size, this, v); + RegisterValue* v = freeRegister(c, BytesPerWord); + apply(c, Move, BytesPerWord, this, v); return v; } @@ -1048,9 +1057,9 @@ preserve(Context* c, int reg) } MyOperand* -operand(Context* c, unsigned size, Value* value = 0) +operand(Context* c, Value* value = 0) { - return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(size, value); + return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(value); } void @@ -1068,16 +1077,23 @@ popState(Context* c) } void -push(Context* c, MyOperand* o) +push(Context* c, unsigned size, MyOperand* o) { - static_cast(o)->next = c->state->stack; - c->state->stack = static_cast(o); + assert(c, o->size == 0 and o->index == 0); + + o->next = c->state->stack; + o->size = ceiling(size, BytesPerWord); + o->index = ceiling(size, BytesPerWord) + + (c->state->stack ? c->state->stack->index : 0); + c->state->stack = o; } MyOperand* -pop(Context* c) +pop(Context* c, unsigned size UNUSED) { MyOperand* o = c->state->stack; + assert(c, ceiling(size, BytesPerWord) == o->size); + c->state->stack = o->next; return o; } @@ -1088,19 +1104,20 @@ 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); + MyOperand* n = operand(c); if (new_) { new_->next = n; } else { top = n; } new_ = n; + new_->size = old->size; new_->index = old->index; if (type == SyncForCall) { - appendSyncForCall(c, old, new_); + appendSyncForCall(c, old->size * BytesPerWord, old, new_); } else { - appendSyncForJump(c, old, new_); + appendSyncForJump(c, old->size * BytesPerWord, old, new_); } } @@ -1118,9 +1135,10 @@ updateJunctions(Context* c) MyOperand* new_ = 0; for (MyOperand* old = i->firstEvent->stack; old; old = old->next) { - MyOperand* n = operand(c, old->size, 0); + MyOperand* n = operand(c); if (new_) new_->next = n; new_ = n; + new_->size = old->size; new_->index = old->index; if (old->event) { @@ -1129,7 +1147,7 @@ updateJunctions(Context* c) p->lastEvent = p->lastEvent->next = new (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(p->lastEvent->next, old, new_); + SyncForJumpEvent(p->lastEvent->next, old->size, old, new_); } } } @@ -1219,21 +1237,12 @@ class MyCompiler: public Compiler { ResolvedPromise(value)); } - virtual Operand* constant8(int64_t value) { - return promiseConstant8(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); - } - virtual Operand* promiseConstant(Promise* value) { - return operand(&c, BytesPerWord, ::constant(&c, value)); - } - - virtual Operand* promiseConstant8(Promise* value) { - return operand(&c, 8, ::constant(&c, value)); + return operand(&c, ::constant(&c, value)); } virtual Operand* address(Promise* address) { - return operand(&c, BytesPerWord, ::address(&c, address)); + return operand(&c, ::address(&c, address)); } virtual Operand* memory(Operand* base, @@ -1243,25 +1252,25 @@ class MyCompiler: public Compiler { TraceHandler* traceHandler = 0) { return operand - (&c, BytesPerWord, ::memory + (&c, ::memory (&c, static_cast(base), displacement, static_cast(index), scale, traceHandler)); } virtual Operand* stack() { - return operand(&c, BytesPerWord, register_(&c, c.assembler->stack())); + return operand(&c, register_(&c, c.assembler->stack())); } virtual Operand* base() { - return operand(&c, BytesPerWord, register_(&c, c.assembler->base())); + return operand(&c, register_(&c, c.assembler->base())); } virtual Operand* thread() { - return operand(&c, BytesPerWord, register_(&c, c.assembler->thread())); + return operand(&c, register_(&c, c.assembler->thread())); } virtual Operand* label() { - return operand(&c, BytesPerWord, ::constant(&c, static_cast(0))); + return operand(&c, ::constant(&c, static_cast(0))); } Promise* machineIp() { @@ -1274,20 +1283,24 @@ class MyCompiler: public Compiler { = machineIp(); } - virtual void push(Operand* value) { - ::push(&c, static_cast(value)); + virtual void push(unsigned size, Operand* value) { + ::push(&c, size, static_cast(value)); } - virtual Operand* pop() { - return ::pop(&c); + virtual Operand* pop(unsigned size) { + return ::pop(&c, size); } - virtual void push(unsigned count) { - for (unsigned i = 0; i < count; ++i) ::push(&c, 0); + virtual void pushed(unsigned count) { + for (unsigned i = 0; i < count; ++i) ::push(&c, BytesPerWord, operand(&c)); } - virtual void pop(unsigned count) { - for (unsigned i = 0; i < count; ++i) ::pop(&c); + virtual void popped(unsigned count) { + for (int i = count; i >= 0;) { + MyOperand* o = c.state->stack; + c.state->stack = o->next; + count -= o->size; + } } virtual Operand* peek(unsigned index) { @@ -1300,17 +1313,23 @@ class MyCompiler: public Compiler { void* indirection, unsigned flags, TraceHandler* traceHandler, - unsigned resultSize, + unsigned, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); unsigned footprint = 0; + unsigned size = BytesPerWord; for (unsigned i = 0; i < argumentCount; ++i) { MyOperand* o = va_arg(a, MyOperand*); - footprint += o->size; - appendArgument(&c, o, i); + if (o) { + appendArgument(&c, size, o, footprint); + size = BytesPerWord; + } else { + size = 8; + } + ++ footprint; } va_end(a); @@ -1321,87 +1340,42 @@ class MyCompiler: public Compiler { + (footprint > c.assembler->argumentRegisterCount() ? footprint - c.assembler->argumentRegisterCount() : 0); - MyOperand* result = operand(&c, resultSize, 0); + MyOperand* result = operand(&c); appendCall(&c, static_cast(address), indirection, flags, traceHandler, result, stackOffset); return result; } - virtual void return_(Operand* value) { - appendReturn(&c, static_cast(value)); + virtual void return_(unsigned size, Operand* value) { + appendReturn(&c, size, static_cast(value)); } - virtual void store(Operand* src, Operand* dst) { - appendMove(&c, Move, static_cast(src), + virtual void store(unsigned size, Operand* src, Operand* dst) { + appendMove(&c, Move, size, static_cast(src), static_cast(dst)); } - virtual void store1(Operand* src, Operand* dst) { - appendMove(&c, Move1, static_cast(src), - static_cast(dst)); - } - - virtual void store2(Operand* src, Operand* dst) { - appendMove(&c, Move2, static_cast(src), - static_cast(dst)); - } - - virtual void store4(Operand* src, Operand* dst) { - appendMove(&c, Move4, static_cast(src), - static_cast(dst)); - } - - virtual void store8(Operand* src, Operand* dst) { - appendMove(&c, Move8, static_cast(src), - static_cast(dst)); - } - - virtual Operand* load(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Move, static_cast(src), dst); + virtual Operand* load(unsigned size, Operand* src) { + MyOperand* dst = operand(&c); + appendMove(&c, Move, size, static_cast(src), dst); return dst; } - virtual Operand* load1(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Move1ToW, static_cast(src), dst); - return dst; - } - - virtual Operand* load2(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Move2ToW, static_cast(src), dst); - return dst; - } - - virtual Operand* load2z(Operand* src) { - MyOperand* dst = operand(&c, BytesPerWord); - appendMove(&c, Move2zToW, static_cast(src), dst); - return dst; - } - - virtual Operand* load4(Operand* src) { - if (BytesPerWord == 4) { - return load(src); - } else { - return load4To8(src); - } - } - - virtual Operand* load8(Operand* src) { - MyOperand* dst = operand(&c, 8); - appendMove(&c, Move8, static_cast(src), dst); + virtual Operand* loadz(unsigned size, Operand* src) { + MyOperand* dst = operand(&c); + appendMove(&c, MoveZ, size, static_cast(src), dst); return dst; } virtual Operand* load4To8(Operand* src) { - MyOperand* dst = operand(&c, 8); - appendMove(&c, Move4To8, static_cast(src), dst); + MyOperand* dst = operand(&c); + appendMove(&c, Move4To8, 0, static_cast(src), dst); return dst; } - virtual void cmp(Operand* a, Operand* b) { - appendCompare(&c, static_cast(a), static_cast(b)); + virtual void cmp(unsigned size, Operand* a, Operand* b) { + appendCompare(&c, size, static_cast(a), + static_cast(b)); } virtual void jl(Operand* address) { @@ -1446,86 +1420,86 @@ class MyCompiler: public Compiler { 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), + virtual Operand* add(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Add, size, 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), + virtual Operand* sub(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Subtract, size, 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), + virtual Operand* mul(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Multiply, size, 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), + virtual Operand* div(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Divide, size, 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), + virtual Operand* rem(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Remainder, size, 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), + virtual Operand* shl(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, ShiftLeft, size, 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), + virtual Operand* shr(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, ShiftRight, size, 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), + virtual Operand* ushr(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, UnsignedShiftRight, size, 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), + virtual Operand* and_(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, And, size, 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), + virtual Operand* or_(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Or, size, 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), + virtual Operand* xor_(unsigned size, Operand* a, Operand* b) { + MyOperand* result = operand(&c); + appendCombine(&c, Xor, size, 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); + virtual Operand* neg(unsigned size, Operand* a) { + MyOperand* result = operand(&c); + appendTranslate(&c, Negate, size, static_cast(a), result); return result; } diff --git a/src/compiler.h b/src/compiler.h index 9778544e4f..aa8a35d381 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -29,10 +29,8 @@ class Compiler { virtual Promise* poolAppend(intptr_t value) = 0; virtual Promise* poolAppendPromise(Promise* value) = 0; - virtual Operand* constant(intptr_t value) = 0; - virtual Operand* constant8(int64_t value) = 0; + virtual Operand* constant(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, @@ -46,10 +44,10 @@ class Compiler { 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 void push(unsigned size, Operand* value) = 0; + virtual Operand* pop(unsigned size) = 0; + virtual void pushed(unsigned count) = 0; + virtual void popped(unsigned count) = 0; virtual Operand* peek(unsigned index) = 0; virtual Operand* call(Operand* address, @@ -59,21 +57,14 @@ class Compiler { unsigned resultSize, unsigned argumentCount, ...) = 0; - virtual void return_(Operand* value) = 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 void return_(unsigned size, Operand* value) = 0; + + virtual void store(unsigned size, Operand* src, Operand* dst) = 0; + virtual Operand* load(unsigned size, Operand* src) = 0; + virtual Operand* loadz(unsigned size, Operand* src) = 0; virtual Operand* load4To8(Operand* src) = 0; - virtual void cmp(Operand* a, Operand* b) = 0; + virtual void cmp(unsigned size, Operand* a, Operand* b) = 0; virtual void jl(Operand* address) = 0; virtual void jg(Operand* address) = 0; virtual void jle(Operand* address) = 0; @@ -81,18 +72,18 @@ class Compiler { 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 Operand* add(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* sub(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* mul(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* div(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* rem(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* shl(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* shr(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* ushr(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* and_(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* or_(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0; + virtual Operand* neg(unsigned size, Operand* a) = 0; virtual unsigned compile() = 0; virtual unsigned poolSize() = 0; diff --git a/src/x86.cpp b/src/x86.cpp index 8809e9c650..e04a3b1488 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -336,6 +336,37 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } } +void +moveMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) +{ + switch (size) { + case 1: + encode2(c, 0x0fbe, b->low, a, true); + break; + + case 2: + encode2(c, 0x0fbf, b->low, a, true); + break; + + case 4: + case 8: + if (BytesPerWord == 4 and size == 8) { + moveMR(c, 4, a, b); + + Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); + Assembler::Register bh(b->high); + moveMR(c, 4, &ah, &bh); + } else if (BytesPerWord == 8 and size == 4) { + encode(c, 0x63, b->low, a, true); + } else { + encode(c, 0x8b, b->low, a, true); + } + break; + + default: abort(c); + } +} + void move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) { @@ -363,14 +394,11 @@ populateTables() UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); - BinaryOperations[INDEX2(Move4, Constant, Register)] = CAST2(moveCR); - BinaryOperations[INDEX2(Move8, Constant, Register)] = CAST2(moveCR); - BinaryOperations[INDEX2(Move4, Constant, Memory)] = CAST2(moveCM); - BinaryOperations[INDEX2(Move8, Constant, Memory)] = CAST2(moveCM); - BinaryOperations[INDEX2(Move4, Register, Memory)] = CAST2(moveRM); - BinaryOperations[INDEX2(Move8, Register, Memory)] = CAST2(moveRM); - BinaryOperations[INDEX2(Move4, Register, Register)] = CAST2(moveRR); - BinaryOperations[INDEX2(Move8, Register, Register)] = CAST2(moveRR); + BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); + BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); + BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); + BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); + BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); } From 6271f878e89162f08b62ed7df0b95a79f7b68209 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Feb 2008 08:21:51 -0700 Subject: [PATCH 004/121] include function prologue and epilogue when compiling --- src/assembler.h | 1 + src/compiler.cpp | 11 +++++++++++ src/x86.cpp | 40 ++++++++++++++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 99caacc8a9..9a7a361784 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -15,6 +15,7 @@ const unsigned OperationCount = Return + 1; enum UnaryOperation { Call, Push, + Pop, JumpIfLess, JumpIfGreater, JumpIfLessOrEqual, diff --git a/src/compiler.cpp b/src/compiler.cpp index 344d79f6b2..ad54cf58d7 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -534,6 +534,10 @@ class ReturnEvent: public Event { } } + Assembler::Register base(c->assembler->base()); + Assembler::Register stack(c->assembler->stack()); + c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack); + c->assembler->apply(Pop, BytesPerWord, Register, &base); c->assembler->apply(Return); } @@ -1156,6 +1160,13 @@ updateJunctions(Context* c) void compile(Context* c) { + Assembler* a = c->assembler; + + Assembler::Register base(a->base()); + Assembler::Register stack(a->stack()); + a->apply(Push, BytesPerWord, Register, &base); + a->apply(Move, BytesPerWord, Register, &stack, Register, &base); + for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { fprintf(stderr, "compile ip %d\n", i); for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { diff --git a/src/x86.cpp b/src/x86.cpp index e04a3b1488..63f0f65671 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -281,6 +281,32 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) c->code.append(0xd0 | a->low); } +void +pushR(Context* c, unsigned size, Assembler::Register* a) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + + pushR(c, 4, &ah); + pushR(c, 4, a); + } else { + c->code.append(0x50 | a->low); + } +} + +void +popR(Context* c, unsigned size, Assembler::Register* a) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + + popR(c, 4, a); + popR(c, 4, &ah); + } else { + c->code.append(0x50 | a->low); + } +} + void moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -307,10 +333,10 @@ void moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) { if (BytesPerWord == 4 and size == 8) { - moveRM(c, 4, a, b); - Assembler::Register ah(a->high); Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + moveRM(c, 4, a, b); moveRM(c, 4, &ah, &bh); } else if (BytesPerWord == 8 and size == 4) { encode(c, 0x89, a->low, b, false); @@ -324,10 +350,10 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - moveRR(c, 4, a, b); - Assembler::Register ah(a->low); Assembler::Register bh(b->low); + + moveRR(c, 4, a, b); moveRR(c, 4, &ah, &bh); } else { rex(c); @@ -351,10 +377,10 @@ moveMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) case 4: case 8: if (BytesPerWord == 4 and size == 8) { - moveMR(c, 4, a, b); - Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); Assembler::Register bh(b->high); + + moveMR(c, 4, a, b); moveMR(c, 4, &ah, &bh); } else if (BytesPerWord == 8 and size == 4) { encode(c, 0x63, b->low, a, true); @@ -393,6 +419,8 @@ populateTables() UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); + UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); + UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); From d654c943f346b71d75ee489a24fcbb465205a92e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 17 Feb 2008 13:57:40 -0700 Subject: [PATCH 005/121] various bugfixes and tweaks in new compiler, primarily related to duplicating stack operands --- src/compile.cpp | 50 +++-- src/compiler.cpp | 472 +++++++++++++++++++++++++++++++++++------------ src/compiler.h | 3 +- src/x86.cpp | 74 +++++++- test/Misc.java | 94 +++++----- 5 files changed, 492 insertions(+), 201 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 753fd663c8..3106bb73d0 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -733,6 +733,10 @@ class Frame { return r; } + Compiler::Operand* peekLong(unsigned index) { + return c->peek(8, index); + } + Compiler::Operand* popLong() { poppedLong(); return popLongQuiet(); @@ -803,10 +807,7 @@ class Frame { } void dup() { - Compiler::Operand* s0 = c->pop(BytesPerWord); - - c->push(BytesPerWord, s0); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, c->peek(BytesPerWord, 0))); dupped(); } @@ -817,7 +818,7 @@ class Frame { c->push(BytesPerWord, s0); c->push(BytesPerWord, s1); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, s0)); duppedX1(); } @@ -830,7 +831,7 @@ class Frame { c->push(BytesPerWord, s0); pushLongQuiet(s1); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, s0)); } else { Compiler::Operand* s1 = c->pop(BytesPerWord); Compiler::Operand* s2 = c->pop(BytesPerWord); @@ -838,7 +839,7 @@ class Frame { c->push(BytesPerWord, s0); c->push(BytesPerWord, s2); c->push(BytesPerWord, s1); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, s0)); } duppedX2(); @@ -846,18 +847,15 @@ class Frame { void dup2() { if (get(sp - 1) == Long) { - Compiler::Operand* s0 = popLongQuiet(); - - pushLongQuiet(s0); - pushLongQuiet(s0); + pushLongQuiet(c->dup(8, peekLong(0))); } else { Compiler::Operand* s0 = c->pop(BytesPerWord); Compiler::Operand* s1 = c->pop(BytesPerWord); c->push(BytesPerWord, s1); c->push(BytesPerWord, s0); - c->push(BytesPerWord, s1); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, s1)); + c->push(BytesPerWord, c->dup(BytesPerWord, s0)); } dupped2(); @@ -870,7 +868,7 @@ class Frame { pushLongQuiet(s0); c->push(BytesPerWord, s1); - pushLongQuiet(s0); + pushLongQuiet(c->dup(8, s0)); } else { Compiler::Operand* s0 = c->pop(BytesPerWord); Compiler::Operand* s1 = c->pop(BytesPerWord); @@ -879,8 +877,8 @@ class Frame { c->push(BytesPerWord, s1); c->push(BytesPerWord, s0); c->push(BytesPerWord, s2); - c->push(BytesPerWord, s1); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, s1)); + c->push(BytesPerWord, c->dup(BytesPerWord, s0)); } dupped2X1(); @@ -895,7 +893,7 @@ class Frame { pushLongQuiet(s0); pushLongQuiet(s1); - pushLongQuiet(s0); + pushLongQuiet(c->dup(8, s0)); } else { Compiler::Operand* s1 = c->pop(BytesPerWord); Compiler::Operand* s2 = c->pop(BytesPerWord); @@ -903,7 +901,7 @@ class Frame { pushLongQuiet(s0); c->push(BytesPerWord, s2); c->push(BytesPerWord, s1); - pushLongQuiet(s0); + pushLongQuiet(c->dup(8, s0)); } } else { Compiler::Operand* s0 = c->pop(BytesPerWord); @@ -915,8 +913,8 @@ class Frame { c->push(BytesPerWord, s0); c->push(BytesPerWord, s3); c->push(BytesPerWord, s2); - c->push(BytesPerWord, s1); - c->push(BytesPerWord, s0); + c->push(BytesPerWord, c->dup(BytesPerWord, s1)); + c->push(BytesPerWord, c->dup(BytesPerWord, s0)); } dupped2X2(); @@ -1788,7 +1786,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Compiler::Operand* instance = c->peek(0); + Compiler::Operand* instance = c->peek(BytesPerWord, 0); c->call (c->constant(reinterpret_cast(checkCast)), @@ -2396,7 +2394,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(target), - c->peek(instance)), + c->peek(BytesPerWord, instance)), 0, 0, frame->trace(target, true), @@ -2443,7 +2441,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) unsigned offset = ClassVtable + (methodOffset(t, target) * BytesPerWord); - Compiler::Operand* instance = c->peek(parameterFootprint - 1); + Compiler::Operand* instance = c->peek + (BytesPerWord, parameterFootprint - 1); unsigned rSize = resultSize(t, methodReturnCode(t, target)); @@ -3463,14 +3462,13 @@ finish(MyThread* t, Context* context) Compiler* c = context->compiler; unsigned codeSize = c->compile(); - object result = allocateCode(t, codeSize + c->poolSize()); + object result = allocateCode(t, pad(codeSize) + c->poolSize()); + PROTECT(t, result); uint8_t* start = reinterpret_cast(&singletonValue(t, result, 0)); c->writeTo(start); - PROTECT(t, result); - unsigned mapSize = frameMapSizeInWords(t, context->method); for (TraceElement* p = context->traceLog; p; p = p->next) { diff --git a/src/compiler.cpp b/src/compiler.cpp index ad54cf58d7..7e40a4655c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -22,10 +22,11 @@ class Value { public: virtual ~Value() { } - virtual bool equals(Value*) { return false; } - virtual bool equals(RegisterValue*) { return false; } + virtual OperandType type() = 0; - virtual void preserve(Context*) { } + virtual bool equals(Value*) { return false; } + + virtual void preserve(Context*, MyOperand*) { } virtual void acquire(Context*, MyOperand*) { } virtual void release(Context*, MyOperand*) { } @@ -39,15 +40,24 @@ class Value { class MyOperand: public Compiler::Operand { public: MyOperand(Value* value): - event(0), value(value), target(0), size(0), index(0), next(0) + event(0), value(value), target(0) { } Event* event; Value* value; Value* target; +}; + +class Stack { + public: + Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next): + operand(operand), size(size), index(index), next(next) + { } + + MyOperand* operand; unsigned size; unsigned index; - MyOperand* next; + Stack* next; }; class State { @@ -57,7 +67,7 @@ class State { next(s) { } - MyOperand* stack; + Stack* stack; State* next; }; @@ -191,7 +201,7 @@ class PoolPromise: public Promise { virtual int64_t value() { if (resolved()) { return reinterpret_cast - (c->machineCode + c->assembler->length() + key); + (c->machineCode + pad(c->assembler->length()) + key); } abort(c); @@ -209,6 +219,8 @@ class CodePromise: public Promise { public: CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { } + CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } + virtual int64_t value() { if (resolved()) { return reinterpret_cast(c->machineCode + offset); @@ -257,6 +269,8 @@ class ConstantValue: public Value { public: ConstantValue(Promise* value): value(value) { } + virtual OperandType type() { return Constant; } + virtual RegisterValue* toRegister(Context* c); virtual void asAssemblerOperand(Context*, @@ -287,6 +301,8 @@ class AddressValue: public Value { public: AddressValue(Promise* address): address(address) { } + virtual OperandType type() { return Address; } + virtual RegisterValue* toRegister(Context* c); virtual void asAssemblerOperand(Context*, @@ -306,35 +322,43 @@ address(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address); } -void preserve(Context* c, int reg); +void preserve(Context* c, int reg, MyOperand* a); class RegisterValue: public Value { public: RegisterValue(int low, int high): register_(low, high) { } - virtual bool equals(Value* o) { return o->equals(this); } + virtual OperandType type() { return Register; } - virtual bool equals(RegisterValue* o) { - return o->register_.low == register_.low - and o->register_.high == register_.high; + virtual bool equals(Value* o) { + return this == o or + (o->type() == Register + and static_cast(o)->register_.low == register_.low + and static_cast(o)->register_.high == register_.high); } - virtual void preserve(Context* c) { - ::preserve(c, register_.low); - if (register_.high >= 0) ::preserve(c, register_.high); + virtual void preserve(Context* c, MyOperand* a) { + ::preserve(c, register_.low, a); + if (register_.high >= 0) ::preserve(c, register_.high, a); } 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; + if (a != c->registers[register_.low].operand) { + fprintf(stderr, "%p acquire %d\n", a, register_.low); + + preserve(c, a); + 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); + if (a == c->registers[register_.low].operand) { + fprintf(stderr, "%p release %d\n", a, register_.low); - c->registers[register_.low].operand = 0; - if (register_.high >= 0) c->registers[register_.high].operand = 0; + c->registers[register_.low].operand = 0; + if (register_.high >= 0) c->registers[register_.high].operand = 0; + } } virtual RegisterValue* toRegister(Context*) { @@ -366,6 +390,17 @@ class MemoryValue: public Value { value(base, offset, index, scale, traceHandler) { } + virtual OperandType type() { return Memory; } + + virtual bool equals(Value* o) { + return this == o or + (o->type() == Memory + and static_cast(o)->value.base == value.base + and static_cast(o)->value.offset == value.offset + and static_cast(o)->value.index == value.index + and static_cast(o)->value.scale == value.scale); + } + virtual RegisterValue* toRegister(Context* c) { RegisterValue* v = freeRegister(c, BytesPerWord); apply(c, Move, BytesPerWord, this, v); @@ -458,7 +493,7 @@ class Event { virtual void compile(Context* c) = 0; Event* next; - MyOperand* stack; + Stack* stack; CodePromise* promises; }; @@ -466,7 +501,10 @@ class ArgumentEvent: public Event { public: ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): Event(c), size(size), a(a), index(index) - { } + { + assert(c, a->event == 0); + a->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == a); @@ -475,7 +513,7 @@ class ArgumentEvent: public Event { return register_(c, c->assembler->argumentRegister(index)); } else { return memory(c, c->assembler->base(), - (v->index + c->stackOffset) * BytesPerWord, + index + (c->stackOffset * BytesPerWord), NoRegister, 0, 0); } } @@ -487,8 +525,12 @@ class ArgumentEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "ArgumentEvent.compile\n"); + + if (a->target == 0) a->target = target(c, a); + a->value->release(c, a); - a->target->preserve(c); + a->target->preserve(c, a); if (not a->target->equals(a->value)) { apply(c, Move, size, a->value, a->target); @@ -511,7 +553,12 @@ class ReturnEvent: public Event { public: ReturnEvent(Context* c, unsigned size, MyOperand* a): Event(c), size(size), a(a) - { } + { + if (a) { + assert(c, a->event == 0); + a->event = this; + } + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == a); @@ -526,7 +573,11 @@ class ReturnEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "ReturnEvent.compile\n"); + if (a) { + if (a->target == 0) a->target = target(c, a); + a->value->release(c, a); if (not a->target->equals(a->value)) { @@ -536,6 +587,7 @@ class ReturnEvent: public Event { Assembler::Register base(c->assembler->base()); Assembler::Register stack(c->assembler->stack()); + c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack); c->assembler->apply(Pop, BytesPerWord, Register, &base); c->assembler->apply(Return); @@ -553,15 +605,19 @@ appendReturn(Context* c, unsigned size, MyOperand* value) class SyncForCallEvent: public Event { public: - SyncForCallEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): - Event(c), size(size), src(src), dst(dst) - { } + SyncForCallEvent(Context* c, unsigned size, unsigned index, MyOperand* src, + MyOperand* dst): + Event(c), size(size), index(index), src(src), dst(dst) + { + assert(c, src->event == 0); + src->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == src); return memory(c, c->assembler->base(), - (v->index + c->stackOffset) * BytesPerWord, + index + (c->stackOffset * BytesPerWord), NoRegister, 0, 0); } @@ -572,43 +628,68 @@ class SyncForCallEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "SyncForCallEvent.compile\n"); + + if (src->target == 0) src->target = target(c, src); + src->value->release(c, src); if (not src->target->equals(src->value)) { + if (src->value->type() == Memory and src->target->type() == Memory) { + RegisterValue* tmp = freeRegister(c, size); + tmp->preserve(c, 0); + apply(c, Move, size, src->value, tmp); + src->value = tmp; + } + apply(c, Move, size, src->value, src->target); } + + dst->value = src->target; } unsigned size; + unsigned index; MyOperand* src; MyOperand* dst; }; void -appendSyncForCall(Context* c, unsigned size, MyOperand* src, MyOperand* dst) +appendSyncForCall(Context* c, unsigned size, unsigned index, MyOperand* src, + MyOperand* dst) { new (c->zone->allocate(sizeof(SyncForCallEvent))) - SyncForCallEvent(c, size, src, dst); + SyncForCallEvent(c, size, index, src, dst); } class SyncForJumpEvent: public Event { public: - SyncForJumpEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): - Event(c), size(size), src(src), dst(dst) - { } + SyncForJumpEvent(Context* c, unsigned size, unsigned index, MyOperand* src, + MyOperand* dst): + Event(c), size(size), index(index), src(src), dst(dst) + { + assert(c, src->event == 0); + src->event = this; + } - SyncForJumpEvent(Event* next, unsigned size, MyOperand* src, MyOperand* dst): - Event(next), size(size), src(src), dst(dst) - { } + SyncForJumpEvent(Context* c, Event* next, unsigned size, unsigned index, + MyOperand* src, MyOperand* dst): + Event(next), size(size), index(index), src(src), dst(dst) + { + assert(c, src->event == 0); + src->event = this; + } 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)); + if (BytesPerWord == 4 and size == 8) { + return register_ + (c, c->assembler->stackSyncRegister(index / BytesPerWord), + c->assembler->stackSyncRegister((index / BytesPerWord) + 1)); } else { - return register_(c, c->assembler->stackSyncRegister(v->index)); + return register_ + (c, c->assembler->stackSyncRegister(index / BytesPerWord)); } } @@ -619,6 +700,10 @@ class SyncForJumpEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "SyncForJumpEvent.compile\n"); + + if (src->target == 0) src->target = target(c, src); + src->value->release(c, src); src->target->acquire(c, dst); @@ -630,15 +715,17 @@ class SyncForJumpEvent: public Event { } unsigned size; + unsigned index; MyOperand* src; MyOperand* dst; }; void -appendSyncForJump(Context* c, unsigned size, MyOperand* src, MyOperand* dst) +appendSyncForJump(Context* c, unsigned size, unsigned index, MyOperand* src, + MyOperand* dst) { new (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(c, size, src, dst); + SyncForJumpEvent(c, size, index, src, dst); } class CallEvent: public Event { @@ -653,7 +740,10 @@ class CallEvent: public Event { traceHandler(traceHandler), result(result), stackOffset(stackOffset) - { } + { + assert(c, address->event == 0); + address->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == address); @@ -672,6 +762,12 @@ class CallEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "CallEvent.compile\n"); + + if (indirection and address->target == 0) { + address->target = target(c, address); + } + address->value->release(c, address); if (result->event) { @@ -680,12 +776,14 @@ class CallEvent: public Event { 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 (stackOffset != c->stackOffset) { + 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)) { + if (address->target->equals(address->value)) { apply(c, Move, BytesPerWord, address->value, address->target); } apply(c, Call, BytesPerWord, @@ -693,6 +791,12 @@ class CallEvent: public Event { } else { apply(c, Call, BytesPerWord, address->value); } + + if (traceHandler) { + traceHandler->handleTrace + (new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, c->assembler->length())); + } } MyOperand* address; @@ -716,7 +820,7 @@ appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, int freeRegister(Context* c) { - for (unsigned i = 0; i < c->assembler->registerCount(); ++i) { + for (int i = c->assembler->registerCount(); i >= 0; --i) { if ((not c->registers[i].reserved) and c->registers[i].operand == 0) { @@ -724,7 +828,7 @@ freeRegister(Context* c) } } - for (unsigned i = 0; i < c->assembler->registerCount(); ++i) { + for (int i = c->assembler->registerCount(); i >= 0; --i) { if (not c->registers[i].reserved) { return i; } @@ -748,15 +852,20 @@ class MoveEvent: public Event { MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src, MyOperand* dst): Event(c), type(type), size(size), src(src), dst(dst) - { } + { + assert(c, src->event == 0); + src->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == src); if (dst->value) { return dst->value; + } else if (dst->event) { + return dst->event->target(c, dst); } else { - return v->event->target(c, dst); + return 0; } } @@ -767,12 +876,18 @@ class MoveEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "MoveEvent.compile\n"); + + if (src->target == 0) src->target = target(c, src); + if (src->target == 0) { - if (dst->value) { - src->target = dst->value; - } else { - src->target = freeRegister(c, size); - } + src->target = freeRegister(c, size); + } else if (src->value->type() == Memory and src->target->type() == Memory) + { + RegisterValue* tmp = freeRegister(c, size); + tmp->preserve(c, 0); + apply(c, Move, size, src->value, tmp); + src->value = tmp; } src->value->release(c, src); @@ -797,11 +912,67 @@ appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src, MoveEvent(c, type, size, src, dst); } +class DupEvent: public Event { + public: + DupEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): + Event(c), size(size), src(src), dst(dst) + { } + + virtual Value* target(Context* c, MyOperand*) { + abort(c); + } + + virtual void replace(Context* c, MyOperand*, MyOperand*) { + abort(c); + } + + virtual void compile(Context* c) { + fprintf(stderr, "DupEvent.compile\n"); + + Value* value = src->value; + Value* target = dst->value; + + if (target == 0) { + if (dst->event) { + target = dst->event->target(c, dst); + } else { + target = freeRegister(c, size); + } + } else if (value->type() == Memory and target->type() == Memory) { + RegisterValue* tmp = freeRegister(c, size); + tmp->preserve(c, 0); + apply(c, Move, size, value, tmp); + value = tmp; + } + + target->acquire(c, dst); + + apply(c, Move, size, value, target); + + dst->value = target; + } + + unsigned size; + MyOperand* src; + MyOperand* dst; +}; + +void +appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst) +{ + new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst); +} + class CompareEvent: public Event { public: CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): Event(c), size(size), a(a), b(b) - { } + { + assert(c, a->event == 0); + a->event = this; + assert(c, b->event == 0); + b->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == a or v == b); @@ -821,6 +992,8 @@ class CompareEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "CompareEvent.compile\n"); + a->value->release(c, a); b->value->release(c, b); @@ -842,7 +1015,10 @@ class BranchEvent: public Event { public: BranchEvent(Context* c, UnaryOperation type, MyOperand* address): Event(c), type(type), address(address) - { } + { + assert(c, address->event == 0); + address->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == address); @@ -857,6 +1033,8 @@ class BranchEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "BranchEvent.compile\n"); + address->value->release(c, address); apply(c, type, BytesPerWord, address->value); @@ -877,7 +1055,10 @@ class JumpEvent: public Event { JumpEvent(Context* c, MyOperand* address): Event(c), address(address) - { } + { + assert(c, address->event == 0); + address->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == address); @@ -891,6 +1072,8 @@ class JumpEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "JumpEvent.compile\n"); + address->value->release(c, address); apply(c, Jump, BytesPerWord, address->value); @@ -913,12 +1096,17 @@ class CombineEvent: public Event { CombineEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* a, MyOperand* b, MyOperand* result): Event(c), type(type), size(size), a(a), b(b), result(result) - { } + { + assert(c, a->event == 0); + a->event = this; + assert(c, b->event == 0); + b->event = this; + } virtual Value* target(Context* c, MyOperand* v) { Assembler::Register ar(NoRegister); Assembler::Register br(NoRegister); - c->assembler->getTargets(type, v->size, &ar, &br); + c->assembler->getTargets(type, size, &ar, &br); if (v == a) { if (ar.low == NoRegister) { @@ -930,7 +1118,16 @@ class CombineEvent: public Event { assert(c, v == b); if (br.low == NoRegister) { - return result->event->target(c, result); + if (result->event) { + Value* v = result->event->target(c, result); + if (v->type() == Register) { + return v; + } else { + return 0; + } + } else { + return 0; + } } else { return register_(c, br.low, br.high); } @@ -949,6 +1146,11 @@ class CombineEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "CombineEvent.compile\n"); + + if (a->target == 0) a->target = target(c, a); + if (b->target == 0) b->target = target(c, b); + a->value->release(c, a); b->value->release(c, b); b->value->acquire(c, result); @@ -985,13 +1187,16 @@ class TranslateEvent: public Event { TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a, MyOperand* result): Event(c), type(type), size(size), a(a), result(result) - { } + { + assert(c, a->event == 0); + a->event = this; + } virtual Value* target(Context* c, MyOperand* v) { assert(c, v == a); Assembler::Register r(NoRegister); - c->assembler->getTargets(type, v->size, &r); + c->assembler->getTargets(type, size, &r); if (r.low == NoRegister) { return result->event->target(c, result); @@ -1007,9 +1212,16 @@ class TranslateEvent: public Event { } virtual void compile(Context* c) { + fprintf(stderr, "TranslateEvent.compile\n"); + + if (a->target == 0) a->target = target(c, a); + result->value->acquire(c, result); - apply(c, type, a->size, a->value); + if (a->target and not a->target->equals(a->value)) { + apply(c, Move, size, a->value, a->target); + } + apply(c, type, size, a->value); result->value = a->value; } @@ -1045,18 +1257,21 @@ AddressValue::toRegister(Context* c) } void -preserve(Context* c, int reg) +preserve(Context* c, int reg, MyOperand* a) { - MyOperand* a = c->registers[reg].operand; - if (a) { - MemoryValue* dst = memory - (c, c->assembler->base(), (a->index + c->stackOffset) * BytesPerWord, - -1, 0, 0); + MyOperand* b = c->registers[reg].operand; + if (b and a != b) { + fprintf(stderr, "%p preserve %d for %p\n", a, reg, b); - apply(c, Move, a->size, a->value, dst); + abort(c); +// MemoryValue* dst = memory +// (c, c->assembler->base(), (b->index + c->stackOffset) * BytesPerWord, +// -1, 0, 0); - a->value = dst; - c->registers[reg].operand = 0; +// apply(c, Move, b->size, b->value, dst); + +// b->value = dst; +// c->registers[reg].operand = 0; } } @@ -1080,52 +1295,59 @@ popState(Context* c) State(c->state->next); } +Stack* +stack(Context* c, MyOperand* operand, unsigned size, unsigned index, + Stack* next) +{ + return new (c->zone->allocate(sizeof(Stack))) + Stack(operand, size, index, next); +} + void push(Context* c, unsigned size, MyOperand* o) { - assert(c, o->size == 0 and o->index == 0); + assert(c, ceiling(size, BytesPerWord)); + assert(c, o->event == 0); - o->next = c->state->stack; - o->size = ceiling(size, BytesPerWord); - o->index = ceiling(size, BytesPerWord) - + (c->state->stack ? c->state->stack->index : 0); - c->state->stack = o; + c->state->stack = stack + (c, o, ceiling(size, BytesPerWord), + ceiling(size, BytesPerWord) + + (c->state->stack ? c->state->stack->index : 0), + c->state->stack); } MyOperand* pop(Context* c, unsigned size UNUSED) { - MyOperand* o = c->state->stack; - assert(c, ceiling(size, BytesPerWord) == o->size); + Stack* s = c->state->stack; + assert(c, ceiling(size, BytesPerWord) == s->size); - c->state->stack = o->next; - return o; + c->state->stack = s->next; + return s->operand; } 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); - if (new_) { - new_->next = n; + Stack* newStack = 0; + for (Stack* s = c->state->stack; s; s = s->next) { + MyOperand* old = s->operand; + MyOperand* new_ = operand(c); + Stack* ns = stack(c, new_, s->size, s->index, 0); + if (newStack) { + newStack->next = ns; } else { - top = n; + newStack = c->state->stack = ns; } - new_ = n; - new_->size = old->size; - new_->index = old->index; if (type == SyncForCall) { - appendSyncForCall(c, old->size * BytesPerWord, old, new_); + appendSyncForCall + (c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_); } else { - appendSyncForJump(c, old->size * BytesPerWord, old, new_); + appendSyncForJump + (c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_); } } - - c->state->stack = top; } void @@ -1137,13 +1359,9 @@ updateJunctions(Context* c) 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); - if (new_) new_->next = n; - new_ = n; - new_->size = old->size; - new_->index = old->index; + for (Stack* s = c->state->stack; s; s = s->next) { + MyOperand* old = s->operand; + MyOperand* new_ = operand(c); if (old->event) { old->event->replace(c, old, new_); @@ -1151,7 +1369,9 @@ updateJunctions(Context* c) p->lastEvent = p->lastEvent->next = new (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(p->lastEvent->next, old->size, old, new_); + SyncForJumpEvent + (c, p->lastEvent->next, s->size * BytesPerWord, + s->index * BytesPerWord, old, new_); } } } @@ -1170,7 +1390,6 @@ compile(Context* c) for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { fprintf(stderr, "compile ip %d\n", i); for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { - fprintf(stderr, "compile ip %d event\n", i); e->compile(c); if (e == c->logicalCode[i].lastEvent) break; @@ -1307,17 +1526,21 @@ class MyCompiler: public Compiler { } virtual void popped(unsigned count) { - for (int i = count; i >= 0;) { - MyOperand* o = c.state->stack; - c.state->stack = o->next; - count -= o->size; + for (unsigned i = count; i > 0;) { + Stack* s = c.state->stack; + c.state->stack = s->next; + i -= s->size; } } - virtual Operand* peek(unsigned index) { - MyOperand* a = c.state->stack; - for (; index; --index) a = a->next; - return a; + virtual Operand* peek(unsigned size, unsigned index) { + Stack* s = c.state->stack; + for (unsigned i = index; i > 0;) { + s = s->next; + i -= s->size; + } + assert(&c, s->size == ceiling(size, BytesPerWord)); + return s->operand; } virtual Operand* call(Operand* address, @@ -1347,9 +1570,10 @@ class MyCompiler: public Compiler { syncStack(&c, SyncForCall); - unsigned stackOffset = c.stackOffset + c.state->stack->index - + (footprint > c.assembler->argumentRegisterCount() ? - footprint - c.assembler->argumentRegisterCount() : 0); + unsigned stackOffset = c.stackOffset + + (c.state->stack ? c.state->stack->index + + (footprint > c.assembler->argumentRegisterCount() ? + footprint - c.assembler->argumentRegisterCount() : 0) : 0); MyOperand* result = operand(&c); appendCall(&c, static_cast(address), indirection, flags, @@ -1384,6 +1608,12 @@ class MyCompiler: public Compiler { return dst; } + virtual Operand* dup(unsigned size, Operand* src) { + MyOperand* dst = operand(&c); + appendDup(&c, size, static_cast(src), dst); + return dst; + } + virtual void cmp(unsigned size, Operand* a, Operand* b) { appendCompare(&c, size, static_cast(a), static_cast(b)); @@ -1530,7 +1760,7 @@ class MyCompiler: public Compiler { int i = 0; for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) { - *reinterpret_cast(dst + c.assembler->length() + (i++)) + *reinterpret_cast(dst + pad(c.assembler->length()) + (i++)) = n->promise->value(); } } diff --git a/src/compiler.h b/src/compiler.h index aa8a35d381..5eb2593e29 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -48,7 +48,7 @@ class Compiler { virtual Operand* pop(unsigned size) = 0; virtual void pushed(unsigned count) = 0; virtual void popped(unsigned count) = 0; - virtual Operand* peek(unsigned index) = 0; + virtual Operand* peek(unsigned size, unsigned index) = 0; virtual Operand* call(Operand* address, void* indirection, @@ -64,6 +64,7 @@ class Compiler { virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; virtual Operand* load4To8(Operand* src) = 0; + virtual Operand* dup(unsigned size, Operand* src) = 0; virtual void cmp(unsigned size, Operand* a, Operand* b) = 0; virtual void jl(Operand* address) = 0; virtual void jg(Operand* address) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index 63f0f65671..b58944785c 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -121,7 +121,7 @@ class Task { class OffsetTask: public Task { public: - OffsetTask(Task* next, Promise* promise, int instructionOffset, + OffsetTask(Task* next, Promise* promise, unsigned instructionOffset, unsigned instructionSize): Task(next), promise(promise), @@ -141,7 +141,7 @@ class OffsetTask: public Task { } Promise* promise; - int instructionOffset; + unsigned instructionOffset; unsigned instructionSize; }; @@ -153,6 +153,30 @@ appendOffsetTask(Context* c, Promise* promise, int instructionOffset, (c->tasks, promise, instructionOffset, instructionSize); } +class ImmediateTask: public Task { + public: + ImmediateTask(Task* next, Promise* promise, unsigned offset): + Task(next), + promise(promise), + offset(offset) + { } + + virtual void run(Context* c) { + intptr_t v = promise->value(); + memcpy(c->result + offset, &v, BytesPerWord); + } + + Promise* promise; + unsigned offset; +}; + +void +appendImmediateTask(Context* c, Promise* promise, unsigned offset) +{ + c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask + (c->tasks, promise, offset); +} + void encode(Context* c, uint8_t* instruction, unsigned length, int a, int b, int32_t displacement, int index, unsigned scale) @@ -307,6 +331,18 @@ popR(Context* c, unsigned size, Assembler::Register* a) } } +void +leaRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) +{ + if (BytesPerWord == 8 and size == 4) { + encode(c, 0x8d, a->low, b, false); + } else { + assert(c, BytesPerWord == 8 or size == 4); + + encode(c, 0x8d, a->low, b, true); + } +} + void moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -315,7 +351,12 @@ moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, rex(c); c->code.append(0xb8 | b->low); - c->code.appendAddress(a->value->value()); + if (a->value->resolved()) { + c->code.appendAddress(a->value->value()); + } else { + appendImmediateTask(c, a->value, c->code.length()); + c->code.appendAddress(static_cast(0)); + } } void @@ -393,6 +434,19 @@ moveMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) } } +void +moveAR(Context* c, unsigned size, Assembler::Address* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Constant constant(a->address); + Assembler::Memory memory(b->low, 0, -1, 0); + + moveCR(c, size, &constant, b); + moveMR(c, size, &memory, b); +} + void move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) { @@ -412,6 +466,15 @@ addRR(Context* c, unsigned size, Assembler::Register* a, c->code.append(0xc0 | (a->low << 3) | b->low); } +void +addRM(Context* c, unsigned size, Assembler::Register* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + encode(c, 0x01, a->low, b, true); +} + void populateTables() { @@ -422,13 +485,16 @@ populateTables() UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); + BinaryOperations[INDEX2(LoadAddress, Register, Memory)] = CAST2(leaRM); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); + BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); + BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); } class MyAssembler: public Assembler { @@ -442,7 +508,7 @@ class MyAssembler: public Assembler { } virtual unsigned registerCount() { - return BytesPerWord == 4 ? 8 : 16; + return 8;//BytesPerWord == 4 ? 8 : 16; } virtual int base() { diff --git a/test/Misc.java b/test/Misc.java index 3565bd4871..76d62c04d6 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,67 +1,60 @@ public class Misc { -// private static int alpha; -// private static int beta; -// private static byte byte1, byte2, byte3; -// private int gamma; + private static int alpha; + private static int beta; + private static byte byte1, byte2, byte3; + private int gamma; -// private String foo(String s) { -// return s; -// } + private String foo(String s) { + return s; + } -// public String bar(String s) { -// return s; -// } + public String bar(String s) { + return s; + } -// private static String baz(String s) { -// return s; -// } + private static String baz(String s) { + return s; + } -// private static void expect(boolean v) { -// if (! v) throw new RuntimeException(); -// } + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } -// private synchronized byte sync() { -// byte[] array = new byte[123]; -// return array[42]; -// } + private synchronized byte sync() { + byte[] array = new byte[123]; + return array[42]; + } -// private static synchronized byte syncStatic(boolean throw_) { -// byte[] array = new byte[123]; -// if (throw_) { -// throw new RuntimeException(); -// } else { -// return array[42]; -// } -// } + private static synchronized byte syncStatic(boolean throw_) { + byte[] array = new byte[123]; + if (throw_) { + throw new RuntimeException(); + } else { + return array[42]; + } + } -// public static void putInt(int val, byte[] dst, int offset) { -// System.out.println("put " + val); -// dst[offset] = (byte)((val >> 24) & 0xff); -// dst[offset+1] = (byte)((val >> 16) & 0xff); -// dst[offset+2] = (byte)((val >> 8) & 0xff); -// dst[offset+3] = (byte)((val ) & 0xff); -// } + public static void putInt(int val, byte[] dst, int offset) { + System.out.println("put " + val); + dst[offset] = (byte)((val >> 24) & 0xff); + dst[offset+1] = (byte)((val >> 16) & 0xff); + dst[offset+2] = (byte)((val >> 8) & 0xff); + dst[offset+3] = (byte)((val ) & 0xff); + } -// public static void putLong(long val, byte[] dst, int offset) { -// putInt((int)(val >> 32), dst, offset); -// putInt((int)val, dst, offset + 4); -// } + public static void putLong(long val, byte[] dst, int offset) { + putInt((int)(val >> 32), dst, offset); + putInt((int)val, dst, offset + 4); + } -// public String toString() { -// return super.toString(); -// } + public String toString() { + return super.toString(); + } public static void main(String[] args) { - int a = 2; - int b = 2; - int c = a + b; - // byte2 = 0; // expect(byte2 == 0); -// Misc m = new Misc(); -// m.toString(); - // expect(Long.valueOf(231L) == 231L); // long x = 231; @@ -97,6 +90,9 @@ public class Misc { // int b = 2; // int c = a + b; + Misc m = new Misc(); +// m.toString(); + // String s = "hello"; // m.foo(s); // m.bar(s); From e8ed2a474949aa3af03b6414a94288eab150b1c9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 17 Feb 2008 15:29:04 -0700 Subject: [PATCH 006/121] various bugfixes in new compiler --- src/assembler.h | 5 ++-- src/compile.cpp | 23 +++++++++++++--- src/compiler.cpp | 41 ++++++++++++++++------------ src/x86.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 112 insertions(+), 28 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 9a7a361784..117d7d3618 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -13,16 +13,17 @@ enum Operation { const unsigned OperationCount = Return + 1; enum UnaryOperation { - Call, Push, Pop, + Call, + AlignedCall, + Jump, JumpIfLess, JumpIfGreater, JumpIfLessOrEqual, JumpIfGreaterOrEqual, JumpIfEqual, JumpIfNotEqual, - Jump, Negate }; diff --git a/src/compile.cpp b/src/compile.cpp index 3106bb73d0..4c0d8bb32b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3510,7 +3510,7 @@ finish(MyThread* t, Context* context) } // for debugging: - if (//false and + if (true or//false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), @@ -3966,7 +3966,7 @@ saveStackAndBase(MyThread* t, Assembler* a) a->apply(Move, BytesPerWord, Register, &base, Memory, &baseDst); Assembler::Register stack(a->stack()); - Assembler::Memory stackDst(a->thread(), difference(&(t->base), t)); + Assembler::Memory stackDst(a->thread(), difference(&(t->stack), t)); a->apply(Move, BytesPerWord, Register, &stack, Memory, &stackDst); } @@ -3983,16 +3983,29 @@ pushThread(MyThread*, Assembler* a) } } +void +popThread(MyThread*, Assembler* a) +{ + if (a->argumentRegisterCount() == 0) { + ResolvedPromise bpwPromise(BytesPerWord); + Assembler::Constant bpw(&bpwPromise); + Assembler::Register stack(a->stack()); + a->apply(Add, BytesPerWord, Constant, &bpw, Register, &stack); + } +} + object compileDefault(MyThread* t, Assembler* a) { saveStackAndBase(t, a); pushThread(t, a); - ResolvedPromise promise(reinterpret_cast(compileMethod)); - Assembler::Constant proc(&promise); + ResolvedPromise procPromise(reinterpret_cast(compileMethod)); + Assembler::Constant proc(&procPromise); a->apply(Call, BytesPerWord, Constant, &proc); + popThread(t, a); + Assembler::Register result(a->returnLow()); a->apply(Jump, BytesPerWord, Register, &result); @@ -4009,6 +4022,8 @@ compileNative(MyThread* t, Assembler* a) Assembler::Constant proc(&promise); a->apply(Call, BytesPerWord, Constant, &proc); + popThread(t, a); + a->apply(Return); return finish(t, a, "native"); diff --git a/src/compiler.cpp b/src/compiler.cpp index 7e40a4655c..52b0e2bf88 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -513,7 +513,7 @@ class ArgumentEvent: public Event { return register_(c, c->assembler->argumentRegister(index)); } else { return memory(c, c->assembler->base(), - index + (c->stackOffset * BytesPerWord), + -(index + ((c->stackOffset + 1) * BytesPerWord)), NoRegister, 0, 0); } } @@ -617,7 +617,7 @@ class SyncForCallEvent: public Event { assert(c, v == src); return memory(c, c->assembler->base(), - index + (c->stackOffset * BytesPerWord), + -(index + ((c->stackOffset + 1) * BytesPerWord)), NoRegister, 0, 0); } @@ -749,8 +749,7 @@ class CallEvent: public Event { assert(c, v == address); if (indirection) { - return register_ - (c, c->assembler->returnLow(), c->assembler->returnHigh()); + return register_(c, c->assembler->returnLow(), NoRegister); } else { return 0; } @@ -777,19 +776,23 @@ class CallEvent: public Event { } if (stackOffset != c->stackOffset) { - apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()), - memory(c, c->assembler->base(), stackOffset * BytesPerWord, - NoRegister, 0, 0)); + apply(c, LoadAddress, BytesPerWord, + memory(c, c->assembler->base(), + -((stackOffset + 1) * BytesPerWord), + NoRegister, 0, 0), + register_(c, c->assembler->stack())); } + UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); + if (indirection) { - if (address->target->equals(address->value)) { + if (not address->target->equals(address->value)) { apply(c, Move, BytesPerWord, address->value, address->target); } - apply(c, Call, BytesPerWord, + apply(c, type, BytesPerWord, constant(c, reinterpret_cast(indirection))); } else { - apply(c, Call, BytesPerWord, address->value); + apply(c, type, BytesPerWord, address->value); } if (traceHandler) { @@ -1303,17 +1306,19 @@ stack(Context* c, MyOperand* operand, unsigned size, unsigned index, Stack(operand, size, index, next); } +Stack* +stack(Context* c, MyOperand* operand, unsigned size, Stack* next) +{ + return stack(c, operand, size, (next ? next->index + size : 0), next); +} + void push(Context* c, unsigned size, MyOperand* o) { assert(c, ceiling(size, BytesPerWord)); assert(c, o->event == 0); - c->state->stack = stack - (c, o, ceiling(size, BytesPerWord), - ceiling(size, BytesPerWord) - + (c->state->stack ? c->state->stack->index : 0), - c->state->stack); + c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); } MyOperand* @@ -1571,9 +1576,9 @@ class MyCompiler: public Compiler { syncStack(&c, SyncForCall); unsigned stackOffset = c.stackOffset - + (c.state->stack ? c.state->stack->index - + (footprint > c.assembler->argumentRegisterCount() ? - footprint - c.assembler->argumentRegisterCount() : 0) : 0); + + (c.state->stack ? c.state->stack->index + c.state->stack->size : 0) + + (footprint > c.assembler->argumentRegisterCount() ? + footprint - c.assembler->argumentRegisterCount() : 0); MyOperand* result = operand(&c); appendCall(&c, static_cast(address), indirection, flags, diff --git a/src/x86.cpp b/src/x86.cpp index b58944785c..9815eb315a 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -297,7 +297,16 @@ callC(Context* c, unsigned size UNUSED, Assembler::Constant* a) } void -jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) +alignedCallC(Context* c, unsigned size, Assembler::Constant* a) +{ + while ((c->code.length() + 1) % 4) { + c->code.append(0x90); + } + callC(c, size, a); +} + +void +callR(Context* c, unsigned size UNUSED, Assembler::Register* a) { assert(c, size == BytesPerWord); @@ -305,6 +314,15 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) c->code.append(0xd0 | a->low); } +void +jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) +{ + assert(c, size == BytesPerWord); + + c->code.append(0xff); + c->code.append(0xe0 | a->low); +} + void pushR(Context* c, unsigned size, Assembler::Register* a) { @@ -318,6 +336,10 @@ pushR(Context* c, unsigned size, Assembler::Register* a) } } +void +move4To8RR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b); + void popR(Context* c, unsigned size, Assembler::Register* a) { @@ -327,12 +349,15 @@ popR(Context* c, unsigned size, Assembler::Register* a) popR(c, 4, a); popR(c, 4, &ah); } else { - c->code.append(0x50 | a->low); + c->code.append(0x58 | a->low); + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, 0, a, a); + } } } void -leaRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) +leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) { if (BytesPerWord == 8 and size == 4) { encode(c, 0x8d, a->low, b, false); @@ -403,6 +428,17 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } } +void +move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8); + + rex(c); + c->code.append(0x63); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void moveMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) { @@ -455,6 +491,29 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) encode(c, 0x63, b->low, a, true); } +void +addCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + if (v) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xc0 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xc0 | b->low); + c->code.append4(v); + } else { + abort(c); + } + } +} + void addRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -481,18 +540,22 @@ populateTables() Operations[Return] = return_; UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); + UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); + UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); - BinaryOperations[INDEX2(LoadAddress, Register, Memory)] = CAST2(leaRM); + BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); + BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); + BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); } From 888836f8cd3a6577ec35fd8084566fa2fc4e80b7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 9 Mar 2008 15:27:51 -0600 Subject: [PATCH 007/121] use push and pop for stack operations instead of mov --- src/compiler.cpp | 509 ++++++++++++++++++----------------------------- src/x86.cpp | 24 ++- 2 files changed, 217 insertions(+), 316 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index a6e78e527a..010b4f6bd7 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -22,24 +22,22 @@ class AddressValue; class RegisterValue; class MemoryValue; class Event; - -enum SyncType { - SyncForCall, - SyncForJump -}; +class Stack; class Value { public: virtual ~Value() { } - virtual OperandType type() = 0; + virtual OperandType type(Context*) = 0; - virtual bool equals(Value*) { return false; } + virtual bool equals(Context*, Value*) { return false; } - virtual void preserve(Context*, MyOperand*) { } - virtual void acquire(Context*, MyOperand*) { } + virtual void preserve(Context*, Stack*, MyOperand*) { } + virtual void acquire(Context*, Stack*, MyOperand*) { } virtual void release(Context*, MyOperand*) { } + virtual Stack* stackPosition(Context*) { return 0; } + virtual RegisterValue* toRegister(Context*) = 0; virtual void asAssemblerOperand(Context*, @@ -279,7 +277,7 @@ class ConstantValue: public Value { public: ConstantValue(Promise* value): value(value) { } - virtual OperandType type() { return Constant; } + virtual OperandType type(Context*) { return Constant; } virtual RegisterValue* toRegister(Context* c); @@ -311,7 +309,7 @@ class AddressValue: public Value { public: AddressValue(Promise* address): address(address) { } - virtual OperandType type() { return Address; } + virtual OperandType type(Context*) { return Address; } virtual RegisterValue* toRegister(Context* c); @@ -332,31 +330,31 @@ address(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address); } -void preserve(Context* c, int reg, MyOperand* a); +void preserve(Context*, Stack*, int, MyOperand*); class RegisterValue: public Value { public: RegisterValue(int low, int high): register_(low, high) { } - virtual OperandType type() { return Register; } + virtual OperandType type(Context*) { return Register; } - virtual bool equals(Value* o) { + virtual bool equals(Context* c, Value* o) { return this == o or - (o->type() == Register + (o->type(c) == Register and static_cast(o)->register_.low == register_.low and static_cast(o)->register_.high == register_.high); } - virtual void preserve(Context* c, MyOperand* a) { - ::preserve(c, register_.low, a); - if (register_.high >= 0) ::preserve(c, register_.high, a); + virtual void preserve(Context* c, Stack* s, MyOperand* a) { + ::preserve(c, s, register_.low, a); + if (register_.high >= 0) ::preserve(c, s, register_.high, a); } - virtual void acquire(Context* c, MyOperand* a) { + virtual void acquire(Context* c, Stack* s, MyOperand* a) { if (a != c->registers[register_.low].operand) { fprintf(stderr, "%p acquire %d\n", a, register_.low); - preserve(c, a); + preserve(c, s, a); c->registers[register_.low].operand = a; if (register_.high >= 0) c->registers[register_.high].operand = a; } @@ -400,11 +398,11 @@ class MemoryValue: public Value { value(base, offset, index, scale, traceHandler) { } - virtual OperandType type() { return Memory; } + virtual OperandType type(Context*) { return Memory; } - virtual bool equals(Value* o) { + virtual bool equals(Context* c, Value* o) { return this == o or - (o->type() == Memory + (o->type(c) == Memory and static_cast(o)->value.base == value.base and static_cast(o)->value.offset == value.offset and static_cast(o)->value.index == value.index @@ -480,6 +478,34 @@ memory(Context* c, MyOperand* base, int offset, MyOperand* index, AbstractMemoryValue(base, offset, index, scale, traceHandler); } +class StackValue: public Value { + public: + StackValue(Stack* stack): stack(stack) { } + + virtual OperandType type(Context* c) { abort(c); } + + virtual RegisterValue* toRegister(Context* c) { + abort(c); + } + + virtual Stack* stackPosition(Context*) { return stack; } + + virtual void asAssemblerOperand(Context* c, + OperandType*, + Assembler::Operand**) + { + abort(c); + } + + Stack* stack; +}; + +StackValue* +stackValue(Context* c, Stack* stack) +{ + return new (c->zone->allocate(sizeof(StackValue))) StackValue(stack); +} + class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0) { @@ -499,7 +525,6 @@ class Event { 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; @@ -512,11 +537,10 @@ class ArgumentEvent: public Event { ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): Event(c), size(size), a(a), index(index) { - assert(c, a->event == 0); a->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c, MyOperand* v UNUSED) { assert(c, v == a); if (index < c->assembler->argumentRegisterCount()) { @@ -528,21 +552,15 @@ class ArgumentEvent: public Event { } } - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == a); - a = new_; - new_->target = old->target; - } - virtual void compile(Context* c) { fprintf(stderr, "ArgumentEvent.compile\n"); if (a->target == 0) a->target = target(c, a); a->value->release(c, a); - a->target->preserve(c, a); + a->target->preserve(c, stack, a); - if (not a->target->equals(a->value)) { + if (not a->target->equals(c, a->value)) { apply(c, Move, size, a->value, a->target); } } @@ -565,23 +583,16 @@ class ReturnEvent: public Event { Event(c), size(size), a(a) { if (a) { - assert(c, a->event == 0); a->event = this; } } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c, MyOperand* v UNUSED) { 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) { fprintf(stderr, "ReturnEvent.compile\n"); @@ -590,7 +601,7 @@ class ReturnEvent: public Event { a->value->release(c, a); - if (not a->target->equals(a->value)) { + if (not a->target->equals(c, a->value)) { apply(c, Move, size, a->value, a->target); } } @@ -613,149 +624,81 @@ appendReturn(Context* c, unsigned size, MyOperand* value) new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } -class SyncForCallEvent: public Event { - public: - SyncForCallEvent(Context* c, unsigned size, unsigned index, MyOperand* src, - MyOperand* dst): - Event(c), size(size), index(index), src(src), dst(dst) - { - assert(c, src->event == 0); - src->event = this; - } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == src); - - return memory(c, c->assembler->base(), - -(index + ((c->stackOffset + 1) * 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) { - fprintf(stderr, "SyncForCallEvent.compile\n"); - - if (src->target == 0) src->target = target(c, src); - - src->value->release(c, src); - - if (not src->target->equals(src->value)) { - if (src->value->type() == Memory and src->target->type() == Memory) { - RegisterValue* tmp = freeRegister(c, size); - tmp->preserve(c, 0); - apply(c, Move, size, src->value, tmp); - src->value = tmp; - } - - apply(c, Move, size, src->value, src->target); - } - - dst->value = src->target; - } - - unsigned size; - unsigned index; - MyOperand* src; - MyOperand* dst; -}; - void -appendSyncForCall(Context* c, unsigned size, unsigned index, MyOperand* src, - MyOperand* dst) +syncStack(Context* c, Stack* start, unsigned count) { - new (c->zone->allocate(sizeof(SyncForCallEvent))) - SyncForCallEvent(c, size, index, src, dst); + Stack* segment[count]; + unsigned index = count; + for (Stack* s = start; s; s = s->next) { + segment[--index] = s; + } + + for (unsigned i = 0; i < count; ++i) { + Stack* s = segment[i]; + s->operand->value->release(c, s->operand); + apply(c, Push, s->size, s->operand->value); + s->operand->value = stackValue(c, s); + } } -class SyncForJumpEvent: public Event { +class SyncStackEvent: public Event { public: - SyncForJumpEvent(Context* c, unsigned size, unsigned index, MyOperand* src, - MyOperand* dst): - Event(c), size(size), index(index), src(src), dst(dst) + SyncStackEvent(Context* c): + Event(c) { - assert(c, src->event == 0); - src->event = this; - } - - SyncForJumpEvent(Context* c, Event* next, unsigned size, unsigned index, - MyOperand* src, MyOperand* dst): - Event(next), size(size), index(index), src(src), dst(dst) - { - assert(c, src->event == 0); - src->event = this; - } - - virtual Value* target(Context* c, MyOperand* v) { - assert(c, v == src); - - if (BytesPerWord == 4 and size == 8) { - return register_ - (c, c->assembler->stackSyncRegister(index / BytesPerWord), - c->assembler->stackSyncRegister((index / BytesPerWord) + 1)); - } else { - return register_ - (c, c->assembler->stackSyncRegister(index / BytesPerWord)); + for (Stack* s = stack; s; s = s->next) { + s->operand->event = this; } } - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == src); - src = new_; - src->target = old->target; + SyncStackEvent(Context* c, Event* next): + Event(c) + { + stack = next->stack; + for (Stack* s = stack; s; s = s->next) { + s->operand->event = this; + } + } + + virtual Value* target(Context*, MyOperand*) { + return 0; } virtual void compile(Context* c) { - fprintf(stderr, "SyncForJumpEvent.compile\n"); + fprintf(stderr, "SyncEvent.compile\n"); - if (src->target == 0) src->target = target(c, src); - - src->value->release(c, src); - src->target->acquire(c, dst); - - if (not src->target->equals(src->value)) { - apply(c, Move, size, src->value, src->target); + unsigned count = 0; + for (Stack* s = stack; + s and s->operand->value->stackPosition(c) == 0; + s = s->next) + { + ++ count; } - dst->value = src->target; + syncStack(c, stack, count); } - - unsigned size; - unsigned index; - MyOperand* src; - MyOperand* dst; }; void -appendSyncForJump(Context* c, unsigned size, unsigned index, MyOperand* src, - MyOperand* dst) -{ - new (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent(c, size, index, src, dst); +appendSyncStack(Context* c) { + new (c->zone->allocate(sizeof(SyncStackEvent))) SyncStackEvent(c); } class CallEvent: public Event { public: CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, MyOperand* result, - unsigned stackOffset): + TraceHandler* traceHandler, MyOperand* result): Event(c), address(address), indirection(indirection), flags(flags), traceHandler(traceHandler), - result(result), - stackOffset(stackOffset) + result(result) { - assert(c, address->event == 0); address->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c, MyOperand* v UNUSED) { assert(c, v == address); if (indirection) { @@ -765,11 +708,6 @@ class CallEvent: public Event { } } - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == address); - address = new_; - } - virtual void compile(Context* c) { fprintf(stderr, "CallEvent.compile\n"); @@ -782,21 +720,13 @@ class CallEvent: public Event { if (result->event) { result->value = register_ (c, c->assembler->returnLow(), c->assembler->returnHigh()); - result->value->acquire(c, result); - } - - if (stackOffset != c->stackOffset) { - apply(c, LoadAddress, BytesPerWord, - memory(c, c->assembler->base(), - -((stackOffset + 1) * BytesPerWord), - NoRegister, 0, 0), - register_(c, c->assembler->stack())); + result->value->acquire(c, stack, result); } UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); if (indirection) { - if (not address->target->equals(address->value)) { + if (not address->target->equals(c, address->value)) { apply(c, Move, BytesPerWord, address->value, address->target); } apply(c, type, BytesPerWord, @@ -817,17 +747,14 @@ class CallEvent: public Event { unsigned flags; TraceHandler* traceHandler; MyOperand* result; - unsigned stackOffset; }; void appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, MyOperand* result, - unsigned stackOffset) + TraceHandler* traceHandler, MyOperand* result) { new (c->zone->allocate(sizeof(CallEvent))) - CallEvent(c, address, indirection, flags, traceHandler, result, - stackOffset); + CallEvent(c, address, indirection, flags, traceHandler, result); } int @@ -866,11 +793,10 @@ class MoveEvent: public Event { MyOperand* dst): Event(c), type(type), size(size), src(src), dst(dst) { - assert(c, src->event == 0); src->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c, MyOperand* v UNUSED) { assert(c, v == src); if (dst->value) { @@ -882,12 +808,6 @@ class MoveEvent: public Event { } } - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == src); - src = new_; - src->target = old->target; - } - virtual void compile(Context* c) { fprintf(stderr, "MoveEvent.compile\n"); @@ -895,16 +815,22 @@ class MoveEvent: public Event { if (src->target == 0) { src->target = freeRegister(c, size); - } else if (src->value->type() == Memory and src->target->type() == Memory) + } else if (type == Move + and size == BytesPerWord + and src->target->equals(c, src->value)) + { + return; + } else if (src->value->type(c) == Memory + and src->target->type(c) == Memory) { RegisterValue* tmp = freeRegister(c, size); - tmp->preserve(c, 0); + tmp->preserve(c, stack, 0); apply(c, Move, size, src->value, tmp); src->value = tmp; } src->value->release(c, src); - src->target->acquire(c, dst); + src->target->acquire(c, stack, dst); apply(c, type, size, src->value, src->target); @@ -935,10 +861,6 @@ class DupEvent: public Event { abort(c); } - virtual void replace(Context* c, MyOperand*, MyOperand*) { - abort(c); - } - virtual void compile(Context* c) { fprintf(stderr, "DupEvent.compile\n"); @@ -948,17 +870,18 @@ class DupEvent: public Event { if (target == 0) { if (dst->event) { target = dst->event->target(c, dst); - } else { + } + if (target == 0) { target = freeRegister(c, size); } - } else if (value->type() == Memory and target->type() == Memory) { + } else if (value->type(c) == Memory and target->type(c) == Memory) { RegisterValue* tmp = freeRegister(c, size); - tmp->preserve(c, 0); + tmp->preserve(c, stack, 0); apply(c, Move, size, value, tmp); value = tmp; } - target->acquire(c, dst); + target->acquire(c, stack, dst); apply(c, Move, size, value, target); @@ -976,34 +899,62 @@ appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst) new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst); } +class PopEvent: public Event { + public: + PopEvent(Context* c): + Event(c) + { } + + virtual Value* target(Context* c, MyOperand*) { + abort(c); + } + + virtual void compile(Context* c) { + fprintf(stderr, "PopEvent.compile\n"); + + MyOperand* dst = stack->operand; + if (dst->value->stackPosition(c)) { + Value* target = dst->target; + + if (target == 0) { + if (dst->event) { + target = dst->event->target(c, dst); + } + if (target == 0) { + target = freeRegister(c, BytesPerWord * stack->size); + } + } + + target->acquire(c, 0, dst); + + apply(c, Pop, BytesPerWord * stack->size, target); + + dst->value = target; + } + } +}; + +void +appendPop(Context* c) +{ + new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c); +} + class CompareEvent: public Event { public: CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): Event(c), size(size), a(a), b(b) { - assert(c, a->event == 0); a->event = this; - assert(c, b->event == 0); b->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { 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) { fprintf(stderr, "CompareEvent.compile\n"); @@ -1029,22 +980,15 @@ class BranchEvent: public Event { BranchEvent(Context* c, UnaryOperation type, MyOperand* address): Event(c), type(type), address(address) { - assert(c, address->event == 0); address->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { assert(c, v == address); return 0; } - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == address); - address = new_; - address->target = old->target; - } - virtual void compile(Context* c) { fprintf(stderr, "BranchEvent.compile\n"); @@ -1069,21 +1013,15 @@ class JumpEvent: public Event { Event(c), address(address) { - assert(c, address->event == 0); address->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { 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) { fprintf(stderr, "JumpEvent.compile\n"); @@ -1093,9 +1031,6 @@ class JumpEvent: public Event { } MyOperand* address; - unsigned stackOffset; - bool alignCall; - TraceHandler* traceHandler; }; void @@ -1110,9 +1045,7 @@ class CombineEvent: public Event { MyOperand* b, MyOperand* result): Event(c), type(type), size(size), a(a), b(b), result(result) { - assert(c, a->event == 0); a->event = this; - assert(c, b->event == 0); b->event = this; } @@ -1133,7 +1066,7 @@ class CombineEvent: public Event { if (br.low == NoRegister) { if (result->event) { Value* v = result->event->target(c, result); - if (v->type() == Register) { + if (v->type(c) == Register) { return v; } else { return 0; @@ -1147,17 +1080,6 @@ class CombineEvent: public Event { } } - 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) { fprintf(stderr, "CombineEvent.compile\n"); @@ -1166,12 +1088,12 @@ class CombineEvent: public Event { a->value->release(c, a); b->value->release(c, b); - b->value->acquire(c, result); + b->value->acquire(c, stack, result); - if (a->target and not a->target->equals(a->value)) { + if (a->target and not a->target->equals(c, a->value)) { apply(c, Move, size, a->value, a->target); } - if (b->target and not b->target->equals(b->value)) { + if (b->target and not b->target->equals(c, b->value)) { apply(c, Move, size, b->value, b->target); } @@ -1201,11 +1123,10 @@ class TranslateEvent: public Event { MyOperand* result): Event(c), type(type), size(size), a(a), result(result) { - assert(c, a->event == 0); a->event = this; } - virtual Value* target(Context* c, MyOperand* v) { + virtual Value* target(Context* c, MyOperand* v UNUSED) { assert(c, v == a); Assembler::Register r(NoRegister); @@ -1218,20 +1139,14 @@ class TranslateEvent: public Event { } } - virtual void replace(Context* c, MyOperand* old, MyOperand* new_) { - assert(c, old == a); - a = new_; - a->target = old->target; - } - virtual void compile(Context* c) { fprintf(stderr, "TranslateEvent.compile\n"); if (a->target == 0) a->target = target(c, a); - result->value->acquire(c, result); + result->value->acquire(c, stack, result); - if (a->target and not a->target->equals(a->value)) { + if (a->target and not a->target->equals(c, a->value)) { apply(c, Move, size, a->value, a->target); } apply(c, type, size, a->value); @@ -1270,21 +1185,29 @@ AddressValue::toRegister(Context* c) } void -preserve(Context* c, int reg, MyOperand* a) +preserve(Context* c, Stack* stack, int reg, MyOperand* a) { MyOperand* b = c->registers[reg].operand; if (b and a != b) { fprintf(stderr, "%p preserve %d for %p\n", a, reg, b); - abort(c); -// MemoryValue* dst = memory -// (c, c->assembler->base(), (b->index + c->stackOffset) * BytesPerWord, -// -1, 0, 0); + unsigned count = 0; + Stack* start = 0; + for (Stack* s = stack; + s and s->operand->value->stackPosition(c) == 0; + s = s->next) + { + if (s->operand == a) { + start = s; + } + if (start) { + ++ count; + } + } -// apply(c, Move, b->size, b->value, dst); + assert(c, start); -// b->value = dst; -// c->registers[reg].operand = 0; + syncStack(c, start, count); } } @@ -1326,7 +1249,6 @@ void push(Context* c, unsigned size, MyOperand* o) { assert(c, ceiling(size, BytesPerWord)); - assert(c, o->event == 0); c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); } @@ -1337,34 +1259,12 @@ pop(Context* c, unsigned size UNUSED) Stack* s = c->state->stack; assert(c, ceiling(size, BytesPerWord) == s->size); + appendPop(c); + c->state->stack = s->next; return s->operand; } -void -syncStack(Context* c, SyncType type) -{ - Stack* newStack = 0; - for (Stack* s = c->state->stack; s; s = s->next) { - MyOperand* old = s->operand; - MyOperand* new_ = operand(c); - Stack* ns = stack(c, new_, s->size, s->index, 0); - if (newStack) { - newStack->next = ns; - } else { - newStack = c->state->stack = ns; - } - - if (type == SyncForCall) { - appendSyncForCall - (c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_); - } else { - appendSyncForJump - (c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_); - } - } -} - void updateJunctions(Context* c) { @@ -1374,20 +1274,10 @@ updateJunctions(Context* c) if (i->predecessor >= 0) { LogicalInstruction* p = c->logicalCode + i->predecessor; - for (Stack* s = c->state->stack; s; s = s->next) { - MyOperand* old = s->operand; - MyOperand* new_ = operand(c); + Event* e = new (c->zone->allocate(sizeof(SyncStackEvent))) + SyncStackEvent(c, p->lastEvent->next); - if (old->event) { - old->event->replace(c, old, new_); - } - - p->lastEvent = p->lastEvent->next = new - (c->zone->allocate(sizeof(SyncForJumpEvent))) - SyncForJumpEvent - (c, p->lastEvent->next, s->size * BytesPerWord, - s->index * BytesPerWord, old, new_); - } + p->lastEvent = p->lastEvent->next = e; } } } @@ -1548,7 +1438,7 @@ class MyCompiler: public Compiler { } } - virtual Operand* peek(unsigned size, unsigned index) { + virtual Operand* peek(unsigned size UNUSED, unsigned index) { Stack* s = c.state->stack; for (unsigned i = index; i > 0;) { s = s->next; @@ -1583,16 +1473,11 @@ class MyCompiler: public Compiler { va_end(a); - syncStack(&c, SyncForCall); - - unsigned stackOffset = c.stackOffset - + (c.state->stack ? c.state->stack->index + c.state->stack->size : 0) - + (footprint > c.assembler->argumentRegisterCount() ? - footprint - c.assembler->argumentRegisterCount() : 0); + appendSyncStack(&c); MyOperand* result = operand(&c); appendCall(&c, static_cast(address), indirection, flags, - traceHandler, result, stackOffset); + traceHandler, result); return result; } @@ -1635,43 +1520,43 @@ class MyCompiler: public Compiler { } virtual void jl(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendBranch(&c, JumpIfLess, static_cast(address)); } virtual void jg(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendBranch(&c, JumpIfGreater, static_cast(address)); } virtual void jle(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); } virtual void jge(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); } virtual void je(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendBranch(&c, JumpIfEqual, static_cast(address)); } virtual void jne(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendBranch(&c, JumpIfNotEqual, static_cast(address)); } virtual void jmp(Operand* address) { - syncStack(&c, SyncForJump); + appendSyncStack(&c); appendJump(&c, static_cast(address)); } diff --git a/src/x86.cpp b/src/x86.cpp index 9815eb315a..fbc792348d 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -356,6 +356,21 @@ popR(Context* c, unsigned size, Assembler::Register* a) } } +void +popM(Context* c, unsigned size, Assembler::Memory* a) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); + + popM(c, 4, a); + popM(c, 4, &ah); + } else { + assert(c, BytesPerWord == 4 or size == 8); + + encode(c, 0x8f, 0, a, false); + } +} + void leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) { @@ -492,8 +507,8 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) } void -addCR(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b) +addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); // todo @@ -515,7 +530,7 @@ addCR(Context* c, unsigned size, Assembler::Constant* a, } void -addRR(Context* c, unsigned size, Assembler::Register* a, +addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); // todo @@ -526,7 +541,7 @@ addRR(Context* c, unsigned size, Assembler::Register* a, } void -addRM(Context* c, unsigned size, Assembler::Register* a, +addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Memory* b) { assert(c, BytesPerWord == 8 or size == 4); @@ -545,6 +560,7 @@ populateTables() UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); + UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); From b7f2f95c39ca1cb50ca03c36fea8a00ddf255fda Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 9 Mar 2008 15:28:23 -0600 Subject: [PATCH 008/121] uncomment MAKEFLAGS = -s --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index e4c489b2a9..92b9595660 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s name = avian version = 0.0.1 From 9a0143594a2d14662afc9a7a525a95425d127148 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 10 Mar 2008 07:27:42 -0600 Subject: [PATCH 009/121] clarify quick start in readme.txt --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 608e7cc42b..7af080e1df 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Quick Start ----------- on Linux: - $ export JAVA_HOME=/usr/local/java # or wherever you have Java installed + $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed $ make $ build/linux-i386-compile-fast/avian -cp build/test Hello From 11dea0ad8ecaffaa8bced7ad941a25321ca04330 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 10 Mar 2008 07:28:21 -0600 Subject: [PATCH 010/121] don't bother calling methods which are known do nothing --- src/compile.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 3fde1abb61..c0b3c11c7b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1436,6 +1436,13 @@ resultSize(MyThread* t, unsigned code) } } +bool +emptyMethod(MyThread* t, object method) +{ + object code = methodCode(t, method); + return (codeLength(t, code) == 1 and codeBody(t, code, 0) == return_); +} + void compileDirectInvoke(MyThread* t, Frame* frame, object target) { @@ -1443,15 +1450,19 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) unsigned rSize = resultSize(t, methodReturnCode(t, target)); - Compiler::Operand* result = c->call - (c->constant - (reinterpret_cast - (&singletonBody(t, methodCompiled(t, target), 0))), - 0, - Compiler::Aligned, - frame->trace(target, false), - rSize, - 0); + Compiler::Operand* result = 0; + + if (not emptyMethod(t, target)) { + result = c->call + (c->constant + (reinterpret_cast + (&singletonBody(t, methodCompiled(t, target), 0))), + 0, + Compiler::Aligned, + frame->trace(target, false), + rSize, + 0); + } c->popped(methodParameterFootprint(t, target)); From 0fe748c3a15dcab54125a4ac56a0e73c66125106 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 10 Mar 2008 07:29:42 -0600 Subject: [PATCH 011/121] avoid unecessary mov instructions --- src/compiler.cpp | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 010b4f6bd7..ca05d57c9b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -641,6 +641,20 @@ syncStack(Context* c, Stack* start, unsigned count) } } +void +syncStack(Context* c, Stack* start) +{ + unsigned count = 0; + for (Stack* s = start; + s and s->operand->value->stackPosition(c) == 0; + s = s->next) + { + ++ count; + } + + syncStack(c, start, count); +} + class SyncStackEvent: public Event { public: SyncStackEvent(Context* c): @@ -667,15 +681,7 @@ class SyncStackEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "SyncEvent.compile\n"); - unsigned count = 0; - for (Stack* s = stack; - s and s->operand->value->stackPosition(c) == 0; - s = s->next) - { - ++ count; - } - - syncStack(c, stack, count); + syncStack(c, stack); } }; @@ -814,11 +820,20 @@ class MoveEvent: public Event { if (src->target == 0) src->target = target(c, src); if (src->target == 0) { - src->target = freeRegister(c, size); + if (type == Move + and size == BytesPerWord + and dst->event == next) + { + dst->value = src->value; + return; + } else { + src->target = freeRegister(c, size); + } } else if (type == Move and size == BytesPerWord and src->target->equals(c, src->value)) { + dst->value = src->value; return; } else if (src->value->type(c) == Memory and src->target->type(c) == Memory) @@ -870,6 +885,10 @@ class DupEvent: public Event { if (target == 0) { if (dst->event) { target = dst->event->target(c, dst); + if (target == 0 and dst->event == next) { + dst->value = src->value; + return; + } } if (target == 0) { target = freeRegister(c, size); From 9e2e614a1530feb7ef711740b835c3f115e76567 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 10 Mar 2008 16:37:21 -0600 Subject: [PATCH 012/121] various fixes to get invokevirtual working --- src/compile.cpp | 7 +++--- src/compiler.cpp | 20 +++++++++++---- src/x86.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ test/Misc.java | 2 +- 4 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index c0b3c11c7b..3063403796 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1439,8 +1439,9 @@ resultSize(MyThread* t, unsigned code) bool emptyMethod(MyThread* t, object method) { - object code = methodCode(t, method); - return (codeLength(t, code) == 1 and codeBody(t, code, 0) == return_); + return ((methodFlags(t, method) & ACC_NATIVE) == 0) + and (codeLength(t, methodCode(t, method)) == 1) + and (codeBody(t, methodCode(t, method), 0) == return_); } void @@ -2475,7 +2476,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1), 0, 0, - frame->trace(0, true), + frame->trace(target, true), rSize, 0); diff --git a/src/compiler.cpp b/src/compiler.cpp index ca05d57c9b..cb7c259779 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -485,7 +485,10 @@ class StackValue: public Value { virtual OperandType type(Context* c) { abort(c); } virtual RegisterValue* toRegister(Context* c) { - abort(c); + return MemoryValue + (c->assembler->base(), (c->stackOffset + stack->index) * BytesPerWord, + NoRegister, 0, 0) + .toRegister(c); } virtual Stack* stackPosition(Context*) { return stack; } @@ -636,7 +639,7 @@ syncStack(Context* c, Stack* start, unsigned count) for (unsigned i = 0; i < count; ++i) { Stack* s = segment[i]; s->operand->value->release(c, s->operand); - apply(c, Push, s->size, s->operand->value); + apply(c, Push, s->size * BytesPerWord, s->operand->value); s->operand->value = stackValue(c, s); } } @@ -1105,17 +1108,24 @@ class CombineEvent: public Event { if (a->target == 0) a->target = target(c, a); if (b->target == 0) b->target = target(c, b); - a->value->release(c, a); - b->value->release(c, b); - b->value->acquire(c, stack, result); + if (b->target == 0) { + b->target = freeRegister(c, BytesPerWord); + } if (a->target and not a->target->equals(c, a->value)) { + a->value->release(c, a); apply(c, Move, size, a->value, a->target); + a->value = a->target; } + if (b->target and not b->target->equals(c, b->value)) { + b->value->release(c, b); apply(c, Move, size, b->value, b->target); + b->value = b->target; } + b->value->acquire(c, stack, result); + apply(c, type, size, a->value, b->value); result->value = b->value; diff --git a/src/x86.cpp b/src/x86.cpp index fbc792348d..68ea6d4a55 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -314,6 +314,14 @@ callR(Context* c, unsigned size UNUSED, Assembler::Register* a) c->code.append(0xd0 | a->low); } +void +callM(Context* c, unsigned size UNUSED, Assembler::Memory* a) +{ + assert(c, size == BytesPerWord); + + encode(c, 0xff, 2, a, false); +} + void jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) { @@ -336,6 +344,21 @@ pushR(Context* c, unsigned size, Assembler::Register* a) } } +void +pushM(Context* c, unsigned size, Assembler::Memory* a) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); + + pushM(c, 4, &ah); + pushM(c, 4, a); + } else { + assert(c, BytesPerWord == 4 or size == 8); + + encode(c, 0xff, 6, a, false); + } +} + void move4To8RR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b); @@ -549,6 +572,42 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, encode(c, 0x01, a->low, b, true); } +void +andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + rex(c); + if (isInt8(a->value->value())) { + c->code.append(0x83); + c->code.append(0xe0 | b->low); + c->code.append(a->value->value()); + } else { + assert(c, isInt32(a->value->value())); + + c->code.append(0x81); + c->code.append(0xe0 | b->low); + c->code.append(a->value->value()); + } +} + +void +andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 4, b, true); + if (isInt8(a->value->value())) { + c->code.append(a->value->value()); + } else if (isInt32(a->value->value())) { + c->code.append4(a->value->value()); + } else { + abort(c); + } +} + void populateTables() { @@ -557,8 +616,10 @@ populateTables() UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); + UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); + UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); @@ -574,6 +635,8 @@ populateTables() BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); + BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); } class MyAssembler: public Assembler { diff --git a/test/Misc.java b/test/Misc.java index 76d62c04d6..613ba102f7 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -91,7 +91,7 @@ public class Misc { // int c = a + b; Misc m = new Misc(); -// m.toString(); + m.toString(); // String s = "hello"; // m.foo(s); From c5b8b83cc75f445a69c65f607d67206458008544 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 11 Mar 2008 10:40:28 -0600 Subject: [PATCH 013/121] clean up code for optimizing stack operations --- src/compiler.cpp | 333 ++++++++++++++++++++++++++--------------------- 1 file changed, 184 insertions(+), 149 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index cb7c259779..094623ddd4 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -21,7 +21,9 @@ class ConstantValue; class AddressValue; class RegisterValue; class MemoryValue; +class StackValue; class Event; +class PushEvent; class Stack; class Value { @@ -36,8 +38,6 @@ class Value { virtual void acquire(Context*, Stack*, MyOperand*) { } virtual void release(Context*, MyOperand*) { } - virtual Stack* stackPosition(Context*) { return 0; } - virtual RegisterValue* toRegister(Context*) = 0; virtual void asAssemblerOperand(Context*, @@ -48,12 +48,14 @@ class Value { class MyOperand: public Compiler::Operand { public: MyOperand(Value* value): - event(0), value(value), target(0) + event(0), value(value), target(0), push(0), pushedValue(0) { } Event* event; Value* value; Value* target; + PushEvent* push; + StackValue* pushedValue; }; class Stack { @@ -209,7 +211,7 @@ class PoolPromise: public Promise { virtual int64_t value() { if (resolved()) { return reinterpret_cast - (c->machineCode + pad(c->assembler->length()) + key); + (c->machineCode + pad(c->assembler->length()) + (key * BytesPerWord)); } abort(c); @@ -356,7 +358,9 @@ class RegisterValue: public Value { preserve(c, s, a); c->registers[register_.low].operand = a; - if (register_.high >= 0) c->registers[register_.high].operand = a; + if (register_.high >= 0) { + c->registers[register_.high].operand = a; + } } } @@ -491,8 +495,6 @@ class StackValue: public Value { .toRegister(c); } - virtual Stack* stackPosition(Context*) { return stack; } - virtual void asAssemblerOperand(Context* c, OperandType*, Assembler::Operand**) @@ -529,6 +531,7 @@ class Event { virtual Value* target(Context* c, MyOperand* value) = 0; virtual void compile(Context* c) = 0; + virtual bool isCritical(Context*) { return false; } Event* next; Stack* stack; @@ -540,6 +543,7 @@ class ArgumentEvent: public Event { ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): Event(c), size(size), a(a), index(index) { + assert(c, a->event == 0); a->event = this; } @@ -586,6 +590,7 @@ class ReturnEvent: public Event { Event(c), size(size), a(a) { if (a) { + assert(c, a->event == 0); a->event = this; } } @@ -627,72 +632,6 @@ appendReturn(Context* c, unsigned size, MyOperand* value) new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } -void -syncStack(Context* c, Stack* start, unsigned count) -{ - Stack* segment[count]; - unsigned index = count; - for (Stack* s = start; s; s = s->next) { - segment[--index] = s; - } - - for (unsigned i = 0; i < count; ++i) { - Stack* s = segment[i]; - s->operand->value->release(c, s->operand); - apply(c, Push, s->size * BytesPerWord, s->operand->value); - s->operand->value = stackValue(c, s); - } -} - -void -syncStack(Context* c, Stack* start) -{ - unsigned count = 0; - for (Stack* s = start; - s and s->operand->value->stackPosition(c) == 0; - s = s->next) - { - ++ count; - } - - syncStack(c, start, count); -} - -class SyncStackEvent: public Event { - public: - SyncStackEvent(Context* c): - Event(c) - { - for (Stack* s = stack; s; s = s->next) { - s->operand->event = this; - } - } - - SyncStackEvent(Context* c, Event* next): - Event(c) - { - stack = next->stack; - for (Stack* s = stack; s; s = s->next) { - s->operand->event = this; - } - } - - virtual Value* target(Context*, MyOperand*) { - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "SyncEvent.compile\n"); - - syncStack(c, stack); - } -}; - -void -appendSyncStack(Context* c) { - new (c->zone->allocate(sizeof(SyncStackEvent))) SyncStackEvent(c); -} - class CallEvent: public Event { public: CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags, @@ -704,6 +643,7 @@ class CallEvent: public Event { traceHandler(traceHandler), result(result) { + assert(c, address->event == 0); address->event = this; } @@ -796,12 +736,126 @@ freeRegister(Context* c, unsigned size) } } +void +syncStack(Context* c, Stack* start, unsigned count) +{ + Stack* segment[count]; + unsigned index = count; + for (Stack* s = start; s and index; s = s->next) { + segment[--index] = s; + } + + for (unsigned i = 0; i < count; ++i) { + Stack* s = segment[i]; + s->operand->value->release(c, s->operand); + apply(c, Push, s->size * BytesPerWord, s->operand->value); + s->operand->pushedValue = stackValue(c, s); + } +} + +void +syncStack(Context* c, Stack* start) +{ + unsigned count = 0; + for (Stack* s = start; s and s->operand->pushedValue == 0; s = s->next) { + ++ count; + } + + syncStack(c, start, count); +} + +class PushEvent: public Event { + public: + PushEvent(Context* c): + Event(c), active(false) + { + assert(c, stack->operand->push == 0); + stack->operand->push = this; + } + + virtual Value* target(Context*, MyOperand*) { + return 0; + } + + virtual void compile(Context* c) { + fprintf(stderr, "PushEvent.compile\n"); + + if (active) { + fprintf(stderr, "PushEvent.compile: active\n"); + syncStack(c, stack); + } + } + + void markStack() { + active = true; + } + + bool active; +}; + +void +appendPush(Context* c) +{ + new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); +} + +class PopEvent: public Event { + public: + PopEvent(Context* c): + Event(c) + { } + + virtual Value* target(Context* c, MyOperand*) { + abort(c); + } + + virtual void compile(Context* c) { + fprintf(stderr, "PopEvent.compile\n"); + + MyOperand* dst = stack->operand; + if (dst->event and dst->pushedValue) { + Value* target = dst->target; + + if (target == 0) { + if (dst->event) { + target = dst->event->target(c, dst); + } + if (target == 0) { + target = freeRegister(c, BytesPerWord * stack->size); + } + } + + target->acquire(c, 0, dst); + + apply(c, Pop, BytesPerWord * stack->size, target); + + dst->value = target; + } + } +}; + +void +appendPop(Context* c) +{ + new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c); +} + +bool +safeToSkipMove(Context* c, MyOperand* a, Event* e) +{ + for (; a->push and a->push != e; e = e->next) { + if (e->isCritical(c)) return false; + } + return true; +} + class MoveEvent: public Event { public: MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src, MyOperand* dst): Event(c), type(type), size(size), src(src), dst(dst) { + assert(c, src->event == 0); src->event = this; } @@ -825,7 +879,7 @@ class MoveEvent: public Event { if (src->target == 0) { if (type == Move and size == BytesPerWord - and dst->event == next) + and safeToSkipMove(c, dst, next)) { dst->value = src->value; return; @@ -838,7 +892,8 @@ class MoveEvent: public Event { { dst->value = src->value; return; - } else if (src->value->type(c) == Memory + } else if ((src->value->type(c) == Address + or src->value->type(c) == Memory) and src->target->type(c) == Memory) { RegisterValue* tmp = freeRegister(c, size); @@ -855,6 +910,12 @@ class MoveEvent: public Event { dst->value = src->target; } + virtual bool isCritical(Context* c) { + if (src->target == 0) src->target = target(c, src); + + return src->target != 0; + } + BinaryOperation type; unsigned size; MyOperand* src; @@ -883,24 +944,20 @@ class DupEvent: public Event { fprintf(stderr, "DupEvent.compile\n"); Value* value = src->value; - Value* target = dst->value; + assert(c, dst->value == 0); + Value* target = 0; + + if (safeToSkipMove(c, dst, next)) { + dst->value = src->value; + return; + } + + if (dst->event) { + target = dst->event->target(c, dst); + } if (target == 0) { - if (dst->event) { - target = dst->event->target(c, dst); - if (target == 0 and dst->event == next) { - dst->value = src->value; - return; - } - } - if (target == 0) { - target = freeRegister(c, size); - } - } else if (value->type(c) == Memory and target->type(c) == Memory) { - RegisterValue* tmp = freeRegister(c, size); - tmp->preserve(c, stack, 0); - apply(c, Move, size, value, tmp); - value = tmp; + target = freeRegister(c, size); } target->acquire(c, stack, dst); @@ -921,53 +978,14 @@ appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst) new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst); } -class PopEvent: public Event { - public: - PopEvent(Context* c): - Event(c) - { } - - virtual Value* target(Context* c, MyOperand*) { - abort(c); - } - - virtual void compile(Context* c) { - fprintf(stderr, "PopEvent.compile\n"); - - MyOperand* dst = stack->operand; - if (dst->value->stackPosition(c)) { - Value* target = dst->target; - - if (target == 0) { - if (dst->event) { - target = dst->event->target(c, dst); - } - if (target == 0) { - target = freeRegister(c, BytesPerWord * stack->size); - } - } - - target->acquire(c, 0, dst); - - apply(c, Pop, BytesPerWord * stack->size, target); - - dst->value = target; - } - } -}; - -void -appendPop(Context* c) -{ - new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c); -} - class CompareEvent: public Event { public: CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): Event(c), size(size), a(a), b(b) { + assert(c, a->event == 0); a->event = this; + assert(c, b->event == 0); b->event = this; } @@ -1002,6 +1020,7 @@ class BranchEvent: public Event { BranchEvent(Context* c, UnaryOperation type, MyOperand* address): Event(c), type(type), address(address) { + assert(c, address->event == 0); address->event = this; } @@ -1035,6 +1054,7 @@ class JumpEvent: public Event { Event(c), address(address) { + assert(c, address->event == 0); address->event = this; } @@ -1067,7 +1087,9 @@ class CombineEvent: public Event { MyOperand* b, MyOperand* result): Event(c), type(type), size(size), a(a), b(b), result(result) { + assert(c, a->event == 0); a->event = this; + assert(c, b->event == 0); b->event = this; } @@ -1152,6 +1174,7 @@ class TranslateEvent: public Event { MyOperand* result): Event(c), type(type), size(size), a(a), result(result) { + assert(c, a->event == 0); a->event = this; } @@ -1222,10 +1245,7 @@ preserve(Context* c, Stack* stack, int reg, MyOperand* a) unsigned count = 0; Stack* start = 0; - for (Stack* s = stack; - s and s->operand->value->stackPosition(c) == 0; - s = s->next) - { + for (Stack* s = stack; s and s->operand->pushedValue == 0; s = s->next) { if (s->operand == a) { start = s; } @@ -1280,6 +1300,8 @@ push(Context* c, unsigned size, MyOperand* o) assert(c, ceiling(size, BytesPerWord)); c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); + + appendPush(c); } MyOperand* @@ -1294,6 +1316,22 @@ pop(Context* c, unsigned size UNUSED) return s->operand; } +void +markStack(Context*, Stack* stack) +{ + for (Stack* s = stack; s; s = s->next) { + if (s->operand->push) { + s->operand->push->markStack(); + } + } +} + +void +markStack(Context* c) +{ + markStack(c, c->state->stack); +} + void updateJunctions(Context* c) { @@ -1303,10 +1341,7 @@ updateJunctions(Context* c) if (i->predecessor >= 0) { LogicalInstruction* p = c->logicalCode + i->predecessor; - Event* e = new (c->zone->allocate(sizeof(SyncStackEvent))) - SyncStackEvent(c, p->lastEvent->next); - - p->lastEvent = p->lastEvent->next = e; + markStack(c, p->lastEvent->stack); } } } @@ -1502,7 +1537,7 @@ class MyCompiler: public Compiler { va_end(a); - appendSyncStack(&c); + markStack(&c); MyOperand* result = operand(&c); appendCall(&c, static_cast(address), indirection, flags, @@ -1549,43 +1584,43 @@ class MyCompiler: public Compiler { } virtual void jl(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendBranch(&c, JumpIfLess, static_cast(address)); } virtual void jg(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendBranch(&c, JumpIfGreater, static_cast(address)); } virtual void jle(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); } virtual void jge(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); } virtual void je(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendBranch(&c, JumpIfEqual, static_cast(address)); } virtual void jne(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendBranch(&c, JumpIfNotEqual, static_cast(address)); } virtual void jmp(Operand* address) { - appendSyncStack(&c); + markStack(&c); appendJump(&c, static_cast(address)); } @@ -1680,7 +1715,7 @@ class MyCompiler: public Compiler { } virtual unsigned poolSize() { - return c.constantCount; + return c.constantCount * BytesPerWord; } virtual void writeTo(uint8_t* dst) { From 7cd79736c22e7b358f2887beac7fd6f891db8cbb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 11 Mar 2008 10:57:35 -0600 Subject: [PATCH 014/121] fix tracking of stack operations in compile.cpp --- src/compile.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 3063403796..423fc0d0f5 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1436,6 +1436,31 @@ resultSize(MyThread* t, unsigned code) } } +void +pushReturnValue(MyThread* t, Frame* frame, unsigned code, + Compiler::Operand* result) +{ + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: + return frame->pushInt(result); + + case ObjectField: + return frame->pushObject(result); + + case LongField: + case DoubleField: + return frame->pushLong(result); + + default: + abort(t); + } +} + bool emptyMethod(MyThread* t, object method) { @@ -1465,10 +1490,10 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) 0); } - c->popped(methodParameterFootprint(t, target)); + frame->pop(methodParameterFootprint(t, target)); if (rSize) { - c->push(rSize, result); + pushReturnValue(t, frame, methodReturnCode(t, target), result); } } @@ -2427,7 +2452,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pop(parameterFootprint); if (rSize) { - c->push(rSize, result); + pushReturnValue(t, frame, methodReturnCode(t, target), result); } } break; @@ -2483,7 +2508,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pop(parameterFootprint); if (rSize) { - c->push(rSize, result); + pushReturnValue(t, frame, methodReturnCode(t, target), result); } } break; From 406f173982968d12235ae83891234e1ef9c51227 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 13 Mar 2008 14:50:56 -0600 Subject: [PATCH 015/121] handle constant array lengths and indexes properly; various bugfixes --- src/compile.cpp | 281 +++++++++++++++++++++++++++++++---------------- src/compiler.cpp | 119 +++++++++++++++----- src/compiler.h | 3 + src/x86.cpp | 70 +++++++++++- 4 files changed, 349 insertions(+), 124 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 423fc0d0f5..7c1f16ea04 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -948,6 +948,8 @@ class Frame { (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) TraceElement(context, target, virtualCall, context->traceLog); + fprintf(stderr, "make element %p at ip %d\n", e, ip); + context->eventLog.append(TraceEvent); context->eventLog.appendAddress(e); @@ -1573,6 +1575,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->startLogicalIp(ip); + if (ip == 0) { + handleEntrance(t, frame); + } + // fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map)); unsigned instruction = codeBody(t, code, ip++); @@ -1591,17 +1597,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (CheckArrayBounds) { Compiler::Operand* load = c->label(); - Compiler::Operand* throw_ = c->label(); + Compiler::Operand* throw_ = 0; - c->cmp(4, c->constant(0), index); - c->jl(throw_); + if (c->isConstant(index)) { + expect(t, c->constantValue(index) >= 0); + } else { + throw_ = c->label(); + c->cmp(4, c->constant(0), index); + c->jl(throw_); + } c->cmp(BytesPerWord, - c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), - index); - c->jl(load); + index, + c->memory(array, ArrayLength, 0, 1, frame->trace(0, false))); + c->jge(load); - c->mark(throw_); + if (not c->isConstant(index)) { + c->mark(throw_); + } c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), @@ -1614,34 +1627,67 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->mark(load); } - switch (instruction) { - case aaload: - frame->pushObject - (c->load - (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); - break; + if (c->isConstant(index)) { + unsigned i = c->constantValue(index); + switch (instruction) { + case aaload: + frame->pushObject + (c->load + (BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord)))); + break; - case faload: - case iaload: - frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); - break; + case faload: + case iaload: + frame->pushInt(c->load(4, c->memory(array, ArrayBody + (i * 4)))); + break; - case baload: - frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); - break; + case baload: + frame->pushInt(c->load(1, c->memory(array, ArrayBody + i))); + break; - case caload: - frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); - break; + case caload: + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody + (i * 2)))); + break; - case daload: - case laload: - frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); - break; + case daload: + case laload: + frame->pushInt(c->load(8, c->memory(array, ArrayBody + (i * 8)))); + break; - case saload: - frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); - break; + case saload: + frame->pushInt(c->load(2, c->memory(array, ArrayBody + (i * 2)))); + break; + } + } else { + switch (instruction) { + case aaload: + frame->pushObject + (c->load + (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); + break; + + case faload: + case iaload: + frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); + break; + + case baload: + frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); + break; + + case caload: + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); + break; + + case daload: + case laload: + frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); + break; + + case saload: + frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); + break; + } } } break; @@ -1667,17 +1713,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (CheckArrayBounds) { Compiler::Operand* store = c->label(); - Compiler::Operand* throw_ = c->label(); + Compiler::Operand* throw_ = 0; - c->cmp(4, c->constant(0), index); - c->jl(throw_); + if (c->isConstant(index)) { + expect(t, c->constantValue(index) >= 0); + } else { + throw_ = c->label(); + c->cmp(4, c->constant(0), index); + c->jl(throw_); + } c->cmp(BytesPerWord, - c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), - index); - c->jl(store); + index, + c->memory(array, ArrayLength, 0, 1, frame->trace(0, false))); + c->jge(store); - c->mark(throw_); + if (not c->isConstant(index)) { + c->mark(throw_); + } c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), @@ -1690,38 +1743,74 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->mark(store); } - switch (instruction) { - case aastore: { - c->call - (c->constant(reinterpret_cast(setMaybeNull)), - context->indirection, - 0, - frame->trace(0, false), - 0, - 4, c->thread(), array, - c->add(4, c->constant(ArrayBody), - c->shl(4, c->constant(log(BytesPerWord)), index)), - value); - } break; + if (c->isConstant(index)) { + unsigned i = c->constantValue(index); + switch (instruction) { + case aastore: { + c->call + (c->constant(reinterpret_cast(setMaybeNull)), + context->indirection, + 0, + frame->trace(0, false), + 0, + 4, c->thread(), array, + c->constant(ArrayBody + (i * BytesPerWord)), + value); + } break; - case fastore: - case iastore: - c->store(4, value, c->memory(array, ArrayBody, index, 4)); - break; + case fastore: + case iastore: + c->store(4, value, c->memory(array, ArrayBody + (i * 4))); + break; - case bastore: - c->store(1, value, c->memory(array, ArrayBody, index, 1)); - break; + case bastore: + c->store(1, value, c->memory(array, ArrayBody + i)); + break; - case castore: - case sastore: - c->store(2, value, c->memory(array, ArrayBody, index, 2)); - break; + case castore: + case sastore: + c->store(2, value, c->memory(array, ArrayBody + (i * 2))); + break; - case dastore: - case lastore: - c->store(8, value, c->memory(array, ArrayBody, index, 8)); - break; + case dastore: + case lastore: + c->store(8, value, c->memory(array, ArrayBody + (i * 8))); + break; + } + } else { + switch (instruction) { + case aastore: { + c->call + (c->constant(reinterpret_cast(setMaybeNull)), + context->indirection, + 0, + frame->trace(0, false), + 0, + 4, c->thread(), array, + c->add(4, c->constant(ArrayBody), + c->shl(4, c->constant(log(BytesPerWord)), index)), + value); + } break; + + case fastore: + case iastore: + c->store(4, value, c->memory(array, ArrayBody, index, 4)); + break; + + case bastore: + c->store(1, value, c->memory(array, ArrayBody, index, 1)); + break; + + case castore: + case sastore: + c->store(2, value, c->memory(array, ArrayBody, index, 2)); + break; + + case dastore: + case lastore: + c->store(8, value, c->memory(array, ArrayBody, index, 8)); + break; + } } } break; @@ -1755,21 +1844,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Compiler::Operand* nonnegative = c->label(); - Compiler::Operand* length = frame->popInt(); - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); + if (c->isConstant(length)) { + expect(t, c->constantValue(length) >= 0); + } else{ + Compiler::Operand* nonnegative = c->label(); - c->mark(nonnegative); + c->cmp(4, c->constant(0), length); + c->jge(nonnegative); + + c->call + (c->constant(reinterpret_cast(throwNegativeArraySize)), + context->indirection, + Compiler::NoReturn, + frame->trace(0, false), + 0, + 2, c->thread(), length); + + c->mark(nonnegative); + } frame->pushObject (c->call @@ -2924,22 +3018,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case newarray: { uint8_t type = codeBody(t, code, ip++); - Compiler::Operand* nonnegative = c->label(); - Compiler::Operand* length = frame->popInt(); - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); + if (c->isConstant(length)) { + expect(t, c->constantValue(length) >= 0); + } else{ + Compiler::Operand* nonnegative = c->label(); - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); + c->cmp(4, c->constant(0), length); + c->jge(nonnegative); - c->mark(nonnegative); + c->call + (c->constant(reinterpret_cast(throwNegativeArraySize)), + context->indirection, + Compiler::NoReturn, + frame->trace(0, false), + 0, + 2, c->thread(), length); + + c->mark(nonnegative); + } object (*constructor)(Thread*, uintptr_t, bool); switch (type) { @@ -2985,7 +3083,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 0, frame->trace(0, false), BytesPerWord, - 2, c->thread(), c->constant(reinterpret_cast(constructor)), + 3, c->thread(), c->constant(reinterpret_cast(constructor)), length)); } break; @@ -3463,6 +3561,7 @@ finish(MyThread* t, Context* context) unsigned mapSize = frameMapSizeInWords(t, context->method); for (TraceElement* p = context->traceLog; p; p = p->next) { + fprintf(stderr, "make node for %p\n", p); object node = makeTraceNode (t, p->address->value(), 0, context->method, p->target, p->virtualCall, mapSize, false); @@ -3562,8 +3661,6 @@ compile(MyThread* t, Context* context) } } - handleEntrance(t, &frame); - compile(t, &frame, 0); if (UNLIKELY(t->exception)) return 0; diff --git a/src/compiler.cpp b/src/compiler.cpp index 094623ddd4..9a2f7cede6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -43,6 +43,8 @@ class Value { virtual void asAssemblerOperand(Context*, OperandType* type, Assembler::Operand** operand) = 0; + + virtual int64_t constantValue(Context*) = 0; }; class MyOperand: public Compiler::Operand { @@ -291,6 +293,10 @@ class ConstantValue: public Value { *operand = &value; } + virtual int64_t constantValue(Context*) { + return value.value->value(); + } + Assembler::Constant value; }; @@ -300,11 +306,17 @@ constant(Context* c, Promise* value) return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); } +ResolvedPromise* +resolved(Context* c, int64_t value) +{ + return new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value); +} + ConstantValue* constant(Context* c, int64_t value) { - return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); + return constant(c, resolved(c, value)); } class AddressValue: public Value { @@ -323,6 +335,10 @@ class AddressValue: public Value { *operand = &address; } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Assembler::Address address; }; @@ -385,6 +401,10 @@ class RegisterValue: public Value { *operand = ®ister_; } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Assembler::Register register_; }; @@ -437,6 +457,10 @@ class MemoryValue: public Value { *operand = &value; } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Assembler::Memory value; }; @@ -467,7 +491,7 @@ class AbstractMemoryValue: public MemoryValue { } virtual int index(Context* c) { - return index_ ? ::toRegister(c, base_) : NoRegister; + return index_ ? ::toRegister(c, index_) : NoRegister; } MyOperand* base_; @@ -502,6 +526,10 @@ class StackValue: public Value { abort(c); } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Stack* stack; }; @@ -514,6 +542,8 @@ stackValue(Context* c, Stack* stack) class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0) { + assert(c, c->logicalIp >= 0); + if (c->event) { c->event->next = this; } @@ -538,13 +568,37 @@ class Event { CodePromise* promises; }; +class NullEvent: public Event { + public: + NullEvent(Context* c): + Event(c) + { } + + virtual Value* target(Context*, MyOperand*) { + return 0; + } + + virtual void compile(Context*) { + // ignore + } +}; + +void +setEvent(Context* c, MyOperand* a, Event* e) +{ + if (a->event) { + a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c); + } else{ + a->event = e; + } +} + class ArgumentEvent: public Event { public: ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): Event(c), size(size), a(a), index(index) { - assert(c, a->event == 0); - a->event = this; + setEvent(c, a, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -590,8 +644,7 @@ class ReturnEvent: public Event { Event(c), size(size), a(a) { if (a) { - assert(c, a->event == 0); - a->event = this; + setEvent(c, a, this); } } @@ -643,8 +696,7 @@ class CallEvent: public Event { traceHandler(traceHandler), result(result) { - assert(c, address->event == 0); - address->event = this; + setEvent(c, address, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -855,8 +907,7 @@ class MoveEvent: public Event { MyOperand* dst): Event(c), type(type), size(size), src(src), dst(dst) { - assert(c, src->event == 0); - src->event = this; + setEvent(c, src, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -983,10 +1034,8 @@ class CompareEvent: public Event { CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): Event(c), size(size), a(a), b(b) { - assert(c, a->event == 0); - a->event = this; - assert(c, b->event == 0); - b->event = this; + setEvent(c, a, this); + setEvent(c, b, this); } virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { @@ -1020,8 +1069,7 @@ class BranchEvent: public Event { BranchEvent(Context* c, UnaryOperation type, MyOperand* address): Event(c), type(type), address(address) { - assert(c, address->event == 0); - address->event = this; + setEvent(c, address, this); } virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { @@ -1054,8 +1102,7 @@ class JumpEvent: public Event { Event(c), address(address) { - assert(c, address->event == 0); - address->event = this; + setEvent(c, address, this); } virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { @@ -1087,10 +1134,8 @@ class CombineEvent: public Event { MyOperand* b, MyOperand* result): Event(c), type(type), size(size), a(a), b(b), result(result) { - assert(c, a->event == 0); - a->event = this; - assert(c, b->event == 0); - b->event = this; + setEvent(c, a, this); + setEvent(c, b, this); } virtual Value* target(Context* c, MyOperand* v) { @@ -1174,8 +1219,7 @@ class TranslateEvent: public Event { MyOperand* result): Event(c), type(type), size(size), a(a), result(result) { - assert(c, a->event == 0); - a->event = this; + setEvent(c, a, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -1356,12 +1400,21 @@ compile(Context* c) a->apply(Push, BytesPerWord, Register, &base); a->apply(Move, BytesPerWord, Register, &stack, Register, &base); + if (c->stackOffset) { + Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); + a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack); + } + for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { fprintf(stderr, "compile ip %d\n", i); for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { e->compile(c); if (e == c->logicalCode[i].lastEvent) break; + + for (CodePromise* p = e->promises; p; p = p->next) { + p->offset = a->length(); + } } } } @@ -1408,8 +1461,7 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppend(intptr_t value) { - return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); + return poolAppendPromise(resolved(&c, value)); } virtual Promise* poolAppendPromise(Promise* value) { @@ -1432,8 +1484,7 @@ class MyCompiler: public Compiler { } virtual Operand* constant(int64_t value) { - return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); + return promiseConstant(resolved(&c, value)); } virtual Operand* promiseConstant(Promise* value) { @@ -1468,6 +1519,16 @@ class MyCompiler: public Compiler { return operand(&c, register_(&c, c.assembler->thread())); } + virtual bool isConstant(Operand* a) { + return static_cast(a)->value + and static_cast(a)->value->type(&c) == Constant; + } + + virtual int64_t constantValue(Operand* a) { + assert(&c, isConstant(a)); + return static_cast(a)->value->constantValue(&c); + } + virtual Operand* label() { return operand(&c, ::constant(&c, static_cast(0))); } diff --git a/src/compiler.h b/src/compiler.h index 725838c062..8136db3586 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -51,6 +51,9 @@ class Compiler { virtual Operand* base() = 0; virtual Operand* thread() = 0; + virtual bool isConstant(Operand* value) = 0; + virtual int64_t constantValue(Operand* value) = 0; + virtual Operand* label() = 0; virtual void mark(Operand* label) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index 68ea6d4a55..79f4178359 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -224,6 +224,7 @@ void encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex) { if (b->traceHandler) { + fprintf(stderr, "handle trace %p\n", b->traceHandler); b->traceHandler->handleTrace(codePromise(c, c->code.length())); } @@ -239,6 +240,7 @@ encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b, bool rex) { if (b->traceHandler) { + fprintf(stderr, "handle trace %p\n", b->traceHandler); b->traceHandler->handleTrace(codePromise(c, c->code.length())); } @@ -331,6 +333,14 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) c->code.append(0xe0 | a->low); } +void +jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x8d, a); +} + void pushR(Context* c, unsigned size, Assembler::Register* a) { @@ -552,6 +562,29 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + if (v) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xe8 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xe8 | b->low); + c->code.append4(v); + } else { + abort(c); + } + } +} + void addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) @@ -598,7 +631,23 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, { assert(c, BytesPerWord == 8 or size == 4); - encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 4, b, true); + encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true); + if (isInt8(a->value->value())) { + c->code.append(a->value->value()); + } else if (isInt32(a->value->value())) { + c->code.append4(a->value->value()); + } else { + abort(c); + } +} + +void +compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true); if (isInt8(a->value->value())) { c->code.append(a->value->value()); } else if (isInt32(a->value->value())) { @@ -614,29 +663,44 @@ populateTables() Operations[Return] = return_; UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); - UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM); + + UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); + UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); + + UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)] + = CAST1(jumpIfGreaterOrEqualC); + UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); + UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); + BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); - BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); + + BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); + BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); + + BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); + + BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); } class MyAssembler: public Assembler { From 6a9fbc0c17fdf6f3db465e2c3332c1398ed4b934 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 13 Mar 2008 17:43:11 -0600 Subject: [PATCH 016/121] allow assembler to acquire and release temporary registers; new machine instruction implementations; bugfixes --- src/assembler.h | 10 ++++ src/compiler.cpp | 57 +++++++++++++++------ src/x86.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 169 insertions(+), 28 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 117d7d3618..01c84edbaf 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -133,8 +133,18 @@ class Assembler { TraceHandler* traceHandler; }; + class Client { + public: + virtual ~Client() { } + + virtual int acquireTemporary() = 0; + virtual void releaseTemporary(int r) = 0; + }; + virtual ~Assembler() { } + virtual void setClient(Client* client) = 0; + virtual unsigned registerCount() = 0; virtual int base() = 0; diff --git a/src/compiler.cpp b/src/compiler.cpp index 9a2f7cede6..5f27e33251 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -759,10 +759,11 @@ appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, } int -freeRegister(Context* c) +freeRegisterExcept(Context* c, int except) { for (int i = c->assembler->registerCount(); i >= 0; --i) { - if ((not c->registers[i].reserved) + if (i != except + and (not c->registers[i].reserved) and c->registers[i].operand == 0) { return i; @@ -770,7 +771,9 @@ freeRegister(Context* c) } for (int i = c->assembler->registerCount(); i >= 0; --i) { - if (not c->registers[i].reserved) { + if (i != except + and (not c->registers[i].reserved)) + { return i; } } @@ -778,11 +781,18 @@ freeRegister(Context* c) abort(c); } +inline int +freeRegister(Context* c) +{ + return freeRegisterExcept(c, NoRegister); +} + RegisterValue* freeRegister(Context* c, unsigned size) { if (BytesPerWord == 4 and size == 8) { - return register_(c, freeRegister(c), freeRegister(c)); + int low = freeRegister(c); + return register_(c, low, freeRegisterExcept(c, low)); } else { return register_(c, freeRegister(c)); } @@ -943,14 +953,6 @@ class MoveEvent: public Event { { dst->value = src->value; return; - } else if ((src->value->type(c) == Address - or src->value->type(c) == Memory) - and src->target->type(c) == Memory) - { - RegisterValue* tmp = freeRegister(c, size); - tmp->preserve(c, stack, 0); - apply(c, Move, size, src->value, tmp); - src->value = tmp; } src->value->release(c, src); @@ -1406,11 +1408,14 @@ compile(Context* c) } for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { + LogicalInstruction* li = c->logicalCode + i; + li->machineOffset = a->length(); + fprintf(stderr, "compile ip %d\n", i); - for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { + for (Event* e = li->firstEvent; e; e = e->next) { e->compile(c); - if (e == c->logicalCode[i].lastEvent) break; + if (e == li->lastEvent) break; for (CodePromise* p = e->promises; p; p = p->next) { p->offset = a->length(); @@ -1419,11 +1424,30 @@ compile(Context* c) } } +class Client: public Assembler::Client { + public: + Client(Context* c): c(c) { } + + virtual int acquireTemporary() { + int r = freeRegister(c); + c->registers[r].reserved = true; + return r; + } + + virtual void releaseTemporary(int r) { + c->registers[r].reserved = false; + } + + Context* c; +}; + class MyCompiler: public Compiler { public: MyCompiler(System* s, Assembler* assembler, Zone* zone): - c(s, assembler, zone) - { } + c(s, assembler, zone), client(&c) + { + assembler->setClient(&client); + } virtual void pushState() { ::pushState(&c); @@ -1795,6 +1819,7 @@ class MyCompiler: public Compiler { } Context c; + Client client; }; } // namespace diff --git a/src/x86.cpp b/src/x86.cpp index 79f4178359..9952fdb452 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -52,11 +52,12 @@ class Task; class Context { public: Context(System* s, Allocator* a, Zone* zone): - s(s), zone(zone), code(s, a, 1024), tasks(0), result(0) + s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0) { } System* s; Zone* zone; + Assembler::Client* client; Vector code; Task* tasks; uint8_t* result; @@ -341,6 +342,50 @@ jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) conditional(c, 0x8d, a); } +void +jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x84, a); +} + +void +moveCR(Context*, unsigned, Assembler::Constant*, Assembler::Register*); + +void +pushR(Context*, unsigned, Assembler::Register*); + +void +pushC(Context* c, unsigned size, Assembler::Constant* a) +{ + int64_t v = a->value->value(); + + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + pushC(c, 4, &ah); + pushC(c, 4, &al); + } else { + if (isInt8(v)) { + c->code.append(0x6a); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x68); + c->code.append4(v); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + pushR(c, size, &tmp); + c->client->releaseTemporary(tmp.low); + } + } +} + void pushR(Context* c, unsigned size, Assembler::Register* a) { @@ -531,6 +576,30 @@ moveAR(Context* c, unsigned size, Assembler::Address* a, moveMR(c, size, &memory, b); } +void +moveAM(Context* c, unsigned size, Assembler::Address* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveAR(c, size, a, &tmp); + moveRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); +} + +void +moveMM(Context* c, unsigned size, Assembler::Memory* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + moveRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); +} + void move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) { @@ -564,7 +633,7 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, void subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, - Assembler::Register* b) + Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); // todo @@ -587,7 +656,7 @@ subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, void addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, - Assembler::Register* b) + Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); // todo @@ -611,17 +680,19 @@ andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, { assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); + rex(c); - if (isInt8(a->value->value())) { + if (isInt8(v)) { c->code.append(0x83); c->code.append(0xe0 | b->low); c->code.append(a->value->value()); - } else { - assert(c, isInt32(a->value->value())); - + } else if (isInt32(v)) { c->code.append(0x81); c->code.append(0xe0 | b->low); - c->code.append(a->value->value()); + c->code.append(v); + } else { + abort(c); } } @@ -631,11 +702,35 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, { assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); + encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true); - if (isInt8(a->value->value())) { - c->code.append(a->value->value()); - } else if (isInt32(a->value->value())) { - c->code.append4(a->value->value()); + if (isInt8(v)) { + c->code.append(v); + } else if (isInt32(v)) { + c->code.append4(v); + } else { + abort(c); + } +} + +void +compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + + if (size == 8) rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf8 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xf8 | b->low); + c->code.append4(v); } else { abort(c); } @@ -648,6 +743,7 @@ compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, assert(c, BytesPerWord == 8 or size == 4); encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true); + if (isInt8(a->value->value())) { c->code.append(a->value->value()); } else if (isInt32(a->value->value())) { @@ -672,7 +768,9 @@ populateTables() UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)] = CAST1(jumpIfGreaterOrEqualC); + UnaryOperations[INDEX1(JumpIfEqual, Constant)] = CAST1(jumpIfEqualC); + UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); @@ -687,6 +785,8 @@ populateTables() BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); + BinaryOperations[INDEX2(Move, Address, Memory)] = CAST2(moveAM); + BinaryOperations[INDEX2(Move, Memory, Memory)] = CAST2(moveMM); BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); @@ -700,6 +800,7 @@ populateTables() BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); + BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); } @@ -713,6 +814,11 @@ class MyAssembler: public Assembler { } } + virtual void setClient(Client* client) { + assert(&c, c.client == 0); + c.client = client; + } + virtual unsigned registerCount() { return 8;//BytesPerWord == 4 ? 8 : 16; } From 6bf0ca5bd93580d8ba9155aa5723e7f947286b35 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 15 Mar 2008 14:24:04 -0600 Subject: [PATCH 017/121] various bugfixes and new instructions --- src/compile.cpp | 3 - src/compiler.cpp | 198 +++++++++++++++++++++++++++++++---------------- src/x86.cpp | 52 ++++++++++++- 3 files changed, 182 insertions(+), 71 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 7c1f16ea04..b029356768 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -948,8 +948,6 @@ class Frame { (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) TraceElement(context, target, virtualCall, context->traceLog); - fprintf(stderr, "make element %p at ip %d\n", e, ip); - context->eventLog.append(TraceEvent); context->eventLog.appendAddress(e); @@ -3561,7 +3559,6 @@ finish(MyThread* t, Context* context) unsigned mapSize = frameMapSizeInWords(t, context->method); for (TraceElement* p = context->traceLog; p; p = p->next) { - fprintf(stderr, "make node for %p\n", p); object node = makeTraceNode (t, p->address->value(), 0, context->method, p->target, p->virtualCall, mapSize, false); diff --git a/src/compiler.cpp b/src/compiler.cpp index 5f27e33251..a59205ced9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -275,7 +275,7 @@ class IpPromise: public Promise { }; RegisterValue* -freeRegister(Context* c, unsigned size); +freeRegister(Context* c, unsigned size, bool allowAcquired); class ConstantValue: public Value { public: @@ -434,7 +434,7 @@ class MemoryValue: public Value { } virtual RegisterValue* toRegister(Context* c) { - RegisterValue* v = freeRegister(c, BytesPerWord); + RegisterValue* v = freeRegister(c, BytesPerWord, false); apply(c, Move, BytesPerWord, this, v); return v; } @@ -560,6 +560,7 @@ class Event { virtual ~Event() { } virtual Value* target(Context* c, MyOperand* value) = 0; + virtual unsigned operandSize(Context* c) = 0; virtual void compile(Context* c) = 0; virtual bool isCritical(Context*) { return false; } @@ -578,6 +579,10 @@ class NullEvent: public Event { return 0; } + virtual unsigned operandSize(Context*) { + return 0; + } + virtual void compile(Context*) { // ignore } @@ -607,22 +612,26 @@ class ArgumentEvent: public Event { if (index < c->assembler->argumentRegisterCount()) { return register_(c, c->assembler->argumentRegister(index)); } else { - return memory(c, c->assembler->base(), - -(index + ((c->stackOffset + 1) * BytesPerWord)), - NoRegister, 0, 0); + return 0; } } + virtual unsigned operandSize(Context*) { + return size; + } + virtual void compile(Context* c) { fprintf(stderr, "ArgumentEvent.compile\n"); if (a->target == 0) a->target = target(c, a); - a->value->release(c, a); - a->target->preserve(c, stack, a); - - if (not a->target->equals(c, a->value)) { + if (a->target == 0) { + apply(c, Push, size, a->value); + a->value = 0; + } else if (not a->target->equals(c, a->value)) { + a->target->preserve(c, stack, a); apply(c, Move, size, a->value, a->target); + a->value->release(c, a); } } @@ -654,16 +663,19 @@ class ReturnEvent: public Event { return register_(c, c->assembler->returnLow(), c->assembler->returnHigh()); } + virtual unsigned operandSize(Context*) { + return size; + } + virtual void compile(Context* c) { fprintf(stderr, "ReturnEvent.compile\n"); if (a) { if (a->target == 0) a->target = target(c, a); - a->value->release(c, a); - if (not a->target->equals(c, a->value)) { apply(c, Move, size, a->value, a->target); + a->value->release(c, a); } } @@ -709,6 +721,10 @@ class CallEvent: public Event { } } + virtual unsigned operandSize(Context*) { + return BytesPerWord; + } + virtual void compile(Context* c) { fprintf(stderr, "CallEvent.compile\n"); @@ -716,14 +732,6 @@ class CallEvent: public Event { address->target = target(c, address); } - address->value->release(c, address); - - if (result->event) { - result->value = register_ - (c, c->assembler->returnLow(), c->assembler->returnHigh()); - result->value->acquire(c, stack, result); - } - UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); if (indirection) { @@ -736,6 +744,14 @@ class CallEvent: public Event { apply(c, type, BytesPerWord, address->value); } + address->value->release(c, address); + + if (result->event) { + result->value = register_ + (c, c->assembler->returnLow(), c->assembler->returnHigh()); + result->value->acquire(c, stack, result); + } + if (traceHandler) { traceHandler->handleTrace (new (c->zone->allocate(sizeof(CodePromise))) @@ -759,7 +775,7 @@ appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, } int -freeRegisterExcept(Context* c, int except) +freeRegisterExcept(Context* c, int except, bool allowAcquired) { for (int i = c->assembler->registerCount(); i >= 0; --i) { if (i != except @@ -770,11 +786,13 @@ freeRegisterExcept(Context* c, int except) } } - for (int i = c->assembler->registerCount(); i >= 0; --i) { - if (i != except - and (not c->registers[i].reserved)) - { - return i; + if (allowAcquired) { + for (int i = c->assembler->registerCount(); i >= 0; --i) { + if (i != except + and (not c->registers[i].reserved)) + { + return i; + } } } @@ -782,19 +800,19 @@ freeRegisterExcept(Context* c, int except) } inline int -freeRegister(Context* c) +freeRegister(Context* c, bool allowAcquired) { - return freeRegisterExcept(c, NoRegister); + return freeRegisterExcept(c, NoRegister, allowAcquired); } RegisterValue* -freeRegister(Context* c, unsigned size) +freeRegister(Context* c, unsigned size, bool allowAcquired) { if (BytesPerWord == 4 and size == 8) { - int low = freeRegister(c); - return register_(c, low, freeRegisterExcept(c, low)); + int low = freeRegister(c, allowAcquired); + return register_(c, low, freeRegisterExcept(c, low, allowAcquired)); } else { - return register_(c, freeRegister(c)); + return register_(c, freeRegister(c, allowAcquired)); } } @@ -809,8 +827,8 @@ syncStack(Context* c, Stack* start, unsigned count) for (unsigned i = 0; i < count; ++i) { Stack* s = segment[i]; - s->operand->value->release(c, s->operand); apply(c, Push, s->size * BytesPerWord, s->operand->value); + s->operand->value->release(c, s->operand); s->operand->pushedValue = stackValue(c, s); } } @@ -835,8 +853,12 @@ class PushEvent: public Event { stack->operand->push = this; } - virtual Value* target(Context*, MyOperand*) { - return 0; + virtual Value* target(Context* c, MyOperand*) { + abort(c); + } + + virtual unsigned operandSize(Context* c) { + abort(c); } virtual void compile(Context* c) { @@ -871,20 +893,22 @@ class PopEvent: public Event { abort(c); } + virtual unsigned operandSize(Context* c) { + abort(c); + } + virtual void compile(Context* c) { fprintf(stderr, "PopEvent.compile\n"); MyOperand* dst = stack->operand; if (dst->event and dst->pushedValue) { - Value* target = dst->target; + Value* target = 0; + if (dst->event and dst->event->operandSize(c) == BytesPerWord) { + target = dst->event->target(c, dst); + } if (target == 0) { - if (dst->event) { - target = dst->event->target(c, dst); - } - if (target == 0) { - target = freeRegister(c, BytesPerWord * stack->size); - } + target = freeRegister(c, BytesPerWord * stack->size, false); } target->acquire(c, 0, dst); @@ -927,9 +951,13 @@ class MoveEvent: public Event { return dst->value; } else if (dst->event) { return dst->event->target(c, dst); - } else { - return 0; } + + return 0; + } + + virtual unsigned operandSize(Context*) { + return size; } virtual void compile(Context* c) { @@ -945,21 +973,21 @@ class MoveEvent: public Event { dst->value = src->value; return; } else { - src->target = freeRegister(c, size); + src->target = freeRegister(c, size, true); } } else if (type == Move - and size == BytesPerWord + and (size == BytesPerWord or src->target->type(c) == Memory) and src->target->equals(c, src->value)) { dst->value = src->value; return; } + apply(c, type, size, src->value, src->target); + src->value->release(c, src); src->target->acquire(c, stack, dst); - apply(c, type, size, src->value, src->target); - dst->value = src->target; } @@ -993,6 +1021,10 @@ class DupEvent: public Event { abort(c); } + virtual unsigned operandSize(Context* c) { + abort(c); + } + virtual void compile(Context* c) { fprintf(stderr, "DupEvent.compile\n"); @@ -1010,7 +1042,7 @@ class DupEvent: public Event { target = dst->event->target(c, dst); } if (target == 0) { - target = freeRegister(c, size); + target = freeRegister(c, size, true); } target->acquire(c, stack, dst); @@ -1046,13 +1078,17 @@ class CompareEvent: public Event { return 0; } + virtual unsigned operandSize(Context*) { + return size; + } + virtual void compile(Context* c) { fprintf(stderr, "CompareEvent.compile\n"); + apply(c, Compare, size, a->value, b->value); + a->value->release(c, a); b->value->release(c, b); - - apply(c, Compare, size, a->value, b->value); } unsigned size; @@ -1080,12 +1116,16 @@ class BranchEvent: public Event { return 0; } + virtual unsigned operandSize(Context*) { + return BytesPerWord; + } + virtual void compile(Context* c) { fprintf(stderr, "BranchEvent.compile\n"); - address->value->release(c, address); - apply(c, type, BytesPerWord, address->value); + + address->value->release(c, address); } UnaryOperation type; @@ -1107,6 +1147,10 @@ class JumpEvent: public Event { setEvent(c, address, this); } + virtual unsigned operandSize(Context*) { + return BytesPerWord; + } + virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { assert(c, v == address); @@ -1116,9 +1160,9 @@ class JumpEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "JumpEvent.compile\n"); - address->value->release(c, address); - apply(c, Jump, BytesPerWord, address->value); + + address->value->release(c, address); } MyOperand* address; @@ -1140,6 +1184,10 @@ class CombineEvent: public Event { setEvent(c, b, this); } + virtual unsigned operandSize(Context*) { + return size; + } + virtual Value* target(Context* c, MyOperand* v) { Assembler::Register ar(NoRegister); Assembler::Register br(NoRegister); @@ -1178,25 +1226,29 @@ class CombineEvent: public Event { if (b->target == 0) b->target = target(c, b); if (b->target == 0) { - b->target = freeRegister(c, BytesPerWord); + b->target = freeRegister(c, BytesPerWord, true); } if (a->target and not a->target->equals(c, a->value)) { - a->value->release(c, a); apply(c, Move, size, a->value, a->target); + a->value->release(c, a); a->value = a->target; + a->value->acquire(c, stack, a); } if (b->target and not b->target->equals(c, b->value)) { - b->value->release(c, b); apply(c, Move, size, b->value, b->target); + b->value->release(c, b); b->value = b->target; + b->value->acquire(c, stack, b); } - b->value->acquire(c, stack, result); - apply(c, type, size, a->value, b->value); + a->value->release(c, a); + b->value->release(c, b); + b->value->acquire(c, stack, result); + result->value = b->value; } @@ -1237,6 +1289,10 @@ class TranslateEvent: public Event { } } + virtual unsigned operandSize(Context*) { + return size; + } + virtual void compile(Context* c) { fprintf(stderr, "TranslateEvent.compile\n"); @@ -1269,7 +1325,7 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a, RegisterValue* ConstantValue::toRegister(Context* c) { - RegisterValue* v = freeRegister(c, BytesPerWord); + RegisterValue* v = freeRegister(c, BytesPerWord, false); apply(c, Move, BytesPerWord, this, v); return v; } @@ -1277,7 +1333,7 @@ ConstantValue::toRegister(Context* c) RegisterValue* AddressValue::toRegister(Context* c) { - RegisterValue* v = freeRegister(c, BytesPerWord); + RegisterValue* v = freeRegister(c, BytesPerWord, false); apply(c, Move, BytesPerWord, this, v); return v; } @@ -1292,7 +1348,7 @@ preserve(Context* c, Stack* stack, int reg, MyOperand* a) unsigned count = 0; Stack* start = 0; for (Stack* s = stack; s and s->operand->pushedValue == 0; s = s->next) { - if (s->operand == a) { + if (s->operand == b) { start = s; } if (start) { @@ -1312,6 +1368,17 @@ operand(Context* c, Value* value = 0) return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(value); } +unsigned +count(Stack* s) +{ + unsigned c = 0; + while (s) { + ++ c; + s = s->next; + } + return c; +} + void pushState(Context* c) { @@ -1411,8 +1478,9 @@ compile(Context* c) LogicalInstruction* li = c->logicalCode + i; li->machineOffset = a->length(); - fprintf(stderr, "compile ip %d\n", i); for (Event* e = li->firstEvent; e; e = e->next) { + fprintf(stderr, "compile event at ip %d with stack count %d\n", + i, count(e->stack)); e->compile(c); if (e == li->lastEvent) break; @@ -1429,7 +1497,7 @@ class Client: public Assembler::Client { Client(Context* c): c(c) { } virtual int acquireTemporary() { - int r = freeRegister(c); + int r = freeRegisterExcept(c, NoRegister, false); c->registers[r].reserved = true; return r; } @@ -1454,7 +1522,7 @@ class MyCompiler: public Compiler { } virtual void popState() { - ::pushState(&c); + ::popState(&c); } virtual void init(unsigned logicalCodeLength, unsigned stackOffset) { diff --git a/src/x86.cpp b/src/x86.cpp index 9952fdb452..1caa4b5512 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -335,11 +335,11 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) } void -jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a) { assert(c, size == BytesPerWord); - conditional(c, 0x8d, a); + unconditional(c, 0xe9, a); } void @@ -350,6 +350,46 @@ jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) conditional(c, 0x84, a); } +void +jumpIfNotEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x85, a); +} + +void +jumpIfGreaterC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x8f, a); +} + +void +jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x8d, a); +} + +void +jumpIfLessC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x8c, a); +} + +void +jumpIfLessOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x8e, a); +} + void moveCR(Context*, unsigned, Assembler::Constant*, Assembler::Register*); @@ -765,10 +805,16 @@ populateTables() UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); + UnaryOperations[INDEX1(Jump, Constant)] = CAST1(jumpC); + UnaryOperations[INDEX1(JumpIfEqual, Constant)] = CAST1(jumpIfEqualC); + UnaryOperations[INDEX1(JumpIfNotEqual, Constant)] = CAST1(jumpIfNotEqualC); + UnaryOperations[INDEX1(JumpIfGreater, Constant)] = CAST1(jumpIfGreaterC); UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)] = CAST1(jumpIfGreaterOrEqualC); - UnaryOperations[INDEX1(JumpIfEqual, Constant)] = CAST1(jumpIfEqualC); + UnaryOperations[INDEX1(JumpIfLess, Constant)] = CAST1(jumpIfLessC); + UnaryOperations[INDEX1(JumpIfLessOrEqual, Constant)] + = CAST1(jumpIfLessOrEqualC); UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); From 8141fc21b427e247e369899501361ed7cd9a16e6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 15 Mar 2008 14:44:14 -0600 Subject: [PATCH 018/121] release base and index values of AbstractMemoryValue if necessary; bugfixes --- src/compiler.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index a59205ced9..f57570e5e2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -380,7 +380,7 @@ class RegisterValue: public Value { } } - virtual void release(Context* c, MyOperand* a UNUSED) { + virtual void release(Context* c, MyOperand* a) { if (a == c->registers[register_.low].operand) { fprintf(stderr, "%p release %d\n", a, register_.low); @@ -486,6 +486,20 @@ class AbstractMemoryValue: public MemoryValue { base_(base), index_(index) { } + virtual void preserve(Context* c, Stack* s, MyOperand*) { + base_->value->preserve(c, s, base_); + if (index_) { + index_->value->preserve(c, s, index_); + } + } + + virtual void release(Context* c, MyOperand*) { + base_->value->release(c, base_); + if (index_) { + index_->value->release(c, index_); + } + } + virtual int base(Context* c) { return ::toRegister(c, base_); } @@ -628,9 +642,11 @@ class ArgumentEvent: public Event { if (a->target == 0) { apply(c, Push, size, a->value); a->value = 0; - } else if (not a->target->equals(c, a->value)) { - a->target->preserve(c, stack, a); - apply(c, Move, size, a->value, a->target); + } else { + if (not a->target->equals(c, a->value)) { + a->target->preserve(c, stack, a); + apply(c, Move, size, a->value, a->target); + } a->value->release(c, a); } } @@ -911,10 +927,10 @@ class PopEvent: public Event { target = freeRegister(c, BytesPerWord * stack->size, false); } - target->acquire(c, 0, dst); - apply(c, Pop, BytesPerWord * stack->size, target); + target->acquire(c, 0, dst); + dst->value = target; } } From 420a054fd8819f68243e95a46cedb9a48b6c61f4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 15 Mar 2008 15:02:19 -0600 Subject: [PATCH 019/121] support 1- and 2-byte moves to memory --- src/assembler.h | 2 +- src/compiler.cpp | 9 +++++-- src/x86.cpp | 63 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 01c84edbaf..35c58afb5b 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -137,7 +137,7 @@ class Assembler { public: virtual ~Client() { } - virtual int acquireTemporary() = 0; + virtual int acquireTemporary(int r = NoRegister) = 0; virtual void releaseTemporary(int r) = 0; }; diff --git a/src/compiler.cpp b/src/compiler.cpp index f57570e5e2..35abe02680 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1512,8 +1512,13 @@ class Client: public Assembler::Client { public: Client(Context* c): c(c) { } - virtual int acquireTemporary() { - int r = freeRegisterExcept(c, NoRegister, false); + virtual int acquireTemporary(int r) { + if (r == NoRegister) { + r = freeRegisterExcept(c, NoRegister, false); + } else { + expect(c, not c->registers[r].reserved); + expect(c, c->registers[r].operand == 0); + } c->registers[r].reserved = true; return r; } diff --git a/src/x86.cpp b/src/x86.cpp index 1caa4b5512..7a435f9ef2 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -528,6 +528,25 @@ moveCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, c->code.append4(a->value->value()); } +void +moveRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->low); + Assembler::Register bh(b->low); + + moveRR(c, 4, a, b); + moveRR(c, 4, &ah, &bh); + } else { + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x89); + c->code.append(0xc0 | (a->low << 3) | b->low); + } +} + void moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) { @@ -540,24 +559,36 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) } else if (BytesPerWord == 8 and size == 4) { encode(c, 0x89, a->low, b, false); } else { - encode(c, 0x89, a->low, b, true); - } -} + switch (size) { + case 1: + if (BytesPerWord == 8) { + if (a->low > rbx) { + encode2(c, 0x4088, a->low, b, false); + } else { + encode(c, 0x88, a->low, b, false); + } + } else { + if (a->low > rbx) { + Assembler::Register ax(c->client->acquireTemporary(rax)); + moveRR(c, BytesPerWord, a, &ax); + moveRM(c, 1, &ax, b); + c->client->releaseTemporary(ax.low); + } else { + encode(c, 0x88, a->low, b, false); + } + } + break; -void -moveRR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) -{ - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->low); - Assembler::Register bh(b->low); + case 2: + encode2(c, 0x6689, a->low, b, false); + break; - moveRR(c, 4, a, b); - moveRR(c, 4, &ah, &bh); - } else { - rex(c); - c->code.append(0x89); - c->code.append(0xc0 | (a->low << 3) | b->low); + case BytesPerWord: + encode(c, 0x89, a->low, b, true); + break; + + default: abort(c); + } } } From 684b402e8295e4d6e027f6cd7a991436c57b5b50 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 15 Mar 2008 17:54:20 -0600 Subject: [PATCH 020/121] bugfixes and new instructions --- src/compile.cpp | 2 +- src/compiler.cpp | 251 +++++++++++++++++++++++++++-------------------- src/x86.cpp | 111 ++++++++++++++++++++- 3 files changed, 256 insertions(+), 108 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index b029356768..f88dc2857a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2589,7 +2589,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* result = c->call (c->memory (c->and_ - (4, c->constant(PointerMask), c->memory + (BytesPerWord, c->constant(PointerMask), c->memory (instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1), 0, 0, diff --git a/src/compiler.cpp b/src/compiler.cpp index 35abe02680..1d4ca71ed4 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -26,6 +26,8 @@ class Event; class PushEvent; class Stack; +void NO_RETURN abort(Context* c); + class Value { public: virtual ~Value() { } @@ -38,26 +40,25 @@ class Value { virtual void acquire(Context*, Stack*, MyOperand*) { } virtual void release(Context*, MyOperand*) { } - virtual RegisterValue* toRegister(Context*) = 0; + virtual int registerValue(Context* c) { abort(c); } + virtual int64_t constantValue(Context* c) { abort(c); } virtual void asAssemblerOperand(Context*, OperandType* type, Assembler::Operand** operand) = 0; - - virtual int64_t constantValue(Context*) = 0; }; class MyOperand: public Compiler::Operand { public: MyOperand(Value* value): - event(0), value(value), target(0), push(0), pushedValue(0) + event(0), value(value), target(0), push(0), pushed(false) { } Event* event; Value* value; Value* target; PushEvent* push; - StackValue* pushedValue; + bool pushed; }; class Stack { @@ -283,8 +284,6 @@ class ConstantValue: public Value { virtual OperandType type(Context*) { return Constant; } - virtual RegisterValue* toRegister(Context* c); - virtual void asAssemblerOperand(Context*, OperandType* type, Assembler::Operand** operand) @@ -325,8 +324,6 @@ class AddressValue: public Value { virtual OperandType type(Context*) { return Address; } - virtual RegisterValue* toRegister(Context* c); - virtual void asAssemblerOperand(Context*, OperandType* type, Assembler::Operand** operand) @@ -335,10 +332,6 @@ class AddressValue: public Value { *operand = &address; } - virtual int64_t constantValue(Context* c) { - abort(c); - } - Assembler::Address address; }; @@ -389,8 +382,8 @@ class RegisterValue: public Value { } } - virtual RegisterValue* toRegister(Context*) { - return this; + virtual int registerValue(Context*) { + return register_.low; } virtual void asAssemblerOperand(Context*, @@ -401,10 +394,6 @@ class RegisterValue: public Value { *operand = ®ister_; } - virtual int64_t constantValue(Context* c) { - abort(c); - } - Assembler::Register register_; }; @@ -433,12 +422,6 @@ class MemoryValue: public Value { and static_cast(o)->value.scale == value.scale); } - virtual RegisterValue* toRegister(Context* c) { - RegisterValue* v = freeRegister(c, BytesPerWord, false); - apply(c, Move, BytesPerWord, this, v); - return v; - } - virtual int base(Context*) { return value.base; } @@ -457,27 +440,9 @@ class MemoryValue: public Value { *operand = &value; } - virtual int64_t constantValue(Context* c) { - abort(c); - } - 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) -{ - return a->value->toRegister(c)->register_.low; -} - class AbstractMemoryValue: public MemoryValue { public: AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, @@ -501,11 +466,11 @@ class AbstractMemoryValue: public MemoryValue { } virtual int base(Context* c) { - return ::toRegister(c, base_); + return base_->value->registerValue(c); } virtual int index(Context* c) { - return index_ ? ::toRegister(c, index_) : NoRegister; + return index_ ? index_->value->registerValue(c) : NoRegister; } MyOperand* base_; @@ -522,35 +487,32 @@ memory(Context* c, MyOperand* base, int offset, MyOperand* index, class StackValue: public Value { public: - StackValue(Stack* stack): stack(stack) { } + StackValue(Context* c, Stack* stack): + stack(stack), + value + (c->assembler->base(), + - (c->stackOffset + stack->index + 1) * BytesPerWord, + NoRegister, 0, 0) + { } - virtual OperandType type(Context* c) { abort(c); } + virtual OperandType type(Context*) { return Memory; } - virtual RegisterValue* toRegister(Context* c) { - return MemoryValue - (c->assembler->base(), (c->stackOffset + stack->index) * BytesPerWord, - NoRegister, 0, 0) - .toRegister(c); - } - - virtual void asAssemblerOperand(Context* c, - OperandType*, - Assembler::Operand**) + virtual void asAssemblerOperand(Context*, + OperandType* type, + Assembler::Operand** operand) { - abort(c); - } - - virtual int64_t constantValue(Context* c) { - abort(c); + *type = Memory; + *operand = &value; } Stack* stack; + Assembler::Memory value; }; StackValue* stackValue(Context* c, Stack* stack) { - return new (c->zone->allocate(sizeof(StackValue))) StackValue(stack); + return new (c->zone->allocate(sizeof(StackValue))) StackValue(c, stack); } class Event { @@ -691,8 +653,8 @@ class ReturnEvent: public Event { if (not a->target->equals(c, a->value)) { apply(c, Move, size, a->value, a->target); - a->value->release(c, a); } + a->value->release(c, a); } Assembler::Register base(c->assembler->base()); @@ -843,9 +805,19 @@ syncStack(Context* c, Stack* start, unsigned count) for (unsigned i = 0; i < count; ++i) { Stack* s = segment[i]; - apply(c, Push, s->size * BytesPerWord, s->operand->value); - s->operand->value->release(c, s->operand); - s->operand->pushedValue = stackValue(c, s); + if (s->operand->value) { + apply(c, Push, s->size * BytesPerWord, s->operand->value); + s->operand->value->release(c, s->operand); + s->operand->pushed = true; + s->operand->value = stackValue(c, s); + } else { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); + c->assembler->apply + (Subtract, BytesPerWord, Constant, &offset, Register, &stack); + s->operand->pushed = true; + s->operand->value = stackValue(c, s); + } } } @@ -853,7 +825,7 @@ void syncStack(Context* c, Stack* start) { unsigned count = 0; - for (Stack* s = start; s and s->operand->pushedValue == 0; s = s->next) { + for (Stack* s = start; s and (not s->operand->pushed); s = s->next) { ++ count; } @@ -901,8 +873,8 @@ appendPush(Context* c) class PopEvent: public Event { public: - PopEvent(Context* c): - Event(c) + PopEvent(Context* c, unsigned count, bool ignore): + Event(c), count(count), ignore(ignore) { } virtual Value* target(Context* c, MyOperand*) { @@ -916,30 +888,53 @@ class PopEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "PopEvent.compile\n"); - MyOperand* dst = stack->operand; - if (dst->event and dst->pushedValue) { - Value* target = 0; + Stack* s = stack; + unsigned ignored = 0; + for (unsigned i = count; i;) { + MyOperand* dst = s->operand; + if (dst->pushed) { + if (dst->event and (not ignore)) { + assert(c, ignored == 0); - if (dst->event and dst->event->operandSize(c) == BytesPerWord) { - target = dst->event->target(c, dst); - } - if (target == 0) { - target = freeRegister(c, BytesPerWord * stack->size, false); + Value* target = 0; + + if (dst->event->operandSize(c) == BytesPerWord) { + target = dst->event->target(c, dst); + } + if (target == 0) { + target = freeRegister(c, BytesPerWord * s->size, false); + } + + apply(c, Pop, BytesPerWord * s->size, target); + + target->acquire(c, 0, dst); + + dst->value = target; + } else { + ignored += s->size; + } } - apply(c, Pop, BytesPerWord * stack->size, target); + i -= s->size; + s = s->next; + } - target->acquire(c, 0, dst); - - dst->value = target; + if (ignored) { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); + c->assembler->apply + (Add, BytesPerWord, Constant, &offset, Register, &stack); } } + + unsigned count; + bool ignore; }; void -appendPop(Context* c) +appendPop(Context* c, unsigned count, bool ignore) { - new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c); + new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } bool @@ -1221,7 +1216,7 @@ class CombineEvent: public Event { if (br.low == NoRegister) { if (result->event) { Value* v = result->event->target(c, result); - if (v->type(c) == Register) { + if (v and v->type(c) == Register) { return v; } else { return 0; @@ -1338,20 +1333,52 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a, TranslateEvent(c, type, size, a, result); } -RegisterValue* -ConstantValue::toRegister(Context* c) -{ - RegisterValue* v = freeRegister(c, BytesPerWord, false); - apply(c, Move, BytesPerWord, this, v); - return v; -} +class MemoryEvent: public Event { + public: + MemoryEvent(Context* c, MyOperand* base, MyOperand* index, + MyOperand* result): + Event(c), base(base), index(index), result(result) + { + setEvent(c, base, this); + if (index) setEvent(c, index, this); + } -RegisterValue* -AddressValue::toRegister(Context* c) + virtual unsigned operandSize(Context*) { + return BytesPerWord; + } + + virtual Value* target(Context* c, MyOperand* v UNUSED) { + assert(c, v == base or v == index); + return 0; + } + + virtual void compile(Context* c) { + fprintf(stderr, "MemoryEvent.compile\n"); + + if (base->value->type(c) != Register) { + base->target = freeRegister(c, BytesPerWord, true); + apply(c, Move, BytesPerWord, base->value, base->target); + base->value->release(c, base); + base->value = base->target; + } + + if (index and index->value->type(c) != Register) { + index->target = freeRegister(c, BytesPerWord, true); + apply(c, Move, BytesPerWord, index->value, index->target); + index->value->release(c, index); + index->value = index->target; + } + } + + MyOperand* base; + MyOperand* index; + MyOperand* result; +}; + +void +appendMemory(Context* c, MyOperand* a, MyOperand* b, MyOperand* result) { - RegisterValue* v = freeRegister(c, BytesPerWord, false); - apply(c, Move, BytesPerWord, this, v); - return v; + new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, a, b, result); } void @@ -1363,7 +1390,7 @@ preserve(Context* c, Stack* stack, int reg, MyOperand* a) unsigned count = 0; Stack* start = 0; - for (Stack* s = stack; s and s->operand->pushedValue == 0; s = s->next) { + for (Stack* s = stack; s and (not s->operand->pushed); s = s->next) { if (s->operand == b) { start = s; } @@ -1429,7 +1456,7 @@ push(Context* c, unsigned size, MyOperand* o) assert(c, ceiling(size, BytesPerWord)); c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); - + appendPush(c); } @@ -1439,7 +1466,7 @@ pop(Context* c, unsigned size UNUSED) Stack* s = c->state->stack; assert(c, ceiling(size, BytesPerWord) == s->size); - appendPop(c); + appendPop(c, s->size, false); c->state->stack = s->next; return s->operand; @@ -1499,11 +1526,11 @@ compile(Context* c) i, count(e->stack)); e->compile(c); - if (e == li->lastEvent) break; - for (CodePromise* p = e->promises; p; p = p->next) { p->offset = a->length(); } + + if (e == li->lastEvent) break; } } } @@ -1614,10 +1641,15 @@ class MyCompiler: public Compiler { unsigned scale = 1, TraceHandler* traceHandler = 0) { - return operand + MyOperand* result = operand (&c, ::memory (&c, static_cast(base), displacement, static_cast(index), scale, traceHandler)); + + appendMemory(&c, static_cast(base), + static_cast(index), result); + + return result; } virtual Operand* stack() { @@ -1652,6 +1684,8 @@ class MyCompiler: public Compiler { } virtual void mark(Operand* label) { + markStack(&c); + static_cast(static_cast(label)->value)->value = machineIp(); } @@ -1665,11 +1699,18 @@ class MyCompiler: public Compiler { } virtual void pushed(unsigned count) { - for (unsigned i = 0; i < count; ++i) ::push(&c, BytesPerWord, operand(&c)); + for (unsigned i = 0; i < count; ++i) { + MyOperand* a = operand(&c); + ::push(&c, BytesPerWord, a); + a->value = stackValue(&c, c.state->stack); + a->pushed = true; + } } virtual void popped(unsigned count) { - for (unsigned i = count; i > 0;) { + appendPop(&c, count, true); + + for (unsigned i = count; i;) { Stack* s = c.state->stack; c.state->stack = s->next; i -= s->size; diff --git a/src/x86.cpp b/src/x86.cpp index 7a435f9ef2..2b8f496f91 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -426,6 +426,20 @@ pushC(Context* c, unsigned size, Assembler::Constant* a) } } +void +moveAR(Context*, unsigned, Assembler::Address*, Assembler::Register* b); + +void +pushA(Context* c, unsigned size, Assembler::Address* a) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveAR(c, size, a, &tmp); + pushR(c, size, &tmp); + c->client->releaseTemporary(tmp.low); +} + void pushR(Context* c, unsigned size, Assembler::Register* a) { @@ -533,8 +547,8 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->low); - Assembler::Register bh(b->low); + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); moveRR(c, 4, a, b); moveRR(c, 4, &ah, &bh); @@ -679,6 +693,35 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) encode(c, 0x63, b->low, a, true); } +void +moveZMR(Context* c, unsigned size, Assembler::Memory* a, + Assembler::Register* b) +{ + switch (size) { + case 2: + encode2(c, 0x0fb7, b->low, a, true); + break; + + default: abort(c); // todo + } +} + +void +moveZRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + switch (size) { + case 2: + rex(c); + c->code.append(0x0f); + c->code.append(0xb7); + c->code.append(0xc0 | (a->low << 3) | b->low); + break; + + default: abort(c); // todo + } +} + void addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -725,6 +768,17 @@ subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x29); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) @@ -807,6 +861,30 @@ compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +compareRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); + + compareRR(c, 4, &ah, &bh); + + // 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); + + compareRR(c, 4, a, b); + } else { + if (size == 8) rex(c); + c->code.append(0x39); + c->code.append(0xc0 | (a->low << 3) | b->low); + } +} + void compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Memory* b) @@ -824,6 +902,27 @@ compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +compareRM(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + encode(c, 0x39, a->low, b, true); +} + +void +compareMM(Context* c, unsigned size UNUSED, Assembler::Memory* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + compareRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); +} + void populateTables() { @@ -848,6 +947,7 @@ populateTables() = CAST1(jumpIfLessOrEqualC); UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC); + UnaryOperations[INDEX1(Push, Address)] = CAST1(pushA); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); @@ -868,6 +968,9 @@ populateTables() BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); + BinaryOperations[INDEX2(MoveZ, Memory, Register)] = CAST2(moveZMR); + BinaryOperations[INDEX2(MoveZ, Register, Register)] = CAST2(moveZRR); + BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); @@ -876,9 +979,13 @@ populateTables() BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); + BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); + BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR); + BinaryOperations[INDEX2(Compare, Register, Memory)] = CAST2(compareRM); BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); + BinaryOperations[INDEX2(Compare, Memory, Memory)] = CAST2(compareMM); } class MyAssembler: public Assembler { From a51c4cef39831d3696f8431785ee66bb55648fcc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 16 Mar 2008 13:38:43 -0600 Subject: [PATCH 021/121] bugfixes --- src/compile.cpp | 36 ++++---- src/compiler.cpp | 208 ++++++++++++++++++++++++++--------------------- src/x86.cpp | 21 ++++- 3 files changed, 153 insertions(+), 112 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index f88dc2857a..9ebdc3d1fc 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2187,13 +2187,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Compiler::Operand* table; if (instruction == getstatic) { - c->call - (c->constant(reinterpret_cast(tryInitClass)), - context->indirection, - 0, - frame->trace(0, false), - 0, - 2, c->thread(), frame->append(fieldClass(t, field))); + if ((classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) + and (classVmFlags(t, fieldClass(t, field)) & InitFlag) == 0) + { + 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))); } else { @@ -3105,13 +3109,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object staticTable = 0; if (instruction == putstatic) { - c->call - (c->constant(reinterpret_cast(tryInitClass)), - context->indirection, - 0, - frame->trace(0, false), - 0, - 2, c->thread(), frame->append(fieldClass(t, field))); + if ((classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) + and (classVmFlags(t, fieldClass(t, field)) & InitFlag) == 0) + { + 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)); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 1d4ca71ed4..9057734c0a 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -40,7 +40,9 @@ class Value { virtual void acquire(Context*, Stack*, MyOperand*) { } virtual void release(Context*, MyOperand*) { } - virtual int registerValue(Context* c) { abort(c); } + virtual bool ready(Context*) { return true; } + + virtual int registerValue(Context*) { return NoRegister; } virtual int64_t constantValue(Context* c) { abort(c); } virtual void asAssemblerOperand(Context*, @@ -465,12 +467,25 @@ class AbstractMemoryValue: public MemoryValue { } } + virtual bool ready(Context* c) { + return base_->value->registerValue(c) != NoRegister + and (index_ == 0 or index_->value->registerValue(c) != NoRegister); + } + virtual int base(Context* c) { - return base_->value->registerValue(c); + int r = base_->value->registerValue(c); + assert(c, r != NoRegister); + return r; } virtual int index(Context* c) { - return index_ ? index_->value->registerValue(c) : NoRegister; + if (index_) { + int r = index_->value->registerValue(c); + assert(c, r != NoRegister); + return r; + } else { + return NoRegister; + } } MyOperand* base_; @@ -675,6 +690,81 @@ appendReturn(Context* c, unsigned size, MyOperand* value) new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } +void +syncStack(Context* c, Stack* start, unsigned count) +{ + Stack* segment[count]; + unsigned index = count; + for (Stack* s = start; s and index; s = s->next) { + segment[--index] = s; + } + + for (unsigned i = 0; i < count; ++i) { + Stack* s = segment[i]; + if (s->operand->value) { + apply(c, Push, s->size * BytesPerWord, s->operand->value); + s->operand->value->release(c, s->operand); + } else { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); + c->assembler->apply + (Subtract, BytesPerWord, Constant, &offset, Register, &stack); + } + s->operand->pushed = true; + s->operand->value = stackValue(c, s); + } +} + +void +syncStack(Context* c, Stack* start) +{ + unsigned count = 0; + for (Stack* s = start; s and (not s->operand->pushed); s = s->next) { + ++ count; + } + + syncStack(c, start, count); +} + +class PushEvent: public Event { + public: + PushEvent(Context* c): + Event(c), active(false) + { + assert(c, stack->operand->push == 0); + stack->operand->push = this; + } + + virtual Value* target(Context*, MyOperand*) { + return 0; + } + + virtual unsigned operandSize(Context*) { + return 0; + } + + virtual void compile(Context* c) { + fprintf(stderr, "PushEvent.compile\n"); + + if (active) { + fprintf(stderr, "PushEvent.compile: active\n"); + syncStack(c, stack); + } + } + + void markStack(Context*) { + active = true; + } + + bool active; +}; + +void +appendPush(Context* c) +{ + new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); +} + class CallEvent: public Event { public: CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags, @@ -724,7 +814,7 @@ class CallEvent: public Event { address->value->release(c, address); - if (result->event) { + if (result->event or (result->push and result->push->active)) { result->value = register_ (c, c->assembler->returnLow(), c->assembler->returnHigh()); result->value->acquire(c, stack, result); @@ -794,83 +884,6 @@ freeRegister(Context* c, unsigned size, bool allowAcquired) } } -void -syncStack(Context* c, Stack* start, unsigned count) -{ - Stack* segment[count]; - unsigned index = count; - for (Stack* s = start; s and index; s = s->next) { - segment[--index] = s; - } - - for (unsigned i = 0; i < count; ++i) { - Stack* s = segment[i]; - if (s->operand->value) { - apply(c, Push, s->size * BytesPerWord, s->operand->value); - s->operand->value->release(c, s->operand); - s->operand->pushed = true; - s->operand->value = stackValue(c, s); - } else { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); - c->assembler->apply - (Subtract, BytesPerWord, Constant, &offset, Register, &stack); - s->operand->pushed = true; - s->operand->value = stackValue(c, s); - } - } -} - -void -syncStack(Context* c, Stack* start) -{ - unsigned count = 0; - for (Stack* s = start; s and (not s->operand->pushed); s = s->next) { - ++ count; - } - - syncStack(c, start, count); -} - -class PushEvent: public Event { - public: - PushEvent(Context* c): - Event(c), active(false) - { - assert(c, stack->operand->push == 0); - stack->operand->push = this; - } - - virtual Value* target(Context* c, MyOperand*) { - abort(c); - } - - virtual unsigned operandSize(Context* c) { - abort(c); - } - - virtual void compile(Context* c) { - fprintf(stderr, "PushEvent.compile\n"); - - if (active) { - fprintf(stderr, "PushEvent.compile: active\n"); - syncStack(c, stack); - } - } - - void markStack() { - active = true; - } - - bool active; -}; - -void -appendPush(Context* c) -{ - new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); -} - class PopEvent: public Event { public: PopEvent(Context* c, unsigned count, bool ignore): @@ -901,14 +914,14 @@ class PopEvent: public Event { if (dst->event->operandSize(c) == BytesPerWord) { target = dst->event->target(c, dst); } - if (target == 0) { + if (target == 0 or (not target->ready(c))) { target = freeRegister(c, BytesPerWord * s->size, false); } - apply(c, Pop, BytesPerWord * s->size, target); - target->acquire(c, 0, dst); + apply(c, Pop, BytesPerWord * s->size, target); + dst->value = target; } else { ignored += s->size; @@ -983,22 +996,26 @@ class MoveEvent: public Event { { dst->value = src->value; return; - } else { - src->target = freeRegister(c, size, true); } } else if (type == Move - and (size == BytesPerWord or src->target->type(c) == Memory) + and (size == BytesPerWord + or src->target->type(c) == Memory) and src->target->equals(c, src->value)) { dst->value = src->value; return; } - apply(c, type, size, src->value, src->target); - src->value->release(c, src); + + if (src->target == 0 or (not src->target->ready(c))) { + src->target = freeRegister(c, size, false); + } + src->target->acquire(c, stack, dst); + apply(c, type, size, src->value, src->target); + dst->value = src->target; } @@ -1052,7 +1069,7 @@ class DupEvent: public Event { if (dst->event) { target = dst->event->target(c, dst); } - if (target == 0) { + if (target == 0 or (not target->ready(c))) { target = freeRegister(c, size, true); } @@ -1236,7 +1253,7 @@ class CombineEvent: public Event { if (a->target == 0) a->target = target(c, a); if (b->target == 0) b->target = target(c, b); - if (b->target == 0) { + if (b->target == 0 or (not b->target->ready(c))) { b->target = freeRegister(c, BytesPerWord, true); } @@ -1309,6 +1326,10 @@ class TranslateEvent: public Event { if (a->target == 0) a->target = target(c, a); + if (not a->target->ready(c)) { + a->target = a->value; + } + result->value->acquire(c, stack, result); if (a->target and not a->target->equals(c, a->value)) { @@ -1473,11 +1494,11 @@ pop(Context* c, unsigned size UNUSED) } void -markStack(Context*, Stack* stack) +markStack(Context* c, Stack* stack) { for (Stack* s = stack; s; s = s->next) { if (s->operand->push) { - s->operand->push->markStack(); + s->operand->push->markStack(c); } } } @@ -1703,7 +1724,6 @@ class MyCompiler: public Compiler { MyOperand* a = operand(&c); ::push(&c, BytesPerWord, a); a->value = stackValue(&c, c.state->stack); - a->pushed = true; } } diff --git a/src/x86.cpp b/src/x86.cpp index 2b8f496f91..308e25b6ae 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -553,11 +553,24 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, moveRR(c, 4, a, b); moveRR(c, 4, &ah, &bh); } else { - assert(c, BytesPerWord == 8 or size == 4); // todo + switch (size) { + case 1: + c->code.append(0xbe); + c->code.append(0xc0 | (a->low << 3) | b->low); + break; - rex(c); - c->code.append(0x89); - c->code.append(0xc0 | (a->low << 3) | b->low); + case 2: + c->code.append(0xbf); + c->code.append(0xc0 | (a->low << 3) | b->low); + break; + + case 8: + rex(c); + case 4: + c->code.append(0x89); + c->code.append(0xc0 | (a->low << 3) | b->low); + break; + } } } From b7ea937708919bd4623ca95175d8c667696086fd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 13 Apr 2008 12:54:50 -0600 Subject: [PATCH 022/121] rough sketch of refined compiler design --- src/compiler.cpp | 419 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 378 insertions(+), 41 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 9057734c0a..1eb5ecfafe 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -16,53 +16,390 @@ using namespace vm; namespace { class Context; -class MyOperand; -class ConstantValue; -class AddressValue; -class RegisterValue; -class MemoryValue; -class StackValue; -class Event; -class PushEvent; -class Stack; void NO_RETURN abort(Context* c); -class Value { +// scratch + +class Value: public Compiler::Operand { public: - virtual ~Value() { } - - virtual OperandType type(Context*) = 0; - - virtual bool equals(Context*, Value*) { return false; } - - virtual void preserve(Context*, Stack*, MyOperand*) { } - virtual void acquire(Context*, Stack*, MyOperand*) { } - virtual void release(Context*, MyOperand*) { } - - virtual bool ready(Context*) { return true; } - - virtual int registerValue(Context*) { return NoRegister; } - virtual int64_t constantValue(Context* c) { abort(c); } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) = 0; -}; - -class MyOperand: public Compiler::Operand { - public: - MyOperand(Value* value): - event(0), value(value), target(0), push(0), pushed(false) + Value(Site* site): + reads(0), sites(site), source(0), target(0) { } - Event* event; - Value* value; - Value* target; - PushEvent* push; - bool pushed; + Read* reads; + Site* sites; + Site* source; + Site* target; }; +class Event { + public: + Event(Context* c): next(0), stack(c->state->stack), promises(0) { + assert(c, c->logicalIp >= 0); + + if (c->event) { + c->event->next = this; + } + + if (c->logicalCode[c->logicalIp].firstEvent == 0) { + c->logicalCode[c->logicalIp].firstEvent = this; + } + + c->event = this; + } + + virtual ~Event() { } + + virtual void compile(Context* c) = 0; + + Event* next; + Stack* stack; + CodePromise* promises; +}; + +class Stack { + public: + Stack(Value* value, unsigned size, unsigned index, Stack* next): + value(value), size(size), index(index), next(next) + { } + + Value* value; + unsigned size; + unsigned index; + Stack* next; +}; + +class CallEvent: public Event { + public: + CallEvent(Context* c, Value* address, void* indirection, unsigned flags, + TraceHandler* traceHandler, Value* result, unsigned resultSize, + unsigned argumentCount): + Event(c), + address(address), + indirection(indirection), + flags(flags), + traceHandler(traceHandler), + result(result) + { + addRead(c, address, BytesPerWord, + (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); + + unsigned index = 0; + Stack* s = stack; + for (unsigned i = 0; i < argumentCount; ++i) { + addRead(c, s->value, s->size * BytesPerWord, + index < c->assembler->argumentRegisterCount() ? + registerSite(c, c->assembler->argumentRegister(index)) : + stackSite(c, s)); + index += s->size; + s = s->next; + } + + if (result) { + addWrite(c, result, resultSize); + } + } + + virtual void compile(Context* c) { + fprintf(stderr, "CallEvent.compile\n"); + + UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); + if (indirection) { + apply(c, type, BytesPerWord, + constantSite(c, reinterpret_cast(indirection))); + } else { + apply(c, type, BytesPerWord, address->source); + } + + if (traceHandler) { + traceHandler->handleTrace + (new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, c->assembler->length())); + } + } + + Value* address; + void* indirection; + unsigned flags; + TraceHandler* traceHandler; + Value* result; +}; + +void +appendCall(Context* c, Value* address, void* indirection, unsigned flags, + TraceHandler* traceHandler, Value* result, unsigned argumentCount) +{ + new (c->zone->allocate(sizeof(CallEvent))) + CallEvent(c, address, indirection, flags, traceHandler, result, + argumentCount); +} + +class ReturnEvent: public Event { + public: + ReturnEvent(Context* c, unsigned size, Value* value): + Event(c), value(value) + { + if (value) { + addRead(c, value, size, registerSite + (c, c->assembler->returnLow(), + size > BytesPerWord ? + c->assembler->returnHigh() : NoRegister)); + } + } + + virtual void compile(Context* c) { + fprintf(stderr, "ReturnEvent.compile\n"); + + Assembler::Register base(c->assembler->base()); + Assembler::Register stack(c->assembler->stack()); + + c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack); + c->assembler->apply(Pop, BytesPerWord, Register, &base); + c->assembler->apply(Return); + } + + Value* value; +}; + +void +appendReturn(Context* c, unsigned size, MyOperand* value) +{ + new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); +} + +class MoveEvent: public Event { + public: + MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src, + Value* dst): + Event(c), type(type), size(size), src(src), dst(dst) + { + addRead(c, src, size, 0); + addWrite(c, dst, size); + } + + virtual void compile(Context* c) { + fprintf(stderr, "MoveEvent.compile\n"); + + apply(c, type, size, src->source, dst->target); + } + + BinaryOperation type; + unsigned size; + Value* src; + Value* dst; +}; + +void +appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, + Value* dst) +{ + new (c->zone->allocate(sizeof(MoveEvent))) + MoveEvent(c, type, size, src, dst); +} + +class CompareEvent: public Event { + public: + CompareEvent(Context* c, unsigned size, Value* first, Value* second): + Event(c), size(size), first(first), second(second) + { + addRead(c, first, size, 0); + addRead(c, second, size, 0); + } + + + virtual void compile(Context* c) { + fprintf(stderr, "CompareEvent.compile\n"); + + apply(c, Compare, size, first->source, second->source); + } + + unsigned size; + Value* first; + Value* second; +}; + +void +appendCompare(Context* c, unsigned size, Value* first, Value* second) +{ + new (c->zone->allocate(sizeof(CompareEvent))) + CompareEvent(c, size, first, second); +} + +class BranchEvent: public Event { + public: + BranchEvent(Context* c, UnaryOperation type, Value* address): + Event(c), type(type), address(address) + { + addRead(c, address, BytesPerWord, 0); + } + + virtual void compile(Context* c) { + fprintf(stderr, "BranchEvent.compile\n"); + + apply(c, type, BytesPerWord, address->source); + } + + UnaryOperation type; + Value* address; +}; + +void +appendBranch(Context* c, UnaryOperation type, Value* address) +{ + new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); +} + +class JumpEvent: public Event { + public: + JumpEvent(Context* c, Value* address): + Event(c), + address(address) + { + addRead(c, address, BytesPerWord, 0); + } + + virtual void compile(Context* c) { + fprintf(stderr, "JumpEvent.compile\n"); + + apply(c, Jump, BytesPerWord, address->source); + } + + Value* address; +}; + +void +appendJump(Context* c, Value* address) +{ + new (c->zone->allocate(sizeof(JumpEvent))) JumpEvent(c, address); +} + +class CombineEvent: public Event { + public: + CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, + Value* second, Value* result): + Event(c), type(type), size(size), first(first), second(second), + result(result) + { + Assembler::Register r1(NoRegister); + Assembler::Register r2(NoRegister); + c->assembler->getTargets(type, size, &r1, &r2); + + addRead(c, first, size, + r1.low == NoRegister ? 0 : registerSite(c, r1.low, r1.high)); + addRead(c, second, size, + r2.low == NoRegister ? + valueSite(c, result) : registerSite(c, r2.low, r2.high)); + addWrite(c, result, size); + } + + virtual void compile(Context* c) { + fprintf(stderr, "CombineEvent.compile\n"); + + apply(c, type, size, first->source, second->source); + } + + BinaryOperation type; + unsigned size; + Value* first; + Value* second; + MyOperand* result; +}; + +void +appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, + Value* second, Value* result) +{ + new (c->zone->allocate(sizeof(CombineEvent))) + CombineEvent(c, type, size, first, second, result); +} + +class TranslateEvent: public Event { + public: + TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value, + Value* result): + Event(c), type(type), size(size), value(value), result(result) + { + addRead(c, value, size, valueSite(c, result)); + addWrite(c, result, size); + } + + virtual void compile(Context* c) { + fprintf(stderr, "TranslateEvent.compile\n"); + + apply(c, type, size, value->source); + } + + UnaryOperation type; + unsigned size; + Value* value; + Value* result; +}; + +void +appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, + Value* result) +{ + new (c->zone->allocate(sizeof(TranslateEvent))) + TranslateEvent(c, type, size, value, result); +} + +class MemoryEvent: public Event { + public: + MemoryEvent(Context* c, Value* base, Value* index, Value* result): + Event(c), base(base), index(index), result(result) + { + addRead(c, base, BytesPerWord, anyRegisterSite(c)); + if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c)); + addWrite(c, BytesPerWord, size); + } + + virtual void compile(Context*) { + fprintf(stderr, "MemoryEvent.compile\n"); + } + + Value* base; + Value* index; + Value* result; +}; + +void +appendMemory(Context* c, Value* base, Value* index, Value* result) +{ + new (c->zone->allocate(sizeof(MemoryEvent))) + MemoryEvent(c, base, index, result); +} + + +void +compile(Context* c) +{ + Assembler* a = c->assembler; + + Assembler::Register base(a->base()); + Assembler::Register stack(a->stack()); + a->apply(Push, BytesPerWord, Register, &base); + a->apply(Move, BytesPerWord, Register, &stack, Register, &base); + + if (c->stackOffset) { + Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); + a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack); + } + + for (Event* e = c->firstEvent; e; e = e->next) { + LogicalInstruction* li = c->logicalCode + e->logicalIp; + li->machineOffset = a->length(); + + e->compile(c); + + for (CodePromise* p = e->promises; p; p = p->next) { + p->offset = a->length(); + } + } +} + +// end scratch + class Stack { public: Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next): @@ -998,8 +1335,8 @@ class MoveEvent: public Event { return; } } else if (type == Move - and (size == BytesPerWord - or src->target->type(c) == Memory) + and size == BytesPerWord + and src->target->type(c) == Register and src->target->equals(c, src->value)) { dst->value = src->value; From f85510c4c4e5c5a59a7ec0ec6f5832912e0335bc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 16 Apr 2008 14:58:21 -0600 Subject: [PATCH 023/121] more work on design sketch of new compiler --- src/compiler.cpp | 304 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 276 insertions(+), 28 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 8d00643b54..ed66eed911 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -16,11 +16,240 @@ using namespace vm; namespace { class Context; +class Value; -void NO_RETURN abort(Context* c); +void NO_RETURN abort(Context*); // scratch +class Site { + public: + Site(): next(0) { } + + virtual ~Site() { } + + virtual unsigned copyCost(Context*, Site*) = 0; + + virtual void copyTo(Context*, unsigned, Site*) = 0; + + virtual void acquire(Context*, unsigned, Value*, Site*) { } + + virtual void asAssemblerOperand(Context*, + OperandType* type, + Assembler::Operand** operand) = 0; + + Site* next; +}; + +class ConstantSite: public Site { + public: + ConstantSite(Promise* value): value(value) { } + + virtual unsigned copyCost(Context*, Site*) { + return 1; + } + + virtual void copyTo(Context* c, unsigned size, Site* dst) { + apply(c, Move, size, this, dst); + } + + virtual OperandType type(Context*) { + return Constant; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return &value; + } + + Assembler::Constant value; +}; + +ConstantSite* +constantSite(Context* c, Promise* value) +{ + return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value); +} + +ResolvedPromise* +resolved(Context* c, int64_t value) +{ + return new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value); +} + +ConstantSite* +constantSite(Context* c, int64_t value) +{ + return constantSite(c, resolved(c, value)); +} + +class AddressSite: public Site { + public: + AddressSite(Promise* address): address(address) { } + + virtual unsigned copyCost(Context*, Site*) { + return 3; + } + + virtual void copyTo(Context* c, unsigned size, Site* dst) { + apply(c, Move, size, this, dst); + } + + virtual OperandType type(Context*) { + return Address; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return &address; + } + + Assembler::Address address; +}; + +AddressSite* +addressSite(Context* c, Promise* address) +{ + return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); +} + +void +acquire(Context* c, int r, unsigned newSize, Value* newValue, Site* newSite) +{ + Value* oldValue = c->registers[r].value; + if (oldValue) { + for (Site** p = &(oldValue->sites); *p;) { + if (c->registers[r].site == *p) { + site = *p; + *p = (*p)->next; + break; + } else { + p = &((*p)->next); + } + } + + if (old->sites == 0 and old->reads) { + apply(c, Push, c->registers[r].size, c->registers[r].site); + old->sites = ???; + } + } + + c->registers[r].size = newSize; + c->registers[r].value = newValue; + c->registers[r].site = newSite; +} + +class RegisterSite: public Site { + public: + RegisterSite(int low, int high): register_(low, high) { } + + virtual unsigned copyCost(Context* c, Site* s) { + if (s and + (this == s or + (s->type(c) == Register + and static_cast(s)->register_.low + == register_.low + and static_cast(s)->register_.high + == register_.high))) + { + return 0; + } else { + return 2; + } + } + + virtual void copyTo(Context* c, unsigned size, Site* dst) { + apply(c, Move, size, this, dst); + } + + virtual void acquire(Context* c, unsigned size, Value* v, Site* s) { + ::acquire(c, register_.low, size, v, s); + if (register_.high >= 0) ::acquire(c, register_.high, size, v, s); + } + + virtual OperandType type(Context*) { + return Register; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return ®ister_; + } + + Assembler::Register register_; +}; + +RegisterSite* +registerSite(Context* c, int low, int high = NoRegister) +{ + return new (c->zone->allocate(sizeof(RegisterSite))) + RegisterSite(low, high); +} + +class MemorySite: public Site { + public: + RegisterSite(int base, int offset, int index, unsigned scale): + value(base, offset, index, scale) + { } + + virtual unsigned copyCost(Context* c, Site* s) { + if (s and + (this == s or + (o->type(c) == Memory + and static_cast(o)->value.base == value.base + and static_cast(o)->value.offset == value.offset + and static_cast(o)->value.index == value.index + and static_cast(o)->value.scale == value.scale))) + { + return 0; + } else { + return 4; + } + } + + virtual void copyTo(Context* c, unsigned size, Site* dst) { + apply(c, Move, size, this, dst); + } + + virtual OperandType type(Context*) { + return Memory; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return &value; + } + + Assembler::Memory value; +}; + +MemorySite* +memorySite(Context* c, int base, int offset, int index, unsigned scale) +{ + return new (c->zone->allocate(sizeof(MemorySite))) + MemorySite(base, offset, index, scale); +} + +class Read { + public: + Read(unsigned size, Value* value, Site* target): + size(size), value(value), target(target), next(0) + { } + + unsigned size; + Value* value; + Site* target; + Read* next; +}; + +class Write { + public: + Write(unsigned size, Value* value): + size(size), value(value), next(0) + { } + + unsigned size; + Value* value; + Write* next; +}; + class Value: public Compiler::Operand { public: Value(Site* site): @@ -142,9 +371,9 @@ class ReturnEvent: public Event { { if (value) { addRead(c, value, size, registerSite - (c, c->assembler->returnLow(), - size > BytesPerWord ? - c->assembler->returnHigh() : NoRegister)); + (c, c->assembler->returnLow(), + size > BytesPerWord ? + c->assembler->returnHigh() : NoRegister)); } } @@ -250,30 +479,6 @@ appendBranch(Context* c, UnaryOperation type, Value* address) new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); } -class JumpEvent: public Event { - public: - JumpEvent(Context* c, Value* address): - Event(c), - address(address) - { - addRead(c, address, BytesPerWord, 0); - } - - virtual void compile(Context* c) { - fprintf(stderr, "JumpEvent.compile\n"); - - apply(c, Jump, BytesPerWord, address->source); - } - - Value* address; -}; - -void -appendJump(Context* c, Value* address) -{ - new (c->zone->allocate(sizeof(JumpEvent))) JumpEvent(c, address); -} - class CombineEvent: public Event { public: CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, @@ -370,6 +575,13 @@ appendMemory(Context* c, Value* base, Value* index, Value* result) MemoryEvent(c, base, index, result); } +void +addSite(Context* c, int size, Value* v, Site* s) +{ + s->acquire(c, size, v, s); + s->next = v->sites; + v->sites = s; +} void compile(Context* c) @@ -390,6 +602,42 @@ compile(Context* c) LogicalInstruction* li = c->logicalCode + e->logicalIp; li->machineOffset = a->length(); + for (Read* r = e->reads; r; r = r->next) { + Site* site = 0; + unsigned copyCost = Site::MaxCopyCost; + for (Site* s = r->value->sites; s; s = s->next) { + unsigned c = s->copyCost(c, r->target); + if (c < copyCost) { + site = s; + copyCost = c; + } + } + + if (r->target) { + if (copyCost) { + addSite(c, r->size, r->value, r->target); + + site->copyTo(c, r->size, r->target); + } + + r->value->source = r->target; + } else { + r->value->source = site; + } + + r->value->reads = r->value->reads->next; + } + + for (Write* w = e->writes; w; w = w->next) { + if (w->value->reads and w->value->reads->target) { + w->value->target = w->value->reads->target; + } else { + w->value->target = freeRegister(c, w->size); + } + + addSite(c, w->size, w->value, w->value->target); + } + e->compile(c); for (CodePromise* p = e->promises; p; p = p->next) { From 3f45d395826a6d3288dbffc63225c39f1e1b77f0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 16 Apr 2008 20:55:38 -0600 Subject: [PATCH 024/121] more compiler work --- src/assembler.h | 9 +- src/compiler.cpp | 1938 +++++++++++----------------------------------- 2 files changed, 477 insertions(+), 1470 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index e3129bd2ee..5b2a3b30d1 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -51,10 +51,11 @@ enum BinaryOperation { const unsigned BinaryOperationCount = Xor + 1; enum OperandType { - Constant, - Address, - Register, - Memory + ConstantOperand, + AddressOperand, + RegisterOperand, + MemoryOperand, + StackOperand }; const unsigned OperandTypeCount = Memory + 1; diff --git a/src/compiler.cpp b/src/compiler.cpp index ed66eed911..f17209ca41 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -20,23 +20,27 @@ class Value; void NO_RETURN abort(Context*); -// scratch - class Site { public: Site(): next(0) { } virtual ~Site() { } + virtual Site* resolve(Context*) { return this; } + virtual unsigned copyCost(Context*, Site*) = 0; - virtual void copyTo(Context*, unsigned, Site*) = 0; + virtual void accept(Context* c, unsigned size, Site* src) { + apply(c, Move, size, src, this); + } - virtual void acquire(Context*, unsigned, Value*, Site*) { } + virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) = 0; + virtual OperandType type(Context*) { + return Constant; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; Site* next; }; @@ -49,10 +53,6 @@ class ConstantSite: public Site { return 1; } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - virtual OperandType type(Context*) { return Constant; } @@ -91,10 +91,6 @@ class AddressSite: public Site { return 3; } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - virtual OperandType type(Context*) { return Address; } @@ -112,25 +108,85 @@ addressSite(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); } +Site* +pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) +{ + Site* site = 0; + unsigned copyCost = 0xFFFFFFFF; + for (Site* s = sites; s; s = s->next) { + unsigned c = s->copyCost(c, target); + if (c < copyCost) { + site = s; + copyCost = c; + } + } + + if (cost) *cost = copyCost; + return site; +} + void -acquire(Context* c, int r, unsigned newSize, Value* newValue, Site* newSite) +syncStack(Context* c, Stack* start, unsigned count) +{ + Stack* segment[count]; + unsigned index = count; + for (Stack* s = start; s and index; s = s->next) { + segment[--index] = s; + } + + for (unsigned i = 0; i < count; ++i) { + Stack* s = segment[i]; + + if (s->value) { + apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); + + StackSite* site = stackSite(c, s); + site->next = s->value->sites; + s->value->sites = site; + } else { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); + c->assembler->apply + (Subtract, BytesPerWord, Constant, &offset, Register, &stack); + } + + s->pushed = true; + } +} + +void +acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, + Site* newSite) { Value* oldValue = c->registers[r].value; if (oldValue) { + if (old->sites->next == 0 and old->reads) { + assert(c, old->sites == oldValue->sites); + + unsigned count = 0; + Stack* start = 0; + for (Stack* s = stack; s and not s->pushed; s = s->next) { + if (s->value == old) { + start = s; + } + if (start) { + ++ count; + } + } + + assert(c, start); + + syncStack(c, start, count); + } + for (Site** p = &(oldValue->sites); *p;) { if (c->registers[r].site == *p) { - site = *p; *p = (*p)->next; break; } else { p = &((*p)->next); } } - - if (old->sites == 0 and old->reads) { - apply(c, Push, c->registers[r].size, c->registers[r].site); - old->sites = ???; - } } c->registers[r].size = newSize; @@ -157,13 +213,11 @@ class RegisterSite: public Site { } } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - - virtual void acquire(Context* c, unsigned size, Value* v, Site* s) { - ::acquire(c, register_.low, size, v, s); - if (register_.high >= 0) ::acquire(c, register_.high, size, v, s); + virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, + Site* s) + { + ::acquire(c, register_.low, stack, size, v, s); + if (register_.high >= 0) ::acquire(c, register_.high, stack, size, v, s); } virtual OperandType type(Context*) { @@ -186,7 +240,7 @@ registerSite(Context* c, int low, int high = NoRegister) class MemorySite: public Site { public: - RegisterSite(int base, int offset, int index, unsigned scale): + MemorySite(int base, int offset, int index, unsigned scale): value(base, offset, index, scale) { } @@ -205,10 +259,6 @@ class MemorySite: public Site { } } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - virtual OperandType type(Context*) { return Memory; } @@ -227,41 +277,317 @@ memorySite(Context* c, int base, int offset, int index, unsigned scale) MemorySite(base, offset, index, scale); } +class ValueSite: public Site { + public: + ValueSite(Value* value): value(value) { } + + virtual Site* resolve(Context* c) { + return value->sites; + } + + virtual unsigned copyCost(Context* c, Site*) { + abort(c); + } + + virtual void copyTo(Context* c, unsigned, Site*) { + abort(c); + } + + virtual OperandType type(Context* c) { + abort(c); + } + + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + abort(c); + } + + Value* value; +}; + +ValueSite* +valueSite(Context* c, Value* v) +{ + return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v); +} + +class StackSite: public Site { + public: + StackSite(Stack* stack): stack(stack) { } + + virtual unsigned copyCost(Context*, Site*) { + return 5; + } + + virtual void accept(Context* c, unsigned size, Site* src) { + apply(c, Push, size, src); + } + + virtual OperandType type(Context*) { + return StackOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + abort(c); + } + + Stack* stack; +}; + +StackSite* +stackSite(Context* c, Stack* s) +{ + return new (c->zone->allocate(sizeof(StackSite))) StackSite(s); +} + +class Stack { + public: + Stack(Value* value, unsigned size, unsigned index, Stack* next): + value(value), size(size), index(index), next(next) + { } + + Value* value; + unsigned size; + unsigned index; + Stack* next; +}; + +class State { + public: + State(State* s): + stack(s ? s->stack : 0), + next(s) + { } + + Stack* stack; + State* next; +}; + +class LogicalInstruction { + public: + unsigned visits; + Event* firstEvent; + Event* lastEvent; + unsigned machineOffset; + int predecessor; +}; + +class Register { + public: + Value* value; + Site* site; + unsigned size; + bool reserved; +}; + +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(Register) * assembler->registerCount()))), + firstConstant(0), + lastConstant(0), + constantCount(0), + junctions(0), + machineCode(0) + { + memset(registers, 0, sizeof(Register) * 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; + Register* 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); +} + class Read { public: - Read(unsigned size, Value* value, Site* target): - size(size), value(value), target(target), next(0) + Read(unsigned size, Value* value, Site* target, Read* next, Read* eventNext): + size(size), value(value), target(target), next(next), eventNext(eventNext) { } unsigned size; Value* value; Site* target; Read* next; + Read* eventNext; }; class Write { public: - Write(unsigned size, Value* value): - size(size), value(value), next(0) + Write(unsigned size, Value* value, Write* eventNext): + size(size), value(value), eventNext(eventNext) { } unsigned size; Value* value; - Write* next; + Write* eventNext; }; class Value: public Compiler::Operand { public: Value(Site* site): - reads(0), sites(site), source(0), target(0) + reads(0), lastRead(0), sites(site), source(0), target(0) { } Read* reads; + Read* lastRead; Site* sites; Site* source; Site* target; }; +void +apply(Context* c, UnaryOperation op, unsigned size, Value* a) +{ + OperandType type = a->type(c); + Assembler::Operand* operand = a->asAssemblerOperand(c); + + c->assembler->apply(op, size, type, operand); +} + +void +apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b) +{ + OperandType aType = a->type(c); + Assembler::Operand* aOperand = a->asAssemblerOperand(c); + + OperandType bType = b->type(c); + Assembler::Operand* bOperand = b->asAssemblerOperand(c); + + 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 + pad(c->assembler->length()) + (key * BytesPerWord)); + } + + 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) { } + + CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } + + 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; +}; + class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0) { @@ -299,6 +625,28 @@ class Stack { Stack* next; }; +void +addRead(Context* c, Value* v, unsigned size, Site* target) +{ + Read* r = new (c->zone->allocate(sizeof(Read))) + Read(v, size, target, 0, c->event-reads); + c->event->reads = r; + + if (v->lastRead) { + r->lastRead->next = r; + } else { + v->reads = r; + } + v->lastRead = r; +} + +void +addWrite(Context* c, Value* v, unsigned size) +{ + c->event->writes = new (c->zone->allocate(sizeof(Write))) + Write(v, size, c->event->writes); +} + class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, @@ -576,13 +924,26 @@ appendMemory(Context* c, Value* base, Value* index, Value* result) } void -addSite(Context* c, int size, Value* v, Site* s) +addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { - s->acquire(c, size, v, s); + s->acquire(c, stack, size, v, s); s->next = v->sites; v->sites = s; } +Site* +target(Context* c, unsigned size, Value* value) +{ + if (value->reads + and value->reads->target + and not value->reads->target->type(c) == StackOperand) + { + return value->reads->target; + } else { + return freeRegister(c, size); + } +} + void compile(Context* c) { @@ -602,25 +963,36 @@ compile(Context* c) LogicalInstruction* li = c->logicalCode + e->logicalIp; li->machineOffset = a->length(); - for (Read* r = e->reads; r; r = r->next) { - Site* site = 0; - unsigned copyCost = Site::MaxCopyCost; - for (Site* s = r->value->sites; s; s = s->next) { - unsigned c = s->copyCost(c, r->target); - if (c < copyCost) { - site = s; - copyCost = c; + for (Read* r = e->reads; r; r = r->eventNext) { + Site* target = (r->target ? r->target->resolve(c) : 0); + + unsigned copyCost; + Site* site = pick(c, r->value->sites, target, ©Cost); + + if (site->type(c) == StackOperand) { + for (Stack* s = e->stack; s; s = s->next) { + if (s->pushed) { + target = ::target(t, s->size * BytesPerWord, s->value); + + addSite(c, e->stack, s->size * BytesPerWord, s->value, target); + + s->pushed = false; + if (s == static_cast(site)->stack) { + site = pick(c, r->value->sites, target, ©Cost); + break; + } + } } } - if (r->target) { + if (target) { if (copyCost) { - addSite(c, r->size, r->value, r->target); + addSite(c, e->stack, r->size, r->value, target); - site->copyTo(c, r->size, r->target); + target->accept(c, r->size, site); } - r->value->source = r->target; + r->value->source = target; } else { r->value->source = site; } @@ -628,14 +1000,10 @@ compile(Context* c) r->value->reads = r->value->reads->next; } - for (Write* w = e->writes; w; w = w->next) { - if (w->value->reads and w->value->reads->target) { - w->value->target = w->value->reads->target; - } else { - w->value->target = freeRegister(c, w->size); - } + for (Write* w = e->writes; w; w = w->eventNext) { + w->value->target = target(t, w->size, w->value); - addSite(c, w->size, w->value, w->value->target); + addSite(c, e->stack, w->size, w->value, w->value->target); } e->compile(c); @@ -646,1376 +1014,6 @@ compile(Context* c) } } -// end scratch - -class Stack { - public: - Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next): - operand(operand), size(size), index(index), next(next) - { } - - MyOperand* operand; - unsigned size; - unsigned index; - Stack* next; -}; - -class State { - public: - State(State* s): - stack(s ? s->stack : 0), - next(s) - { } - - Stack* 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 PoolPromise: public Promise { - public: - PoolPromise(Context* c, int key): c(c), key(key) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + pad(c->assembler->length()) + (key * BytesPerWord)); - } - - 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) { } - - CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } - - 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, bool allowAcquired); - -class ConstantValue: public Value { - public: - ConstantValue(Promise* value): value(value) { } - - virtual OperandType type(Context*) { return Constant; } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Constant; - *operand = &value; - } - - virtual int64_t constantValue(Context*) { - return value.value->value(); - } - - Assembler::Constant value; -}; - -ConstantValue* -constant(Context* c, Promise* value) -{ - return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); -} - -ResolvedPromise* -resolved(Context* c, int64_t value) -{ - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); -} - -ConstantValue* -constant(Context* c, int64_t value) -{ - return constant(c, resolved(c, value)); -} - -class AddressValue: public Value { - public: - AddressValue(Promise* address): address(address) { } - - virtual OperandType type(Context*) { return Address; } - - 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*, Stack*, int, MyOperand*); - -class RegisterValue: public Value { - public: - RegisterValue(int low, int high): register_(low, high) { } - - virtual OperandType type(Context*) { return Register; } - - virtual bool equals(Context* c, Value* o) { - return this == o or - (o->type(c) == Register - and static_cast(o)->register_.low == register_.low - and static_cast(o)->register_.high == register_.high); - } - - virtual void preserve(Context* c, Stack* s, MyOperand* a) { - ::preserve(c, s, register_.low, a); - if (register_.high >= 0) ::preserve(c, s, register_.high, a); - } - - virtual void acquire(Context* c, Stack* s, MyOperand* a) { - if (a != c->registers[register_.low].operand) { - fprintf(stderr, "%p acquire %d\n", a, register_.low); - - preserve(c, s, a); - c->registers[register_.low].operand = a; - if (register_.high >= 0) { - c->registers[register_.high].operand = a; - } - } - } - - virtual void release(Context* c, MyOperand* a) { - if (a == c->registers[register_.low].operand) { - fprintf(stderr, "%p release %d\n", a, register_.low); - - c->registers[register_.low].operand = 0; - if (register_.high >= 0) c->registers[register_.high].operand = 0; - } - } - - virtual int registerValue(Context*) { - return register_.low; - } - - 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): - value(base, offset, index, scale) - { } - - virtual OperandType type(Context*) { return Memory; } - - virtual bool equals(Context* c, Value* o) { - return this == o or - (o->type(c) == Memory - and static_cast(o)->value.base == value.base - and static_cast(o)->value.offset == value.offset - and static_cast(o)->value.index == value.index - and static_cast(o)->value.scale == value.scale); - } - - 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; -}; - -class AbstractMemoryValue: public MemoryValue { - public: - AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, - unsigned scale): - MemoryValue(NoRegister, offset, NoRegister, scale), - base_(base), index_(index) - { } - - virtual void preserve(Context* c, Stack* s, MyOperand*) { - base_->value->preserve(c, s, base_); - if (index_) { - index_->value->preserve(c, s, index_); - } - } - - virtual void release(Context* c, MyOperand*) { - base_->value->release(c, base_); - if (index_) { - index_->value->release(c, index_); - } - } - - virtual bool ready(Context* c) { - return base_->value->registerValue(c) != NoRegister - and (index_ == 0 or index_->value->registerValue(c) != NoRegister); - } - - virtual int base(Context* c) { - int r = base_->value->registerValue(c); - assert(c, r != NoRegister); - return r; - } - - virtual int index(Context* c) { - if (index_) { - int r = index_->value->registerValue(c); - assert(c, r != NoRegister); - return r; - } else { - return NoRegister; - } - } - - MyOperand* base_; - MyOperand* index_; -}; - -AbstractMemoryValue* -memory(Context* c, MyOperand* base, int offset, MyOperand* index, - unsigned scale) -{ - return new (c->zone->allocate(sizeof(AbstractMemoryValue))) - AbstractMemoryValue(base, offset, index, scale); -} - -class StackValue: public Value { - public: - StackValue(Context* c, Stack* stack): - stack(stack), - value - (c->assembler->base(), - - (c->stackOffset + stack->index + 1) * BytesPerWord, - NoRegister, 0, 0) - { } - - virtual OperandType type(Context*) { return Memory; } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Memory; - *operand = &value; - } - - Stack* stack; - Assembler::Memory value; -}; - -StackValue* -stackValue(Context* c, Stack* stack) -{ - return new (c->zone->allocate(sizeof(StackValue))) StackValue(c, stack); -} - -class Event { - public: - Event(Context* c): next(0), stack(c->state->stack), promises(0) { - assert(c, c->logicalIp >= 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 unsigned operandSize(Context* c) = 0; - virtual void compile(Context* c) = 0; - virtual bool isCritical(Context*) { return false; } - - Event* next; - Stack* stack; - CodePromise* promises; -}; - -class NullEvent: public Event { - public: - NullEvent(Context* c): - Event(c) - { } - - virtual Value* target(Context*, MyOperand*) { - return 0; - } - - virtual unsigned operandSize(Context*) { - return 0; - } - - virtual void compile(Context*) { - // ignore - } -}; - -void -setEvent(Context* c, MyOperand* a, Event* e) -{ - if (a->event) { - a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c); - } else{ - a->event = e; - } -} - -class ArgumentEvent: public Event { - public: - ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): - Event(c), size(size), a(a), index(index) - { - setEvent(c, a, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == a); - - if (index < c->assembler->argumentRegisterCount()) { - return register_(c, c->assembler->argumentRegister(index)); - } else { - return 0; - } - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "ArgumentEvent.compile\n"); - - if (a->target == 0) a->target = target(c, a); - - if (a->target == 0) { - apply(c, Push, size, a->value); - a->value = 0; - } else { - if (not a->target->equals(c, a->value)) { - a->target->preserve(c, stack, a); - apply(c, Move, size, a->value, a->target); - } - a->value->release(c, a); - } - } - - unsigned size; - MyOperand* a; - unsigned index; -}; - -void -appendArgument(Context* c, unsigned size, MyOperand* value, unsigned index) -{ - new (c->zone->allocate(sizeof(ArgumentEvent))) - ArgumentEvent(c, size, value, index); -} - -class ReturnEvent: public Event { - public: - ReturnEvent(Context* c, unsigned size, MyOperand* a): - Event(c), size(size), a(a) - { - if (a) { - setEvent(c, a, this); - } - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == a); - - return register_(c, c->assembler->returnLow(), c->assembler->returnHigh()); - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "ReturnEvent.compile\n"); - - if (a) { - if (a->target == 0) a->target = target(c, a); - - if (not a->target->equals(c, a->value)) { - apply(c, Move, size, a->value, a->target); - } - a->value->release(c, a); - } - - Assembler::Register base(c->assembler->base()); - Assembler::Register stack(c->assembler->stack()); - - c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack); - c->assembler->apply(Pop, BytesPerWord, Register, &base); - c->assembler->apply(Return); - } - - unsigned size; - MyOperand* a; -}; - -void -appendReturn(Context* c, unsigned size, MyOperand* value) -{ - new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); -} - -void -syncStack(Context* c, Stack* start, unsigned count) -{ - Stack* segment[count]; - unsigned index = count; - for (Stack* s = start; s and index; s = s->next) { - segment[--index] = s; - } - - for (unsigned i = 0; i < count; ++i) { - Stack* s = segment[i]; - if (s->operand->value) { - apply(c, Push, s->size * BytesPerWord, s->operand->value); - s->operand->value->release(c, s->operand); - } else { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); - c->assembler->apply - (Subtract, BytesPerWord, Constant, &offset, Register, &stack); - } - s->operand->pushed = true; - s->operand->value = stackValue(c, s); - } -} - -void -syncStack(Context* c, Stack* start) -{ - unsigned count = 0; - for (Stack* s = start; s and (not s->operand->pushed); s = s->next) { - ++ count; - } - - syncStack(c, start, count); -} - -class PushEvent: public Event { - public: - PushEvent(Context* c): - Event(c), active(false) - { - assert(c, stack->operand->push == 0); - stack->operand->push = this; - } - - virtual Value* target(Context*, MyOperand*) { - return 0; - } - - virtual unsigned operandSize(Context*) { - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "PushEvent.compile\n"); - - if (active) { - fprintf(stderr, "PushEvent.compile: active\n"); - syncStack(c, stack); - } - } - - void markStack(Context*) { - active = true; - } - - bool active; -}; - -void -appendPush(Context* c) -{ - new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); -} - -class CallEvent: public Event { - public: - CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, MyOperand* result): - Event(c), - address(address), - indirection(indirection), - flags(flags), - traceHandler(traceHandler), - result(result) - { - setEvent(c, address, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == address); - - if (indirection) { - return register_(c, c->assembler->returnLow(), NoRegister); - } else { - return 0; - } - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual void compile(Context* c) { - fprintf(stderr, "CallEvent.compile\n"); - - if (indirection and address->target == 0) { - address->target = target(c, address); - } - - UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); - - if (indirection) { - if (not address->target->equals(c, address->value)) { - apply(c, Move, BytesPerWord, address->value, address->target); - } - apply(c, type, BytesPerWord, - constant(c, reinterpret_cast(indirection))); - } else { - apply(c, type, BytesPerWord, address->value); - } - - address->value->release(c, address); - - if (result->event or (result->push and result->push->active)) { - result->value = register_ - (c, c->assembler->returnLow(), c->assembler->returnHigh()); - result->value->acquire(c, stack, result); - } - - if (traceHandler) { - traceHandler->handleTrace - (new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, c->assembler->length())); - } - } - - MyOperand* address; - void* indirection; - unsigned flags; - TraceHandler* traceHandler; - MyOperand* result; -}; - -void -appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, MyOperand* result) -{ - new (c->zone->allocate(sizeof(CallEvent))) - CallEvent(c, address, indirection, flags, traceHandler, result); -} - -int -freeRegisterExcept(Context* c, int except, bool allowAcquired) -{ - for (int i = c->assembler->registerCount(); i >= 0; --i) { - if (i != except - and (not c->registers[i].reserved) - and c->registers[i].operand == 0) - { - return i; - } - } - - if (allowAcquired) { - for (int i = c->assembler->registerCount(); i >= 0; --i) { - if (i != except - and (not c->registers[i].reserved)) - { - return i; - } - } - } - - abort(c); -} - -inline int -freeRegister(Context* c, bool allowAcquired) -{ - return freeRegisterExcept(c, NoRegister, allowAcquired); -} - -RegisterValue* -freeRegister(Context* c, unsigned size, bool allowAcquired) -{ - if (BytesPerWord == 4 and size == 8) { - int low = freeRegister(c, allowAcquired); - return register_(c, low, freeRegisterExcept(c, low, allowAcquired)); - } else { - return register_(c, freeRegister(c, allowAcquired)); - } -} - -class PopEvent: public Event { - public: - PopEvent(Context* c, unsigned count, bool ignore): - Event(c), count(count), ignore(ignore) - { } - - virtual Value* target(Context* c, MyOperand*) { - abort(c); - } - - virtual unsigned operandSize(Context* c) { - abort(c); - } - - virtual void compile(Context* c) { - fprintf(stderr, "PopEvent.compile\n"); - - Stack* s = stack; - unsigned ignored = 0; - for (unsigned i = count; i;) { - MyOperand* dst = s->operand; - if (dst->pushed) { - if (dst->event and (not ignore)) { - assert(c, ignored == 0); - - Value* target = 0; - - if (dst->event->operandSize(c) == BytesPerWord) { - target = dst->event->target(c, dst); - } - if (target == 0 or (not target->ready(c))) { - target = freeRegister(c, BytesPerWord * s->size, false); - } - - target->acquire(c, 0, dst); - - apply(c, Pop, BytesPerWord * s->size, target); - - dst->value = target; - } else { - ignored += s->size; - } - } - - i -= s->size; - s = s->next; - } - - if (ignored) { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); - c->assembler->apply - (Add, BytesPerWord, Constant, &offset, Register, &stack); - } - } - - unsigned count; - bool ignore; -}; - -void -appendPop(Context* c, unsigned count, bool ignore) -{ - new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); -} - -bool -safeToSkipMove(Context* c, MyOperand* a, Event* e) -{ - for (; a->push and a->push != e; e = e->next) { - if (e->isCritical(c)) return false; - } - return true; -} - -class MoveEvent: public Event { - public: - MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src, - MyOperand* dst): - Event(c), type(type), size(size), src(src), dst(dst) - { - setEvent(c, src, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == src); - - if (dst->value) { - return dst->value; - } else if (dst->event) { - return dst->event->target(c, dst); - } - - return 0; - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "MoveEvent.compile\n"); - - if (src->target == 0) src->target = target(c, src); - - if (src->target == 0) { - if (type == Move - and size == BytesPerWord - and safeToSkipMove(c, dst, next)) - { - dst->value = src->value; - return; - } - } else if (type == Move - and size == BytesPerWord - and src->target->type(c) == Register - and src->target->equals(c, src->value)) - { - dst->value = src->value; - return; - } - - src->value->release(c, src); - - if (src->target == 0 or (not src->target->ready(c))) { - src->target = freeRegister(c, size, false); - } - - src->target->acquire(c, stack, dst); - - apply(c, type, size, src->value, src->target); - - dst->value = src->target; - } - - virtual bool isCritical(Context* c) { - if (src->target == 0) src->target = target(c, src); - - return src->target != 0; - } - - BinaryOperation type; - unsigned size; - MyOperand* src; - MyOperand* dst; -}; - -void -appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src, - MyOperand* dst) -{ - new (c->zone->allocate(sizeof(MoveEvent))) - MoveEvent(c, type, size, src, dst); -} - -class DupEvent: public Event { - public: - DupEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): - Event(c), size(size), src(src), dst(dst) - { } - - virtual Value* target(Context* c, MyOperand*) { - abort(c); - } - - virtual unsigned operandSize(Context* c) { - abort(c); - } - - virtual void compile(Context* c) { - fprintf(stderr, "DupEvent.compile\n"); - - Value* value = src->value; - assert(c, dst->value == 0); - - Value* target = 0; - - if (safeToSkipMove(c, dst, next)) { - dst->value = src->value; - return; - } - - if (dst->event) { - target = dst->event->target(c, dst); - } - if (target == 0 or (not target->ready(c))) { - target = freeRegister(c, size, true); - } - - target->acquire(c, stack, dst); - - apply(c, Move, size, value, target); - - dst->value = target; - } - - unsigned size; - MyOperand* src; - MyOperand* dst; -}; - -void -appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst) -{ - new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst); -} - -class CompareEvent: public Event { - public: - CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): - Event(c), size(size), a(a), b(b) - { - setEvent(c, a, this); - setEvent(c, b, this); - } - - virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { - assert(c, v == a or v == b); - - return 0; - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "CompareEvent.compile\n"); - - apply(c, Compare, size, a->value, b->value); - - a->value->release(c, a); - b->value->release(c, b); - } - - unsigned size; - MyOperand* a; - MyOperand* b; -}; - -void -appendCompare(Context* c, unsigned size, MyOperand* a, MyOperand* b) -{ - new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, a, b); -} - -class BranchEvent: public Event { - public: - BranchEvent(Context* c, UnaryOperation type, MyOperand* address): - Event(c), type(type), address(address) - { - setEvent(c, address, this); - } - - virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { - assert(c, v == address); - - return 0; - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual void compile(Context* c) { - fprintf(stderr, "BranchEvent.compile\n"); - - apply(c, type, BytesPerWord, address->value); - - address->value->release(c, address); - } - - UnaryOperation type; - MyOperand* address; -}; - -void -appendBranch(Context* c, UnaryOperation type, MyOperand* address) -{ - new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); -} - -class JumpEvent: public Event { - public: - JumpEvent(Context* c, MyOperand* address): - Event(c), - address(address) - { - setEvent(c, address, this); - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { - assert(c, v == address); - - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "JumpEvent.compile\n"); - - apply(c, Jump, BytesPerWord, address->value); - - address->value->release(c, address); - } - - MyOperand* address; -}; - -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, unsigned size, MyOperand* a, - MyOperand* b, MyOperand* result): - Event(c), type(type), size(size), a(a), b(b), result(result) - { - setEvent(c, a, this); - setEvent(c, b, this); - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual Value* target(Context* c, MyOperand* v) { - Assembler::Register ar(NoRegister); - Assembler::Register br(NoRegister); - c->assembler->getTargets(type, 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) { - if (result->event) { - Value* v = result->event->target(c, result); - if (v and v->type(c) == Register) { - return v; - } else { - return 0; - } - } else { - return 0; - } - } else { - return register_(c, br.low, br.high); - } - } - } - - virtual void compile(Context* c) { - fprintf(stderr, "CombineEvent.compile\n"); - - if (a->target == 0) a->target = target(c, a); - if (b->target == 0) b->target = target(c, b); - - if (b->target == 0 or (not b->target->ready(c))) { - b->target = freeRegister(c, BytesPerWord, true); - } - - if (a->target and not a->target->equals(c, a->value)) { - apply(c, Move, size, a->value, a->target); - a->value->release(c, a); - a->value = a->target; - a->value->acquire(c, stack, a); - } - - if (b->target and not b->target->equals(c, b->value)) { - apply(c, Move, size, b->value, b->target); - b->value->release(c, b); - b->value = b->target; - b->value->acquire(c, stack, b); - } - - apply(c, type, size, a->value, b->value); - - a->value->release(c, a); - b->value->release(c, b); - b->value->acquire(c, stack, result); - - result->value = b->value; - } - - BinaryOperation type; - unsigned size; - MyOperand* a; - MyOperand* b; - MyOperand* result; -}; - -void -appendCombine(Context* c, BinaryOperation type, unsigned size, MyOperand* a, - MyOperand* b, MyOperand* result) -{ - new (c->zone->allocate(sizeof(CombineEvent))) - CombineEvent(c, type, size, a, b, result); -} - -class TranslateEvent: public Event { - public: - TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a, - MyOperand* result): - Event(c), type(type), size(size), a(a), result(result) - { - setEvent(c, a, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == a); - - Assembler::Register r(NoRegister); - c->assembler->getTargets(type, size, &r); - - if (r.low == NoRegister) { - return result->event->target(c, result); - } else { - return register_(c, r.low, r.high); - } - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "TranslateEvent.compile\n"); - - if (a->target == 0) a->target = target(c, a); - - if (not a->target->ready(c)) { - a->target = a->value; - } - - result->value->acquire(c, stack, result); - - if (a->target and not a->target->equals(c, a->value)) { - apply(c, Move, size, a->value, a->target); - } - apply(c, type, size, a->value); - - result->value = a->value; - } - - UnaryOperation type; - unsigned size; - MyOperand* a; - MyOperand* result; -}; - -void -appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a, - MyOperand* result) -{ - new (c->zone->allocate(sizeof(TranslateEvent))) - TranslateEvent(c, type, size, a, result); -} - -class MemoryEvent: public Event { - public: - MemoryEvent(Context* c, MyOperand* base, MyOperand* index, - MyOperand* result): - Event(c), base(base), index(index), result(result) - { - setEvent(c, base, this); - if (index) setEvent(c, index, this); - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == base or v == index); - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "MemoryEvent.compile\n"); - - if (base->value->type(c) != Register) { - base->target = freeRegister(c, BytesPerWord, true); - apply(c, Move, BytesPerWord, base->value, base->target); - base->value->release(c, base); - base->value = base->target; - } - - if (index and index->value->type(c) != Register) { - index->target = freeRegister(c, BytesPerWord, true); - apply(c, Move, BytesPerWord, index->value, index->target); - index->value->release(c, index); - index->value = index->target; - } - } - - MyOperand* base; - MyOperand* index; - MyOperand* result; -}; - -void -appendMemory(Context* c, MyOperand* a, MyOperand* b, MyOperand* result) -{ - new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, a, b, result); -} - -void -preserve(Context* c, Stack* stack, int reg, MyOperand* a) -{ - MyOperand* b = c->registers[reg].operand; - if (b and a != b) { - fprintf(stderr, "%p preserve %d for %p\n", a, reg, b); - - unsigned count = 0; - Stack* start = 0; - for (Stack* s = stack; s and (not s->operand->pushed); s = s->next) { - if (s->operand == b) { - start = s; - } - if (start) { - ++ count; - } - } - - assert(c, start); - - syncStack(c, start, count); - } -} - -MyOperand* -operand(Context* c, Value* value = 0) -{ - return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(value); -} - unsigned count(Stack* s) { @@ -2042,30 +1040,29 @@ popState(Context* c) } Stack* -stack(Context* c, MyOperand* operand, unsigned size, unsigned index, - Stack* next) +stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) { return new (c->zone->allocate(sizeof(Stack))) - Stack(operand, size, index, next); + Stack(value, size, index, next); } Stack* -stack(Context* c, MyOperand* operand, unsigned size, Stack* next) +stack(Context* c, Value* value, unsigned size, Stack* next) { return stack(c, operand, size, (next ? next->index + size : 0), next); } void -push(Context* c, unsigned size, MyOperand* o) +push(Context* c, unsigned size, Value* v) { assert(c, ceiling(size, BytesPerWord)); - c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); + c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack); appendPush(c); } -MyOperand* +Value* pop(Context* c, unsigned size UNUSED) { Stack* s = c->state->stack; @@ -2074,9 +1071,9 @@ pop(Context* c, unsigned size UNUSED) appendPop(c, s->size, false); c->state->stack = s->next; - return s->operand; + return s->value; } - +// tbc void markStack(Context* c, Stack* stack) { @@ -2107,37 +1104,46 @@ updateJunctions(Context* c) } } -void -compile(Context* c) +int +freeRegisterExcept(Context* c, int except, bool allowAcquired) { - Assembler* a = c->assembler; - - Assembler::Register base(a->base()); - Assembler::Register stack(a->stack()); - a->apply(Push, BytesPerWord, Register, &base); - a->apply(Move, BytesPerWord, Register, &stack, Register, &base); - - if (c->stackOffset) { - Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); - a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack); + for (int i = c->assembler->registerCount(); i >= 0; --i) { + if (i != except + and (not c->registers[i].reserved) + and c->registers[i].value == 0) + { + return i; + } } - for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { - LogicalInstruction* li = c->logicalCode + i; - li->machineOffset = a->length(); - - for (Event* e = li->firstEvent; e; e = e->next) { - fprintf(stderr, "compile event at ip %d with stack count %d\n", - i, count(e->stack)); - e->compile(c); - - for (CodePromise* p = e->promises; p; p = p->next) { - p->offset = a->length(); + if (allowAcquired) { + for (int i = c->assembler->registerCount(); i >= 0; --i) { + if (i != except + and (not c->registers[i].reserved)) + { + return i; } - - if (e == li->lastEvent) break; } } + + abort(c); +} + +int +freeRegister(Context* c, bool allowAcquired) +{ + return freeRegisterExcept(c, NoRegister, allowAcquired); +} + +RegisterSite* +freeRegister(Context* c, unsigned size, bool allowAcquired) +{ + if (BytesPerWord == 4 and size == 8) { + int low = freeRegister(c, allowAcquired); + return registerSite(c, low, freeRegisterExcept(c, low, allowAcquired)); + } else { + return registerSite(c, freeRegister(c, allowAcquired)); + } } class Client: public Assembler::Client { @@ -2149,7 +1155,7 @@ class Client: public Assembler::Client { r = freeRegisterExcept(c, NoRegister, false); } else { expect(c, not c->registers[r].reserved); - expect(c, c->registers[r].operand == 0); + expect(c, c->registers[r].value == 0); } c->registers[r].reserved = true; return r; From f8a5d02f6746326d3934455bb824e7ff53468dcc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 17 Apr 2008 14:48:26 -0600 Subject: [PATCH 025/121] more compiler work --- src/compiler.cpp | 367 ++++++++++++++++++++++++++++++----------------- 1 file changed, 234 insertions(+), 133 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index f17209ca41..c70939d9dd 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -126,7 +126,7 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) } void -syncStack(Context* c, Stack* start, unsigned count) +stackSync(Context* c, Stack* start, unsigned count) { Stack* segment[count]; unsigned index = count; @@ -176,7 +176,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, assert(c, start); - syncStack(c, start, count); + stackSync(c, start, count); } for (Site** p = &(oldValue->sites); *p;) { @@ -464,14 +464,17 @@ expect(Context* c, bool v) class Read { public: - Read(unsigned size, Value* value, Site* target, Read* next, Read* eventNext): - size(size), value(value), target(target), next(next), eventNext(eventNext) + Read(unsigned size, Value* value, Site* target, Read* next, Event* event, + Read* eventNext): + size(size), value(value), target(target), next(next), event(event), + eventNext(eventNext) { } unsigned size; Value* value; Site* target; Read* next; + Event* event; Read* eventNext; }; @@ -499,6 +502,12 @@ class Value: public Compiler::Operand { Site* target; }; +Value* +value(Context* c, Site* site = 0) +{ + return new (c->zone->allocate(sizeof(Value))) Value(site); +} + void apply(Context* c, UnaryOperation op, unsigned size, Value* a) { @@ -626,18 +635,39 @@ class Stack { }; void -addRead(Context* c, Value* v, unsigned size, Site* target) +insertRead(Context* c, Event* thisEvent, Event* before, Value* v, + unsigned size, Site* target) { Read* r = new (c->zone->allocate(sizeof(Read))) - Read(v, size, target, 0, c->event-reads); - c->event->reads = r; + Read(v, size, target, 0, thisEvent, thisEvent-reads); + thisEvent->reads = r; - if (v->lastRead) { - r->lastRead->next = r; - } else { - v->reads = r; + if (before) { + for (Read** p = &(v->reads); *p;) { + if ((*p)->event->sequence >= before->sequence) { + r->next = *p; + *p = r; + break; + } else { + p = &((*p)->next); + } + } } - v->lastRead = r; + + if (r->next == 0) { + if (v->lastRead) { + v->lastRead->next = r; + } else { + v->reads = r; + } + v->lastRead = r; + } +} + +void +addRead(Context* c, Value* v, unsigned size, Site* target) +{ + insertRead(c, c->event, 0, v, size, target); } void @@ -651,28 +681,41 @@ class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, + Value** arguments, unsigned* argumentSizes, unsigned argumentCount): Event(c), address(address), indirection(indirection), - flags(flags), traceHandler(traceHandler), - result(result) + result(result), + flags(flags), + footprint(0) { addRead(c, address, BytesPerWord, (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); + Stack* oldStack = c.state->stack; + + for (int i = argumentCount - 1; i >= 0; --i) { + ::push(c, argumentSizes[i], arguments[i]); + } + unsigned index = 0; - Stack* s = stack; - for (unsigned i = 0; i < argumentCount; ++i) { - addRead(c, s->value, s->size * BytesPerWord, - index < c->assembler->argumentRegisterCount() ? - registerSite(c, c->assembler->argumentRegister(index)) : - stackSite(c, s)); + for (int i = 0; i < argumentCount; ++i) { + Site* target; + if (index < c->assembler->argumentRegisterCount()) { + target = registerSite(c, c->assembler->argumentRegister(index)); + } else { + target = stackSite(c, s); + footprint += s->size; + } + addRead(c, s->value, s->size * BytesPerWord, target); index += s->size; s = s->next; } + c.state->stack = oldStack; + if (result) { addWrite(c, result, resultSize); } @@ -694,13 +737,21 @@ class CallEvent: public Event { (new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, c->assembler->length())); } + + if (footprint) { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, footprint * BytesPerWord)); + c->assembler->apply + (Add, BytesPerWord, Constant, &offset, Register, &stack); + } } Value* address; void* indirection; - unsigned flags; TraceHandler* traceHandler; Value* result; + unsigned flags; + unsigned footprint; }; void @@ -899,28 +950,88 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, class MemoryEvent: public Event { public: - MemoryEvent(Context* c, Value* base, Value* index, Value* result): - Event(c), base(base), index(index), result(result) + MemoryEvent(Context* c, Value* base, int displacement, Value* index, + unsigned scale, Value* result): + Event(c), base(base), displacement(displacement), index(index), + scale(scale), result(result) { addRead(c, base, BytesPerWord, anyRegisterSite(c)); if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c)); - addWrite(c, BytesPerWord, size); } virtual void compile(Context*) { fprintf(stderr, "MemoryEvent.compile\n"); + + int baseRegister; + int indexRegister; + Read* read = reads; + if (index) { + assert(c, read->target->type(c) == RegisterOperand); + indexRegister = static_cast(read->target)->register_.low; + read = read->eventNext; + } else { + indexRegister = NoRegister; + } + assert(c, read->target->type(c) == RegisterOperand); + baseRegister = static_cast(read->target)->register_.low; + + addSite(c, 0, 0, result, memorySite + (c, baseRegister, displacement, indexRegister, scale)); } Value* base; + int displacement; Value* index; + unsigned scale; Value* result; }; void -appendMemory(Context* c, Value* base, Value* index, Value* result) +appendMemory(Context* c, Value* base, int displacement, Value* index, + unsigned scale, Value* result) { new (c->zone->allocate(sizeof(MemoryEvent))) - MemoryEvent(c, base, index, result); + MemoryEvent(c, base, displacement, index, scale, result); +} + +class StackSyncEvent: public Event { + public: + StackSyncEvent(Context* c, bool forCall): + Event(c) + { + unsigned i = 0; + for (Stack* s = stack; s; s = s->next) { + addRead(c, s->value, s->size * BytesPerWord, + forCall ? stackSite(c, s) : stackSyncSite(c, i, s->size)); + i += s->size; + } + } + + StackSyncEvent(Context* c, Event* next): + Event(c, next) + { + unsigned i = 0; + for (Stack* s = stack; s; s = s->next) { + insertRead(c, this, next, s->value, s->size * BytesPerWord, + stackSyncSite(c, i, s->size)); + i += s->size; + } + } + + virtual void compile(Context* c) { + fprintf(stderr, "StackSyncEvent.compile\n"); + + for (Read* r = reads; r; r = r->eventNext) { + r->value->sites = r->target; + r->target->next = 0; + } + } +}; + +void +appendStackSync(Context* c, bool forCall) +{ + new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c, forCall); } void @@ -1073,22 +1184,6 @@ pop(Context* c, unsigned size UNUSED) c->state->stack = s->next; return s->value; } -// tbc -void -markStack(Context* c, Stack* stack) -{ - for (Stack* s = stack; s; s = s->next) { - if (s->operand->push) { - s->operand->push->markStack(c); - } - } -} - -void -markStack(Context* c) -{ - markStack(c, c->state->stack); -} void updateJunctions(Context* c) @@ -1099,7 +1194,9 @@ updateJunctions(Context* c) if (i->predecessor >= 0) { LogicalInstruction* p = c->logicalCode + i->predecessor; - markStack(c, p->lastEvent->stack); + p->lastEvent = p->lastEvent->next + = new (c->zone->allocate(sizeof(StackSyncEvent))) + StackSyncEvent(c, p->lastEvent->next); } } } @@ -1239,11 +1336,11 @@ class MyCompiler: public Compiler { } virtual Operand* promiseConstant(Promise* value) { - return operand(&c, ::constant(&c, value)); + return ::value(&c, ::constantSite(&c, value)); } virtual Operand* address(Promise* address) { - return operand(&c, ::address(&c, address)); + return value(&c, ::addressSite(&c, address)); } virtual Operand* memory(Operand* base, @@ -1251,41 +1348,38 @@ class MyCompiler: public Compiler { Operand* index = 0, unsigned scale = 1) { - MyOperand* result = operand - (&c, ::memory - (&c, static_cast(base), displacement, - static_cast(index), scale)); + MyOperand* result = value(&c); - appendMemory(&c, static_cast(base), - static_cast(index), result); + appendMemory(&c, static_cast(base), displacement, + static_cast(index), scale, result); return result; } virtual Operand* stack() { - return operand(&c, register_(&c, c.assembler->stack())); + return value(&c, registerSite(&c, c.assembler->stack())); } virtual Operand* base() { - return operand(&c, register_(&c, c.assembler->base())); + return value(&c, registerSite(&c, c.assembler->base())); } virtual Operand* thread() { - return operand(&c, register_(&c, c.assembler->thread())); + return value(&c, registerSite(&c, c.assembler->thread())); } virtual bool isConstant(Operand* a) { - return static_cast(a)->value - and static_cast(a)->value->type(&c) == Constant; + return static_cast(a)->value + and static_cast(a)->value->type(&c) == ConstantOperand; } virtual int64_t constantValue(Operand* a) { assert(&c, isConstant(a)); - return static_cast(a)->value->constantValue(&c); + return static_cast(a)->value->constantValue(&c); } virtual Operand* label() { - return operand(&c, ::constant(&c, static_cast(0))); + return value(&c, ::constantSite(&c, static_cast(0))); } Promise* machineIp() { @@ -1294,14 +1388,14 @@ class MyCompiler: public Compiler { } virtual void mark(Operand* label) { - markStack(&c); + appendStackSync(&c); - static_cast(static_cast(label)->value)->value + static_cast(static_cast(label)->value)->value = machineIp(); } virtual void push(unsigned size, Operand* value) { - ::push(&c, size, static_cast(value)); + ::push(&c, size, static_cast(value)); } virtual Operand* pop(unsigned size) { @@ -1310,9 +1404,9 @@ class MyCompiler: public Compiler { virtual void pushed(unsigned count) { for (unsigned i = 0; i < count; ++i) { - MyOperand* a = operand(&c); + Value* a = value(&c); ::push(&c, BytesPerWord, a); - a->value = stackValue(&c, c.state->stack); + a->sites = stackSite(&c, c.state->stack); } } @@ -1333,14 +1427,14 @@ class MyCompiler: public Compiler { i -= s->size; } assert(&c, s->size == ceiling(size, BytesPerWord)); - return s->operand; + return s->value; } virtual Operand* call(Operand* address, void* indirection, unsigned flags, TraceHandler* traceHandler, - unsigned, + unsigned resultSize, unsigned argumentCount, ...) { @@ -1348,11 +1442,16 @@ class MyCompiler: public Compiler { unsigned footprint = 0; unsigned size = BytesPerWord; + Value* arguments[argumentCount]; + unsigned argumentSizes[argumentCount]; + unsigned index = 0; for (unsigned i = 0; i < argumentCount; ++i) { - MyOperand* o = va_arg(a, MyOperand*); + Value* o = va_arg(a, Value*); if (o) { - appendArgument(&c, size, o, footprint); + arguments[index] = o; + argumentSizes[index] = size; size = BytesPerWord; + ++ index; } else { size = 8; } @@ -1361,174 +1460,176 @@ class MyCompiler: public Compiler { va_end(a); - markStack(&c); + appendStackSync(&c, true); + + Value* result = value(&c); + appendCall(&c, static_cast(address), indirection, flags, + traceHandler, result, resultSize, arguments, argumentSizes, + index); - MyOperand* result = operand(&c); - appendCall(&c, static_cast(address), indirection, flags, - traceHandler, result); return result; } virtual void return_(unsigned size, Operand* value) { - appendReturn(&c, size, static_cast(value)); + appendReturn(&c, size, static_cast(value)); } virtual void store(unsigned size, Operand* src, Operand* dst) { - appendMove(&c, Move, size, static_cast(src), - static_cast(dst)); + appendMove(&c, Move, size, static_cast(src), + static_cast(dst)); } virtual Operand* load(unsigned size, Operand* src) { - MyOperand* dst = operand(&c); - appendMove(&c, Move, size, static_cast(src), dst); + Value* dst = value(&c); + appendMove(&c, Move, size, static_cast(src), dst); return dst; } virtual Operand* loadz(unsigned size, Operand* src) { - MyOperand* dst = operand(&c); - appendMove(&c, MoveZ, size, static_cast(src), dst); + Value* dst = value(&c); + appendMove(&c, MoveZ, size, static_cast(src), dst); return dst; } virtual Operand* load4To8(Operand* src) { - MyOperand* dst = operand(&c); - appendMove(&c, Move4To8, 0, static_cast(src), dst); + Value* dst = value(&c); + appendMove(&c, Move4To8, 0, static_cast(src), dst); return dst; } virtual Operand* dup(unsigned size, Operand* src) { - MyOperand* dst = operand(&c); - appendDup(&c, size, static_cast(src), dst); + Value* dst = value(&c); + appendDup(&c, size, static_cast(src), dst); return dst; } virtual void cmp(unsigned size, Operand* a, Operand* b) { - appendCompare(&c, size, static_cast(a), - static_cast(b)); + appendCompare(&c, size, static_cast(a), + static_cast(b)); } virtual void jl(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendBranch(&c, JumpIfLess, static_cast(address)); + appendBranch(&c, JumpIfLess, static_cast(address)); } virtual void jg(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendBranch(&c, JumpIfGreater, static_cast(address)); + appendBranch(&c, JumpIfGreater, static_cast(address)); } virtual void jle(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); + appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); } virtual void jge(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); + appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); } virtual void je(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendBranch(&c, JumpIfEqual, static_cast(address)); + appendBranch(&c, JumpIfEqual, static_cast(address)); } virtual void jne(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendBranch(&c, JumpIfNotEqual, static_cast(address)); + appendBranch(&c, JumpIfNotEqual, static_cast(address)); } virtual void jmp(Operand* address) { - markStack(&c); + appendStackSync(&c); - appendJump(&c, static_cast(address)); + appendBranch(&c, Branch, static_cast(address)); } virtual Operand* add(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Add, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Add, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* sub(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Subtract, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Subtract, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* mul(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Multiply, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Multiply, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* div(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Divide, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Divide, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* rem(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Remainder, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Remainder, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* shl(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, ShiftLeft, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, ShiftLeft, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* shr(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, ShiftRight, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, ShiftRight, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* ushr(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, UnsignedShiftRight, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, UnsignedShiftRight, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* and_(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, And, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, And, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* or_(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Or, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Or, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* xor_(unsigned size, Operand* a, Operand* b) { - MyOperand* result = operand(&c); - appendCombine(&c, Xor, size, static_cast(a), - static_cast(b), result); + Value* result = value(&c); + appendCombine(&c, Xor, size, static_cast(a), + static_cast(b), result); return result; } virtual Operand* neg(unsigned size, Operand* a) { - MyOperand* result = operand(&c); - appendTranslate(&c, Negate, size, static_cast(a), result); + Value* result = value(&c); + appendTranslate(&c, Negate, size, static_cast(a), result); return result; } From a7134a2cd776223dc3486fb5a699a514947a865b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 17 Apr 2008 16:07:32 -0600 Subject: [PATCH 026/121] fix build --- src/assembler.h | 4 +- src/compile.cpp | 85 ++--- src/compiler.cpp | 949 +++++++++++++++++++++++++---------------------- src/compiler.h | 1 - src/x86.cpp | 14 +- 5 files changed, 561 insertions(+), 492 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 5b2a3b30d1..ac56f300ec 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -55,10 +55,10 @@ enum OperandType { AddressOperand, RegisterOperand, MemoryOperand, - StackOperand + StackOperand // for compiler use; not used in assembler }; -const unsigned OperandTypeCount = Memory + 1; +const unsigned OperandTypeCount = MemoryOperand + 1; const int NoRegister = -1; const int AnyRegister = -2; diff --git a/src/compile.cpp b/src/compile.cpp index b3cd33c37b..f2400ec469 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -847,7 +847,7 @@ class Frame { } void dup() { - c->push(BytesPerWord, c->dup(BytesPerWord, c->peek(BytesPerWord, 0))); + c->push(BytesPerWord, c->peek(BytesPerWord, 0)); dupped(); } @@ -858,7 +858,7 @@ class Frame { c->push(BytesPerWord, s0); c->push(BytesPerWord, s1); - c->push(BytesPerWord, c->dup(BytesPerWord, s0)); + c->push(BytesPerWord, s0); duppedX1(); } @@ -871,7 +871,7 @@ class Frame { c->push(BytesPerWord, s0); pushLongQuiet(s1); - c->push(BytesPerWord, c->dup(BytesPerWord, s0)); + c->push(BytesPerWord, s0); } else { Compiler::Operand* s1 = c->pop(BytesPerWord); Compiler::Operand* s2 = c->pop(BytesPerWord); @@ -879,7 +879,7 @@ class Frame { c->push(BytesPerWord, s0); c->push(BytesPerWord, s2); c->push(BytesPerWord, s1); - c->push(BytesPerWord, c->dup(BytesPerWord, s0)); + c->push(BytesPerWord, s0); } duppedX2(); @@ -887,15 +887,15 @@ class Frame { void dup2() { if (get(sp - 1) == Long) { - pushLongQuiet(c->dup(8, peekLong(0))); + pushLongQuiet(peekLong(0)); } else { Compiler::Operand* s0 = c->pop(BytesPerWord); Compiler::Operand* s1 = c->pop(BytesPerWord); c->push(BytesPerWord, s1); c->push(BytesPerWord, s0); - c->push(BytesPerWord, c->dup(BytesPerWord, s1)); - c->push(BytesPerWord, c->dup(BytesPerWord, s0)); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } dupped2(); @@ -908,7 +908,7 @@ class Frame { pushLongQuiet(s0); c->push(BytesPerWord, s1); - pushLongQuiet(c->dup(8, s0)); + pushLongQuiet(s0); } else { Compiler::Operand* s0 = c->pop(BytesPerWord); Compiler::Operand* s1 = c->pop(BytesPerWord); @@ -917,8 +917,8 @@ class Frame { c->push(BytesPerWord, s1); c->push(BytesPerWord, s0); c->push(BytesPerWord, s2); - c->push(BytesPerWord, c->dup(BytesPerWord, s1)); - c->push(BytesPerWord, c->dup(BytesPerWord, s0)); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } dupped2X1(); @@ -933,7 +933,7 @@ class Frame { pushLongQuiet(s0); pushLongQuiet(s1); - pushLongQuiet(c->dup(8, s0)); + pushLongQuiet(s0); } else { Compiler::Operand* s1 = c->pop(BytesPerWord); Compiler::Operand* s2 = c->pop(BytesPerWord); @@ -941,7 +941,7 @@ class Frame { pushLongQuiet(s0); c->push(BytesPerWord, s2); c->push(BytesPerWord, s1); - pushLongQuiet(c->dup(8, s0)); + pushLongQuiet(s0); } } else { Compiler::Operand* s0 = c->pop(BytesPerWord); @@ -953,8 +953,8 @@ class Frame { c->push(BytesPerWord, s0); c->push(BytesPerWord, s3); c->push(BytesPerWord, s2); - c->push(BytesPerWord, c->dup(BytesPerWord, s1)); - c->push(BytesPerWord, c->dup(BytesPerWord, s0)); + c->push(BytesPerWord, s1); + c->push(BytesPerWord, s0); } dupped2X2(); @@ -1710,9 +1710,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } else if (exceptionHandler) { exceptionHandler = false; - c->indirectCall + c->call (c->constant(reinterpret_cast(gcIfNecessary)), + context->indirection, + 0, frame->trace(0, false), + 0, 1, c->thread()); } @@ -2098,7 +2101,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(doubleToInt)), + (c->constant(reinterpret_cast(addDouble)), 0, 0, 0, 8, 2, a, b)); } break; @@ -2833,27 +2836,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } break; case l2d: { - Operand* a = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(longToDouble)), 2, 0, a); - - Operand* result = c->result8(); - frame->pushLong(result); - c->release(result); - c->release(a); + frame->pushLong + (c->call + (c->constant(reinterpret_cast(longToDouble)), + 0, 0, 0, 8, 1, frame->popLong())); } break; case l2f: { - Operand* a = frame->popLong(); - - c->directCall - (c->constant(reinterpret_cast(longToDouble)), 2, 0, a); - - Operand* result = c->result4(); - frame->pushInt(result); - c->release(result); - c->release(a); + frame->pushInt + (c->call + (c->constant(reinterpret_cast(longToFloat)), + 0, 0, 0, 4, 1, frame->popLong())); } break; case l2i: @@ -3819,7 +3812,7 @@ finish(MyThread* t, Context* context) if (Verbose) { logCompile - (start, c->codeSize(), + (start, codeSize, reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), reinterpret_cast @@ -4332,11 +4325,13 @@ saveStackAndBase(MyThread* t, Assembler* a) { Assembler::Register base(a->base()); Assembler::Memory baseDst(a->thread(), difference(&(t->base), t)); - a->apply(Move, BytesPerWord, Register, &base, Memory, &baseDst); + a->apply(Move, BytesPerWord, RegisterOperand, &base, + MemoryOperand, &baseDst); Assembler::Register stack(a->stack()); Assembler::Memory stackDst(a->thread(), difference(&(t->stack), t)); - a->apply(Move, BytesPerWord, Register, &stack, Memory, &stackDst); + a->apply(Move, BytesPerWord, RegisterOperand, &stack, + MemoryOperand, &stackDst); } void @@ -4346,9 +4341,10 @@ pushThread(MyThread*, Assembler* a) if (a->argumentRegisterCount()) { Assembler::Register arg(a->argumentRegister(0)); - a->apply(Move, BytesPerWord, Register, &thread, Register, &arg); + a->apply(Move, BytesPerWord, RegisterOperand, &thread, + RegisterOperand, &arg); } else { - a->apply(Push, BytesPerWord, Register, &thread); + a->apply(Push, BytesPerWord, RegisterOperand, &thread); } } @@ -4359,7 +4355,8 @@ popThread(MyThread*, Assembler* a) ResolvedPromise bpwPromise(BytesPerWord); Assembler::Constant bpw(&bpwPromise); Assembler::Register stack(a->stack()); - a->apply(Add, BytesPerWord, Constant, &bpw, Register, &stack); + a->apply(Add, BytesPerWord, ConstantOperand, &bpw, + RegisterOperand, &stack); } } @@ -4371,12 +4368,12 @@ compileDefault(MyThread* t, Assembler* a) ResolvedPromise procPromise(reinterpret_cast(compileMethod)); Assembler::Constant proc(&procPromise); - a->apply(Call, BytesPerWord, Constant, &proc); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); popThread(t, a); Assembler::Register result(a->returnLow()); - a->apply(Jump, BytesPerWord, Register, &result); + a->apply(Jump, BytesPerWord, RegisterOperand, &result); return finish(t, a, "default"); } @@ -4389,7 +4386,7 @@ compileNative(MyThread* t, Assembler* a) ResolvedPromise promise(reinterpret_cast(invokeNative)); Assembler::Constant proc(&promise); - a->apply(Call, BytesPerWord, Constant, &proc); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); popThread(t, a); @@ -5003,7 +5000,7 @@ processor(MyThread* t) saveStackAndBase(t, a); Assembler::Register proc(a->returnLow()); - a->apply(Jump, BytesPerWord, Register, &proc); + a->apply(Jump, BytesPerWord, RegisterOperand, &proc); p->indirectCallerSize = a->length(); p->indirectCaller = static_cast diff --git a/src/compiler.cpp b/src/compiler.cpp index c70939d9dd..0d023eae4e 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -17,16 +17,25 @@ namespace { class Context; class Value; +class Stack; +class Site; +class Event; void NO_RETURN abort(Context*); +void +apply(Context* c, UnaryOperation op, unsigned size, Site* a); + +void +apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b); + class Site { public: Site(): next(0) { } virtual ~Site() { } - virtual Site* resolve(Context*) { return this; } + virtual Site* resolve(Context*, unsigned) { return this; } virtual unsigned copyCost(Context*, Site*) = 0; @@ -36,319 +45,24 @@ class Site { virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } - virtual OperandType type(Context*) { - return Constant; - } + virtual OperandType type(Context*) = 0; virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; Site* next; }; -class ConstantSite: public Site { - public: - ConstantSite(Promise* value): value(value) { } - - virtual unsigned copyCost(Context*, Site*) { - return 1; - } - - virtual OperandType type(Context*) { - return Constant; - } - - virtual Assembler::Operand* asAssemblerOperand(Context*) { - return &value; - } - - Assembler::Constant value; -}; - -ConstantSite* -constantSite(Context* c, Promise* value) -{ - return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value); -} - -ResolvedPromise* -resolved(Context* c, int64_t value) -{ - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); -} - -ConstantSite* -constantSite(Context* c, int64_t value) -{ - return constantSite(c, resolved(c, value)); -} - -class AddressSite: public Site { - public: - AddressSite(Promise* address): address(address) { } - - virtual unsigned copyCost(Context*, Site*) { - return 3; - } - - virtual OperandType type(Context*) { - return Address; - } - - virtual Assembler::Operand* asAssemblerOperand(Context*) { - return &address; - } - - Assembler::Address address; -}; - -AddressSite* -addressSite(Context* c, Promise* address) -{ - return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); -} - -Site* -pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) -{ - Site* site = 0; - unsigned copyCost = 0xFFFFFFFF; - for (Site* s = sites; s; s = s->next) { - unsigned c = s->copyCost(c, target); - if (c < copyCost) { - site = s; - copyCost = c; - } - } - - if (cost) *cost = copyCost; - return site; -} - -void -stackSync(Context* c, Stack* start, unsigned count) -{ - Stack* segment[count]; - unsigned index = count; - for (Stack* s = start; s and index; s = s->next) { - segment[--index] = s; - } - - for (unsigned i = 0; i < count; ++i) { - Stack* s = segment[i]; - - if (s->value) { - apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); - - StackSite* site = stackSite(c, s); - site->next = s->value->sites; - s->value->sites = site; - } else { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); - c->assembler->apply - (Subtract, BytesPerWord, Constant, &offset, Register, &stack); - } - - s->pushed = true; - } -} - -void -acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, - Site* newSite) -{ - Value* oldValue = c->registers[r].value; - if (oldValue) { - if (old->sites->next == 0 and old->reads) { - assert(c, old->sites == oldValue->sites); - - unsigned count = 0; - Stack* start = 0; - for (Stack* s = stack; s and not s->pushed; s = s->next) { - if (s->value == old) { - start = s; - } - if (start) { - ++ count; - } - } - - assert(c, start); - - stackSync(c, start, count); - } - - for (Site** p = &(oldValue->sites); *p;) { - if (c->registers[r].site == *p) { - *p = (*p)->next; - break; - } else { - p = &((*p)->next); - } - } - } - - c->registers[r].size = newSize; - c->registers[r].value = newValue; - c->registers[r].site = newSite; -} - -class RegisterSite: public Site { - public: - RegisterSite(int low, int high): register_(low, high) { } - - virtual unsigned copyCost(Context* c, Site* s) { - if (s and - (this == s or - (s->type(c) == Register - and static_cast(s)->register_.low - == register_.low - and static_cast(s)->register_.high - == register_.high))) - { - return 0; - } else { - return 2; - } - } - - virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, - Site* s) - { - ::acquire(c, register_.low, stack, size, v, s); - if (register_.high >= 0) ::acquire(c, register_.high, stack, size, v, s); - } - - virtual OperandType type(Context*) { - return Register; - } - - virtual Assembler::Operand* asAssemblerOperand(Context*) { - return ®ister_; - } - - Assembler::Register register_; -}; - -RegisterSite* -registerSite(Context* c, int low, int high = NoRegister) -{ - return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(low, high); -} - -class MemorySite: public Site { - public: - MemorySite(int base, int offset, int index, unsigned scale): - value(base, offset, index, scale) - { } - - virtual unsigned copyCost(Context* c, Site* s) { - if (s and - (this == s or - (o->type(c) == Memory - and static_cast(o)->value.base == value.base - and static_cast(o)->value.offset == value.offset - and static_cast(o)->value.index == value.index - and static_cast(o)->value.scale == value.scale))) - { - return 0; - } else { - return 4; - } - } - - virtual OperandType type(Context*) { - return Memory; - } - - virtual Assembler::Operand* asAssemblerOperand(Context*) { - return &value; - } - - Assembler::Memory value; -}; - -MemorySite* -memorySite(Context* c, int base, int offset, int index, unsigned scale) -{ - return new (c->zone->allocate(sizeof(MemorySite))) - MemorySite(base, offset, index, scale); -} - -class ValueSite: public Site { - public: - ValueSite(Value* value): value(value) { } - - virtual Site* resolve(Context* c) { - return value->sites; - } - - virtual unsigned copyCost(Context* c, Site*) { - abort(c); - } - - virtual void copyTo(Context* c, unsigned, Site*) { - abort(c); - } - - virtual OperandType type(Context* c) { - abort(c); - } - - virtual Assembler::Operand* asAssemblerOperand(Context* c) { - abort(c); - } - - Value* value; -}; - -ValueSite* -valueSite(Context* c, Value* v) -{ - return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v); -} - -class StackSite: public Site { - public: - StackSite(Stack* stack): stack(stack) { } - - virtual unsigned copyCost(Context*, Site*) { - return 5; - } - - virtual void accept(Context* c, unsigned size, Site* src) { - apply(c, Push, size, src); - } - - virtual OperandType type(Context*) { - return StackOperand; - } - - virtual Assembler::Operand* asAssemblerOperand(Context*) { - abort(c); - } - - Stack* stack; -}; - -StackSite* -stackSite(Context* c, Stack* s) -{ - return new (c->zone->allocate(sizeof(StackSite))) StackSite(s); -} - class Stack { public: Stack(Value* value, unsigned size, unsigned index, Stack* next): - value(value), size(size), index(index), next(next) + value(value), size(size), index(index), next(next), pushed(false) { } Value* value; unsigned size; unsigned index; Stack* next; + bool pushed; }; class State { @@ -365,7 +79,6 @@ class State { class LogicalInstruction { public: unsigned visits; - Event* firstEvent; Event* lastEvent; unsigned machineOffset; int predecessor; @@ -398,70 +111,6 @@ class Junction { 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(Register) * assembler->registerCount()))), - firstConstant(0), - lastConstant(0), - constantCount(0), - junctions(0), - machineCode(0) - { - memset(registers, 0, sizeof(Register) * 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; - Register* 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); -} - class Read { public: Read(unsigned size, Value* value, Site* target, Read* next, Event* event, @@ -502,14 +151,406 @@ class Value: public Compiler::Operand { Site* target; }; +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)), + firstEvent(0), + lastEvent(0), + logicalCode(0), + logicalCodeLength(0), + stackOffset(0), + registers(static_cast + (zone->allocate(sizeof(Register) * assembler->registerCount()))), + firstConstant(0), + lastConstant(0), + constantCount(0), + junctions(0), + machineCode(0) + { + memset(registers, 0, sizeof(Register) * 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* firstEvent; + Event* lastEvent; + LogicalInstruction* logicalCode; + unsigned logicalCodeLength; + unsigned stackOffset; + Register* registers; + ConstantPoolNode* firstConstant; + ConstantPoolNode* lastConstant; + unsigned constantCount; + Junction* junctions; + uint8_t* machineCode; +}; + +void +addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) +{ + s->acquire(c, stack, size, v, s); + s->next = v->sites; + v->sites = s; +} + +class ConstantSite: public Site { + public: + ConstantSite(Promise* value): value(value) { } + + virtual unsigned copyCost(Context*, Site*) { + return 1; + } + + virtual OperandType type(Context*) { + return ConstantOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return &value; + } + + Assembler::Constant value; +}; + +ConstantSite* +constantSite(Context* c, Promise* value) +{ + return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value); +} + +ResolvedPromise* +resolved(Context* c, int64_t value) +{ + return new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value); +} + +ConstantSite* +constantSite(Context* c, int64_t value) +{ + return constantSite(c, resolved(c, value)); +} + +class AddressSite: public Site { + public: + AddressSite(Promise* address): address(address) { } + + virtual unsigned copyCost(Context*, Site*) { + return 3; + } + + virtual OperandType type(Context*) { + return AddressOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return &address; + } + + Assembler::Address address; +}; + +AddressSite* +addressSite(Context* c, Promise* address) +{ + return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); +} + +void +acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, + Site* newSite); + +class RegisterSite: public Site { + public: + RegisterSite(int low, int high): register_(low, high) { } + + virtual unsigned copyCost(Context* c, Site* s) { + if (s and + (this == s or + (s->type(c) == RegisterOperand + and static_cast(s)->register_.low + == register_.low + and static_cast(s)->register_.high + == register_.high))) + { + return 0; + } else { + return 2; + } + } + + virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, + Site* s) + { + ::acquire(c, register_.low, stack, size, v, s); + if (register_.high >= 0) ::acquire(c, register_.high, stack, size, v, s); + } + + virtual OperandType type(Context*) { + return RegisterOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return ®ister_; + } + + Assembler::Register register_; +}; + +RegisterSite* +registerSite(Context* c, int low, int high = NoRegister) +{ + return new (c->zone->allocate(sizeof(RegisterSite))) + RegisterSite(low, high); +} + +RegisterSite* +freeRegister(Context* c, unsigned size, bool allowAcquired); + +class MemorySite: public Site { + public: + MemorySite(int base, int offset, int index, unsigned scale): + value(base, offset, index, scale) + { } + + virtual unsigned copyCost(Context* c, Site* s) { + if (s and + (this == s or + (s->type(c) == MemoryOperand + and static_cast(s)->value.base == value.base + and static_cast(s)->value.offset == value.offset + and static_cast(s)->value.index == value.index + and static_cast(s)->value.scale == value.scale))) + { + return 0; + } else { + return 4; + } + } + + virtual OperandType type(Context*) { + return MemoryOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + return &value; + } + + Assembler::Memory value; +}; + +MemorySite* +memorySite(Context* c, int base, int offset, int index, unsigned scale) +{ + return new (c->zone->allocate(sizeof(MemorySite))) + MemorySite(base, offset, index, scale); +} + +class AbstractSite: public Site { + public: + virtual unsigned copyCost(Context* c, Site*) { + abort(c); + } + + virtual void copyTo(Context* c, unsigned, Site*) { + abort(c); + } + + virtual OperandType type(Context* c) { + abort(c); + } + + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + abort(c); + } +}; + +class ValueSite: public AbstractSite { + public: + ValueSite(Value* value): value(value) { } + + virtual Site* resolve(Context*, unsigned) { + return value->sites; + } + + Value* value; +}; + +ValueSite* +valueSite(Context* c, Value* v) +{ + return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v); +} + +class AnyRegisterSite: public AbstractSite { + public: + virtual Site* resolve(Context* c, unsigned size) { + return freeRegister(c, size, true); + } + + Value* value; +}; + +AnyRegisterSite* +anyRegisterSite(Context* c) +{ + return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite(); +} + +class StackSite: public Site { + public: + StackSite(Stack* stack): stack(stack) { } + + virtual unsigned copyCost(Context*, Site*) { + return 5; + } + + virtual void accept(Context* c, unsigned size, Site* src) { + apply(c, Push, size, src); + } + + virtual OperandType type(Context*) { + return StackOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + abort(c); + } + + Stack* stack; +}; + +StackSite* +stackSite(Context* c, Stack* s) +{ + return new (c->zone->allocate(sizeof(StackSite))) StackSite(s); +} + +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); +} + Value* value(Context* c, Site* site = 0) { return new (c->zone->allocate(sizeof(Value))) Value(site); } +Site* +pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) +{ + Site* site = 0; + unsigned copyCost = 0xFFFFFFFF; + for (Site* s = sites; s; s = s->next) { + unsigned v = s->copyCost(c, target); + if (v < copyCost) { + site = s; + copyCost = v; + } + } + + if (cost) *cost = copyCost; + return site; +} + void -apply(Context* c, UnaryOperation op, unsigned size, Value* a) +stackSync(Context* c, Stack* start, unsigned count) +{ + Stack* segment[count]; + unsigned index = count; + for (Stack* s = start; s and index; s = s->next) { + segment[--index] = s; + } + + for (unsigned i = 0; i < count; ++i) { + Stack* s = segment[i]; + + if (s->value) { + apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); + + StackSite* site = stackSite(c, s); + site->next = s->value->sites; + s->value->sites = site; + } else { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); + c->assembler->apply + (Subtract, BytesPerWord, ConstantOperand, &offset, + RegisterOperand, &stack); + } + + s->pushed = true; + } +} + +void +acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, + Site* newSite) +{ + Value* oldValue = c->registers[r].value; + if (oldValue) { + if (oldValue->sites->next == 0 and oldValue->reads) { + unsigned count = 0; + Stack* start = 0; + for (Stack* s = stack; s and not s->pushed; s = s->next) { + if (s->value == oldValue) { + start = s; + } + if (start) { + ++ count; + } + } + + assert(c, start); + + stackSync(c, start, count); + } + + for (Site** p = &(oldValue->sites); *p;) { + if (c->registers[r].site == *p) { + *p = (*p)->next; + break; + } else { + p = &((*p)->next); + } + } + } + + c->registers[r].size = newSize; + c->registers[r].value = newValue; + c->registers[r].site = newSite; +} + +void +apply(Context* c, UnaryOperation op, unsigned size, Site* a) { OperandType type = a->type(c); Assembler::Operand* operand = a->asAssemblerOperand(c); @@ -518,7 +559,7 @@ apply(Context* c, UnaryOperation op, unsigned size, Value* a) } void -apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b) +apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b) { OperandType aType = a->type(c); Assembler::Operand* aOperand = a->asAssemblerOperand(c); @@ -599,20 +640,28 @@ class IpPromise: public Promise { class Event { public: - Event(Context* c): next(0), stack(c->state->stack), promises(0) { + Event(Context* c): + next(0), stack(c->state->stack), promises(0), reads(0), writes(0), + logicalIp(c->logicalIp) + { assert(c, c->logicalIp >= 0); - if (c->event) { - c->event->next = this; + if (c->lastEvent) { + c->lastEvent->next = this; + sequence = c->lastEvent->sequence + 1; + } else { + c->firstEvent = this; + sequence = 0; } - if (c->logicalCode[c->logicalIp].firstEvent == 0) { - c->logicalCode[c->logicalIp].firstEvent = this; - } - - c->event = this; + c->lastEvent = this; } + Event(Context*, Event* next): + next(next), stack(next->stack), promises(0), reads(0), writes(0), + sequence(next->sequence), logicalIp(next->logicalIp) + { } + virtual ~Event() { } virtual void compile(Context* c) = 0; @@ -620,18 +669,10 @@ class Event { Event* next; Stack* stack; CodePromise* promises; -}; - -class Stack { - public: - Stack(Value* value, unsigned size, unsigned index, Stack* next): - value(value), size(size), index(index), next(next) - { } - - Value* value; - unsigned size; - unsigned index; - Stack* next; + Read* reads; + Write* writes; + unsigned sequence; + unsigned logicalIp; }; void @@ -639,7 +680,7 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, unsigned size, Site* target) { Read* r = new (c->zone->allocate(sizeof(Read))) - Read(v, size, target, 0, thisEvent, thisEvent-reads); + Read(size, v, target, 0, thisEvent, thisEvent->reads); thisEvent->reads = r; if (before) { @@ -667,16 +708,19 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, void addRead(Context* c, Value* v, unsigned size, Site* target) { - insertRead(c, c->event, 0, v, size, target); + insertRead(c, c->lastEvent, 0, v, size, target); } void addWrite(Context* c, Value* v, unsigned size) { - c->event->writes = new (c->zone->allocate(sizeof(Write))) - Write(v, size, c->event->writes); + c->lastEvent->writes = new (c->zone->allocate(sizeof(Write))) + Write(size, v, c->lastEvent->writes); } +void +push(Context* c, unsigned size, Value* v); + class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, @@ -694,14 +738,13 @@ class CallEvent: public Event { addRead(c, address, BytesPerWord, (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); - Stack* oldStack = c.state->stack; - for (int i = argumentCount - 1; i >= 0; --i) { ::push(c, argumentSizes[i], arguments[i]); } unsigned index = 0; - for (int i = 0; i < argumentCount; ++i) { + Stack* s = c->state->stack; + for (unsigned i = 0; i < argumentCount; ++i) { Site* target; if (index < c->assembler->argumentRegisterCount()) { target = registerSite(c, c->assembler->argumentRegister(index)); @@ -714,7 +757,7 @@ class CallEvent: public Event { s = s->next; } - c.state->stack = oldStack; + c->state->stack = stack; if (result) { addWrite(c, result, resultSize); @@ -742,7 +785,7 @@ class CallEvent: public Event { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset(resolved(c, footprint * BytesPerWord)); c->assembler->apply - (Add, BytesPerWord, Constant, &offset, Register, &stack); + (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); } } @@ -756,11 +799,12 @@ class CallEvent: public Event { void appendCall(Context* c, Value* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned argumentCount) + TraceHandler* traceHandler, Value* result, unsigned resultSize, + Value** arguments, unsigned* argumentSizes, unsigned argumentCount) { new (c->zone->allocate(sizeof(CallEvent))) CallEvent(c, address, indirection, flags, traceHandler, result, - argumentCount); + resultSize, arguments, argumentSizes, argumentCount); } class ReturnEvent: public Event { @@ -782,8 +826,9 @@ class ReturnEvent: public Event { Assembler::Register base(c->assembler->base()); Assembler::Register stack(c->assembler->stack()); - c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack); - c->assembler->apply(Pop, BytesPerWord, Register, &base); + c->assembler->apply(Move, BytesPerWord, RegisterOperand, &base, + RegisterOperand, &stack); + c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &base); c->assembler->apply(Return); } @@ -791,7 +836,7 @@ class ReturnEvent: public Event { }; void -appendReturn(Context* c, unsigned size, MyOperand* value) +appendReturn(Context* c, unsigned size, Value* value) { new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } @@ -893,7 +938,8 @@ class CombineEvent: public Event { r1.low == NoRegister ? 0 : registerSite(c, r1.low, r1.high)); addRead(c, second, size, r2.low == NoRegister ? - valueSite(c, result) : registerSite(c, r2.low, r2.high)); + valueSite(c, result) : + static_cast(registerSite(c, r2.low, r2.high))); addWrite(c, result, size); } @@ -907,7 +953,7 @@ class CombineEvent: public Event { unsigned size; Value* first; Value* second; - MyOperand* result; + Value* result; }; void @@ -959,7 +1005,7 @@ class MemoryEvent: public Event { if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c)); } - virtual void compile(Context*) { + virtual void compile(Context* c) { fprintf(stderr, "MemoryEvent.compile\n"); int baseRegister; @@ -994,6 +1040,28 @@ appendMemory(Context* c, Value* base, int displacement, Value* index, MemoryEvent(c, base, displacement, index, scale, result); } +Site* +stackSyncSite(Context* c, unsigned index, unsigned size) +{ + int high = NoRegister; + for (int i = c->assembler->registerCount(); i >= 0; --i) { + if (not c->registers[i].reserved) { + if (index == 0) { + if (size == 1) { + return registerSite(c, i, high); + } else { + high = i; + -- size; + } + } else { + -- index; + } + } + } + + abort(c); +} + class StackSyncEvent: public Event { public: StackSyncEvent(Context* c, bool forCall): @@ -1018,7 +1086,7 @@ class StackSyncEvent: public Event { } } - virtual void compile(Context* c) { + virtual void compile(Context*) { fprintf(stderr, "StackSyncEvent.compile\n"); for (Read* r = reads; r; r = r->eventNext) { @@ -1029,19 +1097,11 @@ class StackSyncEvent: public Event { }; void -appendStackSync(Context* c, bool forCall) +appendStackSync(Context* c, bool forCall = false) { new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c, forCall); } -void -addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) -{ - s->acquire(c, stack, size, v, s); - s->next = v->sites; - v->sites = s; -} - Site* target(Context* c, unsigned size, Value* value) { @@ -1051,7 +1111,7 @@ target(Context* c, unsigned size, Value* value) { return value->reads->target; } else { - return freeRegister(c, size); + return freeRegister(c, size, true); } } @@ -1062,12 +1122,14 @@ compile(Context* c) Assembler::Register base(a->base()); Assembler::Register stack(a->stack()); - a->apply(Push, BytesPerWord, Register, &base); - a->apply(Move, BytesPerWord, Register, &stack, Register, &base); + a->apply(Push, BytesPerWord, RegisterOperand, &base); + a->apply(Move, BytesPerWord, RegisterOperand, &stack, + RegisterOperand, &base); if (c->stackOffset) { Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); - a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack); + a->apply(Subtract, BytesPerWord, ConstantOperand, &offset, + RegisterOperand, &stack); } for (Event* e = c->firstEvent; e; e = e->next) { @@ -1075,7 +1137,7 @@ compile(Context* c) li->machineOffset = a->length(); for (Read* r = e->reads; r; r = r->eventNext) { - Site* target = (r->target ? r->target->resolve(c) : 0); + Site* target = (r->target ? r->target->resolve(c, r->size) : 0); unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); @@ -1083,7 +1145,7 @@ compile(Context* c) if (site->type(c) == StackOperand) { for (Stack* s = e->stack; s; s = s->next) { if (s->pushed) { - target = ::target(t, s->size * BytesPerWord, s->value); + target = ::target(c, s->size * BytesPerWord, s->value); addSite(c, e->stack, s->size * BytesPerWord, s->value, target); @@ -1112,7 +1174,7 @@ compile(Context* c) } for (Write* w = e->writes; w; w = w->eventNext) { - w->value->target = target(t, w->size, w->value); + w->value->target = target(c, w->size, w->value); addSite(c, e->stack, w->size, w->value, w->value->target); } @@ -1160,7 +1222,7 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) Stack* stack(Context* c, Value* value, unsigned size, Stack* next) { - return stack(c, operand, size, (next ? next->index + size : 0), next); + return stack(c, value, size, (next ? next->index + size : 0), next); } void @@ -1169,8 +1231,6 @@ push(Context* c, unsigned size, Value* v) assert(c, ceiling(size, BytesPerWord)); c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack); - - appendPush(c); } Value* @@ -1179,7 +1239,7 @@ pop(Context* c, unsigned size UNUSED) Stack* s = c->state->stack; assert(c, ceiling(size, BytesPerWord) == s->size); - appendPop(c, s->size, false); + //appendPop(c, s->size, false); c->state->stack = s->next; return s->value; @@ -1298,7 +1358,7 @@ class MyCompiler: public Compiler { virtual void startLogicalIp(unsigned logicalIp) { if (c.logicalIp >= 0) { - c.logicalCode[c.logicalIp].lastEvent = c.event; + c.logicalCode[c.logicalIp].lastEvent = c.lastEvent; } c.logicalIp = logicalIp; @@ -1348,7 +1408,7 @@ class MyCompiler: public Compiler { Operand* index = 0, unsigned scale = 1) { - MyOperand* result = value(&c); + Value* result = value(&c); appendMemory(&c, static_cast(base), displacement, static_cast(index), scale, result); @@ -1369,13 +1429,19 @@ class MyCompiler: public Compiler { } virtual bool isConstant(Operand* a) { - return static_cast(a)->value - and static_cast(a)->value->type(&c) == ConstantOperand; + for (Site* s = static_cast(a)->sites; s; s = s->next) { + if (s->type(&c) == ConstantOperand) return true; + } + return false; } virtual int64_t constantValue(Operand* a) { - assert(&c, isConstant(a)); - return static_cast(a)->value->constantValue(&c); + for (Site* s = static_cast(a)->sites; s; s = s->next) { + if (s->type(&c) == ConstantOperand) { + return static_cast(s)->value.value->value(); + } + } + abort(&c); } virtual Operand* label() { @@ -1383,15 +1449,20 @@ class MyCompiler: public Compiler { } Promise* machineIp() { - return c.event->promises = new (c.zone->allocate(sizeof(CodePromise))) - CodePromise(&c, c.event->promises); + return c.lastEvent->promises = new (c.zone->allocate(sizeof(CodePromise))) + CodePromise(&c, c.lastEvent->promises); } virtual void mark(Operand* label) { appendStackSync(&c); - static_cast(static_cast(label)->value)->value - = machineIp(); + for (Site* s = static_cast(label)->sites; s; s = s->next) { + if (s->type(&c) == ConstantOperand) { + static_cast(s)->value.value = machineIp(); + return; + } + } + abort(&c); } virtual void push(unsigned size, Operand* value) { @@ -1411,7 +1482,7 @@ class MyCompiler: public Compiler { } virtual void popped(unsigned count) { - appendPop(&c, count, true); +// appendPop(&c, count, true); for (unsigned i = count; i;) { Stack* s = c.state->stack; @@ -1497,12 +1568,6 @@ class MyCompiler: public Compiler { return dst; } - virtual Operand* dup(unsigned size, Operand* src) { - Value* dst = value(&c); - appendDup(&c, size, static_cast(src), dst); - return dst; - } - virtual void cmp(unsigned size, Operand* a, Operand* b) { appendCompare(&c, size, static_cast(a), static_cast(b)); @@ -1547,7 +1612,7 @@ class MyCompiler: public Compiler { virtual void jmp(Operand* address) { appendStackSync(&c); - appendBranch(&c, Branch, static_cast(address)); + appendBranch(&c, Jump, static_cast(address)); } virtual Operand* add(unsigned size, Operand* a, Operand* b) { diff --git a/src/compiler.h b/src/compiler.h index d07d65ace6..5019968e37 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -77,7 +77,6 @@ class Compiler { virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; virtual Operand* load4To8(Operand* src) = 0; - virtual Operand* dup(unsigned size, Operand* src) = 0; virtual void cmp(unsigned size, Operand* a, Operand* b) = 0; virtual void jl(Operand* address) = 0; virtual void jg(Operand* address) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index eb2baf42cb..141815c278 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -287,6 +287,12 @@ conditional(Context* c, unsigned condition, Assembler::Constant* a) c->code.append4(0); } +void +moveCR(Context*, unsigned, Assembler::Constant*, Assembler::Register*); + +void +callR(Context*, unsigned, Assembler::Register*); + void callC(Context* c, unsigned size, Assembler::Constant* a) { @@ -400,9 +406,6 @@ jumpIfLessOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) conditional(c, 0x8e, a); } -void -moveCR(Context*, unsigned, Assembler::Constant*, Assembler::Register*); - void pushR(Context*, unsigned, Assembler::Register*); @@ -951,6 +954,11 @@ populateTables() { Operations[Return] = return_; + const int Constant = ConstantOperand; + const int Address = AddressOperand; + const int Register = RegisterOperand; + const int Memory = MemoryOperand; + UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM); From af2c2e019c7a615d2ff343a0341ffeeee3375a47 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 17 Apr 2008 18:39:41 -0600 Subject: [PATCH 027/121] various bugfixes --- src/compiler.cpp | 204 ++++++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 98 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 0d023eae4e..5a7b9428f0 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -20,6 +20,7 @@ class Value; class Stack; class Site; class Event; +class Read; void NO_RETURN abort(Context*); @@ -35,7 +36,7 @@ class Site { virtual ~Site() { } - virtual Site* resolve(Context*, unsigned) { return this; } + virtual Site* readTarget(Context*, Read*) { return this; } virtual unsigned copyCost(Context*, Site*) = 0; @@ -127,28 +128,16 @@ class Read { Read* eventNext; }; -class Write { - public: - Write(unsigned size, Value* value, Write* eventNext): - size(size), value(value), eventNext(eventNext) - { } - - unsigned size; - Value* value; - Write* eventNext; -}; - class Value: public Compiler::Operand { public: Value(Site* site): - reads(0), lastRead(0), sites(site), source(0), target(0) + reads(0), lastRead(0), sites(site), source(0) { } Read* reads; Read* lastRead; Site* sites; Site* source; - Site* target; }; class Context { @@ -205,6 +194,28 @@ addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) v->sites = s; } +bool +findSite(Context*, Value* v, Site* site) +{ + for (Site* s = v->sites; s; s = s->next) { + if (s == site) return true; + } + return false; +} + +void +removeSite(Context*, Value* v, Site* s) +{ + for (Site** p = &(v->sites); *p;) { + if (s == *p) { + *p = (*p)->next; + break; + } else { + p = &((*p)->next); + } + } +} + class ConstantSite: public Site { public: ConstantSite(Promise* value): value(value) { } @@ -381,8 +392,12 @@ class ValueSite: public AbstractSite { public: ValueSite(Value* value): value(value) { } - virtual Site* resolve(Context*, unsigned) { - return value->sites; + virtual Site* readTarget(Context* c, Read*) { + if (value->reads and value->reads->target) { + return value->reads->target->readTarget(c, value->reads); + } else { + return 0; + } } Value* value; @@ -396,8 +411,13 @@ valueSite(Context* c, Value* v) class AnyRegisterSite: public AbstractSite { public: - virtual Site* resolve(Context* c, unsigned size) { - return freeRegister(c, size, true); + virtual Site* readTarget(Context* c, Read* r) { + for (Site* s = r->value->sites; s; s = s->next) { + if (s->type(c) == RegisterOperand) { + return 0; + } + } + return freeRegister(c, r->size, true); } Value* value; @@ -516,7 +536,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) { Value* oldValue = c->registers[r].value; - if (oldValue) { + if (oldValue and findSite(c, oldValue, c->registers[r].site)) { if (oldValue->sites->next == 0 and oldValue->reads) { unsigned count = 0; Stack* start = 0; @@ -534,14 +554,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, stackSync(c, start, count); } - for (Site** p = &(oldValue->sites); *p;) { - if (c->registers[r].site == *p) { - *p = (*p)->next; - break; - } else { - p = &((*p)->next); - } - } + removeSite(c, oldValue, c->registers[r].site); } c->registers[r].size = newSize; @@ -641,7 +654,7 @@ class IpPromise: public Promise { class Event { public: Event(Context* c): - next(0), stack(c->state->stack), promises(0), reads(0), writes(0), + next(0), stack(c->state->stack), promises(0), reads(0), logicalIp(c->logicalIp) { assert(c, c->logicalIp >= 0); @@ -658,7 +671,7 @@ class Event { } Event(Context*, Event* next): - next(next), stack(next->stack), promises(0), reads(0), writes(0), + next(next), stack(next->stack), promises(0), reads(0), sequence(next->sequence), logicalIp(next->logicalIp) { } @@ -670,7 +683,6 @@ class Event { Stack* stack; CodePromise* promises; Read* reads; - Write* writes; unsigned sequence; unsigned logicalIp; }; @@ -711,20 +723,13 @@ addRead(Context* c, Value* v, unsigned size, Site* target) insertRead(c, c->lastEvent, 0, v, size, target); } -void -addWrite(Context* c, Value* v, unsigned size) -{ - c->lastEvent->writes = new (c->zone->allocate(sizeof(Write))) - Write(size, v, c->lastEvent->writes); -} - void push(Context* c, unsigned size, Value* v); class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned resultSize, + TraceHandler* traceHandler, Value* result, unsigned, Value** arguments, unsigned* argumentSizes, unsigned argumentCount): Event(c), @@ -758,10 +763,6 @@ class CallEvent: public Event { } c->state->stack = stack; - - if (result) { - addWrite(c, result, resultSize); - } } virtual void compile(Context* c) { @@ -775,6 +776,9 @@ class CallEvent: public Event { apply(c, type, BytesPerWord, address->source); } + addSite(c, 0, 0, result, registerSite + (c, c->assembler->returnLow(), c->assembler->returnHigh())); + if (traceHandler) { traceHandler->handleTrace (new (c->zone->allocate(sizeof(CodePromise))) @@ -841,6 +845,19 @@ appendReturn(Context* c, unsigned size, Value* value) new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } +Site* +writeTarget(Context* c, unsigned size, Value* v) +{ + if (v->sites) { + assert(c, v->sites->next == 0); + return v->sites; + } else if (v->reads and v->reads->target) { + Site* s = v->reads->target->readTarget(c, v->reads); + if (s) return s; + } + return freeRegister(c, size, true); +} + class MoveEvent: public Event { public: MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src, @@ -848,13 +865,14 @@ class MoveEvent: public Event { Event(c), type(type), size(size), src(src), dst(dst) { addRead(c, src, size, 0); - addWrite(c, dst, size); } virtual void compile(Context* c) { fprintf(stderr, "MoveEvent.compile\n"); - apply(c, type, size, src->source, dst->target); + Site* target = writeTarget(c, size, dst); + apply(c, type, size, src->source, target); + addSite(c, stack, size, dst, target); } BinaryOperation type; @@ -940,13 +958,14 @@ class CombineEvent: public Event { r2.low == NoRegister ? valueSite(c, result) : static_cast(registerSite(c, r2.low, r2.high))); - addWrite(c, result, size); } virtual void compile(Context* c) { fprintf(stderr, "CombineEvent.compile\n"); apply(c, type, size, first->source, second->source); + removeSite(c, second, second->source); + addSite(c, 0, 0, result, second->source); } BinaryOperation type; @@ -971,13 +990,14 @@ class TranslateEvent: public Event { Event(c), type(type), size(size), value(value), result(result) { addRead(c, value, size, valueSite(c, result)); - addWrite(c, result, size); } virtual void compile(Context* c) { fprintf(stderr, "TranslateEvent.compile\n"); apply(c, type, size, value->source); + removeSite(c, value, value->source); + addSite(c, 0, 0, result, value->source); } UnaryOperation type; @@ -1008,18 +1028,15 @@ class MemoryEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "MemoryEvent.compile\n"); - int baseRegister; int indexRegister; - Read* read = reads; if (index) { - assert(c, read->target->type(c) == RegisterOperand); - indexRegister = static_cast(read->target)->register_.low; - read = read->eventNext; + assert(c, index->source->type(c) == RegisterOperand); + indexRegister = static_cast(index->source)->register_.low; } else { indexRegister = NoRegister; } - assert(c, read->target->type(c) == RegisterOperand); - baseRegister = static_cast(read->target)->register_.low; + assert(c, base->source->type(c) == RegisterOperand); + int baseRegister = static_cast(base->source)->register_.low; addSite(c, 0, 0, result, memorySite (c, baseRegister, displacement, indexRegister, scale)); @@ -1103,15 +1120,43 @@ appendStackSync(Context* c, bool forCall = false) } Site* -target(Context* c, unsigned size, Value* value) +readSource(Context* c, Stack* stack, Read* r) { - if (value->reads - and value->reads->target - and not value->reads->target->type(c) == StackOperand) - { - return value->reads->target; + Site* target = (r->target ? r->target->readTarget(c, r) : 0); + + unsigned copyCost; + Site* site = pick(c, r->value->sites, target, ©Cost); + + if (site->type(c) == StackOperand) { + bool success = false;; + for (Stack* s = stack; s; s = s->next) { + if (s->pushed) { + target = writeTarget(c, s->size * BytesPerWord, s->value); + + addSite(c, stack, s->size * BytesPerWord, s->value, target); + + s->pushed = false; + if (s == static_cast(site)->stack) { + site = pick(c, r->value->sites, target, ©Cost); + success = true; + break; + } + } + } + + assert(c, success); + } + + if (target) { + if (copyCost) { + addSite(c, stack, r->size, r->value, target); + + target->accept(c, r->size, site); + } + + return target; } else { - return freeRegister(c, size, true); + return site; } } @@ -1137,48 +1182,11 @@ compile(Context* c) li->machineOffset = a->length(); for (Read* r = e->reads; r; r = r->eventNext) { - Site* target = (r->target ? r->target->resolve(c, r->size) : 0); - - unsigned copyCost; - Site* site = pick(c, r->value->sites, target, ©Cost); - - if (site->type(c) == StackOperand) { - for (Stack* s = e->stack; s; s = s->next) { - if (s->pushed) { - target = ::target(c, s->size * BytesPerWord, s->value); - - addSite(c, e->stack, s->size * BytesPerWord, s->value, target); - - s->pushed = false; - if (s == static_cast(site)->stack) { - site = pick(c, r->value->sites, target, ©Cost); - break; - } - } - } - } - - if (target) { - if (copyCost) { - addSite(c, e->stack, r->size, r->value, target); - - target->accept(c, r->size, site); - } - - r->value->source = target; - } else { - r->value->source = site; - } + r->value->source = readSource(c, e->stack, r); r->value->reads = r->value->reads->next; } - for (Write* w = e->writes; w; w = w->eventNext) { - w->value->target = target(c, w->size, w->value); - - addSite(c, e->stack, w->size, w->value, w->value->target); - } - e->compile(c); for (CodePromise* p = e->promises; p; p = p->next) { From 329009ae972b2a8f0559a0cd64ae1051f98994d5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 17 Apr 2008 21:47:42 -0600 Subject: [PATCH 028/121] bugfixes involving stack operations --- src/assembler.h | 3 +- src/compiler.cpp | 285 +++++++++++++++++++++++++++++------------------ 2 files changed, 180 insertions(+), 108 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index ac56f300ec..f84dd37b34 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -54,8 +54,7 @@ enum OperandType { ConstantOperand, AddressOperand, RegisterOperand, - MemoryOperand, - StackOperand // for compiler use; not used in assembler + MemoryOperand }; const unsigned OperandTypeCount = MemoryOperand + 1; diff --git a/src/compiler.cpp b/src/compiler.cpp index 5a7b9428f0..fb38dd1be5 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -20,6 +20,7 @@ class Value; class Stack; class Site; class Event; +class PushEvent; class Read; void NO_RETURN abort(Context*); @@ -39,10 +40,6 @@ class Site { virtual Site* readTarget(Context*, Read*) { return this; } virtual unsigned copyCost(Context*, Site*) = 0; - - virtual void accept(Context* c, unsigned size, Site* src) { - apply(c, Move, size, src, this); - } virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } @@ -56,13 +53,15 @@ class Site { class Stack { public: Stack(Value* value, unsigned size, unsigned index, Stack* next): - value(value), size(size), index(index), next(next), pushed(false) + value(value), size(size), index(index), next(next), pushEvent(0), + pushed(false) { } Value* value; unsigned size; unsigned index; Stack* next; + PushEvent* pushEvent; bool pushed; }; @@ -131,13 +130,14 @@ class Read { class Value: public Compiler::Operand { public: Value(Site* site): - reads(0), lastRead(0), sites(site), source(0) + reads(0), lastRead(0), sites(site), source(0), pushCount(0) { } Read* reads; Read* lastRead; Site* sites; Site* source; + unsigned pushCount; }; class Context { @@ -429,35 +429,6 @@ anyRegisterSite(Context* c) return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite(); } -class StackSite: public Site { - public: - StackSite(Stack* stack): stack(stack) { } - - virtual unsigned copyCost(Context*, Site*) { - return 5; - } - - virtual void accept(Context* c, unsigned size, Site* src) { - apply(c, Push, size, src); - } - - virtual OperandType type(Context*) { - return StackOperand; - } - - virtual Assembler::Operand* asAssemblerOperand(Context* c) { - abort(c); - } - - Stack* stack; -}; - -StackSite* -stackSite(Context* c, Stack* s) -{ - return new (c->zone->allocate(sizeof(StackSite))) StackSite(s); -} - inline void NO_RETURN abort(Context* c) { @@ -502,7 +473,7 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) } void -stackSync(Context* c, Stack* start, unsigned count) +syncStack(Context* c, Stack* start, unsigned count) { Stack* segment[count]; unsigned index = count; @@ -512,13 +483,11 @@ stackSync(Context* c, Stack* start, unsigned count) for (unsigned i = 0; i < count; ++i) { Stack* s = segment[i]; + assert(c, not s->pushed); if (s->value) { apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); - - StackSite* site = stackSite(c, s); - site->next = s->value->sites; - s->value->sites = site; + ++ s->value->pushCount; } else { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); @@ -527,20 +496,36 @@ stackSync(Context* c, Stack* start, unsigned count) RegisterOperand, &stack); } + fprintf(stderr, "pushed %p\n", s); + s->pushed = true; } } +void +syncStack(Context* c, Stack* start) +{ + unsigned count = 0; + for (Stack* s = start; s and (not s->pushed); s = s->next) { + ++ count; + } + + syncStack(c, start, count); +} + void acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) { Value* oldValue = c->registers[r].value; if (oldValue and findSite(c, oldValue, c->registers[r].site)) { - if (oldValue->sites->next == 0 and oldValue->reads) { + if (oldValue->pushCount == 0 + and oldValue->sites->next == 0 + and oldValue->reads) + { unsigned count = 0; Stack* start = 0; - for (Stack* s = stack; s and not s->pushed; s = s->next) { + for (Stack* s = stack; s and (not s->pushed); s = s->next) { if (s->value == oldValue) { start = s; } @@ -551,7 +536,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, assert(c, start); - stackSync(c, start, count); + syncStack(c, start, count); } removeSite(c, oldValue, c->registers[r].site); @@ -729,40 +714,18 @@ push(Context* c, unsigned size, Value* v); class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned, - Value** arguments, unsigned* argumentSizes, - unsigned argumentCount): + TraceHandler* traceHandler, Value* result, + unsigned argumentFootprint): Event(c), address(address), indirection(indirection), traceHandler(traceHandler), result(result), flags(flags), - footprint(0) + argumentFootprint(argumentFootprint) { addRead(c, address, BytesPerWord, (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); - - for (int i = argumentCount - 1; i >= 0; --i) { - ::push(c, argumentSizes[i], arguments[i]); - } - - unsigned index = 0; - Stack* s = c->state->stack; - for (unsigned i = 0; i < argumentCount; ++i) { - Site* target; - if (index < c->assembler->argumentRegisterCount()) { - target = registerSite(c, c->assembler->argumentRegister(index)); - } else { - target = stackSite(c, s); - footprint += s->size; - } - addRead(c, s->value, s->size * BytesPerWord, target); - index += s->size; - s = s->next; - } - - c->state->stack = stack; } virtual void compile(Context* c) { @@ -785,9 +748,10 @@ class CallEvent: public Event { CodePromise(c, c->assembler->length())); } - if (footprint) { + if (argumentFootprint) { Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, footprint * BytesPerWord)); + Assembler::Constant offset + (resolved(c, argumentFootprint * BytesPerWord)); c->assembler->apply (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); } @@ -798,17 +762,19 @@ class CallEvent: public Event { TraceHandler* traceHandler; Value* result; unsigned flags; - unsigned footprint; + unsigned argumentFootprint; }; void appendCall(Context* c, Value* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned resultSize, - Value** arguments, unsigned* argumentSizes, unsigned argumentCount) + TraceHandler* traceHandler, Value* result, + unsigned argumentFootprint) { + fprintf(stderr, "appendCall\n"); + new (c->zone->allocate(sizeof(CallEvent))) CallEvent(c, address, indirection, flags, traceHandler, result, - resultSize, arguments, argumentSizes, argumentCount); + argumentFootprint); } class ReturnEvent: public Event { @@ -842,6 +808,8 @@ class ReturnEvent: public Event { void appendReturn(Context* c, unsigned size, Value* value) { + fprintf(stderr, "appendReturn\n"); + new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } @@ -885,6 +853,8 @@ void appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, Value* dst) { + fprintf(stderr, "appendMove\n"); + new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, size, src, dst); } @@ -913,6 +883,8 @@ class CompareEvent: public Event { void appendCompare(Context* c, unsigned size, Value* first, Value* second) { + fprintf(stderr, "appendCompare\n"); + new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, first, second); } @@ -938,6 +910,8 @@ class BranchEvent: public Event { void appendBranch(Context* c, UnaryOperation type, Value* address) { + fprintf(stderr, "appendBranch\n"); + new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); } @@ -979,6 +953,8 @@ void appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Value* second, Value* result) { + fprintf(stderr, "appendCombine\n"); + new (c->zone->allocate(sizeof(CombineEvent))) CombineEvent(c, type, size, first, second, result); } @@ -1010,6 +986,8 @@ void appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, Value* result) { + fprintf(stderr, "appendTranslate\n"); + new (c->zone->allocate(sizeof(TranslateEvent))) TranslateEvent(c, type, size, value, result); } @@ -1053,6 +1031,8 @@ void appendMemory(Context* c, Value* base, int displacement, Value* index, unsigned scale, Value* result) { + fprintf(stderr, "appendMemory\n"); + new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, base, displacement, index, scale, result); } @@ -1081,13 +1061,13 @@ stackSyncSite(Context* c, unsigned index, unsigned size) class StackSyncEvent: public Event { public: - StackSyncEvent(Context* c, bool forCall): + StackSyncEvent(Context* c): Event(c) { unsigned i = 0; for (Stack* s = stack; s; s = s->next) { addRead(c, s->value, s->size * BytesPerWord, - forCall ? stackSite(c, s) : stackSyncSite(c, i, s->size)); + stackSyncSite(c, i, s->size)); i += s->size; } } @@ -1114,9 +1094,97 @@ class StackSyncEvent: public Event { }; void -appendStackSync(Context* c, bool forCall = false) +appendStackSync(Context* c) { - new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c, forCall); + fprintf(stderr, "appendStackSync\n"); + + new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c); +} + +class PushEvent: public Event { + public: + PushEvent(Context* c): + Event(c), active(false) + { + stack->pushEvent = this; + } + + virtual void compile(Context* c) { + fprintf(stderr, "PushEvent.compile\n"); + + if (active) { + syncStack(c, stack); + } + } + + bool active; +}; + +void +appendPush(Context* c) +{ + fprintf(stderr, "appendPush\n"); + + new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); +} + +class PopEvent: public Event { + public: + PopEvent(Context* c, unsigned count, bool ignore): + Event(c), count(count), ignore(ignore) + { } + + virtual void compile(Context* c) { + fprintf(stderr, "PopEvent.compile\n"); + + Stack* s = stack; + unsigned ignored = 0; + for (unsigned i = count; i;) { + if (s->pushed) { + if (s->value->reads and (not ignore)) { + assert(c, ignored == 0); + + fprintf(stderr, "pop %p\n", s); + + Site* target = writeTarget(c, s->size * BytesPerWord, s->value); + + apply(c, Pop, BytesPerWord * s->size, target); + -- s->value->pushCount; + + addSite(c, stack, s->size * BytesPerWord, s->value, target); + } else { + fprintf(stderr, "ignore %p\n", s); + + ignored += s->size; + } + + s->pushed = false; + } else { + fprintf(stderr, "%p not pushed\n", s); + } + + i -= s->size; + s = s->next; + } + + if (ignored) { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); + c->assembler->apply + (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); + } + } + + unsigned count; + bool ignore; +}; + +void +appendPop(Context* c, unsigned count, bool ignore) +{ + fprintf(stderr, "appendPop\n"); + + new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } Site* @@ -1127,31 +1195,11 @@ readSource(Context* c, Stack* stack, Read* r) unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); - if (site->type(c) == StackOperand) { - bool success = false;; - for (Stack* s = stack; s; s = s->next) { - if (s->pushed) { - target = writeTarget(c, s->size * BytesPerWord, s->value); - - addSite(c, stack, s->size * BytesPerWord, s->value, target); - - s->pushed = false; - if (s == static_cast(site)->stack) { - site = pick(c, r->value->sites, target, ©Cost); - success = true; - break; - } - } - } - - assert(c, success); - } - if (target) { if (copyCost) { addSite(c, stack, r->size, r->value, target); - target->accept(c, r->size, site); + apply(c, Move, r->size, site, target); } return target; @@ -1239,6 +1287,8 @@ push(Context* c, unsigned size, Value* v) assert(c, ceiling(size, BytesPerWord)); c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack); + + appendPush(c); } Value* @@ -1247,7 +1297,7 @@ pop(Context* c, unsigned size UNUSED) Stack* s = c->state->stack; assert(c, ceiling(size, BytesPerWord) == s->size); - //appendPop(c, s->size, false); + appendPop(c, s->size, false); c->state->stack = s->next; return s->value; @@ -1485,12 +1535,11 @@ class MyCompiler: public Compiler { for (unsigned i = 0; i < count; ++i) { Value* a = value(&c); ::push(&c, BytesPerWord, a); - a->sites = stackSite(&c, c.state->stack); } } virtual void popped(unsigned count) { -// appendPop(&c, count, true); + appendPop(&c, count, true); for (unsigned i = count; i;) { Stack* s = c.state->stack; @@ -1513,7 +1562,7 @@ class MyCompiler: public Compiler { void* indirection, unsigned flags, TraceHandler* traceHandler, - unsigned resultSize, + unsigned, unsigned argumentCount, ...) { @@ -1539,12 +1588,36 @@ class MyCompiler: public Compiler { va_end(a); - appendStackSync(&c, true); + Stack* oldStack = c.state->stack; + + for (int i = index - 1; i >= 0; --i) { + ::push(&c, argumentSizes[i], arguments[i]); + } + + unsigned ai = 0; + Stack* s = c.state->stack; + for (unsigned i = 0; i < index; ++i) { + Site* target; + if (ai < c.assembler->argumentRegisterCount()) { + target = registerSite(&c, c.assembler->argumentRegister(index)); + } else { + target = 0; + s->pushEvent->active = true; + } + addRead(&c, s->value, s->size * BytesPerWord, target); + ai += s->size; + s = s->next; + } + + c.state->stack = oldStack; + + for (Stack* s = oldStack; s; s = s->next) { + s->pushEvent->active = true; + } Value* result = value(&c); appendCall(&c, static_cast(address), indirection, flags, - traceHandler, result, resultSize, arguments, argumentSizes, - index); + traceHandler, result, footprint); return result; } From 44b3a7c36da805ed969ba3c6dcf6c1127875edd8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 17 Apr 2008 22:16:20 -0600 Subject: [PATCH 029/121] various bugfixes --- src/compile.cpp | 14 +++++++++++--- src/compiler.cpp | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index f2400ec469..d04732e124 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3810,6 +3810,14 @@ finish(MyThread* t, Context* context) set(t, methodCode(t, context->method), CodePool, map); } + for (PoolElement* p = context->objectPool; p; p = p->next) { + intptr_t offset = p->address->value() - reinterpret_cast(start); + + singletonMarkObject(t, result, offset / BytesPerWord); + + set(t, result, SingletonBody + offset, p->value); + } + if (Verbose) { logCompile (start, codeSize, @@ -3822,15 +3830,15 @@ finish(MyThread* t, Context* context) } // for debugging: - if (false and + if (true or//false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/System") == 0 and + "Misc") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "getProperty") == 0) + "main") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index fb38dd1be5..f6372f6cd2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -518,7 +518,10 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) { Value* oldValue = c->registers[r].value; - if (oldValue and findSite(c, oldValue, c->registers[r].site)) { + if (oldValue + and oldValue != newValue + and findSite(c, oldValue, c->registers[r].site)) + { if (oldValue->pushCount == 0 and oldValue->sites->next == 0 and oldValue->reads) @@ -714,7 +717,7 @@ push(Context* c, unsigned size, Value* v); class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, Value* result, + TraceHandler* traceHandler, Value* result, unsigned resultSize, unsigned argumentFootprint): Event(c), address(address), @@ -722,6 +725,7 @@ class CallEvent: public Event { traceHandler(traceHandler), result(result), flags(flags), + resultSize(resultSize), argumentFootprint(argumentFootprint) { addRead(c, address, BytesPerWord, @@ -740,7 +744,9 @@ class CallEvent: public Event { } addSite(c, 0, 0, result, registerSite - (c, c->assembler->returnLow(), c->assembler->returnHigh())); + (c, c->assembler->returnLow(), + resultSize > BytesPerWord ? + c->assembler->returnHigh() : NoRegister)); if (traceHandler) { traceHandler->handleTrace @@ -762,19 +768,20 @@ class CallEvent: public Event { TraceHandler* traceHandler; Value* result; unsigned flags; + unsigned resultSize; unsigned argumentFootprint; }; void appendCall(Context* c, Value* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, Value* result, + TraceHandler* traceHandler, Value* result, unsigned resultSize, unsigned argumentFootprint) { fprintf(stderr, "appendCall\n"); new (c->zone->allocate(sizeof(CallEvent))) CallEvent(c, address, indirection, flags, traceHandler, result, - argumentFootprint); + resultSize, argumentFootprint); } class ReturnEvent: public Event { @@ -1319,20 +1326,31 @@ updateJunctions(Context* c) } } +bool +used(Context* c, int r) +{ + Value* v = c->registers[r].value; + return v + and findSite(c, v, c->registers[r].site) + and v->pushCount == 0 + and v->sites->next == 0 + and v->reads; +} + int freeRegisterExcept(Context* c, int except, bool allowAcquired) { - for (int i = c->assembler->registerCount(); i >= 0; --i) { + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except and (not c->registers[i].reserved) - and c->registers[i].value == 0) + and (not used(c, i))) { return i; } } if (allowAcquired) { - for (int i = c->assembler->registerCount(); i >= 0; --i) { + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except and (not c->registers[i].reserved)) { @@ -1562,7 +1580,7 @@ class MyCompiler: public Compiler { void* indirection, unsigned flags, TraceHandler* traceHandler, - unsigned, + unsigned resultSize, unsigned argumentCount, ...) { @@ -1617,7 +1635,7 @@ class MyCompiler: public Compiler { Value* result = value(&c); appendCall(&c, static_cast(address), indirection, flags, - traceHandler, result, footprint); + traceHandler, result, resultSize, footprint); return result; } From c1ba7a7d587748bd3b55fa492d9e1dad2ee586f8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 18 Apr 2008 11:00:55 -0600 Subject: [PATCH 030/121] optimize op,move sequences where op can place its result directly into the move's destination --- src/compiler.cpp | 340 ++++++++++++++++++++++++++--------------------- 1 file changed, 191 insertions(+), 149 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index f6372f6cd2..dce67f8121 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -37,7 +37,7 @@ class Site { virtual ~Site() { } - virtual Site* readTarget(Context*, Read*) { return this; } + virtual Site* readTarget(Context*, Read*, Event*) { return this; } virtual unsigned copyCost(Context*, Site*) = 0; @@ -186,6 +186,130 @@ class Context { uint8_t* machineCode; }; +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 + pad(c->assembler->length()) + (key * BytesPerWord)); + } + + 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) { } + + CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } + + 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; +}; + +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); +} + +class Event { + public: + Event(Context* c): + next(0), stack(c->state->stack), promises(0), reads(0), + logicalIp(c->logicalIp) + { + assert(c, c->logicalIp >= 0); + + if (c->lastEvent) { + c->lastEvent->next = this; + sequence = c->lastEvent->sequence + 1; + } else { + c->firstEvent = this; + sequence = 0; + } + + c->lastEvent = this; + } + + Event(Context*, Event* next): + next(next), stack(next->stack), promises(0), reads(0), + sequence(next->sequence), logicalIp(next->logicalIp) + { } + + virtual ~Event() { } + + virtual void compile(Context* c) = 0; + + Event* next; + Stack* stack; + CodePromise* promises; + Read* reads; + unsigned sequence; + unsigned logicalIp; +}; + void addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { @@ -388,13 +512,38 @@ class AbstractSite: public Site { } }; +Site* +targetOrNull(Context* c, Value* v, Event* event) +{ + if (v->sites) { + assert(c, v->sites->next == 0); + return v->sites; + } else if (v->reads and v->reads->target) { + return v->reads->target->readTarget(c, v->reads, event); + } else { + return 0; + } +} + +Site* +targetOrRegister(Context* c, unsigned size, Value* v, Event* event) +{ + Site* s = targetOrNull(c, v, event); + if (s) { + return s; + } else { + return freeRegister(c, size, true); + } +} + class ValueSite: public AbstractSite { public: ValueSite(Value* value): value(value) { } - virtual Site* readTarget(Context* c, Read*) { - if (value->reads and value->reads->target) { - return value->reads->target->readTarget(c, value->reads); + virtual Site* readTarget(Context* c, Read*, Event* event) { + Site* s = targetOrNull(c, value, event); + if (s->type(c) == RegisterOperand) { + return s; } else { return 0; } @@ -409,9 +558,30 @@ valueSite(Context* c, Value* v) return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v); } +class MoveSite: public AbstractSite { + public: + MoveSite(Value* value): value(value) { } + + virtual Site* readTarget(Context* c, Read* read, Event* event) { + if (read->event->sequence == event->sequence + 1) { + return targetOrNull(c, value, event); + } else { + return 0; + } + } + + Value* value; +}; + +MoveSite* +moveSite(Context* c, Value* v) +{ + return new (c->zone->allocate(sizeof(MoveSite))) MoveSite(v); +} + class AnyRegisterSite: public AbstractSite { public: - virtual Site* readTarget(Context* c, Read* r) { + virtual Site* readTarget(Context* c, Read* r, Event*) { for (Site* s = r->value->sites; s; s = s->next) { if (s->type(c) == RegisterOperand) { return 0; @@ -429,26 +599,6 @@ anyRegisterSite(Context* c) return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite(); } -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); -} - Value* value(Context* c, Site* site = 0) { @@ -571,110 +721,6 @@ apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b) 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 + pad(c->assembler->length()) + (key * BytesPerWord)); - } - - 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) { } - - CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } - - 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; -}; - -class Event { - public: - Event(Context* c): - next(0), stack(c->state->stack), promises(0), reads(0), - logicalIp(c->logicalIp) - { - assert(c, c->logicalIp >= 0); - - if (c->lastEvent) { - c->lastEvent->next = this; - sequence = c->lastEvent->sequence + 1; - } else { - c->firstEvent = this; - sequence = 0; - } - - c->lastEvent = this; - } - - Event(Context*, Event* next): - next(next), stack(next->stack), promises(0), reads(0), - sequence(next->sequence), logicalIp(next->logicalIp) - { } - - virtual ~Event() { } - - virtual void compile(Context* c) = 0; - - Event* next; - Stack* stack; - CodePromise* promises; - Read* reads; - unsigned sequence; - unsigned logicalIp; -}; - void insertRead(Context* c, Event* thisEvent, Event* before, Value* v, unsigned size, Site* target) @@ -820,33 +866,28 @@ appendReturn(Context* c, unsigned size, Value* value) new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } -Site* -writeTarget(Context* c, unsigned size, Value* v) -{ - if (v->sites) { - assert(c, v->sites->next == 0); - return v->sites; - } else if (v->reads and v->reads->target) { - Site* s = v->reads->target->readTarget(c, v->reads); - if (s) return s; - } - return freeRegister(c, size, true); -} - class MoveEvent: public Event { public: MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src, Value* dst): Event(c), type(type), size(size), src(src), dst(dst) { - addRead(c, src, size, 0); + Site* target; + if (type == Move and size >= BytesPerWord) { + target = moveSite(c, dst); + } else { + target = 0; + } + addRead(c, src, size, target); } virtual void compile(Context* c) { fprintf(stderr, "MoveEvent.compile\n"); - Site* target = writeTarget(c, size, dst); - apply(c, type, size, src->source, target); + Site* target = targetOrRegister(c, size, dst, this); + if (src->source->copyCost(c, target)) { + apply(c, type, size, src->source, target); + } addSite(c, stack, size, dst, target); } @@ -1153,7 +1194,8 @@ class PopEvent: public Event { fprintf(stderr, "pop %p\n", s); - Site* target = writeTarget(c, s->size * BytesPerWord, s->value); + Site* target = targetOrRegister + (c, s->size * BytesPerWord, s->value, this); apply(c, Pop, BytesPerWord * s->size, target); -- s->value->pushCount; @@ -1195,9 +1237,9 @@ appendPop(Context* c, unsigned count, bool ignore) } Site* -readSource(Context* c, Stack* stack, Read* r) +readSource(Context* c, Stack* stack, Read* r, Event* e) { - Site* target = (r->target ? r->target->readTarget(c, r) : 0); + Site* target = (r->target ? r->target->readTarget(c, r, e) : 0); unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); @@ -1237,7 +1279,7 @@ compile(Context* c) li->machineOffset = a->length(); for (Read* r = e->reads; r; r = r->eventNext) { - r->value->source = readSource(c, e->stack, r); + r->value->source = readSource(c, e->stack, r, e); r->value->reads = r->value->reads->next; } From a053a228f017e86b3e1e5564f6de5857c7103e85 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 18 Apr 2008 11:30:54 -0600 Subject: [PATCH 031/121] optimize move,op sequences where op doesn't care where its source operand comes from --- src/compiler.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index dce67f8121..9bfaaf7f93 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -512,6 +512,20 @@ class AbstractSite: public Site { } }; +Site* +targetOrNull(Context* c, Read* r, Event* event) +{ + Value* v = r->value; + if (v->sites) { + assert(c, v->sites->next == 0); + return v->sites; + } else if (r->target) { + return r->target->readTarget(c, r, event); + } else { + return 0; + } +} + Site* targetOrNull(Context* c, Value* v, Event* event) { @@ -563,7 +577,7 @@ class MoveSite: public AbstractSite { MoveSite(Value* value): value(value) { } virtual Site* readTarget(Context* c, Read* read, Event* event) { - if (read->event->sequence == event->sequence + 1) { + if (event->next == read->event) { return targetOrNull(c, value, event); } else { return 0; @@ -884,9 +898,18 @@ class MoveEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "MoveEvent.compile\n"); - Site* target = targetOrRegister(c, size, dst, this); - if (src->source->copyCost(c, target)) { - apply(c, type, size, src->source, target); + Site* target; + if (type == Move + and size >= BytesPerWord + and dst->reads + and next == dst->reads->event) + { + target = src->source; + } else { + target = targetOrRegister(c, size, dst, this); + if (src->source->copyCost(c, target)) { + apply(c, type, size, src->source, target); + } } addSite(c, stack, size, dst, target); } @@ -1149,12 +1172,16 @@ appendStackSync(Context* c) new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c); } +Site* +pushSite(Context*, PushEvent*); + class PushEvent: public Event { public: PushEvent(Context* c): Event(c), active(false) { stack->pushEvent = this; + addRead(c, stack->value, stack->size * BytesPerWord, pushSite(c, this)); } virtual void compile(Context* c) { @@ -1168,6 +1195,27 @@ class PushEvent: public Event { bool active; }; +class PushSite: public AbstractSite { + public: + PushSite(PushEvent* event): event(event) { } + + virtual Site* readTarget(Context* c, Read* r, Event* e) { + if (r->next and (not event->active)) { + return targetOrNull(c, r->next, e); + } else { + return 0; + } + } + + PushEvent* event; +}; + +Site* +pushSite(Context* c, PushEvent* e) +{ + return new (c->zone->allocate(sizeof(PushSite))) PushSite(e); +} + void appendPush(Context* c) { From 8fd1290d02e5a3f995b527e4af4292d584c504b8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 18 Apr 2008 12:36:57 -0600 Subject: [PATCH 032/121] various data flow bugfixes --- src/compiler.cpp | 66 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 9bfaaf7f93..d484cc7a65 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -344,8 +344,8 @@ class ConstantSite: public Site { public: ConstantSite(Promise* value): value(value) { } - virtual unsigned copyCost(Context*, Site*) { - return 1; + virtual unsigned copyCost(Context*, Site* s) { + return (s == this ? 0 : 1); } virtual OperandType type(Context*) { @@ -382,8 +382,8 @@ class AddressSite: public Site { public: AddressSite(Promise* address): address(address) { } - virtual unsigned copyCost(Context*, Site*) { - return 3; + virtual unsigned copyCost(Context*, Site* s) { + return (s == this ? 0 : 3); } virtual OperandType type(Context*) { @@ -554,12 +554,12 @@ class ValueSite: public AbstractSite { public: ValueSite(Value* value): value(value) { } - virtual Site* readTarget(Context* c, Read*, Event* event) { + virtual Site* readTarget(Context* c, Read* r, Event* event) { Site* s = targetOrNull(c, value, event); - if (s->type(c) == RegisterOperand) { + if (s and s->type(c) == RegisterOperand) { return s; } else { - return 0; + return freeRegister(c, r->size, true); } } @@ -598,13 +598,11 @@ class AnyRegisterSite: public AbstractSite { virtual Site* readTarget(Context* c, Read* r, Event*) { for (Site* s = r->value->sites; s; s = s->next) { if (s->type(c) == RegisterOperand) { - return 0; + return s; } } return freeRegister(c, r->size, true); } - - Value* value; }; AnyRegisterSite* @@ -613,6 +611,26 @@ anyRegisterSite(Context* c) return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite(); } +class ConstantOrRegisterSite: public AbstractSite { + public: + virtual Site* readTarget(Context* c, Read* r, Event*) { + for (Site* s = r->value->sites; s; s = s->next) { + OperandType t = s->type(c); + if (t == ConstantOperand or t == RegisterOperand) { + return s; + } + } + return freeRegister(c, r->size, true); + } +}; + +ConstantOrRegisterSite* +constantOrRegisterSite(Context* c) +{ + return new (c->zone->allocate(sizeof(ConstantOrRegisterSite))) + ConstantOrRegisterSite(); +} + Value* value(Context* c, Site* site = 0) { @@ -998,7 +1016,9 @@ class CombineEvent: public Event { c->assembler->getTargets(type, size, &r1, &r2); addRead(c, first, size, - r1.low == NoRegister ? 0 : registerSite(c, r1.low, r1.high)); + r1.low == NoRegister ? + constantOrRegisterSite(c) : + static_cast(registerSite(c, r1.low, r1.high))); addRead(c, second, size, r2.low == NoRegister ? valueSite(c, result) : @@ -1328,7 +1348,9 @@ compile(Context* c) for (Read* r = e->reads; r; r = r->eventNext) { r->value->source = readSource(c, e->stack, r, e); + } + for (Read* r = e->reads; r; r = r->eventNext) { r->value->reads = r->value->reads->next; } @@ -1420,11 +1442,16 @@ bool used(Context* c, int r) { Value* v = c->registers[r].value; - return v - and findSite(c, v, c->registers[r].site) + return v and findSite(c, v, c->registers[r].site) and v->reads; +} + +bool +usedExclusively(Context* c, int r) +{ + Value* v = c->registers[r].value; + return used(c, r) and v->pushCount == 0 - and v->sites->next == 0 - and v->reads; + and v->sites->next == 0; } int @@ -1439,6 +1466,15 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) } } + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (i != except + and (not c->registers[i].reserved) + and (not usedExclusively(c, i))) + { + return i; + } + } + if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except From ab7314e526dbcb8bddbca959b6ac1cbd38a94ced Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 18 Apr 2008 18:19:45 -0600 Subject: [PATCH 033/121] more bugfixes --- src/compile.cpp | 22 ++- src/compiler.cpp | 378 ++++++++++++++++++++++++++++++++--------------- src/x86.cpp | 12 +- 3 files changed, 292 insertions(+), 120 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index d04732e124..0d681d8acf 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1744,12 +1744,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } else { throw_ = c->label(); c->cmp(4, c->constant(0), index); + + frame->pushObject(array); + frame->pushInt(index); + c->jl(throw_); + + index = frame->popInt(); + array = frame->popObject(); } c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); + + frame->pushObject(array); + frame->pushInt(index); + c->jge(load); + index = frame->popInt(); + array = frame->popObject(); + if (not c->isConstant(index)) { c->mark(throw_); } @@ -1762,7 +1776,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, 0, 3, c->thread(), array, index); + frame->pushObject(array); + frame->pushInt(index); + c->mark(load); + + index = frame->popInt(); + array = frame->popObject(); } if (c->isConstant(index)) { @@ -3830,7 +3850,7 @@ finish(MyThread* t, Context* context) } // for debugging: - if (true or//false and + if (false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), diff --git a/src/compiler.cpp b/src/compiler.cpp index d484cc7a65..386eb0fbd8 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -43,6 +43,8 @@ class Site { virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } + virtual void release(Context*) { } + virtual OperandType type(Context*) = 0; virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; @@ -89,6 +91,7 @@ class Register { Value* value; Site* site; unsigned size; + unsigned refCount; bool reserved; }; @@ -163,8 +166,11 @@ class Context { { memset(registers, 0, sizeof(Register) * assembler->registerCount()); + registers[assembler->base()].refCount = 1; registers[assembler->base()].reserved = true; + registers[assembler->stack()].refCount = 1; registers[assembler->stack()].reserved = true; + registers[assembler->thread()].refCount = 1; registers[assembler->thread()].reserved = true; } @@ -310,14 +316,6 @@ class Event { unsigned logicalIp; }; -void -addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) -{ - s->acquire(c, stack, size, v, s); - s->next = v->sites; - v->sites = s; -} - bool findSite(Context*, Value* v, Site* site) { @@ -327,11 +325,23 @@ findSite(Context*, Value* v, Site* site) return false; } +void +addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) +{ + if (not findSite(c, v, s)) { + fprintf(stderr, "add site %p to %p\n", s, v); + s->acquire(c, stack, size, v, s); + s->next = v->sites; + v->sites = s; + } +} + void removeSite(Context*, Value* v, Site* s) { for (Site** p = &(v->sites); *p;) { if (s == *p) { + fprintf(stderr, "remove site %p from %p\n", s, v); *p = (*p)->next; break; } else { @@ -340,6 +350,18 @@ removeSite(Context*, Value* v, Site* s) } } +void +nextRead(Context* c, Value* v) +{ + fprintf(stderr, "pop read %p from %p; next: %p\n", v->reads, v, v->reads->next); + v->reads = v->reads->next; + if (v->reads == 0) { + for (Site* s = v->sites; s; s = s->next) { + s->release(c); + } + } +} + class ConstantSite: public Site { public: ConstantSite(Promise* value): value(value) { } @@ -407,6 +429,9 @@ void acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite); +void +release(Context* c, int r); + class RegisterSite: public Site { public: RegisterSite(int low, int high): register_(low, high) { } @@ -430,7 +455,16 @@ class RegisterSite: public Site { Site* s) { ::acquire(c, register_.low, stack, size, v, s); - if (register_.high >= 0) ::acquire(c, register_.high, stack, size, v, s); + if (register_.high >= 0) { + ::acquire(c, register_.high, stack, size, v, s); + } + } + + virtual void release(Context* c) { + ::release(c, register_.low); + if (register_.high >= 0) { + ::release(c, register_.high); + } } virtual OperandType type(Context*) { @@ -447,6 +481,11 @@ class RegisterSite: public Site { RegisterSite* registerSite(Context* c, int low, int high = NoRegister) { + assert(c, low != NoRegister); + assert(c, low < static_cast(c->assembler->registerCount())); + assert(c, high == NoRegister + or high < static_cast(c->assembler->registerCount())); + return new (c->zone->allocate(sizeof(RegisterSite))) RegisterSite(low, high); } @@ -475,6 +514,24 @@ class MemorySite: public Site { } } + virtual void acquire(Context* c, Stack*, unsigned, Value*, Site*) { + fprintf(stderr, "increment ref count for %d\n", value.base); + ++ c->registers[value.base].refCount; + if (value.index != NoRegister) { + fprintf(stderr, "increment ref count for %d\n", value.index); + ++ c->registers[value.index].refCount; + } + } + + virtual void release(Context* c) { + fprintf(stderr, "decrement ref count for %d\n", value.base); + -- c->registers[value.base].refCount; + if (value.index != NoRegister) { + fprintf(stderr, "decrement ref count for %d\n", value.index); + -- c->registers[value.index].refCount; + } + } + virtual OperandType type(Context*) { return MemoryOperand; } @@ -667,7 +724,7 @@ syncStack(Context* c, Stack* start, unsigned count) Stack* s = segment[i]; assert(c, not s->pushed); - if (s->value) { + if (s->value and s->value->sites) { apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); ++ s->value->pushCount; } else { @@ -699,15 +756,22 @@ void acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) { + if (c->registers[r].reserved) return; + + assert(c, c->registers[r].refCount == 0); + + fprintf(stderr, "acquire %d, value %p, site %p\n", + r, newValue, newSite); + Value* oldValue = c->registers[r].value; if (oldValue and oldValue != newValue and findSite(c, oldValue, c->registers[r].site)) { - if (oldValue->pushCount == 0 - and oldValue->sites->next == 0 - and oldValue->reads) - { + fprintf(stderr, "steal %d from %p: push count: %d next: %p\n", + r, oldValue, oldValue->pushCount, oldValue->sites->next); + + if (oldValue->pushCount == 0 and oldValue->sites->next == 0) { unsigned count = 0; Stack* start = 0; for (Stack* s = stack; s and (not s->pushed); s = s->next) { @@ -732,6 +796,14 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, c->registers[r].site = newSite; } +void +release(Context* c, int r) +{ + c->registers[r].size = 0; + c->registers[r].value = 0; + c->registers[r].site = 0; +} + void apply(Context* c, UnaryOperation op, unsigned size, Site* a) { @@ -759,6 +831,7 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, { Read* r = new (c->zone->allocate(sizeof(Read))) Read(size, v, target, 0, thisEvent, thisEvent->reads); + fprintf(stderr, "add read %p to %p\n", r, v); thisEvent->reads = r; if (before) { @@ -789,6 +862,31 @@ addRead(Context* c, Value* v, unsigned size, Site* target) insertRead(c, c->lastEvent, 0, v, size, target); } +Site* +pushSite(Context*, PushEvent*); + +class PushEvent: public Event { + public: + PushEvent(Context* c): + Event(c), active(false) + { + stack->pushEvent = this; + addRead(c, stack->value, stack->size * BytesPerWord, pushSite(c, this)); + } + + virtual void compile(Context* c) { + fprintf(stderr, "PushEvent.compile\n"); + + if (active) { + syncStack(c, stack); + } + + nextRead(c, stack->value); + } + + bool active; +}; + void push(Context* c, unsigned size, Value* v); @@ -796,7 +894,7 @@ class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, - unsigned argumentFootprint): + Stack* argumentStack, unsigned argumentCount): Event(c), address(address), indirection(indirection), @@ -804,8 +902,27 @@ class CallEvent: public Event { result(result), flags(flags), resultSize(resultSize), - argumentFootprint(argumentFootprint) + argumentFootprint(0) { + Stack* s = argumentStack; + for (unsigned i = 0; i < argumentCount; ++i) { + Site* target; + if (argumentFootprint < c->assembler->argumentRegisterCount()) { + target = registerSite + (c, c->assembler->argumentRegister(argumentFootprint)); + } else { + target = 0; + s->pushEvent->active = true; + } + addRead(c, s->value, s->size * BytesPerWord, target); + argumentFootprint += s->size; + s = s->next; + } + + for (Stack* s = stack; s; s = s->next) { + s->pushEvent->active = true; + } + addRead(c, address, BytesPerWord, (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); } @@ -821,10 +938,16 @@ class CallEvent: public Event { apply(c, type, BytesPerWord, address->source); } - addSite(c, 0, 0, result, registerSite - (c, c->assembler->returnLow(), - resultSize > BytesPerWord ? - c->assembler->returnHigh() : NoRegister)); + for (Read* r = reads; r; r = r->eventNext) { + nextRead(c, r->value); + } + + if (resultSize) { + addSite(c, 0, 0, result, registerSite + (c, c->assembler->returnLow(), + resultSize > BytesPerWord ? + c->assembler->returnHigh() : NoRegister)); + } if (traceHandler) { traceHandler->handleTrace @@ -853,13 +976,13 @@ class CallEvent: public Event { void appendCall(Context* c, Value* address, void* indirection, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, - unsigned argumentFootprint) + Stack* argumentStack, unsigned argumentCount) { fprintf(stderr, "appendCall\n"); new (c->zone->allocate(sizeof(CallEvent))) CallEvent(c, address, indirection, flags, traceHandler, result, - resultSize, argumentFootprint); + resultSize, argumentStack, argumentCount); } class ReturnEvent: public Event { @@ -878,6 +1001,10 @@ class ReturnEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "ReturnEvent.compile\n"); + if (value) { + nextRead(c, value); + } + Assembler::Register base(c->assembler->base()); Assembler::Register stack(c->assembler->stack()); @@ -929,6 +1056,9 @@ class MoveEvent: public Event { apply(c, type, size, src->source, target); } } + + nextRead(c, src); + addSite(c, stack, size, dst, target); } @@ -957,11 +1087,13 @@ class CompareEvent: public Event { addRead(c, second, size, 0); } - virtual void compile(Context* c) { fprintf(stderr, "CompareEvent.compile\n"); apply(c, Compare, size, first->source, second->source); + + nextRead(c, first); + nextRead(c, second); } unsigned size; @@ -990,6 +1122,8 @@ class BranchEvent: public Event { fprintf(stderr, "BranchEvent.compile\n"); apply(c, type, BytesPerWord, address->source); + + nextRead(c, address); } UnaryOperation type; @@ -1029,6 +1163,10 @@ class CombineEvent: public Event { fprintf(stderr, "CombineEvent.compile\n"); apply(c, type, size, first->source, second->source); + + nextRead(c, first); + nextRead(c, second); + removeSite(c, second, second->source); addSite(c, 0, 0, result, second->source); } @@ -1063,6 +1201,9 @@ class TranslateEvent: public Event { fprintf(stderr, "TranslateEvent.compile\n"); apply(c, type, size, value->source); + + nextRead(c, value); + removeSite(c, value, value->source); addSite(c, 0, 0, result, value->source); } @@ -1107,6 +1248,11 @@ class MemoryEvent: public Event { assert(c, base->source->type(c) == RegisterOperand); int baseRegister = static_cast(base->source)->register_.low; + nextRead(c, base); + if (index) { + nextRead(c, index); + } + addSite(c, 0, 0, result, memorySite (c, baseRegister, displacement, indexRegister, scale)); } @@ -1132,7 +1278,7 @@ Site* stackSyncSite(Context* c, unsigned index, unsigned size) { int high = NoRegister; - for (int i = c->assembler->registerCount(); i >= 0; --i) { + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (not c->registers[i].reserved) { if (index == 0) { if (size == 1) { @@ -1174,10 +1320,11 @@ class StackSyncEvent: public Event { } } - virtual void compile(Context*) { + virtual void compile(Context* c) { fprintf(stderr, "StackSyncEvent.compile\n"); for (Read* r = reads; r; r = r->eventNext) { + nextRead(c, r->value); r->value->sites = r->target; r->target->next = 0; } @@ -1192,29 +1339,6 @@ appendStackSync(Context* c) new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c); } -Site* -pushSite(Context*, PushEvent*); - -class PushEvent: public Event { - public: - PushEvent(Context* c): - Event(c), active(false) - { - stack->pushEvent = this; - addRead(c, stack->value, stack->size * BytesPerWord, pushSite(c, this)); - } - - virtual void compile(Context* c) { - fprintf(stderr, "PushEvent.compile\n"); - - if (active) { - syncStack(c, stack); - } - } - - bool active; -}; - class PushSite: public AbstractSite { public: PushSite(PushEvent* event): event(event) { } @@ -1244,6 +1368,62 @@ appendPush(Context* c) new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); } +void +popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) +{ + Stack* s = stack; + unsigned ignored = 0; + for (unsigned i = count; i;) { + if (s->pushed) { + if (s->value->reads and (not ignore)) { + assert(c, ignored == 0); + + fprintf(stderr, "pop %p\n", s); + + Site* target = targetOrRegister + (c, s->size * BytesPerWord, s->value, event); + + apply(c, Pop, BytesPerWord * s->size, target); + -- s->value->pushCount; + + addSite(c, stack, s->size * BytesPerWord, s->value, target); + } else { + fprintf(stderr, "ignore %p\n", s); + + ignored += s->size; + } + + s->pushed = false; + } else { + fprintf(stderr, "%p not pushed\n", s); + } + + i -= s->size; + s = s->next; + } + + if (ignored) { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); + c->assembler->apply + (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); + } +} + +void +popNow(Context* c, Event* event, Stack* stack, Value* v) +{ + unsigned count = 0; + for (Stack* s = stack; s; s = s->next) { + count += s->size; + if (s->value == v) { + popNow(c, event, stack, count, false); + return; + } + } + abort(c); +} + class PopEvent: public Event { public: PopEvent(Context* c, unsigned count, bool ignore): @@ -1253,43 +1433,7 @@ class PopEvent: public Event { virtual void compile(Context* c) { fprintf(stderr, "PopEvent.compile\n"); - Stack* s = stack; - unsigned ignored = 0; - for (unsigned i = count; i;) { - if (s->pushed) { - if (s->value->reads and (not ignore)) { - assert(c, ignored == 0); - - fprintf(stderr, "pop %p\n", s); - - Site* target = targetOrRegister - (c, s->size * BytesPerWord, s->value, this); - - apply(c, Pop, BytesPerWord * s->size, target); - -- s->value->pushCount; - - addSite(c, stack, s->size * BytesPerWord, s->value, target); - } else { - fprintf(stderr, "ignore %p\n", s); - - ignored += s->size; - } - - s->pushed = false; - } else { - fprintf(stderr, "%p not pushed\n", s); - } - - i -= s->size; - s = s->next; - } - - if (ignored) { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); - c->assembler->apply - (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); - } + popNow(c, this, stack, count, ignore); } unsigned count; @@ -1309,11 +1453,22 @@ readSource(Context* c, Stack* stack, Read* r, Event* e) { Site* target = (r->target ? r->target->readTarget(c, r, e) : 0); + fprintf(stderr, "pick from %p\n", r->value); + unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); if (target) { if (copyCost) { + if (site == 0) { + assert(c, r->value->pushCount); + + popNow(c, e, stack, r->value); + + site = pick(c, r->value->sites, target, ©Cost); + assert(c, site); + } + addSite(c, stack, r->size, r->value, target); apply(c, Move, r->size, site, target); @@ -1343,6 +1498,8 @@ compile(Context* c) } for (Event* e = c->firstEvent; e; e = e->next) { + fprintf(stderr, "ip: %d\n", e->logicalIp); + LogicalInstruction* li = c->logicalCode + e->logicalIp; li->machineOffset = a->length(); @@ -1350,10 +1507,6 @@ compile(Context* c) r->value->source = readSource(c, e->stack, r, e); } - for (Read* r = e->reads; r; r = r->eventNext) { - r->value->reads = r->value->reads->next; - } - e->compile(c); for (CodePromise* p = e->promises; p; p = p->next) { @@ -1442,7 +1595,9 @@ bool used(Context* c, int r) { Value* v = c->registers[r].value; - return v and findSite(c, v, c->registers[r].site) and v->reads; + fprintf(stderr, "v: %p found: %d\n", + v, v and findSite(c, v, c->registers[r].site)); + return v and findSite(c, v, c->registers[r].site); } bool @@ -1459,7 +1614,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and (not c->registers[i].reserved) + and c->registers[i].refCount == 0 and (not used(c, i))) { return i; @@ -1468,7 +1623,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and (not c->registers[i].reserved) + and c->registers[i].refCount == 0 and (not usedExclusively(c, i))) { return i; @@ -1478,7 +1633,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and (not c->registers[i].reserved)) + and c->registers[i].refCount == 0) { return i; } @@ -1491,7 +1646,9 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) int freeRegister(Context* c, bool allowAcquired) { - return freeRegisterExcept(c, NoRegister, allowAcquired); + int r = freeRegisterExcept(c, NoRegister, allowAcquired); + fprintf(stderr, "free reg: %d\n", r); + return r; } RegisterSite* @@ -1513,15 +1670,16 @@ class Client: public Assembler::Client { if (r == NoRegister) { r = freeRegisterExcept(c, NoRegister, false); } else { - expect(c, not c->registers[r].reserved); + expect(c, c->registers[r].refCount == 0); expect(c, c->registers[r].value == 0); } - c->registers[r].reserved = true; + ++ c->registers[r].refCount; + fprintf(stderr, "acquire temporary: %d\n", r); return r; } virtual void releaseTemporary(int r) { - c->registers[r].reserved = false; + -- c->registers[r].refCount; } Context* c; @@ -1734,34 +1892,18 @@ class MyCompiler: public Compiler { Stack* oldStack = c.state->stack; - for (int i = index - 1; i >= 0; --i) { + fprintf(stderr, "argument count: %d\n", argumentCount); + for (int i = argumentCount - 1; i >= 0; --i) { ::push(&c, argumentSizes[i], arguments[i]); } - unsigned ai = 0; - Stack* s = c.state->stack; - for (unsigned i = 0; i < index; ++i) { - Site* target; - if (ai < c.assembler->argumentRegisterCount()) { - target = registerSite(&c, c.assembler->argumentRegister(index)); - } else { - target = 0; - s->pushEvent->active = true; - } - addRead(&c, s->value, s->size * BytesPerWord, target); - ai += s->size; - s = s->next; - } - + Stack* argumentStack = c.state->stack; c.state->stack = oldStack; - for (Stack* s = oldStack; s; s = s->next) { - s->pushEvent->active = true; - } - Value* result = value(&c); appendCall(&c, static_cast(address), indirection, flags, - traceHandler, result, resultSize, footprint); + traceHandler, result, resultSize, argumentStack, + index); return result; } diff --git a/src/x86.cpp b/src/x86.cpp index 141815c278..e5bc27a9ec 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -703,7 +703,7 @@ void moveMM(Context* c, unsigned size, Assembler::Memory* a, Assembler::Memory* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + assert(c, BytesPerWord == 8 or size <= 4); // todo Assembler::Register tmp(c->client->acquireTemporary()); moveMR(c, size, a, &tmp); @@ -937,6 +937,15 @@ compareRM(Context* c, unsigned size UNUSED, Assembler::Register* a, encode(c, 0x39, a->low, b, true); } +void +compareMR(Context* c, unsigned size UNUSED, Assembler::Memory* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + encode(c, 0x3b, b->low, a, true); +} + void compareMM(Context* c, unsigned size UNUSED, Assembler::Memory* a, Assembler::Memory* b) @@ -1015,6 +1024,7 @@ populateTables() BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR); BinaryOperations[INDEX2(Compare, Register, Memory)] = CAST2(compareRM); + BinaryOperations[INDEX2(Compare, Memory, Register)] = CAST2(compareMR); BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); BinaryOperations[INDEX2(Compare, Memory, Memory)] = CAST2(compareMM); } From b19c52b501db458cdf7b62cd9d08ae2d696dec45 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 01:03:59 -0600 Subject: [PATCH 034/121] control flow bugfixes --- src/compile.cpp | 10 +- src/compiler.cpp | 304 ++++++++++++++++++++++++++++------------------- 2 files changed, 188 insertions(+), 126 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 0d681d8acf..d86c667558 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1709,6 +1709,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, handleEntrance(t, frame); } else if (exceptionHandler) { exceptionHandler = false; + + frame->pushObject(); c->call (c->constant(reinterpret_cast(gcIfNecessary)), @@ -3850,15 +3852,15 @@ finish(MyThread* t, Context* context) } // for debugging: - if (false and + if (//false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Misc") == 0 and + "java/lang/String") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "main") == 0) + "getBytes") == 0) { asm("int3"); } @@ -3951,8 +3953,6 @@ compile(MyThread* t, Context* context) } } - frame2.pushObject(); - for (unsigned i = 1; i < codeMaxStack(t, methodCode(t, context->method)); ++i) diff --git a/src/compiler.cpp b/src/compiler.cpp index 386eb0fbd8..b9468deaee 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -81,9 +81,9 @@ class State { class LogicalInstruction { public: unsigned visits; + Event* firstEvent; Event* lastEvent; unsigned machineOffset; - int predecessor; }; class Register { @@ -151,16 +151,18 @@ class Context { zone(zone), logicalIp(-1), state(new (zone->allocate(sizeof(State))) State(0)), - firstEvent(0), - lastEvent(0), logicalCode(0), logicalCodeLength(0), stackOffset(0), registers(static_cast (zone->allocate(sizeof(Register) * assembler->registerCount()))), + freeRegisterCount(assembler->registerCount() - 3), + freeRegisters(static_cast + (zone->allocate(sizeof(int) * freeRegisterCount))), firstConstant(0), lastConstant(0), constantCount(0), + nextSequence(0), junctions(0), machineCode(0) { @@ -172,6 +174,13 @@ class Context { registers[assembler->stack()].reserved = true; registers[assembler->thread()].refCount = 1; registers[assembler->thread()].reserved = true; + + unsigned fri = 0; + for (int i = assembler->registerCount() - 1; i >= 0; --i) { + if (not registers[i].reserved) { + freeRegisters[fri++] = i; + } + } } System* system; @@ -179,15 +188,16 @@ class Context { Zone* zone; int logicalIp; State* state; - Event* firstEvent; - Event* lastEvent; LogicalInstruction* logicalCode; unsigned logicalCodeLength; unsigned stackOffset; Register* registers; + unsigned freeRegisterCount; + int* freeRegisters; ConstantPoolNode* firstConstant; ConstantPoolNode* lastConstant; unsigned constantCount; + unsigned nextSequence; Junction* junctions; uint8_t* machineCode; }; @@ -284,24 +294,22 @@ class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0), reads(0), - logicalIp(c->logicalIp) + sequence(c->nextSequence++) { assert(c, c->logicalIp >= 0); - if (c->lastEvent) { - c->lastEvent->next = this; - sequence = c->lastEvent->sequence + 1; + LogicalInstruction* i = c->logicalCode + c->logicalIp; + if (i->lastEvent) { + i->lastEvent->next = this; } else { - c->firstEvent = this; - sequence = 0; + i->firstEvent = this; } - - c->lastEvent = this; + i->lastEvent = this; } Event(Context*, Event* next): next(next), stack(next->stack), promises(0), reads(0), - sequence(next->sequence), logicalIp(next->logicalIp) + sequence(next->sequence) { } virtual ~Event() { } @@ -313,7 +321,6 @@ class Event { CodePromise* promises; Read* reads; unsigned sequence; - unsigned logicalIp; }; bool @@ -337,11 +344,12 @@ addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) } void -removeSite(Context*, Value* v, Site* s) +removeSite(Context* c, Value* v, Site* s) { for (Site** p = &(v->sites); *p;) { if (s == *p) { fprintf(stderr, "remove site %p from %p\n", s, v); + s->release(c); *p = (*p)->next; break; } else { @@ -350,15 +358,23 @@ removeSite(Context*, Value* v, Site* s) } } +void +clearSites(Context* c, Value* v) +{ + for (Site* s = v->sites; s; s = s->next) { + s->release(c); + } + v->sites = 0; +} + void nextRead(Context* c, Value* v) { - fprintf(stderr, "pop read %p from %p; next: %p\n", v->reads, v, v->reads->next); + fprintf(stderr, "pop read %p from %p\n", v->reads, v); + v->reads = v->reads->next; if (v->reads == 0) { - for (Site* s = v->sites; s; s = s->next) { - s->release(c); - } + clearSites(c, v); } } @@ -493,6 +509,22 @@ registerSite(Context* c, int low, int high = NoRegister) RegisterSite* freeRegister(Context* c, unsigned size, bool allowAcquired); +void +increment(Context* c, int r) +{ + fprintf(stderr, "increment %d\n", r); + ++ c->registers[r].refCount; +} + +void +decrement(Context* c, int r) +{ + assert(c, c->registers[r].refCount > 0); + assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); + fprintf(stderr, "decrement %d\n", r); + -- c->registers[r].refCount; +} + class MemorySite: public Site { public: MemorySite(int base, int offset, int index, unsigned scale): @@ -515,20 +547,16 @@ class MemorySite: public Site { } virtual void acquire(Context* c, Stack*, unsigned, Value*, Site*) { - fprintf(stderr, "increment ref count for %d\n", value.base); - ++ c->registers[value.base].refCount; + increment(c, value.base); if (value.index != NoRegister) { - fprintf(stderr, "increment ref count for %d\n", value.index); - ++ c->registers[value.index].refCount; + increment(c, value.index); } } virtual void release(Context* c) { - fprintf(stderr, "decrement ref count for %d\n", value.base); - -- c->registers[value.base].refCount; + decrement(c, value.base); if (value.index != NoRegister) { - fprintf(stderr, "decrement ref count for %d\n", value.index); - -- c->registers[value.index].refCount; + decrement(c, value.index); } } @@ -831,9 +859,10 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, { Read* r = new (c->zone->allocate(sizeof(Read))) Read(size, v, target, 0, thisEvent, thisEvent->reads); - fprintf(stderr, "add read %p to %p\n", r, v); thisEvent->reads = r; + fprintf(stderr, "add read %p to %p\n", r, v); + if (before) { for (Read** p = &(v->reads); *p;) { if ((*p)->event->sequence >= before->sequence) { @@ -859,7 +888,7 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, void addRead(Context* c, Value* v, unsigned size, Site* target) { - insertRead(c, c->lastEvent, 0, v, size, target); + insertRead(c, c->logicalCode[c->logicalIp].lastEvent, 0, v, size, target); } Site* @@ -867,23 +896,26 @@ pushSite(Context*, PushEvent*); class PushEvent: public Event { public: - PushEvent(Context* c): - Event(c), active(false) + PushEvent(Context* c, Stack* s): + Event(c), s(s), active(false) { - stack->pushEvent = this; - addRead(c, stack->value, stack->size * BytesPerWord, pushSite(c, this)); + assert(c, s->pushEvent == 0); + + s->pushEvent = this; + addRead(c, s->value, s->size * BytesPerWord, pushSite(c, this)); } virtual void compile(Context* c) { fprintf(stderr, "PushEvent.compile\n"); if (active) { - syncStack(c, stack); + syncStack(c, s); } - nextRead(c, stack->value); + nextRead(c, s->value); } + Stack* s; bool active; }; @@ -919,10 +951,6 @@ class CallEvent: public Event { s = s->next; } - for (Stack* s = stack; s; s = s->next) { - s->pushEvent->active = true; - } - addRead(c, address, BytesPerWord, (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); } @@ -938,11 +966,15 @@ class CallEvent: public Event { apply(c, type, BytesPerWord, address->source); } + for (Stack* s = stack; s; s = s->next) { + clearSites(c, s->value); + } + for (Read* r = reads; r; r = r->eventNext) { nextRead(c, r->value); } - if (resultSize) { + if (resultSize and result->reads) { addSite(c, 0, 0, result, registerSite (c, c->assembler->returnLow(), resultSize > BytesPerWord ? @@ -955,7 +987,7 @@ class CallEvent: public Event { CodePromise(c, c->assembler->length())); } - if (argumentFootprint) { + if (argumentFootprint and ((flags & Compiler::NoReturn) == 0)) { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset (resolved(c, argumentFootprint * BytesPerWord)); @@ -1059,7 +1091,7 @@ class MoveEvent: public Event { nextRead(c, src); - addSite(c, stack, size, dst, target); + if (dst->reads) addSite(c, stack, size, dst, target); } BinaryOperation type; @@ -1168,7 +1200,7 @@ class CombineEvent: public Event { nextRead(c, second); removeSite(c, second, second->source); - addSite(c, 0, 0, result, second->source); + if (result->reads) addSite(c, 0, 0, result, second->source); } BinaryOperation type; @@ -1205,7 +1237,7 @@ class TranslateEvent: public Event { nextRead(c, value); removeSite(c, value, value->source); - addSite(c, 0, 0, result, value->source); + if (result->reads) addSite(c, 0, 0, result, value->source); } UnaryOperation type; @@ -1277,23 +1309,38 @@ appendMemory(Context* c, Value* base, int displacement, Value* index, Site* stackSyncSite(Context* c, unsigned index, unsigned size) { - int high = NoRegister; - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (not c->registers[i].reserved) { - if (index == 0) { - if (size == 1) { - return registerSite(c, i, high); - } else { - high = i; - -- size; - } - } else { - -- index; - } + assert(c, index + size <= c->freeRegisterCount); + + return registerSite + (c, c->freeRegisters[index], + size == 2 ? c->freeRegisters[index + 1] : NoRegister); +} + +Stack* +stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) +{ + return new (c->zone->allocate(sizeof(Stack))) + Stack(value, size, index, next); +} + +void +resetStack(Context* c) +{ + unsigned i = 0; + Stack* p = 0; + for (Stack* s = c->state->stack; s; s = s->next) { + Stack* n = stack + (c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0); + + if (p) { + p->next = n; + } else { + c->state->stack = n; } + p = n; + + i += s->size; } - - abort(c); } class StackSyncEvent: public Event { @@ -1307,6 +1354,8 @@ class StackSyncEvent: public Event { stackSyncSite(c, i, s->size)); i += s->size; } + + resetStack(c); } StackSyncEvent(Context* c, Event* next): @@ -1325,8 +1374,6 @@ class StackSyncEvent: public Event { for (Read* r = reads; r; r = r->eventNext) { nextRead(c, r->value); - r->value->sites = r->target; - r->target->next = 0; } } }; @@ -1361,11 +1408,28 @@ pushSite(Context* c, PushEvent* e) } void -appendPush(Context* c) +appendPush(Context* c, Stack* s) { fprintf(stderr, "appendPush\n"); - new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); + new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c, s); +} + +void +appendPush(Context* c) +{ + appendPush(c, c->state->stack); +} + +void +ignore(Context* c, unsigned count) +{ + if (count) { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, count * BytesPerWord)); + c->assembler->apply + (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); + } } void @@ -1376,7 +1440,7 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) for (unsigned i = count; i;) { if (s->pushed) { if (s->value->reads and (not ignore)) { - assert(c, ignored == 0); + ::ignore(c, ignored); fprintf(stderr, "pop %p\n", s); @@ -1402,12 +1466,7 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) s = s->next; } - if (ignored) { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); - c->assembler->apply - (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); - } + ::ignore(c, ignored); } void @@ -1497,20 +1556,24 @@ compile(Context* c) RegisterOperand, &stack); } - for (Event* e = c->firstEvent; e; e = e->next) { - fprintf(stderr, "ip: %d\n", e->logicalIp); + for (unsigned i = 0; i < c->logicalCodeLength; ++i) { + LogicalInstruction* li = c->logicalCode + i; + if (li->firstEvent) { + li->machineOffset = a->length(); - LogicalInstruction* li = c->logicalCode + e->logicalIp; - li->machineOffset = a->length(); + fprintf(stderr, "ip: %d\n", i); - for (Read* r = e->reads; r; r = r->eventNext) { - r->value->source = readSource(c, e->stack, r, e); - } + for (Event* e = li->firstEvent; e; e = e->next) { + for (Read* r = e->reads; r; r = r->eventNext) { + r->value->source = readSource(c, e->stack, r, e); + } - e->compile(c); - - for (CodePromise* p = e->promises; p; p = p->next) { - p->offset = a->length(); + e->compile(c); + + for (CodePromise* p = e->promises; p; p = p->next) { + p->offset = a->length(); + } + } } } } @@ -1538,13 +1601,8 @@ popState(Context* c) { c->state = new (c->zone->allocate(sizeof(State))) State(c->state->next); -} -Stack* -stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) -{ - return new (c->zone->allocate(sizeof(Stack))) - Stack(value, size, index, next); + resetStack(c); } Stack* @@ -1581,12 +1639,13 @@ 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; - - p->lastEvent = p->lastEvent->next - = new (c->zone->allocate(sizeof(StackSyncEvent))) - StackSyncEvent(c, p->lastEvent->next); + for (int ip = j->logicalIp - 1; ip >= 0; --ip) { + LogicalInstruction* p = c->logicalCode + ip; + if (p->lastEvent) { + i->lastEvent = i->lastEvent->next + = new (c->zone->allocate(sizeof(StackSyncEvent))) + StackSyncEvent(c, 0); + } } } } @@ -1600,14 +1659,14 @@ used(Context* c, int r) return v and findSite(c, v, c->registers[r].site); } -bool -usedExclusively(Context* c, int r) -{ - Value* v = c->registers[r].value; - return used(c, r) - and v->pushCount == 0 - and v->sites->next == 0; -} +// bool +// usedExclusively(Context* c, int r) +// { +// Value* v = c->registers[r].value; +// return used(c, r) +// and v->pushCount == 0 +// and v->sites->next == 0; +// } int freeRegisterExcept(Context* c, int except, bool allowAcquired) @@ -1621,14 +1680,14 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) } } - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0 - and (not usedExclusively(c, i))) - { - return i; - } - } +// for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { +// if (i != except +// and c->registers[i].refCount == 0 +// and (not usedExclusively(c, i))) +// { +// return i; +// } +// } if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { @@ -1673,13 +1732,12 @@ class Client: public Assembler::Client { expect(c, c->registers[r].refCount == 0); expect(c, c->registers[r].value == 0); } - ++ c->registers[r].refCount; - fprintf(stderr, "acquire temporary: %d\n", r); + increment(c, r); return r; } virtual void releaseTemporary(int r) { - -- c->registers[r].refCount; + decrement(c, r); } Context* c; @@ -1710,17 +1768,14 @@ class MyCompiler: public Compiler { } virtual void visitLogicalIp(unsigned logicalIp) { - if ((++ c.logicalCode[logicalIp].visits) == 1) { + if ((++ c.logicalCode[logicalIp].visits) == 2) { 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.lastEvent; - } - + fprintf(stderr, "ip: %d\n", logicalIp); c.logicalIp = logicalIp; } @@ -1809,8 +1864,9 @@ class MyCompiler: public Compiler { } Promise* machineIp() { - return c.lastEvent->promises = new (c.zone->allocate(sizeof(CodePromise))) - CodePromise(&c, c.lastEvent->promises); + Event* e = c.logicalCode[c.logicalIp].lastEvent; + return e->promises = new (c.zone->allocate(sizeof(CodePromise))) + CodePromise(&c, e->promises); } virtual void mark(Operand* label) { @@ -1890,9 +1946,15 @@ class MyCompiler: public Compiler { va_end(a); + for (Stack* s = c.state->stack; s; s = s->next) { + if (s->pushEvent == 0) { + appendPush(&c, s); + } + s->pushEvent->active = true; + } + Stack* oldStack = c.state->stack; - fprintf(stderr, "argument count: %d\n", argumentCount); for (int i = argumentCount - 1; i >= 0; --i) { ::push(&c, argumentSizes[i], arguments[i]); } From 7b8b7a7b11fdf65a8ead33d7c10c5bdfc052648b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 14:41:31 -0600 Subject: [PATCH 035/121] snapshot --- src/compile.cpp | 37 +++----- src/compiler.cpp | 216 +++++++++++++++++++++++------------------------ 2 files changed, 119 insertions(+), 134 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index d86c667558..7977a266fe 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1734,10 +1734,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iaload: case laload: case saload: { - Compiler::Operand* index = frame->popInt(); - Compiler::Operand* array = frame->popObject(); - if (CheckArrayBounds) { + Compiler::Operand* index = c->peek(4, 0); + Compiler::Operand* array = c->peek(BytesPerWord, 1); + Compiler::Operand* load = c->label(); Compiler::Operand* throw_ = 0; @@ -1746,26 +1746,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } else { throw_ = c->label(); c->cmp(4, c->constant(0), index); - - frame->pushObject(array); - frame->pushInt(index); - c->jl(throw_); - - index = frame->popInt(); - array = frame->popObject(); } c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - - frame->pushObject(array); - frame->pushInt(index); - c->jge(load); - index = frame->popInt(); - array = frame->popObject(); - if (not c->isConstant(index)) { c->mark(throw_); } @@ -1778,15 +1764,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, 0, 3, c->thread(), array, index); - frame->pushObject(array); - frame->pushInt(index); - c->mark(load); - - index = frame->popInt(); - array = frame->popObject(); } + Compiler::Operand* index = frame->popInt(); + Compiler::Operand* array = frame->popObject(); + if (c->isConstant(index)) { unsigned i = c->constantValue(index); switch (instruction) { @@ -3187,7 +3170,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case newarray: { uint8_t type = codeBody(t, code, ip++); - Compiler::Operand* length = frame->popInt(); + Compiler::Operand* length = c->peek(4, 0); if (c->isConstant(length)) { expect(t, c->constantValue(length) >= 0); @@ -3208,6 +3191,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(nonnegative); } + frame->popInt(); + object (*constructor)(Thread*, uintptr_t, bool); switch (type) { case T_BOOLEAN: @@ -3856,11 +3841,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/String") == 0 and + "java/io/PrintStream") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "getBytes") == 0) + "println") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index b9468deaee..9154c8cece 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -56,7 +56,7 @@ class Stack { public: Stack(Value* value, unsigned size, unsigned index, Stack* next): value(value), size(size), index(index), next(next), pushEvent(0), - pushed(false) + pushSite(0), pushed(false) { } Value* value; @@ -64,6 +64,7 @@ class Stack { unsigned index; Stack* next; PushEvent* pushEvent; + Site* pushSite; bool pushed; }; @@ -133,14 +134,14 @@ class Read { class Value: public Compiler::Operand { public: Value(Site* site): - reads(0), lastRead(0), sites(site), source(0), pushCount(0) + reads(0), lastRead(0), sites(site), source(0), target(site) { } Read* reads; Read* lastRead; Site* sites; Site* source; - unsigned pushCount; + Site* target; }; class Context { @@ -314,6 +315,8 @@ class Event { virtual ~Event() { } + virtual void prepare(Context*) { } + virtual void compile(Context* c) = 0; Event* next; @@ -336,7 +339,7 @@ void addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (not findSite(c, v, s)) { - fprintf(stderr, "add site %p to %p\n", s, v); +// fprintf(stderr, "add site %p to %p\n", s, v); s->acquire(c, stack, size, v, s); s->next = v->sites; v->sites = s; @@ -348,7 +351,7 @@ removeSite(Context* c, Value* v, Site* s) { for (Site** p = &(v->sites); *p;) { if (s == *p) { - fprintf(stderr, "remove site %p from %p\n", s, v); +// fprintf(stderr, "remove site %p from %p\n", s, v); s->release(c); *p = (*p)->next; break; @@ -370,7 +373,7 @@ clearSites(Context* c, Value* v) void nextRead(Context* c, Value* v) { - fprintf(stderr, "pop read %p from %p\n", v->reads, v); + // fprintf(stderr, "pop read %p from %p\n", v->reads, v); v->reads = v->reads->next; if (v->reads == 0) { @@ -601,9 +604,8 @@ Site* targetOrNull(Context* c, Read* r, Event* event) { Value* v = r->value; - if (v->sites) { - assert(c, v->sites->next == 0); - return v->sites; + if (v->target) { + return v->target; } else if (r->target) { return r->target->readTarget(c, r, event); } else { @@ -614,9 +616,8 @@ targetOrNull(Context* c, Read* r, Event* event) Site* targetOrNull(Context* c, Value* v, Event* event) { - if (v->sites) { - assert(c, v->sites->next == 0); - return v->sites; + if (v->target) { + return v->target; } else if (v->reads and v->reads->target) { return v->reads->target->readTarget(c, v->reads, event); } else { @@ -740,7 +741,7 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) } void -syncStack(Context* c, Stack* start, unsigned count) +pushNow(Context* c, Stack* start, unsigned count) { Stack* segment[count]; unsigned index = count; @@ -754,7 +755,10 @@ syncStack(Context* c, Stack* start, unsigned count) if (s->value and s->value->sites) { apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); - ++ s->value->pushCount; + s->pushSite = memorySite + (c, c->assembler->base(), + - (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1); + addSite(c, 0, 0, s->value, s->pushSite); } else { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); @@ -763,21 +767,22 @@ syncStack(Context* c, Stack* start, unsigned count) RegisterOperand, &stack); } - fprintf(stderr, "pushed %p\n", s); + fprintf(stderr, "pushed %p value: %p sites: %p\n", + s, s->value, s->value->sites); s->pushed = true; } } void -syncStack(Context* c, Stack* start) +pushNow(Context* c, Stack* start) { unsigned count = 0; for (Stack* s = start; s and (not s->pushed); s = s->next) { ++ count; } - syncStack(c, start, count); + pushNow(c, start, count); } void @@ -788,18 +793,18 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, assert(c, c->registers[r].refCount == 0); - fprintf(stderr, "acquire %d, value %p, site %p\n", - r, newValue, newSite); +// fprintf(stderr, "acquire %d, value %p, site %p\n", +// r, newValue, newSite); Value* oldValue = c->registers[r].value; if (oldValue and oldValue != newValue and findSite(c, oldValue, c->registers[r].site)) { - fprintf(stderr, "steal %d from %p: push count: %d next: %p\n", - r, oldValue, oldValue->pushCount, oldValue->sites->next); +// fprintf(stderr, "steal %d from %p: next: %p\n", +// r, oldValue, oldValue->sites->next); - if (oldValue->pushCount == 0 and oldValue->sites->next == 0) { + if (oldValue->sites->next == 0) { unsigned count = 0; Stack* start = 0; for (Stack* s = stack; s and (not s->pushed); s = s->next) { @@ -813,7 +818,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, assert(c, start); - syncStack(c, start, count); + pushNow(c, start, count); } removeSite(c, oldValue, c->registers[r].site); @@ -861,7 +866,7 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, Read(size, v, target, 0, thisEvent, thisEvent->reads); thisEvent->reads = r; - fprintf(stderr, "add read %p to %p\n", r, v); + // fprintf(stderr, "add read %p to %p\n", r, v); if (before) { for (Read** p = &(v->reads); *p;) { @@ -909,7 +914,7 @@ class PushEvent: public Event { fprintf(stderr, "PushEvent.compile\n"); if (active) { - syncStack(c, s); + pushNow(c, s); } nextRead(c, s->value); @@ -922,6 +927,17 @@ class PushEvent: public Event { void push(Context* c, unsigned size, Value* v); +void +ignore(Context* c, unsigned count) +{ + if (count) { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, count * BytesPerWord)); + c->assembler->apply + (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); + } +} + class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, @@ -970,6 +986,10 @@ class CallEvent: public Event { clearSites(c, s->value); } + for (Stack* s = stack; s; s = s->next) { + if (s->pushSite) addSite(c, 0, 0, s->value, s->pushSite); + } + for (Read* r = reads; r; r = r->eventNext) { nextRead(c, r->value); } @@ -988,11 +1008,7 @@ class CallEvent: public Event { } if (argumentFootprint and ((flags & Compiler::NoReturn) == 0)) { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset - (resolved(c, argumentFootprint * BytesPerWord)); - c->assembler->apply - (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); + ignore(c, argumentFootprint); } } @@ -1343,6 +1359,57 @@ resetStack(Context* c) } } +void +popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) +{ + Stack* s = stack; + unsigned ignored = 0; + for (unsigned i = count; i and s;) { + if (s->pushed) { + if (s->value->reads and (not ignore)) { + ::ignore(c, ignored); + + Site* target = targetOrRegister + (c, s->size * BytesPerWord, s->value, event); + + fprintf(stderr, "pop %p value: %p target: %p\n", s, s->value, target); + + apply(c, Pop, BytesPerWord * s->size, target); + + addSite(c, stack, s->size * BytesPerWord, s->value, target); + } else { + fprintf(stderr, "ignore %p value: %p\n", s, s->value); + + ignored += s->size; + } + + fprintf(stderr, "sites before: "); + for (Site* site = s->value->sites; site; site = site->next) { + fprintf(stderr, "%p ", site); + } + fprintf(stderr, "\n"); + + removeSite(c, s->value, s->pushSite); + + fprintf(stderr, "sites after: "); + for (Site* site = s->value->sites; site; site = site->next) { + fprintf(stderr, "%p ", site); + } + fprintf(stderr, "\n"); + + s->pushSite = 0; + s->pushed = false; + } else { + fprintf(stderr, "%p not pushed\n", s); + } + + i -= s->size; + s = s->next; + } + + ::ignore(c, ignored); +} + class StackSyncEvent: public Event { public: StackSyncEvent(Context* c): @@ -1369,6 +1436,10 @@ class StackSyncEvent: public Event { } } + virtual void prepare(Context* c) { + popNow(c, this, stack, 0xFFFFFFFF, false); + } + virtual void compile(Context* c) { fprintf(stderr, "StackSyncEvent.compile\n"); @@ -1421,68 +1492,6 @@ appendPush(Context* c) appendPush(c, c->state->stack); } -void -ignore(Context* c, unsigned count) -{ - if (count) { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, count * BytesPerWord)); - c->assembler->apply - (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); - } -} - -void -popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) -{ - Stack* s = stack; - unsigned ignored = 0; - for (unsigned i = count; i;) { - if (s->pushed) { - if (s->value->reads and (not ignore)) { - ::ignore(c, ignored); - - fprintf(stderr, "pop %p\n", s); - - Site* target = targetOrRegister - (c, s->size * BytesPerWord, s->value, event); - - apply(c, Pop, BytesPerWord * s->size, target); - -- s->value->pushCount; - - addSite(c, stack, s->size * BytesPerWord, s->value, target); - } else { - fprintf(stderr, "ignore %p\n", s); - - ignored += s->size; - } - - s->pushed = false; - } else { - fprintf(stderr, "%p not pushed\n", s); - } - - i -= s->size; - s = s->next; - } - - ::ignore(c, ignored); -} - -void -popNow(Context* c, Event* event, Stack* stack, Value* v) -{ - unsigned count = 0; - for (Stack* s = stack; s; s = s->next) { - count += s->size; - if (s->value == v) { - popNow(c, event, stack, count, false); - return; - } - } - abort(c); -} - class PopEvent: public Event { public: PopEvent(Context* c, unsigned count, bool ignore): @@ -1512,22 +1521,11 @@ readSource(Context* c, Stack* stack, Read* r, Event* e) { Site* target = (r->target ? r->target->readTarget(c, r, e) : 0); - fprintf(stderr, "pick from %p\n", r->value); - unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); if (target) { if (copyCost) { - if (site == 0) { - assert(c, r->value->pushCount); - - popNow(c, e, stack, r->value); - - site = pick(c, r->value->sites, target, ©Cost); - assert(c, site); - } - addSite(c, stack, r->size, r->value, target); apply(c, Move, r->size, site, target); @@ -1561,9 +1559,11 @@ compile(Context* c) if (li->firstEvent) { li->machineOffset = a->length(); - fprintf(stderr, "ip: %d\n", i); + fprintf(stderr, " -- ip: %d\n", i); for (Event* e = li->firstEvent; e; e = e->next) { + e->prepare(c); + for (Read* r = e->reads; r; r = r->eventNext) { r->value->source = readSource(c, e->stack, r, e); } @@ -1654,8 +1654,8 @@ bool used(Context* c, int r) { Value* v = c->registers[r].value; - fprintf(stderr, "v: %p found: %d\n", - v, v and findSite(c, v, c->registers[r].site)); +// fprintf(stderr, "v: %p found: %d\n", +// v, v and findSite(c, v, c->registers[r].site)); return v and findSite(c, v, c->registers[r].site); } @@ -1706,7 +1706,7 @@ int freeRegister(Context* c, bool allowAcquired) { int r = freeRegisterExcept(c, NoRegister, allowAcquired); - fprintf(stderr, "free reg: %d\n", r); +// fprintf(stderr, "free reg: %d\n", r); return r; } @@ -1775,7 +1775,7 @@ class MyCompiler: public Compiler { } virtual void startLogicalIp(unsigned logicalIp) { - fprintf(stderr, "ip: %d\n", logicalIp); + fprintf(stderr, " -- ip: %d\n", logicalIp); c.logicalIp = logicalIp; } From eb77687a578f2c650d69773aff8f35ec6864251c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 15:52:45 -0600 Subject: [PATCH 036/121] hello, world --- src/compile.cpp | 2 +- src/compiler.cpp | 183 +++++++++++++++++++++++++++-------------------- 2 files changed, 107 insertions(+), 78 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 7977a266fe..ab249e5123 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3837,7 +3837,7 @@ finish(MyThread* t, Context* context) } // for debugging: - if (//false and + if (false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), diff --git a/src/compiler.cpp b/src/compiler.cpp index 9154c8cece..8ca36e63eb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -15,6 +15,10 @@ using namespace vm; namespace { +const bool DebugStack = false; +const bool DebugAppend = false; +const bool DebugCompile = false; + class Context; class Value; class Stack; @@ -92,7 +96,6 @@ class Register { Value* value; Site* site; unsigned size; - unsigned refCount; bool reserved; }; @@ -169,11 +172,8 @@ class Context { { memset(registers, 0, sizeof(Register) * assembler->registerCount()); - registers[assembler->base()].refCount = 1; registers[assembler->base()].reserved = true; - registers[assembler->stack()].refCount = 1; registers[assembler->stack()].reserved = true; - registers[assembler->thread()].refCount = 1; registers[assembler->thread()].reserved = true; unsigned fri = 0; @@ -512,22 +512,6 @@ registerSite(Context* c, int low, int high = NoRegister) RegisterSite* freeRegister(Context* c, unsigned size, bool allowAcquired); -void -increment(Context* c, int r) -{ - fprintf(stderr, "increment %d\n", r); - ++ c->registers[r].refCount; -} - -void -decrement(Context* c, int r) -{ - assert(c, c->registers[r].refCount > 0); - assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); - fprintf(stderr, "decrement %d\n", r); - -- c->registers[r].refCount; -} - class MemorySite: public Site { public: MemorySite(int base, int offset, int index, unsigned scale): @@ -549,17 +533,19 @@ class MemorySite: public Site { } } - virtual void acquire(Context* c, Stack*, unsigned, Value*, Site*) { - increment(c, value.base); + virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, + Site* s) + { + ::acquire(c, value.base, stack, size, v, s); if (value.index != NoRegister) { - increment(c, value.index); + ::acquire(c, value.index, stack, size, v, s); } } virtual void release(Context* c) { - decrement(c, value.base); + ::release(c, value.base); if (value.index != NoRegister) { - decrement(c, value.index); + ::release(c, value.index); } } @@ -660,7 +646,7 @@ valueSite(Context* c, Value* v) class MoveSite: public AbstractSite { public: - MoveSite(Value* value): value(value) { } + MoveSite(Value* value): value(value) { } virtual Site* readTarget(Context* c, Read* read, Event* event) { if (event->next == read->event) { @@ -767,8 +753,10 @@ pushNow(Context* c, Stack* start, unsigned count) RegisterOperand, &stack); } - fprintf(stderr, "pushed %p value: %p sites: %p\n", - s, s->value, s->value->sites); + if (DebugStack) { + fprintf(stderr, "pushed %p value: %p sites: %p\n", + s, s->value, s->value->sites); + } s->pushed = true; } @@ -791,8 +779,6 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, { if (c->registers[r].reserved) return; - assert(c, c->registers[r].refCount == 0); - // fprintf(stderr, "acquire %d, value %p, site %p\n", // r, newValue, newSite); @@ -911,7 +897,9 @@ class PushEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "PushEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "PushEvent.compile\n"); + } if (active) { pushNow(c, s); @@ -972,7 +960,9 @@ class CallEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "CallEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "CallEvent.compile\n"); + } UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); if (indirection) { @@ -1026,7 +1016,9 @@ appendCall(Context* c, Value* address, void* indirection, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, Stack* argumentStack, unsigned argumentCount) { - fprintf(stderr, "appendCall\n"); + if (DebugAppend) { + fprintf(stderr, "appendCall\n"); + } new (c->zone->allocate(sizeof(CallEvent))) CallEvent(c, address, indirection, flags, traceHandler, result, @@ -1047,7 +1039,9 @@ class ReturnEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "ReturnEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "ReturnEvent.compile\n"); + } if (value) { nextRead(c, value); @@ -1068,7 +1062,9 @@ class ReturnEvent: public Event { void appendReturn(Context* c, unsigned size, Value* value) { - fprintf(stderr, "appendReturn\n"); + if (DebugAppend) { + fprintf(stderr, "appendReturn\n"); + } new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); } @@ -1089,7 +1085,9 @@ class MoveEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "MoveEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "MoveEvent.compile\n"); + } Site* target; if (type == Move @@ -1120,7 +1118,9 @@ void appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, Value* dst) { - fprintf(stderr, "appendMove\n"); + if (DebugAppend) { + fprintf(stderr, "appendMove\n"); + } new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, size, src, dst); @@ -1136,7 +1136,9 @@ class CompareEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "CompareEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "CompareEvent.compile\n"); + } apply(c, Compare, size, first->source, second->source); @@ -1152,7 +1154,9 @@ class CompareEvent: public Event { void appendCompare(Context* c, unsigned size, Value* first, Value* second) { - fprintf(stderr, "appendCompare\n"); + if (DebugAppend) { + fprintf(stderr, "appendCompare\n"); + } new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, first, second); @@ -1167,7 +1171,9 @@ class BranchEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "BranchEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "BranchEvent.compile\n"); + } apply(c, type, BytesPerWord, address->source); @@ -1181,7 +1187,9 @@ class BranchEvent: public Event { void appendBranch(Context* c, UnaryOperation type, Value* address) { - fprintf(stderr, "appendBranch\n"); + if (DebugAppend) { + fprintf(stderr, "appendBranch\n"); + } new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); } @@ -1208,7 +1216,9 @@ class CombineEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "CombineEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "CombineEvent.compile\n"); + } apply(c, type, size, first->source, second->source); @@ -1230,7 +1240,9 @@ void appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Value* second, Value* result) { - fprintf(stderr, "appendCombine\n"); + if (DebugAppend) { + fprintf(stderr, "appendCombine\n"); + } new (c->zone->allocate(sizeof(CombineEvent))) CombineEvent(c, type, size, first, second, result); @@ -1246,7 +1258,9 @@ class TranslateEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "TranslateEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "TranslateEvent.compile\n"); + } apply(c, type, size, value->source); @@ -1266,7 +1280,9 @@ void appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, Value* result) { - fprintf(stderr, "appendTranslate\n"); + if (DebugAppend) { + fprintf(stderr, "appendTranslate\n"); + } new (c->zone->allocate(sizeof(TranslateEvent))) TranslateEvent(c, type, size, value, result); @@ -1284,7 +1300,9 @@ class MemoryEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "MemoryEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "MemoryEvent.compile\n"); + } int indexRegister; if (index) { @@ -1301,8 +1319,9 @@ class MemoryEvent: public Event { nextRead(c, index); } - addSite(c, 0, 0, result, memorySite - (c, baseRegister, displacement, indexRegister, scale)); + result->target = memorySite + (c, baseRegister, displacement, indexRegister, scale); + addSite(c, 0, 0, result, result->target); } Value* base; @@ -1316,7 +1335,9 @@ void appendMemory(Context* c, Value* base, int displacement, Value* index, unsigned scale, Value* result) { - fprintf(stderr, "appendMemory\n"); + if (DebugAppend) { + fprintf(stderr, "appendMemory\n"); + } new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, base, displacement, index, scale, result); @@ -1372,35 +1393,29 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) Site* target = targetOrRegister (c, s->size * BytesPerWord, s->value, event); - fprintf(stderr, "pop %p value: %p target: %p\n", s, s->value, target); + if (DebugStack) { + fprintf(stderr, "pop %p value: %p target: %p\n", + s, s->value, target); + } apply(c, Pop, BytesPerWord * s->size, target); addSite(c, stack, s->size * BytesPerWord, s->value, target); } else { - fprintf(stderr, "ignore %p value: %p\n", s, s->value); + if (DebugStack) { + fprintf(stderr, "ignore %p value: %p\n", s, s->value); + } ignored += s->size; } - fprintf(stderr, "sites before: "); - for (Site* site = s->value->sites; site; site = site->next) { - fprintf(stderr, "%p ", site); - } - fprintf(stderr, "\n"); - removeSite(c, s->value, s->pushSite); - - fprintf(stderr, "sites after: "); - for (Site* site = s->value->sites; site; site = site->next) { - fprintf(stderr, "%p ", site); - } - fprintf(stderr, "\n"); - s->pushSite = 0; s->pushed = false; } else { - fprintf(stderr, "%p not pushed\n", s); + if (DebugStack) { + fprintf(stderr, "%p not pushed\n", s); + } } i -= s->size; @@ -1441,7 +1456,9 @@ class StackSyncEvent: public Event { } virtual void compile(Context* c) { - fprintf(stderr, "StackSyncEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "StackSyncEvent.compile\n"); + } for (Read* r = reads; r; r = r->eventNext) { nextRead(c, r->value); @@ -1452,7 +1469,9 @@ class StackSyncEvent: public Event { void appendStackSync(Context* c) { - fprintf(stderr, "appendStackSync\n"); + if (DebugAppend) { + fprintf(stderr, "appendStackSync\n"); + } new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c); } @@ -1481,7 +1500,9 @@ pushSite(Context* c, PushEvent* e) void appendPush(Context* c, Stack* s) { - fprintf(stderr, "appendPush\n"); + if (DebugAppend) { + fprintf(stderr, "appendPush\n"); + } new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c, s); } @@ -1499,7 +1520,9 @@ class PopEvent: public Event { { } virtual void compile(Context* c) { - fprintf(stderr, "PopEvent.compile\n"); + if (DebugCompile) { + fprintf(stderr, "PopEvent.compile\n"); + } popNow(c, this, stack, count, ignore); } @@ -1511,7 +1534,9 @@ class PopEvent: public Event { void appendPop(Context* c, unsigned count, bool ignore) { - fprintf(stderr, "appendPop\n"); + if (DebugAppend) { + fprintf(stderr, "appendPop\n"); + } new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } @@ -1559,7 +1584,9 @@ compile(Context* c) if (li->firstEvent) { li->machineOffset = a->length(); - fprintf(stderr, " -- ip: %d\n", i); + if (DebugCompile) { + fprintf(stderr, " -- ip: %d\n", i); + } for (Event* e = li->firstEvent; e; e = e->next) { e->prepare(c); @@ -1673,7 +1700,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and c->registers[i].refCount == 0 + and (not c->registers[i].reserved) and (not used(c, i))) { return i; @@ -1692,7 +1719,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and c->registers[i].refCount == 0) + and (not c->registers[i].reserved)) { return i; } @@ -1729,15 +1756,15 @@ class Client: public Assembler::Client { if (r == NoRegister) { r = freeRegisterExcept(c, NoRegister, false); } else { - expect(c, c->registers[r].refCount == 0); + expect(c, not c->registers[r].reserved); expect(c, c->registers[r].value == 0); } - increment(c, r); + c->registers[r].reserved = true; return r; } virtual void releaseTemporary(int r) { - decrement(c, r); + c->registers[r].reserved = false; } Context* c; @@ -1775,7 +1802,9 @@ class MyCompiler: public Compiler { } virtual void startLogicalIp(unsigned logicalIp) { - fprintf(stderr, " -- ip: %d\n", logicalIp); + if (DebugAppend) { + fprintf(stderr, " -- ip: %d\n", logicalIp); + } c.logicalIp = logicalIp; } From 50eb1cbb71331e136bb5c98ea0f18bbb8f194bd8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 16:13:57 -0600 Subject: [PATCH 037/121] peek at stack values during bounds checks --- src/compile.cpp | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index ab249e5123..5684ef3062 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1842,19 +1842,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iastore: case lastore: case sastore: { - Compiler::Operand* value; - if (instruction == dastore or instruction == lastore) { - value = frame->popLong(); - } else if (instruction == aastore) { - value = frame->popObject(); - } else { - value = frame->popInt(); - } - - Compiler::Operand* index = frame->popInt(); - Compiler::Operand* array = frame->popObject(); - if (CheckArrayBounds) { + unsigned valueSize + = (instruction == dastore or instruction == lastore ? 2 : 1); + + Compiler::Operand* index = c->peek(4, valueSize); + Compiler::Operand* array = c->peek(BytesPerWord, valueSize + 1); + Compiler::Operand* store = c->label(); Compiler::Operand* throw_ = 0; @@ -1884,6 +1878,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(store); } + Compiler::Operand* value; + if (instruction == dastore or instruction == lastore) { + value = frame->popLong(); + } else if (instruction == aastore) { + value = frame->popObject(); + } else { + value = frame->popInt(); + } + + Compiler::Operand* index = frame->popInt(); + Compiler::Operand* array = frame->popObject(); + if (c->isConstant(index)) { unsigned i = c->constantValue(index); switch (instruction) { @@ -1985,7 +1991,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Compiler::Operand* length = frame->popInt(); + Compiler::Operand* length = c->peek(4, 0); if (c->isConstant(length)) { expect(t, c->constantValue(length) >= 0); @@ -2006,6 +2012,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(nonnegative); } + frame->popInt(); + frame->pushObject (c->call (c->constant(reinterpret_cast(makeBlankObjectArray)), @@ -3375,8 +3383,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, ip = (ip + 3) & ~3; // pad to four byte boundary - Compiler::Operand* key = frame->popInt(); - uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); @@ -3400,6 +3406,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, assert(t, start); Compiler::Operand* defaultCase = c->label(); + + Compiler::Operand* key = frame->popInt(); c->cmp(4, c->constant(bottom), key); c->jl(defaultCase); @@ -3841,11 +3849,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/io/PrintStream") == 0 and + "java/lang/String") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "println") == 0) + "getBytes") == 0) { asm("int3"); } From 8baa2bbd877132c55cde5fea86214405ae074a90 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 18:43:12 -0600 Subject: [PATCH 038/121] insert stack sync events before each instruction with more than one predecessor --- src/compile.cpp | 6 ++- src/compiler.cpp | 120 +++++++++++++++++++++++++++++++++-------------- src/x86.cpp | 25 +++++++++- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 5684ef3062..e2510ca54d 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -714,6 +714,8 @@ class Frame { } void visitLogicalIp(unsigned ip) { + c->visitLogicalIp(ip); + context->eventLog.append(IpEvent); context->eventLog.append2(ip); } @@ -3849,11 +3851,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/String") == 0 and + "Enums") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "getBytes") == 0) + "main") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 8ca36e63eb..fc1ff59cfe 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -15,9 +15,10 @@ using namespace vm; namespace { -const bool DebugStack = false; const bool DebugAppend = false; const bool DebugCompile = false; +const bool DebugStack = false; +const bool DebugRegisters = false; class Context; class Value; @@ -60,7 +61,7 @@ class Stack { public: Stack(Value* value, unsigned size, unsigned index, Stack* next): value(value), size(size), index(index), next(next), pushEvent(0), - pushSite(0), pushed(false) + pushSite(0), syncSite(0), pushed(false) { } Value* value; @@ -69,6 +70,7 @@ class Stack { Stack* next; PushEvent* pushEvent; Site* pushSite; + Site* syncSite; bool pushed; }; @@ -96,6 +98,7 @@ class Register { Value* value; Site* site; unsigned size; + unsigned refCount; bool reserved; }; @@ -172,8 +175,11 @@ class Context { { memset(registers, 0, sizeof(Register) * assembler->registerCount()); + registers[assembler->base()].refCount = 1; registers[assembler->base()].reserved = true; + registers[assembler->stack()].refCount = 1; registers[assembler->stack()].reserved = true; + registers[assembler->thread()].refCount = 1; registers[assembler->thread()].reserved = true; unsigned fri = 0; @@ -308,9 +314,9 @@ class Event { i->lastEvent = this; } - Event(Context*, Event* next): - next(next), stack(next->stack), promises(0), reads(0), - sequence(next->sequence) + Event(Context*, Event* previous): + next(0), stack(previous->stack), promises(0), reads(0), + sequence(previous->sequence) { } virtual ~Event() { } @@ -512,6 +518,26 @@ registerSite(Context* c, int low, int high = NoRegister) RegisterSite* freeRegister(Context* c, unsigned size, bool allowAcquired); +void +increment(Context* c, int r) +{ + if (DebugRegisters) { + fprintf(stderr, "increment %d\n", r); + } + ++ c->registers[r].refCount; +} + +void +decrement(Context* c, int r) +{ + assert(c, c->registers[r].refCount > 0); + assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); + if (DebugRegisters) { + fprintf(stderr, "decrement %d\n", r); + } + -- c->registers[r].refCount; +} + class MemorySite: public Site { public: MemorySite(int base, int offset, int index, unsigned scale): @@ -533,19 +559,17 @@ class MemorySite: public Site { } } - virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, - Site* s) - { - ::acquire(c, value.base, stack, size, v, s); + virtual void acquire(Context* c, Stack*, unsigned, Value*, Site*) { + increment(c, value.base); if (value.index != NoRegister) { - ::acquire(c, value.index, stack, size, v, s); + increment(c, value.index); } } virtual void release(Context* c) { - ::release(c, value.base); + decrement(c, value.base); if (value.index != NoRegister) { - ::release(c, value.index); + decrement(c, value.index); } } @@ -779,16 +803,22 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, { if (c->registers[r].reserved) return; -// fprintf(stderr, "acquire %d, value %p, site %p\n", -// r, newValue, newSite); + if (DebugRegisters) { + fprintf(stderr, "acquire %d, value %p, site %p\n", + r, newValue, newSite); + } Value* oldValue = c->registers[r].value; if (oldValue and oldValue != newValue and findSite(c, oldValue, c->registers[r].site)) { -// fprintf(stderr, "steal %d from %p: next: %p\n", -// r, oldValue, oldValue->sites->next); + assert(c, c->registers[r].refCount == 0); + + if (DebugRegisters) { + fprintf(stderr, "steal %d from %p: next: %p\n", + r, oldValue, oldValue->sites->next); + } if (oldValue->sites->next == 0) { unsigned count = 0; @@ -818,6 +848,10 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, void release(Context* c, int r) { + if (DebugRegisters) { + fprintf(stderr, "release %d\n", r); + } + c->registers[r].size = 0; c->registers[r].value = 0; c->registers[r].site = 0; @@ -845,7 +879,7 @@ apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b) } void -insertRead(Context* c, Event* thisEvent, Event* before, Value* v, +insertRead(Context* c, Event* thisEvent, Event* previousEvent, Value* v, unsigned size, Site* target) { Read* r = new (c->zone->allocate(sizeof(Read))) @@ -854,9 +888,9 @@ insertRead(Context* c, Event* thisEvent, Event* before, Value* v, // fprintf(stderr, "add read %p to %p\n", r, v); - if (before) { + if (previousEvent) { for (Read** p = &(v->reads); *p;) { - if ((*p)->event->sequence >= before->sequence) { + if ((*p)->event->sequence > previousEvent->sequence) { r->next = *p; *p = r; break; @@ -955,6 +989,10 @@ class CallEvent: public Event { s = s->next; } + for (Stack* s = stack; s; s = s->next) { + addRead(c, s->value, s->size * BytesPerWord, 0); + } + addRead(c, address, BytesPerWord, (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); } @@ -963,6 +1001,8 @@ class CallEvent: public Event { if (DebugCompile) { fprintf(stderr, "CallEvent.compile\n"); } + + pushNow(c, stack); UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); if (indirection) { @@ -1432,21 +1472,23 @@ class StackSyncEvent: public Event { { unsigned i = 0; for (Stack* s = stack; s; s = s->next) { - addRead(c, s->value, s->size * BytesPerWord, - stackSyncSite(c, i, s->size)); + s->syncSite = stackSyncSite(c, i, s->size); + addRead(c, s->value, s->size * BytesPerWord, s->syncSite); i += s->size; } resetStack(c); } - StackSyncEvent(Context* c, Event* next): - Event(c, next) + StackSyncEvent(Context* c, Event* previous): + Event(c, previous) { unsigned i = 0; for (Stack* s = stack; s; s = s->next) { - insertRead(c, this, next, s->value, s->size * BytesPerWord, - stackSyncSite(c, i, s->size)); + s->syncSite = stackSyncSite(c, i, s->size); + insertRead(c, this, previous, s->value, s->size * BytesPerWord, + s->syncSite); + s->pushEvent->active = false; i += s->size; } } @@ -1460,6 +1502,14 @@ class StackSyncEvent: public Event { fprintf(stderr, "StackSyncEvent.compile\n"); } + for (Stack* s = stack; s; s = s->next) { + clearSites(c, s->value); + } + + for (Stack* s = stack; s; s = s->next) { + addSite(c, 0, 0, s->value, s->syncSite); + } + for (Read* r = reads; r; r = r->eventNext) { nextRead(c, r->value); } @@ -1664,14 +1714,14 @@ void updateJunctions(Context* c) { for (Junction* j = c->junctions; j; j = j->next) { - LogicalInstruction* i = c->logicalCode + j->logicalIp; - for (int ip = j->logicalIp - 1; ip >= 0; --ip) { LogicalInstruction* p = c->logicalCode + ip; if (p->lastEvent) { - i->lastEvent = i->lastEvent->next +// fprintf(stderr, "update junction at %d, predecessor %d\n", j->logicalIp, ip); + p->lastEvent = p->lastEvent->next = new (c->zone->allocate(sizeof(StackSyncEvent))) - StackSyncEvent(c, 0); + StackSyncEvent(c, p->lastEvent); + break; } } } @@ -1700,7 +1750,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and (not c->registers[i].reserved) + and c->registers[i].refCount == 0 and (not used(c, i))) { return i; @@ -1719,7 +1769,7 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except - and (not c->registers[i].reserved)) + and c->registers[i].refCount == 0) { return i; } @@ -1756,15 +1806,15 @@ class Client: public Assembler::Client { if (r == NoRegister) { r = freeRegisterExcept(c, NoRegister, false); } else { - expect(c, not c->registers[r].reserved); + expect(c, c->registers[r].refCount == 0); expect(c, c->registers[r].value == 0); } - c->registers[r].reserved = true; + increment(c, r); return r; } virtual void releaseTemporary(int r) { - c->registers[r].reserved = false; + decrement(c, r); } Context* c; @@ -1795,6 +1845,8 @@ class MyCompiler: public Compiler { } virtual void visitLogicalIp(unsigned logicalIp) { +// fprintf(stderr, " ++ visit ip: %d visits: %d\n", logicalIp, c.logicalCode[logicalIp].visits + 1); + if ((++ c.logicalCode[logicalIp].visits) == 2) { c.junctions = new (c.zone->allocate(sizeof(Junction))) Junction(logicalIp, c.junctions); diff --git a/src/x86.cpp b/src/x86.cpp index e5bc27a9ec..637830678c 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -837,7 +837,7 @@ andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, if (isInt8(v)) { c->code.append(0x83); c->code.append(0xe0 | b->low); - c->code.append(a->value->value()); + c->code.append(v); } else if (isInt32(v)) { c->code.append(0x81); c->code.append(0xe0 | b->low); @@ -865,6 +865,27 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +shiftLeftCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + + rex(c); + if (v == 1) { + c->code.append(0xd1); + c->code.append(0xe0 | b->low); + } else if (isInt8(v)) { + c->code.append(0xc1); + c->code.append(0xe0 | b->low); + c->code.append(v); + } else { + abort(c); + } +} + void compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -1018,6 +1039,8 @@ populateTables() BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); + BinaryOperations[INDEX2(ShiftLeft, Constant, Register)] = CAST2(shiftLeftCR); + BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); From fb06f7634c73f133627563467a47ba146b0f418a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 19:08:26 -0600 Subject: [PATCH 039/121] fix thinko in MyCompiler::pushed --- src/compiler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index fc1ff59cfe..f659ec8217 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1972,8 +1972,9 @@ class MyCompiler: public Compiler { virtual void pushed(unsigned count) { for (unsigned i = 0; i < count; ++i) { - Value* a = value(&c); - ::push(&c, BytesPerWord, a); + Value* v = value(&c); + c.state->stack = ::stack(&c, v, 1, c.state->stack); + c.state->stack->pushed = true; } } From ddada5551d37377d8422d4e786f62d634334a10e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 20:04:15 -0600 Subject: [PATCH 040/121] fix argument order bug in moveZRR --- src/x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index 637830678c..010f0dc132 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -741,7 +741,7 @@ moveZRR(Context* c, unsigned size, Assembler::Register* a, rex(c); c->code.append(0x0f); c->code.append(0xb7); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); break; default: abort(c); // todo From 281bdb1fab1128d00933681731d21e7e1bb56425 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 20:05:17 -0600 Subject: [PATCH 041/121] avoid inserting redundant stack sync events --- src/compiler.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index f659ec8217..4742c74851 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -325,6 +325,8 @@ class Event { virtual void compile(Context* c) = 0; + virtual bool needsStackSync() { return true; }; + Event* next; Stack* stack; CodePromise* promises; @@ -379,7 +381,7 @@ clearSites(Context* c, Value* v) void nextRead(Context* c, Value* v) { - // fprintf(stderr, "pop read %p from %p\n", v->reads, v); +// fprintf(stderr, "pop read %p from %p; next: %p\n", v->reads, v, v->reads->next); v->reads = v->reads->next; if (v->reads == 0) { @@ -1220,6 +1222,8 @@ class BranchEvent: public Event { nextRead(c, address); } + virtual bool needsStackSync() { return false; }; + UnaryOperation type; Value* address; }; @@ -1488,7 +1492,7 @@ class StackSyncEvent: public Event { s->syncSite = stackSyncSite(c, i, s->size); insertRead(c, this, previous, s->value, s->size * BytesPerWord, s->syncSite); - s->pushEvent->active = false; + if (s->pushEvent) s->pushEvent->active = false; i += s->size; } } @@ -1514,6 +1518,8 @@ class StackSyncEvent: public Event { nextRead(c, r->value); } } + + virtual bool needsStackSync() { return false; }; }; void @@ -1718,9 +1724,11 @@ updateJunctions(Context* c) LogicalInstruction* p = c->logicalCode + ip; if (p->lastEvent) { // fprintf(stderr, "update junction at %d, predecessor %d\n", j->logicalIp, ip); - p->lastEvent = p->lastEvent->next - = new (c->zone->allocate(sizeof(StackSyncEvent))) - StackSyncEvent(c, p->lastEvent); + if (p->lastEvent->needsStackSync()) { + p->lastEvent = p->lastEvent->next + = new (c->zone->allocate(sizeof(StackSyncEvent))) + StackSyncEvent(c, p->lastEvent); + } break; } } From 8ebff705d6c37330667d386f65721b95100525d7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Apr 2008 23:23:08 -0600 Subject: [PATCH 042/121] various fixes --- src/compile.cpp | 31 ++++++-- src/compiler.cpp | 183 +++++++++++++++++++++++++---------------------- 2 files changed, 121 insertions(+), 93 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index e2510ca54d..10f84def2a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -722,6 +722,10 @@ class Frame { void startLogicalIp(unsigned ip) { c->startLogicalIp(ip); + + context->eventLog.append(IpEvent); + context->eventLog.append2(ip); + this->ip = ip; } @@ -1698,10 +1702,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, PROTECT(t, code); while (ip < codeLength(t, code)) { - frame->visitLogicalIp(ip); - if (context->visitTable[ip] ++) { // we've already visited this part of the code + frame->visitLogicalIp(ip); return; } @@ -1749,6 +1752,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, throw_ = c->label(); c->cmp(4, c->constant(0), index); c->jl(throw_); + + index = c->peek(4, 0); + array = c->peek(BytesPerWord, 1); } c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); @@ -1758,6 +1764,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(throw_); } + index = c->peek(4, 0); + array = c->peek(BytesPerWord, 1); + c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), context->indirection, @@ -1860,6 +1869,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, throw_ = c->label(); c->cmp(4, c->constant(0), index); c->jl(throw_); + + index = c->peek(4, valueSize); + array = c->peek(BytesPerWord, valueSize + 1); } c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); @@ -1869,6 +1881,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(throw_); } + index = c->peek(4, valueSize); + array = c->peek(BytesPerWord, valueSize + 1); + c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), context->indirection, @@ -2003,6 +2018,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->cmp(4, c->constant(0), length); c->jge(nonnegative); + length = c->peek(4, 0); + c->call (c->constant(reinterpret_cast(throwNegativeArraySize)), context->indirection, @@ -2014,7 +2031,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(nonnegative); } - frame->popInt(); + length = frame->popInt(); frame->pushObject (c->call @@ -3190,6 +3207,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->cmp(4, c->constant(0), length); c->jge(nonnegative); + length = c->peek(4, 0); + c->call (c->constant(reinterpret_cast(throwNegativeArraySize)), context->indirection, @@ -3201,7 +3220,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->mark(nonnegative); } - frame->popInt(); + length = frame->popInt(); object (*constructor)(Thread*, uintptr_t, bool); switch (type) { @@ -3851,11 +3870,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Enums") == 0 and + "Enums$Suit") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "main") == 0) + "") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 4742c74851..13c70518c5 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -46,7 +46,7 @@ class Site { virtual unsigned copyCost(Context*, Site*) = 0; - virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } + virtual void acquire(Context*, Stack*, unsigned, Value*) { } virtual void release(Context*) { } @@ -87,7 +87,6 @@ class State { class LogicalInstruction { public: - unsigned visits; Event* firstEvent; Event* lastEvent; unsigned machineOffset; @@ -139,8 +138,8 @@ class Read { class Value: public Compiler::Operand { public: - Value(Site* site): - reads(0), lastRead(0), sites(site), source(0), target(site) + Value(Site* site, Site* target): + reads(0), lastRead(0), sites(site), source(0), target(target) { } Read* reads; @@ -171,7 +170,8 @@ class Context { constantCount(0), nextSequence(0), junctions(0), - machineCode(0) + machineCode(0), + stackReset(false) { memset(registers, 0, sizeof(Register) * assembler->registerCount()); @@ -207,6 +207,7 @@ class Context { unsigned nextSequence; Junction* junctions; uint8_t* machineCode; + bool stackReset; }; class PoolPromise: public Promise { @@ -301,7 +302,7 @@ class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0), reads(0), - sequence(c->nextSequence++) + sequence(c->nextSequence++), stackReset(c->stackReset) { assert(c, c->logicalIp >= 0); @@ -312,11 +313,15 @@ class Event { i->firstEvent = this; } i->lastEvent = this; + + if (c->stackReset) { + c->stackReset = false; + } } - Event(Context*, Event* previous): - next(0), stack(previous->stack), promises(0), reads(0), - sequence(previous->sequence) + Event(Context*, Event* previous, Event* next): + next(0), stack(next->stack), promises(0), reads(0), + sequence(previous->sequence), stackReset(false) { } virtual ~Event() { } @@ -325,13 +330,14 @@ class Event { virtual void compile(Context* c) = 0; - virtual bool needsStackSync() { return true; }; + virtual bool needStackSync() { return true; }; Event* next; Stack* stack; CodePromise* promises; Read* reads; unsigned sequence; + bool stackReset; }; bool @@ -348,7 +354,7 @@ addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (not findSite(c, v, s)) { // fprintf(stderr, "add site %p to %p\n", s, v); - s->acquire(c, stack, size, v, s); + s->acquire(c, stack, size, v); s->next = v->sites; v->sites = s; } @@ -478,12 +484,10 @@ class RegisterSite: public Site { } } - virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, - Site* s) - { - ::acquire(c, register_.low, stack, size, v, s); + virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) { + ::acquire(c, register_.low, stack, size, v, this); if (register_.high >= 0) { - ::acquire(c, register_.high, stack, size, v, s); + ::acquire(c, register_.high, stack, size, v, this); } } @@ -561,7 +565,7 @@ class MemorySite: public Site { } } - virtual void acquire(Context* c, Stack*, unsigned, Value*, Site*) { + virtual void acquire(Context* c, Stack*, unsigned, Value*) { increment(c, value.base); if (value.index != NoRegister) { increment(c, value.index); @@ -729,12 +733,6 @@ constantOrRegisterSite(Context* c) ConstantOrRegisterSite(); } -Value* -value(Context* c, Site* site = 0) -{ - return new (c->zone->allocate(sizeof(Value))) Value(site); -} - Site* pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) { @@ -1204,40 +1202,6 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second) CompareEvent(c, size, first, second); } -class BranchEvent: public Event { - public: - BranchEvent(Context* c, UnaryOperation type, Value* address): - Event(c), type(type), address(address) - { - addRead(c, address, BytesPerWord, 0); - } - - virtual void compile(Context* c) { - if (DebugCompile) { - fprintf(stderr, "BranchEvent.compile\n"); - } - - apply(c, type, BytesPerWord, address->source); - - nextRead(c, address); - } - - virtual bool needsStackSync() { return false; }; - - UnaryOperation type; - Value* address; -}; - -void -appendBranch(Context* c, UnaryOperation type, Value* address) -{ - if (DebugAppend) { - fprintf(stderr, "appendBranch\n"); - } - - new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); -} - class CombineEvent: public Event { public: CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, @@ -1404,6 +1368,18 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) Stack(value, size, index, next); } +Value* +value(Context* c, Site* site, Site* target) +{ + return new (c->zone->allocate(sizeof(Value))) Value(site, target); +} + +Value* +value(Context* c, Site* site = 0) +{ + return value(c, site, site); +} + void resetStack(Context* c) { @@ -1422,6 +1398,8 @@ resetStack(Context* c) i += s->size; } + + c->stackReset = true; } void @@ -1480,12 +1458,10 @@ class StackSyncEvent: public Event { addRead(c, s->value, s->size * BytesPerWord, s->syncSite); i += s->size; } - - resetStack(c); } - StackSyncEvent(Context* c, Event* previous): - Event(c, previous) + StackSyncEvent(Context* c, Event* previous, Event* next): + Event(c, previous, next) { unsigned i = 0; for (Stack* s = stack; s; s = s->next) { @@ -1519,7 +1495,7 @@ class StackSyncEvent: public Event { } } - virtual bool needsStackSync() { return false; }; + virtual bool needStackSync() { return false; }; }; void @@ -1532,6 +1508,44 @@ appendStackSync(Context* c) new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c); } +class BranchEvent: public Event { + public: + BranchEvent(Context* c, UnaryOperation type, Value* address): + Event(c), type(type), address(address) + { + addRead(c, address, BytesPerWord, 0); + } + + virtual void compile(Context* c) { + if (DebugCompile) { + fprintf(stderr, "BranchEvent.compile\n"); + } + + apply(c, type, BytesPerWord, address->source); + + nextRead(c, address); + } + + virtual bool needStackSync() { return false; }; + + UnaryOperation type; + Value* address; +}; + +void +appendBranch(Context* c, UnaryOperation type, Value* address) +{ + appendStackSync(c); + + if (DebugAppend) { + fprintf(stderr, "appendBranch\n"); + } + + new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); + + resetStack(c); +} + class PushSite: public AbstractSite { public: PushSite(PushEvent* event): event(event) { } @@ -1645,6 +1659,15 @@ compile(Context* c) } for (Event* e = li->firstEvent; e; e = e->next) { + if (e->stackReset) { + for (Stack* s = e->stack; s; s = s->next) { + assert(c, s->value->sites->next == 0); + if (s->value->reads) { + s->value->sites->acquire(c, 0, 0, s->value); + } + } + } + e->prepare(c); for (Read* r = e->reads; r; r = r->eventNext) { @@ -1720,14 +1743,16 @@ void updateJunctions(Context* c) { for (Junction* j = c->junctions; j; j = j->next) { + LogicalInstruction* i = c->logicalCode + j->logicalIp; + for (int ip = j->logicalIp - 1; ip >= 0; --ip) { LogicalInstruction* p = c->logicalCode + ip; if (p->lastEvent) { // fprintf(stderr, "update junction at %d, predecessor %d\n", j->logicalIp, ip); - if (p->lastEvent->needsStackSync()) { + if (p->lastEvent->needStackSync()) { p->lastEvent = p->lastEvent->next = new (c->zone->allocate(sizeof(StackSyncEvent))) - StackSyncEvent(c, p->lastEvent); + StackSyncEvent(c, p->lastEvent, i->firstEvent); } break; } @@ -1853,12 +1878,9 @@ class MyCompiler: public Compiler { } virtual void visitLogicalIp(unsigned logicalIp) { -// fprintf(stderr, " ++ visit ip: %d visits: %d\n", logicalIp, c.logicalCode[logicalIp].visits + 1); - - if ((++ c.logicalCode[logicalIp].visits) == 2) { - c.junctions = new (c.zone->allocate(sizeof(Junction))) - Junction(logicalIp, c.junctions); - } + c.stackReset = false; + c.junctions = new (c.zone->allocate(sizeof(Junction))) + Junction(logicalIp, c.junctions); } virtual void startLogicalIp(unsigned logicalIp) { @@ -1900,11 +1922,11 @@ class MyCompiler: public Compiler { } virtual Operand* promiseConstant(Promise* value) { - return ::value(&c, ::constantSite(&c, value)); + return ::value(&c, ::constantSite(&c, value), 0); } virtual Operand* address(Promise* address) { - return value(&c, ::addressSite(&c, address)); + return value(&c, ::addressSite(&c, address), 0); } virtual Operand* memory(Operand* base, @@ -1949,7 +1971,7 @@ class MyCompiler: public Compiler { } virtual Operand* label() { - return value(&c, ::constantSite(&c, static_cast(0))); + return value(&c, ::constantSite(&c, static_cast(0)), 0); } Promise* machineIp() { @@ -1960,6 +1982,7 @@ class MyCompiler: public Compiler { virtual void mark(Operand* label) { appendStackSync(&c); + resetStack(&c); for (Site* s = static_cast(label)->sites; s; s = s->next) { if (s->type(&c) == ConstantOperand) { @@ -2093,44 +2116,30 @@ class MyCompiler: public Compiler { } virtual void jl(Operand* address) { - appendStackSync(&c); - appendBranch(&c, JumpIfLess, static_cast(address)); } virtual void jg(Operand* address) { - appendStackSync(&c); - appendBranch(&c, JumpIfGreater, static_cast(address)); } virtual void jle(Operand* address) { - appendStackSync(&c); - appendBranch(&c, JumpIfLessOrEqual, static_cast(address)); } virtual void jge(Operand* address) { - appendStackSync(&c); - appendBranch(&c, JumpIfGreaterOrEqual, static_cast(address)); } virtual void je(Operand* address) { - appendStackSync(&c); - appendBranch(&c, JumpIfEqual, static_cast(address)); } virtual void jne(Operand* address) { - appendStackSync(&c); - appendBranch(&c, JumpIfNotEqual, static_cast(address)); } virtual void jmp(Operand* address) { - appendStackSync(&c); - appendBranch(&c, Jump, static_cast(address)); } From d6c3b2327fd898d57d0cee47feafce55ff62dbc0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 20 Apr 2008 13:35:36 -0600 Subject: [PATCH 043/121] bugfixes; enums test now succeeds --- src/compile.cpp | 8 +-- src/compiler.cpp | 123 +++++++++++++++++++++++++++++------------------ src/x86.cpp | 9 ++++ test/Misc.java | 24 ++++----- 4 files changed, 101 insertions(+), 63 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 10f84def2a..9ba094c51c 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3436,8 +3436,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->cmp(4, c->constant(top), key); c->jg(defaultCase); - c->sub(4, c->constant(bottom), key); - c->jmp(c->memory(start, 0, key, BytesPerWord)); + c->jmp(c->memory(start, 0, c->sub(4, c->constant(bottom), key), + BytesPerWord)); c->mark(defaultCase); c->jmp(frame->machineIp(defaultIp)); @@ -3870,11 +3870,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Enums$Suit") == 0 and + "Enums") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "main") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 13c70518c5..1d05598eab 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -89,7 +89,10 @@ class LogicalInstruction { public: Event* firstEvent; Event* lastEvent; + LogicalInstruction* immediatePredecessor; + Stack* stack; unsigned machineOffset; + bool stackSaved; }; class Register { @@ -138,8 +141,8 @@ class Read { class Value: public Compiler::Operand { public: - Value(Site* site, Site* target): - reads(0), lastRead(0), sites(site), source(0), target(target) + Value(Site* site): + reads(0), lastRead(0), sites(site), source(0), target(site) { } Read* reads; @@ -315,13 +318,14 @@ class Event { i->lastEvent = this; if (c->stackReset) { +// fprintf(stderr, "stack reset\n"); c->stackReset = false; } } - Event(Context*, Event* previous, Event* next): - next(0), stack(next->stack), promises(0), reads(0), - sequence(previous->sequence), stackReset(false) + Event(Context*, unsigned sequence, Stack* stack): + next(0), stack(stack), promises(0), reads(0), + sequence(sequence), stackReset(false) { } virtual ~Event() { } @@ -330,7 +334,7 @@ class Event { virtual void compile(Context* c) = 0; - virtual bool needStackSync() { return true; }; + virtual bool isBranch() { return false; }; Event* next; Stack* stack; @@ -528,7 +532,7 @@ void increment(Context* c, int r) { if (DebugRegisters) { - fprintf(stderr, "increment %d\n", r); + fprintf(stderr, "increment %d to %d\n", r, c->registers[r].refCount + 1); } ++ c->registers[r].refCount; } @@ -539,7 +543,7 @@ decrement(Context* c, int r) assert(c, c->registers[r].refCount > 0); assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); if (DebugRegisters) { - fprintf(stderr, "decrement %d\n", r); + fprintf(stderr, "decrement %d to %d\n", r, c->registers[r].refCount - 1); } -- c->registers[r].refCount; } @@ -879,7 +883,7 @@ apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b) } void -insertRead(Context* c, Event* thisEvent, Event* previousEvent, Value* v, +insertRead(Context* c, Event* thisEvent, int sequence, Value* v, unsigned size, Site* target) { Read* r = new (c->zone->allocate(sizeof(Read))) @@ -888,9 +892,9 @@ insertRead(Context* c, Event* thisEvent, Event* previousEvent, Value* v, // fprintf(stderr, "add read %p to %p\n", r, v); - if (previousEvent) { + if (sequence >= 0) { for (Read** p = &(v->reads); *p;) { - if ((*p)->event->sequence > previousEvent->sequence) { + if ((*p)->event->sequence > static_cast(sequence)) { r->next = *p; *p = r; break; @@ -913,7 +917,7 @@ insertRead(Context* c, Event* thisEvent, Event* previousEvent, Value* v, void addRead(Context* c, Value* v, unsigned size, Site* target) { - insertRead(c, c->logicalCode[c->logicalIp].lastEvent, 0, v, size, target); + insertRead(c, c->logicalCode[c->logicalIp].lastEvent, -1, v, size, target); } Site* @@ -1145,7 +1149,11 @@ class MoveEvent: public Event { nextRead(c, src); - if (dst->reads) addSite(c, stack, size, dst, target); + if (dst->reads) { + addSite(c, stack, size, dst, target); + } else { + removeSite(c, dst, target); + } } BinaryOperation type; @@ -1368,16 +1376,10 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) Stack(value, size, index, next); } -Value* -value(Context* c, Site* site, Site* target) -{ - return new (c->zone->allocate(sizeof(Value))) Value(site, target); -} - Value* value(Context* c, Site* site = 0) { - return value(c, site, site); + return new (c->zone->allocate(sizeof(Value))) Value(site); } void @@ -1460,13 +1462,13 @@ class StackSyncEvent: public Event { } } - StackSyncEvent(Context* c, Event* previous, Event* next): - Event(c, previous, next) + StackSyncEvent(Context* c, unsigned sequence, Stack* stack): + Event(c, sequence, stack) { unsigned i = 0; for (Stack* s = stack; s; s = s->next) { s->syncSite = stackSyncSite(c, i, s->size); - insertRead(c, this, previous, s->value, s->size * BytesPerWord, + insertRead(c, this, sequence, s->value, s->size * BytesPerWord, s->syncSite); if (s->pushEvent) s->pushEvent->active = false; i += s->size; @@ -1494,8 +1496,6 @@ class StackSyncEvent: public Event { nextRead(c, r->value); } } - - virtual bool needStackSync() { return false; }; }; void @@ -1526,7 +1526,7 @@ class BranchEvent: public Event { nextRead(c, address); } - virtual bool needStackSync() { return false; }; + virtual bool isBranch() { return true; }; UnaryOperation type; Value* address; @@ -1660,10 +1660,13 @@ compile(Context* c) for (Event* e = li->firstEvent; e; e = e->next) { if (e->stackReset) { +// fprintf(stderr, "stack reset\n"); for (Stack* s = e->stack; s; s = s->next) { - assert(c, s->value->sites->next == 0); - if (s->value->reads) { - s->value->sites->acquire(c, 0, 0, s->value); + if (s->value->sites) { + assert(c, s->value->sites->next == 0); + if (s->value->reads) { + s->value->sites->acquire(c, 0, 0, s->value); + } } } } @@ -1702,9 +1705,20 @@ pushState(Context* c) State(c->state); } +void +saveStack(Context* c) +{ + if (c->logicalIp >= 0 and not c->logicalCode[c->logicalIp].stackSaved) { + c->logicalCode[c->logicalIp].stackSaved = true; + c->logicalCode[c->logicalIp].stack = c->state->stack; + } +} + void popState(Context* c) { + saveStack(c); + c->state = new (c->zone->allocate(sizeof(State))) State(c->state->next); @@ -1744,19 +1758,11 @@ updateJunctions(Context* c) { for (Junction* j = c->junctions; j; j = j->next) { LogicalInstruction* i = c->logicalCode + j->logicalIp; + LogicalInstruction* p = i->immediatePredecessor; - for (int ip = j->logicalIp - 1; ip >= 0; --ip) { - LogicalInstruction* p = c->logicalCode + ip; - if (p->lastEvent) { -// fprintf(stderr, "update junction at %d, predecessor %d\n", j->logicalIp, ip); - if (p->lastEvent->needStackSync()) { - p->lastEvent = p->lastEvent->next - = new (c->zone->allocate(sizeof(StackSyncEvent))) - StackSyncEvent(c, p->lastEvent, i->firstEvent); - } - break; - } - } + p->lastEvent = p->lastEvent->next + = new (c->zone->allocate(sizeof(StackSyncEvent))) + StackSyncEvent(c, p->lastEvent->sequence, p->stack); } } @@ -1812,6 +1818,18 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) abort(c); } +void +visit(Context* c, unsigned logicalIp) +{ + assert(c, logicalIp < c->logicalCodeLength); + + if (c->logicalIp >= 0 and (not c->stackReset)) { + assert(c, c->logicalCode[logicalIp].immediatePredecessor == 0); + c->logicalCode[logicalIp].immediatePredecessor + = c->logicalCode + c->logicalIp; + } +} + int freeRegister(Context* c, bool allowAcquired) { @@ -1878,15 +1896,25 @@ class MyCompiler: public Compiler { } virtual void visitLogicalIp(unsigned logicalIp) { + visit(&c, logicalIp); + c.stackReset = false; - c.junctions = new (c.zone->allocate(sizeof(Junction))) - Junction(logicalIp, c.junctions); + + if (c.logicalCode[logicalIp].immediatePredecessor) { + c.junctions = new (c.zone->allocate(sizeof(Junction))) + Junction(logicalIp, c.junctions); + } } virtual void startLogicalIp(unsigned logicalIp) { if (DebugAppend) { fprintf(stderr, " -- ip: %d\n", logicalIp); } + + visit(&c, logicalIp); + + saveStack(&c); + c.logicalIp = logicalIp; } @@ -1922,11 +1950,11 @@ class MyCompiler: public Compiler { } virtual Operand* promiseConstant(Promise* value) { - return ::value(&c, ::constantSite(&c, value), 0); + return ::value(&c, ::constantSite(&c, value)); } virtual Operand* address(Promise* address) { - return value(&c, ::addressSite(&c, address), 0); + return value(&c, ::addressSite(&c, address)); } virtual Operand* memory(Operand* base, @@ -1971,7 +1999,7 @@ class MyCompiler: public Compiler { } virtual Operand* label() { - return value(&c, ::constantSite(&c, static_cast(0)), 0); + return value(&c, ::constantSite(&c, static_cast(0))); } Promise* machineIp() { @@ -2242,8 +2270,9 @@ class MyCompiler: public Compiler { int i = 0; for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) { - *reinterpret_cast(dst + pad(c.assembler->length()) + (i++)) + *reinterpret_cast(dst + pad(c.assembler->length()) + i) = n->promise->value(); + i += BytesPerWord; } } diff --git a/src/x86.cpp b/src/x86.cpp index 010f0dc132..346c9b8d61 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -358,6 +358,14 @@ jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a) unconditional(c, 0xe9, a); } +void +jumpM(Context* c, unsigned size UNUSED, Assembler::Memory* a) +{ + assert(c, size == BytesPerWord); + + encode(c, 0xff, 4, a, false); +} + void jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) { @@ -997,6 +1005,7 @@ populateTables() UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); UnaryOperations[INDEX1(Jump, Constant)] = CAST1(jumpC); + UnaryOperations[INDEX1(Jump, Memory)] = CAST1(jumpM); UnaryOperations[INDEX1(JumpIfEqual, Constant)] = CAST1(jumpIfEqualC); UnaryOperations[INDEX1(JumpIfNotEqual, Constant)] = CAST1(jumpIfNotEqualC); diff --git a/test/Misc.java b/test/Misc.java index 92fcb7b339..81ac4b60ca 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -10,13 +10,13 @@ public class Misc { private long time; public Misc() { - expect(! boolean1); - expect(! boolean2); +// expect(! boolean1); +// expect(! boolean2); - time = 0xffffffffffffffffL; +// time = 0xffffffffffffffffL; - expect(! boolean1); - expect(! boolean2); +// expect(! boolean1); +// expect(! boolean2); } private String foo(String s) { @@ -101,17 +101,17 @@ public class Misc { // ClassLoader.getSystemClassLoader().toString(); -// int a = 2; -// int b = 2; -// int c = a + b; + int a = 2; + int b = 2; + int c = a + b; Misc m = new Misc(); m.toString(); -// String s = "hello"; -// m.foo(s); -// m.bar(s); -// baz(s); + String s = "hello"; + m.foo(s); + m.bar(s); + baz(s); // m.sync(); // syncStatic(false); From 9976c1132cb7d3150eab09cf3a8c3d5c2aa65b45 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 20 Apr 2008 14:43:28 -0600 Subject: [PATCH 044/121] fix instruction callR --- src/x86.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 346c9b8d61..8f57f259b6 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -302,7 +302,6 @@ callC(Context* c, unsigned size, Assembler::Constant* a) Assembler::Register r(r10); moveCR(c, size, a, &r); callR(c, size, &r); - c->client->releaseTemporary(r.low); } else { unconditional(c, 0xe8, a); } @@ -330,7 +329,7 @@ callR(Context* c, unsigned size UNUSED, Assembler::Register* a) if (a->low & 8) rex(c, 0x40, a->low); c->code.append(0xff); - c->code.append(0xd0 | a->low); + c->code.append(0xd0 | (a->low & 7)); } void From a259beccdc642c8be30458f2a22d13a32cad01f4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 20 Apr 2008 16:19:11 -0600 Subject: [PATCH 045/121] implement xorRR, remove unused Assembler::stackSyncRegister --- src/assembler.h | 2 -- src/x86.cpp | 30 +++++++++++++----------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index f84dd37b34..e97ee597db 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -153,8 +153,6 @@ class Assembler { 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; diff --git a/src/x86.cpp b/src/x86.cpp index 8f57f259b6..508d4ebd7b 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -872,6 +872,17 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +xorRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x31); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void shiftLeftCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -1047,6 +1058,8 @@ populateTables() BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); + BinaryOperations[INDEX2(Xor, Register, Register)] = CAST2(xorRR); + BinaryOperations[INDEX2(ShiftLeft, Constant, Register)] = CAST2(shiftLeftCR); BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); @@ -1124,23 +1137,6 @@ class MyAssembler: public Assembler { } } - virtual int stackSyncRegister(unsigned index) { - switch (index) { - case 0: - return rax; - case 1: - return rcx; - case 2: - return rdx; - case 3: - return rsi; - case 4: - return rdi; - default: - abort(&c); - } - } - virtual void getTargets(UnaryOperation /*op*/, unsigned /*size*/, Register* r) { From 2289d13cbbc581edbdde4715bd4daaf6d32171b2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 20 Apr 2008 18:20:38 -0600 Subject: [PATCH 046/121] make debug logging more concise --- src/compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index 9ba094c51c..db067d2c02 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3506,7 +3506,7 @@ void logCompile(const void* code, unsigned size, const char* class_, const char* name, const char* spec) { - fprintf(stderr, "%s.%s%s from %p to %p\n", + fprintf(stderr, "%s.%s%s: %p %p\n", class_, name, spec, code, static_cast(code) + size); } From 6b4cafd9622fa96e7bfd8a83de50332099ed4e41 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 20 Apr 2008 18:21:48 -0600 Subject: [PATCH 047/121] fix argument marshalling on amd64 --- src/compiler.cpp | 153 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 37 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 1d05598eab..f17aec81d4 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -46,7 +46,7 @@ class Site { virtual unsigned copyCost(Context*, Site*) = 0; - virtual void acquire(Context*, Stack*, unsigned, Value*) { } + virtual bool tryAcquire(Context*, Stack*, unsigned, Value*) { return true; } virtual void release(Context*) { } @@ -353,15 +353,25 @@ findSite(Context*, Value* v, Site* site) return false; } -void -addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) +bool +tryAddSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (not findSite(c, v, s)) { // fprintf(stderr, "add site %p to %p\n", s, v); - s->acquire(c, stack, size, v); - s->next = v->sites; - v->sites = s; + if (s->tryAcquire(c, stack, size, v)) { + s->next = v->sites; + v->sites = s; + } else { + return false; + } } + return true; +} + +void +addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) +{ + expect(c, tryAddSite(c, stack, size, v, s)); } void @@ -462,9 +472,9 @@ addressSite(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); } -void -acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, - Site* newSite); +bool +tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, + Site* newSite); void release(Context* c, int r); @@ -488,11 +498,19 @@ class RegisterSite: public Site { } } - virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) { - ::acquire(c, register_.low, stack, size, v, this); - if (register_.high >= 0) { - ::acquire(c, register_.high, stack, size, v, this); + virtual bool tryAcquire(Context* c, Stack* stack, unsigned size, Value* v) { + if (::tryAcquire(c, register_.low, stack, size, v, this)) { + if (register_.high != NoRegister) { + if (::tryAcquire(c, register_.high, stack, size, v, this)) { + return true; + } else { + ::release(c, register_.low); + } + } else { + return true; + } } + return false; } virtual void release(Context* c) { @@ -569,11 +587,12 @@ class MemorySite: public Site { } } - virtual void acquire(Context* c, Stack*, unsigned, Value*) { + virtual bool tryAcquire(Context* c, Stack*, unsigned, Value*) { increment(c, value.base); if (value.index != NoRegister) { increment(c, value.index); } + return true; } virtual void release(Context* c) { @@ -772,7 +791,7 @@ pushNow(Context* c, Stack* start, unsigned count) s->pushSite = memorySite (c, c->assembler->base(), - (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1); - addSite(c, 0, 0, s->value, s->pushSite); + addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); } else { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); @@ -801,14 +820,16 @@ pushNow(Context* c, Stack* start) pushNow(c, start, count); } -void -acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, - Site* newSite) +bool +tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, + Site* newSite) { - if (c->registers[r].reserved) return; + assert(c, newSize); + + if (c->registers[r].reserved) return true; if (DebugRegisters) { - fprintf(stderr, "acquire %d, value %p, site %p\n", + fprintf(stderr, "try acquire %d, value %p, site %p\n", r, newValue, newSite); } @@ -820,7 +841,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, assert(c, c->registers[r].refCount == 0); if (DebugRegisters) { - fprintf(stderr, "steal %d from %p: next: %p\n", + fprintf(stderr, "try steal %d from %p: next: %p\n", r, oldValue, oldValue->sites->next); } @@ -836,9 +857,11 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, } } - assert(c, start); - - pushNow(c, start, count); + if (start) { + pushNow(c, start, count); + } else { + return false; + } } removeSite(c, oldValue, c->registers[r].site); @@ -847,6 +870,8 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, c->registers[r].size = newSize; c->registers[r].value = newValue; c->registers[r].site = newSite; + + return true; } void @@ -979,17 +1004,19 @@ class CallEvent: public Event { argumentFootprint(0) { Stack* s = argumentStack; + unsigned index = 0; for (unsigned i = 0; i < argumentCount; ++i) { Site* target; - if (argumentFootprint < c->assembler->argumentRegisterCount()) { + if (index < c->assembler->argumentRegisterCount()) { target = registerSite - (c, c->assembler->argumentRegister(argumentFootprint)); + (c, c->assembler->argumentRegister(index)); } else { target = 0; s->pushEvent->active = true; + ++ argumentFootprint; } addRead(c, s->value, s->size * BytesPerWord, target); - argumentFootprint += s->size; + index += s->size; s = s->next; } @@ -1021,7 +1048,9 @@ class CallEvent: public Event { } for (Stack* s = stack; s; s = s->next) { - if (s->pushSite) addSite(c, 0, 0, s->value, s->pushSite); + if (s->pushSite) { + addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); + } } for (Read* r = reads; r; r = r->eventNext) { @@ -1029,7 +1058,7 @@ class CallEvent: public Event { } if (resultSize and result->reads) { - addSite(c, 0, 0, result, registerSite + addSite(c, 0, resultSize, result, registerSite (c, c->assembler->returnLow(), resultSize > BytesPerWord ? c->assembler->returnHigh() : NoRegister)); @@ -1242,7 +1271,9 @@ class CombineEvent: public Event { nextRead(c, second); removeSite(c, second, second->source); - if (result->reads) addSite(c, 0, 0, result, second->source); + if (result->reads) { + addSite(c, 0, size, result, second->source); + } } BinaryOperation type; @@ -1283,7 +1314,9 @@ class TranslateEvent: public Event { nextRead(c, value); removeSite(c, value, value->source); - if (result->reads) addSite(c, 0, 0, result, value->source); + if (result->reads) { + addSite(c, 0, size, result, value->source); + } } UnaryOperation type; @@ -1489,7 +1522,7 @@ class StackSyncEvent: public Event { } for (Stack* s = stack; s; s = s->next) { - addSite(c, 0, 0, s->value, s->syncSite); + addSite(c, 0, s->size * BytesPerWord, s->value, s->syncSite); } for (Read* r = reads; r; r = r->eventNext) { @@ -1611,6 +1644,24 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } +void +swapRegisters(Context* c, int* ap, int* bp) +{ + Assembler::Register a(*ap); + Assembler::Register b(*bp); + + c->assembler->apply + (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); + c->assembler->apply + (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); + c->assembler->apply + (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); + + int t = *ap; + *ap = *bp; + *bp = t; +} + Site* readSource(Context* c, Stack* stack, Read* r, Event* e) { @@ -1621,12 +1672,39 @@ readSource(Context* c, Stack* stack, Read* r, Event* e) if (target) { if (copyCost) { - addSite(c, stack, r->size, r->value, target); + if (tryAddSite(c, stack, r->size, r->value, target)) { + apply(c, Move, r->size, site, target); + return target; + } else { + // this is a filthy hack, but I think the core idea is right: - apply(c, Move, r->size, site, target); + assert(c, target->type(c) == RegisterOperand); + + RegisterSite* ts = static_cast(target); + + for (Site* s = r->value->sites; s; s = s->next) { + if (s->type(c) == RegisterOperand) { + RegisterSite* rs = static_cast(s); + + RegisterSite* os = static_cast + (c->registers[ts->register_.low].site); + + assert(c, os->register_.low == ts->register_.low); + assert(c, os->register_.high == NoRegister); + assert(c, ts->register_.high == NoRegister); + assert(c, rs->register_.high == NoRegister); + + swapRegisters(c, &(os->register_.low), &(rs->register_.low)); + + return rs; + } + } + } + + abort(c); + } else { + return target; } - - return target; } else { return site; } @@ -1665,7 +1743,8 @@ compile(Context* c) if (s->value->sites) { assert(c, s->value->sites->next == 0); if (s->value->reads) { - s->value->sites->acquire(c, 0, 0, s->value); + expect(c, s->value->sites->tryAcquire + (c, 0, s->size * BytesPerWord, s->value)); } } } From 571bffde092844ce96d260027e89f3877ea8bdf9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 20 Apr 2008 20:50:46 -0600 Subject: [PATCH 048/121] fix some issues with 64-bit moves on 32-bit machines --- src/compiler.cpp | 8 +++---- src/x86.cpp | 55 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index f17aec81d4..a12ebebab2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -15,8 +15,8 @@ using namespace vm; namespace { -const bool DebugAppend = false; -const bool DebugCompile = false; +const bool DebugAppend = true; +const bool DebugCompile = true; const bool DebugStack = false; const bool DebugRegisters = false; @@ -824,8 +824,6 @@ bool tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) { - assert(c, newSize); - if (c->registers[r].reserved) return true; if (DebugRegisters) { @@ -2213,7 +2211,7 @@ class MyCompiler: public Compiler { virtual Operand* load4To8(Operand* src) { Value* dst = value(&c); - appendMove(&c, Move4To8, 0, static_cast(src), dst); + appendMove(&c, Move4To8, 8, static_cast(src), dst); return dst; } diff --git a/src/x86.cpp b/src/x86.cpp index 508d4ebd7b..ad12475da5 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -643,11 +643,25 @@ void move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8); + if (BytesPerWord == 8) { + rex(c); + c->code.append(0x63); + c->code.append(0xc0 | (a->low << 3) | b->low); + } else { + if (a->low == rax and b->low == rax and b->high == rdx) { + c->code.append(0x99); // cdq + } else { + Assembler::Register axdx(c->client->acquireTemporary(rax), + c->client->acquireTemporary(rdx)); - rex(c); - c->code.append(0x63); - c->code.append(0xc0 | (a->low << 3) | b->low); + moveRR(c, 4, a, &axdx); + move4To8RR(c, 0, &axdx, &axdx); + moveRR(c, 8, &axdx, b); + + c->client->releaseTemporary(axdx.low); + c->client->releaseTemporary(axdx.high); + } + } } void @@ -710,20 +724,37 @@ void moveMM(Context* c, unsigned size, Assembler::Memory* a, Assembler::Memory* b) { - assert(c, BytesPerWord == 8 or size <= 4); // todo - - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, size, a, &tmp); - moveRM(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + if (BytesPerWord == 8 or size <= 4) { + Assembler::Register tmp(c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + moveRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } else { + Assembler::Register tmp(c->client->acquireTemporary(), + c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + moveRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + c->client->releaseTemporary(tmp.high); + } } void move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8); // todo + if (BytesPerWord == 8) { + encode(c, 0x63, b->low, a, true); + } else { + Assembler::Register axdx(c->client->acquireTemporary(rax), + c->client->acquireTemporary(rdx)); - encode(c, 0x63, b->low, a, true); + moveMR(c, 4, a, &axdx); + move4To8RR(c, 0, &axdx, &axdx); + moveRR(c, 8, &axdx, b); + + c->client->releaseTemporary(axdx.low); + c->client->releaseTemporary(axdx.high); + } } void From d5137a7cdf4044b9a061b0c2e7efa17a7a08f330 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Apr 2008 14:56:03 -0600 Subject: [PATCH 049/121] use stack instead of registers to save data across jumps and branches; bugfixes --- src/compile.cpp | 86 ++++++-------------- src/compiler.cpp | 199 +++++++++++++++++++++++------------------------ src/compiler.h | 1 + src/x86.cpp | 85 +++++++++++++++++++- 4 files changed, 204 insertions(+), 167 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index db067d2c02..9bd513b945 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -751,7 +751,7 @@ class Frame { void pushLongQuiet(Compiler::Operand* o) { if (BytesPerWord == 8) { - c->pushed(1); + c->push(8); } c->push(8, o); } @@ -774,7 +774,7 @@ class Frame { Compiler::Operand* popLongQuiet() { Compiler::Operand* r = c->pop(8); if (BytesPerWord == 8) { - c->popped(1); + c->pop(8); } return r; } @@ -1364,16 +1364,28 @@ longToFloat(int64_t a) } object FORCE_ALIGN -makeBlankObjectArray(Thread* t, object class_, int32_t length) +makeBlankObjectArray(MyThread* t, object class_, int32_t length) { - return makeObjectArray(t, class_, length, true); + if (length >= 0) { + return makeObjectArray(t, class_, length, true); + } else { + object message = makeString(t, "%d", length); + t->exception = makeNegativeArraySizeException(t, message); + unwind(t); + } } object FORCE_ALIGN -makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool), +makeBlankArray(MyThread* t, object (*constructor)(Thread*, uintptr_t, bool), int32_t length) { - return constructor(t, length, true); + if (length >= 0) { + return constructor(t, length, true); + } else { + object message = makeString(t, "%d", length); + t->exception = makeNegativeArraySizeException(t, message); + unwind(t); + } } uintptr_t @@ -1478,14 +1490,6 @@ throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index) unwind(t); } -void NO_RETURN FORCE_ALIGN -throwNegativeArraySize(MyThread* t, int32_t length) -{ - object message = makeString(t, "%d", length); - t->exception = makeArrayIndexOutOfBoundsException(t, message); - unwind(t); -} - void NO_RETURN FORCE_ALIGN throw_(MyThread* t, object o) { @@ -2008,30 +2012,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Compiler::Operand* length = c->peek(4, 0); - - if (c->isConstant(length)) { - expect(t, c->constantValue(length) >= 0); - } else{ - Compiler::Operand* nonnegative = c->label(); - - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); - - length = c->peek(4, 0); - - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); - - c->mark(nonnegative); - } - - length = frame->popInt(); + Compiler::Operand* length = frame->popInt(); frame->pushObject (c->call @@ -3197,30 +3178,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case newarray: { uint8_t type = codeBody(t, code, ip++); - Compiler::Operand* length = c->peek(4, 0); - - if (c->isConstant(length)) { - expect(t, c->constantValue(length) >= 0); - } else{ - Compiler::Operand* nonnegative = c->label(); - - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); - - length = c->peek(4, 0); - - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); - - c->mark(nonnegative); - } - - length = frame->popInt(); + Compiler::Operand* length = frame->popInt(); object (*constructor)(Thread*, uintptr_t, bool); switch (type) { @@ -3870,11 +3828,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Enums") == 0 and + "java/lang/StringBuilder") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "main") == 0) + "") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index a12ebebab2..9370f9d565 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -17,8 +17,8 @@ namespace { const bool DebugAppend = true; const bool DebugCompile = true; -const bool DebugStack = false; -const bool DebugRegisters = false; +const bool DebugStack = true; +const bool DebugRegisters = true; class Context; class Value; @@ -61,7 +61,7 @@ class Stack { public: Stack(Value* value, unsigned size, unsigned index, Stack* next): value(value), size(size), index(index), next(next), pushEvent(0), - pushSite(0), syncSite(0), pushed(false) + pushSite(0), pushed(false) { } Value* value; @@ -70,7 +70,6 @@ class Stack { Stack* next; PushEvent* pushEvent; Site* pushSite; - Site* syncSite; bool pushed; }; @@ -141,8 +140,8 @@ class Read { class Value: public Compiler::Operand { public: - Value(Site* site): - reads(0), lastRead(0), sites(site), source(0), target(site) + Value(Site* site, Site* target): + reads(0), lastRead(0), sites(site), source(0), target(target) { } Read* reads; @@ -330,8 +329,6 @@ class Event { virtual ~Event() { } - virtual void prepare(Context*) { } - virtual void compile(Context* c) = 0; virtual bool isBranch() { return false; }; @@ -773,6 +770,14 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) return site; } +Site* +pushSite(Context* c, unsigned index) +{ + return memorySite + (c, c->assembler->base(), + - (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1); +} + void pushNow(Context* c, Stack* start, unsigned count) { @@ -787,11 +792,12 @@ pushNow(Context* c, Stack* start, unsigned count) assert(c, not s->pushed); if (s->value and s->value->sites) { - apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); - s->pushSite = memorySite - (c, c->assembler->base(), - - (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1); + Site* source = pick(c, s->value->sites); + + s->pushSite = pushSite(c, s->index); addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); + + apply(c, Push, s->size * BytesPerWord, source); } else { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); @@ -959,7 +965,7 @@ class PushEvent: public Event { virtual void compile(Context* c) { if (DebugCompile) { - fprintf(stderr, "PushEvent.compile\n"); + fprintf(stderr, "PushEvent.compile active: %d\n", active); } if (active) { @@ -1161,17 +1167,17 @@ class MoveEvent: public Event { } Site* target; + unsigned cost; if (type == Move and size >= BytesPerWord and dst->reads and next == dst->reads->event) { target = src->source; + cost = 0; } else { target = targetOrRegister(c, size, dst, this); - if (src->source->copyCost(c, target)) { - apply(c, type, size, src->source, target); - } + cost = src->source->copyCost(c, target); } nextRead(c, src); @@ -1181,6 +1187,10 @@ class MoveEvent: public Event { } else { removeSite(c, dst, target); } + + if (cost) { + apply(c, type, size, src->source, target); + } } BinaryOperation type; @@ -1390,16 +1400,6 @@ appendMemory(Context* c, Value* base, int displacement, Value* index, MemoryEvent(c, base, displacement, index, scale, result); } -Site* -stackSyncSite(Context* c, unsigned index, unsigned size) -{ - assert(c, index + size <= c->freeRegisterCount); - - return registerSite - (c, c->freeRegisters[index], - size == 2 ? c->freeRegisters[index + 1] : NoRegister); -} - Stack* stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) { @@ -1408,9 +1408,9 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) } Value* -value(Context* c, Site* site = 0) +value(Context* c, Site* site = 0, Site* target = 0) { - return new (c->zone->allocate(sizeof(Value))) Value(site); + return new (c->zone->allocate(sizeof(Value))) Value(site, target); } void @@ -1419,8 +1419,9 @@ resetStack(Context* c) unsigned i = 0; Stack* p = 0; for (Stack* s = c->state->stack; s; s = s->next) { - Stack* n = stack - (c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0); + Stack* n = stack(c, value(c), s->size, s->index, 0); + n->value->sites = n->pushSite = pushSite(c, s->index); + n->pushed = true; if (p) { p->next = n; @@ -1453,9 +1454,9 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) s, s->value, target); } - apply(c, Pop, BytesPerWord * s->size, target); - addSite(c, stack, s->size * BytesPerWord, s->value, target); + + apply(c, Pop, BytesPerWord * s->size, target); } else { if (DebugStack) { fprintf(stderr, "ignore %p value: %p\n", s, s->value); @@ -1485,31 +1486,21 @@ class StackSyncEvent: public Event { StackSyncEvent(Context* c): Event(c) { - unsigned i = 0; for (Stack* s = stack; s; s = s->next) { - s->syncSite = stackSyncSite(c, i, s->size); - addRead(c, s->value, s->size * BytesPerWord, s->syncSite); - i += s->size; - } + if (s->pushEvent) s->pushEvent->active = true; + addRead(c, s->value, s->size * BytesPerWord, 0); + } } StackSyncEvent(Context* c, unsigned sequence, Stack* stack): Event(c, sequence, stack) { - unsigned i = 0; for (Stack* s = stack; s; s = s->next) { - s->syncSite = stackSyncSite(c, i, s->size); - insertRead(c, this, sequence, s->value, s->size * BytesPerWord, - s->syncSite); - if (s->pushEvent) s->pushEvent->active = false; - i += s->size; + if (s->pushEvent) s->pushEvent->active = true; + insertRead(c, this, sequence, s->value, s->size * BytesPerWord, 0); } } - virtual void prepare(Context* c) { - popNow(c, this, stack, 0xFFFFFFFF, false); - } - virtual void compile(Context* c) { if (DebugCompile) { fprintf(stderr, "StackSyncEvent.compile\n"); @@ -1520,7 +1511,9 @@ class StackSyncEvent: public Event { } for (Stack* s = stack; s; s = s->next) { - addSite(c, 0, s->size * BytesPerWord, s->value, s->syncSite); + if (s->pushSite) { + addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); + } } for (Read* r = reads; r; r = r->eventNext) { @@ -1642,23 +1635,23 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } -void -swapRegisters(Context* c, int* ap, int* bp) -{ - Assembler::Register a(*ap); - Assembler::Register b(*bp); +// void +// swapRegisters(Context* c, int* ap, int* bp) +// { +// Assembler::Register a(*ap); +// Assembler::Register b(*bp); - c->assembler->apply - (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); - c->assembler->apply - (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); - c->assembler->apply - (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); +// c->assembler->apply +// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); +// c->assembler->apply +// (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); +// c->assembler->apply +// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); - int t = *ap; - *ap = *bp; - *bp = t; -} +// int t = *ap; +// *ap = *bp; +// *bp = t; +// } Site* readSource(Context* c, Stack* stack, Read* r, Event* e) @@ -1674,29 +1667,30 @@ readSource(Context* c, Stack* stack, Read* r, Event* e) apply(c, Move, r->size, site, target); return target; } else { - // this is a filthy hack, but I think the core idea is right: + abort(c); +// // this is a filthy hack, but I think the core idea is right: - assert(c, target->type(c) == RegisterOperand); +// assert(c, target->type(c) == RegisterOperand); - RegisterSite* ts = static_cast(target); +// RegisterSite* ts = static_cast(target); - for (Site* s = r->value->sites; s; s = s->next) { - if (s->type(c) == RegisterOperand) { - RegisterSite* rs = static_cast(s); +// for (Site* s = r->value->sites; s; s = s->next) { +// if (s->type(c) == RegisterOperand) { +// RegisterSite* rs = static_cast(s); - RegisterSite* os = static_cast - (c->registers[ts->register_.low].site); +// RegisterSite* os = static_cast +// (c->registers[ts->register_.low].site); - assert(c, os->register_.low == ts->register_.low); - assert(c, os->register_.high == NoRegister); - assert(c, ts->register_.high == NoRegister); - assert(c, rs->register_.high == NoRegister); +// assert(c, os->register_.low == ts->register_.low); +// assert(c, os->register_.high == NoRegister); +// assert(c, ts->register_.high == NoRegister); +// assert(c, rs->register_.high == NoRegister); - swapRegisters(c, &(os->register_.low), &(rs->register_.low)); +// swapRegisters(c, &(os->register_.low), &(rs->register_.low)); - return rs; - } - } +// return rs; +// } +// } } abort(c); @@ -1736,7 +1730,7 @@ compile(Context* c) for (Event* e = li->firstEvent; e; e = e->next) { if (e->stackReset) { -// fprintf(stderr, "stack reset\n"); + fprintf(stderr, "stack reset\n"); for (Stack* s = e->stack; s; s = s->next) { if (s->value->sites) { assert(c, s->value->sites->next == 0); @@ -1748,8 +1742,6 @@ compile(Context* c) } } - e->prepare(c); - for (Read* r = e->reads; r; r = r->eventNext) { r->value->source = readSource(c, e->stack, r, e); } @@ -1852,14 +1844,12 @@ used(Context* c, int r) return v and findSite(c, v, c->registers[r].site); } -// bool -// usedExclusively(Context* c, int r) -// { -// Value* v = c->registers[r].value; -// return used(c, r) -// and v->pushCount == 0 -// and v->sites->next == 0; -// } +bool +usedExclusively(Context* c, int r) +{ + Value* v = c->registers[r].value; + return used(c, r) and v->sites->next == 0; +} int freeRegisterExcept(Context* c, int except, bool allowAcquired) @@ -1873,14 +1863,14 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) } } -// for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { -// if (i != except -// and c->registers[i].refCount == 0 -// and (not usedExclusively(c, i))) -// { -// return i; -// } -// } + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (i != except + and c->registers[i].refCount == 0 + and (not usedExclusively(c, i))) + { + return i; + } + } if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { @@ -2048,15 +2038,18 @@ class MyCompiler: public Compiler { } virtual Operand* stack() { - return value(&c, registerSite(&c, c.assembler->stack())); + Site* s = registerSite(&c, c.assembler->stack()); + return value(&c, s, s); } virtual Operand* base() { - return value(&c, registerSite(&c, c.assembler->base())); + Site* s = registerSite(&c, c.assembler->base()); + return value(&c, s, s); } virtual Operand* thread() { - return value(&c, registerSite(&c, c.assembler->thread())); + Site* s = registerSite(&c, c.assembler->thread()); + return value(&c, s, s); } virtual bool isConstant(Operand* a) { @@ -2098,6 +2091,10 @@ class MyCompiler: public Compiler { abort(&c); } + virtual void push(unsigned size) { + ::push(&c, size, value(&c)); + } + virtual void push(unsigned size, Operand* value) { ::push(&c, size, static_cast(value)); } diff --git a/src/compiler.h b/src/compiler.h index 5019968e37..62f4387be5 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -57,6 +57,7 @@ class Compiler { virtual Operand* label() = 0; virtual void mark(Operand* label) = 0; + virtual void push(unsigned size) = 0; virtual void push(unsigned size, Operand* value) = 0; virtual Operand* pop(unsigned size) = 0; virtual void pushed(unsigned count) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index ad12475da5..25827bde41 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -35,6 +35,18 @@ enum { r15 = 15, }; +int64_t FORCE_ALIGN +divideLong(int64_t a, int64_t b) +{ + return a / b; +} + +int64_t FORCE_ALIGN +moduloLong(int64_t a, int64_t b) +{ + return a % b; +} + inline bool isInt8(intptr_t v) { @@ -523,6 +535,17 @@ popM(Context* c, unsigned size, Assembler::Memory* a) } } +void +negateR(Context* c, unsigned size, Assembler::Register* a) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0xf7); + c->code.append(0xd8 | a->low); +} + + void leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) { @@ -575,13 +598,19 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: + if (BytesPerWord == 8) { + c->code.append(0x0f); + } c->code.append(0xbe); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); break; case 2: + if (BytesPerWord == 8) { + c->code.append(0x0f); + } c->code.append(0xbf); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); break; case 8: @@ -863,6 +892,54 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, encode(c, 0x01, a->low, b, true); } +void +divideRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register axdx(c->client->acquireTemporary(rax), + c->client->acquireTemporary(rdx)); + + pushR(c, size, a); + pushR(c, size, b); + + ResolvedPromise addressPromise(reinterpret_cast(divideLong)); + Assembler::Constant address(&addressPromise); + callC(c, BytesPerWord, &address); + + ResolvedPromise offsetPromise(16); + Assembler::Constant offset(&offsetPromise); + Assembler::Register stack(rsp); + addCR(c, BytesPerWord, &offset, &stack); + + moveRR(c, size, &axdx, b); + + c->client->releaseTemporary(axdx.low); + c->client->releaseTemporary(axdx.high); + } else { + Assembler::Register ax(rax); + Assembler::Register dx(c->client->acquireTemporary(rdx)); + + if (b->low != rax) { + c->client->acquireTemporary(ax.low); + moveRR(c, BytesPerWord, b, &ax); + } + + rex(c); + c->code.append(0x99); + rex(c); + c->code.append(0xf7); + c->code.append(0xf8 | a->low); + + if (b->low != rax) { + moveRR(c, BytesPerWord, &ax, b); + c->client->releaseTemporary(ax.low); + } + + c->client->releaseTemporary(dx.low); + } +} + void andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -1065,6 +1142,8 @@ populateTables() UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); + UnaryOperations[INDEX1(Negate, Register)] = CAST1(negateR); + BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); @@ -1086,6 +1165,8 @@ populateTables() BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); From 5b7372a3bb43ec3819c37bd33f2c8d87aff3e68a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 27 Apr 2008 14:15:18 -0600 Subject: [PATCH 050/121] various bugfixes; majority of tests now pass --- src/assembler.h | 3 ++ src/compile.cpp | 4 +- src/compiler.cpp | 127 +++++++++++++++++++++++++++++------------------ src/x86.cpp | 97 +++++++++++++++++++++++++++++++++--- 4 files changed, 176 insertions(+), 55 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index e97ee597db..1a8a1f6fba 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -136,6 +136,9 @@ class Assembler { virtual int acquireTemporary(int r = NoRegister) = 0; virtual void releaseTemporary(int r) = 0; + + virtual void save(int r) = 0; + virtual void restore(int r) = 0; }; virtual ~Assembler() { } diff --git a/src/compile.cpp b/src/compile.cpp index 9bd513b945..0712548195 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3828,11 +3828,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/StringBuilder") == 0 and + "java/lang/Class") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "replace") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 9370f9d565..d24d98aca6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -15,10 +15,10 @@ using namespace vm; namespace { -const bool DebugAppend = true; -const bool DebugCompile = true; -const bool DebugStack = true; -const bool DebugRegisters = true; +const bool DebugAppend = false; +const bool DebugCompile = false; +const bool DebugStack = false; +const bool DebugRegisters = false; class Context; class Value; @@ -101,6 +101,7 @@ class Register { unsigned size; unsigned refCount; bool reserved; + bool pushed; }; class ConstantPoolNode { @@ -826,6 +827,42 @@ pushNow(Context* c, Stack* start) pushNow(c, start, count); } +bool +trySteal(Context* c, int r, Stack* stack) +{ + Value* v = c->registers[r].value; + + assert(c, c->registers[r].refCount == 0); + + if (DebugRegisters) { + fprintf(stderr, "try steal %d from %p: next: %p\n", + r, v, v->sites->next); + } + + if (v->sites->next == 0) { + unsigned count = 0; + Stack* start = 0; + for (Stack* s = stack; s and (not s->pushed); s = s->next) { + if (s->value == v) { + start = s; + } + if (start) { + ++ count; + } + } + + if (start) { + pushNow(c, start, count); + } else { + return false; + } + } + + removeSite(c, v, c->registers[r].site); + + return true; +} + bool tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) @@ -842,33 +879,9 @@ tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, and oldValue != newValue and findSite(c, oldValue, c->registers[r].site)) { - assert(c, c->registers[r].refCount == 0); - - if (DebugRegisters) { - fprintf(stderr, "try steal %d from %p: next: %p\n", - r, oldValue, oldValue->sites->next); + if (not trySteal(c, r, stack)) { + return false; } - - if (oldValue->sites->next == 0) { - unsigned count = 0; - Stack* start = 0; - for (Stack* s = stack; s and (not s->pushed); s = s->next) { - if (s->value == oldValue) { - start = s; - } - if (start) { - ++ count; - } - } - - if (start) { - pushNow(c, start, count); - } else { - return false; - } - } - - removeSite(c, oldValue, c->registers[r].site); } c->registers[r].size = newSize; @@ -1182,15 +1195,15 @@ class MoveEvent: public Event { nextRead(c, src); + if (cost) { + apply(c, type, size, src->source, target); + } + if (dst->reads) { addSite(c, stack, size, dst, target); } else { removeSite(c, dst, target); } - - if (cost) { - apply(c, type, size, src->source, target); - } } BinaryOperation type; @@ -1730,7 +1743,7 @@ compile(Context* c) for (Event* e = li->firstEvent; e; e = e->next) { if (e->stackReset) { - fprintf(stderr, "stack reset\n"); +// fprintf(stderr, "stack reset\n"); for (Stack* s = e->stack; s; s = s->next) { if (s->value->sites) { assert(c, s->value->sites->next == 0); @@ -1863,16 +1876,16 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) } } - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0 - and (not usedExclusively(c, i))) - { - return i; - } - } - if (allowAcquired) { + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (i != except + and c->registers[i].refCount == 0 + and (not usedExclusively(c, i))) + { + return i; + } + } + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except and c->registers[i].refCount == 0) @@ -1924,8 +1937,9 @@ class Client: public Assembler::Client { if (r == NoRegister) { r = freeRegisterExcept(c, NoRegister, false); } else { - expect(c, c->registers[r].refCount == 0); - expect(c, c->registers[r].value == 0); + expect(c, (c->registers[r].refCount == 0 + and c->registers[r].value == 0) + or c->registers[r].pushed); } increment(c, r); return r; @@ -1935,6 +1949,22 @@ class Client: public Assembler::Client { decrement(c, r); } + virtual void save(int r) { + if (c->registers[r].refCount or c->registers[r].value) { + Assembler::Register operand(r); + c->assembler->apply(Push, BytesPerWord, RegisterOperand, &operand); + c->registers[r].pushed = true; + } + } + + virtual void restore(int r) { + if (c->registers[r].pushed) { + Assembler::Register operand(r); + c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &operand); + c->registers[r].pushed = false; + } + } + Context* c; }; @@ -2092,7 +2122,10 @@ class MyCompiler: public Compiler { } virtual void push(unsigned size) { - ::push(&c, size, value(&c)); + assert(&c, ceiling(size, BytesPerWord)); + + c.state->stack = ::stack + (&c, value(&c), ceiling(size, BytesPerWord), c.state->stack); } virtual void push(unsigned size, Operand* value) { diff --git a/src/x86.cpp b/src/x86.cpp index 25827bde41..9e1f796a10 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -598,6 +598,7 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: + rex(c); if (BytesPerWord == 8) { c->code.append(0x0f); } @@ -606,6 +607,7 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, break; case 2: + rex(c); if (BytesPerWord == 8) { c->code.append(0x0f); } @@ -675,7 +677,7 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, if (BytesPerWord == 8) { rex(c); c->code.append(0x63); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); } else { if (a->low == rax and b->low == rax and b->high == rdx) { c->code.append(0x99); // cdq @@ -897,6 +899,8 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { + abort(c); // todo: sync stack first + Assembler::Register axdx(c->client->acquireTemporary(rax), c->client->acquireTemporary(rdx)); @@ -918,10 +922,18 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, c->client->releaseTemporary(axdx.high); } else { Assembler::Register ax(rax); - Assembler::Register dx(c->client->acquireTemporary(rdx)); + Assembler::Register divisor(a->low); + + if (a->low == rdx) { + divisor.low = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, a, &divisor); + } else if (b->low != rdx) { + c->client->save(rdx); + } if (b->low != rax) { - c->client->acquireTemporary(ax.low); + c->client->save(rax); + c->client->acquireTemporary(rax); moveRR(c, BytesPerWord, b, &ax); } @@ -929,14 +941,85 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, c->code.append(0x99); rex(c); c->code.append(0xf7); - c->code.append(0xf8 | a->low); + c->code.append(0xf8 | divisor.low); if (b->low != rax) { moveRR(c, BytesPerWord, &ax, b); - c->client->releaseTemporary(ax.low); + c->client->releaseTemporary(rax); + c->client->restore(rax); } - c->client->releaseTemporary(dx.low); + if (a->low == rdx) { + moveRR(c, BytesPerWord, &divisor, a); + c->client->releaseTemporary(divisor.low); + } else if (b->low != rdx) { + c->client->restore(rdx); + } + } +} + +void +remainderRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + abort(c); // todo: sync stack first + + Assembler::Register axdx(c->client->acquireTemporary(rax), + c->client->acquireTemporary(rdx)); + + pushR(c, size, a); + pushR(c, size, b); + + ResolvedPromise addressPromise(reinterpret_cast(moduloLong)); + Assembler::Constant address(&addressPromise); + callC(c, BytesPerWord, &address); + + ResolvedPromise offsetPromise(16); + Assembler::Constant offset(&offsetPromise); + Assembler::Register stack(rsp); + addCR(c, BytesPerWord, &offset, &stack); + + moveRR(c, size, &axdx, b); + + c->client->releaseTemporary(axdx.low); + c->client->releaseTemporary(axdx.high); + } else { + Assembler::Register ax(rax); + Assembler::Register dx(rdx); + Assembler::Register divisor(a->low); + + if (a->low == rdx) { + divisor.low = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, a, &divisor); + } else if (b->low != rdx) { + c->client->save(rdx); + } + + if (b->low != rax) { + c->client->save(rax); + c->client->acquireTemporary(rax); + moveRR(c, BytesPerWord, b, &ax); + } + + rex(c); + c->code.append(0x99); + rex(c); + c->code.append(0xf7); + c->code.append(0xf8 | divisor.low); + + if (b->low != rdx) { + moveRR(c, BytesPerWord, &dx, b); + c->client->releaseTemporary(rax); + c->client->restore(rax); + } + + if (a->low == rdx) { + moveRR(c, BytesPerWord, &divisor, a); + c->client->releaseTemporary(divisor.low); + } else if (b->low != rdx) { + c->client->restore(rdx); + } } } @@ -1167,6 +1250,8 @@ populateTables() BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR); + BinaryOperations[INDEX2(Remainder, Register, Register)] = CAST2(remainderRR); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); From cc64668657320f374b8589592b234a8750e55c4e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 27 Apr 2008 14:42:57 -0600 Subject: [PATCH 051/121] add support for more instructions to assembler --- src/x86.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 11 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 9e1f796a10..491adaee43 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -894,6 +894,46 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, encode(c, 0x01, a->low, b, true); } +void +multiplyRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x0f); + c->code.append(0xaf); + c->code.append(0xc0 | (b->low << 3) | a->low); +} + +void +multiplyCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + if (v) { + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x6b); + c->code.append(0xc0 | (b->low << 3) | b->low); + c->code.append(v); + } else { + c->code.append(0x69); + c->code.append(0xc0 | (b->low << 3) | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + multiplyRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } + } +} + void divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -958,6 +998,18 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, } } +void +divideCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + divideRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); +} + void remainderRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -1023,25 +1075,41 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, } } +void +andRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x21); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); + assert(c, BytesPerWord == 8 or size == 4); // todo int64_t v = a->value->value(); - rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xe0 | b->low); - c->code.append(v); - } else if (isInt32(v)) { - c->code.append(0x81); - c->code.append(0xe0 | b->low); - c->code.append(v); + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xe0 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xe0 | b->low); + c->code.append(v); + } } else { - abort(c); + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + andRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } } @@ -1074,6 +1142,34 @@ xorRR(Context* c, unsigned size UNUSED, Assembler::Register* a, c->code.append(0xc0 | (a->low << 3) | b->low); } +void +xorCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + if (v) { + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf0 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xf0 | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + xorRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } + } +} + void shiftLeftCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -1248,14 +1344,20 @@ populateTables() BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(Multiply, Register, Register)] = CAST2(multiplyRR); + BinaryOperations[INDEX2(Multiply, Constant, Register)] = CAST2(multiplyCR); + BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR); + BinaryOperations[INDEX2(Divide, Constant, Register)] = CAST2(divideCR); BinaryOperations[INDEX2(Remainder, Register, Register)] = CAST2(remainderRR); + BinaryOperations[INDEX2(And, Register, Register)] = CAST2(andRR); BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); BinaryOperations[INDEX2(Xor, Register, Register)] = CAST2(xorRR); + BinaryOperations[INDEX2(Xor, Constant, Register)] = CAST2(xorCR); BinaryOperations[INDEX2(ShiftLeft, Constant, Register)] = CAST2(shiftLeftCR); From 8be4cf8fa662956cc878a2429fe81658b7ac3fc7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 27 Apr 2008 15:58:29 -0600 Subject: [PATCH 052/121] fix pushState and popState to work as intended --- src/compiler.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index d24d98aca6..d411d3d1cb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -75,9 +75,9 @@ class Stack { class State { public: - State(State* s): - stack(s ? s->stack : 0), - next(s) + State(State* next, Stack* stack): + stack(stack), + next(next) { } Stack* stack; @@ -159,7 +159,7 @@ class Context { assembler(assembler), zone(zone), logicalIp(-1), - state(new (zone->allocate(sizeof(State))) State(0)), + state(new (zone->allocate(sizeof(State))) State(0, 0)), logicalCode(0), logicalCodeLength(0), stackOffset(0), @@ -1784,7 +1784,7 @@ void pushState(Context* c) { c->state = new (c->zone->allocate(sizeof(State))) - State(c->state); + State(c->state, c->state->stack); } void @@ -1802,8 +1802,8 @@ popState(Context* c) saveStack(c); c->state = new (c->zone->allocate(sizeof(State))) - State(c->state->next); - + State(c->state->next->next, c->state->next->stack); + resetStack(c); } From 505e0bd7db9d47038fc892bf1fea7c41a7923574 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 27 Apr 2008 16:25:17 -0600 Subject: [PATCH 053/121] treat 4-byte reg-to-reg moves as 8-byte moves on amd64 since the intention is to copy integer values verbatim; all tests now pass on amd64 --- src/x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index 491adaee43..d9772160c5 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -616,8 +616,8 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, break; case 8: - rex(c); case 4: + rex(c); c->code.append(0x89); c->code.append(0xc0 | (a->low << 3) | b->low); break; From 5e45475f3692733b2158b882def0e30f8a395e15 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 27 Apr 2008 16:43:15 -0600 Subject: [PATCH 054/121] fix unused parameter warnings --- src/x86.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index d9772160c5..3bfa697763 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -536,7 +536,7 @@ popM(Context* c, unsigned size, Assembler::Memory* a) } void -negateR(Context* c, unsigned size, Assembler::Register* a) +negateR(Context* c, unsigned size UNUSED, Assembler::Register* a) { assert(c, BytesPerWord == 8 or size == 4); // todo @@ -895,7 +895,7 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -multiplyRR(Context* c, unsigned size, Assembler::Register* a, +multiplyRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); // todo From 1b5f14d847c4d40fd6df3bac92a93de7e26aa0e1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Apr 2008 09:53:48 -0600 Subject: [PATCH 055/121] re-enable tests in Misc and get them working --- src/compile.cpp | 32 ++++++--- src/compiler.cpp | 38 ++++++++-- src/compiler.h | 2 + src/x86.cpp | 181 +++++++++++++++++++++++++++++++++++++++-------- test/Misc.java | 99 ++++++++++++++------------ 5 files changed, 261 insertions(+), 91 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index cebeb4f00f..bb8afc1d7d 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -552,10 +552,16 @@ class Frame { } ~Frame() { - if (level > 1 and t->exception == 0) { - c->popState(); + if (t->exception == 0) { + if (level > 0) { + c->saveStack(); + c->popState(); + c->resetStack(); + } - context->eventLog.append(PopEvent); + if (level > 1) { + context->eventLog.append(PopEvent); + } } } @@ -2913,17 +2919,25 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popLong(); c->cmp(8, a, b); + c->jl(less); + c->pushState(); + c->jg(greater); + c->pushState(); c->push(4, c->constant(0)); c->jmp(next); - + + c->popState(); c->mark(less); + c->push(4, c->constant(-1)); c->jmp(next); + c->popState(); c->mark(greater); + c->push(4, c->constant(1)); c->mark(next); @@ -3085,13 +3099,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } return; case lshl: { - Compiler::Operand* a = frame->popLong(); + Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popLong(); frame->pushLong(c->shl(8, a, b)); } break; case lshr: { - Compiler::Operand* a = frame->popLong(); + Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popLong(); frame->pushLong(c->shr(8, a, b)); } break; @@ -3128,7 +3142,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } break; case lushr: { - Compiler::Operand* a = frame->popLong(); + Compiler::Operand* a = frame->popInt(); Compiler::Operand* b = frame->popLong(); frame->pushLong(c->ushr(8, a, b)); } break; @@ -3861,11 +3875,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/Class") == 0 and + "java/nio/ByteBuffer") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "replace") == 0) + "checkPut") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index d411d3d1cb..d9afedf22b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -556,11 +556,11 @@ increment(Context* c, int r) void decrement(Context* c, int r) { - assert(c, c->registers[r].refCount > 0); - assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); if (DebugRegisters) { fprintf(stderr, "decrement %d to %d\n", r, c->registers[r].refCount - 1); } + assert(c, c->registers[r].refCount > 0); + assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); -- c->registers[r].refCount; } @@ -1783,6 +1783,13 @@ count(Stack* s) void pushState(Context* c) { + if (DebugAppend) { + unsigned count = 0; for (State* s = c->state; s; s = s->next) ++ count; + fprintf(stderr, "push at level %d\n", count); + count = 0; for (Stack* s = c->state->stack; s; s = s->next) ++ count; + fprintf(stderr, "stack count: %d\n", count); + } + c->state = new (c->zone->allocate(sizeof(State))) State(c->state, c->state->stack); } @@ -1793,18 +1800,27 @@ saveStack(Context* c) if (c->logicalIp >= 0 and not c->logicalCode[c->logicalIp].stackSaved) { c->logicalCode[c->logicalIp].stackSaved = true; c->logicalCode[c->logicalIp].stack = c->state->stack; + + if (DebugAppend) { + unsigned count = 0; + for (Stack* s = c->state->stack; s; s = s->next) ++ count; + fprintf(stderr, "stack count after ip %d: %d\n", c->logicalIp, count); + } } } void popState(Context* c) { - saveStack(c); - c->state = new (c->zone->allocate(sizeof(State))) State(c->state->next->next, c->state->next->stack); - resetStack(c); + if (DebugAppend) { + unsigned count = 0; for (State* s = c->state; s; s = s->next) ++ count; + fprintf(stderr, "pop to level %d\n", count); + count = 0; for (Stack* s = c->state->stack; s; s = s->next) ++ count; + fprintf(stderr, "stack count: %d\n", count); + } } Stack* @@ -1984,6 +2000,14 @@ class MyCompiler: public Compiler { ::popState(&c); } + virtual void saveStack() { + ::saveStack(&c); + } + + virtual void resetStack() { + ::resetStack(&c); + } + virtual void init(unsigned logicalCodeLength, unsigned stackOffset) { c.logicalCodeLength = logicalCodeLength; c.stackOffset = stackOffset; @@ -2010,7 +2034,7 @@ class MyCompiler: public Compiler { visit(&c, logicalIp); - saveStack(&c); + ::saveStack(&c); c.logicalIp = logicalIp; } @@ -2110,7 +2134,7 @@ class MyCompiler: public Compiler { virtual void mark(Operand* label) { appendStackSync(&c); - resetStack(&c); + ::resetStack(&c); for (Site* s = static_cast(label)->sites; s; s = s->next) { if (s->type(&c) == ConstantOperand) { diff --git a/src/compiler.h b/src/compiler.h index 62f4387be5..d17396a484 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -28,6 +28,8 @@ class Compiler { virtual void pushState() = 0; virtual void popState() = 0; + virtual void saveStack() = 0; + virtual void resetStack() = 0; virtual void init(unsigned logicalCodeSize, unsigned localFootprint) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index 3bfa697763..bcbbdea3dd 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -575,14 +575,45 @@ moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } void -moveCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, +moveCM(Context* c, unsigned size, Assembler::Constant* a, Assembler::Memory* b) { - assert(c, isInt32(a->value->value())); // todo - assert(c, BytesPerWord == 8 or size == 4); // todo + int64_t v = a->value->value(); - encode(c, 0xc7, 0, b, true); - c->code.append4(a->value->value()); + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + moveCM(c, 4, &al, b); + moveCM(c, 4, &ah, &bh); + } else if (BytesPerWord == 8 and size == 4) { + encode(c, 0xc7, 0, b, false); + c->code.append4(a->value->value()); + } else { + switch (size) { + case 1: + encode(c, 0xc6, 0, b, false); + c->code.append(a->value->value()); + break; + + case 2: + encode2(c, 0x66c7, 0, b, false); + c->code.append2(a->value->value()); + break; + + case BytesPerWord: + encode(c, 0xc7, 0, b, true); + c->code.append4(a->value->value()); + break; + + default: abort(c); + } + } } void @@ -1103,7 +1134,7 @@ andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } else { c->code.append(0x81); c->code.append(0xe0 | b->low); - c->code.append(v); + c->code.append4(v); } } else { Assembler::Register tmp(c->client->acquireTemporary()); @@ -1131,6 +1162,17 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +orRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0x09); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void xorRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) @@ -1171,46 +1213,89 @@ xorCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } void -shiftLeftCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, - Assembler::Register* b) -{ - assert(c, BytesPerWord == 8 or size == 4); +shift(Context* c, int type, Assembler::Register* a, Assembler::Register* b) { + if (a->low == rcx) { + rex(c); + c->code.append(0xd3); + c->code.append(type | b->low); + } else { + Assembler::Register cx(c->client->acquireTemporary(rcx)); + moveRR(c, BytesPerWord, a, &cx); + shift(c, type, &cx, b); + c->client->releaseTemporary(cx.low); + } +} +void +shift(Context* c, int type, Assembler::Constant* a, Assembler::Register* b) +{ int64_t v = a->value->value(); rex(c); if (v == 1) { c->code.append(0xd1); - c->code.append(0xe0 | b->low); + c->code.append(type | b->low); } else if (isInt8(v)) { c->code.append(0xc1); - c->code.append(0xe0 | b->low); + c->code.append(type | b->low); c->code.append(v); } else { abort(c); - } + } } void -compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, - Assembler::Register* b) +shiftLeftRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); - int64_t v = a->value->value(); + shift(c, 0xe0, a, b); +} - if (size == 8) rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xf8 | b->low); - c->code.append(v); - } else if (isInt32(v)) { - c->code.append(0x81); - c->code.append(0xf8 | b->low); - c->code.append4(v); - } else { - abort(c); - } +void +shiftLeftCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + shift(c, 0xe0, a, b); +} + +void +shiftRightRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + shift(c, 0xf8, a, b); +} + +void +shiftRightCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + shift(c, 0xf8, a, b); +} + +void +unsignedShiftRightRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + shift(c, 0xe8, a, b); +} + +void +unsignedShiftRightCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + shift(c, 0xe8, a, b); } void @@ -1237,6 +1322,33 @@ compareRR(Context* c, unsigned size UNUSED, Assembler::Register* a, } } +void +compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + + if (isInt32(v)) { + if (size == 8) rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf8 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xf8 | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + compareRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } +} + void compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Memory* b) @@ -1356,11 +1468,24 @@ populateTables() BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); + BinaryOperations[INDEX2(Or, Register, Register)] = CAST2(orRR); + BinaryOperations[INDEX2(Xor, Register, Register)] = CAST2(xorRR); BinaryOperations[INDEX2(Xor, Constant, Register)] = CAST2(xorCR); + BinaryOperations[INDEX2(ShiftLeft, Register, Register)] = CAST2(shiftLeftRR); BinaryOperations[INDEX2(ShiftLeft, Constant, Register)] = CAST2(shiftLeftCR); + BinaryOperations[INDEX2(ShiftRight, Register, Register)] + = CAST2(shiftRightRR); + BinaryOperations[INDEX2(ShiftRight, Constant, Register)] + = CAST2(shiftRightCR); + + BinaryOperations[INDEX2(UnsignedShiftRight, Register, Register)] + = CAST2(unsignedShiftRightRR); + BinaryOperations[INDEX2(UnsignedShiftRight, Constant, Register)] + = CAST2(unsignedShiftRightCR); + BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); diff --git a/test/Misc.java b/test/Misc.java index 81ac4b60ca..9c4aeded4a 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -10,13 +10,13 @@ public class Misc { private long time; public Misc() { -// expect(! boolean1); -// expect(! boolean2); + expect(! boolean1); + expect(! boolean2); -// time = 0xffffffffffffffffL; + time = 0xffffffffffffffffL; -// expect(! boolean1); -// expect(! boolean2); + expect(! boolean1); + expect(! boolean2); } private String foo(String s) { @@ -67,39 +67,44 @@ public class Misc { } public static void main(String[] args) { -// byte2 = 0; -// expect(byte2 == 0); + byte2 = 0; + expect(byte2 == 0); -// expect(Long.valueOf(231L) == 231L); + expect(Long.valueOf(231L) == 231L); -// long x = 231; -// expect((x >> 32) == 0); -// expect((x >>> 32) == 0); -// expect((x << 32) == 992137445376L); + long x = 231; + expect((x >> 32) == 0); + expect((x >>> 32) == 0); + expect((x << 32) == 992137445376L); -// long y = -231; -// expect((y >> 32) == 0xffffffffffffffffL); -// expect((y >>> 32) == 0xffffffffL); + int shift = 32; + expect((x >> shift) == 0); + expect((x >>> shift) == 0); + expect((x << shift) == 992137445376L); -// byte[] array = new byte[8]; -// putLong(231, array, 0); -// expect((array[0] & 0xff) == 0); -// expect((array[1] & 0xff) == 0); -// expect((array[2] & 0xff) == 0); -// expect((array[3] & 0xff) == 0); -// expect((array[4] & 0xff) == 0); -// expect((array[5] & 0xff) == 0); -// expect((array[6] & 0xff) == 0); -// expect((array[7] & 0xff) == 231); + long y = -231; + expect((y >> 32) == 0xffffffffffffffffL); + expect((y >>> 32) == 0xffffffffL); -// java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); -// buffer.putLong(231); -// buffer.flip(); -// expect(buffer.getLong() == 231); + byte[] array = new byte[8]; + putLong(231, array, 0); + expect((array[0] & 0xff) == 0); + expect((array[1] & 0xff) == 0); + expect((array[2] & 0xff) == 0); + expect((array[3] & 0xff) == 0); + expect((array[4] & 0xff) == 0); + expect((array[5] & 0xff) == 0); + expect((array[6] & 0xff) == 0); + expect((array[7] & 0xff) == 231); -// boolean v = Boolean.valueOf("true"); + java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); + buffer.putLong(231); + buffer.flip(); + expect(buffer.getLong() == 231); -// ClassLoader.getSystemClassLoader().toString(); + boolean v = Boolean.valueOf("true"); + + ClassLoader.getSystemClassLoader().toString(); int a = 2; int b = 2; @@ -113,23 +118,23 @@ public class Misc { m.bar(s); baz(s); -// m.sync(); -// syncStatic(false); -// try { -// syncStatic(true); -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } + m.sync(); + syncStatic(false); + try { + syncStatic(true); + } catch (RuntimeException e) { + e.printStackTrace(); + } -// int d = alpha; -// beta = 42; -// alpha = 43; -// int e = beta; -// int f = alpha; -// m.gamma = 44; + int d = alpha; + beta = 42; + alpha = 43; + int e = beta; + int f = alpha; + m.gamma = 44; -// expect(beta == 42); -// expect(alpha == 43); -// expect(m.gamma == 44); + expect(beta == 42); + expect(alpha == 43); + expect(m.gamma == 44); } } From 90ae9a70ee41cc7a74e86989e40afa701206674c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Apr 2008 10:52:54 -0600 Subject: [PATCH 056/121] fix encoding reg-to-reg moves of one and two byte sizes --- src/x86.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index bcbbdea3dd..4bd840b1c3 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -630,18 +630,14 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, switch (size) { case 1: rex(c); - if (BytesPerWord == 8) { - c->code.append(0x0f); - } + c->code.append(0x0f); c->code.append(0xbe); c->code.append(0xc0 | (b->low << 3) | a->low); break; case 2: rex(c); - if (BytesPerWord == 8) { - c->code.append(0x0f); - } + c->code.append(0x0f); c->code.append(0xbf); c->code.append(0xc0 | (b->low << 3) | a->low); break; From 8738bddcb99d79776950e91921886bbf679733a7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Apr 2008 16:08:31 -0600 Subject: [PATCH 057/121] bugfixes, mainly concerning 32-bit machines --- src/assembler.h | 7 +- src/compile.cpp | 4 +- src/compiler.cpp | 48 +++--- src/x86.cpp | 409 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 348 insertions(+), 120 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 1a8a1f6fba..c72fe53a99 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -134,7 +134,7 @@ class Assembler { public: virtual ~Client() { } - virtual int acquireTemporary(int r = NoRegister) = 0; + virtual int acquireTemporary() = 0; virtual void releaseTemporary(int r) = 0; virtual void save(int r) = 0; @@ -156,11 +156,8 @@ class Assembler { virtual unsigned argumentRegisterCount() = 0; virtual int argumentRegister(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; + Register* a, Register* b, bool* syncStack) = 0; virtual void apply(Operation op) = 0; diff --git a/src/compile.cpp b/src/compile.cpp index bb8afc1d7d..9845ec598a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3875,11 +3875,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/nio/ByteBuffer") == 0 and + "java/lang/Class") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "checkPut") == 0) + "replace") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index d9afedf22b..06ec5fb361 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1195,13 +1195,15 @@ class MoveEvent: public Event { nextRead(c, src); + if (dst->reads) { + addSite(c, stack, size, dst, target); + } + if (cost) { apply(c, type, size, src->source, target); } - if (dst->reads) { - addSite(c, stack, size, dst, target); - } else { + if (dst->reads == 0) { removeSite(c, dst, target); } } @@ -1263,22 +1265,20 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second) class CombineEvent: public Event { public: CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, - Value* second, Value* result): + Value* second, Value* result, Assembler::Register* r1, + Assembler::Register* r2): Event(c), type(type), size(size), first(first), second(second), result(result) { - Assembler::Register r1(NoRegister); - Assembler::Register r2(NoRegister); - c->assembler->getTargets(type, size, &r1, &r2); - addRead(c, first, size, - r1.low == NoRegister ? + r1->low == NoRegister ? constantOrRegisterSite(c) : - static_cast(registerSite(c, r1.low, r1.high))); + static_cast(registerSite(c, r1->low, r1->high))); + addRead(c, second, size, - r2.low == NoRegister ? + r2->low == NoRegister ? valueSite(c, result) : - static_cast(registerSite(c, r2.low, r2.high))); + static_cast(registerSite(c, r2->low, r2->high))); } virtual void compile(Context* c) { @@ -1304,16 +1304,28 @@ class CombineEvent: public Event { Value* result; }; +void +appendStackSync(Context* c); + void appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Value* second, Value* result) { + Assembler::Register r1(NoRegister); + Assembler::Register r2(NoRegister); + bool syncStack; + c->assembler->getTargets(type, size, &r1, &r2, &syncStack); + + if (syncStack) { + appendStackSync(c); + } + if (DebugAppend) { fprintf(stderr, "appendCombine\n"); } new (c->zone->allocate(sizeof(CombineEvent))) - CombineEvent(c, type, size, first, second, result); + CombineEvent(c, type, size, first, second, result, &r1, &r2); } class TranslateEvent: public Event { @@ -1949,14 +1961,8 @@ class Client: public Assembler::Client { public: Client(Context* c): c(c) { } - virtual int acquireTemporary(int r) { - if (r == NoRegister) { - r = freeRegisterExcept(c, NoRegister, false); - } else { - expect(c, (c->registers[r].refCount == 0 - and c->registers[r].value == 0) - or c->registers[r].pushed); - } + virtual int acquireTemporary() { + int r = freeRegisterExcept(c, NoRegister, false); increment(c, r); return r; } diff --git a/src/x86.cpp b/src/x86.cpp index 4bd840b1c3..0779870503 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -95,6 +95,13 @@ expect(Context* c, bool v) expect(c->s, v); } +ResolvedPromise* +resolved(Context* c, int64_t value) +{ + return new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value); +} + class CodePromise: public Promise { public: CodePromise(Context* c, unsigned offset): c(c), offset(offset) { } @@ -434,12 +441,12 @@ pushC(Context* c, unsigned size, Assembler::Constant* a) int64_t v = a->value->value(); if (BytesPerWord == 4 and size == 8) { - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); - ResolvedPromise low(v & 0xFFFFFFFF); Assembler::Constant al(&low); + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + pushC(c, 4, &ah); pushC(c, 4, &al); } else { @@ -536,13 +543,65 @@ popM(Context* c, unsigned size, Assembler::Memory* a) } void -negateR(Context* c, unsigned size UNUSED, Assembler::Register* a) +addCarryCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + assert(c, BytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xd0 | b->low); + c->code.append(v); + } else { + abort(c); + } +} - rex(c); - c->code.append(0xf7); - c->code.append(0xd8 | a->low); +void +moveRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b); + +void +negateR(Context* c, unsigned size, Assembler::Register* a) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ax(rax); + Assembler::Register dx(rdx); + + Assembler::Register ah(a->high); + + ResolvedPromise zeroPromise(0); + Assembler::Constant zero(&zeroPromise); + + if (a->low != rax) { + c->client->save(rax); + moveRR(c, BytesPerWord, a, &ax); + } + + if (a->high != rdx) { + c->client->save(rdx); + moveRR(c, BytesPerWord, &ah, &dx); + } + + negateR(c, 4, &ax); + addCarryCR(c, 4, &zero, &dx); + negateR(c, 4, &dx); + + if (a->high != rdx) { + moveRR(c, BytesPerWord, &dx, a); + c->client->restore(rdx); + } + + if (a->low != rax) { + moveRR(c, BytesPerWord, &ax, a); + c->client->restore(rax); + } + } else { + rex(c); + c->code.append(0xf7); + c->code.append(0xd8 | a->low); + } } @@ -559,18 +618,31 @@ leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) } void -moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +moveCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + int64_t v = a->value->value(); - rex(c, 0x48, b->low); - c->code.append(0xb8 | b->low); - if (a->value->resolved()) { - c->code.appendAddress(a->value->value()); + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + moveCR(c, 4, &al, b); + moveCR(c, 4, &ah, &bh); } else { - appendImmediateTask(c, a->value, c->code.length()); - c->code.appendAddress(static_cast(0)); + rex(c, 0x48, b->low); + c->code.append(0xb8 | b->low); + if (a->value->resolved()) { + c->code.appendAddress(a->value->value()); + } else { + appendImmediateTask(c, a->value, c->code.length()); + c->code.appendAddress(static_cast(0)); + } } } @@ -629,10 +701,25 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: - rex(c); - c->code.append(0x0f); - c->code.append(0xbe); - c->code.append(0xc0 | (b->low << 3) | a->low); + if (BytesPerWord == 4 and a->low > rbx) { + if (b->low > rbx) { + c->client->save(rax); + + Assembler::Register ax(rax); + moveRR(c, BytesPerWord, a, &ax); + moveRR(c, 1, &ax, b); + + c->client->restore(rax); + } else { + moveRR(c, BytesPerWord, a, b); + moveRR(c, 1, b, b); + } + } else { + rex(c); + c->code.append(0x0f); + c->code.append(0xbe); + c->code.append(0xc0 | (b->low << 3) | a->low); + } break; case 2: @@ -674,10 +761,13 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) } } else { if (a->low > rbx) { - Assembler::Register ax(c->client->acquireTemporary(rax)); + c->client->save(rax); + + Assembler::Register ax(rax); moveRR(c, BytesPerWord, a, &ax); moveRM(c, 1, &ax, b); - c->client->releaseTemporary(ax.low); + + c->client->restore(rax); } else { encode(c, 0x88, a->low, b, false); } @@ -709,15 +799,32 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, if (a->low == rax and b->low == rax and b->high == rdx) { c->code.append(0x99); // cdq } else { - Assembler::Register axdx(c->client->acquireTemporary(rax), - c->client->acquireTemporary(rdx)); + Assembler::Register axdx(rax, rdx); + Assembler::Register dx(rdx); + Assembler::Register bh(b->high); + + bool saveAX = a->low != rax and b->low != rax and b->high != rax; + bool saveDX = b->low != rdx and b->high != rdx; + + if (saveDX) c->client->save(rdx); + if (saveAX) c->client->save(rax); + + if (a->low != rax) { + moveRR(c, 4, a, &axdx); + } - moveRR(c, 4, a, &axdx); move4To8RR(c, 0, &axdx, &axdx); - moveRR(c, 8, &axdx, b); - c->client->releaseTemporary(axdx.low); - c->client->releaseTemporary(axdx.high); + if (b->low != rax) { + moveRR(c, 4, &axdx, b); + } + + if (b->high != rdx) { + moveRR(c, 4, &dx, &bh); + } + + if (saveAX) c->client->restore(rax); + if (saveDX) c->client->restore(rdx); } } } @@ -803,15 +910,29 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) if (BytesPerWord == 8) { encode(c, 0x63, b->low, a, true); } else { - Assembler::Register axdx(c->client->acquireTemporary(rax), - c->client->acquireTemporary(rdx)); + Assembler::Register axdx(rax, rdx); + Assembler::Register dx(rdx); + Assembler::Register bh(b->high); + + bool saveAX = b->low != rax and b->high != rax; + bool saveDX = b->low != rdx and b->high != rdx; + + if (saveDX) c->client->save(rdx); + if (saveAX) c->client->save(rax); moveMR(c, 4, a, &axdx); move4To8RR(c, 0, &axdx, &axdx); - moveRR(c, 8, &axdx, b); - c->client->releaseTemporary(axdx.low); - c->client->releaseTemporary(axdx.high); + if (b->low != rax) { + moveRR(c, 4, &axdx, b); + } + + if (b->high != rdx) { + moveRR(c, 4, &dx, &bh); + } + + if (saveAX) c->client->restore(rax); + if (saveDX) c->client->restore(rdx); } } @@ -867,25 +988,52 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +subtractBorrowCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xd8 | b->low); + c->code.append(v); + } else { + abort(c); + } +} + void subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo - int64_t v = a->value->value(); if (v) { - rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xe8 | b->low); - c->code.append(v); - } else if (isInt32(v)) { - c->code.append(0x81); - c->code.append(0xe8 | b->low); - c->code.append4(v); + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + subtractCR(c, 4, &al, b); + subtractBorrowCR(c, 4, &ah, &bh); } else { - abort(c); + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xe8 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xe8 | b->low); + c->code.append4(v); + } else { + abort(c); + } } } } @@ -902,14 +1050,31 @@ subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +addCarryRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + rex(c); + c->code.append(0x11); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + +void +addRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); - rex(c); - c->code.append(0x01); - c->code.append(0xc0 | (a->low << 3) | b->low); + addRR(c, 4, a, b); + addCarryRR(c, 4, &ah, &bh); + } else { + rex(c); + c->code.append(0x01); + c->code.append(0xc0 | (a->low << 3) | b->low); + } } void @@ -966,16 +1131,21 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - abort(c); // todo: sync stack first + Assembler::Register axdx(rax, rdx); + Assembler::Register dx(rdx); + Assembler::Register bh(b->high); - Assembler::Register axdx(c->client->acquireTemporary(rax), - c->client->acquireTemporary(rdx)); + bool saveAX = b->low != rax and b->high != rax; + bool saveDX = b->low != rdx and b->high != rdx; + + if (saveDX) c->client->save(rdx); + if (saveAX) c->client->save(rax); pushR(c, size, a); pushR(c, size, b); - ResolvedPromise addressPromise(reinterpret_cast(divideLong)); - Assembler::Constant address(&addressPromise); + Assembler::Constant address + (resolved(c, reinterpret_cast(divideLong))); callC(c, BytesPerWord, &address); ResolvedPromise offsetPromise(16); @@ -983,24 +1153,29 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register stack(rsp); addCR(c, BytesPerWord, &offset, &stack); - moveRR(c, size, &axdx, b); + if (b->low != rax) { + moveRR(c, 4, &axdx, b); + } - c->client->releaseTemporary(axdx.low); - c->client->releaseTemporary(axdx.high); + if (b->high != rdx) { + moveRR(c, 4, &dx, &bh); + } + + if (saveAX) c->client->restore(rax); + if (saveDX) c->client->restore(rdx); } else { Assembler::Register ax(rax); Assembler::Register divisor(a->low); if (a->low == rdx) { divisor.low = c->client->acquireTemporary(); - moveRR(c, BytesPerWord, a, &divisor); + moveRR(c, BytesPerWord, a, &divisor); } else if (b->low != rdx) { c->client->save(rdx); } if (b->low != rax) { c->client->save(rax); - c->client->acquireTemporary(rax); moveRR(c, BytesPerWord, b, &ax); } @@ -1012,7 +1187,6 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, if (b->low != rax) { moveRR(c, BytesPerWord, &ax, b); - c->client->releaseTemporary(rax); c->client->restore(rax); } @@ -1042,16 +1216,21 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - abort(c); // todo: sync stack first + Assembler::Register axdx(rax, rdx); + Assembler::Register dx(rdx); + Assembler::Register bh(b->high); - Assembler::Register axdx(c->client->acquireTemporary(rax), - c->client->acquireTemporary(rdx)); + bool saveAX = b->low != rax and b->high != rax; + bool saveDX = b->low != rdx and b->high != rdx; + + if (saveDX) c->client->save(rdx); + if (saveAX) c->client->save(rax); pushR(c, size, a); pushR(c, size, b); - ResolvedPromise addressPromise(reinterpret_cast(moduloLong)); - Assembler::Constant address(&addressPromise); + Assembler::Constant address + (resolved(c, reinterpret_cast(moduloLong))); callC(c, BytesPerWord, &address); ResolvedPromise offsetPromise(16); @@ -1059,10 +1238,16 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register stack(rsp); addCR(c, BytesPerWord, &offset, &stack); - moveRR(c, size, &axdx, b); + if (b->low != rax) { + moveRR(c, 4, &axdx, b); + } - c->client->releaseTemporary(axdx.low); - c->client->releaseTemporary(axdx.high); + if (b->high != rdx) { + moveRR(c, 4, &dx, &bh); + } + + if (saveAX) c->client->restore(rax); + if (saveDX) c->client->restore(rdx); } else { Assembler::Register ax(rax); Assembler::Register dx(rdx); @@ -1077,7 +1262,6 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, if (b->low != rax) { c->client->save(rax); - c->client->acquireTemporary(rax); moveRR(c, BytesPerWord, b, &ax); } @@ -1089,7 +1273,9 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, if (b->low != rdx) { moveRR(c, BytesPerWord, &dx, b); - c->client->releaseTemporary(rax); + } + + if (b->low != rax) { c->client->restore(rax); } @@ -1215,10 +1401,25 @@ shift(Context* c, int type, Assembler::Register* a, Assembler::Register* b) { c->code.append(0xd3); c->code.append(type | b->low); } else { - Assembler::Register cx(c->client->acquireTemporary(rcx)); + Assembler::Register target(b->low); + + if (b->low == rcx) { + target.low = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, b, &target); + } else { + c->client->save(rcx); + } + + Assembler::Register cx(rcx); moveRR(c, BytesPerWord, a, &cx); shift(c, type, &cx, b); - c->client->releaseTemporary(cx.low); + + if (b->low == rcx) { + moveRR(c, BytesPerWord, &target, b); + c->client->releaseTemporary(target.low); + } else { + c->client->restore(rcx); + } } } @@ -1346,19 +1547,39 @@ compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } void -compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, +compareCM(Context* c, unsigned size, Assembler::Constant* a, Assembler::Memory* b) { - assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); - encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true); + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); - if (isInt8(a->value->value())) { - c->code.append(a->value->value()); - } else if (isInt32(a->value->value())) { - c->code.append4(a->value->value()); + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + compareCM(c, 4, &ah, &bh); + + // 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); + + compareCM(c, 4, &al, b); } else { - abort(c); + encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); + + if (isInt8(v)) { + c->code.append(v); + } else if (isInt32(v)) { + c->code.append4(v); + } else { + abort(c); + } } } @@ -1557,22 +1778,26 @@ class MyAssembler: public Assembler { } } - virtual void getTargets(UnaryOperation /*op*/, unsigned /*size*/, - Register* r) + virtual void getTargets(BinaryOperation op, unsigned size, + Register* a, Register* b, bool* syncStack) { - // todo - r->low = NoRegister; - r->high = NoRegister; - } - - virtual void getTargets(BinaryOperation /*op*/, unsigned /*size*/, - Register* a, Register* b) - { - // todo a->low = NoRegister; a->high = NoRegister; b->low = NoRegister; b->high = NoRegister; + *syncStack = false; + + switch (op) { + case Divide: + case Remainder: + if (BytesPerWord == 4 and size == 8) { + *syncStack = true; + } + break; + + default: + break; + } } virtual void apply(Operation op) { From a07a189ddbe0c565322ddb48687e30668416ba2e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Apr 2008 18:58:02 -0600 Subject: [PATCH 058/121] fix various register marshalling bugs --- src/x86.cpp | 192 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 116 insertions(+), 76 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 0779870503..049008fb52 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -562,6 +562,88 @@ void moveRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b); +void +xorRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b); + +void +swap(Context* c, Assembler::Register* a, Assembler::Register* b) +{ + xorRR(c, 4, a, b); + xorRR(c, 4, b, b); + xorRR(c, 4, a, b); +} + +void +marshal(Context* c, int sl, int sh, int dl, int dh) +{ + Assembler::Register slr(sl); + Assembler::Register shr(sh); + Assembler::Register dlr(dl); + Assembler::Register dhr(dh); + + if (sl == dl or sh == dh) { + if (sl != dl) { + c->client->save(dl); + moveRR(c, BytesPerWord, &slr, &dlr); + } else if (sh != dh) { + c->client->save(dh); + moveRR(c, BytesPerWord, &shr, &dhr); + } + } else if (sl == dh or sh == dl) { + swap(c, &slr, &shr); + + if (sl != dh) { + c->client->save(dh); + moveRR(c, BytesPerWord, &slr, &dhr); + } else if (sh != dl) { + c->client->save(dl); + moveRR(c, BytesPerWord, &shr, &dlr); + } + } else { + c->client->save(dl); + moveRR(c, BytesPerWord, &slr, &dlr); + + c->client->save(dh); + moveRR(c, BytesPerWord, &shr, &dhr); + } +} + +void +unmarshal(Context* c, int sl, int sh, int dl, int dh) +{ + Assembler::Register slr(sl); + Assembler::Register shr(sh); + Assembler::Register dlr(dl); + Assembler::Register dhr(dh); + + if (sl == dl or sh == dh) { + if (sl != dl) { + moveRR(c, BytesPerWord, &slr, &dlr); + c->client->restore(sl); + } else if (sh != dh) { + moveRR(c, BytesPerWord, &shr, &dhr); + c->client->restore(sh); + } + } else if (sl == dh or sh == dl) { + if (sl != dh) { + moveRR(c, BytesPerWord, &slr, &dhr); + c->client->restore(sh); + } else if (sh != dl) { + moveRR(c, BytesPerWord, &shr, &dlr); + c->client->restore(sl); + } + + swap(c, &dlr, &dhr); + } else { + moveRR(c, BytesPerWord, &slr, &dlr); + c->client->restore(sl); + + moveRR(c, BytesPerWord, &shr, &dhr); + c->client->restore(sh); + } +} + void negateR(Context* c, unsigned size, Assembler::Register* a) { @@ -569,34 +651,16 @@ negateR(Context* c, unsigned size, Assembler::Register* a) Assembler::Register ax(rax); Assembler::Register dx(rdx); - Assembler::Register ah(a->high); - ResolvedPromise zeroPromise(0); Assembler::Constant zero(&zeroPromise); - if (a->low != rax) { - c->client->save(rax); - moveRR(c, BytesPerWord, a, &ax); - } - - if (a->high != rdx) { - c->client->save(rdx); - moveRR(c, BytesPerWord, &ah, &dx); - } + marshal(c, a->low, a->high, rax, rdx); negateR(c, 4, &ax); addCarryCR(c, 4, &zero, &dx); negateR(c, 4, &dx); - - if (a->high != rdx) { - moveRR(c, BytesPerWord, &dx, a); - c->client->restore(rdx); - } - if (a->low != rax) { - moveRR(c, BytesPerWord, &ax, a); - c->client->restore(rax); - } + unmarshal(c, rax, rdx, a->low, a->high); } else { rex(c); c->code.append(0xf7); @@ -787,6 +851,30 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) } } +void +move(Context* c, int sl, int sh, int dl, int dh) +{ + Assembler::Register slr(sl); + Assembler::Register shr(sh); + Assembler::Register dlr(dl); + Assembler::Register dhr(dh); + + if (sl == dh and sh == dl) { + swap(c, &slr, &shr); + } else { + if (sl != dl) { + if (sh == dl) { + moveRR(c, 4, &shr, &dhr); + } + moveRR(c, 4, &slr, &dlr); + } + + if (sh != dh and sh != dl) { + moveRR(c, 4, &shr, &dhr); + } + } +} + void move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) @@ -815,13 +903,7 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, move4To8RR(c, 0, &axdx, &axdx); - if (b->low != rax) { - moveRR(c, 4, &axdx, b); - } - - if (b->high != rdx) { - moveRR(c, 4, &dx, &bh); - } + move(c, rax, rdx, b->low, b->high); if (saveAX) c->client->restore(rax); if (saveDX) c->client->restore(rdx); @@ -923,13 +1005,7 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) moveMR(c, 4, a, &axdx); move4To8RR(c, 0, &axdx, &axdx); - if (b->low != rax) { - moveRR(c, 4, &axdx, b); - } - - if (b->high != rdx) { - moveRR(c, 4, &dx, &bh); - } + move(c, rax, rdx, b->low, b->high); if (saveAX) c->client->restore(rax); if (saveDX) c->client->restore(rdx); @@ -1131,16 +1207,6 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - Assembler::Register axdx(rax, rdx); - Assembler::Register dx(rdx); - Assembler::Register bh(b->high); - - bool saveAX = b->low != rax and b->high != rax; - bool saveDX = b->low != rdx and b->high != rdx; - - if (saveDX) c->client->save(rdx); - if (saveAX) c->client->save(rax); - pushR(c, size, a); pushR(c, size, b); @@ -1148,21 +1214,13 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, (resolved(c, reinterpret_cast(divideLong))); callC(c, BytesPerWord, &address); + Assembler::Register axdx(rax, rdx); + moveRR(c, 4, &axdx, b); + ResolvedPromise offsetPromise(16); Assembler::Constant offset(&offsetPromise); Assembler::Register stack(rsp); addCR(c, BytesPerWord, &offset, &stack); - - if (b->low != rax) { - moveRR(c, 4, &axdx, b); - } - - if (b->high != rdx) { - moveRR(c, 4, &dx, &bh); - } - - if (saveAX) c->client->restore(rax); - if (saveDX) c->client->restore(rdx); } else { Assembler::Register ax(rax); Assembler::Register divisor(a->low); @@ -1216,16 +1274,6 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - Assembler::Register axdx(rax, rdx); - Assembler::Register dx(rdx); - Assembler::Register bh(b->high); - - bool saveAX = b->low != rax and b->high != rax; - bool saveDX = b->low != rdx and b->high != rdx; - - if (saveDX) c->client->save(rdx); - if (saveAX) c->client->save(rax); - pushR(c, size, a); pushR(c, size, b); @@ -1233,21 +1281,13 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, (resolved(c, reinterpret_cast(moduloLong))); callC(c, BytesPerWord, &address); + Assembler::Register axdx(rax, rdx); + moveRR(c, 4, &axdx, b); + ResolvedPromise offsetPromise(16); Assembler::Constant offset(&offsetPromise); Assembler::Register stack(rsp); addCR(c, BytesPerWord, &offset, &stack); - - if (b->low != rax) { - moveRR(c, 4, &axdx, b); - } - - if (b->high != rdx) { - moveRR(c, 4, &dx, &bh); - } - - if (saveAX) c->client->restore(rax); - if (saveDX) c->client->restore(rdx); } else { Assembler::Register ax(rax); Assembler::Register dx(rdx); From 7791b1df804b5c9ec06bdf54bf419d4bd36e7a3a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 08:57:24 -0600 Subject: [PATCH 059/121] support 64-bit operands on 32-bit systems in compareCR --- src/x86.cpp | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 049008fb52..d1181e949c 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1563,26 +1563,44 @@ void compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); - int64_t v = a->value->value(); - if (isInt32(v)) { - if (size == 8) rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xf8 | b->low); - c->code.append(v); - } else { - c->code.append(0x81); - c->code.append(0xf8 | b->low); - c->code.append4(v); - } + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + Assembler::Register bh(b->high); + + compareCR(c, 4, &ah, &bh); + + // 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); + + compareCR(c, 4, &al, b); } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - compareRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + if (isInt32(v)) { + if (size == 8) rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf8 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xf8 | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + compareRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } } } From c96f44d77d9b18264a21b4e92cc421e698e3202e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 08:59:12 -0600 Subject: [PATCH 060/121] don't skip move when MoveEvent is followed by a PushEvent which is not active; use existing register site in ValueSite when possible --- src/compile.cpp | 4 ++-- src/compiler.cpp | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 9845ec598a..22fc715c49 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3875,11 +3875,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/Class") == 0 and + "java/lang/Number") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "replace") == 0) + "") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 06ec5fb361..86d36f8cfd 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -332,7 +332,7 @@ class Event { virtual void compile(Context* c) = 0; - virtual bool isBranch() { return false; }; + virtual bool skipMove(unsigned) { return false; } Event* next; Stack* stack; @@ -682,6 +682,11 @@ class ValueSite: public AbstractSite { if (s and s->type(c) == RegisterOperand) { return s; } else { + for (Site* s = r->value->sites; s; s = s->next) { + if (s->type(c) == RegisterOperand) { + return s; + } + } return freeRegister(c, r->size, true); } } @@ -988,6 +993,10 @@ class PushEvent: public Event { nextRead(c, s->value); } + virtual bool skipMove(unsigned size) { + return active and size >= 4; + } + Stack* s; bool active; }; @@ -1182,9 +1191,9 @@ class MoveEvent: public Event { Site* target; unsigned cost; if (type == Move - and size >= BytesPerWord and dst->reads - and next == dst->reads->event) + and next == dst->reads->event + and dst->reads->event->skipMove(size)) { target = src->source; cost = 0; @@ -1575,8 +1584,6 @@ class BranchEvent: public Event { nextRead(c, address); } - virtual bool isBranch() { return true; }; - UnaryOperation type; Value* address; }; From 22382a5c8b6d0ebef9f951ad38f64bd2e385374c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 09:30:41 -0600 Subject: [PATCH 061/121] fix amd64 regression in PushEvent::skipMove --- src/compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 86d36f8cfd..3c71af9c68 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -994,7 +994,7 @@ class PushEvent: public Event { } virtual bool skipMove(unsigned size) { - return active and size >= 4; + return active and size >= BytesPerWord; } Stack* s; From d50e3aaee03b7521a0103129f14570c15b33311b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 10:25:20 -0600 Subject: [PATCH 062/121] preserve operands to CombineEvent and TranslateEvent when necessary --- src/compile.cpp | 4 ++-- src/compiler.cpp | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 22fc715c49..c95b4021ae 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3875,11 +3875,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/Number") == 0 and + "java/nio/ByteBuffer") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "get") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 3c71af9c68..a06e8c93aa 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -355,7 +355,7 @@ bool tryAddSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (not findSite(c, v, s)) { -// fprintf(stderr, "add site %p to %p\n", s, v); +// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), v); if (s->tryAcquire(c, stack, size, v)) { s->next = v->sites; v->sites = s; @@ -377,7 +377,7 @@ removeSite(Context* c, Value* v, Site* s) { for (Site** p = &(v->sites); *p;) { if (s == *p) { -// fprintf(stderr, "remove site %p from %p\n", s, v); +// fprintf(stderr, "remove site %p (%d) from %p\n", s, s->type(c), v); s->release(c); *p = (*p)->next; break; @@ -1271,6 +1271,17 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second) CompareEvent(c, size, first, second); } +void +maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) +{ + if (v->reads->next and v->sites->next == 0) { + assert(c, v->sites == s); + Site* r = freeRegister(c, size, true); + addSite(c, stack, size, v, r); + apply(c, Move, size, s, r); + } +} + class CombineEvent: public Event { public: CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, @@ -1295,6 +1306,8 @@ class CombineEvent: public Event { fprintf(stderr, "CombineEvent.compile\n"); } + maybePreserve(c, stack, size, second, second->source); + apply(c, type, size, first->source, second->source); nextRead(c, first); @@ -1351,6 +1364,8 @@ class TranslateEvent: public Event { fprintf(stderr, "TranslateEvent.compile\n"); } + maybePreserve(c, stack, size, value, value->source); + apply(c, type, size, value->source); nextRead(c, value); From 377e2864d9d671ba7fa3b8d82df06ad7bb30035b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 10:40:44 -0600 Subject: [PATCH 063/121] fix argument marshalling for floating point helper functions on 32-bit systems --- src/compile.cpp | 20 ++++++++++---------- src/compiler.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index c95b4021ae..03e8f7401e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2147,7 +2147,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(addDouble)), - context->indirection, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 4, 0, a, 0, b)); } break; case dcmpg: { @@ -2157,7 +2157,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesG)), - context->indirection, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 4, 0, a, 0, b)); } break; case dcmpl: { @@ -2167,7 +2167,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesL)), - context->indirection, 0, 0, 4, 2, a, b)); + context->indirection, 0, 0, 4, 4, 0, a, 0, b)); } break; case dconst_0: @@ -2185,7 +2185,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(divideDouble)), - context->indirection, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 4, 0, a, 0, b)); } break; case dmul: { @@ -2195,14 +2195,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(multiplyDouble)), - context->indirection, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 4, 0, a, 0, b)); } break; case dneg: { frame->pushLong (c->call (c->constant(reinterpret_cast(negateDouble)), - context->indirection, 0, 0, 8, 1, frame->popLong())); + context->indirection, 0, 0, 8, 2, 0, frame->popLong())); } break; case vm::drem: { @@ -2212,7 +2212,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(moduloDouble)), - context->indirection, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 4, 0, a, 0, b)); } break; case dsub: { @@ -2222,7 +2222,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(subtractDouble)), - context->indirection, 0, 0, 8, 2, a, b)); + context->indirection, 0, 0, 8, 4, 0, a, 0, b)); } break; case dup: @@ -3875,11 +3875,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/nio/ByteBuffer") == 0 and + "Floats") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "get") == 0) + "multiply") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index a06e8c93aa..99d45120db 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2255,7 +2255,7 @@ class MyCompiler: public Compiler { Stack* oldStack = c.state->stack; - for (int i = argumentCount - 1; i >= 0; --i) { + for (int i = index - 1; i >= 0; --i) { ::push(&c, argumentSizes[i], arguments[i]); } From 9dafe37ff3788d9f35ce2564001b9965c7bf3b65 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 10:55:56 -0600 Subject: [PATCH 064/121] fix code ordering bug in MyCompiler::peek --- src/compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 99d45120db..a9e0fd776b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2209,8 +2209,8 @@ class MyCompiler: public Compiler { virtual Operand* peek(unsigned size UNUSED, unsigned index) { Stack* s = c.state->stack; for (unsigned i = index; i > 0;) { - s = s->next; i -= s->size; + s = s->next; } assert(&c, s->size == ceiling(size, BytesPerWord)); return s->value; From 4652b7aea05fbe389a257fb5fcc94e7c38112167 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 10:56:29 -0600 Subject: [PATCH 065/121] enable 64-bit various operations on 32-bit systems --- src/x86.cpp | 147 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 54 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index d1181e949c..fd280a0209 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1042,24 +1042,35 @@ moveZRR(Context* c, unsigned size, Assembler::Register* a, } void -addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +addCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo - int64_t v = a->value->value(); if (v) { - rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xc0 | b->low); - c->code.append(v); - } else if (isInt32(v)) { - c->code.append(0x81); - c->code.append(0xc0 | b->low); - c->code.append4(v); + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + addCR(c, 4, &al, b); + addCarryCR(c, 4, &ah, &bh); } else { - abort(c); + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xc0 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xc0 | b->low); + c->code.append4(v); + } else { + abort(c); + } } } } @@ -1340,29 +1351,40 @@ andRR(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +andCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo - int64_t v = a->value->value(); - if (isInt32(v)) { - rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xe0 | b->low); - c->code.append(v); - } else { - c->code.append(0x81); - c->code.append(0xe0 | b->low); - c->code.append4(v); - } + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + andCR(c, 4, &al, b); + andCR(c, 4, &ah, &bh); } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - andRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xe0 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xe0 | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + andRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } } } @@ -1396,40 +1418,57 @@ orRR(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -xorRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +xorRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); - rex(c); - c->code.append(0x31); - c->code.append(0xc0 | (a->low << 3) | b->low); + xorRR(c, 4, a, b); + xorRR(c, 4, &ah, &bh); + } else { + rex(c); + c->code.append(0x31); + c->code.append(0xc0 | (a->low << 3) | b->low); + } } void -xorCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +xorCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo - int64_t v = a->value->value(); if (v) { - if (isInt32(v)) { - rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xf0 | b->low); - c->code.append(v); - } else { - c->code.append(0x81); - c->code.append(0xf0 | b->low); - c->code.append4(v); - } + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + xorCR(c, 4, &al, b); + xorCR(c, 4, &ah, &bh); } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - xorRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf0 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xf0 | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + xorRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } } } } From 3fa3fd0796b86ccd54350d0f45e257e8631060dc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 14:24:08 -0600 Subject: [PATCH 066/121] fix stack index calculation when pushing operands --- src/compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index a9e0fd776b..d6cd216115 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1860,7 +1860,7 @@ popState(Context* c) Stack* stack(Context* c, Value* value, unsigned size, Stack* next) { - return stack(c, value, size, (next ? next->index + size : 0), next); + return stack(c, value, size, (next ? next->index + next->size : 0), next); } void From 4c2d44099bcf2e889c7254413a5a1ff9b19ef092 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 14:24:52 -0600 Subject: [PATCH 067/121] support more 64-bit operations on 32-bit systems --- src/x86.cpp | 243 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 177 insertions(+), 66 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index fd280a0209..4683fbdfd4 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1340,14 +1340,20 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, } void -andRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +andRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); - rex(c); - c->code.append(0x21); - c->code.append(0xc0 | (a->low << 3) | b->low); + andRR(c, 4, a, b); + andRR(c, 4, &ah, &bh); + } else { + rex(c); + c->code.append(0x21); + c->code.append(0xc0 | (a->low << 3) | b->low); + } } void @@ -1407,14 +1413,20 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, } void -orRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +orRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); - rex(c); - c->code.append(0x09); - c->code.append(0xc0 | (a->low << 3) | b->low); + orRR(c, 4, a, b); + orRR(c, 4, &ah, &bh); + } else { + rex(c); + c->code.append(0x09); + c->code.append(0xc0 | (a->low << 3) | b->low); + } } void @@ -1474,104 +1486,203 @@ xorCR(Context* c, unsigned size, Assembler::Constant* a, } void -shift(Context* c, int type, Assembler::Register* a, Assembler::Register* b) { - if (a->low == rcx) { - rex(c); - c->code.append(0xd3); - c->code.append(type | b->low); - } else { - Assembler::Register target(b->low); +doShift(Context* c, void (*shift) + (Context*, unsigned, Assembler::Register*, Assembler::Register*), + unsigned size, Assembler::Register* a, Assembler::Register* b) +{ + Assembler::Register target(b->low, b->high); - if (b->low == rcx) { - target.low = c->client->acquireTemporary(); - moveRR(c, BytesPerWord, b, &target); - } else { - c->client->save(rcx); - } + if (b->low == rcx) { + target.low = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, b, &target); + } else if (b->high == rcx) { + target.high = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, b, &target); + } else { + c->client->save(rcx); + } + + Assembler::Register cx(rcx); + moveRR(c, BytesPerWord, a, &cx); + shift(c, size, &cx, b); + + if (b->low == rcx) { + moveRR(c, BytesPerWord, &target, b); + c->client->releaseTemporary(target.low); + } else if (b->high == rcx) { + moveRR(c, BytesPerWord, &target, b); + c->client->releaseTemporary(target.high); + } else { + c->client->restore(rcx); + } +} + +void +doShift(Context* c, void (*shift) + (Context*, unsigned, Assembler::Register*, Assembler::Register*), + int type, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + int64_t v = a->value->value(); + + if (BytesPerWord == 4 and size == 8) { + c->client->save(rcx); Assembler::Register cx(rcx); - moveRR(c, BytesPerWord, a, &cx); - shift(c, type, &cx, b); + moveCR(c, 4, a, &cx); + shift(c, size, &cx, b); - if (b->low == rcx) { - moveRR(c, BytesPerWord, &target, b); - c->client->releaseTemporary(target.low); + c->client->restore(rcx); + } else { + rex(c); + if (v == 1) { + c->code.append(0xd1); + c->code.append(type | b->low); + } else if (isInt8(v)) { + c->code.append(0xc1); + c->code.append(type | b->low); + c->code.append(v); } else { - c->client->restore(rcx); + abort(c); } } } void -shift(Context* c, int type, Assembler::Constant* a, Assembler::Register* b) -{ - int64_t v = a->value->value(); - - rex(c); - if (v == 1) { - c->code.append(0xd1); - c->code.append(type | b->low); - } else if (isInt8(v)) { - c->code.append(0xc1); - c->code.append(type | b->low); - c->code.append(v); - } else { - abort(c); - } -} +compareCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b); void -shiftLeftRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +shiftLeftRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); + if (a->low == rcx) { + if (BytesPerWord == 4 and size == 8) { + // shld + c->code.append(0x0f); + c->code.append(0xa5); + c->code.append(0xc0 | (b->low << 3) | b->high); - shift(c, 0xe0, a, b); + // shl + c->code.append(0xd3); + c->code.append(0xe0 | b->low); + + ResolvedPromise promise(32); + Assembler::Constant constant(&promise); + compareCR(c, 4, &constant, a); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + c->code.append4(2 + 2); + + Assembler::Register bh(b->high); + moveRR(c, 4, b, &bh); // 2 bytes + xorRR(c, 4, b, b); // 2 bytes + } else { + rex(c); + c->code.append(0xd3); + c->code.append(0xe0 | b->low); + } + } else { + doShift(c, shiftLeftRR, size, a, b); + } } void -shiftLeftCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +shiftLeftCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); - - shift(c, 0xe0, a, b); + doShift(c, shiftLeftRR, 0xe0, size, a, b); } void -shiftRightRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +shiftRightRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); + if (a->low == rcx) { + if (BytesPerWord == 4 and size == 8) { + // shrd + c->code.append(0x0f); + c->code.append(0xad); + c->code.append(0xc0 | (b->high << 3) | b->low); - shift(c, 0xf8, a, b); + // sar + c->code.append(0xd3); + c->code.append(0xf8 | b->high); + + ResolvedPromise promise(32); + Assembler::Constant constant(&promise); + compareCR(c, 4, &constant, a); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + c->code.append4(2 + 3); + + Assembler::Register bh(b->high); + moveRR(c, 4, &bh, b); // 2 bytes + + // sar 31,high + c->code.append(0xc1); + c->code.append(0xf8 | b->high); + c->code.append(31); + } else { + rex(c); + c->code.append(0xd3); + c->code.append(0xf8 | b->low); + } + } else { + doShift(c, shiftRightRR, size, a, b); + } } void -shiftRightCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +shiftRightCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); - - shift(c, 0xf8, a, b); + doShift(c, shiftRightRR, 0xf8, size, a, b); } void -unsignedShiftRightRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +unsignedShiftRightRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); + if (a->low == rcx) { + if (BytesPerWord == 4 and size == 8) { + // shld + c->code.append(0x0f); + c->code.append(0xa5); + c->code.append(0xc0 | (b->high << 3) | b->low); - shift(c, 0xe8, a, b); + // shr + c->code.append(0xd3); + c->code.append(0xe8 | b->high); + + ResolvedPromise promise(32); + Assembler::Constant constant(&promise); + compareCR(c, 4, &constant, a); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + c->code.append4(2 + 2); + + Assembler::Register bh(b->high); + moveRR(c, 4, &bh, b); // 2 bytes + xorRR(c, 4, &bh, &bh); // 2 bytes + } else { + rex(c); + c->code.append(0xd3); + c->code.append(0xe8 | b->low); + } + } else { + doShift(c, unsignedShiftRightRR, size, a, b); + } } void -unsignedShiftRightCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); - - shift(c, 0xe8, a, b); + doShift(c, unsignedShiftRightRR, 0xe8, size, a, b); } void From 59f92b620816249a95c591445636e22ccc494b89 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 16:11:17 -0600 Subject: [PATCH 068/121] support 64-bit multiplies on 32-bit systems --- src/x86.cpp | 116 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 35 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 4683fbdfd4..5dc5e0f8f0 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -35,6 +35,12 @@ enum { r15 = 15, }; +int64_t FORCE_ALIGN +multiplyLong(int64_t a, int64_t b) +{ + return a * b; +} + int64_t FORCE_ALIGN divideLong(int64_t a, int64_t b) { @@ -438,9 +444,9 @@ pushR(Context*, unsigned, Assembler::Register*); void pushC(Context* c, unsigned size, Assembler::Constant* a) { - int64_t v = a->value->value(); - if (BytesPerWord == 4 and size == 8) { + int64_t v = a->value->value(); + ResolvedPromise low(v & 0xFFFFFFFF); Assembler::Constant al(&low); @@ -450,17 +456,26 @@ pushC(Context* c, unsigned size, Assembler::Constant* a) pushC(c, 4, &ah); pushC(c, 4, &al); } else { - if (isInt8(v)) { - c->code.append(0x6a); - c->code.append(v); - } else if (isInt32(v)) { - c->code.append(0x68); - c->code.append4(v); + if (a->value->resolved()) { + int64_t v = a->value->value(); + if (isInt8(v)) { + c->code.append(0x6a); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x68); + c->code.append4(v); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + pushR(c, size, &tmp); + c->client->releaseTemporary(tmp.low); + } } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - pushR(c, size, &tmp); - c->client->releaseTemporary(tmp.low); + assert(c, BytesPerWord == 4); + + c->code.append(0x68); + appendImmediateTask(c, a->value, c->code.length()); + c->code.appendAddress(static_cast(0)); } } } @@ -1174,41 +1189,71 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -multiplyRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +multiplyRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + pushR(c, size, a); + pushR(c, size, b); + + Assembler::Constant address + (resolved(c, reinterpret_cast(multiplyLong))); + callC(c, BytesPerWord, &address); - rex(c); - c->code.append(0x0f); - c->code.append(0xaf); - c->code.append(0xc0 | (b->low << 3) | a->low); + Assembler::Register axdx(rax, rdx); + moveRR(c, 4, &axdx, b); + + ResolvedPromise offsetPromise(16); + Assembler::Constant offset(&offsetPromise); + Assembler::Register stack(rsp); + addCR(c, BytesPerWord, &offset, &stack); + } else { + rex(c); + c->code.append(0x0f); + c->code.append(0xaf); + c->code.append(0xc0 | (b->low << 3) | a->low); + } } void multiplyCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + pushC(c, size, a); + pushR(c, size, b); + + Assembler::Constant address + (resolved(c, reinterpret_cast(multiplyLong))); + callC(c, BytesPerWord, &address); - int64_t v = a->value->value(); - if (v) { - if (isInt32(v)) { - rex(c); - if (isInt8(v)) { - c->code.append(0x6b); - c->code.append(0xc0 | (b->low << 3) | b->low); - c->code.append(v); + Assembler::Register axdx(rax, rdx); + moveRR(c, 4, &axdx, b); + + ResolvedPromise offsetPromise(16); + Assembler::Constant offset(&offsetPromise); + Assembler::Register stack(rsp); + addCR(c, BytesPerWord, &offset, &stack); + } else { + int64_t v = a->value->value(); + if (v) { + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x6b); + c->code.append(0xc0 | (b->low << 3) | b->low); + c->code.append(v); + } else { + c->code.append(0x69); + c->code.append(0xc0 | (b->low << 3) | b->low); + c->code.append4(v); + } } else { - c->code.append(0x69); - c->code.append(0xc0 | (b->low << 3) | b->low); - c->code.append4(v); + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + multiplyRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - multiplyRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); } } } @@ -1996,6 +2041,7 @@ class MyAssembler: public Assembler { *syncStack = false; switch (op) { + case Multiply: case Divide: case Remainder: if (BytesPerWord == 4 and size == 8) { From 76405901537fa41598aa5b80e43426fb70fbed84 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 17:16:53 -0600 Subject: [PATCH 069/121] implement orCR and compareRC --- src/x86.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 5dc5e0f8f0..d5a9b0f673 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -471,11 +471,16 @@ pushC(Context* c, unsigned size, Assembler::Constant* a) c->client->releaseTemporary(tmp.low); } } else { - assert(c, BytesPerWord == 4); - - c->code.append(0x68); - appendImmediateTask(c, a->value, c->code.length()); - c->code.appendAddress(static_cast(0)); + if (BytesPerWord == 4) { + c->code.append(0x68); + appendImmediateTask(c, a->value, c->code.length()); + c->code.appendAddress(static_cast(0)); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + pushR(c, size, &tmp); + c->client->releaseTemporary(tmp.low); + } } } } @@ -1474,6 +1479,45 @@ orRR(Context* c, unsigned size, Assembler::Register* a, } } +void +orCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + int64_t v = a->value->value(); + if (v) { + if (BytesPerWord == 4 and size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + orCR(c, 4, &al, b); + orCR(c, 4, &ah, &bh); + } else { + if (isInt32(v)) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xc8 | b->low); + c->code.append(v); + } else { + c->code.append(0x81); + c->code.append(0xc8 | b->low); + c->code.append4(v); + } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + orRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + void xorRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -1866,6 +1910,18 @@ compareMM(Context* c, unsigned size UNUSED, Assembler::Memory* a, c->client->releaseTemporary(tmp.low); } +void +compareRC(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Constant* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, b, &tmp); + compareRR(c, size, a, &tmp); + c->client->releaseTemporary(tmp.low); +} + void populateTables() { @@ -1939,6 +1995,7 @@ populateTables() BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); BinaryOperations[INDEX2(Or, Register, Register)] = CAST2(orRR); + BinaryOperations[INDEX2(Or, Constant, Register)] = CAST2(orCR); BinaryOperations[INDEX2(Xor, Register, Register)] = CAST2(xorRR); BinaryOperations[INDEX2(Xor, Constant, Register)] = CAST2(xorCR); @@ -1960,6 +2017,7 @@ populateTables() BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); + BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC); BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR); BinaryOperations[INDEX2(Compare, Register, Memory)] = CAST2(compareRM); BinaryOperations[INDEX2(Compare, Memory, Register)] = CAST2(compareMR); From 3909e3f032df3281d62a19790002ad66112b26ba Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 29 Apr 2008 17:18:28 -0600 Subject: [PATCH 070/121] fix thinko concerning stack resets in compile() --- src/compiler.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index d6cd216115..1bd5ac623d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1781,10 +1781,8 @@ compile(Context* c) for (Stack* s = e->stack; s; s = s->next) { if (s->value->sites) { assert(c, s->value->sites->next == 0); - if (s->value->reads) { - expect(c, s->value->sites->tryAcquire - (c, 0, s->size * BytesPerWord, s->value)); - } + expect(c, s->value->sites->tryAcquire + (c, 0, s->size * BytesPerWord, s->value)); } } } From e2b24263a232fa031497359c3af1c1d788cbc776 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 30 Apr 2008 09:44:17 -0600 Subject: [PATCH 071/121] various bugfixes --- src/compile.cpp | 6 +- src/compiler.cpp | 175 +++++++++++++++++++++-------------------------- src/heap.cpp | 2 +- src/x86.cpp | 62 +++++++++++++---- test/Misc.java | 120 +++++++++++++++++--------------- 5 files changed, 196 insertions(+), 169 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 03e8f7401e..9a870fb15b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = true; +const bool Verbose = false; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -3875,11 +3875,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Floats") == 0 and + "org/eclipse/swt/graphics/ImageData") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "multiply") == 0) + "") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 1bd5ac623d..2af6534795 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -387,6 +387,21 @@ removeSite(Context* c, Value* v, Site* s) } } +void +removeMemorySites(Context* c, Value* v) +{ + for (Site** p = &(v->sites); *p;) { + if ((*p)->type(c) == MemoryOperand) { +// fprintf(stderr, "remove site %p (%d) from %p\n", s, s->type(c), v); + (*p)->release(c); + *p = (*p)->next; + break; + } else { + p = &((*p)->next); + } + } +} + void clearSites(Context* c, Value* v) { @@ -542,7 +557,7 @@ registerSite(Context* c, int low, int high = NoRegister) } RegisterSite* -freeRegister(Context* c, unsigned size, bool allowAcquired); +freeRegister(Context* c, unsigned size); void increment(Context* c, int r) @@ -662,14 +677,40 @@ targetOrNull(Context* c, Value* v, Event* event) } } +bool +used(Context* c, int r) +{ + Value* v = c->registers[r].value; +// fprintf(stderr, "v: %p found: %d\n", +// v, v and findSite(c, v, c->registers[r].site)); + return v and findSite(c, v, c->registers[r].site); +} + +bool +usedExclusively(Context* c, int r) +{ + Value* v = c->registers[r].value; + return used(c, r) and v->sites->next == 0; +} + +bool +isFree(Context* c, Site* s) +{ + return s->type(c) != RegisterOperand + or not (usedExclusively(c, static_cast(s)->register_.low) + or (static_cast(s)->register_.high != NoRegister + and usedExclusively + (c, static_cast(s)->register_.high))); +} + Site* targetOrRegister(Context* c, unsigned size, Value* v, Event* event) { Site* s = targetOrNull(c, v, event); - if (s) { + if (s and isFree(c, s)) { return s; } else { - return freeRegister(c, size, true); + return freeRegister(c, size); } } @@ -687,7 +728,7 @@ class ValueSite: public AbstractSite { return s; } } - return freeRegister(c, r->size, true); + return freeRegister(c, r->size); } } @@ -729,7 +770,7 @@ class AnyRegisterSite: public AbstractSite { return s; } } - return freeRegister(c, r->size, true); + return freeRegister(c, r->size); } }; @@ -748,7 +789,7 @@ class ConstantOrRegisterSite: public AbstractSite { return s; } } - return freeRegister(c, r->size, true); + return freeRegister(c, r->size); } }; @@ -800,6 +841,8 @@ pushNow(Context* c, Stack* start, unsigned count) if (s->value and s->value->sites) { Site* source = pick(c, s->value->sites); + removeMemorySites(c, s->value); + s->pushSite = pushSite(c, s->index); addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); @@ -1276,7 +1319,7 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (v->reads->next and v->sites->next == 0) { assert(c, v->sites == s); - Site* r = freeRegister(c, size, true); + Site* r = freeRegister(c, size); addSite(c, stack, size, v, r); apply(c, Move, size, s, r); } @@ -1682,68 +1725,24 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } -// void -// swapRegisters(Context* c, int* ap, int* bp) -// { -// Assembler::Register a(*ap); -// Assembler::Register b(*bp); - -// c->assembler->apply -// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); -// c->assembler->apply -// (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); -// c->assembler->apply -// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); - -// int t = *ap; -// *ap = *bp; -// *bp = t; -// } - Site* readSource(Context* c, Stack* stack, Read* r, Event* e) { Site* target = (r->target ? r->target->readTarget(c, r, e) : 0); + if (target and not isFree(c, target)) { + target = 0; + } + unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); if (target) { if (copyCost) { - if (tryAddSite(c, stack, r->size, r->value, target)) { - apply(c, Move, r->size, site, target); - return target; - } else { - abort(c); -// // this is a filthy hack, but I think the core idea is right: - -// assert(c, target->type(c) == RegisterOperand); - -// RegisterSite* ts = static_cast(target); - -// for (Site* s = r->value->sites; s; s = s->next) { -// if (s->type(c) == RegisterOperand) { -// RegisterSite* rs = static_cast(s); - -// RegisterSite* os = static_cast -// (c->registers[ts->register_.low].site); - -// assert(c, os->register_.low == ts->register_.low); -// assert(c, os->register_.high == NoRegister); -// assert(c, ts->register_.high == NoRegister); -// assert(c, rs->register_.high == NoRegister); - -// swapRegisters(c, &(os->register_.low), &(rs->register_.low)); - -// return rs; -// } -// } - } - - abort(c); - } else { - return target; + addSite(c, stack, r->size, r->value, target); + apply(c, Move, r->size, site, target); } + return target; } else { return site; } @@ -1896,24 +1895,8 @@ updateJunctions(Context* c) } } -bool -used(Context* c, int r) -{ - Value* v = c->registers[r].value; -// fprintf(stderr, "v: %p found: %d\n", -// v, v and findSite(c, v, c->registers[r].site)); - return v and findSite(c, v, c->registers[r].site); -} - -bool -usedExclusively(Context* c, int r) -{ - Value* v = c->registers[r].value; - return used(c, r) and v->sites->next == 0; -} - int -freeRegisterExcept(Context* c, int except, bool allowAcquired) +freeRegisterExcept(Context* c, int except) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { if (i != except @@ -1924,22 +1907,20 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) } } - if (allowAcquired) { - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0 - and (not usedExclusively(c, i))) - { - return i; - } + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (i != except + and c->registers[i].refCount == 0 + and (not usedExclusively(c, i))) + { + return i; } + } - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0) - { - return i; - } + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (i != except + and c->registers[i].refCount == 0) + { + return i; } } @@ -1959,21 +1940,21 @@ visit(Context* c, unsigned logicalIp) } int -freeRegister(Context* c, bool allowAcquired) +freeRegister(Context* c) { - int r = freeRegisterExcept(c, NoRegister, allowAcquired); + int r = freeRegisterExcept(c, NoRegister); // fprintf(stderr, "free reg: %d\n", r); return r; } RegisterSite* -freeRegister(Context* c, unsigned size, bool allowAcquired) +freeRegister(Context* c, unsigned size) { if (BytesPerWord == 4 and size == 8) { - int low = freeRegister(c, allowAcquired); - return registerSite(c, low, freeRegisterExcept(c, low, allowAcquired)); + int low = freeRegister(c); + return registerSite(c, low, freeRegisterExcept(c, low)); } else { - return registerSite(c, freeRegister(c, allowAcquired)); + return registerSite(c, freeRegister(c)); } } @@ -1982,13 +1963,15 @@ class Client: public Assembler::Client { Client(Context* c): c(c) { } virtual int acquireTemporary() { - int r = freeRegisterExcept(c, NoRegister, false); + int r = freeRegisterExcept(c, NoRegister); + save(r); increment(c, r); return r; } virtual void releaseTemporary(int r) { decrement(c, r); + restore(r); } virtual void save(int r) { diff --git a/src/heap.cpp b/src/heap.cpp index d4942e6f0e..a70f176b3e 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -29,7 +29,7 @@ const unsigned InitialTenuredFixieCeilingInBytes = 4 * 1024 * 1024; const unsigned LowMemoryPaddingInBytes = 1024 * 1024; -const bool Verbose = true; +const bool Verbose = false; const bool Verbose2 = false; const bool Debug = false; const bool DebugFixies = false; diff --git a/src/x86.cpp b/src/x86.cpp index d5a9b0f673..eddf5dfea7 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -563,7 +563,7 @@ popM(Context* c, unsigned size, Assembler::Memory* a) } void -addCarryCR(Context* c, unsigned size, Assembler::Constant* a, +addCarryCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); @@ -1096,7 +1096,7 @@ addCR(Context* c, unsigned size, Assembler::Constant* a, } void -subtractBorrowCR(Context* c, unsigned size, Assembler::Constant* a, +subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); @@ -1112,7 +1112,7 @@ subtractBorrowCR(Context* c, unsigned size, Assembler::Constant* a, } void -subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +subtractCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { int64_t v = a->value->value(); @@ -1157,7 +1157,7 @@ subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -addCarryRR(Context* c, unsigned size, Assembler::Register* a, +addCarryRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); @@ -1286,7 +1286,7 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register ax(rax); Assembler::Register divisor(a->low); - if (a->low == rdx) { + if (a->low == rdx or a->low == rax) { divisor.low = c->client->acquireTemporary(); moveRR(c, BytesPerWord, a, &divisor); } else if (b->low != rdx) { @@ -1294,7 +1294,9 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, } if (b->low != rax) { - c->client->save(rax); + if (a->low != rax) { + c->client->save(rax); + } moveRR(c, BytesPerWord, b, &ax); } @@ -1306,10 +1308,12 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, if (b->low != rax) { moveRR(c, BytesPerWord, &ax, b); - c->client->restore(rax); + if (a->low != rax) { + c->client->restore(rax); + } } - if (a->low == rdx) { + if (a->low == rdx or a->low == rax) { moveRR(c, BytesPerWord, &divisor, a); c->client->releaseTemporary(divisor.low); } else if (b->low != rdx) { @@ -1354,7 +1358,7 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register dx(rdx); Assembler::Register divisor(a->low); - if (a->low == rdx) { + if (a->low == rdx or a->low == rax) { divisor.low = c->client->acquireTemporary(); moveRR(c, BytesPerWord, a, &divisor); } else if (b->low != rdx) { @@ -1362,7 +1366,9 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, } if (b->low != rax) { - c->client->save(rax); + if (a->low != rax) { + c->client->save(rax); + } moveRR(c, BytesPerWord, b, &ax); } @@ -1376,11 +1382,11 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, moveRR(c, BytesPerWord, &dx, b); } - if (b->low != rax) { + if (b->low != rax and a->low != rax) { c->client->restore(rax); } - if (a->low == rdx) { + if (a->low == rdx or a->low == rax) { moveRR(c, BytesPerWord, &divisor, a); c->client->releaseTemporary(divisor.low); } else if (b->low != rdx) { @@ -1389,6 +1395,33 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a, } } +void +remainderCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + pushC(c, size, a); + pushR(c, size, b); + + Assembler::Constant address + (resolved(c, reinterpret_cast(moduloLong))); + callC(c, BytesPerWord, &address); + + Assembler::Register axdx(rax, rdx); + moveRR(c, 4, &axdx, b); + + ResolvedPromise offsetPromise(16); + Assembler::Constant offset(&offsetPromise); + Assembler::Register stack(rsp); + addCR(c, BytesPerWord, &offset, &stack); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + remainderRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } +} + void andRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -1775,7 +1808,7 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, } void -compareRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +compareRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { @@ -1799,7 +1832,7 @@ compareRR(Context* c, unsigned size UNUSED, Assembler::Register* a, } void -compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, +compareCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { int64_t v = a->value->value(); @@ -1988,6 +2021,7 @@ populateTables() BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR); BinaryOperations[INDEX2(Divide, Constant, Register)] = CAST2(divideCR); + BinaryOperations[INDEX2(Remainder, Constant, Register)] = CAST2(remainderCR); BinaryOperations[INDEX2(Remainder, Register, Register)] = CAST2(remainderRR); BinaryOperations[INDEX2(And, Register, Register)] = CAST2(andRR); diff --git a/test/Misc.java b/test/Misc.java index 9c4aeded4a..09915f0830 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -66,75 +66,85 @@ public class Misc { return super.toString(); } + private static int zap() { + return 42; + } + + private static int zip() { + return 5 + zap(); + } + public static void main(String[] args) { - byte2 = 0; - expect(byte2 == 0); +// byte2 = 0; +// expect(byte2 == 0); - expect(Long.valueOf(231L) == 231L); +// expect(Long.valueOf(231L) == 231L); - long x = 231; - expect((x >> 32) == 0); - expect((x >>> 32) == 0); - expect((x << 32) == 992137445376L); +// long x = 231; +// expect((x >> 32) == 0); +// expect((x >>> 32) == 0); +// expect((x << 32) == 992137445376L); - int shift = 32; - expect((x >> shift) == 0); - expect((x >>> shift) == 0); - expect((x << shift) == 992137445376L); +// int shift = 32; +// expect((x >> shift) == 0); +// expect((x >>> shift) == 0); +// expect((x << shift) == 992137445376L); - long y = -231; - expect((y >> 32) == 0xffffffffffffffffL); - expect((y >>> 32) == 0xffffffffL); +// long y = -231; +// expect((y >> 32) == 0xffffffffffffffffL); +// expect((y >>> 32) == 0xffffffffL); - byte[] array = new byte[8]; - putLong(231, array, 0); - expect((array[0] & 0xff) == 0); - expect((array[1] & 0xff) == 0); - expect((array[2] & 0xff) == 0); - expect((array[3] & 0xff) == 0); - expect((array[4] & 0xff) == 0); - expect((array[5] & 0xff) == 0); - expect((array[6] & 0xff) == 0); - expect((array[7] & 0xff) == 231); +// byte[] array = new byte[8]; +// putLong(231, array, 0); +// expect((array[0] & 0xff) == 0); +// expect((array[1] & 0xff) == 0); +// expect((array[2] & 0xff) == 0); +// expect((array[3] & 0xff) == 0); +// expect((array[4] & 0xff) == 0); +// expect((array[5] & 0xff) == 0); +// expect((array[6] & 0xff) == 0); +// expect((array[7] & 0xff) == 231); - java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); - buffer.putLong(231); - buffer.flip(); - expect(buffer.getLong() == 231); +// java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); +// buffer.putLong(231); +// buffer.flip(); +// expect(buffer.getLong() == 231); - boolean v = Boolean.valueOf("true"); +// boolean v = Boolean.valueOf("true"); - ClassLoader.getSystemClassLoader().toString(); +// ClassLoader.getSystemClassLoader().toString(); - int a = 2; - int b = 2; - int c = a + b; +// int a = 2; +// int b = 2; +// int c = a + b; - Misc m = new Misc(); - m.toString(); +// Misc m = new Misc(); +// m.toString(); - String s = "hello"; - m.foo(s); - m.bar(s); - baz(s); +// String s = "hello"; +// m.foo(s); +// m.bar(s); +// baz(s); - m.sync(); - syncStatic(false); - try { - syncStatic(true); - } catch (RuntimeException e) { - e.printStackTrace(); - } +// m.sync(); +// syncStatic(false); +// try { +// syncStatic(true); +// } catch (RuntimeException e) { +// e.printStackTrace(); +// } - int d = alpha; - beta = 42; - alpha = 43; - int e = beta; - int f = alpha; - m.gamma = 44; +// int d = alpha; +// beta = 42; +// alpha = 43; +// int e = beta; +// int f = alpha; +// m.gamma = 44; - expect(beta == 42); - expect(alpha == 43); - expect(m.gamma == 44); +// expect(beta == 42); +// expect(alpha == 43); +// expect(m.gamma == 44); + + zip(); } } From 844841937f01800c8947c4e8d44b0942d3c21c11 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 30 Apr 2008 10:46:46 -0600 Subject: [PATCH 072/121] fix use of wrong constant in x86.cpp --- src/x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index eddf5dfea7..db046f862b 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -3,7 +3,7 @@ using namespace vm; -#define INDEX1(a, b) ((a) + (BinaryOperationCount * (b))) +#define INDEX1(a, b) ((a) + (UnaryOperationCount * (b))) #define CAST1(x) reinterpret_cast(x) From 918193fa602b0527dc0f832767a525371a46a4ed Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 30 Apr 2008 11:15:21 -0600 Subject: [PATCH 073/121] fix 32-bit right unsigned shifts on amd64 --- src/x86.cpp | 2 +- test/Misc.java | 129 ++++++++++++++++++++++++++++--------------------- 2 files changed, 75 insertions(+), 56 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index db046f862b..801478f923 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1791,7 +1791,7 @@ unsignedShiftRightRR(Context* c, unsigned size, Assembler::Register* a, moveRR(c, 4, &bh, b); // 2 bytes xorRR(c, 4, &bh, &bh); // 2 bytes } else { - rex(c); + if (size == 8) rex(c); c->code.append(0xd3); c->code.append(0xe8 | b->low); } diff --git a/test/Misc.java b/test/Misc.java index 09915f0830..1fa2c2d9c5 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -75,75 +75,94 @@ public class Misc { } public static void main(String[] args) { -// byte2 = 0; -// expect(byte2 == 0); + { int a = -5; + int b = 2; + expect(a >> b == -5 >> 2); + expect(a >>> b == -5 >>> 2); + expect(a << b == -5 << 2); + expect(a * b == -5 * 2); + expect(a / b == -5 / 2); + expect(a % b == -5 % 2); -// expect(Long.valueOf(231L) == 231L); + a = 5; + b = 2; + expect(a >> b == 5 >> 2); + expect(a >>> b == 5 >>> 2); + expect(a << b == 5 << 2); + expect(a * b == 5 * 2); + expect(a / b == 5 / 2); + expect(a % b == 5 % 2); + } -// long x = 231; -// expect((x >> 32) == 0); -// expect((x >>> 32) == 0); -// expect((x << 32) == 992137445376L); + byte2 = 0; + expect(byte2 == 0); -// int shift = 32; -// expect((x >> shift) == 0); -// expect((x >>> shift) == 0); -// expect((x << shift) == 992137445376L); + expect(Long.valueOf(231L) == 231L); -// long y = -231; -// expect((y >> 32) == 0xffffffffffffffffL); -// expect((y >>> 32) == 0xffffffffL); + long x = 231; + expect((x >> 32) == 0); + expect((x >>> 32) == 0); + expect((x << 32) == 992137445376L); -// byte[] array = new byte[8]; -// putLong(231, array, 0); -// expect((array[0] & 0xff) == 0); -// expect((array[1] & 0xff) == 0); -// expect((array[2] & 0xff) == 0); -// expect((array[3] & 0xff) == 0); -// expect((array[4] & 0xff) == 0); -// expect((array[5] & 0xff) == 0); -// expect((array[6] & 0xff) == 0); -// expect((array[7] & 0xff) == 231); + int shift = 32; + expect((x >> shift) == 0); + expect((x >>> shift) == 0); + expect((x << shift) == 992137445376L); -// java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); -// buffer.putLong(231); -// buffer.flip(); -// expect(buffer.getLong() == 231); + long y = -231; + expect((y >> 32) == 0xffffffffffffffffL); + expect((y >>> 32) == 0xffffffffL); -// boolean v = Boolean.valueOf("true"); + byte[] array = new byte[8]; + putLong(231, array, 0); + expect((array[0] & 0xff) == 0); + expect((array[1] & 0xff) == 0); + expect((array[2] & 0xff) == 0); + expect((array[3] & 0xff) == 0); + expect((array[4] & 0xff) == 0); + expect((array[5] & 0xff) == 0); + expect((array[6] & 0xff) == 0); + expect((array[7] & 0xff) == 231); -// ClassLoader.getSystemClassLoader().toString(); + java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); + buffer.putLong(231); + buffer.flip(); + expect(buffer.getLong() == 231); -// int a = 2; -// int b = 2; -// int c = a + b; + boolean v = Boolean.valueOf("true"); -// Misc m = new Misc(); -// m.toString(); + ClassLoader.getSystemClassLoader().toString(); -// String s = "hello"; -// m.foo(s); -// m.bar(s); -// baz(s); + int a = 2; + int b = 2; + int c = a + b; -// m.sync(); -// syncStatic(false); -// try { -// syncStatic(true); -// } catch (RuntimeException e) { -// e.printStackTrace(); -// } + Misc m = new Misc(); + m.toString(); -// int d = alpha; -// beta = 42; -// alpha = 43; -// int e = beta; -// int f = alpha; -// m.gamma = 44; + String s = "hello"; + m.foo(s); + m.bar(s); + baz(s); -// expect(beta == 42); -// expect(alpha == 43); -// expect(m.gamma == 44); + m.sync(); + syncStatic(false); + try { + syncStatic(true); + } catch (RuntimeException e) { + e.printStackTrace(); + } + + int d = alpha; + beta = 42; + alpha = 43; + int e = beta; + int f = alpha; + m.gamma = 44; + + expect(beta == 42); + expect(alpha == 43); + expect(m.gamma == 44); zip(); } From bf08cc4c53de1daacf8a77084e8bff0b0f6158ee Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 30 Apr 2008 11:47:25 -0600 Subject: [PATCH 074/121] fix array bounds checks --- src/compile.cpp | 11 ++--- test/Misc.java | 110 +++++++++++++++++++++++++++--------------------- 2 files changed, 68 insertions(+), 53 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 9a870fb15b..b0721925a2 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1517,7 +1517,8 @@ void NO_RETURN FORCE_ALIGN throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index) { object message = makeString - (t, "array of length %d indexed at %d", arrayLength(t, array), index); + (t, "array of length %d indexed at %d", + cast(array, BytesPerWord), index); t->exception = makeArrayIndexOutOfBoundsException(t, message); unwind(t); } @@ -1794,7 +1795,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - c->jge(load); + c->jg(load); if (not c->isConstant(index)) { c->mark(throw_); @@ -1911,7 +1912,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - c->jge(store); + c->jg(store); if (not c->isConstant(index)) { c->mark(throw_); @@ -3875,11 +3876,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "org/eclipse/swt/graphics/ImageData") == 0 and + "Misc") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "main") == 0) { asm("int3"); } diff --git a/test/Misc.java b/test/Misc.java index 1fa2c2d9c5..259a87b5b4 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -99,30 +99,32 @@ public class Misc { expect(Long.valueOf(231L) == 231L); - long x = 231; - expect((x >> 32) == 0); - expect((x >>> 32) == 0); - expect((x << 32) == 992137445376L); + { long x = 231; + expect((x >> 32) == 0); + expect((x >>> 32) == 0); + expect((x << 32) == 992137445376L); - int shift = 32; - expect((x >> shift) == 0); - expect((x >>> shift) == 0); - expect((x << shift) == 992137445376L); + int shift = 32; + expect((x >> shift) == 0); + expect((x >>> shift) == 0); + expect((x << shift) == 992137445376L); - long y = -231; - expect((y >> 32) == 0xffffffffffffffffL); - expect((y >>> 32) == 0xffffffffL); + long y = -231; + expect((y >> 32) == 0xffffffffffffffffL); + expect((y >>> 32) == 0xffffffffL); + } - byte[] array = new byte[8]; - putLong(231, array, 0); - expect((array[0] & 0xff) == 0); - expect((array[1] & 0xff) == 0); - expect((array[2] & 0xff) == 0); - expect((array[3] & 0xff) == 0); - expect((array[4] & 0xff) == 0); - expect((array[5] & 0xff) == 0); - expect((array[6] & 0xff) == 0); - expect((array[7] & 0xff) == 231); + { byte[] array = new byte[8]; + putLong(231, array, 0); + expect((array[0] & 0xff) == 0); + expect((array[1] & 0xff) == 0); + expect((array[2] & 0xff) == 0); + expect((array[3] & 0xff) == 0); + expect((array[4] & 0xff) == 0); + expect((array[5] & 0xff) == 0); + expect((array[6] & 0xff) == 0); + expect((array[7] & 0xff) == 231); + } java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); buffer.putLong(231); @@ -133,37 +135,49 @@ public class Misc { ClassLoader.getSystemClassLoader().toString(); - int a = 2; - int b = 2; - int c = a + b; - - Misc m = new Misc(); - m.toString(); - - String s = "hello"; - m.foo(s); - m.bar(s); - baz(s); - - m.sync(); - syncStatic(false); - try { - syncStatic(true); - } catch (RuntimeException e) { - e.printStackTrace(); + { int a = 2; + int b = 2; + int c = a + b; } - int d = alpha; - beta = 42; - alpha = 43; - int e = beta; - int f = alpha; - m.gamma = 44; + { Misc m = new Misc(); + m.toString(); - expect(beta == 42); - expect(alpha == 43); - expect(m.gamma == 44); + String s = "hello"; + m.foo(s); + m.bar(s); + baz(s); + + m.sync(); + syncStatic(false); + try { + syncStatic(true); + } catch (RuntimeException e) { + e.printStackTrace(); + } + + int d = alpha; + beta = 42; + alpha = 43; + int e = beta; + int f = alpha; + m.gamma = 44; + + expect(beta == 42); + expect(alpha == 43); + expect(m.gamma == 44); + } zip(); + + int[] array = new int[0]; + Exception exception = null; + try { + int x = array[0]; + } catch (ArrayIndexOutOfBoundsException e) { + exception = e; + } + + expect(exception != null); } } From 7b809efd3f830e00186e0b75b6917ada3483b931 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 30 Apr 2008 12:44:27 -0600 Subject: [PATCH 075/121] fix shift bugs --- src/x86.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 801478f923..3575304b7d 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1626,7 +1626,7 @@ doShift(Context* c, void (*shift) Assembler::Register cx(rcx); moveRR(c, BytesPerWord, a, &cx); - shift(c, size, &cx, b); + shift(c, size, &cx, &target); if (b->low == rcx) { moveRR(c, BytesPerWord, &target, b); @@ -1656,7 +1656,7 @@ doShift(Context* c, void (*shift) c->client->restore(rcx); } else { - rex(c); + if (size == 8) rex(c); if (v == 1) { c->code.append(0xd1); c->code.append(type | b->low); @@ -1701,7 +1701,7 @@ shiftLeftRR(Context* c, unsigned size, Assembler::Register* a, moveRR(c, 4, b, &bh); // 2 bytes xorRR(c, 4, b, b); // 2 bytes } else { - rex(c); + if (size == 8) rex(c); c->code.append(0xd3); c->code.append(0xe0 | b->low); } @@ -1748,7 +1748,7 @@ shiftRightRR(Context* c, unsigned size, Assembler::Register* a, c->code.append(0xf8 | b->high); c->code.append(31); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0xd3); c->code.append(0xf8 | b->low); } From 2e108861daff44cb7cd59b7ab12b4edb4b41472f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 4 May 2008 13:09:12 -0600 Subject: [PATCH 076/121] remove operand marshalling from the assembler in favor of doing it in the compiler --- src/assembler.h | 8 +- src/x86.cpp | 703 +++++++++++++++++------------------------------- 2 files changed, 254 insertions(+), 457 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index c72fe53a99..226bc31351 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -156,8 +156,12 @@ class Assembler { virtual unsigned argumentRegisterCount() = 0; virtual int argumentRegister(unsigned index) = 0; - virtual void getTargets(BinaryOperation op, unsigned size, - Register* a, Register* b, bool* syncStack) = 0; + virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, + uint64_t* registerMask, uintptr_t* procedure); + + virtual void plan(UnaryOperation op, unsigned size, uint8_t* aTypeMask, + uint64_t* aRegisterMask, uint8_t* bTypeMask, + uint64_t* bRegisterMask, uintptr_t* procedure); virtual void apply(Operation op) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index 3575304b7d..8b9f025659 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -35,12 +35,6 @@ enum { r15 = 15, }; -int64_t FORCE_ALIGN -multiplyLong(int64_t a, int64_t b) -{ - return a * b; -} - int64_t FORCE_ALIGN divideLong(int64_t a, int64_t b) { @@ -589,106 +583,33 @@ xorRR(Context* c, unsigned size, Assembler::Register* a, void swap(Context* c, Assembler::Register* a, Assembler::Register* b) { + // todo: use xchg instead xorRR(c, 4, a, b); xorRR(c, 4, b, b); xorRR(c, 4, a, b); } -void -marshal(Context* c, int sl, int sh, int dl, int dh) -{ - Assembler::Register slr(sl); - Assembler::Register shr(sh); - Assembler::Register dlr(dl); - Assembler::Register dhr(dh); - - if (sl == dl or sh == dh) { - if (sl != dl) { - c->client->save(dl); - moveRR(c, BytesPerWord, &slr, &dlr); - } else if (sh != dh) { - c->client->save(dh); - moveRR(c, BytesPerWord, &shr, &dhr); - } - } else if (sl == dh or sh == dl) { - swap(c, &slr, &shr); - - if (sl != dh) { - c->client->save(dh); - moveRR(c, BytesPerWord, &slr, &dhr); - } else if (sh != dl) { - c->client->save(dl); - moveRR(c, BytesPerWord, &shr, &dlr); - } - } else { - c->client->save(dl); - moveRR(c, BytesPerWord, &slr, &dlr); - - c->client->save(dh); - moveRR(c, BytesPerWord, &shr, &dhr); - } -} - -void -unmarshal(Context* c, int sl, int sh, int dl, int dh) -{ - Assembler::Register slr(sl); - Assembler::Register shr(sh); - Assembler::Register dlr(dl); - Assembler::Register dhr(dh); - - if (sl == dl or sh == dh) { - if (sl != dl) { - moveRR(c, BytesPerWord, &slr, &dlr); - c->client->restore(sl); - } else if (sh != dh) { - moveRR(c, BytesPerWord, &shr, &dhr); - c->client->restore(sh); - } - } else if (sl == dh or sh == dl) { - if (sl != dh) { - moveRR(c, BytesPerWord, &slr, &dhr); - c->client->restore(sh); - } else if (sh != dl) { - moveRR(c, BytesPerWord, &shr, &dlr); - c->client->restore(sl); - } - - swap(c, &dlr, &dhr); - } else { - moveRR(c, BytesPerWord, &slr, &dlr); - c->client->restore(sl); - - moveRR(c, BytesPerWord, &shr, &dhr); - c->client->restore(sh); - } -} - void negateR(Context* c, unsigned size, Assembler::Register* a) { if (BytesPerWord == 4 and size == 8) { - Assembler::Register ax(rax); - Assembler::Register dx(rdx); + assert(c, a->low == rax and a->high == rdx); ResolvedPromise zeroPromise(0); Assembler::Constant zero(&zeroPromise); - marshal(c, a->low, a->high, rax, rdx); + Assembler::Register ah(a->high); - negateR(c, 4, &ax); - addCarryCR(c, 4, &zero, &dx); - negateR(c, 4, &dx); - - unmarshal(c, rax, rdx, a->low, a->high); + negateR(c, 4, a); + addCarryCR(c, 4, &zero, &ah); + negateR(c, 4, &ah); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0xf7); c->code.append(0xd8 | a->low); } } - void leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) { @@ -785,25 +706,12 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: - if (BytesPerWord == 4 and a->low > rbx) { - if (b->low > rbx) { - c->client->save(rax); + assert(c, BytesPerWord == 8 or (a->low <= rbx and b->low <= rbx)); - Assembler::Register ax(rax); - moveRR(c, BytesPerWord, a, &ax); - moveRR(c, 1, &ax, b); - - c->client->restore(rax); - } else { - moveRR(c, BytesPerWord, a, b); - moveRR(c, 1, b, b); - } - } else { - rex(c); - c->code.append(0x0f); - c->code.append(0xbe); - c->code.append(0xc0 | (b->low << 3) | a->low); - } + rex(c); + c->code.append(0x0f); + c->code.append(0xbe); + c->code.append(0xc0 | (b->low << 3) | a->low); break; case 2: @@ -844,17 +752,9 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) encode(c, 0x88, a->low, b, false); } } else { - if (a->low > rbx) { - c->client->save(rax); + assert(c, a->low <= rbx); - Assembler::Register ax(rax); - moveRR(c, BytesPerWord, a, &ax); - moveRM(c, 1, &ax, b); - - c->client->restore(rax); - } else { - encode(c, 0x88, a->low, b, false); - } + encode(c, 0x88, a->low, b, false); } break; @@ -872,31 +772,7 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) } void -move(Context* c, int sl, int sh, int dl, int dh) -{ - Assembler::Register slr(sl); - Assembler::Register shr(sh); - Assembler::Register dlr(dl); - Assembler::Register dhr(dh); - - if (sl == dh and sh == dl) { - swap(c, &slr, &shr); - } else { - if (sl != dl) { - if (sh == dl) { - moveRR(c, 4, &shr, &dhr); - } - moveRR(c, 4, &slr, &dlr); - } - - if (sh != dh and sh != dl) { - moveRR(c, 4, &shr, &dhr); - } - } -} - -void -move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, +move4To8RR(Context* c, unsigned, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 8) { @@ -907,26 +783,10 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, if (a->low == rax and b->low == rax and b->high == rdx) { c->code.append(0x99); // cdq } else { - Assembler::Register axdx(rax, rdx); - Assembler::Register dx(rdx); - Assembler::Register bh(b->high); + assert(c, b->low == rax and b->high == rdx); - bool saveAX = a->low != rax and b->low != rax and b->high != rax; - bool saveDX = b->low != rdx and b->high != rdx; - - if (saveDX) c->client->save(rdx); - if (saveAX) c->client->save(rax); - - if (a->low != rax) { - moveRR(c, 4, a, &axdx); - } - - move4To8RR(c, 0, &axdx, &axdx); - - move(c, rax, rdx, b->low, b->high); - - if (saveAX) c->client->restore(rax); - if (saveDX) c->client->restore(rdx); + moveRR(c, 4, a, b); + move4To8RR(c, 0, b, b); } } } @@ -1012,23 +872,10 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) if (BytesPerWord == 8) { encode(c, 0x63, b->low, a, true); } else { - Assembler::Register axdx(rax, rdx); - Assembler::Register dx(rdx); - Assembler::Register bh(b->high); + assert(c, b->low == rax and b->high == rdx); - bool saveAX = b->low != rax and b->high != rax; - bool saveDX = b->low != rdx and b->high != rdx; - - if (saveDX) c->client->save(rdx); - if (saveAX) c->client->save(rax); - - moveMR(c, 4, a, &axdx); - move4To8RR(c, 0, &axdx, &axdx); - - move(c, rax, rdx, b->low, b->high); - - if (saveAX) c->client->restore(rax); - if (saveDX) c->client->restore(rdx); + moveMR(c, 4, a, b); + move4To8RR(c, 0, b, b); } } @@ -1079,7 +926,7 @@ addCR(Context* c, unsigned size, Assembler::Constant* a, addCR(c, 4, &al, b); addCarryCR(c, 4, &ah, &bh); } else { - rex(c); + if (size == 8) rex(c); if (isInt8(v)) { c->code.append(0x83); c->code.append(0xc0 | b->low); @@ -1129,7 +976,7 @@ subtractCR(Context* c, unsigned size, Assembler::Constant* a, subtractCR(c, 4, &al, b); subtractBorrowCR(c, 4, &ah, &bh); } else { - rex(c); + if (size == 8) rex(c); if (isInt8(v)) { c->code.append(0x83); c->code.append(0xe8 | b->low); @@ -1146,23 +993,23 @@ subtractCR(Context* c, unsigned size, Assembler::Constant* a, } void -subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +subtractRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); // todo - rex(c); + if (size == 8) rex(c); c->code.append(0x29); c->code.append(0xc0 | (a->low << 3) | b->low); } void -addCarryRR(Context* c, unsigned size UNUSED, Assembler::Register* a, +addCarryRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { assert(c, BytesPerWord == 8 or size == 4); - rex(c); + if (size == 8) rex(c); c->code.append(0x11); c->code.append(0xc0 | (a->low << 3) | b->low); } @@ -1178,7 +1025,7 @@ addRR(Context* c, unsigned size, Assembler::Register* a, addRR(c, 4, a, b); addCarryRR(c, 4, &ah, &bh); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0x01); c->code.append(0xc0 | (a->low << 3) | b->low); } @@ -1198,22 +1045,32 @@ multiplyRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { - pushR(c, size, a); - pushR(c, size, b); - - Assembler::Constant address - (resolved(c, reinterpret_cast(multiplyLong))); - callC(c, BytesPerWord, &address); + assert(c, b->high == rdx); + assert(c, b->low != rax); + assert(c, a->low != rax); + assert(c, a->high != rax); + + c->client->save(rax); Assembler::Register axdx(rax, rdx); + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); + + moveRR(c, 4, b, &axdx); + multiplyRR(c, 4, &ah, b); + multiplyRR(c, 4, a, &bh); + addRR(c, 4, &bh, b); + + // mul a->low,%eax%edx + c->code.append(0xf7); + c->code.append(0xe8 | a->low); + + addRR(c, 4, b, &bh); moveRR(c, 4, &axdx, b); - ResolvedPromise offsetPromise(16); - Assembler::Constant offset(&offsetPromise); - Assembler::Register stack(rsp); - addCR(c, BytesPerWord, &offset, &stack); + c->client->restore(rax); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0x0f); c->code.append(0xaf); c->code.append(0xc0 | (b->low << 3) | a->low); @@ -1224,26 +1081,23 @@ void multiplyCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { + assert(c, BytesPerWord == 8 or size == 4); + if (BytesPerWord == 4 and size == 8) { - pushC(c, size, a); - pushR(c, size, b); - - Assembler::Constant address - (resolved(c, reinterpret_cast(multiplyLong))); - callC(c, BytesPerWord, &address); + const uint32_t mask = ~((1 << rax) | (1 << rdx)); + Assembler::Register tmp(c->client->acquireTemporary(mask), + c->client->acquireTemporary(mask)); - Assembler::Register axdx(rax, rdx); - moveRR(c, 4, &axdx, b); + moveCR(c, size, a, &tmp); + remainderRR(c, size, &tmp, b); - ResolvedPromise offsetPromise(16); - Assembler::Constant offset(&offsetPromise); - Assembler::Register stack(rsp); - addCR(c, BytesPerWord, &offset, &stack); + c->client->releaseTemporary(tmp.low); + c->client->releaseTemporary(tmp.high); } else { int64_t v = a->value->value(); if (v) { if (isInt32(v)) { - rex(c); + if (size == 8) rex(c); if (isInt8(v)) { c->code.append(0x6b); c->code.append(0xc0 | (b->low << 3) | b->low); @@ -1267,68 +1121,30 @@ void divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - pushR(c, size, a); - pushR(c, size, b); + assert(c, BytesPerWord == 8 or size == 4); + + assert(c, b->low == rax); + assert(c, a->low != rdx); + + c->client->save(rdx); - Assembler::Constant address - (resolved(c, reinterpret_cast(divideLong))); - callC(c, BytesPerWord, &address); + if (size == 8) rex(c); + c->code.append(0x99); // cdq + if (size == 8) rex(c); + c->code.append(0xf7); + c->code.append(0xf8 | a->low); - Assembler::Register axdx(rax, rdx); - moveRR(c, 4, &axdx, b); - - ResolvedPromise offsetPromise(16); - Assembler::Constant offset(&offsetPromise); - Assembler::Register stack(rsp); - addCR(c, BytesPerWord, &offset, &stack); - } else { - Assembler::Register ax(rax); - Assembler::Register divisor(a->low); - - if (a->low == rdx or a->low == rax) { - divisor.low = c->client->acquireTemporary(); - moveRR(c, BytesPerWord, a, &divisor); - } else if (b->low != rdx) { - c->client->save(rdx); - } - - if (b->low != rax) { - if (a->low != rax) { - c->client->save(rax); - } - moveRR(c, BytesPerWord, b, &ax); - } - - rex(c); - c->code.append(0x99); - rex(c); - c->code.append(0xf7); - c->code.append(0xf8 | divisor.low); - - if (b->low != rax) { - moveRR(c, BytesPerWord, &ax, b); - if (a->low != rax) { - c->client->restore(rax); - } - } - - if (a->low == rdx or a->low == rax) { - moveRR(c, BytesPerWord, &divisor, a); - c->client->releaseTemporary(divisor.low); - } else if (b->low != rdx) { - c->client->restore(rdx); - } - } + c->client->restore(rdx); } void divideCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + assert(c, BytesPerWord == 8 or size == 4); - Assembler::Register tmp(c->client->acquireTemporary()); + const uint32_t mask = ~((1 << rax) | (1 << rdx)); + Assembler::Register tmp(c->client->acquireTemporary(mask)); moveCR(c, size, a, &tmp); divideRR(c, size, &tmp, b); c->client->releaseTemporary(tmp.low); @@ -1338,88 +1154,36 @@ void remainderRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - pushR(c, size, a); - pushR(c, size, b); + assert(c, BytesPerWord == 8 or size == 4); + + assert(c, b->low == rax); + assert(c, a->low != rdx); + + c->client->save(rdx); - Assembler::Constant address - (resolved(c, reinterpret_cast(moduloLong))); - callC(c, BytesPerWord, &address); + if (size == 8) rex(c); + c->code.append(0x99); // cdq + if (size == 8) rex(c); + c->code.append(0xf7); + c->code.append(0xf8 | a->low); - Assembler::Register axdx(rax, rdx); - moveRR(c, 4, &axdx, b); + Assembler::Register dx(rdx); + moveRR(c, BytesPerWord, &dx, b); - ResolvedPromise offsetPromise(16); - Assembler::Constant offset(&offsetPromise); - Assembler::Register stack(rsp); - addCR(c, BytesPerWord, &offset, &stack); - } else { - Assembler::Register ax(rax); - Assembler::Register dx(rdx); - Assembler::Register divisor(a->low); - - if (a->low == rdx or a->low == rax) { - divisor.low = c->client->acquireTemporary(); - moveRR(c, BytesPerWord, a, &divisor); - } else if (b->low != rdx) { - c->client->save(rdx); - } - - if (b->low != rax) { - if (a->low != rax) { - c->client->save(rax); - } - moveRR(c, BytesPerWord, b, &ax); - } - - rex(c); - c->code.append(0x99); - rex(c); - c->code.append(0xf7); - c->code.append(0xf8 | divisor.low); - - if (b->low != rdx) { - moveRR(c, BytesPerWord, &dx, b); - } - - if (b->low != rax and a->low != rax) { - c->client->restore(rax); - } - - if (a->low == rdx or a->low == rax) { - moveRR(c, BytesPerWord, &divisor, a); - c->client->releaseTemporary(divisor.low); - } else if (b->low != rdx) { - c->client->restore(rdx); - } - } + c->client->restore(rdx); } void remainderCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - pushC(c, size, a); - pushR(c, size, b); - - Assembler::Constant address - (resolved(c, reinterpret_cast(moduloLong))); - callC(c, BytesPerWord, &address); + assert(c, BytesPerWord == 8 or size == 4); - Assembler::Register axdx(rax, rdx); - moveRR(c, 4, &axdx, b); - - ResolvedPromise offsetPromise(16); - Assembler::Constant offset(&offsetPromise); - Assembler::Register stack(rsp); - addCR(c, BytesPerWord, &offset, &stack); - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - remainderRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); - } + const uint32_t mask = ~((1 << rax) | (1 << rdx)); + Assembler::Register tmp(c->client->acquireTemporary(mask)); + moveCR(c, size, a, &tmp); + remainderRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } void @@ -1433,7 +1197,7 @@ andRR(Context* c, unsigned size, Assembler::Register* a, andRR(c, 4, a, b); andRR(c, 4, &ah, &bh); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0x21); c->code.append(0xc0 | (a->low << 3) | b->low); } @@ -1458,7 +1222,7 @@ andCR(Context* c, unsigned size, Assembler::Constant* a, andCR(c, 4, &ah, &bh); } else { if (isInt32(v)) { - rex(c); + if (size == 8) rex(c); if (isInt8(v)) { c->code.append(0x83); c->code.append(0xe0 | b->low); @@ -1497,7 +1261,7 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, void orRR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) + Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { Assembler::Register ah(a->high); @@ -1506,7 +1270,7 @@ orRR(Context* c, unsigned size, Assembler::Register* a, orRR(c, 4, a, b); orRR(c, 4, &ah, &bh); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0x09); c->code.append(0xc0 | (a->low << 3) | b->low); } @@ -1514,7 +1278,7 @@ orRR(Context* c, unsigned size, Assembler::Register* a, void orCR(Context* c, unsigned size, Assembler::Constant* a, - Assembler::Register* b) + Assembler::Register* b) { int64_t v = a->value->value(); if (v) { @@ -1531,7 +1295,7 @@ orCR(Context* c, unsigned size, Assembler::Constant* a, orCR(c, 4, &ah, &bh); } else { if (isInt32(v)) { - rex(c); + if (size == 8) rex(c); if (isInt8(v)) { c->code.append(0x83); c->code.append(0xc8 | b->low); @@ -1562,7 +1326,7 @@ xorRR(Context* c, unsigned size, Assembler::Register* a, xorRR(c, 4, a, b); xorRR(c, 4, &ah, &bh); } else { - rex(c); + if (size == 8) rex(c); c->code.append(0x31); c->code.append(0xc0 | (a->low << 3) | b->low); } @@ -1587,7 +1351,7 @@ xorCR(Context* c, unsigned size, Assembler::Constant* a, xorCR(c, 4, &ah, &bh); } else { if (isInt32(v)) { - rex(c); + if (size == 8) rex(c); if (isInt8(v)) { c->code.append(0x83); c->code.append(0xf0 | b->low); @@ -1607,38 +1371,6 @@ xorCR(Context* c, unsigned size, Assembler::Constant* a, } } -void -doShift(Context* c, void (*shift) - (Context*, unsigned, Assembler::Register*, Assembler::Register*), - unsigned size, Assembler::Register* a, Assembler::Register* b) -{ - Assembler::Register target(b->low, b->high); - - if (b->low == rcx) { - target.low = c->client->acquireTemporary(); - moveRR(c, BytesPerWord, b, &target); - } else if (b->high == rcx) { - target.high = c->client->acquireTemporary(); - moveRR(c, BytesPerWord, b, &target); - } else { - c->client->save(rcx); - } - - Assembler::Register cx(rcx); - moveRR(c, BytesPerWord, a, &cx); - shift(c, size, &cx, &target); - - if (b->low == rcx) { - moveRR(c, BytesPerWord, &target, b); - c->client->releaseTemporary(target.low); - } else if (b->high == rcx) { - moveRR(c, BytesPerWord, &target, b); - c->client->releaseTemporary(target.high); - } else { - c->client->restore(rcx); - } -} - void doShift(Context* c, void (*shift) (Context*, unsigned, Assembler::Register*, Assembler::Register*), @@ -1676,37 +1408,35 @@ compareCR(Context* c, unsigned size, Assembler::Constant* a, void shiftLeftRR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) + Assembler::Register* b) { - if (a->low == rcx) { - if (BytesPerWord == 4 and size == 8) { - // shld - c->code.append(0x0f); - c->code.append(0xa5); - c->code.append(0xc0 | (b->low << 3) | b->high); + assert(c, a->low == rcx); - // shl - c->code.append(0xd3); - c->code.append(0xe0 | b->low); + if (BytesPerWord == 4 and size == 8) { + // shld + c->code.append(0x0f); + c->code.append(0xa5); + c->code.append(0xc0 | (b->low << 3) | b->high); - ResolvedPromise promise(32); - Assembler::Constant constant(&promise); - compareCR(c, 4, &constant, a); + // shl + c->code.append(0xd3); + c->code.append(0xe0 | b->low); - c->code.append(0x0f); - c->code.append(0x8c); // jl - c->code.append4(2 + 2); + ResolvedPromise promise(32); + Assembler::Constant constant(&promise); + compareCR(c, 4, &constant, a); - Assembler::Register bh(b->high); - moveRR(c, 4, b, &bh); // 2 bytes - xorRR(c, 4, b, b); // 2 bytes - } else { - if (size == 8) rex(c); - c->code.append(0xd3); - c->code.append(0xe0 | b->low); - } + c->code.append(0x0f); + c->code.append(0x8c); // jl + c->code.append4(2 + 2); + + Assembler::Register bh(b->high); + moveRR(c, 4, b, &bh); // 2 bytes + xorRR(c, 4, b, b); // 2 bytes } else { - doShift(c, shiftLeftRR, size, a, b); + if (size == 8) rex(c); + c->code.append(0xd3); + c->code.append(0xe0 | b->low); } } @@ -1721,39 +1451,37 @@ void shiftRightRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - if (a->low == rcx) { - if (BytesPerWord == 4 and size == 8) { - // shrd - c->code.append(0x0f); - c->code.append(0xad); - c->code.append(0xc0 | (b->high << 3) | b->low); + assert(c, a->low == rcx); - // sar - c->code.append(0xd3); - c->code.append(0xf8 | b->high); + if (BytesPerWord == 4 and size == 8) { + // shrd + c->code.append(0x0f); + c->code.append(0xad); + c->code.append(0xc0 | (b->high << 3) | b->low); - ResolvedPromise promise(32); - Assembler::Constant constant(&promise); - compareCR(c, 4, &constant, a); + // sar + c->code.append(0xd3); + c->code.append(0xf8 | b->high); - c->code.append(0x0f); - c->code.append(0x8c); // jl - c->code.append4(2 + 3); + ResolvedPromise promise(32); + Assembler::Constant constant(&promise); + compareCR(c, 4, &constant, a); - Assembler::Register bh(b->high); - moveRR(c, 4, &bh, b); // 2 bytes + c->code.append(0x0f); + c->code.append(0x8c); // jl + c->code.append4(2 + 3); - // sar 31,high - c->code.append(0xc1); - c->code.append(0xf8 | b->high); - c->code.append(31); - } else { - if (size == 8) rex(c); - c->code.append(0xd3); - c->code.append(0xf8 | b->low); - } + Assembler::Register bh(b->high); + moveRR(c, 4, &bh, b); // 2 bytes + + // sar 31,high + c->code.append(0xc1); + c->code.append(0xf8 | b->high); + c->code.append(31); } else { - doShift(c, shiftRightRR, size, a, b); + if (size == 8) rex(c); + c->code.append(0xd3); + c->code.append(0xf8 | b->low); } } @@ -1768,35 +1496,33 @@ void unsignedShiftRightRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - if (a->low == rcx) { - if (BytesPerWord == 4 and size == 8) { - // shld - c->code.append(0x0f); - c->code.append(0xa5); - c->code.append(0xc0 | (b->high << 3) | b->low); + assert(c, a->low == rcx); - // shr - c->code.append(0xd3); - c->code.append(0xe8 | b->high); + if (BytesPerWord == 4 and size == 8) { + // shld + c->code.append(0x0f); + c->code.append(0xa5); + c->code.append(0xc0 | (b->high << 3) | b->low); - ResolvedPromise promise(32); - Assembler::Constant constant(&promise); - compareCR(c, 4, &constant, a); + // shr + c->code.append(0xd3); + c->code.append(0xe8 | b->high); - c->code.append(0x0f); - c->code.append(0x8c); // jl - c->code.append4(2 + 2); + ResolvedPromise promise(32); + Assembler::Constant constant(&promise); + compareCR(c, 4, &constant, a); - Assembler::Register bh(b->high); - moveRR(c, 4, &bh, b); // 2 bytes - xorRR(c, 4, &bh, &bh); // 2 bytes - } else { - if (size == 8) rex(c); - c->code.append(0xd3); - c->code.append(0xe8 | b->low); - } + c->code.append(0x0f); + c->code.append(0x8c); // jl + c->code.append4(2 + 2); + + Assembler::Register bh(b->high); + moveRR(c, 4, &bh, b); // 2 bytes + xorRR(c, 4, &bh, &bh); // 2 bytes } else { - doShift(c, unsignedShiftRightRR, size, a, b); + if (size == 8) rex(c); + c->code.append(0xd3); + c->code.append(0xe8 | b->low); } } @@ -1914,11 +1640,14 @@ compareCM(Context* c, unsigned size, Assembler::Constant* a, } void -compareRM(Context* c, unsigned size UNUSED, Assembler::Register* a, +compareRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) { assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, a, a); + } encode(c, 0x39, a->low, b, true); } @@ -1928,6 +1657,9 @@ compareMR(Context* c, unsigned size UNUSED, Assembler::Memory* a, { assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, b, b); + } encode(c, 0x3b, b->low, a, true); } @@ -2123,24 +1855,85 @@ class MyAssembler: public Assembler { } } - virtual void getTargets(BinaryOperation op, unsigned size, - Register* a, Register* b, bool* syncStack) + virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, + uint64_t* registerMask, uintptr_t* procedure) { - a->low = NoRegister; - a->high = NoRegister; - b->low = NoRegister; - b->high = NoRegister; - *syncStack = false; + if (op == Negate and BytesPerWord == 4 and size == 8) { + *typeMask = 1 << RegisterOperand; + *registerMask = (static_cast(1) << (rdx + 32)) + | (static_cast(1) << rax); + } else { + *typeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *registerMask = ~static_cast(0); + } + *procedure = 0; + } + + virtual void plan(UnaryOperation op, unsigned size, uint8_t* aTypeMask, + uint64_t* aRegisterMask, uint8_t* bTypeMask, + uint64_t* bRegisterMask, uintptr_t* procedure) + { + *aTypeMask = ~static_cast(0); + *aRegisterMask = ~static_cast(0); + + *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); + *bRegisterMask = ~static_cast(0); + + *procedure = 0; switch (op) { + case Move: + if (BytesPerWord == 4 and size == 1) { + const uint32_t mask + = (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx); + *aRegisterMask = (static_cast(mask) << 32) | mask; + *bRegisterMask = (static_cast(mask) << 32) | mask; + } + break; + + case Move4To8: + if (BytesPerWord == 4) { + const uint32_t mask = ~((1 << rax) | (1 << rdx)); + *aRegisterMask = (static_cast(mask) << 32) | mask; + *bRegisterMask = (static_cast(1) << (rdx + 32)) + | (static_cast(1) << rax); + } + break; + case Multiply: + if (BytesPerWord == 4 and size == 8) { + const uint32_t mask = ~((1 << rax) | (1 << rdx)); + *aRegisterMask = (static_cast(mask) << 32) | mask; + *bRegisterMask = (static_cast(1) << (rdx + 32)) | mask; + } + break; + case Divide: + if (BytesPerWord == 4 and size == 8) { + *procedure = reinterpret_cast(divideLong); + } else { + *aRegisterMask = ~((1 << rax) | (1 << rdx)); + *bRegisterMask = 1 << rax; + } + break; + case Remainder: if (BytesPerWord == 4 and size == 8) { - *syncStack = true; + *procedure = reinterpret_cast(moduloLong); + } else { + *aRegisterMask = ~((1 << rax) | (1 << rdx)); + *bRegisterMask = 1 << rax; } break; + case ShiftLeft: + case ShiftRight: + case UnsignedShiftRight: + *aRegisterMask = static_cast(1) << rcx; + const uint32_t mask = ~(1 << rcx); + *bRegisterMask = (static_cast(mask) << 32) | mask; + break; + default: break; } From efb30b225602b772db7e9f3ad17ec0e3073335ee Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 4 May 2008 14:55:34 -0600 Subject: [PATCH 077/121] progress towards more flexible register allocation in compiler --- src/compiler.cpp | 346 +++++++++++++++++++++++------------------------ 1 file changed, 171 insertions(+), 175 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 2af6534795..c3fa3b7f86 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -165,9 +165,6 @@ class Context { stackOffset(0), registers(static_cast (zone->allocate(sizeof(Register) * assembler->registerCount()))), - freeRegisterCount(assembler->registerCount() - 3), - freeRegisters(static_cast - (zone->allocate(sizeof(int) * freeRegisterCount))), firstConstant(0), lastConstant(0), constantCount(0), @@ -184,13 +181,6 @@ class Context { registers[assembler->stack()].reserved = true; registers[assembler->thread()].refCount = 1; registers[assembler->thread()].reserved = true; - - unsigned fri = 0; - for (int i = assembler->registerCount() - 1; i >= 0; --i) { - if (not registers[i].reserved) { - freeRegisters[fri++] = i; - } - } } System* system; @@ -202,8 +192,6 @@ class Context { unsigned logicalCodeLength; unsigned stackOffset; Register* registers; - unsigned freeRegisterCount; - int* freeRegisters; ConstantPoolNode* firstConstant; ConstantPoolNode* lastConstant; unsigned constantCount; @@ -557,7 +545,8 @@ registerSite(Context* c, int low, int high = NoRegister) } RegisterSite* -freeRegister(Context* c, unsigned size); +freeRegister(Context* c, unsigned size, + uint64_t mask = ~static_cast(0)); void increment(Context* c, int r) @@ -633,8 +622,58 @@ memorySite(Context* c, int base, int offset, int index, unsigned scale) MemorySite(base, offset, index, scale); } +bool +matchRegister(Context* c, Site* s, uint64_t mask) +{ + assert(c, s->type(c) == RegisterOperand); + + RegisterSite* r = static_cast(s); + return ((static_cast(1) << r->low) & mask) + and (r->high == NoRegister + or ((static_cast(1) << (r->high + 32)) & mask)); +} + +bool +match(Context* c, Site* s, uint8_t typeMask, uint64_t registerMask) +{ + OperandType t = s->type(c); + return ((1 << t) & typeMask) + and (t != RegisterOperand or matchRegister(c, s, registerMask)); +} + class AbstractSite: public Site { public: + AbstractSite(Value* value, uint8_t typeMask, uint64_t registerMask): + value(value), registerMask(registerMask), typeMask(typeMask) + { } + + virtual Site* readTarget(Context* c, Read* r, Event*) { + if (value) { + Site* s = targetOrNull(c, value, event); + if (s and match(c, s, typeMask, registerMask)) { + return s; + } + } + + Site* site = 0; + unsigned copyCost = 0xFFFFFFFF; + for (Site* s = r->value->sites; s; s = s->next) { + if (match(c, s, typeMask, registerMask)) { + unsigned v = s->copyCost(c, 0); + if (v < copyCost) { + site = s; + copyCost = v; + } + } + } + + if (site) { + return site; + } else { + return freeRegister(c, r->size, registerMask); + } + } + virtual unsigned copyCost(Context* c, Site*) { abort(c); } @@ -650,8 +689,27 @@ class AbstractSite: public Site { virtual Assembler::Operand* asAssemblerOperand(Context* c) { abort(c); } + + Value* value; + uint64_t registerMask; + uint8_t typeMask; }; +AbstractSite* +abstractSite(Context* c, Value* v = 0, + uint8_t typeMask = ~static_cast(0), + uint64_t registerMask = ~static_cast(0)) +{ + return new (c->zone->allocate(sizeof(AbstractSite))) + AbstractSite(v, typeMask, registerMask); +} + +AbstractSite* +anyRegisterSite(Context* c) +{ + return abstractSite(c, 0, 1 << RegisterOperand, ~static_cast(0)); +} + Site* targetOrNull(Context* c, Read* r, Event* event) { @@ -714,92 +772,6 @@ targetOrRegister(Context* c, unsigned size, Value* v, Event* event) } } -class ValueSite: public AbstractSite { - public: - ValueSite(Value* value): value(value) { } - - virtual Site* readTarget(Context* c, Read* r, Event* event) { - Site* s = targetOrNull(c, value, event); - if (s and s->type(c) == RegisterOperand) { - return s; - } else { - for (Site* s = r->value->sites; s; s = s->next) { - if (s->type(c) == RegisterOperand) { - return s; - } - } - return freeRegister(c, r->size); - } - } - - Value* value; -}; - -ValueSite* -valueSite(Context* c, Value* v) -{ - return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v); -} - -class MoveSite: public AbstractSite { - public: - MoveSite(Value* value): value(value) { } - - virtual Site* readTarget(Context* c, Read* read, Event* event) { - if (event->next == read->event) { - return targetOrNull(c, value, event); - } else { - return 0; - } - } - - Value* value; -}; - -MoveSite* -moveSite(Context* c, Value* v) -{ - return new (c->zone->allocate(sizeof(MoveSite))) MoveSite(v); -} - -class AnyRegisterSite: public AbstractSite { - public: - virtual Site* readTarget(Context* c, Read* r, Event*) { - for (Site* s = r->value->sites; s; s = s->next) { - if (s->type(c) == RegisterOperand) { - return s; - } - } - return freeRegister(c, r->size); - } -}; - -AnyRegisterSite* -anyRegisterSite(Context* c) -{ - return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite(); -} - -class ConstantOrRegisterSite: public AbstractSite { - public: - virtual Site* readTarget(Context* c, Read* r, Event*) { - for (Site* s = r->value->sites; s; s = s->next) { - OperandType t = s->type(c); - if (t == ConstantOperand or t == RegisterOperand) { - return s; - } - } - return freeRegister(c, r->size); - } -}; - -ConstantOrRegisterSite* -constantOrRegisterSite(Context* c) -{ - return new (c->zone->allocate(sizeof(ConstantOrRegisterSite))) - ConstantOrRegisterSite(); -} - Site* pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) { @@ -1214,15 +1186,9 @@ appendReturn(Context* c, unsigned size, Value* value) class MoveEvent: public Event { public: MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src, - Value* dst): + Value* dst, Site* srcTarget): Event(c), type(type), size(size), src(src), dst(dst) { - Site* target; - if (type == Move and size >= BytesPerWord) { - target = moveSite(c, dst); - } else { - target = 0; - } addRead(c, src, size, target); } @@ -1274,8 +1240,26 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, fprintf(stderr, "appendMove\n"); } + Site* target; + if (type == Move and size >= BytesPerWord) { + target = moveSite(c, dst); + } else { + target = 0; + } + + AbstractSite* srcTarget = abstractSite(c, dst); + AbstractSite* dstTarget = abstractSite(c); + uintptr_t procedure; + + c->assembler->plan(type, size, + &(srcTarget->typeMask), &(srcTarget->registerMask), + &(dstTarget->typeMask), &(dstTarget->registerMask), + &procedure); + + assert(c, procedure == 0); // todo + new (c->zone->allocate(sizeof(MoveEvent))) - MoveEvent(c, type, size, src, dst); + MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); } class CompareEvent: public Event { @@ -1328,20 +1312,13 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) class CombineEvent: public Event { public: CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first, - Value* second, Value* result, Assembler::Register* r1, - Assembler::Register* r2): + Value* second, Value* result, Site* firstTarget, + Site* secondTarget): Event(c), type(type), size(size), first(first), second(second), result(result) { - addRead(c, first, size, - r1->low == NoRegister ? - constantOrRegisterSite(c) : - static_cast(registerSite(c, r1->low, r1->high))); - - addRead(c, second, size, - r2->low == NoRegister ? - valueSite(c, result) : - static_cast(registerSite(c, r2->low, r2->high))); + addRead(c, first, size, firstTarget); + addRead(c, second, size, secondTarget); } virtual void compile(Context* c) { @@ -1376,30 +1353,45 @@ void appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Value* second, Value* result) { - Assembler::Register r1(NoRegister); - Assembler::Register r2(NoRegister); - bool syncStack; - c->assembler->getTargets(type, size, &r1, &r2, &syncStack); + AbstractSite* firstTarget = abstractSite(c); + AbstractSite* secondTarget = abstractSite(c, result); + uintptr_t procedure; - if (syncStack) { - appendStackSync(c); + c->assembler->plan(type, size, + &(firstTarget->typeMask), &(firstTarget->registerMask), + &(secondTarget->typeMask), &(secondTarget->registerMask), + &procedure); + + if (procedure) { + Stack* oldStack = c.state->stack; + + ::push(&c, size, second); + ::push(&c, size, first); + + Stack* argumentStack = c.state->stack; + c.state->stack = oldStack; + + Value* result = value(c); + appendCall(&c, constant(c, procedure), Compiler::Indirect, + 0, result, size, argumentStack, 2); + } else { + if (DebugAppend) { + fprintf(stderr, "appendCombine\n"); + } + + new (c->zone->allocate(sizeof(CombineEvent))) + CombineEvent(c, type, size, first, second, result, firstTarget, + secondTarget); } - - if (DebugAppend) { - fprintf(stderr, "appendCombine\n"); - } - - new (c->zone->allocate(sizeof(CombineEvent))) - CombineEvent(c, type, size, first, second, result, &r1, &r2); } class TranslateEvent: public Event { public: TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value, - Value* result): + Value* result, Site* target): Event(c), type(type), size(size), value(value), result(result) { - addRead(c, value, size, valueSite(c, result)); + addRead(c, value, size, target); } virtual void compile(Context* c) { @@ -1433,8 +1425,16 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, fprintf(stderr, "appendTranslate\n"); } + AbstractSite* target = abstractSite(c, result); + uintptr_t procedure; + + c->assembler->plan + (type, size, &(target->typeMask), &(target->registerMask), &procedure); + + assert(c, procedure == 0); // todo + new (c->zone->allocate(sizeof(TranslateEvent))) - TranslateEvent(c, type, size, value, result); + TranslateEvent(c, type, size, value, result, target); } class MemoryEvent: public Event { @@ -1466,6 +1466,10 @@ class MemoryEvent: public Event { nextRead(c, base); if (index) { nextRead(c, index); + + if (BytesPerWord == 8) { + apply(c, Move4To8, 0, index->source, index->source); + } } result->target = memorySite @@ -1895,38 +1899,6 @@ updateJunctions(Context* c) } } -int -freeRegisterExcept(Context* c, int except) -{ - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0 - and (not used(c, i))) - { - return i; - } - } - - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0 - and (not usedExclusively(c, i))) - { - return i; - } - } - - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (i != except - and c->registers[i].refCount == 0) - { - return i; - } - } - - abort(c); -} - void visit(Context* c, unsigned logicalIp) { @@ -1940,21 +1912,45 @@ visit(Context* c, unsigned logicalIp) } int -freeRegister(Context* c) +freeRegister2(Context* c, int32_t mask) { - int r = freeRegisterExcept(c, NoRegister); -// fprintf(stderr, "free reg: %d\n", r); - return r; + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (((1 << i) & mask) + and c->registers[i].refCount == 0 + and (not used(c, i))) + { + return i; + } + } + + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (((1 << i) & mask) + and c->registers[i].refCount == 0 + and (not usedExclusively(c, i))) + { + return i; + } + } + + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (((1 << i) & mask) + and not c->registers[i].reserved) + { + return i; + } + } + + abort(c); } RegisterSite* -freeRegister(Context* c, unsigned size) +freeRegister(Context* c, unsigned size, uint64_t mask) { if (BytesPerWord == 4 and size == 8) { - int low = freeRegister(c); - return registerSite(c, low, freeRegisterExcept(c, low)); + int low = freeRegister2(c, mask); + return registerSite(c, low, freeRegister2(c, (mask >> 32) & ~(1 << low))); } else { - return registerSite(c, freeRegister(c)); + return registerSite(c, freeRegister2(c, mask)); } } @@ -1963,7 +1959,7 @@ class Client: public Assembler::Client { Client(Context* c): c(c) { } virtual int acquireTemporary() { - int r = freeRegisterExcept(c, NoRegister); + int r = freeRegister2(c, ~static_cast(0)); save(r); increment(c, r); return r; From f1809897bd11a41cae7d45bffcda18e4c8b0abbd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 6 May 2008 15:13:02 -0600 Subject: [PATCH 078/121] fix build --- src/assembler.h | 9 +- src/compile.cpp | 131 +++++++++++---------------- src/compiler.cpp | 227 +++++++++++++++++++++++------------------------ src/compiler.h | 5 +- src/x86.cpp | 8 +- 5 files changed, 177 insertions(+), 203 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 226bc31351..ebbc4a487b 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -134,7 +134,8 @@ class Assembler { public: virtual ~Client() { } - virtual int acquireTemporary() = 0; + virtual int acquireTemporary + (uint32_t mask = ~static_cast(0)) = 0; virtual void releaseTemporary(int r) = 0; virtual void save(int r) = 0; @@ -157,11 +158,11 @@ class Assembler { virtual int argumentRegister(unsigned index) = 0; virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, - uint64_t* registerMask, uintptr_t* procedure); + uint64_t* registerMask, uintptr_t* procedure) = 0; - virtual void plan(UnaryOperation op, unsigned size, uint8_t* aTypeMask, + virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask, uint64_t* aRegisterMask, uint8_t* bTypeMask, - uint64_t* bRegisterMask, uintptr_t* procedure); + uint64_t* bRegisterMask, uintptr_t* procedure) = 0; virtual void apply(Operation op) = 0; diff --git a/src/compile.cpp b/src/compile.cpp index b0721925a2..fc7590a10a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = false; +const bool Verbose = true; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -463,9 +463,8 @@ class Context { thread(t), zone(t->m->system, t->m->heap, 16 * 1024), assembler(makeAssembler(t->m->system, t->m->heap, &zone)), - compiler(makeCompiler(t->m->system, assembler, &zone)), + compiler(makeCompiler(t->m->system, assembler, &zone, indirection)), method(method), - indirection(indirection), objectPool(0), traceLog(0), traceLogCount(0), @@ -481,7 +480,6 @@ class Context { assembler(makeAssembler(t->m->system, t->m->heap, &zone)), compiler(0), method(0), - indirection(0), objectPool(0), traceLog(0), traceLogCount(0), @@ -501,7 +499,6 @@ class Context { Assembler* assembler; Compiler* compiler; object method; - void* indirection; PoolElement* objectPool; TraceElement* traceLog; unsigned traceLogCount; @@ -1637,7 +1634,6 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) (reinterpret_cast (&singletonBody(t, nativeCompiled(t), 0))), 0, - 0, frame->trace(target, false), rSize, 0); @@ -1646,7 +1642,6 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) (c->constant (reinterpret_cast (&singletonBody(t, defaultCompiled(t), 0))), - 0, Compiler::Aligned, frame->trace(target, false), rSize, @@ -1657,7 +1652,6 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) (reinterpret_cast (&singletonBody(t, methodCompiled(t, target), 0))), 0, - 0, frame->trace(0, false), rSize, 0); @@ -1687,8 +1681,7 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) } c->call(c->constant(function), - frame->context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 2, c->thread(), lock); @@ -1756,8 +1749,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->call (c->constant(reinterpret_cast(gcIfNecessary)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 1, c->thread()); @@ -1806,8 +1798,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), - context->indirection, - Compiler::NoReturn, + Compiler::NoReturn | Compiler::Indirect, frame->trace(0, false), 0, 3, c->thread(), array, index); @@ -1923,8 +1914,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), - context->indirection, - Compiler::NoReturn, + Compiler::NoReturn | Compiler::Indirect, frame->trace(0, false), 0, 3, c->thread(), array, index); @@ -1950,8 +1940,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case aastore: { c->call (c->constant(reinterpret_cast(setMaybeNull)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 4, c->thread(), array, @@ -1983,8 +1972,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case aastore: { c->call (c->constant(reinterpret_cast(setMaybeNull)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 4, c->thread(), array, @@ -2050,8 +2038,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call (c->constant(reinterpret_cast(makeBlankObjectArray)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(class_), length)); @@ -2091,8 +2078,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case athrow: { c->call (c->constant(reinterpret_cast(throw_)), - context->indirection, - Compiler::NoReturn, + Compiler::NoReturn | Compiler::Indirect, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); @@ -2113,8 +2099,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->call (c->constant(reinterpret_cast(checkCast)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 3, c->thread(), frame->append(class_), instance); @@ -2124,21 +2109,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(doubleToFloat)), - context->indirection, 0, 0, 4, 1, frame->popLong())); + Compiler::Indirect, 0, 4, 1, frame->popLong())); } break; case d2i: { frame->pushInt (c->call (c->constant(reinterpret_cast(doubleToInt)), - context->indirection, 0, 0, 4, 1, frame->popLong())); + Compiler::Indirect, 0, 4, 1, frame->popLong())); } break; case d2l: { frame->pushLong (c->call (c->constant(reinterpret_cast(doubleToLong)), - context->indirection, 0, 0, 8, 1, frame->popLong())); + Compiler::Indirect, 0, 8, 1, frame->popLong())); } break; case dadd: { @@ -2148,7 +2133,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(addDouble)), - context->indirection, 0, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); } break; case dcmpg: { @@ -2158,7 +2143,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesG)), - context->indirection, 0, 0, 4, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 4, 4, 0, a, 0, b)); } break; case dcmpl: { @@ -2168,7 +2153,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesL)), - context->indirection, 0, 0, 4, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 4, 4, 0, a, 0, b)); } break; case dconst_0: @@ -2186,7 +2171,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(divideDouble)), - context->indirection, 0, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); } break; case dmul: { @@ -2196,14 +2181,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(multiplyDouble)), - context->indirection, 0, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); } break; case dneg: { frame->pushLong (c->call (c->constant(reinterpret_cast(negateDouble)), - context->indirection, 0, 0, 8, 2, 0, frame->popLong())); + Compiler::Indirect, 0, 8, 2, 0, frame->popLong())); } break; case vm::drem: { @@ -2213,7 +2198,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(moduloDouble)), - context->indirection, 0, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); } break; case dsub: { @@ -2223,7 +2208,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(subtractDouble)), - context->indirection, 0, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); } break; case dup: @@ -2254,21 +2239,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(floatToDouble)), - context->indirection, 0, 0, 8, 1, frame->popInt())); + Compiler::Indirect, 0, 8, 1, frame->popInt())); } break; case f2i: { frame->pushInt (c->call (c->constant(reinterpret_cast(floatToInt)), - context->indirection, 0, 0, 4, 1, frame->popInt())); + Compiler::Indirect, 0, 4, 1, frame->popInt())); } break; case f2l: { frame->pushLong (c->call (c->constant(reinterpret_cast(floatToLong)), - context->indirection, 0, 0, 8, 1, frame->popInt())); + Compiler::Indirect, 0, 8, 1, frame->popInt())); } break; case fadd: { @@ -2278,7 +2263,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(addFloat)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case fcmpg: { @@ -2288,7 +2273,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareFloatsG)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case fcmpl: { @@ -2298,7 +2283,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareFloatsL)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case fconst_0: @@ -2320,7 +2305,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(divideFloat)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case fmul: { @@ -2330,14 +2315,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(multiplyFloat)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case fneg: { frame->pushInt (c->call (c->constant(reinterpret_cast(negateFloat)), - context->indirection, 0, 0, 4, 1, frame->popInt())); + Compiler::Indirect, 0, 4, 1, frame->popInt())); } break; case vm::frem: { @@ -2347,7 +2332,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(moduloFloat)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case fsub: { @@ -2357,7 +2342,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(subtractFloat)), - context->indirection, 0, 0, 4, 2, a, b)); + Compiler::Indirect, 0, 4, 2, a, b)); } break; case getfield: @@ -2375,8 +2360,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, { c->call (c->constant(reinterpret_cast(tryInitClass)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 2, c->thread(), frame->append(fieldClass(t, field))); @@ -2455,14 +2439,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(intToDouble)), - context->indirection, 0, 0, 8, 1, frame->popInt())); + Compiler::Indirect, 0, 8, 1, frame->popInt())); } break; case i2f: { frame->pushInt (c->call (c->constant(reinterpret_cast(intToFloat)), - context->indirection, 0, 0, 4, 1, frame->popInt())); + Compiler::Indirect, 0, 4, 1, frame->popInt())); } break; case i2l: @@ -2689,7 +2673,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(instanceOf)), - context->indirection, 0, 0, 4, + Compiler::Indirect, 0, 4, 3, c->thread(), frame->append(class_), frame->popObject())); } break; @@ -2710,14 +2694,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (c->call (c->constant (reinterpret_cast(findInterfaceMethodFromInstance)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(target), c->peek(BytesPerWord, instance)), 0, - 0, frame->trace(target, true), rSize, 0); @@ -2773,7 +2755,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (BytesPerWord, c->constant(PointerMask), c->memory(instance, 0, 0, 1)), offset, 0, 1), 0, - 0, frame->trace(target, true), rSize, 0); @@ -2885,14 +2866,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(longToDouble)), - context->indirection, 0, 0, 8, 1, frame->popLong())); + Compiler::Indirect, 0, 8, 1, frame->popLong())); } break; case l2f: { frame->pushInt (c->call (c->constant(reinterpret_cast(longToFloat)), - context->indirection, 0, 0, 4, 1, frame->popLong())); + Compiler::Indirect, 0, 4, 1, frame->popLong())); } break; case l2i: @@ -3070,7 +3051,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jmp (c->call (c->constant(reinterpret_cast(lookUpAddress)), - context->indirection, 0, 0, BytesPerWord, + Compiler::Indirect, 0, BytesPerWord, 4, key, start, c->constant(pairCount), default_)); for (int32_t i = 0; i < pairCount; ++i) { @@ -3157,15 +3138,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case monitorenter: { c->call (c->constant(reinterpret_cast(acquireMonitorForObject)), - context->indirection, - 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); + Compiler::Indirect, + frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case monitorexit: { c->call (c->constant(reinterpret_cast(releaseMonitorForObject)), - context->indirection, - 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); + Compiler::Indirect, + frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case multianewarray: { @@ -3178,8 +3159,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* result = c->call (c->constant(reinterpret_cast(makeMultidimensionalArray)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), BytesPerWord, 4, c->thread(), frame->append(class_), @@ -3199,8 +3179,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call (c->constant(reinterpret_cast(makeNewWeakReference)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), BytesPerWord, 2, c->thread(), frame->append(class_))); @@ -3208,8 +3187,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call (c->constant(reinterpret_cast(makeNew)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), BytesPerWord, 2, c->thread(), frame->append(class_))); @@ -3261,8 +3239,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call (c->constant(reinterpret_cast(makeBlankArray)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), BytesPerWord, 3, c->thread(), c->constant(reinterpret_cast(constructor)), @@ -3294,8 +3271,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, { c->call (c->constant(reinterpret_cast(tryInitClass)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 2, c->thread(), frame->append(fieldClass(t, field))); @@ -3360,15 +3336,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (instruction == putfield) { c->call (c->constant(reinterpret_cast(setMaybeNull)), - context->indirection, - 0, + Compiler::Indirect, frame->trace(0, false), 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } else { c->call (c->constant(reinterpret_cast(set)), - context->indirection, 0, 0, 0, + Compiler::Indirect, 0, 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } break; @@ -3872,7 +3847,7 @@ finish(MyThread* t, Context* context) } // for debugging: - if (false and + if (//false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), diff --git a/src/compiler.cpp b/src/compiler.cpp index c3fa3b7f86..ed2a80644e 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -154,10 +154,11 @@ class Value: public Compiler::Operand { class Context { public: - Context(System* system, Assembler* assembler, Zone* zone): + Context(System* system, Assembler* assembler, Zone* zone, void* indirection): system(system), assembler(assembler), zone(zone), + indirection(indirection), logicalIp(-1), state(new (zone->allocate(sizeof(State))) State(0, 0)), logicalCode(0), @@ -186,6 +187,7 @@ class Context { System* system; Assembler* assembler; Zone* zone; + void* indirection; int logicalIp; State* state; LogicalInstruction* logicalCode; @@ -628,9 +630,9 @@ matchRegister(Context* c, Site* s, uint64_t mask) assert(c, s->type(c) == RegisterOperand); RegisterSite* r = static_cast(s); - return ((static_cast(1) << r->low) & mask) - and (r->high == NoRegister - or ((static_cast(1) << (r->high + 32)) & mask)); + return ((static_cast(1) << r->register_.low) & mask) + and (r->register_.high == NoRegister + or ((static_cast(1) << (r->register_.high + 32)) & mask)); } bool @@ -641,75 +643,6 @@ match(Context* c, Site* s, uint8_t typeMask, uint64_t registerMask) and (t != RegisterOperand or matchRegister(c, s, registerMask)); } -class AbstractSite: public Site { - public: - AbstractSite(Value* value, uint8_t typeMask, uint64_t registerMask): - value(value), registerMask(registerMask), typeMask(typeMask) - { } - - virtual Site* readTarget(Context* c, Read* r, Event*) { - if (value) { - Site* s = targetOrNull(c, value, event); - if (s and match(c, s, typeMask, registerMask)) { - return s; - } - } - - Site* site = 0; - unsigned copyCost = 0xFFFFFFFF; - for (Site* s = r->value->sites; s; s = s->next) { - if (match(c, s, typeMask, registerMask)) { - unsigned v = s->copyCost(c, 0); - if (v < copyCost) { - site = s; - copyCost = v; - } - } - } - - if (site) { - return site; - } else { - return freeRegister(c, r->size, registerMask); - } - } - - virtual unsigned copyCost(Context* c, Site*) { - abort(c); - } - - virtual void copyTo(Context* c, unsigned, Site*) { - abort(c); - } - - virtual OperandType type(Context* c) { - abort(c); - } - - virtual Assembler::Operand* asAssemblerOperand(Context* c) { - abort(c); - } - - Value* value; - uint64_t registerMask; - uint8_t typeMask; -}; - -AbstractSite* -abstractSite(Context* c, Value* v = 0, - uint8_t typeMask = ~static_cast(0), - uint64_t registerMask = ~static_cast(0)) -{ - return new (c->zone->allocate(sizeof(AbstractSite))) - AbstractSite(v, typeMask, registerMask); -} - -AbstractSite* -anyRegisterSite(Context* c) -{ - return abstractSite(c, 0, 1 << RegisterOperand, ~static_cast(0)); -} - Site* targetOrNull(Context* c, Read* r, Event* event) { @@ -735,6 +668,78 @@ targetOrNull(Context* c, Value* v, Event* event) } } +class AbstractSite: public Site { + public: + virtual unsigned copyCost(Context* c, Site*) { + abort(c); + } + + virtual void copyTo(Context* c, unsigned, Site*) { + abort(c); + } + + virtual OperandType type(Context* c) { + abort(c); + } + + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + abort(c); + } +}; + +class VirtualSite: public AbstractSite { + public: + VirtualSite(Value* value, uint8_t typeMask, uint64_t registerMask): + value(value), registerMask(registerMask), typeMask(typeMask) + { } + + virtual Site* readTarget(Context* c, Read* r, Event* e) { + if (value) { + Site* s = targetOrNull(c, value, e); + if (s and match(c, s, typeMask, registerMask)) { + return s; + } + } + + Site* site = 0; + unsigned copyCost = 0xFFFFFFFF; + for (Site* s = r->value->sites; s; s = s->next) { + if (match(c, s, typeMask, registerMask)) { + unsigned v = s->copyCost(c, 0); + if (v < copyCost) { + site = s; + copyCost = v; + } + } + } + + if (site) { + return site; + } else { + return freeRegister(c, r->size, registerMask); + } + } + + Value* value; + uint64_t registerMask; + uint8_t typeMask; +}; + +VirtualSite* +virtualSite(Context* c, Value* v = 0, + uint8_t typeMask = ~static_cast(0), + uint64_t registerMask = ~static_cast(0)) +{ + return new (c->zone->allocate(sizeof(VirtualSite))) + VirtualSite(v, typeMask, registerMask); +} + +VirtualSite* +anyRegisterSite(Context* c) +{ + return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast(0)); +} + bool used(Context* c, int r) { @@ -1032,12 +1037,11 @@ ignore(Context* c, unsigned count) class CallEvent: public Event { public: - CallEvent(Context* c, Value* address, void* indirection, unsigned flags, + CallEvent(Context* c, Value* address, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, Stack* argumentStack, unsigned argumentCount): Event(c), address(address), - indirection(indirection), traceHandler(traceHandler), result(result), flags(flags), @@ -1066,7 +1070,8 @@ class CallEvent: public Event { } addRead(c, address, BytesPerWord, - (indirection ? registerSite(c, c->assembler->returnLow()) : 0)); + ((flags & Compiler::Indirect) ? + registerSite(c, c->assembler->returnLow()) : 0)); } virtual void compile(Context* c) { @@ -1077,9 +1082,9 @@ class CallEvent: public Event { pushNow(c, stack); UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); - if (indirection) { + if (flags & Compiler::Indirect) { apply(c, type, BytesPerWord, - constantSite(c, reinterpret_cast(indirection))); + constantSite(c, reinterpret_cast(c->indirection))); } else { apply(c, type, BytesPerWord, address->source); } @@ -1117,7 +1122,6 @@ class CallEvent: public Event { } Value* address; - void* indirection; TraceHandler* traceHandler; Value* result; unsigned flags; @@ -1126,7 +1130,7 @@ class CallEvent: public Event { }; void -appendCall(Context* c, Value* address, void* indirection, unsigned flags, +appendCall(Context* c, Value* address, unsigned flags, TraceHandler* traceHandler, Value* result, unsigned resultSize, Stack* argumentStack, unsigned argumentCount) { @@ -1135,7 +1139,7 @@ appendCall(Context* c, Value* address, void* indirection, unsigned flags, } new (c->zone->allocate(sizeof(CallEvent))) - CallEvent(c, address, indirection, flags, traceHandler, result, + CallEvent(c, address, flags, traceHandler, result, resultSize, argumentStack, argumentCount); } @@ -1189,7 +1193,7 @@ class MoveEvent: public Event { Value* dst, Site* srcTarget): Event(c), type(type), size(size), src(src), dst(dst) { - addRead(c, src, size, target); + addRead(c, src, size, srcTarget); } virtual void compile(Context* c) { @@ -1240,15 +1244,8 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, fprintf(stderr, "appendMove\n"); } - Site* target; - if (type == Move and size >= BytesPerWord) { - target = moveSite(c, dst); - } else { - target = 0; - } - - AbstractSite* srcTarget = abstractSite(c, dst); - AbstractSite* dstTarget = abstractSite(c); + VirtualSite* srcTarget = virtualSite(c, dst); + VirtualSite* dstTarget = virtualSite(c); uintptr_t procedure; c->assembler->plan(type, size, @@ -1259,7 +1256,7 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, assert(c, procedure == 0); // todo new (c->zone->allocate(sizeof(MoveEvent))) - MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); + MoveEvent(c, type, size, src, dst, srcTarget); } class CompareEvent: public Event { @@ -1349,12 +1346,18 @@ class CombineEvent: public Event { void appendStackSync(Context* c); +Value* +value(Context* c, Site* site = 0, Site* target = 0) +{ + return new (c->zone->allocate(sizeof(Value))) Value(site, target); +} + void appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Value* second, Value* result) { - AbstractSite* firstTarget = abstractSite(c); - AbstractSite* secondTarget = abstractSite(c, result); + VirtualSite* firstTarget = virtualSite(c); + VirtualSite* secondTarget = virtualSite(c, result); uintptr_t procedure; c->assembler->plan(type, size, @@ -1363,16 +1366,16 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, &procedure); if (procedure) { - Stack* oldStack = c.state->stack; + Stack* oldStack = c->state->stack; - ::push(&c, size, second); - ::push(&c, size, first); + ::push(c, size, second); + ::push(c, size, first); - Stack* argumentStack = c.state->stack; - c.state->stack = oldStack; + Stack* argumentStack = c->state->stack; + c->state->stack = oldStack; Value* result = value(c); - appendCall(&c, constant(c, procedure), Compiler::Indirect, + appendCall(c, value(c, constantSite(c, procedure)), Compiler::Indirect, 0, result, size, argumentStack, 2); } else { if (DebugAppend) { @@ -1425,7 +1428,7 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, fprintf(stderr, "appendTranslate\n"); } - AbstractSite* target = abstractSite(c, result); + VirtualSite* target = virtualSite(c, result); uintptr_t procedure; c->assembler->plan @@ -1503,12 +1506,6 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) Stack(value, size, index, next); } -Value* -value(Context* c, Site* site = 0, Site* target = 0) -{ - return new (c->zone->allocate(sizeof(Value))) Value(site, target); -} - void resetStack(Context* c) { @@ -1958,8 +1955,8 @@ class Client: public Assembler::Client { public: Client(Context* c): c(c) { } - virtual int acquireTemporary() { - int r = freeRegister2(c, ~static_cast(0)); + virtual int acquireTemporary(uint32_t mask) { + int r = freeRegister2(c, mask); save(r); increment(c, r); return r; @@ -1991,8 +1988,8 @@ class Client: public Assembler::Client { class MyCompiler: public Compiler { public: - MyCompiler(System* s, Assembler* assembler, Zone* zone): - c(s, assembler, zone), client(&c) + MyCompiler(System* s, Assembler* assembler, Zone* zone, void* indirection): + c(s, assembler, zone, indirection), client(&c) { assembler->setClient(&client); } @@ -2194,7 +2191,6 @@ class MyCompiler: public Compiler { } virtual Operand* call(Operand* address, - void* indirection, unsigned flags, TraceHandler* traceHandler, unsigned resultSize, @@ -2240,7 +2236,7 @@ class MyCompiler: public Compiler { c.state->stack = oldStack; Value* result = value(&c); - appendCall(&c, static_cast(address), indirection, flags, + appendCall(&c, static_cast(address), flags, traceHandler, result, resultSize, argumentStack, index); @@ -2425,10 +2421,11 @@ class MyCompiler: public Compiler { namespace vm { Compiler* -makeCompiler(System* system, Assembler* assembler, Zone* zone) +makeCompiler(System* system, Assembler* assembler, Zone* zone, + void* indirection) { return new (zone->allocate(sizeof(MyCompiler))) - MyCompiler(system, assembler, zone); + MyCompiler(system, assembler, zone, indirection); } } // namespace vm diff --git a/src/compiler.h b/src/compiler.h index d17396a484..7bb4186b56 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -21,6 +21,7 @@ class Compiler { public: static const unsigned Aligned = 1 << 0; static const unsigned NoReturn = 1 << 1; + static const unsigned Indirect = 1 << 2; class Operand { }; @@ -67,7 +68,6 @@ class Compiler { virtual Operand* peek(unsigned size, unsigned index) = 0; virtual Operand* call(Operand* address, - void* indirection, unsigned flags, TraceHandler* traceHandler, unsigned resultSize, @@ -109,7 +109,8 @@ class Compiler { }; Compiler* -makeCompiler(System* system, Assembler* assembler, Zone* zone); +makeCompiler(System* system, Assembler* assembler, Zone* zone, + void* indirection); } // namespace vm diff --git a/src/x86.cpp b/src/x86.cpp index 8b9f025659..e00ab4107b 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1089,7 +1089,7 @@ multiplyCR(Context* c, unsigned size, Assembler::Constant* a, c->client->acquireTemporary(mask)); moveCR(c, size, a, &tmp); - remainderRR(c, size, &tmp, b); + multiplyRR(c, size, &tmp, b); c->client->releaseTemporary(tmp.low); c->client->releaseTemporary(tmp.high); @@ -1869,7 +1869,7 @@ class MyAssembler: public Assembler { *procedure = 0; } - virtual void plan(UnaryOperation op, unsigned size, uint8_t* aTypeMask, + virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask, uint64_t* aRegisterMask, uint8_t* bTypeMask, uint64_t* bRegisterMask, uintptr_t* procedure) { @@ -1928,11 +1928,11 @@ class MyAssembler: public Assembler { case ShiftLeft: case ShiftRight: - case UnsignedShiftRight: + case UnsignedShiftRight: { *aRegisterMask = static_cast(1) << rcx; const uint32_t mask = ~(1 << rcx); *bRegisterMask = (static_cast(mask) << 32) | mask; - break; + } break; default: break; From a40635fdba2c29e298a7d2c36540c2aa898c1541 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 12 May 2008 07:54:47 -0600 Subject: [PATCH 079/121] rework register allocation to be more flexible --- src/assembler.h | 1 + src/compiler.cpp | 498 +++++++++++++++++++++++++++-------------------- 2 files changed, 292 insertions(+), 207 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index ebbc4a487b..44c127db05 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -34,6 +34,7 @@ enum BinaryOperation { Move, MoveZ, Move4To8, + Swap, Compare, Add, Subtract, diff --git a/src/compiler.cpp b/src/compiler.cpp index ed2a80644e..afd895d1f2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -42,14 +42,18 @@ class Site { virtual ~Site() { } - virtual Site* readTarget(Context*, Read*, Event*) { return this; } + virtual Site* readTarget(Context*, Read*) { return this; } virtual unsigned copyCost(Context*, Site*) = 0; - virtual bool tryAcquire(Context*, Stack*, unsigned, Value*) { return true; } + virtual void acquire(Context*, Stack*, unsigned, Value*) { } virtual void release(Context*) { } + virtual void freeze(Context*) { } + + virtual void thaw(Context*) { } + virtual OperandType type(Context*) = 0; virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; @@ -96,10 +100,17 @@ class LogicalInstruction { class Register { public: + Register(int number): + value(0), site(0), number(number), size(0), refCount(0), freezeCount(0), + reserved(false), pushed(false) + { } + Value* value; Site* site; + int number; unsigned size; unsigned refCount; + unsigned freezeCount; bool reserved; bool pushed; }; @@ -164,8 +175,9 @@ class Context { logicalCode(0), logicalCodeLength(0), stackOffset(0), - registers(static_cast - (zone->allocate(sizeof(Register) * assembler->registerCount()))), + registers + (static_cast + (zone->allocate(sizeof(Register*) * assembler->registerCount()))), firstConstant(0), lastConstant(0), constantCount(0), @@ -174,14 +186,13 @@ class Context { machineCode(0), stackReset(false) { - memset(registers, 0, sizeof(Register) * assembler->registerCount()); - - registers[assembler->base()].refCount = 1; - registers[assembler->base()].reserved = true; - registers[assembler->stack()].refCount = 1; - registers[assembler->stack()].reserved = true; - registers[assembler->thread()].refCount = 1; - registers[assembler->thread()].reserved = true; + for (unsigned i = 0; i < assembler->registerCount(); ++i) { + registers[i] = new (zone->allocate(sizeof(Register))) Register(i); + } + + registers[assembler->base()]->reserved = true; + registers[assembler->stack()]->reserved = true; + registers[assembler->thread()]->reserved = true; } System* system; @@ -193,7 +204,7 @@ class Context { LogicalInstruction* logicalCode; unsigned logicalCodeLength; unsigned stackOffset; - Register* registers; + Register** registers; ConstantPoolNode* firstConstant; ConstantPoolNode* lastConstant; unsigned constantCount; @@ -341,25 +352,15 @@ findSite(Context*, Value* v, Site* site) return false; } -bool -tryAddSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) -{ - if (not findSite(c, v, s)) { -// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), v); - if (s->tryAcquire(c, stack, size, v)) { - s->next = v->sites; - v->sites = s; - } else { - return false; - } - } - return true; -} - void addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { - expect(c, tryAddSite(c, stack, size, v, s)); + if (not findSite(c, v, s)) { +// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), v); + s->acquire(c, stack, size, v); + s->next = v->sites; + v->sites = s; + } } void @@ -475,25 +476,37 @@ addressSite(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); } -bool -tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, - Site* newSite); +Register* +acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, + Value* newValue, Site* newSite); void -release(Context* c, int r); +release(Context* c, Register* r); class RegisterSite: public Site { public: - RegisterSite(int low, int high): register_(low, high) { } + RegisterSite(uint64_t mask): + mask(mask), low(0), high(0), register_(NoRegister, NoRegister) + { } + + void sync(Context* c) { + assert(c, low); + + register_.low = low->number; + register_.high = (high? high->number : NoRegister); + } virtual unsigned copyCost(Context* c, Site* s) { + sync(c); + if (s and (this == s or (s->type(c) == RegisterOperand - and static_cast(s)->register_.low - == register_.low - and static_cast(s)->register_.high - == register_.high))) + and (static_cast(s)->mask + & (static_cast(1) << register_.low)) + and (register_.high == NoRegister + or (static_cast(s)->mask + & (static_cast(1) << (register_.high + 32))))))) { return 0; } else { @@ -501,36 +514,54 @@ class RegisterSite: public Site { } } - virtual bool tryAcquire(Context* c, Stack* stack, unsigned size, Value* v) { - if (::tryAcquire(c, register_.low, stack, size, v, this)) { - if (register_.high != NoRegister) { - if (::tryAcquire(c, register_.high, stack, size, v, this)) { - return true; - } else { - ::release(c, register_.low); - } - } else { - return true; - } + virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) { + low = ::acquire(c, mask, stack, size, v, this); + if (size > BytesPerWord) { + ++ low->freezeCount; + high = ::acquire(c, mask >> 32, stack, size, v, this); + -- low->freezeCount; } - return false; } virtual void release(Context* c) { - ::release(c, register_.low); - if (register_.high >= 0) { - ::release(c, register_.high); - } + assert(c, low); + + ::release(c, low); + if (high) { + ::release(c, high); + } + } + + virtual void freeze(Context* c) { + assert(c, low); + + ++ low->freezeCount; + if (high) { + ++ high->freezeCount; + } + } + + virtual void thaw(Context* c) { + assert(c, low); + + -- low->freezeCount; + if (high) { + -- high->freezeCount; + } } virtual OperandType type(Context*) { return RegisterOperand; } - virtual Assembler::Operand* asAssemblerOperand(Context*) { + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + sync(c); return ®ister_; } + uint64_t mask; + Register* low; + Register* high; Assembler::Register register_; }; @@ -542,41 +573,67 @@ registerSite(Context* c, int low, int high = NoRegister) assert(c, high == NoRegister or high < static_cast(c->assembler->registerCount())); + uint64_t mask; + if (high == NoRegister) { + mask = static_cast(1) << low; + } else { + mask = (static_cast(1) << (high + 32)) + | (static_cast(1) << low); + } return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(low, high); + RegisterSite(mask); } RegisterSite* -freeRegister(Context* c, unsigned size, - uint64_t mask = ~static_cast(0)); - -void -increment(Context* c, int r) +freeRegister(Context* c, uint64_t mask = ~static_cast(0)) { + return new (c->zone->allocate(sizeof(RegisterSite))) + RegisterSite(mask); +} + +Register* +increment(Context* c, int i) +{ + Register* r = c->registers[i]; + if (DebugRegisters) { - fprintf(stderr, "increment %d to %d\n", r, c->registers[r].refCount + 1); + fprintf(stderr, "increment %d to %d\n", r->number, r->refCount + 1); } - ++ c->registers[r].refCount; + + ++ r->refCount; + + return r; } void -decrement(Context* c, int r) +decrement(Context* c, Register* r) { + assert(c, r->refCount > 0); + if (DebugRegisters) { - fprintf(stderr, "decrement %d to %d\n", r, c->registers[r].refCount - 1); + fprintf(stderr, "decrement %d to %d\n", + r->number, r->refCount - 1); } - assert(c, c->registers[r].refCount > 0); - assert(c, c->registers[r].refCount > 1 or (not c->registers[r].reserved)); - -- c->registers[r].refCount; + + -- r->refCount; } class MemorySite: public Site { public: MemorySite(int base, int offset, int index, unsigned scale): - value(base, offset, index, scale) + base(0), index(0), value(base, offset, index, scale) { } + void sync(Context* c) { + assert(c, base); + + value.base = base->number; + value.index = (index? index->number : NoRegister); + } + virtual unsigned copyCost(Context* c, Site* s) { + sync(c); + if (s and (this == s or (s->type(c) == MemoryOperand @@ -591,18 +648,17 @@ class MemorySite: public Site { } } - virtual bool tryAcquire(Context* c, Stack*, unsigned, Value*) { - increment(c, value.base); + virtual void acquire(Context* c, Stack*, unsigned, Value*) { + base = increment(c, value.base); if (value.index != NoRegister) { - increment(c, value.index); + index = increment(c, value.index); } - return true; } virtual void release(Context* c) { - decrement(c, value.base); - if (value.index != NoRegister) { - decrement(c, value.index); + decrement(c, base); + if (index) { + decrement(c, index); } } @@ -610,10 +666,13 @@ class MemorySite: public Site { return MemoryOperand; } - virtual Assembler::Operand* asAssemblerOperand(Context*) { + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + sync(c); return &value; } + Register* base; + Register* index; Assembler::Memory value; }; @@ -644,25 +703,25 @@ match(Context* c, Site* s, uint8_t typeMask, uint64_t registerMask) } Site* -targetOrNull(Context* c, Read* r, Event* event) +targetOrNull(Context* c, Read* r) { Value* v = r->value; if (v->target) { return v->target; } else if (r->target) { - return r->target->readTarget(c, r, event); + return r->target->readTarget(c, r); } else { return 0; } } Site* -targetOrNull(Context* c, Value* v, Event* event) +targetOrNull(Context* c, Value* v) { if (v->target) { return v->target; } else if (v->reads and v->reads->target) { - return v->reads->target->readTarget(c, v->reads, event); + return v->reads->target->readTarget(c, v->reads); } else { return 0; } @@ -693,9 +752,9 @@ class VirtualSite: public AbstractSite { value(value), registerMask(registerMask), typeMask(typeMask) { } - virtual Site* readTarget(Context* c, Read* r, Event* e) { + virtual Site* readTarget(Context* c, Read* r) { if (value) { - Site* s = targetOrNull(c, value, e); + Site* s = targetOrNull(c, value); if (s and match(c, s, typeMask, registerMask)) { return s; } @@ -716,7 +775,7 @@ class VirtualSite: public AbstractSite { if (site) { return site; } else { - return freeRegister(c, r->size, registerMask); + return freeRegister(c, registerMask); } } @@ -740,40 +799,14 @@ anyRegisterSite(Context* c) return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast(0)); } -bool -used(Context* c, int r) -{ - Value* v = c->registers[r].value; -// fprintf(stderr, "v: %p found: %d\n", -// v, v and findSite(c, v, c->registers[r].site)); - return v and findSite(c, v, c->registers[r].site); -} - -bool -usedExclusively(Context* c, int r) -{ - Value* v = c->registers[r].value; - return used(c, r) and v->sites->next == 0; -} - -bool -isFree(Context* c, Site* s) -{ - return s->type(c) != RegisterOperand - or not (usedExclusively(c, static_cast(s)->register_.low) - or (static_cast(s)->register_.high != NoRegister - and usedExclusively - (c, static_cast(s)->register_.high))); -} - Site* -targetOrRegister(Context* c, unsigned size, Value* v, Event* event) +targetOrRegister(Context* c, Value* v) { - Site* s = targetOrNull(c, v, event); - if (s and isFree(c, s)) { + Site* s = targetOrNull(c, v); + if (s) { return s; } else { - return freeRegister(c, size); + return freeRegister(c); } } @@ -853,15 +886,15 @@ pushNow(Context* c, Stack* start) } bool -trySteal(Context* c, int r, Stack* stack) +trySteal(Context* c, Register* r, Stack* stack) { - Value* v = c->registers[r].value; + assert(c, r->refCount == 0); - assert(c, c->registers[r].refCount == 0); + Value* v = r->value; if (DebugRegisters) { fprintf(stderr, "try steal %d from %p: next: %p\n", - r, v, v->sites->next); + r->number, v, v->sites->next); } if (v->sites->next == 0) { @@ -883,49 +916,143 @@ trySteal(Context* c, int r, Stack* stack) } } - removeSite(c, v, c->registers[r].site); + removeSite(c, v, r->site); return true; } bool -tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, - Site* newSite) +used(Context* c, Register* r) { - if (c->registers[r].reserved) return true; + Value* v = r->value; + return v and findSite(c, v, r->site); +} - if (DebugRegisters) { - fprintf(stderr, "try acquire %d, value %p, site %p\n", - r, newValue, newSite); +bool +usedExclusively(Context* c, Register* r) +{ + return used(c, r) and r->value->sites->next == 0; +} + +unsigned +registerCost(Context* c, Register* r) +{ + if (r->reserved or r->freezeCount) { + return 6; } - Value* oldValue = c->registers[r].value; - if (oldValue - and oldValue != newValue - and findSite(c, oldValue, c->registers[r].site)) - { - if (not trySteal(c, r, stack)) { - return false; + unsigned cost = 0; + + if (used(c, r)) { + ++ cost; + if (usedExclusively(c, r)) { + cost += 2; } } - c->registers[r].size = newSize; - c->registers[r].value = newValue; - c->registers[r].site = newSite; + if (r->refCount) { + cost += 2; + } - return true; + return cost; +} + +Register* +pickRegister(Context* c, uint32_t mask) +{ + Register* register_ = 0; + unsigned cost = 5; + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if ((1 << i) & mask) { + Register* r = c->registers[i]; + if ((static_cast(1) << i) == mask) { + assert(c, r->freezeCount == 0); + return r; + } + + unsigned myCost = registerCost(c, r); + if (myCost < cost) { + register_ = r; + cost = myCost; + } + } + } + + expect(c, register_); + + return register_; } void -release(Context* c, int r) +swap(Context* c, Register* a, Register* b) { + Assembler::Register ar(a->number); + Assembler::Register br(b->number); + c->assembler->apply + (Swap, BytesPerWord, RegisterOperand, &ar, RegisterOperand, &br); + + c->registers[a->number] = b; + c->registers[b->number] = a; + + int t = a->number; + a->number = b->number; + b->number = t; +} + +Register* +replace(Context* c, Stack* stack, Register* r) +{ + ++ r->freezeCount; + Register* s = acquire(c, ~0, stack, r->size, r->value, r->site); + -- r->freezeCount; + swap(c, r, s); + return s; +} + +Register* +acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, + Value* newValue, Site* newSite) +{ + Register* r = pickRegister(c, mask); + + if (r->reserved) return r; + if (DebugRegisters) { - fprintf(stderr, "release %d\n", r); + fprintf(stderr, "acquire %d, value %p, site %p\n", + r->number, newValue, newSite); } - c->registers[r].size = 0; - c->registers[r].value = 0; - c->registers[r].site = 0; + if (r->refCount) { + r = replace(c, stack, r); + } else { + Value* oldValue = r->value; + if (oldValue + and oldValue != newValue + and findSite(c, oldValue, r->site)) + { + if (not trySteal(c, r, stack)) { + r = replace(c, stack, r); + } + } + } + + r->size = newSize; + r->value = newValue; + r->site = newSite; + + return r; +} + +void +release(Context*, Register* r) +{ + if (DebugRegisters) { + fprintf(stderr, "release %d\n", r->number); + } + + r->size = 0; + r->value = 0; + r->site = 0; } void @@ -1211,7 +1338,7 @@ class MoveEvent: public Event { target = src->source; cost = 0; } else { - target = targetOrRegister(c, size, dst, this); + target = targetOrRegister(c, dst); cost = src->source->copyCost(c, target); } @@ -1300,7 +1427,8 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (v->reads->next and v->sites->next == 0) { assert(c, v->sites == s); - Site* r = freeRegister(c, size); + Site* r = targetOrNull(c, v->reads->next); + if (r == 0) r = freeRegister(c); addSite(c, stack, size, v, r); apply(c, Move, size, s, r); } @@ -1530,7 +1658,7 @@ resetStack(Context* c) } void -popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) +popNow(Context* c, Stack* stack, unsigned count, bool ignore) { Stack* s = stack; unsigned ignored = 0; @@ -1539,8 +1667,7 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) if (s->value->reads and (not ignore)) { ::ignore(c, ignored); - Site* target = targetOrRegister - (c, s->size * BytesPerWord, s->value, event); + Site* target = targetOrRegister(c, s->value); if (DebugStack) { fprintf(stderr, "pop %p value: %p target: %p\n", @@ -1665,9 +1792,9 @@ class PushSite: public AbstractSite { public: PushSite(PushEvent* event): event(event) { } - virtual Site* readTarget(Context* c, Read* r, Event* e) { + virtual Site* readTarget(Context* c, Read* r) { if (r->next and (not event->active)) { - return targetOrNull(c, r->next, e); + return targetOrNull(c, r->next); } else { return 0; } @@ -1709,7 +1836,7 @@ class PopEvent: public Event { fprintf(stderr, "PopEvent.compile\n"); } - popNow(c, this, stack, count, ignore); + popNow(c, stack, count, ignore); } unsigned count; @@ -1727,13 +1854,9 @@ appendPop(Context* c, unsigned count, bool ignore) } Site* -readSource(Context* c, Stack* stack, Read* r, Event* e) +readSource(Context* c, Stack* stack, Read* r) { - Site* target = (r->target ? r->target->readTarget(c, r, e) : 0); - - if (target and not isFree(c, target)) { - target = 0; - } + Site* target = (r->target ? r->target->readTarget(c, r) : 0); unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); @@ -1781,14 +1904,18 @@ compile(Context* c) for (Stack* s = e->stack; s; s = s->next) { if (s->value->sites) { assert(c, s->value->sites->next == 0); - expect(c, s->value->sites->tryAcquire - (c, 0, s->size * BytesPerWord, s->value)); + s->value->sites->acquire(c, 0, s->size * BytesPerWord, s->value); } } } for (Read* r = e->reads; r; r = r->eventNext) { - r->value->source = readSource(c, e->stack, r, e); + r->value->source = readSource(c, e->stack, r); + r->value->source->freeze(c); + } + + for (Read* r = e->reads; r; r = r->eventNext) { + r->value->source->thaw(c); } e->compile(c); @@ -1908,78 +2035,35 @@ visit(Context* c, unsigned logicalIp) } } -int -freeRegister2(Context* c, int32_t mask) -{ - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (((1 << i) & mask) - and c->registers[i].refCount == 0 - and (not used(c, i))) - { - return i; - } - } - - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (((1 << i) & mask) - and c->registers[i].refCount == 0 - and (not usedExclusively(c, i))) - { - return i; - } - } - - for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { - if (((1 << i) & mask) - and not c->registers[i].reserved) - { - return i; - } - } - - abort(c); -} - -RegisterSite* -freeRegister(Context* c, unsigned size, uint64_t mask) -{ - if (BytesPerWord == 4 and size == 8) { - int low = freeRegister2(c, mask); - return registerSite(c, low, freeRegister2(c, (mask >> 32) & ~(1 << low))); - } else { - return registerSite(c, freeRegister2(c, mask)); - } -} - class Client: public Assembler::Client { public: Client(Context* c): c(c) { } virtual int acquireTemporary(uint32_t mask) { - int r = freeRegister2(c, mask); + int r = pickRegister(c, mask)->number; save(r); increment(c, r); return r; } virtual void releaseTemporary(int r) { - decrement(c, r); + decrement(c, c->registers[r]); restore(r); } virtual void save(int r) { - if (c->registers[r].refCount or c->registers[r].value) { + if (c->registers[r]->refCount or c->registers[r]->value) { Assembler::Register operand(r); c->assembler->apply(Push, BytesPerWord, RegisterOperand, &operand); - c->registers[r].pushed = true; + c->registers[r]->pushed = true; } } virtual void restore(int r) { - if (c->registers[r].pushed) { + if (c->registers[r]->pushed) { Assembler::Register operand(r); c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &operand); - c->registers[r].pushed = false; + c->registers[r]->pushed = false; } } From 08beaad1b6968f34695812625e9bd210043e9528 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 May 2008 11:27:57 -0600 Subject: [PATCH 080/121] various bugfixes related to new register allocation code --- src/compile.cpp | 6 +++--- src/compiler.cpp | 34 ++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index fc7590a10a..3e30f56915 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3847,15 +3847,15 @@ finish(MyThread* t, Context* context) } // for debugging: - if (//false and + if (false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Misc") == 0 and + "java/lang/String") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "main") == 0) + "getBytes") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index afd895d1f2..dea5a710a3 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -485,8 +485,8 @@ release(Context* c, Register* r); class RegisterSite: public Site { public: - RegisterSite(uint64_t mask): - mask(mask), low(0), high(0), register_(NoRegister, NoRegister) + RegisterSite(uint64_t mask, Register* low = 0, Register* high = 0): + mask(mask), low(low), high(high), register_(NoRegister, NoRegister) { } void sync(Context* c) { @@ -520,6 +520,11 @@ class RegisterSite: public Site { ++ low->freezeCount; high = ::acquire(c, mask >> 32, stack, size, v, this); -- low->freezeCount; + + mask = (static_cast(1) << (high->number + 32)) | + (static_cast(1) << low->number); + } else { + mask = static_cast(1) << low->number; } } @@ -527,8 +532,10 @@ class RegisterSite: public Site { assert(c, low); ::release(c, low); + low = 0; if (high) { ::release(c, high); + high = 0; } } @@ -574,14 +581,17 @@ registerSite(Context* c, int low, int high = NoRegister) or high < static_cast(c->assembler->registerCount())); uint64_t mask; + Register* hr; if (high == NoRegister) { + hr = 0; mask = static_cast(1) << low; } else { + hr = c->registers[high]; mask = (static_cast(1) << (high + 32)) | (static_cast(1) << low); } return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(mask); + RegisterSite(mask, c->registers[low], hr); } RegisterSite* @@ -1340,6 +1350,9 @@ class MoveEvent: public Event { } else { target = targetOrRegister(c, dst); cost = src->source->copyCost(c, target); + if (cost == 0) { + target = src->source; + } } nextRead(c, src); @@ -1596,11 +1609,11 @@ class MemoryEvent: public Event { nextRead(c, base); if (index) { - nextRead(c, index); - if (BytesPerWord == 8) { apply(c, Move4To8, 0, index->source, index->source); } + + nextRead(c, index); } result->target = memorySite @@ -1861,9 +1874,9 @@ readSource(Context* c, Stack* stack, Read* r) unsigned copyCost; Site* site = pick(c, r->value->sites, target, ©Cost); - if (target) { - if (copyCost) { - addSite(c, stack, r->size, r->value, target); + if (target and copyCost) { + addSite(c, stack, r->size, r->value, target); + if (site) { apply(c, Move, r->size, site, target); } return target; @@ -1911,11 +1924,11 @@ compile(Context* c) for (Read* r = e->reads; r; r = r->eventNext) { r->value->source = readSource(c, e->stack, r); - r->value->source->freeze(c); + if (r->value->source) r->value->source->freeze(c); } for (Read* r = e->reads; r; r = r->eventNext) { - r->value->source->thaw(c); + if (r->value->source) r->value->source->thaw(c); } e->compile(c); @@ -2251,6 +2264,7 @@ class MyCompiler: public Compiler { Value* v = value(&c); c.state->stack = ::stack(&c, v, 1, c.state->stack); c.state->stack->pushed = true; +// v->sites = pushSite(&c, c.state->stack->index); } } From 13d6ab023f2a022a5e91d3b7037d3d691f974e69 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 May 2008 11:28:19 -0600 Subject: [PATCH 081/121] implement addCM --- src/x86.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/x86.cpp b/src/x86.cpp index e00ab4107b..c82b609496 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -908,6 +908,25 @@ moveZRR(Context* c, unsigned size, Assembler::Register* a, } } +void +addCM(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + unsigned i = (isInt8(v) ? 0x83 : 0x81); + + encode(c, i, 0, b, true); + if (isInt8(v)) { + c->code.append(v); + } else if (isInt32(v)) { + c->code.append4(v); + } else { + abort(c); + } +} + void addCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) @@ -1746,6 +1765,7 @@ populateTables() BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(Add, Constant, Memory)] = CAST2(addCM); BinaryOperations[INDEX2(Multiply, Register, Register)] = CAST2(multiplyRR); BinaryOperations[INDEX2(Multiply, Constant, Register)] = CAST2(multiplyCR); From 482065f91a5ce62e3688c3363f4989c0418b9505 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 May 2008 16:36:22 -0600 Subject: [PATCH 082/121] fix code ordering bug in popNow() --- src/compiler.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index dea5a710a3..5cac9b78ec 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1677,6 +1677,10 @@ popNow(Context* c, Stack* stack, unsigned count, bool ignore) unsigned ignored = 0; for (unsigned i = count; i and s;) { if (s->pushed) { + removeSite(c, s->value, s->pushSite); + s->pushSite = 0; + s->pushed = false; + if (s->value->reads and (not ignore)) { ::ignore(c, ignored); @@ -1697,10 +1701,6 @@ popNow(Context* c, Stack* stack, unsigned count, bool ignore) ignored += s->size; } - - removeSite(c, s->value, s->pushSite); - s->pushSite = 0; - s->pushed = false; } else { if (DebugStack) { fprintf(stderr, "%p not pushed\n", s); @@ -1876,9 +1876,7 @@ readSource(Context* c, Stack* stack, Read* r) if (target and copyCost) { addSite(c, stack, r->size, r->value, target); - if (site) { - apply(c, Move, r->size, site, target); - } + apply(c, Move, r->size, site, target); return target; } else { return site; From 73b8cc55957f77ad6094263fc9721388eac743fc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 May 2008 17:19:41 -0600 Subject: [PATCH 083/121] fix unused variable warnings --- src/compiler.cpp | 12 ++++++------ src/x86.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 5cac9b78ec..b0f7d1ad47 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -489,7 +489,7 @@ class RegisterSite: public Site { mask(mask), low(low), high(high), register_(NoRegister, NoRegister) { } - void sync(Context* c) { + void sync(Context* c UNUSED) { assert(c, low); register_.low = low->number; @@ -539,7 +539,7 @@ class RegisterSite: public Site { } } - virtual void freeze(Context* c) { + virtual void freeze(Context* c UNUSED) { assert(c, low); ++ low->freezeCount; @@ -548,7 +548,7 @@ class RegisterSite: public Site { } } - virtual void thaw(Context* c) { + virtual void thaw(Context* c UNUSED) { assert(c, low); -- low->freezeCount; @@ -616,7 +616,7 @@ increment(Context* c, int i) } void -decrement(Context* c, Register* r) +decrement(Context* c UNUSED, Register* r) { assert(c, r->refCount > 0); @@ -634,7 +634,7 @@ class MemorySite: public Site { base(0), index(0), value(base, offset, index, scale) { } - void sync(Context* c) { + void sync(Context* c UNUSED) { assert(c, base); value.base = base->number; @@ -694,7 +694,7 @@ memorySite(Context* c, int base, int offset, int index, unsigned scale) } bool -matchRegister(Context* c, Site* s, uint64_t mask) +matchRegister(Context* c UNUSED, Site* s, uint64_t mask) { assert(c, s->type(c) == RegisterOperand); diff --git a/src/x86.cpp b/src/x86.cpp index c82b609496..a1c28c0dbc 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -909,7 +909,7 @@ moveZRR(Context* c, unsigned size, Assembler::Register* a, } void -addCM(Context* c, unsigned size, Assembler::Constant* a, +addCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Memory* b) { assert(c, BytesPerWord == 8 or size == 4); // todo @@ -1138,7 +1138,7 @@ multiplyCR(Context* c, unsigned size, Assembler::Constant* a, void divideRR(Context* c, unsigned size, Assembler::Register* a, - Assembler::Register* b) + Assembler::Register* b UNUSED) { assert(c, BytesPerWord == 8 or size == 4); From 04f4ad4f580e71097ca0aebbc92e3b24252bc916 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 May 2008 17:22:44 -0600 Subject: [PATCH 084/121] fix variadic argument passing bug on amd64 --- src/compile.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 3e30f56915..e716b9b7ec 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2133,7 +2133,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(addDouble)), - Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dcmpg: { @@ -2143,7 +2145,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesG)), - Compiler::Indirect, 0, 4, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 4, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dcmpl: { @@ -2153,7 +2157,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(compareDoublesL)), - Compiler::Indirect, 0, 4, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 4, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dconst_0: @@ -2171,7 +2177,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(divideDouble)), - Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dmul: { @@ -2181,14 +2189,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(multiplyDouble)), - Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dneg: { frame->pushLong (c->call (c->constant(reinterpret_cast(negateDouble)), - Compiler::Indirect, 0, 8, 2, 0, frame->popLong())); + Compiler::Indirect, 0, 8, 2, + static_cast(0), frame->popLong())); } break; case vm::drem: { @@ -2198,7 +2209,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(moduloDouble)), - Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dsub: { @@ -2208,7 +2221,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(subtractDouble)), - Compiler::Indirect, 0, 8, 4, 0, a, 0, b)); + Compiler::Indirect, 0, 8, 4, + static_cast(0), a, + static_cast(0), b)); } break; case dup: @@ -3851,11 +3866,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/String") == 0 and + "Enums") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "getBytes") == 0) + "checkFaceCard") == 0) { asm("int3"); } From 8434abaa0e1a911cb44437034bb085d42383e721 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 May 2008 17:33:55 -0600 Subject: [PATCH 085/121] implement swapRR --- src/x86.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index a1c28c0dbc..6ecd286005 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -580,15 +580,6 @@ void xorRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b); -void -swap(Context* c, Assembler::Register* a, Assembler::Register* b) -{ - // todo: use xchg instead - xorRR(c, 4, a, b); - xorRR(c, 4, b, b); - xorRR(c, 4, a, b); -} - void negateR(Context* c, unsigned size, Assembler::Register* a) { @@ -908,6 +899,14 @@ moveZRR(Context* c, unsigned size, Assembler::Register* a, } } +void +swapRR(Context* c, unsigned, Assembler::Register* a, Assembler::Register* b) +{ + rex(c); + c->code.append(0x87); + c->code.append(0xc0 | (b->low << 3) | a->low); +} + void addCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Memory* b) @@ -1762,6 +1761,8 @@ populateTables() BinaryOperations[INDEX2(MoveZ, Memory, Register)] = CAST2(moveZMR); BinaryOperations[INDEX2(MoveZ, Register, Register)] = CAST2(moveZRR); + BinaryOperations[INDEX2(Swap, Register, Register)] = CAST2(swapRR); + BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); From 505d6df7ae7dda2924e86f8ca940ccd830957d96 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 May 2008 18:04:25 -0600 Subject: [PATCH 086/121] reorder code in CallEvent ctor to ensure we don't clobber argument registers when it comes time to marshal values for reading --- src/compiler.cpp | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index b0f7d1ad47..fd5cc0f81b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -476,6 +476,26 @@ addressSite(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); } +void +freeze(Register* r) +{ + if (DebugRegisters) { + fprintf(stderr, "freeze %d to %d\n", r->number, r->freezeCount + 1); + } + + ++ r->freezeCount; +} + +void +thaw(Register* r) +{ + if (DebugRegisters) { + fprintf(stderr, "thaw %d to %d\n", r->number, r->freezeCount - 1); + } + + -- r->freezeCount; +} + Register* acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, Value* newValue, Site* newSite); @@ -517,9 +537,9 @@ class RegisterSite: public Site { virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) { low = ::acquire(c, mask, stack, size, v, this); if (size > BytesPerWord) { - ++ low->freezeCount; + ::freeze(low); high = ::acquire(c, mask >> 32, stack, size, v, this); - -- low->freezeCount; + ::thaw(low); mask = (static_cast(1) << (high->number + 32)) | (static_cast(1) << low->number); @@ -542,18 +562,18 @@ class RegisterSite: public Site { virtual void freeze(Context* c UNUSED) { assert(c, low); - ++ low->freezeCount; + ::freeze(low); if (high) { - ++ high->freezeCount; + ::freeze(high); } } virtual void thaw(Context* c UNUSED) { assert(c, low); - -- low->freezeCount; + ::thaw(low); if (high) { - -- high->freezeCount; + ::thaw(high); } } @@ -621,8 +641,7 @@ decrement(Context* c UNUSED, Register* r) assert(c, r->refCount > 0); if (DebugRegisters) { - fprintf(stderr, "decrement %d to %d\n", - r->number, r->refCount - 1); + fprintf(stderr, "decrement %d to %d\n", r->number, r->refCount - 1); } -- r->refCount; @@ -1012,9 +1031,9 @@ swap(Context* c, Register* a, Register* b) Register* replace(Context* c, Stack* stack, Register* r) { - ++ r->freezeCount; + freeze(r); Register* s = acquire(c, ~0, stack, r->size, r->value, r->site); - -- r->freezeCount; + thaw(r); swap(c, r, s); return s; } @@ -1185,6 +1204,10 @@ class CallEvent: public Event { resultSize(resultSize), argumentFootprint(0) { + for (Stack* s = stack; s; s = s->next) { + addRead(c, s->value, s->size * BytesPerWord, 0); + } + Stack* s = argumentStack; unsigned index = 0; for (unsigned i = 0; i < argumentCount; ++i) { @@ -1202,10 +1225,6 @@ class CallEvent: public Event { s = s->next; } - for (Stack* s = stack; s; s = s->next) { - addRead(c, s->value, s->size * BytesPerWord, 0); - } - addRead(c, address, BytesPerWord, ((flags & Compiler::Indirect) ? registerSite(c, c->assembler->returnLow()) : 0)); From 2ed6247cec39b67077e9dbc38bfc575df73c00fc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 15 May 2008 08:29:19 -0600 Subject: [PATCH 087/121] fix freezing and thawing of read sites where the same value is read multiple times in compile() --- src/compiler.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index fd5cc0f81b..dc0043327f 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -305,7 +305,7 @@ expect(Context* c, bool v) class Event { public: Event(Context* c): - next(0), stack(c->state->stack), promises(0), reads(0), + next(0), stack(c->state->stack), promises(0), reads(0), readCount(0), sequence(c->nextSequence++), stackReset(c->stackReset) { assert(c, c->logicalIp >= 0); @@ -325,7 +325,7 @@ class Event { } Event(Context*, unsigned sequence, Stack* stack): - next(0), stack(stack), promises(0), reads(0), + next(0), stack(stack), promises(0), reads(0), readCount(0), sequence(sequence), stackReset(false) { } @@ -339,6 +339,7 @@ class Event { Stack* stack; CodePromise* promises; Read* reads; + unsigned readCount; unsigned sequence; bool stackReset; }; @@ -1106,12 +1107,13 @@ apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b) } void -insertRead(Context* c, Event* thisEvent, int sequence, Value* v, +insertRead(Context* c, Event* event, int sequence, Value* v, unsigned size, Site* target) { Read* r = new (c->zone->allocate(sizeof(Read))) - Read(size, v, target, 0, thisEvent, thisEvent->reads); - thisEvent->reads = r; + Read(size, v, target, 0, event, event->reads); + event->reads = r; + ++ event->readCount; // fprintf(stderr, "add read %p to %p\n", r, v); @@ -1939,13 +1941,20 @@ compile(Context* c) } } + Site* sites[e->readCount]; + unsigned si = 0; for (Read* r = e->reads; r; r = r->eventNext) { r->value->source = readSource(c, e->stack, r); - if (r->value->source) r->value->source->freeze(c); + + if (r->value->source) { + assert(c, si < e->readCount); + sites[si++] = r->value->source; + r->value->source->freeze(c); + } } - for (Read* r = e->reads; r; r = r->eventNext) { - if (r->value->source) r->value->source->thaw(c); + while (si) { + sites[--si]->thaw(c); } e->compile(c); From bbd1ee5540863392fab30f8a4cea9e95ce55f921 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 15 May 2008 14:00:57 -0600 Subject: [PATCH 088/121] various register marshalling bugfixes --- src/compiler.cpp | 88 ++++++++++++++++++++++++++++++++++++++---------- src/x86.cpp | 1 + test/Misc.java | 27 +++++++++++++++ 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index dc0043327f..8c0fcbb6f5 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -54,6 +54,8 @@ class Site { virtual void thaw(Context*) { } + virtual void validate(Context*, Stack*, unsigned, Value*) { } + virtual OperandType type(Context*) = 0; virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; @@ -101,12 +103,13 @@ class LogicalInstruction { class Register { public: Register(int number): - value(0), site(0), number(number), size(0), refCount(0), freezeCount(0), - reserved(false), pushed(false) + value(0), site(0), mask(0), number(number), size(0), refCount(0), + freezeCount(0), reserved(false), pushed(false) { } Value* value; Site* site; + uint32_t mask; int number; unsigned size; unsigned refCount; @@ -384,7 +387,7 @@ removeMemorySites(Context* c, Value* v) { for (Site** p = &(v->sites); *p;) { if ((*p)->type(c) == MemoryOperand) { -// fprintf(stderr, "remove site %p (%d) from %p\n", s, s->type(c), v); +// fprintf(stderr, "remove site %p (%d) from %p\n", *p, (*p)->type(c), v); (*p)->release(c); *p = (*p)->next; break; @@ -504,6 +507,10 @@ acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, void release(Context* c, Register* r); +Register* +validate(Context* c, uint32_t mask, Stack* stack, unsigned size, + Value* value, Site* site, Register* current); + class RegisterSite: public Site { public: RegisterSite(uint64_t mask, Register* low = 0, Register* high = 0): @@ -578,6 +585,15 @@ class RegisterSite: public Site { } } + virtual void validate(Context* c, Stack* stack, unsigned size, Value* v) { + low = ::validate(c, mask, stack, size, v, this, low); + if (size > BytesPerWord) { + ::freeze(low); + high = ::validate(c, mask >> 32, stack, size, v, this, high); + ::thaw(low); + } + } + virtual OperandType type(Context*) { return RegisterOperand; } @@ -816,8 +832,8 @@ class VirtualSite: public AbstractSite { VirtualSite* virtualSite(Context* c, Value* v = 0, - uint8_t typeMask = ~static_cast(0), - uint64_t registerMask = ~static_cast(0)) + uint8_t typeMask = ~static_cast(0), + uint64_t registerMask = ~static_cast(0)) { return new (c->zone->allocate(sizeof(VirtualSite))) VirtualSite(v, typeMask, registerMask); @@ -996,7 +1012,6 @@ pickRegister(Context* c, uint32_t mask) if ((1 << i) & mask) { Register* r = c->registers[i]; if ((static_cast(1) << i) == mask) { - assert(c, r->freezeCount == 0); return r; } @@ -1032,10 +1047,14 @@ swap(Context* c, Register* a, Register* b) Register* replace(Context* c, Stack* stack, Register* r) { + uint32_t mask = (r->freezeCount? r->mask : ~0); + freeze(r); - Register* s = acquire(c, ~0, stack, r->size, r->value, r->site); + Register* s = acquire(c, mask, stack, r->size, r->value, r->site); thaw(r); + swap(c, r, s); + return s; } @@ -1066,6 +1085,7 @@ acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, } } + r->mask = mask; r->size = newSize; r->value = newValue; r->site = newSite; @@ -1080,11 +1100,31 @@ release(Context*, Register* r) fprintf(stderr, "release %d\n", r->number); } + r->mask = 0; r->size = 0; r->value = 0; r->site = 0; } +Register* +validate(Context* c, uint32_t mask, Stack* stack, unsigned size, + Value* value, Site* site, Register* current) +{ + if ((mask & (1 << current->number)) == 0) { + Register* r = acquire(c, mask, stack, size, value, site); + release(c, current); + + Assembler::Register rr(r->number); + Assembler::Register cr(current->number); + c->assembler->apply + (Move, BytesPerWord, RegisterOperand, &cr, RegisterOperand, &rr); + + return r; + } else { + return current; + } +} + void apply(Context* c, UnaryOperation op, unsigned size, Site* a) { @@ -1206,17 +1246,15 @@ class CallEvent: public Event { resultSize(resultSize), argumentFootprint(0) { - for (Stack* s = stack; s; s = s->next) { - addRead(c, s->value, s->size * BytesPerWord, 0); - } - + uint32_t mask = ~0; Stack* s = argumentStack; unsigned index = 0; for (unsigned i = 0; i < argumentCount; ++i) { Site* target; if (index < c->assembler->argumentRegisterCount()) { - target = registerSite - (c, c->assembler->argumentRegister(index)); + int r = c->assembler->argumentRegister(index); + target = registerSite(c, r); + mask &= ~(1 << r); } else { target = 0; s->pushEvent->active = true; @@ -1227,9 +1265,20 @@ class CallEvent: public Event { s = s->next; } - addRead(c, address, BytesPerWord, - ((flags & Compiler::Indirect) ? - registerSite(c, c->assembler->returnLow()) : 0)); + if (flags & Compiler::Indirect) { + int r = c->assembler->returnLow(); + addRead(c, address, BytesPerWord, registerSite(c, r)); + mask &= ~(1 << r); + } else { + addRead(c, address, BytesPerWord, virtualSite + (c, 0, ~0, (static_cast(mask) << 32) | mask)); + } + + for (Stack* s = stack; s; s = s->next) { + s->pushEvent->active = true; + addRead(c, s->value, s->size * BytesPerWord, virtualSite + (c, 0, ~0, (static_cast(mask) << 32) | mask)); + } } virtual void compile(Context* c) { @@ -1462,7 +1511,7 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) if (v->reads->next and v->sites->next == 0) { assert(c, v->sites == s); Site* r = targetOrNull(c, v->reads->next); - if (r == 0) r = freeRegister(c); + if (r == 0 or r == s) r = freeRegister(c); addSite(c, stack, size, v, r); apply(c, Move, size, s, r); } @@ -1890,6 +1939,10 @@ appendPop(Context* c, unsigned count, bool ignore) Site* readSource(Context* c, Stack* stack, Read* r) { + if (r->value->sites == 0) { + return 0; + } + Site* target = (r->target ? r->target->readTarget(c, r) : 0); unsigned copyCost; @@ -1900,6 +1953,7 @@ readSource(Context* c, Stack* stack, Read* r) apply(c, Move, r->size, site, target); return target; } else { + site->validate(c, stack, r->size, r->value); return site; } } diff --git a/src/x86.cpp b/src/x86.cpp index 6ecd286005..882fcdd864 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1950,6 +1950,7 @@ class MyAssembler: public Assembler { case ShiftLeft: case ShiftRight: case UnsignedShiftRight: { + *aTypeMask = (1 << RegisterOperand); *aRegisterMask = static_cast(1) << rcx; const uint32_t mask = ~(1 << rcx); *bRegisterMask = (static_cast(mask) << 32) | mask; diff --git a/test/Misc.java b/test/Misc.java index 259a87b5b4..89605d4400 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -75,6 +75,23 @@ public class Misc { } public static void main(String[] args) { + { int get_buffer = 2144642881; + int bits_left = 30; + int l = 9; + int code = (((get_buffer >> (bits_left -= (l)))) & ((1<<(l))-1)); + expect(code == 510); + } + + { int width = 8; + int height = 8; + int depth = 24; + int scanlinePad = 4; + + int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) + / scanlinePad * scanlinePad; + expect(bytesPerLine == 24); + } + { int a = -5; int b = 2; expect(a >> b == -5 >> 2); @@ -83,6 +100,11 @@ public class Misc { expect(a * b == -5 * 2); expect(a / b == -5 / 2); expect(a % b == -5 % 2); + expect((a & b) == (-5 & 2)); + expect((a | b) == (-5 | 2)); + expect((a ^ b) == (-5 ^ 2)); + expect(-a == 5); + expect(~a == ~-5); a = 5; b = 2; @@ -92,6 +114,11 @@ public class Misc { expect(a * b == 5 * 2); expect(a / b == 5 / 2); expect(a % b == 5 % 2); + expect((a & b) == (5 & 2)); + expect((a | b) == (5 | 2)); + expect((a ^ b) == (5 ^ 2)); + expect(-a == -5); + expect(~a == ~5); } byte2 = 0; From 7f72a6469d818203bf945fddd10ee4c7375d6aeb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 15 May 2008 17:19:23 -0600 Subject: [PATCH 089/121] more register marshalling bugfixes; simple swt apps now run on amd64 --- src/compiler.cpp | 107 +++++++++++++++++++++++++---------------------- test/Misc.java | 7 +++- 2 files changed, 64 insertions(+), 50 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 8c0fcbb6f5..b7933621e2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -24,6 +24,7 @@ class Context; class Value; class Stack; class Site; +class RegisterSite; class Event; class PushEvent; class Read; @@ -103,13 +104,12 @@ class LogicalInstruction { class Register { public: Register(int number): - value(0), site(0), mask(0), number(number), size(0), refCount(0), + value(0), site(0), number(number), size(0), refCount(0), freezeCount(0), reserved(false), pushed(false) { } Value* value; - Site* site; - uint32_t mask; + RegisterSite* site; int number; unsigned size; unsigned refCount; @@ -502,14 +502,14 @@ thaw(Register* r) Register* acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, - Value* newValue, Site* newSite); + Value* newValue, RegisterSite* newSite); void release(Context* c, Register* r); Register* validate(Context* c, uint32_t mask, Stack* stack, unsigned size, - Value* value, Site* site, Register* current); + Value* value, RegisterSite* site, Register* current); class RegisterSite: public Site { public: @@ -543,27 +543,15 @@ class RegisterSite: public Site { } virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) { - low = ::acquire(c, mask, stack, size, v, this); - if (size > BytesPerWord) { - ::freeze(low); - high = ::acquire(c, mask >> 32, stack, size, v, this); - ::thaw(low); - - mask = (static_cast(1) << (high->number + 32)) | - (static_cast(1) << low->number); - } else { - mask = static_cast(1) << low->number; - } + validate(c, stack, size, v); } virtual void release(Context* c) { assert(c, low); ::release(c, low); - low = 0; if (high) { ::release(c, high); - high = 0; } } @@ -617,27 +605,35 @@ registerSite(Context* c, int low, int high = NoRegister) assert(c, high == NoRegister or high < static_cast(c->assembler->registerCount())); - uint64_t mask; Register* hr; if (high == NoRegister) { hr = 0; - mask = static_cast(1) << low; } else { hr = c->registers[high]; - mask = (static_cast(1) << (high + 32)) - | (static_cast(1) << low); } return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(mask, c->registers[low], hr); + RegisterSite(~static_cast(0), c->registers[low], hr); } RegisterSite* -freeRegister(Context* c, uint64_t mask = ~static_cast(0)) +freeRegisterSite(Context* c, uint64_t mask = ~static_cast(0)) { return new (c->zone->allocate(sizeof(RegisterSite))) RegisterSite(mask); } +RegisterSite* +fixedRegisterSite(Context* c, int low, int high = NoRegister) +{ + uint64_t mask = static_cast(1) << low; + if (high != NoRegister) { + mask |= static_cast(1) << (high + 32); + } + + return new (c->zone->allocate(sizeof(RegisterSite))) + RegisterSite(mask); +} + Register* increment(Context* c, int i) { @@ -821,7 +817,7 @@ class VirtualSite: public AbstractSite { if (site) { return site; } else { - return freeRegister(c, registerMask); + return freeRegisterSite(c, registerMask); } } @@ -852,7 +848,7 @@ targetOrRegister(Context* c, Value* v) if (s) { return s; } else { - return freeRegister(c); + return freeRegisterSite(c); } } @@ -1031,6 +1027,9 @@ pickRegister(Context* c, uint32_t mask) void swap(Context* c, Register* a, Register* b) { + assert(c, a != b); + assert(c, a->number != b->number); + Assembler::Register ar(a->number); Assembler::Register br(b->number); c->assembler->apply @@ -1047,7 +1046,7 @@ swap(Context* c, Register* a, Register* b) Register* replace(Context* c, Stack* stack, Register* r) { - uint32_t mask = (r->freezeCount? r->mask : ~0); + uint32_t mask = (r->freezeCount? r->site->mask : ~0); freeze(r); Register* s = acquire(c, mask, stack, r->size, r->value, r->site); @@ -1060,7 +1059,7 @@ replace(Context* c, Stack* stack, Register* r) Register* acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, - Value* newValue, Site* newSite) + Value* newValue, RegisterSite* newSite) { Register* r = pickRegister(c, mask); @@ -1085,7 +1084,6 @@ acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, } } - r->mask = mask; r->size = newSize; r->value = newValue; r->site = newSite; @@ -1100,7 +1098,6 @@ release(Context*, Register* r) fprintf(stderr, "release %d\n", r->number); } - r->mask = 0; r->size = 0; r->value = 0; r->site = 0; @@ -1108,21 +1105,33 @@ release(Context*, Register* r) Register* validate(Context* c, uint32_t mask, Stack* stack, unsigned size, - Value* value, Site* site, Register* current) + Value* value, RegisterSite* site, Register* current) { - if ((mask & (1 << current->number)) == 0) { - Register* r = acquire(c, mask, stack, size, value, site); + if (current and (mask & (1 << current->number))) { + if (current->reserved or current->value == value) { + return current; + } + + if (current->value == 0) { + current->size = size; + current->value = value; + current->site = site; + return current; + } + } + + Register* r = acquire(c, mask, stack, size, value, site); + + if (current and current != r) { release(c, current); Assembler::Register rr(r->number); Assembler::Register cr(current->number); c->assembler->apply (Move, BytesPerWord, RegisterOperand, &cr, RegisterOperand, &rr); - - return r; - } else { - return current; } + + return r; } void @@ -1253,7 +1262,7 @@ class CallEvent: public Event { Site* target; if (index < c->assembler->argumentRegisterCount()) { int r = c->assembler->argumentRegister(index); - target = registerSite(c, r); + target = fixedRegisterSite(c, r); mask &= ~(1 << r); } else { target = 0; @@ -1267,7 +1276,7 @@ class CallEvent: public Event { if (flags & Compiler::Indirect) { int r = c->assembler->returnLow(); - addRead(c, address, BytesPerWord, registerSite(c, r)); + addRead(c, address, BytesPerWord, fixedRegisterSite(c, r)); mask &= ~(1 << r); } else { addRead(c, address, BytesPerWord, virtualSite @@ -1296,6 +1305,12 @@ class CallEvent: public Event { apply(c, type, BytesPerWord, address->source); } + if (traceHandler) { + traceHandler->handleTrace + (new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, c->assembler->length())); + } + for (Stack* s = stack; s; s = s->next) { clearSites(c, s->value); } @@ -1317,12 +1332,6 @@ class CallEvent: public Event { c->assembler->returnHigh() : NoRegister)); } - if (traceHandler) { - traceHandler->handleTrace - (new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, c->assembler->length())); - } - if (argumentFootprint and ((flags & Compiler::NoReturn) == 0)) { ignore(c, argumentFootprint); } @@ -1356,7 +1365,7 @@ class ReturnEvent: public Event { Event(c), value(value) { if (value) { - addRead(c, value, size, registerSite + addRead(c, value, size, fixedRegisterSite (c, c->assembler->returnLow(), size > BytesPerWord ? c->assembler->returnHigh() : NoRegister)); @@ -1511,7 +1520,7 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) if (v->reads->next and v->sites->next == 0) { assert(c, v->sites == s); Site* r = targetOrNull(c, v->reads->next); - if (r == 0 or r == s) r = freeRegister(c); + if (r == 0 or r == s) r = freeRegisterSite(c); addSite(c, stack, size, v, r); apply(c, Move, size, s, r); } @@ -1543,7 +1552,7 @@ class CombineEvent: public Event { removeSite(c, second, second->source); if (result->reads) { - addSite(c, 0, size, result, second->source); + addSite(c, 0, 0, result, second->source); } } @@ -1621,7 +1630,7 @@ class TranslateEvent: public Event { removeSite(c, value, value->source); if (result->reads) { - addSite(c, 0, size, result, value->source); + addSite(c, 0, 0, result, value->source); } } diff --git a/test/Misc.java b/test/Misc.java index 89605d4400..50b303d4be 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -74,6 +74,10 @@ public class Misc { return 5 + zap(); } + private static int zup() { + return zap() + 5; + } + public static void main(String[] args) { { int get_buffer = 2144642881; int bits_left = 30; @@ -195,7 +199,8 @@ public class Misc { expect(m.gamma == 44); } - zip(); + expect(zip() == 47); + expect(zup() == 47); int[] array = new int[0]; Exception exception = null; From d7fc4aa4382b04c8f2fcf56ca9e28fc17763f08e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 15 May 2008 18:34:48 -0600 Subject: [PATCH 090/121] fix offset computation in compareCR and compareCM --- src/x86.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 882fcdd864..628e62f125 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1596,9 +1596,14 @@ compareCR(Context* c, unsigned size, Assembler::Constant* a, // bits; otherwise, we jump past that comparison c->code.append(0x0f); c->code.append(0x85); // jne - c->code.append4(2); + + unsigned comparisonOffset = c->code.length(); + c->code.append4(0); compareCR(c, 4, &al, b); + + int32_t comparisonSize = c->code.length() - comparisonOffset - 4; + c->code.set(comparisonOffset, &comparisonSize, 4); } else { if (isInt32(v)) { if (size == 8) rex(c); @@ -1641,9 +1646,14 @@ compareCM(Context* c, unsigned size, Assembler::Constant* a, // bits; otherwise, we jump past that comparison c->code.append(0x0f); c->code.append(0x85); // jne - c->code.append4(2); + + unsigned comparisonOffset = c->code.length(); + c->code.append4(0); compareCM(c, 4, &al, b); + + int32_t comparisonSize = c->code.length() - comparisonOffset - 4; + c->code.set(comparisonOffset, &comparisonSize, 4); } else { encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); From 21c5eb2d9ec172eab14c350fab62c643bdd8598c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 15 May 2008 18:35:17 -0600 Subject: [PATCH 091/121] fix thinko in appendCombine --- src/compiler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index b7933621e2..bea734f818 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1586,6 +1586,8 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, &procedure); if (procedure) { + secondTarget->value = 0; + Stack* oldStack = c->state->stack; ::push(c, size, second); @@ -1594,7 +1596,6 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Stack* argumentStack = c->state->stack; c->state->stack = oldStack; - Value* result = value(c); appendCall(c, value(c, constantSite(c, procedure)), Compiler::Indirect, 0, result, size, argumentStack, 2); } else { From 790e2fee42ca9805600aa92b4305d7eea9cccd89 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 16 May 2008 10:01:24 -0600 Subject: [PATCH 092/121] respect constraints specified by Assembler::plan in MoveEvent::compile --- src/compiler.cpp | 32 +++++++++++++++++++++++++------- src/x86.cpp | 2 ++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index bea734f818..d69215a5ca 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -817,6 +817,7 @@ class VirtualSite: public AbstractSite { if (site) { return site; } else { + assert(c, typeMask & (1 << RegisterOperand)); return freeRegisterSite(c, registerMask); } } @@ -1267,7 +1268,7 @@ class CallEvent: public Event { } else { target = 0; s->pushEvent->active = true; - ++ argumentFootprint; + argumentFootprint += s->size; } addRead(c, s->value, s->size * BytesPerWord, target); index += s->size; @@ -1406,8 +1407,8 @@ appendReturn(Context* c, unsigned size, Value* value) class MoveEvent: public Event { public: MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src, - Value* dst, Site* srcTarget): - Event(c), type(type), size(size), src(src), dst(dst) + Value* dst, Site* srcTarget, VirtualSite* dstTarget): + Event(c), type(type), size(size), src(src), dst(dst), dstTarget(dstTarget) { addRead(c, src, size, srcTarget); } @@ -1429,6 +1430,9 @@ class MoveEvent: public Event { } else { target = targetOrRegister(c, dst); cost = src->source->copyCost(c, target); + if (type != Move) { + ++ cost; + } if (cost == 0) { target = src->source; } @@ -1441,7 +1445,20 @@ class MoveEvent: public Event { } if (cost) { - apply(c, type, size, src->source, target); + if (match(c, target, dstTarget->typeMask, dstTarget->registerMask)) { + apply(c, type, size, src->source, target); + } else { + assert(c, dstTarget->typeMask & (1 << RegisterOperand)); + + Site* tmpTarget = freeRegisterSite(c, dstTarget->registerMask); + + addSite(c, stack, size, dst, tmpTarget); + + apply(c, type, size, src->source, tmpTarget); + apply(c, Move, max(size, BytesPerWord), tmpTarget, target); + + removeSite(c, dst, tmpTarget); + } } if (dst->reads == 0) { @@ -1453,6 +1470,7 @@ class MoveEvent: public Event { unsigned size; Value* src; Value* dst; + VirtualSite* dstTarget; }; void @@ -1475,7 +1493,7 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, assert(c, procedure == 0); // todo new (c->zone->allocate(sizeof(MoveEvent))) - MoveEvent(c, type, size, src, dst, srcTarget); + MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); } class CompareEvent: public Event { @@ -1590,8 +1608,8 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Stack* oldStack = c->state->stack; - ::push(c, size, second); ::push(c, size, first); + ::push(c, size, second); Stack* argumentStack = c->state->stack; c->state->stack = oldStack; @@ -1690,7 +1708,7 @@ class MemoryEvent: public Event { nextRead(c, base); if (index) { if (BytesPerWord == 8) { - apply(c, Move4To8, 0, index->source, index->source); + apply(c, Move4To8, 8, index->source, index->source); } nextRead(c, index); diff --git a/src/x86.cpp b/src/x86.cpp index 628e62f125..2e1cec2fc8 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1941,6 +1941,7 @@ class MyAssembler: public Assembler { case Divide: if (BytesPerWord == 4 and size == 8) { + *bTypeMask = ~static_cast(0); *procedure = reinterpret_cast(divideLong); } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); @@ -1950,6 +1951,7 @@ class MyAssembler: public Assembler { case Remainder: if (BytesPerWord == 4 and size == 8) { + *bTypeMask = ~static_cast(0); *procedure = reinterpret_cast(moduloLong); } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); From 85a772b0a7eb6f2562854c7d75b5c7e1f86cd0f0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 16 May 2008 10:18:36 -0600 Subject: [PATCH 093/121] add read of size 4 in CombineEvent for first operand of shift operation --- src/compiler.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index d69215a5ca..a53aa684ba 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1552,7 +1552,23 @@ class CombineEvent: public Event { Event(c), type(type), size(size), first(first), second(second), result(result) { - addRead(c, first, size, firstTarget); + // todo: we should really specify the sizes of each operand + // seperately for binary operations. The following is a hack + // until then. + unsigned firstSize; + switch (type) { + case ShiftLeft: + case ShiftRight: + case UnsignedShiftRight: + firstSize = 4; + break; + + default: + firstSize = size; + break; + } + + addRead(c, first, firstSize, firstTarget); addRead(c, second, size, secondTarget); } From 15c2eb13f2af1f0e75bb7d961515e29bd7253962 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 May 2008 18:13:27 -0600 Subject: [PATCH 094/121] don't generate code for a move from a register to itself --- src/x86.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 2e1cec2fc8..544e08a495 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -714,9 +714,11 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, case 8: case 4: - rex(c); - c->code.append(0x89); - c->code.append(0xc0 | (a->low << 3) | b->low); + if (a->low != b->low) { + rex(c); + c->code.append(0x89); + c->code.append(0xc0 | (a->low << 3) | b->low); + } break; } } From 2bb310981d4259d90e40f398159e26fa66395a1d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 May 2008 19:26:36 -0600 Subject: [PATCH 095/121] clean up MoveEvent.compile --- src/compiler.cpp | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index a53aa684ba..3a1b98509f 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -953,8 +953,14 @@ trySteal(Context* c, Register* r, Stack* stack) } if (start) { + if (DebugRegisters) { + fprintf(stderr, "push %p\n", v); + } pushNow(c, start, count); } else { + if (DebugRegisters) { + fprintf(stderr, "unable to steal %d from %p\n", r->number, v); + } return false; } } @@ -1053,6 +1059,10 @@ replace(Context* c, Stack* stack, Register* r) Register* s = acquire(c, mask, stack, r->size, r->value, r->site); thaw(r); + if (DebugRegisters) { + fprintf(stderr, "replace %d with %d\n", r->number, s->number); + } + swap(c, r, s); return s; @@ -1067,8 +1077,8 @@ acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize, if (r->reserved) return r; if (DebugRegisters) { - fprintf(stderr, "acquire %d, value %p, site %p\n", - r->number, newValue, newSite); + fprintf(stderr, "acquire %d, value %p, site %p freeze count %d ref count %d used %d used exclusively %d\n", + r->number, newValue, newSite, r->freezeCount, r->refCount, used(c, r), usedExclusively(c, r)); } if (r->refCount) { @@ -1118,6 +1128,8 @@ validate(Context* c, uint32_t mask, Stack* stack, unsigned size, current->value = value; current->site = site; return current; + } else { + abort(c); } } @@ -1430,21 +1442,20 @@ class MoveEvent: public Event { } else { target = targetOrRegister(c, dst); cost = src->source->copyCost(c, target); - if (type != Move) { - ++ cost; - } if (cost == 0) { target = src->source; } } - nextRead(c, src); + if (target == src->source) { + nextRead(c, src); + } if (dst->reads) { addSite(c, stack, size, dst, target); } - if (cost) { + if (cost or type != Move) { if (match(c, target, dstTarget->typeMask, dstTarget->registerMask)) { apply(c, type, size, src->source, target); } else { @@ -1455,15 +1466,24 @@ class MoveEvent: public Event { addSite(c, stack, size, dst, tmpTarget); apply(c, type, size, src->source, tmpTarget); - apply(c, Move, max(size, BytesPerWord), tmpTarget, target); - removeSite(c, dst, tmpTarget); + if (dst->reads == 0) { + removeSite(c, dst, tmpTarget); + + apply(c, Move, size, tmpTarget, target); + } else { + removeSite(c, dst, target); + } } } if (dst->reads == 0) { removeSite(c, dst, target); } + + if (target != src->source) { + nextRead(c, src); + } } BinaryOperation type; From b6b84af123bf386a1608dfdcfd12816e07593d1e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 May 2008 21:32:14 -0600 Subject: [PATCH 096/121] various bugfixes --- src/compiler.cpp | 10 +++++++--- src/x86.cpp | 11 +++++------ test/Misc.java | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 3a1b98509f..a1a9ea3755 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -625,9 +625,13 @@ freeRegisterSite(Context* c, uint64_t mask = ~static_cast(0)) RegisterSite* fixedRegisterSite(Context* c, int low, int high = NoRegister) { - uint64_t mask = static_cast(1) << low; - if (high != NoRegister) { - mask |= static_cast(1) << (high + 32); + uint64_t mask; + if (high == NoRegister) { + mask = (~static_cast(0) << 32) + | (static_cast(1) << low); + } else { + mask = (static_cast(1) << (high + 32)) + | (static_cast(1) << low); } return new (c->zone->allocate(sizeof(RegisterSite))) diff --git a/src/x86.cpp b/src/x86.cpp index 2e1cec2fc8..db2c2a25fd 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1081,7 +1081,7 @@ multiplyRR(Context* c, unsigned size, Assembler::Register* a, // mul a->low,%eax%edx c->code.append(0xf7); - c->code.append(0xe8 | a->low); + c->code.append(0xe0 | a->low); addRR(c, 4, b, &bh); moveRR(c, 4, &axdx, b); @@ -1099,8 +1099,6 @@ void multiplyCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); - if (BytesPerWord == 4 and size == 8) { const uint32_t mask = ~((1 << rax) | (1 << rdx)); Assembler::Register tmp(c->client->acquireTemporary(mask), @@ -1517,9 +1515,9 @@ unsignedShiftRightRR(Context* c, unsigned size, Assembler::Register* a, assert(c, a->low == rcx); if (BytesPerWord == 4 and size == 8) { - // shld + // shrd c->code.append(0x0f); - c->code.append(0xa5); + c->code.append(0xad); c->code.append(0xc0 | (b->high << 3) | b->low); // shr @@ -1963,7 +1961,8 @@ class MyAssembler: public Assembler { case ShiftRight: case UnsignedShiftRight: { *aTypeMask = (1 << RegisterOperand); - *aRegisterMask = static_cast(1) << rcx; + *aRegisterMask = (~static_cast(0) << 32) + | (static_cast(1) << rcx); const uint32_t mask = ~(1 << rcx); *bRegisterMask = (static_cast(mask) << 32) | mask; } break; diff --git a/test/Misc.java b/test/Misc.java index 50b303d4be..c262c09833 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -125,6 +125,35 @@ public class Misc { expect(~a == ~5); } + { long a = -5; + long b = 2; + expect(a >> b == -5L >> 2); + expect(a >>> b == -5L >>> 2); + expect(a << b == -5L << 2); + expect(a * b == -5L * 2L); + expect(a / b == -5L / 2L); + expect(a % b == -5L % 2L); + expect((a & b) == (-5L & 2L)); + expect((a | b) == (-5L | 2L)); + expect((a ^ b) == (-5L ^ 2L)); + expect(-a == 5L); + expect(~a == ~-5L); + + a = 5; + b = 2; + expect(a >> b == 5L >> 2); + expect(a >>> b == 5L >>> 2); + expect(a << b == 5L << 2); + expect(a * b == 5L * 2L); + expect(a / b == 5L / 2L); + expect(a % b == 5L % 2L); + expect((a & b) == (5L & 2L)); + expect((a | b) == (5L | 2L)); + expect((a ^ b) == (5L ^ 2L)); + expect(-a == -5L); + expect(~a == ~5L); + } + byte2 = 0; expect(byte2 == 0); @@ -174,6 +203,10 @@ public class Misc { { Misc m = new Misc(); m.toString(); + expect(m.time == 0xffffffffffffffffL); + long t = m.time; + expect(t == 0xffffffffffffffffL); + String s = "hello"; m.foo(s); m.bar(s); From 4858972dbc6f7cced7210531a4a9004ebf213d07 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 May 2008 09:43:31 -0600 Subject: [PATCH 097/121] support 64-bit subtracts on 32-bit systems; allow constant shift counts in MyAssembler::plan --- src/x86.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 343c287288..c6dccfdd09 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1012,15 +1012,32 @@ subtractCR(Context* c, unsigned size, Assembler::Constant* a, } } +void +subtractBorrowRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + if (size == 8) rex(c); + c->code.append(0x19); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void subtractRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); - if (size == 8) rex(c); - c->code.append(0x29); - c->code.append(0xc0 | (a->low << 3) | b->low); + subtractRR(c, 4, a, b); + subtractBorrowRR(c, 4, &ah, &bh); + } else { + if (size == 8) rex(c); + c->code.append(0x29); + c->code.append(0xc0 | (a->low << 3) | b->low); + } } void @@ -1962,7 +1979,7 @@ class MyAssembler: public Assembler { case ShiftLeft: case ShiftRight: case UnsignedShiftRight: { - *aTypeMask = (1 << RegisterOperand); + *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); *aRegisterMask = (~static_cast(0) << 32) | (static_cast(1) << rcx); const uint32_t mask = ~(1 << rcx); From b2e25f4e1718558131299286bf591d5df6b61877 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 May 2008 09:45:11 -0600 Subject: [PATCH 098/121] reorder makeMultidimensionalArray parameters to remove the need for the caller to save the stack pointer in a temporary register --- src/compile.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index e716b9b7ec..f36d9aa0c2 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = true; +const bool Verbose = false; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -1499,8 +1499,8 @@ makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* stack, } object FORCE_ALIGN -makeMultidimensionalArray(MyThread* t, object class_, uintptr_t* stack, - int32_t dimensions) +makeMultidimensionalArray(MyThread* t, object class_, int32_t dimensions, + uintptr_t* stack) { object r = makeMultidimensionalArray2(t, class_, stack, dimensions); if (UNLIKELY(t->exception)) { @@ -3177,8 +3177,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Indirect, frame->trace(0, false), BytesPerWord, - 4, c->thread(), frame->append(class_), - c->load(BytesPerWord, c->stack()), c->constant(dimensions)); + 4, c->thread(), frame->append(class_), c->constant(dimensions), + c->stack()); frame->pop(dimensions); frame->pushObject(result); @@ -3866,11 +3866,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Enums") == 0 and + "org/eclipse/swt/widgets/CoolBar") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "checkFaceCard") == 0) + "layoutItems") == 0) { asm("int3"); } From c9f06933e23335f5caff6b1b0871188e734fb8d6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 May 2008 09:45:52 -0600 Subject: [PATCH 099/121] test long addition and subtraction in Misc, as well as multidimensional array creation --- test/Misc.java | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/test/Misc.java b/test/Misc.java index c262c09833..489386a3f5 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -101,6 +101,8 @@ public class Misc { expect(a >> b == -5 >> 2); expect(a >>> b == -5 >>> 2); expect(a << b == -5 << 2); + expect(a + b == -5 + 2); + expect(a - b == -5 - 2); expect(a * b == -5 * 2); expect(a / b == -5 / 2); expect(a % b == -5 % 2); @@ -115,6 +117,8 @@ public class Misc { expect(a >> b == 5 >> 2); expect(a >>> b == 5 >>> 2); expect(a << b == 5 << 2); + expect(a + b == 5 + 2); + expect(a - b == 5 - 2); expect(a * b == 5 * 2); expect(a / b == 5 / 2); expect(a % b == 5 % 2); @@ -130,6 +134,8 @@ public class Misc { expect(a >> b == -5L >> 2); expect(a >>> b == -5L >>> 2); expect(a << b == -5L << 2); + expect(a + b == -5L + 2L); + expect(a - b == -5L - 2L); expect(a * b == -5L * 2L); expect(a / b == -5L / 2L); expect(a % b == -5L % 2L); @@ -144,6 +150,8 @@ public class Misc { expect(a >> b == 5L >> 2); expect(a >>> b == 5L >>> 2); expect(a << b == 5L << 2); + expect(a + b == 5L + 2L); + expect(a - b == 5L - 2L); expect(a * b == 5L * 2L); expect(a / b == 5L / 2L); expect(a % b == 5L % 2L); @@ -235,14 +243,20 @@ public class Misc { expect(zip() == 47); expect(zup() == 47); - int[] array = new int[0]; - Exception exception = null; - try { - int x = array[0]; - } catch (ArrayIndexOutOfBoundsException e) { - exception = e; + { int[] array = new int[0]; + Exception exception = null; + try { + int x = array[0]; + } catch (ArrayIndexOutOfBoundsException e) { + exception = e; + } + + expect(exception != null); } - expect(exception != null); + { Object[][] array = new Object[1][1]; + expect(array.length == 1); + expect(array[0].length == 1); + } } } From f3fb81371407f66b5f27f6e97bd0a468bcb2bb42 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 May 2008 22:24:12 -0600 Subject: [PATCH 100/121] update valgrind.supp to suppress ld-2.6.so warnings --- makefile | 2 +- valgrind.supp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 94158128c8..63954a932f 100644 --- a/makefile +++ b/makefile @@ -43,7 +43,7 @@ ar = ar ranlib = ranlib objcopy = objcopy vg = nice valgrind --num-callers=32 --db-attach=yes --freelist-vol=100000000 -vg += --leak-check=full +vg += --leak-check=full --suppressions=valgrind.supp db = gdb --args javac = javac jar = jar diff --git a/valgrind.supp b/valgrind.supp index 9ca17ffbbf..89e9ef784b 100644 --- a/valgrind.supp +++ b/valgrind.supp @@ -5,6 +5,12 @@ obj:/lib/ld-2.3.6.so } +{ + + Memcheck:Cond + obj:/lib/ld-2.6.so +} + { Memcheck:Addr4 From 56d88517642f42aeceb3f67001fd7f89296f8732 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 May 2008 22:28:47 -0600 Subject: [PATCH 101/121] constrain temporary register in moveMM according to moveMR's requirements --- src/x86.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index c6dccfdd09..c45ef7ea44 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -845,7 +845,14 @@ moveMM(Context* c, unsigned size, Assembler::Memory* a, Assembler::Memory* b) { if (BytesPerWord == 8 or size <= 4) { - Assembler::Register tmp(c->client->acquireTemporary()); + uint32_t mask; + if (BytesPerWord == 4 and size == 1) { + mask = (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx); + } else { + mask = ~static_cast(0); + } + + Assembler::Register tmp(c->client->acquireTemporary(mask)); moveMR(c, size, a, &tmp); moveRM(c, size, &tmp, b); c->client->releaseTemporary(tmp.low); From 3c30e815ec1d5656992efc70824681ad89321e18 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 May 2008 22:31:52 -0600 Subject: [PATCH 102/121] optimize multiple loads from the same local variable --- src/compile.cpp | 39 +++----- src/compiler.cpp | 236 ++++++++++++++++++++++++++++++++++++++--------- src/compiler.h | 6 +- 3 files changed, 209 insertions(+), 72 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index f36d9aa0c2..4f68d10a7e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -849,51 +849,36 @@ class Frame { void loadInt(unsigned index) { assert(t, index < localSize()); - pushInt - (c->load - (4, c->memory(c->base(), localOffset(t, index, context->method)))); + pushInt(c->loadLocal(BytesPerWord, index)); } void loadLong(unsigned index) { assert(t, index < static_cast(localSize() - 1)); - pushLong - (c->load - (8, c->memory(c->base(), localOffset(t, index + 1, context->method)))); + pushLong(c->loadLocal(8, index + 1)); } void loadObject(unsigned index) { assert(t, index < localSize()); - pushObject - (c->load - (BytesPerWord, - c->memory(c->base(), localOffset(t, index, context->method)))); + pushObject(c->loadLocal(BytesPerWord, index)); } void storeInt(unsigned index) { - c->store - (4, popInt(), c->memory - (c->base(), localOffset(t, index, context->method))); + c->storeLocal(BytesPerWord, popInt(), index); storedInt(index); } void storeLong(unsigned index) { - c->store - (8, popLong(), c->memory - (c->base(), localOffset(t, index + 1, context->method))); + c->storeLocal(8, popLong(), index + 1); storedLong(index); } void storeObject(unsigned index) { - c->store - (BytesPerWord, popObject(), c->memory - (c->base(), localOffset(t, index, context->method))); + c->storeLocal(BytesPerWord, popObject(), index); storedObject(index); } void storeObjectOrAddress(unsigned index) { - c->store - (BytesPerWord, c->pop(BytesPerWord), c->memory - (c->base(), localOffset(t, index, context->method))); + c->storeLocal(BytesPerWord, c->pop(BytesPerWord), index); assert(t, sp >= 1); assert(t, sp - 1 >= localSize()); @@ -2641,7 +2626,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = c->memory (c->base(), localOffset(t, index, context->method)); - c->store(4, c->add(4, c->constant(count), a), a); + c->storeLocal(4, c->add(4, c->constant(count), a), index); } break; case iload: @@ -3456,7 +3441,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* a = c->memory (c->base(), localOffset(t, index, context->method)); - c->store(4, c->add(4, c->constant(count), a), a); + c->storeLocal(4, c->add(4, c->constant(count), a), index); } break; case iload: { @@ -3866,11 +3851,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "org/eclipse/swt/widgets/CoolBar") == 0 and + "java/lang/String") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "layoutItems") == 0) + "") == 0) { asm("int3"); } @@ -3890,7 +3875,7 @@ compile(MyThread* t, Context* context) unsigned footprint = methodParameterFootprint(t, context->method); unsigned locals = localSize(t, context->method); - c->init(codeLength(t, methodCode(t, context->method)), locals - footprint); + c->init(codeLength(t, methodCode(t, context->method)), footprint, locals); uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))]; Frame frame(context, stackMap); diff --git a/src/compiler.cpp b/src/compiler.cpp index a1a9ea3755..65e8218922 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -91,12 +91,26 @@ class State { State* next; }; +class Local { + public: + Local(unsigned size, unsigned index, Value* value, Site* site, Local* next): + size(size), index(index), value(value), site(site), next(next) + { } + + unsigned size; + unsigned index; + Value* value; + Site* site; + Local* next; +}; + class LogicalInstruction { public: Event* firstEvent; Event* lastEvent; LogicalInstruction* immediatePredecessor; Stack* stack; + Local* locals; unsigned machineOffset; bool stackSaved; }; @@ -177,7 +191,8 @@ class Context { state(new (zone->allocate(sizeof(State))) State(0, 0)), logicalCode(0), logicalCodeLength(0), - stackOffset(0), + parameterFootprint(0), + localFootprint(0), registers (static_cast (zone->allocate(sizeof(Register*) * assembler->registerCount()))), @@ -187,6 +202,8 @@ class Context { nextSequence(0), junctions(0), machineCode(0), + locals(0), + localTable(0), stackReset(false) { for (unsigned i = 0; i < assembler->registerCount(); ++i) { @@ -206,7 +223,8 @@ class Context { State* state; LogicalInstruction* logicalCode; unsigned logicalCodeLength; - unsigned stackOffset; + unsigned parameterFootprint; + unsigned localFootprint; Register** registers; ConstantPoolNode* firstConstant; ConstantPoolNode* lastConstant; @@ -214,6 +232,8 @@ class Context { unsigned nextSequence; Junction* junctions; uint8_t* machineCode; + Local* locals; + Local** localTable; bool stackReset; }; @@ -308,8 +328,8 @@ expect(Context* c, bool v) class Event { public: Event(Context* c): - next(0), stack(c->state->stack), promises(0), reads(0), readCount(0), - sequence(c->nextSequence++), stackReset(c->stackReset) + next(0), stack(c->state->stack), locals(c->locals), promises(0), reads(0), + readCount(0), sequence(c->nextSequence++), stackReset(c->stackReset) { assert(c, c->logicalIp >= 0); @@ -327,8 +347,8 @@ class Event { } } - Event(Context*, unsigned sequence, Stack* stack): - next(0), stack(stack), promises(0), reads(0), readCount(0), + Event(Context*, unsigned sequence, Stack* stack, Local* locals): + next(0), stack(stack), locals(locals), promises(0), reads(0), readCount(0), sequence(sequence), stackReset(false) { } @@ -340,6 +360,7 @@ class Event { Event* next; Stack* stack; + Local* locals; CodePromise* promises; Read* reads; unsigned readCount; @@ -347,6 +368,19 @@ class Event { bool stackReset; }; +int +localOffset(Context* c, int v) +{ + int parameterFootprint = c->parameterFootprint * BytesPerWord; + + v *= BytesPerWord; + if (v < parameterFootprint) { + return (parameterFootprint - v - BytesPerWord) + (BytesPerWord * 2); + } else { + return -(v + BytesPerWord - parameterFootprint); + } +} + bool findSite(Context*, Value* v, Site* site) { @@ -723,7 +757,8 @@ class MemorySite: public Site { }; MemorySite* -memorySite(Context* c, int base, int offset, int index, unsigned scale) +memorySite(Context* c, int base, int offset = 0, int index = NoRegister, + unsigned scale = 1) { return new (c->zone->allocate(sizeof(MemorySite))) MemorySite(base, offset, index, scale); @@ -874,12 +909,18 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) return site; } +unsigned +stackOffset(Context* c) +{ + return c->localFootprint - c->parameterFootprint; +} + Site* pushSite(Context* c, unsigned index) { return memorySite (c, c->assembler->base(), - - (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1); + - (stackOffset(c) + index + 1) * BytesPerWord, NoRegister, 1); } void @@ -1259,6 +1300,41 @@ ignore(Context* c, unsigned count) } } +void +cleanStack(Context* c, Stack* stack, Local* locals, Read* reads) +{ + for (Local* l = locals; l; l = l->next) { + clearSites(c, l->value); + } + + for (Local* l = locals; l; l = l->next) { + addSite(c, 0, l->size * BytesPerWord, l->value, l->site); + } + + for (Stack* s = stack; s; s = s->next) { + clearSites(c, s->value); + } + + for (Stack* s = stack; s; s = s->next) { + if (s->pushSite) { + addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); + } + } + + for (Read* r = reads; r; r = r->eventNext) { + nextRead(c, r->value); + } +} + +void +resetLocals(Context* c) +{ + for (Local* l = c->locals; l; l = l->next) { + c->localTable[l->index] = 0; + } + c->locals = 0; +} + class CallEvent: public Event { public: CallEvent(Context* c, Value* address, unsigned flags, @@ -1305,6 +1381,8 @@ class CallEvent: public Event { addRead(c, s->value, s->size * BytesPerWord, virtualSite (c, 0, ~0, (static_cast(mask) << 32) | mask)); } + + resetLocals(c); } virtual void compile(Context* c) { @@ -1328,19 +1406,7 @@ class CallEvent: public Event { CodePromise(c, c->assembler->length())); } - for (Stack* s = stack; s; s = s->next) { - clearSites(c, s->value); - } - - for (Stack* s = stack; s; s = s->next) { - if (s->pushSite) { - addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); - } - } - - for (Read* r = reads; r; r = r->eventNext) { - nextRead(c, r->value); - } + cleanStack(c, stack, locals, reads); if (resultSize and result->reads) { addSite(c, 0, resultSize, result, registerSite @@ -1455,7 +1521,11 @@ class MoveEvent: public Event { nextRead(c, src); } - if (dst->reads) { + bool isStore = dst->reads == 0; + + assert(c, isStore or target != src->source or src->reads == 0); + + if (not isStore) { addSite(c, stack, size, dst, target); } @@ -1471,7 +1541,7 @@ class MoveEvent: public Event { apply(c, type, size, src->source, tmpTarget); - if (dst->reads == 0) { + if (isStore) { removeSite(c, dst, tmpTarget); apply(c, Move, size, tmpTarget, target); @@ -1481,7 +1551,7 @@ class MoveEvent: public Event { } } - if (dst->reads == 0) { + if (isStore) { removeSite(c, dst, target); } @@ -1661,6 +1731,9 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, fprintf(stderr, "appendCombine\n"); } + firstTarget->typeMask &= ~(1 << MemoryOperand); + secondTarget->typeMask &= ~(1 << MemoryOperand); + new (c->zone->allocate(sizeof(CombineEvent))) CombineEvent(c, type, size, first, second, result, firstTarget, secondTarget); @@ -1715,6 +1788,8 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, assert(c, procedure == 0); // todo + target->typeMask &= ~(1 << MemoryOperand); + new (c->zone->allocate(sizeof(TranslateEvent))) TranslateEvent(c, type, size, value, result, target); } @@ -1805,6 +1880,8 @@ resetStack(Context* c) i += s->size; } + resetLocals(c); + c->stackReset = true; } @@ -1863,8 +1940,8 @@ class StackSyncEvent: public Event { } } - StackSyncEvent(Context* c, unsigned sequence, Stack* stack): - Event(c, sequence, stack) + StackSyncEvent(Context* c, unsigned sequence, Stack* stack, Local* locals): + Event(c, sequence, stack, locals) { for (Stack* s = stack; s; s = s->next) { if (s->pushEvent) s->pushEvent->active = true; @@ -1877,19 +1954,7 @@ class StackSyncEvent: public Event { fprintf(stderr, "StackSyncEvent.compile\n"); } - for (Stack* s = stack; s; s = s->next) { - clearSites(c, s->value); - } - - for (Stack* s = stack; s; s = s->next) { - if (s->pushSite) { - addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); - } - } - - for (Read* r = reads; r; r = r->eventNext) { - nextRead(c, r->value); - } + cleanStack(c, stack, locals, reads); } }; @@ -2004,6 +2069,45 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } +class LocalEvent: public Event { + public: + LocalEvent(Context* c, unsigned size, Value* newValue, Value* oldValue, + Site* site): + Event(c), size(size), newValue(newValue), oldValue(oldValue), site(site) + { } + + virtual void compile(Context* c) { + if (DebugCompile) { + fprintf(stderr, "LocalEvent.compile\n"); + } + + if (oldValue) { + removeSite(c, oldValue, site); + } + + if (newValue->reads) { + addSite(c, 0, size, newValue, site); + } + } + + unsigned size; + Value* newValue; + Value* oldValue; + Site* site; +}; + +void +appendLocal(Context* c, unsigned size, Value* newValue, Value* oldValue, + Site* site) +{ + if (DebugAppend) { + fprintf(stderr, "appendLocal\n"); + } + + new (c->zone->allocate(sizeof(LocalEvent))) + LocalEvent(c, size, newValue, oldValue, site); +} + Site* readSource(Context* c, Stack* stack, Read* r) { @@ -2037,8 +2141,8 @@ compile(Context* c) a->apply(Move, BytesPerWord, RegisterOperand, &stack, RegisterOperand, &base); - if (c->stackOffset) { - Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); + if (stackOffset(c)) { + Assembler::Constant offset(resolved(c, stackOffset(c) * BytesPerWord)); a->apply(Subtract, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); } @@ -2120,6 +2224,7 @@ saveStack(Context* c) if (c->logicalIp >= 0 and not c->logicalCode[c->logicalIp].stackSaved) { c->logicalCode[c->logicalIp].stackSaved = true; c->logicalCode[c->logicalIp].stack = c->state->stack; + c->logicalCode[c->logicalIp].locals = c->locals; if (DebugAppend) { unsigned count = 0; @@ -2159,6 +2264,27 @@ push(Context* c, unsigned size, Value* v) appendPush(c); } +void +addLocal(Context* c, unsigned size, unsigned index, Value* newValue) +{ + Value* oldValue; + unsigned s = ceiling(size, BytesPerWord); + Local* local = c->localTable[index]; + if (local) { + oldValue = local->value; + c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) + Local(s, index, newValue, local->site, c->locals); + } else { + oldValue = 0; + c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) + Local(s, index, newValue, memorySite + (c, c->assembler->base(), localOffset(c, index)), + c->locals); + } + + appendLocal(c, s, newValue, oldValue, c->localTable[index]->site); +} + Value* pop(Context* c, unsigned size UNUSED) { @@ -2180,7 +2306,7 @@ updateJunctions(Context* c) p->lastEvent = p->lastEvent->next = new (c->zone->allocate(sizeof(StackSyncEvent))) - StackSyncEvent(c, p->lastEvent->sequence, p->stack); + StackSyncEvent(c, p->lastEvent->sequence, p->stack, p->locals); } } @@ -2255,12 +2381,20 @@ class MyCompiler: public Compiler { ::resetStack(&c); } - virtual void init(unsigned logicalCodeLength, unsigned stackOffset) { + virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint, + unsigned localFootprint) + { c.logicalCodeLength = logicalCodeLength; - c.stackOffset = stackOffset; + c.parameterFootprint = parameterFootprint; + c.localFootprint = localFootprint; + c.logicalCode = static_cast (c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength)); memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength); + + c.localTable = static_cast + (c.zone->allocate(sizeof(Local*) * localFootprint)); + memset(c.localTable, 0, sizeof(Local*) * localFootprint); } virtual void visitLogicalIp(unsigned logicalIp) { @@ -2493,6 +2627,20 @@ class MyCompiler: public Compiler { appendReturn(&c, size, static_cast(value)); } + virtual void storeLocal(unsigned size, Operand* src, unsigned index) { + assert(&c, index < c.localFootprint); + store(size, src, memory(base(), localOffset(&c, index))); + addLocal(&c, size, index, value(&c)); + } + + virtual Operand* loadLocal(unsigned size, unsigned index) { + assert(&c, index < c.localFootprint); + if (c.localTable[index] == 0) { + addLocal(&c, size, index, value(&c)); + } + return c.localTable[index]->value; + } + virtual void store(unsigned size, Operand* src, Operand* dst) { appendMove(&c, Move, size, static_cast(src), static_cast(dst)); diff --git a/src/compiler.h b/src/compiler.h index 7bb4186b56..93d4d0a351 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -32,7 +32,8 @@ class Compiler { virtual void saveStack() = 0; virtual void resetStack() = 0; - virtual void init(unsigned logicalCodeSize, unsigned localFootprint) = 0; + virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint, + unsigned localFootprint) = 0; virtual void visitLogicalIp(unsigned logicalIp) = 0; virtual void startLogicalIp(unsigned logicalIp) = 0; @@ -76,6 +77,9 @@ class Compiler { virtual void return_(unsigned size, Operand* value) = 0; + virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0; + virtual Operand* loadLocal(unsigned size, unsigned index) = 0; + virtual void store(unsigned size, Operand* src, Operand* dst) = 0; virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; From b52cefa86e3208172ac6a7e612c595d87e321a73 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 07:27:05 -0600 Subject: [PATCH 103/121] disallow memory operands in 32-bit comparisons on amd64 --- src/compiler.cpp | 20 ++++++++++++++++---- src/x86.cpp | 15 ++++++++++++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 65e8218922..d3aa2751cf 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1592,11 +1592,12 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, class CompareEvent: public Event { public: - CompareEvent(Context* c, unsigned size, Value* first, Value* second): + CompareEvent(Context* c, unsigned size, Value* first, Value* second, + Site* firstTarget, Site* secondTarget): Event(c), size(size), first(first), second(second) { - addRead(c, first, size, 0); - addRead(c, second, size, 0); + addRead(c, first, size, firstTarget); + addRead(c, second, size, secondTarget); } virtual void compile(Context* c) { @@ -1618,12 +1619,23 @@ class CompareEvent: public Event { void appendCompare(Context* c, unsigned size, Value* first, Value* second) { + VirtualSite* firstTarget = virtualSite(c); + VirtualSite* secondTarget = virtualSite(c); + uintptr_t procedure; + + c->assembler->plan(Compare, size, + &(firstTarget->typeMask), &(firstTarget->registerMask), + &(secondTarget->typeMask), &(secondTarget->registerMask), + &procedure); + + assert(c, procedure == 0); // todo + if (DebugAppend) { fprintf(stderr, "appendCompare\n"); } new (c->zone->allocate(sizeof(CompareEvent))) - CompareEvent(c, size, first, second); + CompareEvent(c, size, first, second, firstTarget, secondTarget); } void diff --git a/src/x86.cpp b/src/x86.cpp index c45ef7ea44..efa90b52a7 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1928,7 +1928,7 @@ class MyAssembler: public Assembler { uint64_t* aRegisterMask, uint8_t* bTypeMask, uint64_t* bRegisterMask, uintptr_t* procedure) { - *aTypeMask = ~static_cast(0); + *aTypeMask = ~0; *aRegisterMask = ~static_cast(0); *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); @@ -1937,6 +1937,15 @@ class MyAssembler: public Assembler { *procedure = 0; switch (op) { + case Compare: + if (BytesPerWord == 8 and size != 8) { + *aTypeMask = ~(1 << MemoryOperand); + *bTypeMask = ~(1 << MemoryOperand); + } else { + *bTypeMask = ~0; + } + break; + case Move: if (BytesPerWord == 4 and size == 1) { const uint32_t mask @@ -1965,7 +1974,7 @@ class MyAssembler: public Assembler { case Divide: if (BytesPerWord == 4 and size == 8) { - *bTypeMask = ~static_cast(0); + *bTypeMask = ~0; *procedure = reinterpret_cast(divideLong); } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); @@ -1975,7 +1984,7 @@ class MyAssembler: public Assembler { case Remainder: if (BytesPerWord == 4 and size == 8) { - *bTypeMask = ~static_cast(0); + *bTypeMask = ~0; *procedure = reinterpret_cast(moduloLong); } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); From ad6153612b3c4797a4a5ed3e7ce64be710656e42 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 07:43:37 -0600 Subject: [PATCH 104/121] disallow memory,constant comparisons on x86 --- src/x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index efa90b52a7..9e95005c59 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1942,7 +1942,7 @@ class MyAssembler: public Assembler { *aTypeMask = ~(1 << MemoryOperand); *bTypeMask = ~(1 << MemoryOperand); } else { - *bTypeMask = ~0; + *bTypeMask = ~(1 << ConstantOperand); } break; From 08a1921eb79e49cf4c369bfd0aea8114238a446d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 07:44:39 -0600 Subject: [PATCH 105/121] only set target equal to src->source in MoveEvent.compile if it is a simple load or store --- src/compiler.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index d3aa2751cf..9d00f5dc4e 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1500,6 +1500,9 @@ class MoveEvent: public Event { fprintf(stderr, "MoveEvent.compile\n"); } + bool isLoad = src->reads->next == 0; + bool isStore = dst->reads == 0; + Site* target; unsigned cost; if (type == Move @@ -1512,7 +1515,7 @@ class MoveEvent: public Event { } else { target = targetOrRegister(c, dst); cost = src->source->copyCost(c, target); - if (cost == 0) { + if (cost == 0 and (isLoad or isStore)) { target = src->source; } } @@ -1521,9 +1524,7 @@ class MoveEvent: public Event { nextRead(c, src); } - bool isStore = dst->reads == 0; - - assert(c, isStore or target != src->source or src->reads == 0); + assert(c, isLoad or isStore or target != src->source); if (not isStore) { addSite(c, stack, size, dst, target); From 292f84a3fac399e85852c0fa0bd1b6731dfa7a1c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 08:50:37 -0600 Subject: [PATCH 106/121] fix thinko in laload implementation --- src/compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index 4f68d10a7e..4fee8788b7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1818,7 +1818,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case daload: case laload: - frame->pushInt(c->load(8, c->memory(array, ArrayBody + (i * 8)))); + frame->pushLong(c->load(8, c->memory(array, ArrayBody + (i * 8)))); break; case saload: From 83da1ec205412dfd7095806f78f0c717fa9473ff Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 08:53:40 -0600 Subject: [PATCH 107/121] preserve old value of local variable across store if it will be used later; tweak site ownership transfer in MoveEvent.compile --- src/compiler.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 9d00f5dc4e..e9540c4306 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1520,12 +1520,12 @@ class MoveEvent: public Event { } } - if (target == src->source) { - nextRead(c, src); - } - assert(c, isLoad or isStore or target != src->source); + if (target == src->source) { + removeSite(c, src, target); + } + if (not isStore) { addSite(c, stack, size, dst, target); } @@ -1556,9 +1556,7 @@ class MoveEvent: public Event { removeSite(c, dst, target); } - if (target != src->source) { - nextRead(c, src); - } + nextRead(c, src); } BinaryOperation type; @@ -1639,15 +1637,22 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second) CompareEvent(c, size, first, second, firstTarget, secondTarget); } +void +preserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s, + Read* read) +{ + assert(c, v->sites == s); + Site* r = targetOrNull(c, read); + if (r == 0 or r == s) r = freeRegisterSite(c); + addSite(c, stack, size, v, r); + apply(c, Move, size, s, r); +} + void maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { if (v->reads->next and v->sites->next == 0) { - assert(c, v->sites == s); - Site* r = targetOrNull(c, v->reads->next); - if (r == 0 or r == s) r = freeRegisterSite(c); - addSite(c, stack, size, v, r); - apply(c, Move, size, s, r); + preserve(c, stack, size, v, s, v->reads->next); } } @@ -2095,6 +2100,12 @@ class LocalEvent: public Event { } if (oldValue) { + if (oldValue->reads + and oldValue->sites->next == 0 + and oldValue->sites == site) + { + preserve(c, stack, size, oldValue, site, oldValue->reads); + } removeSite(c, oldValue, site); } From 983e64c86affd19ed000fa719581f388304ccea0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 10:14:54 -0600 Subject: [PATCH 108/121] preserve old value of local variable *before* it is overwritten --- src/compiler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index e9540c4306..ddbda59956 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2306,7 +2306,8 @@ addLocal(Context* c, unsigned size, unsigned index, Value* newValue) c->locals); } - appendLocal(c, s, newValue, oldValue, c->localTable[index]->site); + appendLocal(c, s * BytesPerWord, newValue, oldValue, + c->localTable[index]->site); } Value* @@ -2653,8 +2654,8 @@ class MyCompiler: public Compiler { virtual void storeLocal(unsigned size, Operand* src, unsigned index) { assert(&c, index < c.localFootprint); - store(size, src, memory(base(), localOffset(&c, index))); addLocal(&c, size, index, value(&c)); + store(size, src, memory(base(), localOffset(&c, index))); } virtual Operand* loadLocal(unsigned size, unsigned index) { From 651c4559dbf50c584b526c9223bca7ef4e14e1ba Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 19 May 2008 10:39:05 -0600 Subject: [PATCH 109/121] implement compareAR --- src/x86.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/x86.cpp b/src/x86.cpp index 9e95005c59..727020a502 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1599,6 +1599,18 @@ compareRR(Context* c, unsigned size, Assembler::Register* a, } } +void +compareAR(Context* c, unsigned size, Assembler::Address* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + Assembler::Register tmp(c->client->acquireTemporary()); + moveAR(c, size, a, &tmp); + compareRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); +} + void compareCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) @@ -1840,6 +1852,7 @@ populateTables() BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC); BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR); + BinaryOperations[INDEX2(Compare, Address, Register)] = CAST2(compareAR); BinaryOperations[INDEX2(Compare, Register, Memory)] = CAST2(compareRM); BinaryOperations[INDEX2(Compare, Memory, Register)] = CAST2(compareMR); BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); From d604efd8f591c29dcda8c94e437f63652b062c9f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 20 May 2008 13:11:42 -0600 Subject: [PATCH 110/121] fix local variable caching bug --- src/compiler.cpp | 118 +++++++++++++++++++++++++++++++++-------------- test/Misc.java | 41 ++++++++++++++++ 2 files changed, 124 insertions(+), 35 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index ddbda59956..a50d99002c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -94,11 +94,12 @@ class State { class Local { public: Local(unsigned size, unsigned index, Value* value, Site* site, Local* next): - size(size), index(index), value(value), site(site), next(next) + size(size), index(index), reuse(true), value(value), site(site), next(next) { } unsigned size; unsigned index; + bool reuse; Value* value; Site* site; Local* next; @@ -1304,11 +1305,7 @@ void cleanStack(Context* c, Stack* stack, Local* locals, Read* reads) { for (Local* l = locals; l; l = l->next) { - clearSites(c, l->value); - } - - for (Local* l = locals; l; l = l->next) { - addSite(c, 0, l->size * BytesPerWord, l->value, l->site); + l->reuse = false; } for (Stack* s = stack; s; s = s->next) { @@ -2087,49 +2084,96 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } +class ClobberLocalEvent: public Event { + public: + ClobberLocalEvent(Context* c, unsigned size, Local* local): + Event(c), size(size), local(local) + { } + + virtual void compile(Context* c) { + if (DebugCompile) { + fprintf(stderr, "ClobberLocalEvent.compile\n"); + } + + Value* v = local->value; + Site* s = local->site; + if (v->reads + and v->sites->next == 0 + and v->sites == s) + { + preserve(c, stack, size, v, s, v->reads); + } + removeSite(c, v, s); + } + + unsigned size; + Local* local; +}; + +void +appendClobberLocal(Context* c, unsigned size, Local* local) +{ + if (DebugAppend) { + fprintf(stderr, "appendClobberLocal\n"); + } + + new (c->zone->allocate(sizeof(ClobberLocalEvent))) + ClobberLocalEvent(c, size, local); +} + class LocalEvent: public Event { public: - LocalEvent(Context* c, unsigned size, Value* newValue, Value* oldValue, - Site* site): - Event(c), size(size), newValue(newValue), oldValue(oldValue), site(site) - { } + LocalEvent(Context* c, unsigned size, Local* oldLocal, Local* newLocal): + Event(c), size(size), oldLocal(oldLocal), newLocal(newLocal) + { + if (oldLocal) { + addRead(c, oldLocal->value, size, 0); + } + } virtual void compile(Context* c) { if (DebugCompile) { fprintf(stderr, "LocalEvent.compile\n"); } - if (oldValue) { - if (oldValue->reads - and oldValue->sites->next == 0 - and oldValue->sites == site) - { - preserve(c, stack, size, oldValue, site, oldValue->reads); + Site* sites = 0; + if (oldLocal) { + Value* v = oldLocal->value; + if (oldLocal->reuse and v->reads->next == 0) { + sites = v->sites; } - removeSite(c, oldValue, site); + + nextRead(c, v); } - if (newValue->reads) { - addSite(c, 0, size, newValue, site); + Value* v = newLocal->value; + if (v->reads) { + for (Site* s = sites; s;) { + Site* t = s->next; + if (s->type(c) != MemoryOperand) { + addSite(c, stack, size, v, s); + } + s = t; + } + + addSite(c, 0, size, v, newLocal->site); } } unsigned size; - Value* newValue; - Value* oldValue; - Site* site; + Local* oldLocal; + Local* newLocal; }; void -appendLocal(Context* c, unsigned size, Value* newValue, Value* oldValue, - Site* site) +appendLocal(Context* c, unsigned size, Local* oldLocal, Local* newLocal) { if (DebugAppend) { fprintf(stderr, "appendLocal\n"); } new (c->zone->allocate(sizeof(LocalEvent))) - LocalEvent(c, size, newValue, oldValue, site); + LocalEvent(c, size, oldLocal, newLocal); } Site* @@ -2291,23 +2335,19 @@ push(Context* c, unsigned size, Value* v) void addLocal(Context* c, unsigned size, unsigned index, Value* newValue) { - Value* oldValue; unsigned s = ceiling(size, BytesPerWord); Local* local = c->localTable[index]; if (local) { - oldValue = local->value; c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) Local(s, index, newValue, local->site, c->locals); } else { - oldValue = 0; c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) Local(s, index, newValue, memorySite (c, c->assembler->base(), localOffset(c, index)), c->locals); } - appendLocal(c, s * BytesPerWord, newValue, oldValue, - c->localTable[index]->site); + appendLocal(c, s * BytesPerWord, local, c->locals); } Value* @@ -2654,16 +2694,24 @@ class MyCompiler: public Compiler { virtual void storeLocal(unsigned size, Operand* src, unsigned index) { assert(&c, index < c.localFootprint); - addLocal(&c, size, index, value(&c)); + + if (c.localTable[index]) { + appendClobberLocal(&c, size, c.localTable[index]); + c.localTable[index] = 0; + } + store(size, src, memory(base(), localOffset(&c, index))); + + // todo: find out why this doesn't work and fix it: +// addLocal(&c, size, index, static_cast(src)); } virtual Operand* loadLocal(unsigned size, unsigned index) { assert(&c, index < c.localFootprint); - if (c.localTable[index] == 0) { - addLocal(&c, size, index, value(&c)); - } - return c.localTable[index]->value; + + Value* v = value(&c); + addLocal(&c, size, index, v); + return v; } virtual void store(unsigned size, Operand* src, Operand* dst) { diff --git a/test/Misc.java b/test/Misc.java index 489386a3f5..8dca62403f 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -78,7 +78,22 @@ public class Misc { return zap() + 5; } + private static class Foo { + public int a; + public int b; + public int c; + } + + private static int bar(int a, int b, int c) { + return a + b + c; + } + public static void main(String[] args) { + { Foo foo = new Foo(); + int x = foo.a + foo.b + foo.c; + bar(foo.a, foo.b, foo.c); + } + { int get_buffer = 2144642881; int bits_left = 30; int l = 9; @@ -254,9 +269,35 @@ public class Misc { expect(exception != null); } + { int[] array = new int[3]; + int i = 0; + array[i++] = 1; + array[i++] = 2; + array[i++] = 3; + + expect(array[--i] == 3); + expect(array[--i] == 2); + expect(array[--i] == 1); + } + { Object[][] array = new Object[1][1]; expect(array.length == 1); expect(array[0].length == 1); } + + { + Object a = new Object(); + Object b = new Object(); + expect(a != b); + + Object c = a; + Object d = b; + expect(c != d); + + c = (c == a) ? b : a; + d = (d == a) ? b : a; + + expect(c != d); + } } } From 36dbf1ad14a34493edf3e549ba89c40bd634e6ad Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 20 May 2008 15:24:10 -0600 Subject: [PATCH 111/121] fix another local variable caching bug --- src/compiler.cpp | 72 +++++++++++++++++++++++------------------------- test/Misc.java | 6 ++++ 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index a50d99002c..1dbacd819d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -93,8 +93,10 @@ class State { class Local { public: - Local(unsigned size, unsigned index, Value* value, Site* site, Local* next): - size(size), index(index), reuse(true), value(value), site(site), next(next) + Local(unsigned size, unsigned index, Value* value, Site* site, Local* old, + Local* next): + size(size), index(index), reuse(true), value(value), site(site), old(old), + next(next) { } unsigned size; @@ -102,6 +104,7 @@ class Local { bool reuse; Value* value; Site* site; + Local* old; Local* next; }; @@ -2095,15 +2098,17 @@ class ClobberLocalEvent: public Event { fprintf(stderr, "ClobberLocalEvent.compile\n"); } - Value* v = local->value; - Site* s = local->site; - if (v->reads - and v->sites->next == 0 - and v->sites == s) - { - preserve(c, stack, size, v, s, v->reads); + for (Local* l = local; l; l = l->old) { + Value* v = l->value; + Site* s = l->site; + if (v->reads + and v->sites->next == 0 + and v->sites == s) + { + preserve(c, stack, size, v, s, v->reads); + } + removeSite(c, v, s); } - removeSite(c, v, s); } unsigned size; @@ -2123,11 +2128,11 @@ appendClobberLocal(Context* c, unsigned size, Local* local) class LocalEvent: public Event { public: - LocalEvent(Context* c, unsigned size, Local* oldLocal, Local* newLocal): - Event(c), size(size), oldLocal(oldLocal), newLocal(newLocal) + LocalEvent(Context* c, unsigned size, Local* local): + Event(c), size(size), local(local) { - if (oldLocal) { - addRead(c, oldLocal->value, size, 0); + if (local->old) { + addRead(c, local->old->value, size, 0); } } @@ -2137,43 +2142,41 @@ class LocalEvent: public Event { } Site* sites = 0; - if (oldLocal) { - Value* v = oldLocal->value; - if (oldLocal->reuse and v->reads->next == 0) { + if (local->old) { + Value* v = local->old->value; + if (local->old->reuse and v->reads->next == 0) { sites = v->sites; } nextRead(c, v); } - Value* v = newLocal->value; + Value* v = local->value; if (v->reads) { for (Site* s = sites; s;) { Site* t = s->next; if (s->type(c) != MemoryOperand) { - addSite(c, stack, size, v, s); + addSite(c, 0, size, v, s); } s = t; } - addSite(c, 0, size, v, newLocal->site); + addSite(c, 0, size, v, local->site); } } unsigned size; - Local* oldLocal; - Local* newLocal; + Local* local; }; void -appendLocal(Context* c, unsigned size, Local* oldLocal, Local* newLocal) +appendLocal(Context* c, unsigned size, Local* local) { if (DebugAppend) { fprintf(stderr, "appendLocal\n"); } - new (c->zone->allocate(sizeof(LocalEvent))) - LocalEvent(c, size, oldLocal, newLocal); + new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local); } Site* @@ -2335,19 +2338,14 @@ push(Context* c, unsigned size, Value* v) void addLocal(Context* c, unsigned size, unsigned index, Value* newValue) { - unsigned s = ceiling(size, BytesPerWord); - Local* local = c->localTable[index]; - if (local) { - c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) - Local(s, index, newValue, local->site, c->locals); - } else { - c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) - Local(s, index, newValue, memorySite - (c, c->assembler->base(), localOffset(c, index)), - c->locals); - } + unsigned sizeInWords = ceiling(size, BytesPerWord); - appendLocal(c, s * BytesPerWord, local, c->locals); + c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) + Local(sizeInWords, index, newValue, memorySite + (c, c->assembler->base(), localOffset(c, index)), + c->localTable[index], c->locals); + + appendLocal(c, sizeInWords * BytesPerWord, c->locals); } Value* diff --git a/test/Misc.java b/test/Misc.java index 8dca62403f..9b570794d3 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -82,6 +82,7 @@ public class Misc { public int a; public int b; public int c; + public int[] array; } private static int bar(int a, int b, int c) { @@ -299,5 +300,10 @@ public class Misc { expect(c != d); } + + { Foo foo = new Foo(); + foo.array = new int[3]; + foo.a = (foo.a + 1) % foo.array.length; + } } } From 21cb1c3c8fe6c7f9d0921cb6a016874a10a627c1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 20 May 2008 16:47:53 -0600 Subject: [PATCH 112/121] remove Event::validate, since it is no longer needed and actually causes trouble --- src/compiler.cpp | 19 ++++++------------- test/Misc.java | 7 +++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 1dbacd819d..e890b589d3 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -55,8 +55,6 @@ class Site { virtual void thaw(Context*) { } - virtual void validate(Context*, Stack*, unsigned, Value*) { } - virtual OperandType type(Context*) = 0; virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; @@ -581,7 +579,12 @@ class RegisterSite: public Site { } virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) { - validate(c, stack, size, v); + low = ::validate(c, mask, stack, size, v, this, low); + if (size > BytesPerWord) { + ::freeze(low); + high = ::validate(c, mask >> 32, stack, size, v, this, high); + ::thaw(low); + } } virtual void release(Context* c) { @@ -611,15 +614,6 @@ class RegisterSite: public Site { } } - virtual void validate(Context* c, Stack* stack, unsigned size, Value* v) { - low = ::validate(c, mask, stack, size, v, this, low); - if (size > BytesPerWord) { - ::freeze(low); - high = ::validate(c, mask >> 32, stack, size, v, this, high); - ::thaw(low); - } - } - virtual OperandType type(Context*) { return RegisterOperand; } @@ -2196,7 +2190,6 @@ readSource(Context* c, Stack* stack, Read* r) apply(c, Move, r->size, site, target); return target; } else { - site->validate(c, stack, r->size, r->value); return site; } } diff --git a/test/Misc.java b/test/Misc.java index 9b570794d3..5ccc1df9d9 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -89,7 +89,14 @@ public class Misc { return a + b + c; } + private static long roundUp(long a, long b) { + a += b - 1L; + return a - (a % b); + } + public static void main(String[] args) { + expect(roundUp(156, 2) == 156); + { Foo foo = new Foo(); int x = foo.a + foo.b + foo.c; bar(foo.a, foo.b, foo.c); From 3326aafdacf32bb6ba65326202398274bed90f32 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 22 May 2008 11:15:18 -0600 Subject: [PATCH 113/121] various 32-bit fixes --- src/compiler.cpp | 11 +++- src/x86.cpp | 145 +++++++++++++++++++++++++++-------------------- test/Misc.java | 12 ++++ 3 files changed, 102 insertions(+), 66 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index e890b589d3..b69bd94c64 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -768,9 +768,14 @@ matchRegister(Context* c UNUSED, Site* s, uint64_t mask) assert(c, s->type(c) == RegisterOperand); RegisterSite* r = static_cast(s); - return ((static_cast(1) << r->register_.low) & mask) - and (r->register_.high == NoRegister - or ((static_cast(1) << (r->register_.high + 32)) & mask)); + if (r->low) { + r->sync(c); + return ((static_cast(1) << r->register_.low) & mask) + and (r->register_.high == NoRegister + or ((static_cast(1) << (r->register_.high + 32)) & mask)); + } else { + return false; + } } bool diff --git a/src/x86.cpp b/src/x86.cpp index 727020a502..658138e8c2 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -697,12 +697,17 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: - assert(c, BytesPerWord == 8 or (a->low <= rbx and b->low <= rbx)); + if (BytesPerWord == 4 and a->low > rbx) { + assert(c, b->low <= rbx); - rex(c); - c->code.append(0x0f); - c->code.append(0xbe); - c->code.append(0xc0 | (b->low << 3) | a->low); + moveRR(c, BytesPerWord, a, b); + moveRR(c, 1, b, b); + } else { + rex(c); + c->code.append(0x0f); + c->code.append(0xbe); + c->code.append(0xc0 | (b->low << 3) | a->low); + } break; case 2: @@ -1575,6 +1580,27 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, doShift(c, unsignedShiftRightRR, 0xe8, size, a, b); } +void +multiwordCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah, + Assembler::Operand* bl, Assembler::Operand* bh, + BinaryOperationType op) +{ + op(c, BytesPerWord, ah, bh); + + // 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 + + unsigned comparisonOffset = c->code.length(); + c->code.append4(0); + + op(c, BytesPerWord, al, bl); + + int32_t comparisonSize = c->code.length() - comparisonOffset - 4; + c->code.set(comparisonOffset, &comparisonSize, 4); +} + void compareRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -1583,15 +1609,7 @@ compareRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register ah(a->high); Assembler::Register bh(b->high); - compareRR(c, 4, &ah, &bh); - - // 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); - - compareRR(c, 4, a, b); + multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRR)); } else { if (size == 8) rex(c); c->code.append(0x39); @@ -1626,20 +1644,7 @@ compareCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register bh(b->high); - compareCR(c, 4, &ah, &bh); - - // 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 - - unsigned comparisonOffset = c->code.length(); - c->code.append4(0); - - compareCR(c, 4, &al, b); - - int32_t comparisonSize = c->code.length() - comparisonOffset - 4; - c->code.set(comparisonOffset, &comparisonSize, 4); + multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCR)); } else { if (isInt32(v)) { if (size == 8) rex(c); @@ -1676,20 +1681,7 @@ compareCM(Context* c, unsigned size, Assembler::Constant* a, Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - compareCM(c, 4, &ah, &bh); - - // 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 - - unsigned comparisonOffset = c->code.length(); - c->code.append4(0); - - compareCM(c, 4, &al, b); - - int32_t comparisonSize = c->code.length() - comparisonOffset - 4; - c->code.set(comparisonOffset, &comparisonSize, 4); + multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCM)); } else { encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); @@ -1707,48 +1699,75 @@ void compareRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); + Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - if (BytesPerWord == 8 and size == 4) { - move4To8RR(c, size, a, a); + multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRM)); + } else { + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, a, a); + } + encode(c, 0x39, a->low, b, true); } - encode(c, 0x39, a->low, b, true); } void -compareMR(Context* c, unsigned size UNUSED, Assembler::Memory* a, +compareMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); + Assembler::Register bh(b->high); - if (BytesPerWord == 8 and size == 4) { - move4To8RR(c, size, b, b); + multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMR)); + } else { + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, b, b); + } + encode(c, 0x3b, b->low, a, true); } - encode(c, 0x3b, b->low, a, true); } void -compareMM(Context* c, unsigned size UNUSED, Assembler::Memory* a, +compareMM(Context* c, unsigned size, Assembler::Memory* a, Assembler::Memory* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); + Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, size, a, &tmp); - compareRM(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMM)); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + compareRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); + } } void -compareRC(Context* c, unsigned size UNUSED, Assembler::Register* a, +compareRC(Context* c, unsigned size, Assembler::Register* a, Assembler::Constant* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + if (BytesPerWord == 4 and size == 8) { + Assembler::Register ah(a->high); - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, b, &tmp); - compareRR(c, size, a, &tmp); - c->client->releaseTemporary(tmp.low); + int64_t v = b->value->value(); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant bl(&low); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant bh(&high); + + multiwordCompare(c, a, &ah, &bl, &bh, CAST2(compareRC)); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, b, &tmp); + compareRR(c, size, a, &tmp); + c->client->releaseTemporary(tmp.low); + } } void diff --git a/test/Misc.java b/test/Misc.java index 5ccc1df9d9..483ba73820 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -312,5 +312,17 @@ public class Misc { foo.array = new int[3]; foo.a = (foo.a + 1) % foo.array.length; } + + { int j = 0; + byte[] decodeTable = new byte[256]; + for (int i = 'A'; i <= 'Z'; ++i) decodeTable[i] = (byte) j++; + for (int i = 'a'; i <= 'z'; ++i) decodeTable[i] = (byte) j++; + for (int i = '0'; i <= '9'; ++i) decodeTable[i] = (byte) j++; + decodeTable['+'] = (byte) j++; + decodeTable['/'] = (byte) j++; + decodeTable['='] = 0; + + expect(decodeTable['a'] != 0); + } } } From f05318b78785fa7dbd5718caee08b7b5da0bc19f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 22 May 2008 18:08:41 -0600 Subject: [PATCH 114/121] fix thinkos in d2i and friends --- src/compile.cpp | 15 ++++++++++----- test/Floats.java | 13 +++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 4fee8788b7..f11b69d367 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2094,21 +2094,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call (c->constant(reinterpret_cast(doubleToFloat)), - Compiler::Indirect, 0, 4, 1, frame->popLong())); + Compiler::Indirect, 0, 4, 2, + static_cast(0), frame->popLong())); } break; case d2i: { frame->pushInt (c->call (c->constant(reinterpret_cast(doubleToInt)), - Compiler::Indirect, 0, 4, 1, frame->popLong())); + Compiler::Indirect, 0, 4, 2, + static_cast(0), frame->popLong())); } break; case d2l: { frame->pushLong (c->call (c->constant(reinterpret_cast(doubleToLong)), - Compiler::Indirect, 0, 8, 1, frame->popLong())); + Compiler::Indirect, 0, 8, 2, + static_cast(0), frame->popLong())); } break; case dadd: { @@ -2866,14 +2869,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call (c->constant(reinterpret_cast(longToDouble)), - Compiler::Indirect, 0, 8, 1, frame->popLong())); + Compiler::Indirect, 0, 8, 2, + static_cast(0), frame->popLong())); } break; case l2f: { frame->pushInt (c->call (c->constant(reinterpret_cast(longToFloat)), - Compiler::Indirect, 0, 4, 1, frame->popLong())); + Compiler::Indirect, 0, 4, 2, + static_cast(0), frame->popLong())); } break; case l2i: diff --git a/test/Floats.java b/test/Floats.java index 4db89a233c..655935d03f 100644 --- a/test/Floats.java +++ b/test/Floats.java @@ -32,5 +32,18 @@ public class Floats { expect(divide(0.5d, 0.5d) == 1.0d); expect(subtract(0.5d, 0.5d) == 0.0d); + + double d = 1d; + expect(((int) d) == 1); + + expect(Math.round(0.4f) == 0); + expect(Math.round(0.5f) == 1); + expect(Math.round(1.0f) == 1); + expect(Math.round(1.9f) == 2); + + expect(Math.round(0.4d) == 0); + expect(Math.round(0.5d) == 1); + expect(Math.round(1.0d) == 1); + expect(Math.round(1.9d) == 2); } } From 51256f3cc2b846a9dfbbdb562b1613343bab454a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 22 May 2008 18:16:44 -0600 Subject: [PATCH 115/121] fix moveCM for 64-bit constants on 64-bit machines --- src/x86.cpp | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 658138e8c2..67a2e59eac 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -648,7 +648,23 @@ moveCM(Context* c, unsigned size, Assembler::Constant* a, { int64_t v = a->value->value(); - if (BytesPerWord == 4 and size == 8) { + switch (size) { + case 1: + encode(c, 0xc6, 0, b, false); + c->code.append(a->value->value()); + break; + + case 2: + encode2(c, 0x66c7, 0, b, false); + c->code.append2(a->value->value()); + break; + + case 4: + encode(c, 0xc7, 0, b, true); + c->code.append4(a->value->value()); + break; + + case 8: { ResolvedPromise high((v >> 32) & 0xFFFFFFFF); Assembler::Constant ah(&high); @@ -659,28 +675,9 @@ moveCM(Context* c, unsigned size, Assembler::Constant* a, moveCM(c, 4, &al, b); moveCM(c, 4, &ah, &bh); - } else if (BytesPerWord == 8 and size == 4) { - encode(c, 0xc7, 0, b, false); - c->code.append4(a->value->value()); - } else { - switch (size) { - case 1: - encode(c, 0xc6, 0, b, false); - c->code.append(a->value->value()); - break; + } break; - case 2: - encode2(c, 0x66c7, 0, b, false); - c->code.append2(a->value->value()); - break; - - case BytesPerWord: - encode(c, 0xc7, 0, b, true); - c->code.append4(a->value->value()); - break; - - default: abort(c); - } + default: abort(c); } } From 65830a76c50d1e9166c30aac3c09a2a74bd05f5f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 31 May 2008 16:14:27 -0600 Subject: [PATCH 116/121] improve efficiency of array bounds checks and generate a thunk table for native functions called indirectly --- src/assembler.h | 4 +- src/compile.cpp | 703 +++++++++++++++++++++++++---------------------- src/compiler.cpp | 180 +++++++++--- src/compiler.h | 14 +- src/thunks.cpp | 44 +++ src/x86.cpp | 39 ++- 6 files changed, 595 insertions(+), 389 deletions(-) create mode 100644 src/thunks.cpp diff --git a/src/assembler.h b/src/assembler.h index 44c127db05..e597554ee8 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -159,11 +159,11 @@ class Assembler { virtual int argumentRegister(unsigned index) = 0; virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, - uint64_t* registerMask, uintptr_t* procedure) = 0; + uint64_t* registerMask, bool* thunk) = 0; virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask, uint64_t* aRegisterMask, uint8_t* bTypeMask, - uint64_t* bRegisterMask, uintptr_t* procedure) = 0; + uint64_t* bRegisterMask, bool* thunk) = 0; virtual void apply(Operation op) = 0; diff --git a/src/compile.cpp b/src/compile.cpp index f11b69d367..0a61e7a3c8 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = false; +const bool Verbose = true; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -438,6 +438,19 @@ makeRootTable(MyThread* t, Zone* zone, object method) return table; } +enum Thunk { +#define THUNK(s) s##Thunk, + +#include "thunks.cpp" + +#undef THUNK +}; + +const unsigned ThunkCount = gcIfNecessaryThunk + 1; + +intptr_t +getThunk(MyThread* t, Thunk thunk); + class Context { public: class MyProtector: public Thread::Protector { @@ -459,11 +472,43 @@ class Context { Context* c; }; - Context(MyThread* t, object method, void* indirection): + class MyClient: public Compiler::Client { + public: + MyClient(MyThread* t): t(t) { } + + virtual intptr_t getThunk(UnaryOperation, unsigned) { + abort(t); + } + + virtual intptr_t getThunk(BinaryOperation op, unsigned size) { + switch (op) { + case Divide: + if (size == 8) { + return ::getThunk(t, divideLongThunk); + } + break; + + case Remainder: + if (size == 8) { + return ::getThunk(t, moduloLongThunk); + } + break; + + default: break; + } + + abort(t); + } + + MyThread* t; + }; + + Context(MyThread* t, object method): thread(t), zone(t->m->system, t->m->heap, 16 * 1024), assembler(makeAssembler(t->m->system, t->m->heap, &zone)), - compiler(makeCompiler(t->m->system, assembler, &zone, indirection)), + client(t), + compiler(makeCompiler(t->m->system, assembler, &zone, &client)), method(method), objectPool(0), traceLog(0), @@ -478,6 +523,7 @@ class Context { thread(t), zone(t->m->system, t->m->heap, LikelyPageSizeInBytes), assembler(makeAssembler(t->m->system, t->m->heap, &zone)), + client(t), compiler(0), method(0), objectPool(0), @@ -497,6 +543,7 @@ class Context { MyThread* thread; Zone zone; Assembler* assembler; + MyClient client; Compiler* compiler; object method; PoolElement* objectPool; @@ -1323,13 +1370,13 @@ negateFloat(uint32_t a) return floatToBits(- bitsToFloat(a)); } -int64_t +int64_t FORCE_ALIGN divideLong(int64_t b, int64_t a) { return a / b; } -int64_t +int64_t FORCE_ALIGN moduloLong(int64_t b, int64_t a) { return a % b; @@ -1495,13 +1542,36 @@ makeMultidimensionalArray(MyThread* t, object class_, int32_t dimensions, } } -void NO_RETURN FORCE_ALIGN -throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index) +unsigned +traceSize(Thread* t) { - object message = makeString - (t, "array of length %d indexed at %d", - cast(array, BytesPerWord), index); - t->exception = makeArrayIndexOutOfBoundsException(t, message); + class Counter: public Processor::StackVisitor { + public: + Counter(): count(0) { } + + virtual bool visit(Processor::StackWalker*) { + ++ count; + return true; + } + + unsigned count; + } counter; + + t->m->processor->walkStack(t, &counter); + + return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray) + + (counter.count * FixedSizeOfTraceElement); +} + +void NO_RETURN FORCE_ALIGN +throwArrayIndexOutOfBounds(MyThread* t) +{ + ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t)); + + t->tracing = true; + t->exception = makeArrayIndexOutOfBoundsException(t, 0); + t->tracing = false; + unwind(t); } @@ -1598,10 +1668,13 @@ emptyMethod(MyThread* t, object method) } object -defaultCompiled(MyThread* t); +defaultThunk(MyThread* t); object -nativeCompiled(MyThread* t); +nativeThunk(MyThread* t); + +object +aioobThunk(MyThread* t); void compileDirectInvoke(MyThread* t, Frame* frame, object target) @@ -1617,16 +1690,16 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) result = c->call (c->constant (reinterpret_cast - (&singletonBody(t, nativeCompiled(t), 0))), + (&singletonBody(t, nativeThunk(t), 0))), 0, frame->trace(target, false), rSize, 0); - } else if (methodCompiled(t, target) == defaultCompiled(t)) { + } else if (methodCompiled(t, target) == defaultThunk(t)) { result = c->call (c->constant (reinterpret_cast - (&singletonBody(t, defaultCompiled(t), 0))), + (&singletonBody(t, defaultThunk(t), 0))), Compiler::Aligned, frame->trace(target, false), rSize, @@ -1666,7 +1739,7 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) } c->call(c->constant(function), - Compiler::Indirect, + 0, frame->trace(0, false), 0, 2, c->thread(), lock); @@ -1692,14 +1765,14 @@ handleEntrance(MyThread* t, Frame* frame) } handleMonitorEvent - (t, frame, reinterpret_cast(acquireMonitorForObject)); + (t, frame, getThunk(t, acquireMonitorForObjectThunk)); } void handleExit(MyThread* t, Frame* frame) { handleMonitorEvent - (t, frame, reinterpret_cast(releaseMonitorForObject)); + (t, frame, getThunk(t, releaseMonitorForObjectThunk)); } void @@ -1733,8 +1806,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject(); c->call - (c->constant(reinterpret_cast(gcIfNecessary)), - Compiler::Indirect, + (c->constant(getThunk(t, gcIfNecessaryThunk)), + 0, frame->trace(0, false), 0, 1, c->thread()); @@ -1753,47 +1826,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iaload: case laload: case saload: { - if (CheckArrayBounds) { - Compiler::Operand* index = c->peek(4, 0); - Compiler::Operand* array = c->peek(BytesPerWord, 1); - - Compiler::Operand* load = c->label(); - Compiler::Operand* throw_ = 0; - - if (c->isConstant(index)) { - expect(t, c->constantValue(index) >= 0); - } else { - throw_ = c->label(); - c->cmp(4, c->constant(0), index); - c->jl(throw_); - - index = c->peek(4, 0); - array = c->peek(BytesPerWord, 1); - } - - c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - c->jg(load); - - if (not c->isConstant(index)) { - c->mark(throw_); - } - - index = c->peek(4, 0); - array = c->peek(BytesPerWord, 1); - - c->call - (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), - Compiler::NoReturn | Compiler::Indirect, - frame->trace(0, false), - 0, - 3, c->thread(), array, index); - - c->mark(load); - } - Compiler::Operand* index = frame->popInt(); Compiler::Operand* array = frame->popObject(); + if (CheckArrayBounds) { + c->checkBounds(array, ArrayLength, index, reinterpret_cast + (&singletonValue(t, aioobThunk(t), 0))); + } + if (c->isConstant(index)) { unsigned i = c->constantValue(index); switch (instruction) { @@ -1866,47 +1906,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iastore: case lastore: case sastore: { - if (CheckArrayBounds) { - unsigned valueSize - = (instruction == dastore or instruction == lastore ? 2 : 1); - - Compiler::Operand* index = c->peek(4, valueSize); - Compiler::Operand* array = c->peek(BytesPerWord, valueSize + 1); - - Compiler::Operand* store = c->label(); - Compiler::Operand* throw_ = 0; - - if (c->isConstant(index)) { - expect(t, c->constantValue(index) >= 0); - } else { - throw_ = c->label(); - c->cmp(4, c->constant(0), index); - c->jl(throw_); - - index = c->peek(4, valueSize); - array = c->peek(BytesPerWord, valueSize + 1); - } - - c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - c->jg(store); - - if (not c->isConstant(index)) { - c->mark(throw_); - } - - index = c->peek(4, valueSize); - array = c->peek(BytesPerWord, valueSize + 1); - - c->call - (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), - Compiler::NoReturn | Compiler::Indirect, - frame->trace(0, false), - 0, - 3, c->thread(), array, index); - - c->mark(store); - } - Compiler::Operand* value; if (instruction == dastore or instruction == lastore) { value = frame->popLong(); @@ -1919,13 +1918,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* index = frame->popInt(); Compiler::Operand* array = frame->popObject(); + if (CheckArrayBounds) { + c->checkBounds(array, ArrayLength, index, reinterpret_cast + (&singletonValue(t, aioobThunk(t), 0))); + } + if (c->isConstant(index)) { unsigned i = c->constantValue(index); switch (instruction) { case aastore: { c->call - (c->constant(reinterpret_cast(setMaybeNull)), - Compiler::Indirect, + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, frame->trace(0, false), 0, 4, c->thread(), array, @@ -1956,8 +1960,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, switch (instruction) { case aastore: { c->call - (c->constant(reinterpret_cast(setMaybeNull)), - Compiler::Indirect, + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, frame->trace(0, false), 0, 4, c->thread(), array, @@ -2022,8 +2026,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call - (c->constant(reinterpret_cast(makeBlankObjectArray)), - Compiler::Indirect, + (c->constant(getThunk(t, makeBlankObjectArrayThunk)), + 0, frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(class_), length)); @@ -2062,8 +2066,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case athrow: { c->call - (c->constant(reinterpret_cast(throw_)), - Compiler::NoReturn | Compiler::Indirect, + (c->constant(getThunk(t, throw_Thunk)), + Compiler::NoReturn, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); @@ -2083,8 +2087,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* instance = c->peek(BytesPerWord, 0); c->call - (c->constant(reinterpret_cast(checkCast)), - Compiler::Indirect, + (c->constant(getThunk(t, checkCastThunk)), + 0, frame->trace(0, false), 0, 3, c->thread(), frame->append(class_), instance); @@ -2093,24 +2097,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case d2f: { frame->pushInt (c->call - (c->constant(reinterpret_cast(doubleToFloat)), - Compiler::Indirect, 0, 4, 2, + (c->constant(getThunk(t, doubleToFloatThunk)), + 0, 0, 4, 2, static_cast(0), frame->popLong())); } break; case d2i: { frame->pushInt (c->call - (c->constant(reinterpret_cast(doubleToInt)), - Compiler::Indirect, 0, 4, 2, + (c->constant(getThunk(t, doubleToIntThunk)), + 0, 0, 4, 2, static_cast(0), frame->popLong())); } break; case d2l: { frame->pushLong (c->call - (c->constant(reinterpret_cast(doubleToLong)), - Compiler::Indirect, 0, 8, 2, + (c->constant(getThunk(t, doubleToLongThunk)), + 0, 0, 8, 2, static_cast(0), frame->popLong())); } break; @@ -2120,8 +2124,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(addDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, addDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2132,8 +2136,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareDoublesG)), - Compiler::Indirect, 0, 4, 4, + (c->constant(getThunk(t, compareDoublesGThunk)), + 0, 0, 4, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2144,8 +2148,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareDoublesL)), - Compiler::Indirect, 0, 4, 4, + (c->constant(getThunk(t, compareDoublesLThunk)), + 0, 0, 4, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2164,8 +2168,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(divideDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, divideDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2176,8 +2180,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(multiplyDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, multiplyDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2185,8 +2189,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case dneg: { frame->pushLong (c->call - (c->constant(reinterpret_cast(negateDouble)), - Compiler::Indirect, 0, 8, 2, + (c->constant(getThunk(t, negateDoubleThunk)), + 0, 0, 8, 2, static_cast(0), frame->popLong())); } break; @@ -2196,8 +2200,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(moduloDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, moduloDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2208,8 +2212,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(subtractDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, subtractDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2241,22 +2245,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case f2d: { frame->pushLong (c->call - (c->constant(reinterpret_cast(floatToDouble)), - Compiler::Indirect, 0, 8, 1, frame->popInt())); + (c->constant(getThunk(t, floatToDoubleThunk)), + 0, 0, 8, 1, frame->popInt())); } break; case f2i: { frame->pushInt (c->call - (c->constant(reinterpret_cast(floatToInt)), - Compiler::Indirect, 0, 4, 1, frame->popInt())); + (c->constant(getThunk(t, floatToIntThunk)), + 0, 0, 4, 1, frame->popInt())); } break; case f2l: { frame->pushLong (c->call - (c->constant(reinterpret_cast(floatToLong)), - Compiler::Indirect, 0, 8, 1, frame->popInt())); + (c->constant(getThunk(t, floatToLongThunk)), + 0, 0, 8, 1, frame->popInt())); } break; case fadd: { @@ -2265,8 +2269,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(addFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, addFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fcmpg: { @@ -2275,8 +2279,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareFloatsG)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, compareFloatsGThunk)), + 0, 0, 4, 2, a, b)); } break; case fcmpl: { @@ -2285,8 +2289,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareFloatsL)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, compareFloatsLThunk)), + 0, 0, 4, 2, a, b)); } break; case fconst_0: @@ -2307,8 +2311,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(divideFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, divideFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fmul: { @@ -2317,15 +2321,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(multiplyFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, multiplyFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fneg: { frame->pushInt (c->call - (c->constant(reinterpret_cast(negateFloat)), - Compiler::Indirect, 0, 4, 1, frame->popInt())); + (c->constant(getThunk(t, negateFloatThunk)), + 0, 0, 4, 1, frame->popInt())); } break; case vm::frem: { @@ -2334,8 +2338,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(moduloFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, moduloFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fsub: { @@ -2344,8 +2348,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(subtractFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, subtractFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case getfield: @@ -2362,8 +2366,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, and (classVmFlags(t, fieldClass(t, field)) & InitFlag) == 0) { c->call - (c->constant(reinterpret_cast(tryInitClass)), - Compiler::Indirect, + (c->constant(getThunk(t, tryInitClassThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->append(fieldClass(t, field))); @@ -2441,15 +2445,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case i2d: { frame->pushLong (c->call - (c->constant(reinterpret_cast(intToDouble)), - Compiler::Indirect, 0, 8, 1, frame->popInt())); + (c->constant(getThunk(t, intToDoubleThunk)), + 0, 0, 8, 1, frame->popInt())); } break; case i2f: { frame->pushInt (c->call - (c->constant(reinterpret_cast(intToFloat)), - Compiler::Indirect, 0, 4, 1, frame->popInt())); + (c->constant(getThunk(t, intToFloatThunk)), + 0, 0, 4, 1, frame->popInt())); } break; case i2l: @@ -2675,8 +2679,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(instanceOf)), - Compiler::Indirect, 0, 4, + (c->constant(getThunk(t, instanceOfThunk)), + 0, 0, 4, 3, c->thread(), frame->append(class_), frame->popObject())); } break; @@ -2696,8 +2700,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* result = c->call (c->call (c->constant - (reinterpret_cast(findInterfaceMethodFromInstance)), - Compiler::Indirect, + (getThunk(t, findInterfaceMethodFromInstanceThunk)), + 0, frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(target), @@ -2868,16 +2872,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case l2d: { frame->pushLong (c->call - (c->constant(reinterpret_cast(longToDouble)), - Compiler::Indirect, 0, 8, 2, + (c->constant(getThunk(t, longToDoubleThunk)), + 0, 0, 8, 2, static_cast(0), frame->popLong())); } break; case l2f: { frame->pushInt (c->call - (c->constant(reinterpret_cast(longToFloat)), - Compiler::Indirect, 0, 4, 2, + (c->constant(getThunk(t, longToFloatThunk)), + 0, 0, 4, 2, static_cast(0), frame->popLong())); } break; @@ -3055,8 +3059,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jmp (c->call - (c->constant(reinterpret_cast(lookUpAddress)), - Compiler::Indirect, 0, BytesPerWord, + (c->constant(getThunk(t, lookUpAddressThunk)), + 0, 0, BytesPerWord, 4, key, start, c->constant(pairCount), default_)); for (int32_t i = 0; i < pairCount; ++i) { @@ -3142,15 +3146,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case monitorenter: { c->call - (c->constant(reinterpret_cast(acquireMonitorForObject)), - Compiler::Indirect, + (c->constant(getThunk(t, acquireMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case monitorexit: { c->call - (c->constant(reinterpret_cast(releaseMonitorForObject)), - Compiler::Indirect, + (c->constant(getThunk(t, releaseMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; @@ -3163,8 +3167,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, PROTECT(t, class_); Compiler::Operand* result = c->call - (c->constant(reinterpret_cast(makeMultidimensionalArray)), - Compiler::Indirect, + (c->constant(getThunk(t, makeMultidimensionalArrayThunk)), + 0, frame->trace(0, false), BytesPerWord, 4, c->thread(), frame->append(class_), c->constant(dimensions), @@ -3183,16 +3187,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (classVmFlags(t, class_) & WeakReferenceFlag) { frame->pushObject (c->call - (c->constant(reinterpret_cast(makeNewWeakReference)), - Compiler::Indirect, + (c->constant(getThunk(t, makeNewWeakReferenceThunk)), + 0, frame->trace(0, false), BytesPerWord, 2, c->thread(), frame->append(class_))); } else { frame->pushObject (c->call - (c->constant(reinterpret_cast(makeNew)), - Compiler::Indirect, + (c->constant(getThunk(t, makeNewThunk)), + 0, frame->trace(0, false), BytesPerWord, 2, c->thread(), frame->append(class_))); @@ -3243,8 +3247,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call - (c->constant(reinterpret_cast(makeBlankArray)), - Compiler::Indirect, + (c->constant(getThunk(t, makeBlankArrayThunk)), + 0, frame->trace(0, false), BytesPerWord, 3, c->thread(), c->constant(reinterpret_cast(constructor)), @@ -3275,8 +3279,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, and (classVmFlags(t, fieldClass(t, field)) & InitFlag) == 0) { c->call - (c->constant(reinterpret_cast(tryInitClass)), - Compiler::Indirect, + (c->constant(getThunk(t, tryInitClassThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->append(fieldClass(t, field))); @@ -3340,15 +3344,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case ObjectField: if (instruction == putfield) { c->call - (c->constant(reinterpret_cast(setMaybeNull)), - Compiler::Indirect, + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, frame->trace(0, false), 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } else { c->call - (c->constant(reinterpret_cast(set)), - Compiler::Indirect, 0, 0, + (c->constant(getThunk(t, setThunk)), + 0, 0, 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } break; @@ -3683,7 +3687,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, return eventIndex; } -Allocator* +Zone* codeZone(MyThread* t); int @@ -3722,6 +3726,14 @@ frameObjectMapSize(MyThread* t, object method, object map) return ceiling(intArrayLength(t, map) * size, 32 + size); } +unsigned +codeSingletonSizeInBytes(MyThread*, unsigned codeSizeInBytes) +{ + unsigned count = ceiling(codeSizeInBytes, BytesPerWord); + unsigned size = count + singletonMaskSize(count); + return pad(SingletonBody + (size * BytesPerWord)); +} + object allocateCode(MyThread* t, unsigned codeSizeInBytes) { @@ -3860,7 +3872,7 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "compareTo") == 0) { asm("int3"); } @@ -4380,41 +4392,6 @@ popThread(MyThread*, Assembler* a) } } -object -compileDefault(MyThread* t, Assembler* a) -{ - saveStackAndBase(t, a); - pushThread(t, a); - - ResolvedPromise procPromise(reinterpret_cast(compileMethod)); - Assembler::Constant proc(&procPromise); - a->apply(Call, BytesPerWord, ConstantOperand, &proc); - - popThread(t, a); - - Assembler::Register result(a->returnLow()); - a->apply(Jump, BytesPerWord, RegisterOperand, &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, ConstantOperand, &proc); - - popThread(t, a); - - a->apply(Return); - - return finish(t, a, "native"); -} - class ArgumentList { public: ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_, @@ -4593,27 +4570,6 @@ invoke(Thread* thread, object method, ArgumentList* arguments) return r; } -unsigned -traceSize(Thread* t) -{ - class Counter: public Processor::StackVisitor { - public: - Counter(): count(0) { } - - virtual bool visit(Processor::StackWalker*) { - ++ count; - return true; - } - - unsigned count; - } counter; - - t->m->processor->walkStack(t, &counter); - - return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray) - + (counter.count * FixedSizeOfTraceElement); -} - class SegFaultHandler: public System::SignalHandler { public: SegFaultHandler(): m(0) { } @@ -4686,14 +4642,13 @@ class MyProcessor: public Processor { MyProcessor(System* s, Allocator* allocator): s(s), allocator(allocator), - defaultCompiled(0), - nativeCompiled(0), + defaultThunk(0), + nativeThunk(0), + aioobThunk(0), callTable(0), callTableSize(0), methodTree(0), methodTreeSentinal(0), - indirectCaller(0), - indirectCallerSize(0), codeAllocator(s), codeZone(s, &codeAllocator, 64 * 1024) { } @@ -4707,22 +4662,6 @@ class MyProcessor: public Processor { return t; } - object getDefaultCompiled(MyThread* t) { - if (defaultCompiled == 0) { - Context context(t); - defaultCompiled = compileDefault(t, context.assembler); - } - return defaultCompiled; - } - - object getNativeCompiled(MyThread* t) { - if (nativeCompiled == 0) { - Context context(t); - nativeCompiled = compileNative(t, context.assembler); - } - return nativeCompiled; - } - virtual object makeMethod(vm::Thread* t, uint8_t vmFlags, @@ -4739,7 +4678,7 @@ class MyProcessor: public Processor { return vm::makeMethod (t, vmFlags, returnCode, parameterCount, parameterFootprint, flags, offset, name, spec, class_, code, - getDefaultCompiled(static_cast(t))); + ::defaultThunk(static_cast(t))); } virtual object @@ -4770,7 +4709,7 @@ class MyProcessor: public Processor { initVtable(Thread* t, object c) { void* compiled = &singletonBody - (t, getDefaultCompiled(static_cast(t)), 0); + (t, ::defaultThunk(static_cast(t)), 0); for (unsigned i = 0; i < classLength(t, c); ++i) { classVtable(t, c, i) = compiled; @@ -4801,8 +4740,6 @@ class MyProcessor: public Processor { MyThread* t = static_cast(vmt); if (t == t->m->rootThread) { - v->visit(&defaultCompiled); - v->visit(&nativeCompiled); v->visit(&callTable); v->visit(&methodTree); v->visit(&methodTreeSentinal); @@ -4970,13 +4907,13 @@ class MyProcessor: public Processor { virtual object getStackTrace(Thread* vmt, Thread* vmTarget) { MyThread* t = static_cast(vmt); MyThread* target = static_cast(vmTarget); - - processor(t)->getDefaultCompiled(t); - processor(t)->getNativeCompiled(t); + MyProcessor* p = processor(t); class Visitor: public System::ThreadVisitor { public: - Visitor(MyThread* t, MyThread* target): t(t), target(target) { } + Visitor(MyThread* t, MyProcessor* p, MyThread* target): + t(t), p(p), target(target) + { } virtual void visit(void* ip, void* base, void* stack) { void* oldIp = target->ip; @@ -4988,25 +4925,12 @@ class MyProcessor: public Processor { target->base = base; target->stack = stack; } else { - MyProcessor* p = processor(t); + uint8_t* thunkStart = reinterpret_cast + (&singletonValue(t, p->thunkTable, 0)); + uint8_t* thunkEnd = thunkStart + (p->thunkSize * ThunkCount); - uint8_t* default_ = reinterpret_cast - (&singletonValue(t, p->defaultCompiled, 0)); - unsigned defaultSize = singletonLength(t, p->defaultCompiled); - - uint8_t* native = reinterpret_cast - (&singletonValue(t, p->nativeCompiled, 0)); - unsigned nativeSize = singletonLength(t, p->nativeCompiled); - - if ((static_cast(ip) >= p->indirectCaller - and static_cast(ip) - < p->indirectCaller + p->indirectCallerSize) - - or (static_cast(ip) >= default_ - and static_cast(ip) < default_ + defaultSize) - - or (static_cast(ip) >= native - and static_cast(ip) < native + nativeSize)) + if (static_cast(ip) >= thunkStart + and static_cast(ip) < thunkEnd) { target->ip = *static_cast(stack); target->base = base; @@ -5026,9 +4950,10 @@ class MyProcessor: public Processor { } MyThread* t; + MyProcessor* p; MyThread* target; object trace; - } visitor(t, target); + } visitor(t, p, target); t->m->system->visit(t->systemThread, target->systemThread, &visitor); @@ -5043,19 +4968,159 @@ class MyProcessor: public Processor { System* s; Allocator* allocator; - object defaultCompiled; - object nativeCompiled; + object defaultThunk; + object nativeThunk; + object aioobThunk; + object thunkTable; + unsigned thunkSize; object callTable; unsigned callTableSize; object methodTree; object methodTreeSentinal; - uint8_t* indirectCaller; - unsigned indirectCallerSize; SegFaultHandler segFaultHandler; CodeAllocator codeAllocator; Zone codeZone; }; +intptr_t +getThunk(MyThread* t, Thunk thunk) +{ + MyProcessor* p = processor(t); + + return reinterpret_cast + (&singletonValue(t, p->thunkTable, (thunk * p->thunkSize) / BytesPerWord)); +} + +void +compileThunks(MyThread* t, MyProcessor* p) +{ + class ThunkContext { + public: + class MyPromise: public Promise { + public: + MyPromise(): resolved_(false) { } + + virtual int64_t value() { + return value_; + } + + virtual bool resolved() { + return resolved_; + } + + int64_t value_; + bool resolved_; + }; + + ThunkContext(MyThread* t): context(t) { } + + Context context; + MyPromise promise; + }; + + ThunkContext defaultContext(t); + + { Assembler* a = defaultContext.context.assembler; + + saveStackAndBase(t, a); + pushThread(t, a); + + defaultContext.promise.resolved_ = true; + defaultContext.promise.value_ = reinterpret_cast(compileMethod); + + Assembler::Constant proc(&(defaultContext.promise)); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); + + popThread(t, a); + + Assembler::Register result(a->returnLow()); + a->apply(Jump, BytesPerWord, RegisterOperand, &result); + } + + ThunkContext nativeContext(t); + + { Assembler* a = nativeContext.context.assembler; + + saveStackAndBase(t, a); + pushThread(t, a); + + nativeContext.promise.resolved_ = true; + nativeContext.promise.value_ = reinterpret_cast(invokeNative); + + Assembler::Constant proc(&(nativeContext.promise)); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); + + popThread(t, a); + + a->apply(Return); + } + + ThunkContext aioobContext(t); + + { Assembler* a = aioobContext.context.assembler; + + saveStackAndBase(t, a); + pushThread(t, a); + + aioobContext.promise.resolved_ = true; + aioobContext.promise.value_ = reinterpret_cast + (throwArrayIndexOutOfBounds); + + Assembler::Constant proc(&(aioobContext.promise)); + a->apply(Jump, BytesPerWord, ConstantOperand, &proc); + } + + ThunkContext tableContext(t); + + { Assembler* a = tableContext.context.assembler; + + saveStackAndBase(t, a); + + Assembler::Constant proc(&(tableContext.promise)); + a->apply(Jump, BytesPerWord, ConstantOperand, &proc); + } + + p->thunkSize = pad(tableContext.context.assembler->length()); + + expect(t, codeZone(t)->ensure + (codeSingletonSizeInBytes + (t, defaultContext.context.assembler->length()) + + codeSingletonSizeInBytes + (t, nativeContext.context.assembler->length()) + + codeSingletonSizeInBytes + (t, aioobContext.context.assembler->length()) + + codeSingletonSizeInBytes + (t, p->thunkSize * ThunkCount))); + + Zone::Segment* oldSegment = codeZone(t)->segment; + + p->defaultThunk = finish(t, defaultContext.context.assembler, "default"); + p->nativeThunk = finish(t, nativeContext.context.assembler, "native"); + p->aioobThunk = finish(t, aioobContext.context.assembler, "aioob"); + + p->thunkTable = allocateCode(t, p->thunkSize * ThunkCount); + uint8_t* start = reinterpret_cast + (&singletonValue(t, p->thunkTable, 0)); + + if (Verbose) { + logCompile(start, p->thunkSize * ThunkCount, 0, "thunkTable", 0); + fprintf(stderr, "thunk size: %d\n", p->thunkSize); + } + + tableContext.promise.resolved_ = true; + +#define THUNK(s) \ + tableContext.promise.value_ = reinterpret_cast(s); \ + tableContext.context.assembler->writeTo(start); \ + start += p->thunkSize; + +#include "thunks.cpp" + +#undef THUNK + + assert(t, oldSegment == codeZone(t)->segment); +} + MyProcessor* processor(MyThread* t) { @@ -5070,23 +5135,7 @@ processor(MyThread* t) set(t, p->methodTree, TreeNodeLeft, p->methodTreeSentinal); set(t, p->methodTree, TreeNodeRight, p->methodTreeSentinal); - Context context(t); - Assembler* a = context.assembler; - - saveStackAndBase(t, a); - - Assembler::Register proc(a->returnLow()); - a->apply(Jump, BytesPerWord, RegisterOperand, &proc); - - p->indirectCallerSize = a->length(); - p->indirectCaller = static_cast - (p->codeZone.allocate(p->indirectCallerSize)); - a->writeTo(p->indirectCaller); - - if (Verbose) { - logCompile - (p->indirectCaller, p->indirectCallerSize, 0, "indirect caller", 0); - } + compileThunks(t, p); p->segFaultHandler.m = t->m; expect(t, t->m->system->success @@ -5097,15 +5146,21 @@ processor(MyThread* t) } object -defaultCompiled(MyThread* t) +defaultThunk(MyThread* t) { - return processor(t)->getDefaultCompiled(t); + return processor(t)->defaultThunk; } object -nativeCompiled(MyThread* t) +nativeThunk(MyThread* t) { - return processor(t)->getNativeCompiled(t); + return processor(t)->nativeThunk; +} + +object +aioobThunk(MyThread* t) +{ + return processor(t)->aioobThunk; } void @@ -5113,21 +5168,21 @@ compile(MyThread* t, object method) { MyProcessor* p = processor(t); - if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { + if (methodCompiled(t, method) == p->defaultThunk) { PROTECT(t, method); ACQUIRE(t, t->m->classLock); - if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { + if (methodCompiled(t, method) == p->defaultThunk) { initClass(t, methodClass(t, method)); if (UNLIKELY(t->exception)) return; - if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { + if (methodCompiled(t, method) == p->defaultThunk) { object compiled; if (methodFlags(t, method) & ACC_NATIVE) { - compiled = p->getNativeCompiled(t); + compiled = p->nativeThunk; } else { - Context context(t, method, p->indirectCaller); + Context context(t, method); compiled = compile(t, &context); if (UNLIKELY(t->exception)) return; } @@ -5252,7 +5307,7 @@ methodTreeSentinal(MyThread* t) return processor(t)->methodTreeSentinal; } -Allocator* +Zone* codeZone(MyThread* t) { return &(processor(t)->codeZone); } diff --git a/src/compiler.cpp b/src/compiler.cpp index b69bd94c64..c941ba377c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -184,11 +184,12 @@ class Value: public Compiler::Operand { class Context { public: - Context(System* system, Assembler* assembler, Zone* zone, void* indirection): + Context(System* system, Assembler* assembler, Zone* zone, + Compiler::Client* client): system(system), assembler(assembler), zone(zone), - indirection(indirection), + client(client), logicalIp(-1), state(new (zone->allocate(sizeof(State))) State(0, 0)), logicalCode(0), @@ -220,7 +221,7 @@ class Context { System* system; Assembler* assembler; Zone* zone; - void* indirection; + Compiler::Client* client; int logicalIp; State* state; LogicalInstruction* logicalCode; @@ -884,6 +885,13 @@ anyRegisterSite(Context* c) return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast(0)); } +VirtualSite* +registerOrConstantSite(Context* c) +{ + return virtualSite(c, 0, (1 << RegisterOperand) | (1 << ConstantOperand), + ~static_cast(0)); +} + Site* targetOrRegister(Context* c, Value* v) { @@ -1366,14 +1374,8 @@ class CallEvent: public Event { s = s->next; } - if (flags & Compiler::Indirect) { - int r = c->assembler->returnLow(); - addRead(c, address, BytesPerWord, fixedRegisterSite(c, r)); - mask &= ~(1 << r); - } else { - addRead(c, address, BytesPerWord, virtualSite - (c, 0, ~0, (static_cast(mask) << 32) | mask)); - } + addRead(c, address, BytesPerWord, virtualSite + (c, 0, ~0, (static_cast(mask) << 32) | mask)); for (Stack* s = stack; s; s = s->next) { s->pushEvent->active = true; @@ -1392,12 +1394,7 @@ class CallEvent: public Event { pushNow(c, stack); UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); - if (flags & Compiler::Indirect) { - apply(c, type, BytesPerWord, - constantSite(c, reinterpret_cast(c->indirection))); - } else { - apply(c, type, BytesPerWord, address->source); - } + apply(c, type, BytesPerWord, address->source); if (traceHandler) { traceHandler->handleTrace @@ -1575,14 +1572,14 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, VirtualSite* srcTarget = virtualSite(c, dst); VirtualSite* dstTarget = virtualSite(c); - uintptr_t procedure; + bool thunk; c->assembler->plan(type, size, &(srcTarget->typeMask), &(srcTarget->registerMask), &(dstTarget->typeMask), &(dstTarget->registerMask), - &procedure); + &thunk); - assert(c, procedure == 0); // todo + assert(c, not thunk); // todo new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); @@ -1619,14 +1616,14 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second) { VirtualSite* firstTarget = virtualSite(c); VirtualSite* secondTarget = virtualSite(c); - uintptr_t procedure; + bool thunk; c->assembler->plan(Compare, size, &(firstTarget->typeMask), &(firstTarget->registerMask), &(secondTarget->typeMask), &(secondTarget->registerMask), - &procedure); + &thunk); - assert(c, procedure == 0); // todo + assert(c, not thunk); // todo if (DebugAppend) { fprintf(stderr, "appendCompare\n"); @@ -1723,14 +1720,14 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, { VirtualSite* firstTarget = virtualSite(c); VirtualSite* secondTarget = virtualSite(c, result); - uintptr_t procedure; + bool thunk; c->assembler->plan(type, size, &(firstTarget->typeMask), &(firstTarget->registerMask), &(secondTarget->typeMask), &(secondTarget->registerMask), - &procedure); + &thunk); - if (procedure) { + if (thunk) { secondTarget->value = 0; Stack* oldStack = c->state->stack; @@ -1741,8 +1738,8 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Stack* argumentStack = c->state->stack; c->state->stack = oldStack; - appendCall(c, value(c, constantSite(c, procedure)), Compiler::Indirect, - 0, result, size, argumentStack, 2); + appendCall(c, value(c, constantSite(c, c->client->getThunk(type, size))), + 0, 0, result, size, argumentStack, 2); } else { if (DebugAppend) { fprintf(stderr, "appendCombine\n"); @@ -1798,12 +1795,12 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, } VirtualSite* target = virtualSite(c, result); - uintptr_t procedure; + bool thunk; c->assembler->plan - (type, size, &(target->typeMask), &(target->registerMask), &procedure); + (type, size, &(target->typeMask), &(target->registerMask), &thunk); - assert(c, procedure == 0); // todo + assert(c, not thunk); // todo target->typeMask &= ~(1 << MemoryOperand); @@ -2178,6 +2175,105 @@ appendLocal(Context* c, unsigned size, Local* local) new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local); } +CodePromise* +codePromise(Context* c, Event* e) +{ + return e->promises = new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, e->promises); +} + +CodePromise* +codePromise(Context* c, int offset) +{ + return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); +} + +class BoundsCheckEvent: public Event { + public: + BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler): + Event(c), object(object), lengthOffset(lengthOffset), index(index), + handler(handler) + { + addRead(c, object, BytesPerWord, anyRegisterSite(c)); + addRead(c, index, BytesPerWord, registerOrConstantSite(c)); + } + + virtual void compile(Context* c) { + if (DebugCompile) { + fprintf(stderr, "BoundsCheckEvent.compile\n"); + } + + Assembler* a = c->assembler; + + ConstantSite* constant = 0; + for (Site* s = index->sites; s; s = s->next) { + if (s->type(c) == ConstantOperand) { + constant = static_cast(s); + break; + } + } + + CodePromise* nextPromise = codePromise(c, -1); + CodePromise* outOfBoundsPromise; + + if (constant) { + expect(c, constant->value.value->value() >= 0); + } else { + outOfBoundsPromise = codePromise(c, -1); + + apply(c, Compare, 4, constantSite(c, resolved(c, 0)), index->source); + + Assembler::Constant outOfBoundsConstant(outOfBoundsPromise); + a->apply + (JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant); + } + + assert(c, object->source->type(c) == RegisterOperand); + int base = static_cast(object->source)->register_.low; + + Site* length = memorySite(c, base, lengthOffset); + length->acquire(c, 0, 0, 0); + + apply(c, Compare, BytesPerWord, index->source, length); + + length->release(c); + + Assembler::Constant nextConstant(nextPromise); + a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant); + + if (constant == 0) { + outOfBoundsPromise->offset = a->length(); + } + + ResolvedPromise handlerPromise(handler); + Assembler::Constant handlerConstant(&handlerPromise); + a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant); + + nextPromise->offset = a->length(); + + nextRead(c, object); + nextRead(c, index); + } + + Value* object; + unsigned lengthOffset; + Value* index; + intptr_t handler; +}; + +void +appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler) +{ + if (DebugAppend) { + fprintf(stderr, "appendLocal\n"); + } + + new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent + (c, object, lengthOffset, index, handler); +} + Site* readSource(Context* c, Stack* stack, Read* r) { @@ -2420,8 +2516,9 @@ class Client: public Assembler::Client { class MyCompiler: public Compiler { public: - MyCompiler(System* s, Assembler* assembler, Zone* zone, void* indirection): - c(s, assembler, zone, indirection), client(&c) + MyCompiler(System* s, Assembler* assembler, Zone* zone, + Compiler::Client* compilerClient): + c(s, assembler, zone, compilerClient), client(&c) { assembler->setClient(&client); } @@ -2569,9 +2666,7 @@ class MyCompiler: public Compiler { } Promise* machineIp() { - Event* e = c.logicalCode[c.logicalIp].lastEvent; - return e->promises = new (c.zone->allocate(sizeof(CodePromise))) - CodePromise(&c, e->promises); + return codePromise(&c, c.logicalCode[c.logicalIp].lastEvent); } virtual void mark(Operand* label) { @@ -2710,6 +2805,13 @@ class MyCompiler: public Compiler { return v; } + virtual void checkBounds(Operand* object, unsigned lengthOffset, + Operand* index, intptr_t handler) + { + appendBoundsCheck(&c, static_cast(object), + lengthOffset, static_cast(index), handler); + } + virtual void store(unsigned size, Operand* src, Operand* dst) { appendMove(&c, Move, size, static_cast(src), static_cast(dst)); @@ -2876,7 +2978,7 @@ class MyCompiler: public Compiler { } Context c; - Client client; + ::Client client; }; } // namespace @@ -2885,10 +2987,10 @@ namespace vm { Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, - void* indirection) + Compiler::Client* client) { return new (zone->allocate(sizeof(MyCompiler))) - MyCompiler(system, assembler, zone, indirection); + MyCompiler(system, assembler, zone, client); } } // namespace vm diff --git a/src/compiler.h b/src/compiler.h index 93d4d0a351..6d27a60cc1 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -19,9 +19,16 @@ namespace vm { class Compiler { public: + class Client { + public: + virtual ~Client() { } + + virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0; + virtual intptr_t getThunk(BinaryOperation op, unsigned size) = 0; + }; + static const unsigned Aligned = 1 << 0; static const unsigned NoReturn = 1 << 1; - static const unsigned Indirect = 1 << 2; class Operand { }; @@ -80,6 +87,9 @@ class Compiler { virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0; virtual Operand* loadLocal(unsigned size, unsigned index) = 0; + virtual void checkBounds(Operand* object, unsigned lengthOffset, + Operand* index, intptr_t handler) = 0; + virtual void store(unsigned size, Operand* src, Operand* dst) = 0; virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; @@ -114,7 +124,7 @@ class Compiler { Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, - void* indirection); + Compiler::Client* client); } // namespace vm diff --git a/src/thunks.cpp b/src/thunks.cpp new file mode 100644 index 0000000000..833ffd8114 --- /dev/null +++ b/src/thunks.cpp @@ -0,0 +1,44 @@ +THUNK(tryInitClass) +THUNK(findInterfaceMethodFromInstance) +THUNK(compareDoublesG) +THUNK(compareDoublesL) +THUNK(compareFloatsG) +THUNK(compareFloatsL) +THUNK(addDouble) +THUNK(subtractDouble) +THUNK(multiplyDouble) +THUNK(divideDouble) +THUNK(moduloDouble) +THUNK(negateDouble) +THUNK(doubleToFloat) +THUNK(doubleToInt) +THUNK(doubleToLong) +THUNK(addFloat) +THUNK(subtractFloat) +THUNK(multiplyFloat) +THUNK(divideFloat) +THUNK(moduloFloat) +THUNK(negateFloat) +THUNK(floatToDouble) +THUNK(floatToInt) +THUNK(floatToLong) +THUNK(intToDouble) +THUNK(intToFloat) +THUNK(longToDouble) +THUNK(longToFloat) +THUNK(divideLong) +THUNK(moduloLong) +THUNK(makeBlankObjectArray) +THUNK(makeBlankArray) +THUNK(lookUpAddress) +THUNK(setMaybeNull) +THUNK(acquireMonitorForObject) +THUNK(releaseMonitorForObject) +THUNK(makeMultidimensionalArray) +THUNK(throw_) +THUNK(checkCast) +THUNK(instanceOf) +THUNK(makeNewWeakReference) +THUNK(makeNew) +THUNK(set) +THUNK(gcIfNecessary) diff --git a/src/x86.cpp b/src/x86.cpp index 67a2e59eac..75334f5b84 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -35,18 +35,6 @@ enum { r15 = 15, }; -int64_t FORCE_ALIGN -divideLong(int64_t a, int64_t b) -{ - return a / b; -} - -int64_t FORCE_ALIGN -moduloLong(int64_t a, int64_t b) -{ - return a % b; -} - inline bool isInt8(intptr_t v) { @@ -364,16 +352,23 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) { assert(c, size == BytesPerWord); + if (a->low & 8) rex(c, 0x40, a->low); c->code.append(0xff); - c->code.append(0xe0 | a->low); + c->code.append(0xe0 | (a->low & 7)); } void -jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +jumpC(Context* c, unsigned size, Assembler::Constant* a) { assert(c, size == BytesPerWord); - unconditional(c, 0xe9, a); + if (BytesPerWord == 8) { + Assembler::Register r(r10); + moveCR(c, size, a, &r); + jumpR(c, size, &r); + } else { + unconditional(c, 0xe9, a); + } } void @@ -660,7 +655,7 @@ moveCM(Context* c, unsigned size, Assembler::Constant* a, break; case 4: - encode(c, 0xc7, 0, b, true); + encode(c, 0xc7, 0, b, false); c->code.append4(a->value->value()); break; @@ -1940,7 +1935,7 @@ class MyAssembler: public Assembler { } virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, - uint64_t* registerMask, uintptr_t* procedure) + uint64_t* registerMask, bool* thunk) { if (op == Negate and BytesPerWord == 4 and size == 8) { *typeMask = 1 << RegisterOperand; @@ -1950,12 +1945,12 @@ class MyAssembler: public Assembler { *typeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *registerMask = ~static_cast(0); } - *procedure = 0; + *thunk = false; } virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask, uint64_t* aRegisterMask, uint8_t* bTypeMask, - uint64_t* bRegisterMask, uintptr_t* procedure) + uint64_t* bRegisterMask, bool* thunk) { *aTypeMask = ~0; *aRegisterMask = ~static_cast(0); @@ -1963,7 +1958,7 @@ class MyAssembler: public Assembler { *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *bRegisterMask = ~static_cast(0); - *procedure = 0; + *thunk = false; switch (op) { case Compare: @@ -2004,7 +1999,7 @@ class MyAssembler: public Assembler { case Divide: if (BytesPerWord == 4 and size == 8) { *bTypeMask = ~0; - *procedure = reinterpret_cast(divideLong); + *thunk = true; } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); *bRegisterMask = 1 << rax; @@ -2014,7 +2009,7 @@ class MyAssembler: public Assembler { case Remainder: if (BytesPerWord == 4 and size == 8) { *bTypeMask = ~0; - *procedure = reinterpret_cast(moduloLong); + *thunk = true; } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); *bRegisterMask = 1 << rax; From e68a18248cef9293e836065241d1d377e0e12dfd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 31 May 2008 16:24:04 -0600 Subject: [PATCH 117/121] use codePromise helper function in CallEvent ctor --- src/compiler.cpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index c941ba377c..a6f6cbe6c1 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1342,6 +1342,19 @@ resetLocals(Context* c) c->locals = 0; } +CodePromise* +codePromise(Context* c, Event* e) +{ + return e->promises = new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, e->promises); +} + +CodePromise* +codePromise(Context* c, int offset) +{ + return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); +} + class CallEvent: public Event { public: CallEvent(Context* c, Value* address, unsigned flags, @@ -1397,9 +1410,7 @@ class CallEvent: public Event { apply(c, type, BytesPerWord, address->source); if (traceHandler) { - traceHandler->handleTrace - (new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, c->assembler->length())); + traceHandler->handleTrace(codePromise(c, c->assembler->length())); } cleanStack(c, stack, locals, reads); @@ -2175,19 +2186,6 @@ appendLocal(Context* c, unsigned size, Local* local) new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local); } -CodePromise* -codePromise(Context* c, Event* e) -{ - return e->promises = new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, e->promises); -} - -CodePromise* -codePromise(Context* c, int offset) -{ - return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); -} - class BoundsCheckEvent: public Event { public: BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, From 1450b12e5b3189b78988ad27538601e24c1789cf Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 31 May 2008 16:24:32 -0600 Subject: [PATCH 118/121] visit thunk objects during GC in MyProcessor::visitObjects --- src/compile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compile.cpp b/src/compile.cpp index 0a61e7a3c8..283a965f59 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -4740,6 +4740,10 @@ class MyProcessor: public Processor { MyThread* t = static_cast(vmt); if (t == t->m->rootThread) { + v->visit(&defaultThunk); + v->visit(&nativeThunk); + v->visit(&aioobThunk); + v->visit(&thunkTable); v->visit(&callTable); v->visit(&methodTree); v->visit(&methodTreeSentinal); From eacca98c3f974f00ef63728aabc5a899d83f46e8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 31 May 2008 16:53:37 -0600 Subject: [PATCH 119/121] fix regressions affecting 32-bit systems --- src/compile.cpp | 2 +- src/compiler.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 283a965f59..cc5685d907 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5071,7 +5071,7 @@ compileThunks(MyThread* t, MyProcessor* p) (throwArrayIndexOutOfBounds); Assembler::Constant proc(&(aioobContext.promise)); - a->apply(Jump, BytesPerWord, ConstantOperand, &proc); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); } ThunkContext tableContext(t); diff --git a/src/compiler.cpp b/src/compiler.cpp index a6f6cbe6c1..0db6962c87 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1743,8 +1743,8 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Stack* oldStack = c->state->stack; - ::push(c, size, first); ::push(c, size, second); + ::push(c, size, first); Stack* argumentStack = c->state->stack; c->state->stack = oldStack; @@ -2244,8 +2244,7 @@ class BoundsCheckEvent: public Event { outOfBoundsPromise->offset = a->length(); } - ResolvedPromise handlerPromise(handler); - Assembler::Constant handlerConstant(&handlerPromise); + Assembler::Constant handlerConstant(resolved(c, handler)); a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant); nextPromise->offset = a->length(); From 7cdff9f1eea603faf58f86759e16e5a2bfa2b0cd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 31 May 2008 17:06:45 -0600 Subject: [PATCH 120/121] disable debug logging and fix build warnings --- src/compile.cpp | 6 +----- src/compiler.cpp | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index cc5685d907..c3e6b9f6bb 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = true; +const bool Verbose = false; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -5096,8 +5096,6 @@ compileThunks(MyThread* t, MyProcessor* p) + codeSingletonSizeInBytes (t, p->thunkSize * ThunkCount))); - Zone::Segment* oldSegment = codeZone(t)->segment; - p->defaultThunk = finish(t, defaultContext.context.assembler, "default"); p->nativeThunk = finish(t, nativeContext.context.assembler, "native"); p->aioobThunk = finish(t, aioobContext.context.assembler, "aioob"); @@ -5121,8 +5119,6 @@ compileThunks(MyThread* t, MyProcessor* p) #include "thunks.cpp" #undef THUNK - - assert(t, oldSegment == codeZone(t)->segment); } MyProcessor* diff --git a/src/compiler.cpp b/src/compiler.cpp index 0db6962c87..6936575bd4 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2213,7 +2213,7 @@ class BoundsCheckEvent: public Event { } CodePromise* nextPromise = codePromise(c, -1); - CodePromise* outOfBoundsPromise; + CodePromise* outOfBoundsPromise = 0; if (constant) { expect(c, constant->value.value->value() >= 0); From 2f3e1ea393558fccd56898d739e78506413eaf05 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 31 May 2008 19:40:18 -0600 Subject: [PATCH 121/121] fix incorrect debug logging message --- src/compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 6936575bd4..9ef5968078 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2264,7 +2264,7 @@ appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, Value* index, intptr_t handler) { if (DebugAppend) { - fprintf(stderr, "appendLocal\n"); + fprintf(stderr, "appendBoundsCheck\n"); } new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent