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 {
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<unsigned>
(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<uint8_t*>
(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();
}
}

View File

@ -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<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 {
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<uint8_t*>(returnAddress) - 5;
assert(&c, *instruction == 0xE8);
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
int32_t v = static_cast<uint8_t*>(newTarget)
- static_cast<uint8_t*>(returnAddress);
@ -1203,52 +1376,9 @@ class MyCompiler: public Compiler {
};
unsigned
PoolPromise::value(Compiler* compiler)
MyPromise::value(Compiler* compiler)
{
Context* c = &(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);
return value(&(static_cast<MyCompiler*>(compiler)->c));
}
} // namespace

View File

@ -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;

View File

@ -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);