mirror of
https://github.com/corda/corda.git
synced 2025-01-19 03:06:36 +00:00
2+2 test now works with new JIT code
This commit is contained in:
parent
286f290665
commit
fdeafe46fd
5
makefile
5
makefile
@ -28,7 +28,7 @@ src = src
|
||||
classpath = classpath
|
||||
test = test
|
||||
|
||||
input = $(test-build)/Exceptions.class
|
||||
input = $(test-build)/Misc.class
|
||||
|
||||
build-cxx = g++
|
||||
build-cc = gcc
|
||||
@ -40,6 +40,7 @@ ranlib = ranlib
|
||||
objcopy = objcopy
|
||||
vg = nice valgrind --suppressions=valgrind.supp --undef-value-errors=no \
|
||||
--num-callers=32 --db-attach=yes --freelist-vol=100000000
|
||||
vg += --leak-check=full
|
||||
db = gdb --args
|
||||
javac = javac
|
||||
jar = jar
|
||||
@ -105,7 +106,7 @@ ifeq ($(platform),windows)
|
||||
endif
|
||||
|
||||
ifeq ($(mode),debug)
|
||||
cflags += -O0 -g3 -DNDEBUG
|
||||
cflags += -O0 -g3
|
||||
endif
|
||||
ifeq ($(mode),stress)
|
||||
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS
|
||||
|
@ -11,35 +11,38 @@ vmInvoke:
|
||||
|
||||
// rbx is a callee-saved register (so are r12-r15, but we don't use those)
|
||||
pushq %rbx
|
||||
|
||||
// %rdi: function
|
||||
// %rsi: stack
|
||||
// %rdx: stackSize
|
||||
// %rcx: returnType
|
||||
|
||||
// %rdi: thread
|
||||
// %rsi: function
|
||||
// %rdx: stack
|
||||
// %rcx: stackSize
|
||||
// %r8 : returnType
|
||||
|
||||
mov %rdi,%rbx
|
||||
|
||||
// reserve space for arguments
|
||||
pushq %rdx
|
||||
subq %rdx,%rsp
|
||||
pushq %rcx
|
||||
subq %rcx,%rsp
|
||||
|
||||
// copy memory arguments into place
|
||||
movq $0,%r8
|
||||
movq $0,%r9
|
||||
jmp test
|
||||
|
||||
loop:
|
||||
movq %r8,%rax
|
||||
movq %r8,%r9
|
||||
addq %rsp,%r9
|
||||
addq %rsi,%rax
|
||||
movq %r9,%rax
|
||||
movq %r9,%r10
|
||||
addq %rsp,%r10
|
||||
addq %rdx,%rax
|
||||
movq (%rax),%rax
|
||||
movq %rax,(%r9)
|
||||
addq $8,%r8
|
||||
movq %rax,(%r10)
|
||||
addq $8,%r9
|
||||
|
||||
test:
|
||||
cmpq %rdx,%r8
|
||||
cmpq %rcx,%r9
|
||||
jb loop
|
||||
|
||||
// call function
|
||||
call *%rdi
|
||||
call *%rsi
|
||||
|
||||
// pop arguments
|
||||
addq -16(%rbp),%rsp
|
||||
@ -68,13 +71,16 @@ vmInvoke:
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
|
||||
// 8(%ebp): function
|
||||
// 12(%ebp): stack
|
||||
// 16(%ebp): stackSize
|
||||
// 20(%ebp): returnType
|
||||
// 8(%ebp): thread
|
||||
// 12(%ebp): function
|
||||
// 16(%ebp): stack
|
||||
// 20(%ebp): stackSize
|
||||
// 24(%ebp): returnType
|
||||
|
||||
mov 8(%ebp),%rbx
|
||||
|
||||
// reserve space for arguments
|
||||
subl 16(%ebp),%esp
|
||||
subl 20(%ebp),%esp
|
||||
|
||||
// copy arguments into place
|
||||
movl $0,%ecx
|
||||
@ -84,23 +90,23 @@ loop:
|
||||
movl %ecx,%eax
|
||||
movl %ecx,%edx
|
||||
addl %esp,%edx
|
||||
addl 12(%ebp),%eax
|
||||
addl 16(%ebp),%eax
|
||||
movl (%eax),%eax
|
||||
movl %eax,(%edx)
|
||||
addl $4,%ecx
|
||||
|
||||
test:
|
||||
cmpl 16(%ebp),%ecx
|
||||
cmpl 20(%ebp),%ecx
|
||||
jb loop
|
||||
|
||||
// call function
|
||||
call *8(%ebp)
|
||||
call *12(%ebp)
|
||||
|
||||
// pop arguments
|
||||
addl 16(%ebp),%esp
|
||||
addl 20(%ebp),%esp
|
||||
|
||||
// handle return value based on expected type
|
||||
movl 20(%ebp),%ecx
|
||||
movl 24(%ebp),%ecx
|
||||
|
||||
void:
|
||||
cmpl $VOID_TYPE,%ecx
|
||||
|
@ -314,7 +314,9 @@ class Frame {
|
||||
}
|
||||
|
||||
~Frame() {
|
||||
t->m->system->free(codeMask);
|
||||
if (next == 0) {
|
||||
t->m->system->free(codeMask);
|
||||
}
|
||||
}
|
||||
|
||||
Operand* append(object o) {
|
||||
@ -378,13 +380,17 @@ class Frame {
|
||||
}
|
||||
|
||||
void storedInt(unsigned index) {
|
||||
assert(t, index < localSize(t, method));
|
||||
clearBit(map, index);
|
||||
if (index >= parameterFootprint(t, method)) {
|
||||
assert(t, index - parameterFootprint(t, method) < localSize(t, method));
|
||||
clearBit(map, index - parameterFootprint(t, method));
|
||||
}
|
||||
}
|
||||
|
||||
void storedObject(unsigned index) {
|
||||
assert(t, index < localSize(t, method));
|
||||
markBit(map, index);
|
||||
if (index >= parameterFootprint(t, method)) {
|
||||
assert(t, index - parameterFootprint(t, method) < localSize(t, method));
|
||||
markBit(map, index - parameterFootprint(t, method));
|
||||
}
|
||||
}
|
||||
|
||||
void dupped() {
|
||||
@ -2729,7 +2735,8 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
{
|
||||
unsigned count = ceiling(c->size(), BytesPerWord);
|
||||
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);
|
||||
singletonMask(t, result)[0] = 1;
|
||||
|
||||
@ -3108,11 +3115,13 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
||||
while (true) {
|
||||
object node = findTraceNode(t, *stack);
|
||||
if (node) {
|
||||
object method = traceNodeMethod(t, node);
|
||||
|
||||
PROTECT(t, node);
|
||||
|
||||
// we only need to visit the parameters of this method if the
|
||||
// caller is native. Otherwise, the caller owns them.
|
||||
object next = findTraceNode(t, static_cast<void**>(base)[1]);
|
||||
object method = traceNodeMethod(t, node);
|
||||
|
||||
if (next == 0) {
|
||||
visitParameters(t, v, base, method);
|
||||
}
|
||||
@ -3345,7 +3354,7 @@ class MyProcessor: public Processor {
|
||||
virtual Thread*
|
||||
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);
|
||||
t->init();
|
||||
return t;
|
||||
@ -3410,21 +3419,23 @@ class MyProcessor: public Processor {
|
||||
object loader,
|
||||
unsigned vtableLength)
|
||||
{
|
||||
object c = vm::makeClass
|
||||
return vm::makeClass
|
||||
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
|
||||
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
|
||||
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
|
||||
= ((flags & ACC_NATIVE)
|
||||
= ((classFlags(t, c) & ACC_NATIVE)
|
||||
? getNativeCompiled(static_cast<MyThread*>(t))
|
||||
: getDefaultCompiled(static_cast<MyThread*>(t)));
|
||||
|
||||
classVtable(t, c, i) = &singletonBody(t, compiled, 0);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual void
|
||||
@ -3586,6 +3597,13 @@ class MyProcessor: public Processor {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void dispose(Thread* thread) {
|
||||
MyThread* t = static_cast<MyThread*>(thread);
|
||||
while (t->reference) {
|
||||
vm::dispose(t, t->reference);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (indirectCaller) {
|
||||
s->free(indirectCaller);
|
||||
@ -3599,7 +3617,7 @@ class MyProcessor: public Processor {
|
||||
object nativeCompiled;
|
||||
object addressTable;
|
||||
unsigned addressCount;
|
||||
void* indirectCaller;
|
||||
uint8_t* indirectCaller;
|
||||
};
|
||||
|
||||
MyProcessor*
|
||||
@ -3619,8 +3637,11 @@ processor(MyThread* t)
|
||||
|
||||
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->dispose();
|
||||
}
|
||||
}
|
||||
return p;
|
||||
@ -3631,14 +3652,12 @@ compile(MyThread* t, object method)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
|
||||
object stub = p->getDefaultCompiled(t);
|
||||
|
||||
if (methodCompiled(t, method) == stub) {
|
||||
if (methodCompiled(t, method) == p->getDefaultCompiled(t)) {
|
||||
PROTECT(t, method);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
if (methodCompiled(t, method) == stub) {
|
||||
if (methodCompiled(t, method) == p->getDefaultCompiled(t)) {
|
||||
PROTECT(t, method);
|
||||
|
||||
Compiler* c = makeCompiler(t->m->system, p->indirectCaller);
|
||||
@ -3655,6 +3674,7 @@ object
|
||||
findTraceNode(MyThread* t, void* address)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
intptr_t key = reinterpret_cast<intptr_t>(address);
|
||||
unsigned index = static_cast<uintptr_t>(key)
|
||||
@ -3700,13 +3720,12 @@ void
|
||||
insertTraceNode(MyThread* t, object node)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
ENTER(t, Thread::ExclusiveState);
|
||||
PROTECT(t, node);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
++ p->addressCount;
|
||||
|
||||
if (p->addressCount >= arrayLength(t, p->addressTable) * 2) {
|
||||
PROTECT(t, node);
|
||||
|
||||
p->addressTable = resizeTable
|
||||
(t, p->addressTable, arrayLength(t, p->addressTable) * 2);
|
||||
}
|
||||
|
424
src/compiler.cpp
424
src/compiler.cpp
@ -25,8 +25,19 @@ enum Register {
|
||||
r15 = 15,
|
||||
};
|
||||
|
||||
const unsigned RegisterCount32 = 8;
|
||||
const unsigned RegisterCount64 = 16;
|
||||
const unsigned RegisterCount = BytesPerWord * 2;
|
||||
|
||||
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
|
||||
isInt8(intptr_t v)
|
||||
@ -40,14 +51,28 @@ isInt32(intptr_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 {
|
||||
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 start;
|
||||
int end;
|
||||
int offset;
|
||||
IpTask* task;
|
||||
};
|
||||
|
||||
int
|
||||
@ -59,45 +84,45 @@ compareIpMappingPointers(const void* a, const void* b)
|
||||
|
||||
class MyPromise: public Promise {
|
||||
public:
|
||||
MyPromise(intptr_t value): resolved(false), value_(value) { }
|
||||
MyPromise(intptr_t key): key(key) { }
|
||||
|
||||
bool resolved;
|
||||
intptr_t value_;
|
||||
intptr_t key;
|
||||
};
|
||||
|
||||
class PoolPromise: public MyPromise {
|
||||
public:
|
||||
PoolPromise(intptr_t value): MyPromise(value) { }
|
||||
PoolPromise(intptr_t key): MyPromise(key) { }
|
||||
|
||||
virtual unsigned value(Compiler*);
|
||||
};
|
||||
|
||||
class CodePromise: public MyPromise {
|
||||
public:
|
||||
CodePromise(intptr_t value): MyPromise(value) { }
|
||||
CodePromise(intptr_t key): MyPromise(key) { }
|
||||
|
||||
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 {
|
||||
public:
|
||||
IpPromise(intptr_t value): MyPromise(value) { }
|
||||
IpPromise(intptr_t key): MyPromise(key) { }
|
||||
|
||||
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 {
|
||||
public:
|
||||
enum Operation {
|
||||
@ -156,8 +181,6 @@ class MyOperand: public Operand {
|
||||
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
|
||||
};
|
||||
|
||||
class StackOperand;
|
||||
|
||||
class RegisterOperand: public MyOperand {
|
||||
public:
|
||||
RegisterOperand(Register value):
|
||||
@ -169,17 +192,25 @@ class RegisterOperand: public MyOperand {
|
||||
stack = 0;
|
||||
}
|
||||
|
||||
virtual Register asRegister(Context*) {
|
||||
return value;
|
||||
}
|
||||
|
||||
virtual void release(Context* c UNUSED) {
|
||||
assert(c, reserved);
|
||||
reserved = false;
|
||||
}
|
||||
|
||||
virtual void apply(Context* c, Operation) { abort(c); }
|
||||
virtual void apply(Context*, Operation);
|
||||
|
||||
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
|
||||
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;
|
||||
bool reserved;
|
||||
StackOperand* stack;
|
||||
@ -191,7 +222,9 @@ class ImmediateOperand: public MyOperand {
|
||||
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) {
|
||||
operand->accept(c, operation, this);
|
||||
@ -206,8 +239,10 @@ class AbsoluteOperand: public MyOperand {
|
||||
value(value)
|
||||
{ }
|
||||
|
||||
virtual void apply(Context* c, Operation operation);
|
||||
|
||||
virtual void setAbsolute(Context*, intptr_t v) {
|
||||
value->value_ = v;
|
||||
value->key = v;
|
||||
}
|
||||
|
||||
MyPromise* value;
|
||||
@ -223,10 +258,17 @@ class MemoryOperand: public MyOperand {
|
||||
scale(scale)
|
||||
{ }
|
||||
|
||||
virtual StackOperand* logicalPush(Context* c);
|
||||
|
||||
virtual void apply(Context* c, Operation operation);
|
||||
|
||||
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
|
||||
operand->accept(c, operation, this);
|
||||
}
|
||||
|
||||
virtual void accept(Context*, Operation, RegisterOperand*);
|
||||
virtual void accept(Context*, Operation, ImmediateOperand*);
|
||||
|
||||
MyOperand* base;
|
||||
int displacement;
|
||||
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;
|
||||
StackOperand* next;
|
||||
int index;
|
||||
@ -287,10 +335,12 @@ class Context {
|
||||
zone(s, 8 * 1024),
|
||||
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
|
||||
stack(0),
|
||||
machineTable(0),
|
||||
logicalTable(0)
|
||||
ipTable(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)))
|
||||
RegisterOperand(static_cast<Register>(i));
|
||||
}
|
||||
@ -305,8 +355,7 @@ class Context {
|
||||
ipMappings.dispose();
|
||||
constantPool.dispose();
|
||||
code.dispose();
|
||||
if (machineTable) s->free(machineTable);
|
||||
if (logicalTable) s->free(logicalTable);
|
||||
if (ipTable) s->free(ipTable);
|
||||
}
|
||||
|
||||
System* s;
|
||||
@ -316,9 +365,8 @@ class Context {
|
||||
Zone zone;
|
||||
intptr_t indirectCaller;
|
||||
StackOperand* stack;
|
||||
IpMapping** machineTable;
|
||||
IpMapping** logicalTable;
|
||||
RegisterOperand* registers[RegisterCount64];
|
||||
IpMapping** ipTable;
|
||||
RegisterOperand* registers[RegisterCount];
|
||||
};
|
||||
|
||||
inline void NO_RETURN
|
||||
@ -367,6 +415,15 @@ memory(Context* c, MyOperand* base, int displacement,
|
||||
MemoryOperand(base, displacement, index, scale);
|
||||
}
|
||||
|
||||
IpMapping*
|
||||
currentMapping(Context* c)
|
||||
{
|
||||
IpMapping* mapping;
|
||||
c->ipMappings.get
|
||||
(c->ipMappings.length() - BytesPerWord, &mapping, BytesPerWord);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
void
|
||||
flush(Context* c, StackOperand* s)
|
||||
{
|
||||
@ -380,13 +437,14 @@ flush(Context* c, StackOperand* s)
|
||||
}
|
||||
|
||||
RegisterOperand*
|
||||
temporary(Context* c)
|
||||
temporary(Context* c, bool reserve)
|
||||
{
|
||||
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]->stack) {
|
||||
c->registers[i]->reserved = true;
|
||||
if (c->registers[i]->stack == 0) {
|
||||
if (reserve) c->registers[i]->reserved = true;
|
||||
return c->registers[i];
|
||||
} else if (r == 0 or r->stack->index > c->registers[i]->stack->index) {
|
||||
r = c->registers[i];
|
||||
@ -429,14 +487,16 @@ pop(Context* c, MyOperand* dst)
|
||||
MyOperand*
|
||||
pop(Context* c)
|
||||
{
|
||||
MyOperand* r;
|
||||
if (c->stack->flushed) {
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
RegisterOperand* tmp = temporary(c, true);
|
||||
tmp->apply(c, MyOperand::pop);
|
||||
return tmp;
|
||||
r = tmp;
|
||||
} else {
|
||||
return c->stack->base;
|
||||
r = c->stack->base;
|
||||
}
|
||||
c->stack = c->stack->next;
|
||||
return r;
|
||||
}
|
||||
|
||||
MyOperand*
|
||||
@ -521,7 +581,6 @@ pushArguments(Context* c, unsigned count, va_list list)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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 {
|
||||
public:
|
||||
MyCompiler(System* s, void* indirectCaller):
|
||||
@ -579,8 +824,18 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Promise* codeOffset() {
|
||||
return new (c.zone.allocate(sizeof(CodePromise)))
|
||||
CodePromise(c.code.length());
|
||||
if (c.code.length() == 0) {
|
||||
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) {
|
||||
@ -651,7 +906,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Operand* temporary() {
|
||||
return ::temporary(&c);
|
||||
return ::temporary(&c, true);
|
||||
}
|
||||
|
||||
virtual void release(Operand* v) {
|
||||
@ -868,12 +1123,13 @@ class MyCompiler: public Compiler {
|
||||
|
||||
virtual void epilogue() {
|
||||
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) {
|
||||
new (c.ipMappings.allocate(sizeof(IpMapping)))
|
||||
IpMapping(ip, c.code.length());
|
||||
c.ipMappings.appendAddress
|
||||
(new (c.zone.allocate(sizeof(IpMapping)))
|
||||
IpMapping(ip, c.code.length()));
|
||||
}
|
||||
|
||||
virtual Operand* logicalIp(unsigned ip) {
|
||||
@ -888,39 +1144,40 @@ class MyCompiler: public Compiler {
|
||||
return c.code.length() + c.constantPool.length();
|
||||
}
|
||||
|
||||
virtual void writeTo(void* out) {
|
||||
unsigned tableSize = (c.ipMappings.length() / sizeof(IpMapping));
|
||||
virtual void writeTo(uint8_t* out) {
|
||||
unsigned tableSize = (c.ipMappings.length() / BytesPerWord);
|
||||
|
||||
c.machineTable = static_cast<IpMapping**>
|
||||
(c.s->allocate(tableSize * BytesPerWord));
|
||||
c.logicalTable = static_cast<IpMapping**>
|
||||
(c.s->allocate(tableSize * BytesPerWord));
|
||||
c.ipTable = static_cast<IpMapping**>
|
||||
(c.s->allocate(c.ipMappings.length()));
|
||||
|
||||
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()) {
|
||||
mapping->end = c.ipMappings.peek<IpMapping>
|
||||
((i + 1) * sizeof(IpMapping))->start;
|
||||
if (i + 1 < tableSize) {
|
||||
IpMapping* next;
|
||||
c.ipMappings.get((i + 1) * BytesPerWord, &next, BytesPerWord);
|
||||
mapping->end = next->start;
|
||||
} else {
|
||||
mapping->end = c.code.length();
|
||||
}
|
||||
|
||||
c.machineTable[i] = mapping;
|
||||
c.logicalTable[i] = mapping;
|
||||
c.ipTable[i] = mapping;
|
||||
}
|
||||
|
||||
qsort(c.logicalTable, c.ipMappings.length() / sizeof(IpMapping),
|
||||
BytesPerWord, compareIpMappingPointers);
|
||||
qsort(c.ipTable, tableSize, BytesPerWord, compareIpMappingPointers);
|
||||
|
||||
uint8_t* p = static_cast<uint8_t*>(out);
|
||||
uint8_t* p = out;
|
||||
|
||||
for (unsigned i = 0; i < tableSize; ++i) {
|
||||
IpMapping* mapping = c.logicalTable[i];
|
||||
mapping->offset = (p - static_cast<uint8_t*>(out));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
p += length;
|
||||
}
|
||||
|
||||
@ -950,8 +1207,8 @@ PoolPromise::value(Compiler* compiler)
|
||||
{
|
||||
Context* c = &(static_cast<MyCompiler*>(compiler)->c);
|
||||
|
||||
if (c->logicalTable) {
|
||||
return c->code.length() + value_;
|
||||
if (c->ipTable) {
|
||||
return c->code.length() + key;
|
||||
}
|
||||
|
||||
abort(c);
|
||||
@ -962,21 +1219,8 @@ CodePromise::value(Compiler* compiler)
|
||||
{
|
||||
Context* c = &(static_cast<MyCompiler*>(compiler)->c);
|
||||
|
||||
if (c->logicalTable) {
|
||||
unsigned bottom = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (c->ipTable) {
|
||||
return key;
|
||||
}
|
||||
|
||||
abort(c);
|
||||
@ -987,18 +1231,18 @@ IpPromise::value(Compiler* compiler)
|
||||
{
|
||||
Context* c = &(static_cast<MyCompiler*>(compiler)->c);
|
||||
|
||||
if (c->logicalTable) {
|
||||
if (c->ipTable) {
|
||||
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) {
|
||||
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;
|
||||
} else if (value_ < mapping->ip) {
|
||||
} else if (key < mapping->ip) {
|
||||
top = middle;
|
||||
} else if (value_ > mapping->ip) {
|
||||
} else if (key > mapping->ip) {
|
||||
bottom = middle + 1;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ class Compiler {
|
||||
virtual Operand* logicalIp(unsigned) = 0;
|
||||
|
||||
virtual unsigned size() = 0;
|
||||
virtual void writeTo(void*) = 0;
|
||||
virtual void writeTo(uint8_t*) = 0;
|
||||
|
||||
virtual void updateCall(void* returnAddress, void* newTarget) = 0;
|
||||
|
||||
|
@ -2867,6 +2867,12 @@ class MyProcessor: public Processor {
|
||||
methodTable, staticTable, loader, 0, false);
|
||||
}
|
||||
|
||||
virtual void
|
||||
initVtable(Thread*, object)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual void
|
||||
initClass(vm::Thread* t, object c)
|
||||
{
|
||||
@ -3009,6 +3015,10 @@ class MyProcessor: public Processor {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void dispose(vm::Thread*) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(this);
|
||||
}
|
||||
|
@ -1498,7 +1498,7 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
||||
object vtable = classVirtualTable
|
||||
(t, arrayBody(t, t->m->types, Machine::JobjectType));
|
||||
|
||||
return t->m->processor->makeClass
|
||||
object c = t->m->processor->makeClass
|
||||
(t,
|
||||
0,
|
||||
0,
|
||||
@ -1515,6 +1515,10 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
||||
elementClass,
|
||||
t->m->loader,
|
||||
arrayLength(t, vtable));
|
||||
|
||||
t->m->processor->initVtable(t, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
object
|
||||
@ -1662,6 +1666,8 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
|
||||
|
||||
set(t, class_, ClassVirtualTable, vtable);
|
||||
|
||||
t->m->processor->initVtable(t, class_);
|
||||
|
||||
hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash);
|
||||
}
|
||||
|
||||
@ -1986,6 +1992,8 @@ Thread::exit()
|
||||
void
|
||||
Thread::dispose()
|
||||
{
|
||||
m->processor->dispose(this);
|
||||
|
||||
if (systemThread) {
|
||||
systemThread->dispose();
|
||||
}
|
||||
@ -2471,6 +2479,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
||||
classLoader(t, class_),
|
||||
vtableLength);
|
||||
|
||||
t->m->processor->initVtable(t, real);
|
||||
|
||||
updateClassTables(t, real, class_);
|
||||
|
||||
return real;
|
||||
|
@ -67,6 +67,9 @@ class Processor {
|
||||
object loader,
|
||||
unsigned vtableLength) = 0;
|
||||
|
||||
virtual void
|
||||
initVtable(Thread* t, object c) = 0;
|
||||
|
||||
virtual void
|
||||
initClass(Thread* t, object c) = 0;
|
||||
|
||||
@ -96,6 +99,9 @@ class Processor {
|
||||
invokeList(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, va_list arguments) = 0;
|
||||
|
||||
virtual void
|
||||
dispose(Thread* t) = 0;
|
||||
|
||||
virtual void
|
||||
dispose() = 0;
|
||||
|
||||
|
@ -15,24 +15,24 @@ public class Misc {
|
||||
}
|
||||
|
||||
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 b = 2;
|
||||
int c = a + b;
|
||||
|
||||
Misc m = new Misc();
|
||||
String s = "hello";
|
||||
m.foo(s);
|
||||
m.bar(s);
|
||||
baz(s);
|
||||
// Misc m = new Misc();
|
||||
// String s = "hello";
|
||||
// m.foo(s);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user