JIT progress: new, invokespecial, etc.

This commit is contained in:
Joel Dice 2007-12-11 16:52:28 -07:00
parent 396c979de8
commit d70e3aaefb
4 changed files with 223 additions and 72 deletions

View File

@ -18,6 +18,8 @@ vmJump(void* address, void* base, void* stack);
namespace { namespace {
const bool Verbose = true;
class MyThread: public Thread { class MyThread: public Thread {
public: public:
class CallTrace { class CallTrace {
@ -351,7 +353,7 @@ class Frame {
} }
static unsigned traceSizeInBytes(Thread* t, object method) { static unsigned traceSizeInBytes(Thread* t, object method) {
return BytesPerWord + BytesPerWord + 1 + mapSizeInWords(t, method); return sizeof(TraceElement) + mapSizeInWords(t, method);
} }
void pushedInt() { void pushedInt() {
@ -655,21 +657,26 @@ class Frame {
} }
void loadInt(unsigned index) { void loadInt(unsigned index) {
assert(t, index < localSize(t, method)); assert(t, index < codeMaxLocals(t, methodCode(t, method)));
assert(t, getBit(map, index) == 0); assert(t, index < parameterFootprint(t, method)
or getBit(map, index - parameterFootprint(t, method)) == 0);
pushInt(c->memory(c->base(), localOffset(t, index, method))); pushInt(c->memory(c->base(), localOffset(t, index, method)));
} }
void loadLong(unsigned index) { void loadLong(unsigned index) {
assert(t, index < localSize(t, method) - 1); assert(t, index < static_cast<unsigned>
assert(t, getBit(map, index) == 0); (codeMaxLocals(t, methodCode(t, method)) - 1));
assert(t, getBit(map, index + 1) == 0); 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))); pushLong(c->memory(c->base(), localOffset(t, index, method)));
} }
void loadObject(unsigned index) { void loadObject(unsigned index) {
assert(t, index < localSize(t, method)); assert(t, index < codeMaxLocals(t, methodCode(t, method)));
assert(t, getBit(map, index) != 0); assert(t, index < parameterFootprint(t, method)
or getBit(map, index - parameterFootprint(t, method)) != 0);
pushObject(c->memory(c->base(), localOffset(t, index, method))); pushObject(c->memory(c->base(), localOffset(t, index, method)));
} }
@ -2733,7 +2740,7 @@ object
finish(MyThread* t, Compiler* c, object method, Vector* objectPool, finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
Vector* traceLog) Vector* traceLog)
{ {
unsigned count = ceiling(c->size(), BytesPerWord); unsigned count = ceiling(c->codeSize() + c->poolSize(), BytesPerWord);
unsigned size = count + singletonMaskSize(count); unsigned size = count + singletonMaskSize(count);
object result = allocate2 object result = allocate2
(t, SingletonBody + size * BytesPerWord, true, true); (t, SingletonBody + size * BytesPerWord, true, true);
@ -2828,6 +2835,14 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
set(t, code, CodeLineNumberTable, newTable); 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; return result;
@ -3638,7 +3653,7 @@ processor(MyThread* t)
c->jmp(c->indirectTarget()); c->jmp(c->indirectTarget());
p->indirectCaller = static_cast<uint8_t*> p->indirectCaller = static_cast<uint8_t*>
(t->m->system->allocate(c->size())); (t->m->system->allocate(c->codeSize()));
c->writeTo(p->indirectCaller); c->writeTo(p->indirectCaller);
c->dispose(); c->dispose();
@ -3665,6 +3680,11 @@ compile(MyThread* t, object method)
object compiled = compile(t, c, method); object compiled = compile(t, c, method);
set(t, method, MethodCompiled, compiled); set(t, method, MethodCompiled, compiled);
if (methodVirtual(t, method)) {
classVtable(t, methodClass(t, method), methodOffset(t, method))
= &singletonValue(t, compiled, 0);
}
c->dispose(); c->dispose();
} }
} }

View File

