mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +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
|
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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
424
src/compiler.cpp
424
src/compiler.cpp
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user