2+2 test now works with new JIT code

This commit is contained in:
Joel Dice 2007-12-11 14:26:59 -07:00
parent 286f290665
commit fdeafe46fd
9 changed files with 451 additions and 155 deletions

View File

@ -28,7 +28,7 @@ src = src
classpath = classpath classpath = classpath
test = test test = test
input = $(test-build)/Exceptions.class input = $(test-build)/Misc.class
build-cxx = g++ build-cxx = g++
build-cc = gcc build-cc = gcc
@ -40,6 +40,7 @@ ranlib = ranlib
objcopy = objcopy objcopy = objcopy
vg = nice valgrind --suppressions=valgrind.supp --undef-value-errors=no \ vg = nice valgrind --suppressions=valgrind.supp --undef-value-errors=no \
--num-callers=32 --db-attach=yes --freelist-vol=100000000 --num-callers=32 --db-attach=yes --freelist-vol=100000000
vg += --leak-check=full
db = gdb --args db = gdb --args
javac = javac javac = javac
jar = jar jar = jar
@ -105,7 +106,7 @@ ifeq ($(platform),windows)
endif endif
ifeq ($(mode),debug) ifeq ($(mode),debug)
cflags += -O0 -g3 -DNDEBUG cflags += -O0 -g3
endif endif
ifeq ($(mode),stress) ifeq ($(mode),stress)
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS cflags += -O0 -g3 -DNDEBUG -DVM_STRESS

View File

@ -11,35 +11,38 @@ vmInvoke:
// rbx is a callee-saved register (so are r12-r15, but we don't use those) // rbx is a callee-saved register (so are r12-r15, but we don't use those)
pushq %rbx pushq %rbx
// %rdi: function // %rdi: thread
// %rsi: stack // %rsi: function
// %rdx: stackSize // %rdx: stack
// %rcx: returnType // %rcx: stackSize
// %r8 : returnType
mov %rdi,%rbx
// reserve space for arguments // reserve space for arguments
pushq %rdx pushq %rcx
subq %rdx,%rsp subq %rcx,%rsp
// copy memory arguments into place // copy memory arguments into place
movq $0,%r8 movq $0,%r9
jmp test jmp test
loop: loop:
movq %r8,%rax movq %r9,%rax
movq %r8,%r9 movq %r9,%r10
addq %rsp,%r9 addq %rsp,%r10
addq %rsi,%rax addq %rdx,%rax
movq (%rax),%rax movq (%rax),%rax
movq %rax,(%r9) movq %rax,(%r10)
addq $8,%r8 addq $8,%r9
test: test:
cmpq %rdx,%r8 cmpq %rcx,%r9
jb loop jb loop
// call function // call function
call *%rdi call *%rsi
// pop arguments // pop arguments
addq -16(%rbp),%rsp addq -16(%rbp),%rsp
@ -68,13 +71,16 @@ vmInvoke:
pushl %esi pushl %esi
pushl %edi pushl %edi
// 8(%ebp): function // 8(%ebp): thread
// 12(%ebp): stack // 12(%ebp): function
// 16(%ebp): stackSize // 16(%ebp): stack
// 20(%ebp): returnType // 20(%ebp): stackSize
// 24(%ebp): returnType
mov 8(%ebp),%rbx
// reserve space for arguments // reserve space for arguments
subl 16(%ebp),%esp subl 20(%ebp),%esp
// copy arguments into place // copy arguments into place
movl $0,%ecx movl $0,%ecx
@ -84,23 +90,23 @@ loop:
movl %ecx,%eax movl %ecx,%eax
movl %ecx,%edx movl %ecx,%edx
addl %esp,%edx addl %esp,%edx
addl 12(%ebp),%eax addl 16(%ebp),%eax
movl (%eax),%eax movl (%eax),%eax
movl %eax,(%edx) movl %eax,(%edx)
addl $4,%ecx addl $4,%ecx
test: test:
cmpl 16(%ebp),%ecx cmpl 20(%ebp),%ecx
jb loop jb loop
// call function // call function
call *8(%ebp) call *12(%ebp)
// pop arguments // pop arguments
addl 16(%ebp),%esp addl 20(%ebp),%esp
// handle return value based on expected type // handle return value based on expected type
movl 20(%ebp),%ecx movl 24(%ebp),%ecx
void: void:
cmpl $VOID_TYPE,%ecx cmpl $VOID_TYPE,%ecx