@ -29,6 +29,7 @@ const unsigned RegisterCount = BytesPerWord * 2;
class Context; class Context;
class ImmediateOperand; class ImmediateOperand;
class AbsoluteOperand;
class RegisterOperand; class RegisterOperand;
class MemoryOperand; class MemoryOperand;
class StackOperand; class StackOperand;
@ -53,12 +54,21 @@ isInt32(intptr_t v)
class IpTask { class IpTask {
public: public:
enum Priority {
LowPriority,
HighPriority
};
IpTask(IpTask* next): next(next) { } IpTask(IpTask* next): next(next) { }
virtual ~IpTask() { } virtual ~IpTask() { }
virtual void run(Context* c, unsigned ip, unsigned start, unsigned end, virtual void run(Context* c, unsigned ip, unsigned start, unsigned end,
uint8_t* code, unsigned offset) = 0; uint8_t* code, unsigned offset) = 0;
virtual Priority priority() {
return LowPriority;
}
IpTask* next; IpTask* next;
}; };
@ -86,6 +96,10 @@ class MyPromise: public Promise {
public: public:
MyPromise(intptr_t key): key(key) { } MyPromise(intptr_t key): key(key) { }
virtual unsigned value(Compiler*);
virtual unsigned value(Context*) = 0;
intptr_t key; intptr_t key;
}; };
@ -93,14 +107,14 @@ class PoolPromise: public MyPromise {
public: public:
PoolPromise(intptr_t key): MyPromise(key) { } PoolPromise(intptr_t key): MyPromise(key) { }
virtual unsigned value(Compiler*); virtual unsigned value(Context*);
}; };
class CodePromise: public MyPromise { class CodePromise: public MyPromise {
public: public:
CodePromise(intptr_t key): MyPromise(key) { } CodePromise(intptr_t key): MyPromise(key) { }
virtual unsigned value(Compiler*); virtual unsigned value(Context*);
}; };
class CodePromiseTask: public IpTask { class CodePromiseTask: public IpTask {
@ -113,6 +127,10 @@ class CodePromiseTask: public IpTask {
p->key = offset + (p->key - start); p->key = offset + (p->key - start);
} }
virtual Priority priority() {
return HighPriority;
}
CodePromise* p; CodePromise* p;
}; };
@ -120,7 +138,7 @@ class IpPromise: public MyPromise {
public: public:
IpPromise(intptr_t key): MyPromise(key) { } IpPromise(intptr_t key): MyPromise(key) { }
virtual unsigned value(Compiler*); virtual unsigned value(Context*);
}; };
class MyOperand: public Operand { 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, ImmediateOperand*) { abort(c); }
virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*) { 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) value(value), reserved(false), stack(0)
{ } { }
virtual StackOperand* logicalPush(Context* c);
virtual void logicalFlush(Context* c UNUSED, StackOperand* s UNUSED) { virtual void logicalFlush(Context* c UNUSED, StackOperand* s UNUSED) {
assert(c, stack == s); assert(c, stack == s);
stack = 0; stack = 0;
@ -209,6 +231,7 @@ class RegisterOperand: public MyOperand {
virtual void accept(Context*, Operation, RegisterOperand*); virtual void accept(Context*, Operation, RegisterOperand*);
virtual void accept(Context*, Operation, ImmediateOperand*); virtual void accept(Context*, Operation, ImmediateOperand*);
virtual void accept(Context*, Operation, AbsoluteOperand*);
virtual void accept(Context*, Operation, MemoryOperand*); virtual void accept(Context*, Operation, MemoryOperand*);
Register value; Register value;
@ -241,6 +264,10 @@ class AbsoluteOperand: public MyOperand {
virtual void apply(Context* c, Operation operation); 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) { virtual void setAbsolute(Context*, intptr_t v) {
value->key = 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, virtual void accept(Context* c, Operation operation,
RegisterOperand* operand) 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 void
RegisterOperand::apply(Context* c, Operation operation) RegisterOperand::apply(Context* c, Operation operation)
{ {
@ -680,13 +729,21 @@ RegisterOperand::accept(Context* c, Operation operation,
ImmediateOperand* operand) ImmediateOperand* operand)
{ {
switch (operation) { switch (operation) {
case sub: case mov:
assert(c, isInt8(operand->value)); // todo
rex(c); rex(c);
c->code.append(0x83); c->code.append(0xb8 | value);
c->code.append(0xe8 | value); c->code.appendAddress(operand->value);
c->code.append(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; break;
default: abort(c); 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<intptr_t>(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 { class DirectCallTask: public IpTask {
public: public:
DirectCallTask(unsigned start, uint8_t* address, IpTask* next): DirectCallTask(unsigned start, uint8_t* address, IpTask* next):
@ -718,8 +811,11 @@ class DirectCallTask: public IpTask {
uint8_t* code, unsigned offset) uint8_t* code, unsigned offset)
{ {
uint8_t* instruction = code + offset + (this->start - start); uint8_t* instruction = code + offset + (this->start - start);
assert(c, *instruction == 0xe8);
intptr_t v = address - instruction; intptr_t v = address - instruction;
assert(c, isInt32(v)); assert(c, isInt32(v));
int32_t v32 = v; int32_t v32 = v;
memcpy(instruction + 1, &v32, 4); memcpy(instruction + 1, &v32, 4);
} }
@ -748,6 +844,13 @@ ImmediateOperand::apply(Context* c, Operation operation)
c->code.append(0xE8); c->code.append(0xE8);
c->code.append4(0); c->code.append4(0);
} break; } break;
case alignedCall: {
while ((c->code.length() + 1) % 4) {
c->code.append(0x90);
}
apply(c, call);
} break;
default: abort(c); default: abort(c);
} }
@ -776,6 +879,10 @@ void
MemoryOperand::apply(Context* c, Operation operation) MemoryOperand::apply(Context* c, Operation operation)
{ {
switch (operation) { switch (operation) {
case pop:
encode(c, 0x8f, 0, 0x40, 0x80, rax, base->asRegister(c), displacement);
break;
default: abort(c); 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 { class MyCompiler: public Compiler {
public: public:
MyCompiler(System* s, void* indirectCaller): MyCompiler(System* s, void* indirectCaller):
@ -1140,8 +1308,12 @@ class MyCompiler: public Compiler {
return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip); return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip);
} }
virtual unsigned size() { virtual unsigned codeSize() {
return c.code.length() + c.constantPool.length(); return c.code.length();
}
virtual unsigned poolSize() {
return c.constantPool.length();
} }
virtual void writeTo(uint8_t* out) { virtual void writeTo(uint8_t* out) {
@ -1172,21 +1344,22 @@ class MyCompiler: public Compiler {
for (unsigned i = 0; i < tableSize; ++i) { for (unsigned i = 0; i < tableSize; ++i) {
IpMapping* mapping = c.ipTable[i]; IpMapping* mapping = c.ipTable[i];
int length = mapping->end - mapping->start; int length = mapping->end - mapping->start;
memcpy(p, c.code.data + mapping->start, length);
for (IpTask* t = mapping->task; t; t = t->next) { memcpy(p, c.code.data + mapping->start, length);
t->run(&c, mapping->ip, mapping->start, mapping->end, out, p - out);
}
p += length; p += length;
} }
memcpy(p, c.constantPool.data, c.constantPool.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) { virtual void updateCall(void* returnAddress, void* newTarget) {
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5; uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
assert(&c, *instruction == 0xE8); assert(&c, *instruction == 0xE8);
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
int32_t v = static_cast<uint8_t*>(newTarget) int32_t v = static_cast<uint8_t*>(newTarget)
- static_cast<uint8_t*>(returnAddress); - static_cast<uint8_t*>(returnAddress);
@ -1203,52 +1376,9 @@ class MyCompiler: public Compiler {
}; };
unsigned unsigned
PoolPromise::value(Compiler* compiler) MyPromise::value(Compiler* compiler)
{ {
Context* c = &(static_cast<MyCompiler*>(compiler)->c); return value(&(static_cast<MyCompiler*>(compiler)->c));
if (c->ipTable) {
return c->code.length() + key;
}
abort(c);
}
unsigned
CodePromise::value(Compiler* compiler)
{
Context* c = &(static_cast<MyCompiler*>(compiler)->c);
if (c->ipTable) {
return key;
}
abort(c);
}
unsigned
IpPromise::value(Compiler* compiler)
{
Context* c = &(static_cast<MyCompiler*>(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);
} }
} // namespace } // namespace

View File

@ -94,7 +94,8 @@ class Compiler {
virtual void startLogicalIp(unsigned) = 0; virtual void startLogicalIp(unsigned) = 0;
virtual Operand* logicalIp(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 writeTo(uint8_t*) = 0;
virtual void updateCall(void* returnAddress, void* newTarget) = 0; virtual void updateCall(void* returnAddress, void* newTarget) = 0;

View File

@ -23,7 +23,7 @@ public class Misc {
int b = 2; int b = 2;
int c = a + b; int c = a + b;
// Misc m = new Misc(); Misc m = new Misc();
// String s = "hello"; // String s = "hello";
// m.foo(s); // m.foo(s);
// m.bar(s); // m.bar(s);