From 796a64a426dbaf7cefce3db823e1cfa477cf3f17 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 15 Dec 2007 17:24:15 -0700 Subject: [PATCH] lots of JIT bugfixes and cleanups --- makefile | 2 +- src/builtin.cpp | 2 + src/compile.cpp | 242 +++++++++++++----------- src/compiler.cpp | 468 ++++++++++++++++++++++++++++++----------------- src/compiler.h | 51 +++--- test/Misc.java | 22 ++- 6 files changed, 480 insertions(+), 307 deletions(-) diff --git a/makefile b/makefile index 1bc59372f5..8c300ac823 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,7 @@ src = src classpath = classpath test = test -input = $(test-build)/Misc.class +input = $(test-build)/Enums.class build-cxx = g++ build-cc = gcc diff --git a/src/builtin.cpp b/src/builtin.cpp index c96218d64c..024ba8b2af 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -617,6 +617,8 @@ Java_java_lang_Throwable_trace(Thread* t, jclass, jint skipCount) t->m->processor->walkStack(t, &v); + if (v.trace == 0) v.trace = makeArray(t, 0, true); + return makeLocalReference(t, v.trace); } diff --git a/src/compile.cpp b/src/compile.cpp index 1d90fda38d..c4bf495068 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -188,7 +188,9 @@ class MyStackWalker: public Processor::StackWalker { if (nativeMethod) { return 0; } else { - return traceNodeAddress(t, node); + intptr_t start = reinterpret_cast + (&singletonValue(t, methodCompiled(t, traceNodeMethod(t, node)), 0)); + return traceNodeAddress(t, node) - start; } } @@ -244,19 +246,21 @@ localOffset(MyThread* t, int v, object method) class PoolElement { public: - PoolElement(object value, Promise* offset): value(value), offset(offset) { } + PoolElement(object value, Promise* address): + value(value), address(address) + { } object value; - Promise* offset; + Promise* address; }; class TraceElement { public: - TraceElement(object target, Promise* offset, bool virtualCall): - target(target), offset(offset), virtualCall(virtualCall) { } + TraceElement(object target, Promise* machineIp, bool virtualCall): + target(target), machineIp(machineIp), virtualCall(virtualCall) { } object target; - Promise* offset; + Promise* machineIp; bool virtualCall; uint8_t map[0]; }; @@ -292,6 +296,7 @@ class Frame { next(0), t(t), c(c), + stack(0), method(method), map(map), objectPool(objectPool), @@ -308,6 +313,7 @@ class Frame { next(f), t(f->t), c(f->c), + stack(f->stack), method(f->method), map(map), objectPool(f->objectPool), @@ -327,9 +333,9 @@ class Frame { } Operand* append(object o) { - new (objectPool->allocate(sizeof(PoolElement))) - PoolElement(o, c->poolOffset()); - return c->poolAppend(c->constant(0)); + Promise* p = c->poolAppend(0); + new (objectPool->allocate(sizeof(PoolElement))) PoolElement(o, p); + return c->absolute(p); } static unsigned parameterFootprint(Thread* t, object method) { @@ -578,7 +584,7 @@ class Frame { void trace(object target, bool virtualCall) { TraceElement* e = new (traceLog->allocate(traceSizeInBytes(t, method))) - TraceElement(target, c->codeOffset(), virtualCall); + TraceElement(target, c->machineIp(), virtualCall); memcpy(e->map, map, mapSizeInWords(t, method) * BytesPerWord); } @@ -586,42 +592,46 @@ class Frame { trace(0, false); } + Operand* machineIp(unsigned logicalIp) { + return c->promiseConstant(c->machineIp(logicalIp)); + } + void startLogicalIp(unsigned ip) { c->startLogicalIp(ip); this->ip = ip; } void pushInt(Operand* o) { - c->push(o); + stack = c->push(stack, o); pushedInt(); } void pushObject(Operand* o) { - c->push(o); + stack = c->push(stack, o); pushedObject(); } void pushObject() { - c->push(1); + stack = c->push(stack, 1); pushedObject(); } void pushLong(Operand* o) { - c->push2(o); + stack = c->push2(stack, o); pushedInt(); pushedInt(); } void pop(unsigned count) { popped(count); - c->pop(count); + stack = c->pop(stack, count); } Operand* topInt() { assert(t, sp >= 1); assert(t, sp - 1 >= localSize(t, method)); assert(t, getBit(map, sp - 1) == 0); - return c->stack(0); + return c->stack(stack, 0); } Operand* topLong() { @@ -629,45 +639,47 @@ class Frame { assert(t, sp - 2 >= localSize(t, method)); assert(t, getBit(map, sp - 1) == 0); assert(t, getBit(map, sp - 2) == 0); - return c->stack(1); + return c->stack(stack, 1); } Operand* topObject() { assert(t, sp >= 1); assert(t, sp - 1 >= localSize(t, method)); assert(t, getBit(map, sp - 1) != 0); - return c->stack(0); + return c->stack(stack, 0); } Operand* popInt() { - poppedInt(); - return c->pop(); + Operand* tmp = c->temporary(); + popInt(tmp); + return tmp; } Operand* popLong() { - poppedInt(); - poppedInt(); - return c->pop2(); + Operand* tmp = c->temporary(); + popLong(tmp); + return tmp; } Operand* popObject() { - poppedObject(); - return c->pop(); + Operand* tmp = c->temporary(); + popObject(tmp); + return tmp; } void popInt(Operand* o) { - c->pop(o); + stack = c->pop(stack, o); poppedInt(); } void popLong(Operand* o) { - c->pop2(o); + stack = c->pop2(stack, o); poppedInt(); poppedInt(); } void popObject(Operand* o) { - c->pop(o); + stack = c->pop(stack, o); poppedObject(); } @@ -712,83 +724,84 @@ class Frame { } void increment(unsigned index, unsigned count) { - assert(t, index < localSize(t, method)); - assert(t, getBit(map, index) == 0); + assert(t, index < codeMaxLocals(t, methodCode(t, method))); + assert(t, index < parameterFootprint(t, method) + or getBit(map, index - parameterFootprint(t, method)) == 0); c->add(c->constant(count), c->memory(c->base(), localOffset(t, index, method))); } void dup() { - c->push(c->stack(0)); + stack = c->push(stack, c->stack(stack, 0)); dupped(); } void dupX1() { - Operand* s0 = c->stack(0); - Operand* s1 = c->stack(1); + Operand* s0 = c->stack(stack, 0); + Operand* s1 = c->stack(stack, 1); c->mov(s0, s1); c->mov(s1, s0); - c->push(s0); + stack = c->push(stack, s0); duppedX1(); } void dupX2() { - Operand* s0 = c->stack(0); - Operand* s1 = c->stack(1); - Operand* s2 = c->stack(2); + Operand* s0 = c->stack(stack, 0); + Operand* s1 = c->stack(stack, 1); + Operand* s2 = c->stack(stack, 2); c->mov(s0, s2); c->mov(s2, s1); c->mov(s1, s0); - c->push(s0); + stack = c->push(stack, s0); duppedX2(); } void dup2() { - Operand* s0 = c->stack(0); + Operand* s0 = c->stack(stack, 0); - c->push(s0); - c->push(s0); + stack = c->push(stack, s0); + stack = c->push(stack, s0); dupped2(); } void dup2X1() { - Operand* s0 = c->stack(0); - Operand* s1 = c->stack(1); - Operand* s2 = c->stack(2); + Operand* s0 = c->stack(stack, 0); + Operand* s1 = c->stack(stack, 1); + Operand* s2 = c->stack(stack, 2); c->mov(s1, s2); c->mov(s0, s1); c->mov(s2, s0); - c->push(s1); - c->push(s0); + stack = c->push(stack, s1); + stack = c->push(stack, s0); dupped2X1(); } void dup2X2() { - Operand* s0 = c->stack(0); - Operand* s1 = c->stack(1); - Operand* s2 = c->stack(2); - Operand* s3 = c->stack(3); + Operand* s0 = c->stack(stack, 0); + Operand* s1 = c->stack(stack, 1); + Operand* s2 = c->stack(stack, 2); + Operand* s3 = c->stack(stack, 3); c->mov(s1, s3); c->mov(s0, s2); c->mov(s3, s1); c->mov(s2, s0); - c->push(s1); - c->push(s0); + stack = c->push(stack, s1); + stack = c->push(stack, s0); dupped2X2(); } void swap() { - Operand* s0 = c->stack(0); - Operand* s1 = c->stack(1); + Operand* s0 = c->stack(stack, 0); + Operand* s1 = c->stack(stack, 1); Operand* tmp = c->temporary(); c->mov(s0, tmp); @@ -803,6 +816,7 @@ class Frame { Frame* next; MyThread* t; Compiler* c; + Stack* stack; object method; uintptr_t* map; Vector* objectPool; @@ -1818,7 +1832,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - c->jmp(c->logicalIp(newIp)); + c->jmp(frame->machineIp(newIp)); ip = newIp; } break; @@ -1826,7 +1840,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 5) + codeReadInt32(t, code, ip); assert(t, newIp < codeLength(t, code)); - c->jmp(c->logicalIp(newIp)); + c->jmp(frame->machineIp(newIp)); ip = newIp; } break; @@ -1930,7 +1944,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* target = c->logicalIp(newIp); + Operand* target = frame->machineIp(newIp); if (instruction == if_acmpeq) { c->je(target); } else { @@ -1956,7 +1970,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* target = c->logicalIp(newIp); + Operand* target = frame->machineIp(newIp); switch (instruction) { case if_icmpeq: c->je(target); @@ -1995,7 +2009,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->cmp(c->constant(0), a); c->release(a); - Operand* target = c->logicalIp(newIp); + Operand* target = frame->machineIp(newIp); switch (instruction) { case ifeq: c->je(target); @@ -2026,11 +2040,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* a = frame->popObject(); c->cmp(c->constant(0), a); c->release(a); - Operand* target = c->logicalIp(newIp); + Operand* target = frame->machineIp(newIp); if (instruction == ifnull) { c->je(target); } else { @@ -2145,7 +2159,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* found = c->directCall (c->constant (reinterpret_cast(findInterfaceMethodFromInstance)), - 3, c->thread(), frame->append(target), c->stack(instance)); + 3, c->thread(), frame->append(target), + c->stack(frame->stack, instance)); c->mov(c->memory(found, MethodCompiled), found); @@ -2195,7 +2210,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) unsigned offset = ClassVtable + (methodOffset(t, target) * BytesPerWord); - Operand* instance = c->stack(parameterFootprint - 1); + Operand* instance = c->stack(frame->stack, parameterFootprint - 1); Operand* class_ = c->temporary(); c->mov(c->memory(instance), class_); @@ -2432,30 +2447,28 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); - compile(t, frame, defaultIp); - if (UNLIKELY(t->exception)) return; - - Operand* default_ = c->poolAppend(c->logicalIp(defaultIp)); + Operand* default_ = c->absolute + (c->poolAppendPromise(c->machineIp(defaultIp))); int32_t pairCount = codeReadInt32(t, code, ip); - Operand* start; + Operand* start = 0; + uint32_t ipTable[pairCount]; for (int32_t i = 0; i < pairCount; ++i) { unsigned index = ip + (i * 8); int32_t key = codeReadInt32(t, code, index); uint32_t newIp = base + codeReadInt32(t, code, index); assert(t, newIp < codeLength(t, code)); - compile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; - - Operand* result = c->poolAppend(c->constant(key)); - c->poolAppend(c->logicalIp(newIp)); + ipTable[i] = newIp; + Promise* p = c->poolAppend(key); if (i == 0) { - start = result; + start = c->promiseConstant(p); } + c->poolAppendPromise(c->machineIp(newIp)); } + assert(t, start); c->jmp (c->directCall @@ -2463,6 +2476,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 4, key, start, c->constant(pairCount), default_)); c->release(key); + + for (int32_t i = 0; i < pairCount; ++i) { + compile(t, frame, ipTable[i]); + if (UNLIKELY(t->exception)) return; + } + + compile(t, frame, defaultIp); + if (UNLIKELY(t->exception)) return; } return; case lor: { @@ -2611,7 +2632,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* size = frame->popInt(); c->cmp(c->constant(0), size); - c->release(size); c->jge(nonnegative); @@ -2658,7 +2678,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* result = c->indirectCall (c->constant(reinterpret_cast(makeBlankArray)), - 2, c->constant(reinterpret_cast(constructor)), size); + 3, c->thread(), c->constant(reinterpret_cast(constructor)), + size); + + c->release(size); frame->trace(); @@ -2782,29 +2805,25 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); - - compile(t, frame, defaultIp); - if (UNLIKELY(t->exception)) return; - Operand* default_ = c->poolAppend(c->logicalIp(defaultIp)); - int32_t bottom = codeReadInt32(t, code, ip); int32_t top = codeReadInt32(t, code, ip); - Operand* start; - for (int32_t i = 0; i < bottom - top + 1; ++i) { + Operand* start = 0; + uint32_t ipTable[top - bottom + 1]; + for (int32_t i = 0; i < top - bottom + 1; ++i) { unsigned index = ip + (i * 4); uint32_t newIp = base + codeReadInt32(t, code, index); assert(t, newIp < codeLength(t, code)); - - compile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; - Operand* result = c->poolAppend(c->logicalIp(newIp)); + ipTable[i] = newIp; + + Promise* p = c->poolAppendPromise(c->machineIp(newIp)); if (i == 0) { - start = result; + start = c->promiseConstant(p); } } + assert(t, start); Operand* defaultCase = c->label(); @@ -2814,13 +2833,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->cmp(c->constant(top), key); c->jg(defaultCase); - c->shl(c->constant(1), key); + c->sub(c->constant(bottom), key); c->jmp(c->memory(start, 0, key, BytesPerWord)); c->mark(defaultCase); - c->jmp(default_); + 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; + } + + compile(t, frame, defaultIp); + if (UNLIKELY(t->exception)) return; } return; case wide: { @@ -2887,10 +2914,12 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, for (unsigned i = 0; i < objectPool->length(); i += sizeof(PoolElement)) { PoolElement* e = objectPool->peek(i); + intptr_t offset = e->address->value(c) + - reinterpret_cast(start); - singletonMarkObject(t, result, e->offset->value(c) / BytesPerWord); + singletonMarkObject(t, result, offset / BytesPerWord); - set(t, result, SingletonBody + e->offset->value(c), e->value); + set(t, result, SingletonBody + offset, e->value); } unsigned traceSize = Frame::traceSizeInBytes(t, method); @@ -2899,9 +2928,8 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, TraceElement* e = traceLog->peek(i); object node = makeTraceNode - (t, reinterpret_cast(start + e->offset->value(c)), - 0, method, e->target, e->virtualCall, mapSize / BytesPerWord, - false); + (t, e->machineIp->value(c), 0, method, e->target, e->virtualCall, + mapSize / BytesPerWord, false); if (mapSize) { memcpy(&traceNodeMap(t, node, 0), e->map, mapSize); @@ -2927,16 +2955,16 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, (t, newTable, i); exceptionHandlerStart(newHandler) - = c->logicalIpToOffset(exceptionHandlerStart(oldHandler)) - ->value(c); + = c->machineIp(exceptionHandlerStart(oldHandler))->value(c) + - reinterpret_cast(start); exceptionHandlerEnd(newHandler) - = c->logicalIpToOffset(exceptionHandlerEnd(oldHandler)) - ->value(c); + = c->machineIp(exceptionHandlerEnd(oldHandler))->value(c) + - reinterpret_cast(start); exceptionHandlerIp(newHandler) - = c->logicalIpToOffset(exceptionHandlerIp(oldHandler)) - ->value(c); + = c->machineIp(exceptionHandlerIp(oldHandler))->value(c) + - reinterpret_cast(start); exceptionHandlerCatchType(newHandler) = exceptionHandlerCatchType(oldHandler); @@ -2957,8 +2985,9 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, LineNumber* oldLine = lineNumberTableBody(t, oldTable, i); LineNumber* newLine = lineNumberTableBody(t, newTable, i); - lineNumberIp(newLine) = c->logicalIpToOffset(lineNumberIp(oldLine)) - ->value(c); + lineNumberIp(newLine) + = c->machineIp(lineNumberIp(oldLine))->value(c) + - reinterpret_cast(start); lineNumberLine(newLine) = lineNumberLine(oldLine); } @@ -2979,10 +3008,10 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, if (false and strcmp(reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), - "java/lang/Boolean") == 0 and + "Enums") == 0 and strcmp(reinterpret_cast (&byteArrayBody(t, methodName(t, method), 0)), - "booleanValue") == 0) + "checkFaceCard") == 0) { asm("int3"); } @@ -3474,8 +3503,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments) break; case ObjectField: - r = (result == 0 ? 0 : - *reinterpret_cast(static_cast(result))); + r = reinterpret_cast(result); break; case VoidField: diff --git a/src/compiler.cpp b/src/compiler.cpp index 16de6b7f23..176d33ba11 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -36,13 +36,14 @@ enum SelectionType { const bool Verbose = false; const unsigned RegisterCount = BytesPerWord * 2; +const unsigned GprParameterCount = 6; class Context; +class MyOperand; class ImmediateOperand; class AbsoluteOperand; class RegisterOperand; class MemoryOperand; -class StackOperand; class CodePromise; class MyPromise; @@ -64,6 +65,16 @@ isInt32(intptr_t v) return v == static_cast(v); } +class RegisterNode { + public: + RegisterNode(Register value, RegisterNode* next): + value(value), next(next) + { } + + Register value; + RegisterNode* next; +}; + class Task { public: Task(Task* next): next(next) { } @@ -105,6 +116,17 @@ class Segment { Event* event; }; +class MyStack: public Stack { + public: + MyStack(MyOperand* value, int index, MyStack* next): + value(value), index(index), next(next) + { } + + MyOperand* value; + int index; + MyStack* next; +}; + class MyOperand: public Operand { public: enum Operation { @@ -144,9 +166,12 @@ class MyOperand: public Operand { virtual Register asRegister(Context* c) { abort(c); } + virtual RegisterNode* dependencies(Context*, RegisterNode* next) + { return next; } + virtual void release(Context*) { /* ignore */ } - virtual void setLabelValue(Context* c, CodePromise*) { abort(c); } + virtual void setLabelValue(Context* c, MyPromise*) { abort(c); } virtual void apply(Context*, Operation) = 0; @@ -181,6 +206,8 @@ class RegisterOperand: public MyOperand { return value; } + virtual RegisterNode* dependencies(Context* c, RegisterNode* next); + void acquire(Context* c UNUSED) { assert(c, not reserved); // fprintf(stderr, "acquire %d\n", value); @@ -253,7 +280,9 @@ class AddressOperand: public MyOperand { promise(promise) { } - virtual void setLabelValue(Context*, CodePromise*); + virtual Register asRegister(Context* c); + + virtual void setLabelValue(Context*, MyPromise*); virtual void apply(Context*, Operation); virtual void apply(Context* c, Operation, MyOperand*) { abort(c); } @@ -313,6 +342,15 @@ class MemoryOperand: public MyOperand { virtual Register asRegister(Context*); + virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { + next = base->dependencies(c, next); + if (index) { + return index->dependencies(c, next); + } else { + return next; + } + } + virtual void apply(Context*, Operation); virtual void apply(Context* c, Operation operation, MyOperand* operand) { @@ -404,6 +442,10 @@ class WrapperOperand: public MyOperand { return base->asRegister(c); } + virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { + return base->dependencies(c, next); + } + virtual void apply(Context* c, Operation operation) { base->apply(c, operation); } @@ -461,16 +503,6 @@ class WrapperOperand: public MyOperand { MyOperand* base; }; -class StackOperand: public WrapperOperand { - public: - StackOperand(MyOperand* base, int index, StackOperand* next): - WrapperOperand(base), index(index), next(next) - { } - - int index; - StackOperand* next; -}; - class TemporaryOperand: public WrapperOperand { public: TemporaryOperand(MyOperand* base): @@ -497,7 +529,6 @@ class Context { zone(s, 8 * 1024), indirectCaller(reinterpret_cast(indirectCaller)), segmentTable(0), - stack(0), reserved(0), codeLength(-1) { @@ -529,7 +560,6 @@ class Context { Zone zone; intptr_t indirectCaller; Segment** segmentTable; - StackOperand* stack; unsigned reserved; int codeLength; RegisterOperand* registers[RegisterCount]; @@ -585,7 +615,7 @@ class PoolPromise: public MyPromise { virtual intptr_t value(Context* c) { if (resolved(c)) { - return c->codeLength + key; + return reinterpret_cast(c->code.data + c->codeLength + key); } abort(c); @@ -600,17 +630,13 @@ class PoolPromise: public MyPromise { class CodePromise: public MyPromise { public: - CodePromise(bool absolute): - offset(-1), absolute(absolute) + CodePromise(): + offset(-1) { } virtual intptr_t value(Context* c) { if (resolved(c)) { - if (absolute) { - return reinterpret_cast(c->code.data + offset); - } else { - return offset; - } + return reinterpret_cast(c->code.data + offset); } abort(c); @@ -621,13 +647,12 @@ class CodePromise: public MyPromise { } intptr_t offset; - bool absolute; }; class IpPromise: public MyPromise { public: - IpPromise(intptr_t logicalIp, bool absolute): - logicalIp(logicalIp), absolute(absolute) + IpPromise(intptr_t logicalIp): + logicalIp(logicalIp) { } virtual intptr_t value(Context* c) { @@ -639,11 +664,7 @@ class IpPromise: public MyPromise { Segment* s = c->segmentTable[middle]; if (logicalIp == s->logicalIp) { - if (absolute) { - return reinterpret_cast(c->code.data + s->offset); - } else { - return s->offset; - } + return reinterpret_cast(c->code.data + s->offset); } else if (logicalIp < s->logicalIp) { top = middle; } else if (logicalIp > s->logicalIp) { @@ -660,7 +681,6 @@ class IpPromise: public MyPromise { } intptr_t logicalIp; - bool absolute; }; AddressOperand* @@ -837,6 +857,99 @@ class ReleaseEvent: public Event { MyOperand* operand; }; + +class Movement { + public: + MyOperand* source; + Register destination; + RegisterNode* dependencies; +}; + +void +push(Context* c, Movement* table, unsigned size) +{ + 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); + } +} + +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 { + public: + ArgumentEvent(MyOperand** arguments, unsigned count, Event* next): + Event(next), + arguments(arguments), + count(count) + { } + + virtual void run(Context* c) { + if (BytesPerWord == 8) { + const unsigned size = min(count, GprParameterCount); + Movement moveTable[size]; + + 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::push); + } + } + + push(c, moveTable, size); + } else { + for (int i = count - 1; i >= 0; --i) { + arguments[i]->apply(c, MyOperand::push); + } + } + } + + MyOperand** arguments; + unsigned count; +}; + void appendOperation(Context* c, MyOperand::Operation operation) { @@ -877,105 +990,88 @@ appendRelease(Context* c, Operand* operand) ReleaseEvent(operand, s->event); } -StackOperand* -pushed(Context* c) +void +appendArgumentEvent(Context* c, MyOperand** arguments, unsigned count) { - int index = (c->stack ? - c->stack->index + (c->stack->footprint() / BytesPerWord) : - 0); - - MyOperand* base = memory - (c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1); - - return c->stack = new (c->zone.allocate(sizeof(StackOperand))) - StackOperand(base, index, c->stack); + Segment* s = currentSegment(c); + s->event = new (c->zone.allocate(sizeof(ArgumentEvent))) + ArgumentEvent(arguments, count, s->event); } -void -push(Context* c, int count) +MyStack* +pushed(Context* c, MyStack* stack) +{ + int index = (stack ? + stack->index + (stack->value->footprint() / BytesPerWord) : + 0); + + MyOperand* value = memory + (c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1); + + return new (c->zone.allocate(sizeof(MyStack))) MyStack(value, index, stack); +} + +MyStack* +push(Context* c, MyStack* stack, int count) { appendOperation (c, MyOperand::sub, immediate(c, count * BytesPerWord), register_(c, rsp)); while (count) { -- count; - pushed(c); + stack = pushed(c, stack); } + + return stack; } -StackOperand* -push(Context* c, MyOperand* v) +MyStack* +push(Context* c, MyStack* stack, MyOperand* v) { appendOperation(c, MyOperand::push, v); - return pushed(c); + return pushed(c, stack); } -void -pop(Context* c, int count) +MyStack* +pop(Context* c, MyStack* stack, int count) { appendOperation (c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp)); while (count) { - count -= (c->stack->footprint() / BytesPerWord); + count -= (stack->value->footprint() / BytesPerWord); assert(c, count >= 0); - c->stack = c->stack->next; + stack = stack->next; } + + return stack; } -void -pop(Context* c, MyOperand* dst) +MyStack* +pop(Context* c, MyStack* stack, MyOperand* dst) { appendOperation(c, MyOperand::pop, dst); - c->stack = c->stack->next; -} - -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); - } + return stack->next; } unsigned pushArguments(Context* c, unsigned count, va_list list) { - MyOperand* arguments[count]; + MyOperand** arguments = static_cast + (c->zone.allocate(count * BytesPerWord)); unsigned footprint = 0; for (unsigned i = 0; i < count; ++i) { arguments[i] = va_arg(list, MyOperand*); footprint += pad(arguments[i]->footprint()); } - const int GprCount = 6; - for (int i = count - 1; i >= 0; --i) { - if (BytesPerWord == 8 and i < GprCount) { - appendOperation - (c, MyOperand::mov, arguments[i], register_(c, gpRegister(c, i))); - } else { - appendOperation(c, MyOperand::push, arguments[i]); - } - } + appendArgumentEvent(c, arguments, count); if (BytesPerWord == 8) { - if (footprint > GprCount * BytesPerWord) { - return footprint - GprCount * BytesPerWord; + if (footprint > GprParameterCount * BytesPerWord) { + return footprint - GprParameterCount * BytesPerWord; } else { return 0; } @@ -1038,6 +1134,13 @@ encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex) encode(c, instruction, a, r, b->displacement, index, b->scale); } +RegisterNode* +RegisterOperand::dependencies(Context* c, RegisterNode* next) +{ + return new (c->zone.allocate(sizeof(RegisterNode))) + RegisterNode(value, next); +} + void RegisterOperand::apply(Context* c, Operation operation) { @@ -1142,19 +1245,17 @@ RegisterOperand::accept(Context* c, Operation operation, } break; case and_: { - if (operand->value) { - rex(c); - if (isInt8(operand->value)) { - c->code.append(0x83); - c->code.append(0xe0 | value); - c->code.append(operand->value); - } else { - assert(c, isInt32(operand->value)); + rex(c); + if (isInt8(operand->value)) { + c->code.append(0x83); + c->code.append(0xe0 | value); + c->code.append(operand->value); + } else { + assert(c, isInt32(operand->value)); - c->code.append(0x81); - c->code.append(0xe0 | value); - c->code.append(operand->value); - } + c->code.append(0x81); + c->code.append(0xe0 | value); + c->code.append(operand->value); } } break; @@ -1173,6 +1274,22 @@ RegisterOperand::accept(Context* c, Operation operation, c->code.appendAddress(operand->value); } break; + case shl: { + if (operand->value) { + rex(c); + if (operand->value == 1) { + c->code.append(0xd1); + c->code.append(0xe0 | value); + } else { + assert(c, isInt8(operand->value)); + + c->code.append(0xc1); + c->code.append(0xe0 | value); + c->code.append(operand->value); + } + } + } break; + case sub: { if (operand->value) { assert(c, isInt8(operand->value)); // todo @@ -1243,9 +1360,7 @@ ImmediateOperand* value(Context* c, AbsoluteOperand* operand) { if (c->codeLength >= 0) { - return immediate - (c, reinterpret_cast - (c->code.data + operand->promise->value(c))); + return immediate(c, operand->promise->value(c)); } else { return immediate(c, 0); } @@ -1306,7 +1421,7 @@ conditional(Context* c, unsigned condition, AddressOperand* operand) } void -AddressOperand::setLabelValue(Context*, CodePromise* p) +AddressOperand::setLabelValue(Context*, MyPromise* p) { promise = p; } @@ -1358,6 +1473,22 @@ AddressOperand::apply(Context* c, Operation operation) } } +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)); + tmp->release(c); + return tmp->value; +} + void ImmediateOperand::apply(Context* c, Operation operation) { @@ -1436,6 +1567,10 @@ MemoryOperand::apply(Context* c, Operation operation) encode(c, 0xff, 2, this, false); break; + case jmp: + encode(c, 0xff, 4, this, false); + break; + case neg: encode(c, 0xf7, 2, this, true); break; @@ -1472,6 +1607,10 @@ MemoryOperand::accept(Context* c, Operation operation, RegisterOperand* operand) { switch (operation) { + case and_: { + encode(c, 0x21, operand->value, this, true); + } break; + case add: { encode(c, 0x01, operand->value, this, true); } break; @@ -1656,14 +1795,8 @@ class MyCompiler: public Compiler { c(s, indirectCaller) { } - virtual Promise* poolOffset() { - return new (c.zone.allocate(sizeof(PoolPromise))) - PoolPromise(c.constantPool.length()); - } - - virtual Promise* codeOffset() { - CodePromise* p = new (c.zone.allocate(sizeof(CodePromise))) - CodePromise(false); + virtual Promise* machineIp() { + CodePromise* p = new (c.zone.allocate(sizeof(CodePromise))) CodePromise(); Segment* s = currentSegment(&c); s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask))) @@ -1672,64 +1805,77 @@ class MyCompiler: public Compiler { return p; } - virtual Operand* poolAppend(Operand* v) { - Operand* r = absolute(&c, static_cast(poolOffset())); + virtual Promise* machineIp(unsigned logicalIp) { + return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(logicalIp); + } + + virtual Promise* poolAppend(intptr_t v) { + return poolAppendPromise + (new (c.zone.allocate(sizeof(ResolvedPromise))) ResolvedPromise(v)); + } + + virtual Promise* poolAppendPromise(Promise* v) { + Promise* p = new (c.zone.allocate(sizeof(PoolPromise))) + PoolPromise(c.constantPool.length()); c.constantPool.appendAddress(v); - return r; + return p; } virtual Operand* constant(intptr_t v) { return immediate(&c, v); } - virtual void push(unsigned count) { - ::push(&c, count); + virtual Operand* promiseConstant(Promise* p) { + return address(&c, static_cast(p)); } - virtual void push(Operand* v) { - ::push(&c, static_cast(v)); + virtual Operand* absolute(Promise* p) { + return ::absolute(&c, static_cast(p)); } - virtual void push2(Operand* v) { - push(v); - if (BytesPerWord == 8) push(immediate(&c, 0)); + virtual Stack* push(Stack* s, unsigned count) { + return ::push(&c, static_cast(s), count); } - virtual Operand* stack(unsigned index) { - StackOperand* s = c.stack; - unsigned i = 0; - if (s->footprint() / BytesPerWord == 2) ++ i; - - for (; i < index; ++i) { - s = s->next; - if (s->footprint() / BytesPerWord == 2) ++ i; - } + virtual Stack* push(Stack* s, Operand* v) { + return ::push(&c, static_cast(s), static_cast(v)); + } + virtual Stack* push2(Stack* s, Operand* v) { + s = push(s, v); + if (BytesPerWord == 8) s = push(s, immediate(&c, 0)); return s; } - virtual void pop(unsigned count) { - ::pop(&c, count); + virtual Operand* stack(Stack* s, unsigned index) { + MyStack* stack = static_cast(s); + unsigned i = 0; + + if (stack->value->footprint() / BytesPerWord == 2) { + ++ i; + } + + for (; i < index; ++i) { + stack = stack->next; + if (stack->value->footprint() / BytesPerWord == 2) { + ++ i; + } + } + + return stack->value; } - virtual Operand* pop() { - Operand* tmp = static_cast(temporary()); - pop(tmp); - return tmp; + virtual Stack* pop(Stack* s, unsigned count) { + return ::pop(&c, static_cast(s), count); } - virtual Operand* pop2() { - if (BytesPerWord == 8) pop(1); - return pop(); + virtual Stack* pop(Stack* s, Operand* dst) { + return ::pop(&c, static_cast(s), static_cast(dst)); } - virtual void pop(Operand* dst) { - ::pop(&c, static_cast(dst)); - } - - virtual void pop2(Operand* dst) { - if (BytesPerWord == 8) pop(1); - pop(dst); + virtual Stack* pop2(Stack* s, Operand* dst) { + if (BytesPerWord == 8) s = pop(s, 1); + return pop(s, dst); } virtual Operand* stack() { @@ -1764,14 +1910,8 @@ class MyCompiler: public Compiler { } virtual void mark(Operand* label) { - CodePromise* p = new (c.zone.allocate(sizeof(CodePromise))) - CodePromise(true); - - Segment* s = currentSegment(&c); - s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask))) - CodePromiseTask(p, s->event->task); - - static_cast(label)->setLabelValue(&c, p); + static_cast(label)->setLabelValue + (&c, static_cast(machineIp())); } virtual Operand* indirectCall @@ -1972,15 +2112,6 @@ class MyCompiler: public Compiler { Segment(ip, new (c.zone.allocate(sizeof(Event))) Event(0))); } - virtual Operand* logicalIp(unsigned ip) { - return address - (&c, new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, true)); - } - - virtual Promise* logicalIpToOffset(unsigned ip) { - return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, false); - } - virtual unsigned codeSize() { if (c.codeLength < 0) { assert(&c, c.code.length() == 0); @@ -1997,9 +2128,10 @@ class MyCompiler: public Compiler { c.code.wrap(out, codeSize()); writeCode(&c); - memcpy(out + codeSize(), - c.constantPool.data, - c.constantPool.length()); + 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); + } } virtual void updateCall(void* returnAddress, void* newTarget) { diff --git a/src/compiler.h b/src/compiler.h index b1ccef5db9..cd49edabab 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -7,6 +7,8 @@ namespace vm { class Operand { }; +class Stack { }; + class Compiler; class Promise { @@ -20,20 +22,29 @@ class Compiler { public: virtual ~Compiler() { } - virtual Promise* poolOffset() = 0; - virtual Promise* codeOffset() = 0; - virtual Promise* logicalIpToOffset(unsigned) = 0; + virtual Promise* machineIp() = 0; + virtual Promise* machineIp(unsigned logicalIp) = 0; - virtual Operand* poolAppend(Operand*) = 0; + virtual Promise* poolAppend(intptr_t) = 0; + virtual Promise* poolAppendPromise(Promise*) = 0; virtual Operand* constant(intptr_t) = 0; + virtual Operand* promiseConstant(Promise*) = 0; + virtual Operand* absolute(Promise*) = 0; + virtual Operand* memory(Operand* base, int displacement = 0, + Operand* index = 0, unsigned scale = 1) = 0; + + virtual Operand* select1(Operand*) = 0; + virtual Operand* select2(Operand*) = 0; + virtual Operand* select2z(Operand*) = 0; + virtual Operand* select4(Operand*) = 0; + virtual Operand* select8(Operand*) = 0; virtual Operand* stack() = 0; virtual Operand* base() = 0; virtual Operand* thread() = 0; virtual Operand* indirectTarget() = 0; virtual Operand* temporary() = 0; - virtual Operand* stack(unsigned) = 0; virtual void release(Operand*) = 0; virtual Operand* label() = 0; @@ -46,19 +57,19 @@ class Compiler { virtual Operand* directCall (Operand* address, unsigned argumentCount, ...) = 0; + virtual Operand* call(Operand*) = 0; + virtual Operand* alignedCall(Operand*) = 0; virtual void return_(Operand*) = 0; virtual void ret() = 0; - virtual void push(unsigned count) = 0; - virtual void push(Operand*) = 0; - virtual void push2(Operand*) = 0; - virtual void pop(unsigned count) = 0; - virtual Operand* pop() = 0; - virtual Operand* pop2() = 0; - virtual void pop(Operand*) = 0; - virtual void pop2(Operand*) = 0; - virtual Operand* call(Operand*) = 0; - virtual Operand* alignedCall(Operand*) = 0; + virtual Stack* push(Stack*, unsigned count) = 0; + virtual Stack* push(Stack*, Operand*) = 0; + virtual Stack* push2(Stack*, Operand*) = 0; + virtual Stack* pop(Stack*, unsigned count) = 0; + virtual Stack* pop(Stack*, Operand*) = 0; + virtual Stack* pop2(Stack*, Operand*) = 0; + virtual Operand* stack(Stack*, unsigned) = 0; + virtual void mov(Operand* src, Operand* dst) = 0; virtual void cmp(Operand* subtrahend, Operand* minuend) = 0; virtual void jl(Operand*) = 0; @@ -81,21 +92,11 @@ class Compiler { virtual void xor_(Operand* v, Operand* dst) = 0; virtual void neg(Operand*) = 0; - virtual Operand* memory(Operand* base, int displacement = 0, - Operand* index = 0, unsigned scale = 1) = 0; - - virtual Operand* select1(Operand*) = 0; - virtual Operand* select2(Operand*) = 0; - virtual Operand* select2z(Operand*) = 0; - virtual Operand* select4(Operand*) = 0; - virtual Operand* select8(Operand*) = 0; - virtual void prologue() = 0; virtual void reserve(unsigned size) = 0; virtual void epilogue() = 0; virtual void startLogicalIp(unsigned) = 0; - virtual Operand* logicalIp(unsigned) = 0; virtual unsigned codeSize() = 0; virtual unsigned poolSize() = 0; diff --git a/test/Misc.java b/test/Misc.java index 956c220b16..96fbc6b198 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,6 +1,7 @@ public class Misc { private static int alpha; private static int beta; + private int gamma; private String foo(String s) { return s; @@ -13,11 +14,15 @@ public class Misc { private static String baz(String s) { return s; } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } public static void main(String[] args) { boolean v = Boolean.valueOf("true"); -// ClassLoader.getSystemClassLoader().toString(); + ClassLoader.getSystemClassLoader().toString(); int a = 2; int b = 2; @@ -29,10 +34,15 @@ public class Misc { m.bar(s); baz(s); -// int d = alpha; -// beta = 42; -// alpha = 43; -// int e = beta; -// int f = alpha; + 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); } }