View File

@ -314,7 +314,9 @@ class Frame {
} }
~Frame() { ~Frame() {
t->m->system->free(codeMask); if (next == 0) {
t->m->system->free(codeMask);
}
} }
Operand* append(object o) { Operand* append(object o) {
@ -378,13 +380,17 @@ class Frame {
} }
void storedInt(unsigned index) { void storedInt(unsigned index) {
assert(t, index < localSize(t, method)); if (index >= parameterFootprint(t, method)) {
clearBit(map, index); assert(t, index - parameterFootprint(t, method) < localSize(t, method));
clearBit(map, index - parameterFootprint(t, method));
}
} }
void storedObject(unsigned index) { void storedObject(unsigned index) {
assert(t, index < localSize(t, method)); if (index >= parameterFootprint(t, method)) {
markBit(map, index); assert(t, index - parameterFootprint(t, method) < localSize(t, method));
markBit(map, index - parameterFootprint(t, method));
}
} }
void dupped() { void dupped() {
@ -2729,7 +2735,8 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
{ {
unsigned count = ceiling(c->size(), BytesPerWord); unsigned count = ceiling(c->size(), BytesPerWord);
unsigned size = count + singletonMaskSize(count); unsigned size = count + singletonMaskSize(count);
object result = allocate2(t, size * BytesPerWord, true, true); object result = allocate2
(t, SingletonBody + size * BytesPerWord, true, true);
initSingleton(t, result, size, true); initSingleton(t, result, size, true);
singletonMask(t, result)[0] = 1; singletonMask(t, result)[0] = 1;
@ -3108,11 +3115,13 @@ visitStack(MyThread* t, Heap::Visitor* v)
while (true) { while (true) {
object node = findTraceNode(t, *stack); object node = findTraceNode(t, *stack);
if (node) { if (node) {
object method = traceNodeMethod(t, node); PROTECT(t, node);
// we only need to visit the parameters of this method if the // we only need to visit the parameters of this method if the
// caller is native. Otherwise, the caller owns them. // caller is native. Otherwise, the caller owns them.
object next = findTraceNode(t, static_cast<void**>(base)[1]); object next = findTraceNode(t, static_cast<void**>(base)[1]);
object method = traceNodeMethod(t, node);
if (next == 0) { if (next == 0) {
visitParameters(t, v, base, method); visitParameters(t, v, base, method);
} }
@ -3345,7 +3354,7 @@ class MyProcessor: public Processor {
virtual Thread* virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent) makeThread(Machine* m, object javaThread, Thread* parent)
{ {
MyThread* t = new (s->allocate(sizeof(Thread))) MyThread* t = new (s->allocate(sizeof(MyThread)))
MyThread(m, javaThread, parent); MyThread(m, javaThread, parent);
t->init(); t->init();
return t; return t;
@ -3410,21 +3419,23 @@ class MyProcessor: public Processor {
object loader, object loader,
unsigned vtableLength) unsigned vtableLength)
{ {
object c = vm::makeClass return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize, (t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
objectMask, name, super, interfaceTable, virtualTable, fieldTable, objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, vtableLength, false); methodTable, staticTable, loader, vtableLength, false);
}
for (unsigned i = 0; i < vtableLength; ++i) { virtual void
initVtable(Thread* t, object c)
{
for (unsigned i = 0; i < classLength(t, c); ++i) {
object compiled object compiled
= ((flags & ACC_NATIVE) = ((classFlags(t, c) & ACC_NATIVE)
? getNativeCompiled(static_cast<MyThread*>(t)) ? getNativeCompiled(static_cast<MyThread*>(t))
: getDefaultCompiled(static_cast<MyThread*>(t))); : getDefaultCompiled(static_cast<MyThread*>(t)));
classVtable(t, c, i) = &singletonBody(t, compiled, 0); classVtable(t, c, i) = &singletonBody(t, compiled, 0);
} }
return c;
} }
virtual void virtual void
@ -3586,6 +3597,13 @@ class MyProcessor: public Processor {
return 0; return 0;
} }
virtual void dispose(Thread* thread) {
MyThread* t = static_cast<MyThread*>(thread);
while (t->reference) {
vm::dispose(t, t->reference);
}
}
virtual void dispose() { virtual void dispose() {
if (indirectCaller) { if (indirectCaller) {
s->free(indirectCaller); s->free(indirectCaller);
@ -3599,7 +3617,7 @@ class MyProcessor: public Processor {
object nativeCompiled; object nativeCompiled;
object addressTable; object addressTable;
unsigned addressCount; unsigned addressCount;
void* indirectCaller; uint8_t* indirectCaller;
}; };
MyProcessor* MyProcessor*
@ -3619,8 +3637,11 @@ processor(MyThread* t)
c->jmp(c->indirectTarget()); c->jmp(c->indirectTarget());
p->indirectCaller = t->m->system->allocate(c->size()); p->indirectCaller = static_cast<uint8_t*>
(t->m->system->allocate(c->size()));
c->writeTo(p->indirectCaller); c->writeTo(p->indirectCaller);
c->dispose();
} }
} }
return p; return p;
@ -3631,14 +3652,12 @@ compile(MyThread* t, object method)
{ {
MyProcessor* p = processor(t); MyProcessor* p = processor(t);
object stub = p->getDefaultCompiled(t); if (methodCompiled(t, method) == p->getDefaultCompiled(t)) {
if (methodCompiled(t, method) == stub) {
PROTECT(t, method); PROTECT(t, method);
ACQUIRE(t, t->m->classLock); ACQUIRE(t, t->m->classLock);
if (methodCompiled(t, method) == stub) { if (methodCompiled(t, method) == p->getDefaultCompiled(t)) {
PROTECT(t, method); PROTECT(t, method);
Compiler* c = makeCompiler(t->m->system, p->indirectCaller); Compiler* c = makeCompiler(t->m->system, p->indirectCaller);
@ -3655,6 +3674,7 @@ object
findTraceNode(MyThread* t, void* address) findTraceNode(MyThread* t, void* address)
{ {
MyProcessor* p = processor(t); MyProcessor* p = processor(t);
ACQUIRE(t, t->m->classLock);
intptr_t key = reinterpret_cast<intptr_t>(address); intptr_t key = reinterpret_cast<intptr_t>(address);
unsigned index = static_cast<uintptr_t>(key) unsigned index = static_cast<uintptr_t>(key)
@ -3700,13 +3720,12 @@ void
insertTraceNode(MyThread* t, object node) insertTraceNode(MyThread* t, object node)
{ {
MyProcessor* p = processor(t); MyProcessor* p = processor(t);
ENTER(t, Thread::ExclusiveState); PROTECT(t, node);
ACQUIRE(t, t->m->classLock);
++ p->addressCount; ++ p->addressCount;
if (p->addressCount >= arrayLength(t, p->addressTable) * 2) { if (p->addressCount >= arrayLength(t, p->addressTable) * 2) {
PROTECT(t, node);
p->addressTable = resizeTable p->addressTable = resizeTable
(t, p->addressTable, arrayLength(t, p->addressTable) * 2); (t, p->addressTable, arrayLength(t, p->addressTable) * 2);
} }

View File

@ -25,8 +25,19 @@ enum Register {
r15 = 15, r15 = 15,
}; };
const unsigned RegisterCount32 = 8; const unsigned RegisterCount = BytesPerWord * 2;
const unsigned RegisterCount64 = 16;
class Context;
class ImmediateOperand;
class RegisterOperand;
class MemoryOperand;
class StackOperand;
void NO_RETURN abort(Context*);
#ifndef NDEBUG
void assert(Context*, bool);
#endif // not NDEBUG
inline bool inline bool
isInt8(intptr_t v) isInt8(intptr_t v)
@ -40,14 +51,28 @@ isInt32(intptr_t v)
return v == static_cast<int32_t>(v); return v == static_cast<int32_t>(v);
} }
class IpTask {
public:
IpTask(IpTask* next): next(next) { }
virtual ~IpTask() { }
virtual void run(Context* c, unsigned ip, unsigned start, unsigned end,
uint8_t* code, unsigned offset) = 0;
IpTask* next;
};
class IpMapping { class IpMapping {
public: public:
IpMapping(unsigned ip, unsigned start): ip(ip), start(start), end(-1) { } IpMapping(int ip, int start):
ip(ip), start(start), end(-1), task(0)
{ }
const int ip; const int ip;
const int start; const int start;
int end; int end;
int offset; IpTask* task;
}; };
int int
@ -59,45 +84,45 @@ compareIpMappingPointers(const void* a, const void* b)
class MyPromise: public Promise { class MyPromise: public Promise {
public: public:
MyPromise(intptr_t value): resolved(false), value_(value) { } MyPromise(intptr_t key): key(key) { }
bool resolved; intptr_t key;
intptr_t value_;
}; };
class PoolPromise: public MyPromise { class PoolPromise: public MyPromise {
public: public:
PoolPromise(intptr_t value): MyPromise(value) { } PoolPromise(intptr_t key): MyPromise(key) { }
virtual unsigned value(Compiler*); virtual unsigned value(Compiler*);
}; };
class CodePromise: public MyPromise { class CodePromise: public MyPromise {
public: public:
CodePromise(intptr_t value): MyPromise(value) { } CodePromise(intptr_t key): MyPromise(key) { }
virtual unsigned value(Compiler*); virtual unsigned value(Compiler*);
}; };
class CodePromiseTask: public IpTask {
public:
CodePromiseTask(CodePromise* p, IpTask* next): IpTask(next), p(p) { }
virtual void run(Context*, unsigned, unsigned start, unsigned, uint8_t*,
unsigned offset)
{
p->key = offset + (p->key - start);
}
CodePromise* p;
};
class IpPromise: public MyPromise { class IpPromise: public MyPromise {
public: public:
IpPromise(intptr_t value): MyPromise(value) { } IpPromise(intptr_t key): MyPromise(key) { }
virtual unsigned value(Compiler*); virtual unsigned value(Compiler*);
}; };
class Context;
class ImmediateOperand;
class RegisterOperand;
class MemoryOperand;
class StackOperand;
void NO_RETURN abort(Context*);
#ifndef NDEBUG
void assert(Context*, bool);
#endif // not NDEBUG
class MyOperand: public Operand { class MyOperand: public Operand {
public: public:
enum Operation { enum Operation {
@ -156,8 +181,6 @@ class MyOperand: public Operand {
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); } virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
}; };
class StackOperand;
class RegisterOperand: public MyOperand { class RegisterOperand: public MyOperand {
public: public:
RegisterOperand(Register value): RegisterOperand(Register value):
@ -169,17 +192,25 @@ class RegisterOperand: public MyOperand {
stack = 0; stack = 0;
} }
virtual Register asRegister(Context*) {
return value;
}
virtual void release(Context* c UNUSED) { virtual void release(Context* c UNUSED) {
assert(c, reserved); assert(c, reserved);
reserved = false; reserved = false;
} }
virtual void apply(Context* c, Operation) { abort(c); } virtual void apply(Context*, Operation);
virtual void apply(Context* c, Operation operation, MyOperand* operand) { virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this); operand->accept(c, operation, this);
} }
virtual void accept(Context*, Operation, RegisterOperand*);
virtual void accept(Context*, Operation, ImmediateOperand*);
virtual void accept(Context*, Operation, MemoryOperand*);
Register value; Register value;
bool reserved; bool reserved;
StackOperand* stack; StackOperand* stack;
@ -191,7 +222,9 @@ class ImmediateOperand: public MyOperand {
value(value) value(value)
{ } { }
virtual void apply(Context* c, Operation) { abort(c); } virtual StackOperand* logicalPush(Context* c);
virtual void apply(Context* c, Operation operation);
virtual void apply(Context* c, Operation operation, MyOperand* operand) { virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this); operand->accept(c, operation, this);
@ -206,8 +239,10 @@ class AbsoluteOperand: public MyOperand {
value(value) value(value)
{ } { }
virtual void apply(Context* c, Operation operation);
virtual void setAbsolute(Context*, intptr_t v) { virtual void setAbsolute(Context*, intptr_t v) {
value->value_ = v; value->key = v;
} }
MyPromise* value; MyPromise* value;
@ -223,10 +258,17 @@ class MemoryOperand: public MyOperand {
scale(scale) scale(scale)
{ } { }
virtual StackOperand* logicalPush(Context* c);
virtual void apply(Context* c, Operation operation);
virtual void apply(Context* c, Operation operation, MyOperand* operand) { virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this); operand->accept(c, operation, this);
} }
virtual void accept(Context*, Operation, RegisterOperand*);
virtual void accept(Context*, Operation, ImmediateOperand*);
MyOperand* base; MyOperand* base;
int displacement; int displacement;
MyOperand* index; MyOperand* index;
@ -271,6 +313,12 @@ class StackOperand: public MyOperand {
} }
} }
virtual void accept(Context* c, Operation operation,
RegisterOperand* operand)
{
base->accept(c, operation, operand);
}
MyOperand* base; MyOperand* base;
StackOperand* next; StackOperand* next;
int index; int index;
@ -287,10 +335,12 @@ class Context {
zone(s, 8 * 1024), zone(s, 8 * 1024),
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)), indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
stack(0), stack(0),
machineTable(0), ipTable(0)
logicalTable(0)
{ {
for (unsigned i = 0; i < RegisterCount64; ++i) { ipMappings.appendAddress
(new (zone.allocate(sizeof(IpMapping))) IpMapping(-1, 0));
for (unsigned i = 0; i < RegisterCount; ++i) {
registers[i] = new (zone.allocate(sizeof(RegisterOperand))) registers[i] = new (zone.allocate(sizeof(RegisterOperand)))
RegisterOperand(static_cast<Register>(i)); RegisterOperand(static_cast<Register>(i));
} }
@ -305,8 +355,7 @@ class Context {
ipMappings.dispose(); ipMappings.dispose();
constantPool.dispose(); constantPool.dispose();
code.dispose(); code.dispose();
if (machineTable) s->free(machineTable); if (ipTable) s->free(ipTable);
if (logicalTable) s->free(logicalTable);
} }
System* s; System* s;
@ -316,9 +365,8 @@ class Context {
Zone zone; Zone zone;
intptr_t indirectCaller; intptr_t indirectCaller;
StackOperand* stack; StackOperand* stack;
IpMapping** machineTable; IpMapping** ipTable;
IpMapping** logicalTable; RegisterOperand* registers[RegisterCount];
RegisterOperand* registers[RegisterCount64];
}; };
inline void NO_RETURN inline void NO_RETURN
@ -367,6 +415,15 @@ memory(Context* c, MyOperand* base, int displacement,
MemoryOperand(base, displacement, index, scale); MemoryOperand(base, displacement, index, scale);
} }
IpMapping*
currentMapping(Context* c)
{
IpMapping* mapping;
c->ipMappings.get
(c->ipMappings.length() - BytesPerWord, &mapping, BytesPerWord);
return mapping;
}
void void
flush(Context* c, StackOperand* s) flush(Context* c, StackOperand* s)
{ {
@ -380,13 +437,14 @@ flush(Context* c, StackOperand* s)
} }
RegisterOperand* RegisterOperand*
temporary(Context* c) temporary(Context* c, bool reserve)
{ {
RegisterOperand* r = 0; RegisterOperand* r = 0;
for (unsigned i = 0; i < RegisterCount32; ++i) { // we don't yet support using r9-r15
for (unsigned i = 0; i < 8/*RegisterCount*/; ++i) {
if (not c->registers[i]->reserved) { if (not c->registers[i]->reserved) {
if (not c->registers[i]->stack) { if (c->registers[i]->stack == 0) {
c->registers[i]->reserved = true; if (reserve) c->registers[i]->reserved = true;
return c->registers[i]; return c->registers[i];
} else if (r == 0 or r->stack->index > c->registers[i]->stack->index) { } else if (r == 0 or r->stack->index > c->registers[i]->stack->index) {
r = c->registers[i]; r = c->registers[i];
@ -429,14 +487,16 @@ pop(Context* c, MyOperand* dst)
MyOperand* MyOperand*
pop(Context* c) pop(Context* c)
{ {
MyOperand* r;
if (c->stack->flushed) { if (c->stack->flushed) {
RegisterOperand* tmp = temporary(c); RegisterOperand* tmp = temporary(c, true);
tmp->apply(c, MyOperand::pop); tmp->apply(c, MyOperand::pop);
return tmp; r = tmp;
} else { } else {
return c->stack->base; r = c->stack->base;
} }
c->stack = c->stack->next; c->stack = c->stack->next;
return r;
} }
MyOperand* MyOperand*
@ -521,7 +581,6 @@ pushArguments(Context* c, unsigned count, va_list list)
} }
} }
void void
rex(Context* c) rex(Context* c)
{ {
@ -567,6 +626,192 @@ encode(Context* c, uint8_t instruction, uint8_t zeroPrefix,
} }
} }
void
RegisterOperand::apply(Context* c, Operation operation)
{
switch (operation) {
case push:
c->code.append(0x50 | value);
break;
case pop:
c->code.append(0x58 | value);
break;
case jmp:
c->code.append(0xff);
c->code.append(0xe0 | value);
break;
case call:
c->code.append(0xff);
c->code.append(0xd0 | value);
break;
default: abort(c);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
RegisterOperand* operand)
{
switch (operation) {
case mov:
if (value != operand->value) {
rex(c);
c->code.append(0x89);
c->code.append(0xc0 | (operand->value << 3) | value);
}
break;
case add:
rex(c);
c->code.append(0x01);
c->code.append(0xc0 | (operand->value << 3) | value);
break;
default: abort(c);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
ImmediateOperand* operand)
{
switch (operation) {
case sub:
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);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
MemoryOperand* operand)
{
switch (operation) {
case mov:
rex(c);
encode(c, 0x8b, 0, 0x40, 0x80, value, operand->base->asRegister(c),
operand->displacement);
break;
default: abort(c);
}
}
class DirectCallTask: public IpTask {
public:
DirectCallTask(unsigned start, uint8_t* address, IpTask* next):
IpTask(next), start(start), address(address)
{ }
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 = address - instruction;
assert(c, isInt32(v));
int32_t v32 = v;
memcpy(instruction + 1, &v32, 4);
}
unsigned start;
uint8_t* address;
};
StackOperand*
ImmediateOperand::logicalPush(Context* c)
{
return c->stack = new (c->zone.allocate(sizeof(StackOperand)))
StackOperand(this, c->stack);
}
void
ImmediateOperand::apply(Context* c, Operation operation)
{
switch (operation) {
case call: {
IpMapping* mapping = currentMapping(c);
mapping->task = new (c->zone.allocate(sizeof(DirectCallTask)))
DirectCallTask
(c->code.length(), reinterpret_cast<uint8_t*>(value), mapping->task);
c->code.append(0xE8);
c->code.append4(0);
} break;
default: abort(c);
}
}
void
AbsoluteOperand::apply(Context* c, Operation operation)
{
switch (operation) {
default: abort(c);
}
}
StackOperand*
MemoryOperand::logicalPush(Context* c)
{
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;
return c->stack;
}
void
MemoryOperand::apply(Context* c, Operation operation)
{
switch (operation) {
default: abort(c);
}
}
void
MemoryOperand::accept(Context* c, Operation operation,
RegisterOperand* operand)
{
switch (operation) {
case mov:
rex(c);
encode(c, 0x89, 0, 0x40, 0x80, operand->value, base->asRegister(c),
displacement);
break;
default: abort(c);
}
}
void
MemoryOperand::accept(Context* c, Operation operation,
ImmediateOperand* operand)
{
switch (operation) {
case mov:
assert(c, isInt32(operand->value)); // todo
rex(c);
encode(c, 0xc7, 0, 0x40, 0x80, rax, base->asRegister(c), displacement);
c->code.append4(operand->value);
break;
default: abort(c);
}
}
class MyCompiler: public Compiler { class MyCompiler: public Compiler {
public: public:
MyCompiler(System* s, void* indirectCaller): MyCompiler(System* s, void* indirectCaller):
@ -579,8 +824,18 @@ class MyCompiler: public Compiler {
} }
virtual Promise* codeOffset() { virtual Promise* codeOffset() {
return new (c.zone.allocate(sizeof(CodePromise))) if (c.code.length() == 0) {
CodePromise(c.code.length()); return new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0);
} else {
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise)))
CodePromise(c.code.length());
IpMapping* mapping = currentMapping(&c);
mapping->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
CodePromiseTask(p, mapping->task);
return p;
}
} }
virtual Operand* poolAppend(Operand* v) { virtual Operand* poolAppend(Operand* v) {
@ -651,7 +906,7 @@ class MyCompiler: public Compiler {
} }
virtual Operand* temporary() { virtual Operand* temporary() {
return ::temporary(&c); return ::temporary(&c, true);
} }
virtual void release(Operand* v) { virtual void release(Operand* v) {
@ -868,12 +1123,13 @@ class MyCompiler: public Compiler {
virtual void epilogue() { virtual void epilogue() {
register_(&c, rbp)->apply(&c, MyOperand::mov, register_(&c, rsp)); register_(&c, rbp)->apply(&c, MyOperand::mov, register_(&c, rsp));
register_(&c, rbp)->apply(&c, MyOperand::push); register_(&c, rbp)->apply(&c, MyOperand::pop);
} }
virtual void startLogicalIp(unsigned ip) { virtual void startLogicalIp(unsigned ip) {
new (c.ipMappings.allocate(sizeof(IpMapping))) c.ipMappings.appendAddress
IpMapping(ip, c.code.length()); (new (c.zone.allocate(sizeof(IpMapping)))
IpMapping(ip, c.code.length()));
} }
virtual Operand* logicalIp(unsigned ip) { virtual Operand* logicalIp(unsigned ip) {
@ -888,39 +1144,40 @@ class MyCompiler: public Compiler {
return c.code.length() + c.constantPool.length(); return c.code.length() + c.constantPool.length();
} }
virtual void writeTo(void* out) { virtual void writeTo(uint8_t* out) {
unsigned tableSize = (c.ipMappings.length() / sizeof(IpMapping)); unsigned tableSize = (c.ipMappings.length() / BytesPerWord);
c.machineTable = static_cast<IpMapping**> c.ipTable = static_cast<IpMapping**>
(c.s->allocate(tableSize * BytesPerWord)); (c.s->allocate(c.ipMappings.length()));
c.logicalTable = static_cast<IpMapping**>
(c.s->allocate(tableSize * BytesPerWord));
for (unsigned i = 0; i < tableSize; ++i) { for (unsigned i = 0; i < tableSize; ++i) {
IpMapping* mapping = c.ipMappings.peek<IpMapping>(i * sizeof(IpMapping)); IpMapping* mapping;
c.ipMappings.get(i * BytesPerWord, &mapping, BytesPerWord);
if (i + 1 < c.ipMappings.length()) { if (i + 1 < tableSize) {
mapping->end = c.ipMappings.peek<IpMapping> IpMapping* next;
((i + 1) * sizeof(IpMapping))->start; c.ipMappings.get((i + 1) * BytesPerWord, &next, BytesPerWord);
mapping->end = next->start;
} else { } else {
mapping->end = c.code.length(); mapping->end = c.code.length();
} }
c.machineTable[i] = mapping; c.ipTable[i] = mapping;
c.logicalTable[i] = mapping;
} }
qsort(c.logicalTable, c.ipMappings.length() / sizeof(IpMapping), qsort(c.ipTable, tableSize, BytesPerWord, compareIpMappingPointers);
BytesPerWord, compareIpMappingPointers);
uint8_t* p = static_cast<uint8_t*>(out); uint8_t* p = out;
for (unsigned i = 0; i < tableSize; ++i) { for (unsigned i = 0; i < tableSize; ++i) {
IpMapping* mapping = c.logicalTable[i]; IpMapping* mapping = c.ipTable[i];
mapping->offset = (p - static_cast<uint8_t*>(out));
int length = mapping->end - mapping->start; int length = mapping->end - mapping->start;
memcpy(p, c.code.data + mapping->start, length); 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);
}
p += length; p += length;
} }
@ -950,8 +1207,8 @@ PoolPromise::value(Compiler* compiler)
{ {
Context* c = &(static_cast<MyCompiler*>(compiler)->c); Context* c = &(static_cast<MyCompiler*>(compiler)->c);
if (c->logicalTable) { if (c->ipTable) {
return c->code.length() + value_; return c->code.length() + key;
} }
abort(c); abort(c);
@ -962,21 +1219,8 @@ CodePromise::value(Compiler* compiler)
{ {
Context* c = &(static_cast<MyCompiler*>(compiler)->c); Context* c = &(static_cast<MyCompiler*>(compiler)->c);
if (c->logicalTable) { if (c->ipTable) {
unsigned bottom = 0; return key;
unsigned top = c->ipMappings.length() / sizeof(IpMapping);
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
IpMapping* mapping = c->machineTable[middle];
if (value_ >= mapping->start and value_ < mapping->end) {
return mapping->offset + (value_ - mapping->start);
} else if (value_ < mapping->start) {
top = middle;
} else if (value_ > mapping->start) {
bottom = middle + 1;
}
}
} }
abort(c); abort(c);
@ -987,18 +1231,18 @@ IpPromise::value(Compiler* compiler)
{ {
Context* c = &(static_cast<MyCompiler*>(compiler)->c); Context* c = &(static_cast<MyCompiler*>(compiler)->c);
if (c->logicalTable) { if (c->ipTable) {
unsigned bottom = 0; unsigned bottom = 0;
unsigned top = c->ipMappings.length() / sizeof(IpMapping); unsigned top = c->ipMappings.length() / BytesPerWord;
for (unsigned span = top - bottom; span; span = top - bottom) { for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2); unsigned middle = bottom + (span / 2);
IpMapping* mapping = c->logicalTable[middle]; IpMapping* mapping = c->ipTable[middle];
if (value_ == mapping->ip) { if (key == mapping->ip) {
return mapping->start; return mapping->start;
} else if (value_ < mapping->ip) { } else if (key < mapping->ip) {
top = middle; top = middle;
} else if (value_ > mapping->ip) { } else if (key > mapping->ip) {
bottom = middle + 1; bottom = middle + 1;
} }
} }

View File

@ -95,7 +95,7 @@ class Compiler {
virtual Operand* logicalIp(unsigned) = 0; virtual Operand* logicalIp(unsigned) = 0;
virtual unsigned size() = 0; virtual unsigned size() = 0;
virtual void writeTo(void*) = 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

@ -2867,6 +2867,12 @@ class MyProcessor: public Processor {
methodTable, staticTable, loader, 0, false); methodTable, staticTable, loader, 0, false);
} }
virtual void
initVtable(Thread*, object)
{
// ignore
}
virtual void virtual void
initClass(vm::Thread* t, object c) initClass(vm::Thread* t, object c)
{ {
@ -3009,6 +3015,10 @@ class MyProcessor: public Processor {
} }
} }
virtual void dispose(vm::Thread*) {
// ignore
}
virtual void dispose() { virtual void dispose() {
s->free(this); s->free(this);
} }

View File

@ -1498,7 +1498,7 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
object vtable = classVirtualTable object vtable = classVirtualTable
(t, arrayBody(t, t->m->types, Machine::JobjectType)); (t, arrayBody(t, t->m->types, Machine::JobjectType));
return t->m->processor->makeClass object c = t->m->processor->makeClass
(t, (t,
0, 0,
0, 0,
@ -1515,6 +1515,10 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
elementClass, elementClass,
t->m->loader, t->m->loader,
arrayLength(t, vtable)); arrayLength(t, vtable));
t->m->processor->initVtable(t, c);
return c;
} }
object object
@ -1662,6 +1666,8 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
set(t, class_, ClassVirtualTable, vtable); set(t, class_, ClassVirtualTable, vtable);
t->m->processor->initVtable(t, class_);
hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash); hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash);
} }
@ -1986,6 +1992,8 @@ Thread::exit()
void void
Thread::dispose() Thread::dispose()
{ {
m->processor->dispose(this);
if (systemThread) { if (systemThread) {
systemThread->dispose(); systemThread->dispose();
} }
@ -2471,6 +2479,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
classLoader(t, class_), classLoader(t, class_),
vtableLength); vtableLength);
t->m->processor->initVtable(t, real);
updateClassTables(t, real, class_); updateClassTables(t, real, class_);
return real; return real;

View File

@ -67,6 +67,9 @@ class Processor {
object loader, object loader,
unsigned vtableLength) = 0; unsigned vtableLength) = 0;
virtual void
initVtable(Thread* t, object c) = 0;
virtual void virtual void
initClass(Thread* t, object c) = 0; initClass(Thread* t, object c) = 0;
@ -96,6 +99,9 @@ class Processor {
invokeList(Thread* t, const char* className, const char* methodName, invokeList(Thread* t, const char* className, const char* methodName,
const char* methodSpec, object this_, va_list arguments) = 0; const char* methodSpec, object this_, va_list arguments) = 0;
virtual void
dispose(Thread* t) = 0;
virtual void virtual void
dispose() = 0; dispose() = 0;

View File

@ -15,24 +15,24 @@ public class Misc {
} }
public static void main(String[] args) { public static void main(String[] args) {
boolean v = Boolean.valueOf("true"); // boolean v = Boolean.valueOf("true");
ClassLoader.getSystemClassLoader().toString(); // ClassLoader.getSystemClassLoader().toString();
int a = 2; int a = 2;
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);
baz(s); // baz(s);
int d = alpha; // int d = alpha;
beta = 42; // beta = 42;
alpha = 43; // alpha = 43;
int e = beta; // int e = beta;
int f = alpha; // int f = alpha;
} }
} }