From d70e3aaefb67db0cab931a96e4b047db8d1a7dd6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 11 Dec 2007 16:52:28 -0700 Subject: [PATCH] JIT progress: new, invokespecial, etc. --- src/compile.cpp | 40 ++++++-- src/compiler.cpp | 250 +++++++++++++++++++++++++++++++++++------------ src/compiler.h | 3 +- test/Misc.java | 2 +- 4 files changed, 223 insertions(+), 72 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index be3fbcfa92..9c2f43b902 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -18,6 +18,8 @@ vmJump(void* address, void* base, void* stack); namespace { +const bool Verbose = true; + class MyThread: public Thread { public: class CallTrace { @@ -351,7 +353,7 @@ class Frame { } static unsigned traceSizeInBytes(Thread* t, object method) { - return BytesPerWord + BytesPerWord + 1 + mapSizeInWords(t, method); + return sizeof(TraceElement) + mapSizeInWords(t, method); } void pushedInt() { @@ -655,21 +657,26 @@ class Frame { } void loadInt(unsigned index) { - 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); pushInt(c->memory(c->base(), localOffset(t, index, method))); } void loadLong(unsigned index) { - assert(t, index < localSize(t, method) - 1); - assert(t, getBit(map, index) == 0); - assert(t, getBit(map, index + 1) == 0); + assert(t, index < static_cast + (codeMaxLocals(t, methodCode(t, method)) - 1)); + assert(t, index < parameterFootprint(t, method) + or getBit(map, index - parameterFootprint(t, method)) == 0); + assert(t, index < parameterFootprint(t, method) + or getBit(map, index + 1 - parameterFootprint(t, method)) == 0); pushLong(c->memory(c->base(), localOffset(t, index, method))); } void loadObject(unsigned index) { - 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); pushObject(c->memory(c->base(), localOffset(t, index, method))); } @@ -2733,7 +2740,7 @@ object finish(MyThread* t, Compiler* c, object method, Vector* objectPool, Vector* traceLog) { - unsigned count = ceiling(c->size(), BytesPerWord); + unsigned count = ceiling(c->codeSize() + c->poolSize(), BytesPerWord); unsigned size = count + singletonMaskSize(count); object result = allocate2 (t, SingletonBody + size * BytesPerWord, true, true); @@ -2828,6 +2835,14 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, set(t, code, CodeLineNumberTable, newTable); } } + + if (Verbose) { + fprintf(stderr, "%s.%s from %p to %p\n", + &byteArrayBody(t, className(t, methodClass(t, method)), 0), + &byteArrayBody(t, methodName(t, method), 0), + start, + start + c->codeSize()); + } } return result; @@ -3638,7 +3653,7 @@ processor(MyThread* t) c->jmp(c->indirectTarget()); p->indirectCaller = static_cast - (t->m->system->allocate(c->size())); + (t->m->system->allocate(c->codeSize())); c->writeTo(p->indirectCaller); c->dispose(); @@ -3665,6 +3680,11 @@ compile(MyThread* t, object method) object compiled = compile(t, c, method); set(t, method, MethodCompiled, compiled); + if (methodVirtual(t, method)) { + classVtable(t, methodClass(t, method), methodOffset(t, method)) + = &singletonValue(t, compiled, 0); + } + c->dispose(); } } diff --git a/src/compiler.cpp b/src/compiler.cpp index 112968c4c3..66647f7487 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -29,6 +29,7 @@ const unsigned RegisterCount = BytesPerWord * 2; class Context; class ImmediateOperand; +class AbsoluteOperand; class RegisterOperand; class MemoryOperand; class StackOperand; @@ -53,12 +54,21 @@ isInt32(intptr_t v) class IpTask { public: + enum Priority { + LowPriority, + HighPriority + }; + IpTask(IpTask* next): next(next) { } virtual ~IpTask() { } virtual void run(Context* c, unsigned ip, unsigned start, unsigned end, uint8_t* code, unsigned offset) = 0; + + virtual Priority priority() { + return LowPriority; + } IpTask* next; }; @@ -86,6 +96,10 @@ class MyPromise: public Promise { public: MyPromise(intptr_t key): key(key) { } + virtual unsigned value(Compiler*); + + virtual unsigned value(Context*) = 0; + intptr_t key; }; @@ -93,14 +107,14 @@ class PoolPromise: public MyPromise { public: PoolPromise(intptr_t key): MyPromise(key) { } - virtual unsigned value(Compiler*); + virtual unsigned value(Context*); }; class CodePromise: public MyPromise { public: CodePromise(intptr_t key): MyPromise(key) { } - virtual unsigned value(Compiler*); + virtual unsigned value(Context*); }; class CodePromiseTask: public IpTask { @@ -113,6 +127,10 @@ class CodePromiseTask: public IpTask { p->key = offset + (p->key - start); } + virtual Priority priority() { + return HighPriority; + } + CodePromise* p; }; @@ -120,7 +138,7 @@ class IpPromise: public MyPromise { public: IpPromise(intptr_t key): MyPromise(key) { } - virtual unsigned value(Compiler*); + virtual unsigned value(Context*); }; class MyOperand: public Operand { @@ -178,6 +196,8 @@ class MyOperand: public Operand { virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); } + virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); } + virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); } }; @@ -187,6 +207,8 @@ class RegisterOperand: public MyOperand { value(value), reserved(false), stack(0) { } + virtual StackOperand* logicalPush(Context* c); + virtual void logicalFlush(Context* c UNUSED, StackOperand* s UNUSED) { assert(c, stack == s); stack = 0; @@ -209,6 +231,7 @@ class RegisterOperand: public MyOperand { virtual void accept(Context*, Operation, RegisterOperand*); virtual void accept(Context*, Operation, ImmediateOperand*); + virtual void accept(Context*, Operation, AbsoluteOperand*); virtual void accept(Context*, Operation, MemoryOperand*); Register value; @@ -241,6 +264,10 @@ class AbsoluteOperand: public MyOperand { virtual void apply(Context* c, Operation operation); + virtual void apply(Context* c, Operation operation, MyOperand* operand) { + operand->accept(c, operation, this); + } + virtual void setAbsolute(Context*, intptr_t v) { value->key = v; } @@ -313,6 +340,10 @@ class StackOperand: public MyOperand { } } + virtual StackOperand* logicalPush(Context* c) { + return base->logicalPush(c); + } + virtual void accept(Context* c, Operation operation, RegisterOperand* operand) { @@ -626,6 +657,24 @@ encode(Context* c, uint8_t instruction, uint8_t zeroPrefix, } } +StackOperand* +RegisterOperand::logicalPush(Context* c) +{ + if (reserved or stack) { + RegisterOperand* tmp = temporary(c, false); + tmp->accept(c, mov, this); + c->stack = new (c->zone.allocate(sizeof(StackOperand))) + StackOperand(tmp, c->stack); + tmp->stack = c->stack; + } else { + c->stack = new (c->zone.allocate(sizeof(StackOperand))) + StackOperand(this, c->stack); + stack = c->stack; + } + + return c->stack; +} + void RegisterOperand::apply(Context* c, Operation operation) { @@ -680,13 +729,21 @@ RegisterOperand::accept(Context* c, Operation operation, ImmediateOperand* operand) { switch (operation) { - case sub: - assert(c, isInt8(operand->value)); // todo - + case mov: rex(c); - c->code.append(0x83); - c->code.append(0xe8 | value); - c->code.append(operand->value); + c->code.append(0xb8 | value); + c->code.appendAddress(operand->value); + break; + + case sub: + if (operand->value) { + assert(c, isInt8(operand->value)); // todo + + rex(c); + c->code.append(0x83); + c->code.append(0xe8 | value); + c->code.append(operand->value); + } break; default: abort(c); @@ -708,6 +765,42 @@ RegisterOperand::accept(Context* c, Operation operation, } } +class AbsoluteMovTask: public IpTask { + public: + AbsoluteMovTask(unsigned start, MyPromise* promise, IpTask* next): + IpTask(next), start(start), promise(promise) + { } + + virtual void run(Context* c UNUSED, unsigned, unsigned start, unsigned, + uint8_t* code, unsigned offset) + { + uint8_t* instruction = code + offset + (this->start - start); + intptr_t v = reinterpret_cast(code + promise->value(c)); + memcpy(instruction + (BytesPerWord / 8) + 1, &v, BytesPerWord); + } + + unsigned start; + MyPromise* promise; +}; + +void +RegisterOperand::accept(Context* c, Operation operation, + AbsoluteOperand* operand) +{ + switch (operation) { + case mov: { + IpMapping* mapping = currentMapping(c); + mapping->task = new (c->zone.allocate(sizeof(AbsoluteMovTask))) + AbsoluteMovTask(c->code.length(), operand->value, mapping->task); + + accept(c, mov, immediate(c, 0)); + accept(c, mov, memory(c, this, 0, 0, 1)); + } break; + + default: abort(c); + } +} + class DirectCallTask: public IpTask { public: DirectCallTask(unsigned start, uint8_t* address, IpTask* next): @@ -718,8 +811,11 @@ class DirectCallTask: public IpTask { uint8_t* code, unsigned offset) { uint8_t* instruction = code + offset + (this->start - start); + assert(c, *instruction == 0xe8); + intptr_t v = address - instruction; assert(c, isInt32(v)); + int32_t v32 = v; memcpy(instruction + 1, &v32, 4); } @@ -748,6 +844,13 @@ ImmediateOperand::apply(Context* c, Operation operation) c->code.append(0xE8); c->code.append4(0); } break; + + case alignedCall: { + while ((c->code.length() + 1) % 4) { + c->code.append(0x90); + } + apply(c, call); + } break; default: abort(c); } @@ -776,6 +879,10 @@ void MemoryOperand::apply(Context* c, Operation operation) { switch (operation) { + case pop: + encode(c, 0x8f, 0, 0x40, 0x80, rax, base->asRegister(c), displacement); + break; + default: abort(c); } } @@ -812,6 +919,67 @@ MemoryOperand::accept(Context* c, Operation operation, } } +unsigned +PoolPromise::value(Context* c) +{ + if (c->ipTable) { + return c->code.length() + key; + } + + abort(c); +} + +unsigned +CodePromise::value(Context* c) +{ + if (c->ipTable) { + return key; + } + + abort(c); +} + +unsigned +IpPromise::value(Context* c) +{ + if (c->ipTable) { + unsigned bottom = 0; + unsigned top = c->ipMappings.length() / BytesPerWord; + for (unsigned span = top - bottom; span; span = top - bottom) { + unsigned middle = bottom + (span / 2); + IpMapping* mapping = c->ipTable[middle]; + + if (key == mapping->ip) { + return mapping->start; + } else if (key < mapping->ip) { + top = middle; + } else if (key > mapping->ip) { + bottom = middle + 1; + } + } + } + + abort(c); +} + +void +runTasks(Context* c, uint8_t* out, IpTask::Priority priority) +{ + uint8_t* p = out; + for (unsigned i = 0; i < c->ipMappings.length() / BytesPerWord; ++i) { + IpMapping* mapping = c->ipTable[i]; + int length = mapping->end - mapping->start; + + for (IpTask* t = mapping->task; t; t = t->next) { + if (t->priority() == priority) { + t->run(c, mapping->ip, mapping->start, mapping->end, out, p - out); + } + } + + p += length; + } +} + class MyCompiler: public Compiler { public: MyCompiler(System* s, void* indirectCaller): @@ -1140,8 +1308,12 @@ class MyCompiler: public Compiler { return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip); } - virtual unsigned size() { - return c.code.length() + c.constantPool.length(); + virtual unsigned codeSize() { + return c.code.length(); + } + + virtual unsigned poolSize() { + return c.constantPool.length(); } virtual void writeTo(uint8_t* out) { @@ -1172,21 +1344,22 @@ class MyCompiler: public Compiler { for (unsigned i = 0; i < tableSize; ++i) { IpMapping* mapping = c.ipTable[i]; int length = mapping->end - mapping->start; - memcpy(p, c.code.data + mapping->start, length); - for (IpTask* t = mapping->task; t; t = t->next) { - t->run(&c, mapping->ip, mapping->start, mapping->end, out, p - out); - } + memcpy(p, c.code.data + mapping->start, length); p += length; } memcpy(p, c.constantPool.data, c.constantPool.length()); + + runTasks(&c, out, IpTask::HighPriority); + runTasks(&c, out, IpTask::LowPriority); } 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); @@ -1203,52 +1376,9 @@ class MyCompiler: public Compiler { }; unsigned -PoolPromise::value(Compiler* compiler) +MyPromise::value(Compiler* compiler) { - Context* c = &(static_cast(compiler)->c); - - if (c->ipTable) { - return c->code.length() + key; - } - - abort(c); -} - -unsigned -CodePromise::value(Compiler* compiler) -{ - Context* c = &(static_cast(compiler)->c); - - if (c->ipTable) { - return key; - } - - abort(c); -} - -unsigned -IpPromise::value(Compiler* compiler) -{ - Context* c = &(static_cast(compiler)->c); - - if (c->ipTable) { - unsigned bottom = 0; - unsigned top = c->ipMappings.length() / BytesPerWord; - for (unsigned span = top - bottom; span; span = top - bottom) { - unsigned middle = bottom + (span / 2); - IpMapping* mapping = c->ipTable[middle]; - - if (key == mapping->ip) { - return mapping->start; - } else if (key < mapping->ip) { - top = middle; - } else if (key > mapping->ip) { - bottom = middle + 1; - } - } - } - - abort(c); + return value(&(static_cast(compiler)->c)); } } // namespace diff --git a/src/compiler.h b/src/compiler.h index acc9546173..81a8cc5280 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -94,7 +94,8 @@ class Compiler { virtual void startLogicalIp(unsigned) = 0; virtual Operand* logicalIp(unsigned) = 0; - virtual unsigned size() = 0; + virtual unsigned codeSize() = 0; + virtual unsigned poolSize() = 0; virtual void writeTo(uint8_t*) = 0; virtual void updateCall(void* returnAddress, void* newTarget) = 0; diff --git a/test/Misc.java b/test/Misc.java index a0a1910f30..f96d04e2b4 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -23,7 +23,7 @@ public class Misc { int b = 2; int c = a + b; -// Misc m = new Misc(); + Misc m = new Misc(); // String s = "hello"; // m.foo(s); // m.bar(s);