mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
lots of JIT bugfixes and cleanups
This commit is contained in:
parent
924a588cdf
commit
796a64a426
2
makefile
2
makefile
@ -28,7 +28,7 @@ src = src
|
||||
classpath = classpath
|
||||
test = test
|
||||
|
||||
input = $(test-build)/Misc.class
|
||||
input = $(test-build)/Enums.class
|
||||
|
||||
build-cxx = g++
|
||||
build-cc = gcc
|
||||
|
@ -617,6 +617,8 @@ Java_java_lang_Throwable_trace(Thread* t, jclass, jint skipCount)
|
||||
|
||||
t->m->processor->walkStack(t, &v);
|
||||
|
||||
if (v.trace == 0) v.trace = makeArray(t, 0, true);
|
||||
|
||||
return makeLocalReference(t, v.trace);
|
||||
}
|
||||
|
||||
|
242
src/compile.cpp
242
src/compile.cpp
@ -188,7 +188,9 @@ class MyStackWalker: public Processor::StackWalker {
|
||||
if (nativeMethod) {
|
||||
return 0;
|
||||
} else {
|
||||
return traceNodeAddress(t, node);
|
||||
intptr_t start = reinterpret_cast<intptr_t>
|
||||
(&singletonValue(t, methodCompiled(t, traceNodeMethod(t, node)), 0));
|
||||
return traceNodeAddress(t, node) - start;
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,19 +246,21 @@ localOffset(MyThread* t, int v, object method)
|
||||
|
||||
class PoolElement {
|
||||
public:
|
||||
PoolElement(object value, Promise* offset): value(value), offset(offset) { }
|
||||
PoolElement(object value, Promise* address):
|
||||
value(value), address(address)
|
||||
{ }
|
||||
|
||||
object value;
|
||||
Promise* offset;
|
||||
Promise* address;
|
||||
};
|
||||
|
||||
class TraceElement {
|
||||
public:
|
||||
TraceElement(object target, Promise* offset, bool virtualCall):
|
||||
target(target), offset(offset), virtualCall(virtualCall) { }
|
||||
TraceElement(object target, Promise* machineIp, bool virtualCall):
|
||||
target(target), machineIp(machineIp), virtualCall(virtualCall) { }
|
||||
|
||||
object target;
|
||||
Promise* offset;
|
||||
Promise* machineIp;
|
||||
bool virtualCall;
|
||||
uint8_t map[0];
|
||||
};
|
||||
@ -292,6 +296,7 @@ class Frame {
|
||||
next(0),
|
||||
t(t),
|
||||
c(c),
|
||||
stack(0),
|
||||
method(method),
|
||||
map(map),
|
||||
objectPool(objectPool),
|
||||
@ -308,6 +313,7 @@ class Frame {
|
||||
next(f),
|
||||
t(f->t),
|
||||
c(f->c),
|
||||
stack(f->stack),
|
||||
method(f->method),
|
||||
map(map),
|
||||
objectPool(f->objectPool),
|
||||
@ -327,9 +333,9 @@ class Frame {
|
||||
}
|
||||
|
||||
Operand* append(object o) {
|
||||
new (objectPool->allocate(sizeof(PoolElement)))
|
||||
PoolElement(o, c->poolOffset());
|
||||
return c->poolAppend(c->constant(0));
|
||||
Promise* p = c->poolAppend(0);
|
||||
new (objectPool->allocate(sizeof(PoolElement))) PoolElement(o, p);
|
||||
return c->absolute(p);
|
||||
}
|
||||
|
||||
static unsigned parameterFootprint(Thread* t, object method) {
|
||||
@ -578,7 +584,7 @@ class Frame {
|
||||
|
||||
void trace(object target, bool virtualCall) {
|
||||
TraceElement* e = new (traceLog->allocate(traceSizeInBytes(t, method)))
|
||||
TraceElement(target, c->codeOffset(), virtualCall);
|
||||
TraceElement(target, c->machineIp(), virtualCall);
|
||||
memcpy(e->map, map, mapSizeInWords(t, method) * BytesPerWord);
|
||||
}
|
||||
|
||||
@ -586,42 +592,46 @@ class Frame {
|
||||
trace(0, false);
|
||||
}
|
||||
|
||||
Operand* machineIp(unsigned logicalIp) {
|
||||
return c->promiseConstant(c->machineIp(logicalIp));
|
||||
}
|
||||
|
||||
void startLogicalIp(unsigned ip) {
|
||||
c->startLogicalIp(ip);
|
||||
this->ip = ip;
|
||||
}
|
||||
|
||||
void pushInt(Operand* o) {
|
||||
c->push(o);
|
||||
stack = c->push(stack, o);
|
||||
pushedInt();
|
||||
}
|
||||
|
||||
void pushObject(Operand* o) {
|
||||
c->push(o);
|
||||
stack = c->push(stack, o);
|
||||
pushedObject();
|
||||
}
|
||||
|
||||
void pushObject() {
|
||||
c->push(1);
|
||||
stack = c->push(stack, 1);
|
||||
pushedObject();
|
||||
}
|
||||
|
||||
void pushLong(Operand* o) {
|
||||
c->push2(o);
|
||||
stack = c->push2(stack, o);
|
||||
pushedInt();
|
||||
pushedInt();
|
||||
}
|
||||
|
||||
void pop(unsigned count) {
|
||||
popped(count);
|
||||
c->pop(count);
|
||||
stack = c->pop(stack, count);
|
||||
}
|
||||
|
||||
Operand* topInt() {
|
||||
assert(t, sp >= 1);
|
||||
assert(t, sp - 1 >= localSize(t, method));
|
||||
assert(t, getBit(map, sp - 1) == 0);
|
||||
return c->stack(0);
|
||||
return c->stack(stack, 0);
|
||||
}
|
||||
|
||||
Operand* topLong() {
|
||||
@ -629,45 +639,47 @@ class Frame {
|
||||
assert(t, sp - 2 >= localSize(t, method));
|
||||
assert(t, getBit(map, sp - 1) == 0);
|
||||
assert(t, getBit(map, sp - 2) == 0);
|
||||
return c->stack(1);
|
||||
return c->stack(stack, 1);
|
||||
}
|
||||
|
||||
Operand* topObject() {
|
||||
assert(t, sp >= 1);
|
||||
assert(t, sp - 1 >= localSize(t, method));
|
||||
assert(t, getBit(map, sp - 1) != 0);
|
||||
return c->stack(0);
|
||||
return c->stack(stack, 0);
|
||||
}
|
||||
|
||||
Operand* popInt() {
|
||||
poppedInt();
|
||||
return c->pop();
|
||||
Operand* tmp = c->temporary();
|
||||
popInt(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Operand* popLong() {
|
||||
poppedInt();
|
||||
poppedInt();
|
||||
return c->pop2();
|
||||
Operand* tmp = c->temporary();
|
||||
popLong(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Operand* popObject() {
|
||||
poppedObject();
|
||||
return c->pop();
|
||||
Operand* tmp = c->temporary();
|
||||
popObject(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void popInt(Operand* o) {
|
||||
c->pop(o);
|
||||
stack = c->pop(stack, o);
|
||||
poppedInt();
|
||||
}
|
||||
|
||||
void popLong(Operand* o) {
|
||||
c->pop2(o);
|
||||
stack = c->pop2(stack, o);
|
||||
poppedInt();
|
||||
poppedInt();
|
||||
}
|
||||
|
||||
void popObject(Operand* o) {
|
||||
c->pop(o);
|
||||
stack = c->pop(stack, o);
|
||||
poppedObject();
|
||||
}
|
||||
|
||||
@ -712,83 +724,84 @@ class Frame {
|
||||
}
|
||||
|
||||
void increment(unsigned index, unsigned count) {
|
||||
assert(t, index < localSize(t, method));
|
||||
assert(t, getBit(map, index) == 0);
|
||||
assert(t, index < codeMaxLocals(t, methodCode(t, method)));
|
||||
assert(t, index < parameterFootprint(t, method)
|
||||
or getBit(map, index - parameterFootprint(t, method)) == 0);
|
||||
c->add(c->constant(count),
|
||||
c->memory(c->base(), localOffset(t, index, method)));
|
||||
}
|
||||
|
||||
void dup() {
|
||||
c->push(c->stack(0));
|
||||
stack = c->push(stack, c->stack(stack, 0));
|
||||
dupped();
|
||||
}
|
||||
|
||||
void dupX1() {
|
||||
Operand* s0 = c->stack(0);
|
||||
Operand* s1 = c->stack(1);
|
||||
Operand* s0 = c->stack(stack, 0);
|
||||
Operand* s1 = c->stack(stack, 1);
|
||||
|
||||
c->mov(s0, s1);
|
||||
c->mov(s1, s0);
|
||||
c->push(s0);
|
||||
stack = c->push(stack, s0);
|
||||
|
||||
duppedX1();
|
||||
}
|
||||
|
||||
void dupX2() {
|
||||
Operand* s0 = c->stack(0);
|
||||
Operand* s1 = c->stack(1);
|
||||
Operand* s2 = c->stack(2);
|
||||
Operand* s0 = c->stack(stack, 0);
|
||||
Operand* s1 = c->stack(stack, 1);
|
||||
Operand* s2 = c->stack(stack, 2);
|
||||
|
||||
c->mov(s0, s2);
|
||||
c->mov(s2, s1);
|
||||
c->mov(s1, s0);
|
||||
c->push(s0);
|
||||
stack = c->push(stack, s0);
|
||||
|
||||
duppedX2();
|
||||
}
|
||||
|
||||
void dup2() {
|
||||
Operand* s0 = c->stack(0);
|
||||
Operand* s0 = c->stack(stack, 0);
|
||||
|
||||
c->push(s0);
|
||||
c->push(s0);
|
||||
stack = c->push(stack, s0);
|
||||
stack = c->push(stack, s0);
|
||||
|
||||
dupped2();
|
||||
}
|
||||
|
||||
void dup2X1() {
|
||||
Operand* s0 = c->stack(0);
|
||||
Operand* s1 = c->stack(1);
|
||||
Operand* s2 = c->stack(2);
|
||||
Operand* s0 = c->stack(stack, 0);
|
||||
Operand* s1 = c->stack(stack, 1);
|
||||
Operand* s2 = c->stack(stack, 2);
|
||||
|
||||
c->mov(s1, s2);
|
||||
c->mov(s0, s1);
|
||||
c->mov(s2, s0);
|
||||
c->push(s1);
|
||||
c->push(s0);
|
||||
stack = c->push(stack, s1);
|
||||
stack = c->push(stack, s0);
|
||||
|
||||
dupped2X1();
|
||||
}
|
||||
|
||||
void dup2X2() {
|
||||
Operand* s0 = c->stack(0);
|
||||
Operand* s1 = c->stack(1);
|
||||
Operand* s2 = c->stack(2);
|
||||
Operand* s3 = c->stack(3);
|
||||
Operand* s0 = c->stack(stack, 0);
|
||||
Operand* s1 = c->stack(stack, 1);
|
||||
Operand* s2 = c->stack(stack, 2);
|
||||
Operand* s3 = c->stack(stack, 3);
|
||||
|
||||
c->mov(s1, s3);
|
||||
c->mov(s0, s2);
|
||||
c->mov(s3, s1);
|
||||
c->mov(s2, s0);
|
||||
c->push(s1);
|
||||
c->push(s0);
|
||||
stack = c->push(stack, s1);
|
||||
stack = c->push(stack, s0);
|
||||
|
||||
dupped2X2();
|
||||
}
|
||||
|
||||
void swap() {
|
||||
Operand* s0 = c->stack(0);
|
||||
Operand* s1 = c->stack(1);
|
||||
Operand* s0 = c->stack(stack, 0);
|
||||
Operand* s1 = c->stack(stack, 1);
|
||||
Operand* tmp = c->temporary();
|
||||
|
||||
c->mov(s0, tmp);
|
||||
@ -803,6 +816,7 @@ class Frame {
|
||||
Frame* next;
|
||||
MyThread* t;
|
||||
Compiler* c;
|
||||
Stack* stack;
|
||||
object method;
|
||||
uintptr_t* map;
|
||||
Vector* objectPool;
|
||||
@ -1818,7 +1832,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
||||
assert(t, newIp < codeLength(t, code));
|
||||
|
||||
c->jmp(c->logicalIp(newIp));
|
||||
c->jmp(frame->machineIp(newIp));
|
||||
ip = newIp;
|
||||
} break;
|
||||
|
||||
@ -1826,7 +1840,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
uint32_t newIp = (ip - 5) + codeReadInt32(t, code, ip);
|
||||
assert(t, newIp < codeLength(t, code));
|
||||
|
||||
c->jmp(c->logicalIp(newIp));
|
||||
c->jmp(frame->machineIp(newIp));
|
||||
ip = newIp;
|
||||
} break;
|
||||
|
||||
@ -1930,7 +1944,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
|
||||
Operand* target = c->logicalIp(newIp);
|
||||
Operand* target = frame->machineIp(newIp);
|
||||
if (instruction == if_acmpeq) {
|
||||
c->je(target);
|
||||
} else {
|
||||
@ -1956,7 +1970,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
|
||||
Operand* target = c->logicalIp(newIp);
|
||||
Operand* target = frame->machineIp(newIp);
|
||||
switch (instruction) {
|
||||
case if_icmpeq:
|
||||
c->je(target);
|
||||
@ -1995,7 +2009,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->cmp(c->constant(0), a);
|
||||
c->release(a);
|
||||
|
||||
Operand* target = c->logicalIp(newIp);
|
||||
Operand* target = frame->machineIp(newIp);
|
||||
switch (instruction) {
|
||||
case ifeq:
|
||||
c->je(target);
|
||||
@ -2026,11 +2040,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
||||
assert(t, newIp < codeLength(t, code));
|
||||
|
||||
Operand* a = frame->popInt();
|
||||
Operand* a = frame->popObject();
|
||||
c->cmp(c->constant(0), a);
|
||||
c->release(a);
|
||||
|
||||
Operand* target = c->logicalIp(newIp);
|
||||
Operand* target = frame->machineIp(newIp);
|
||||
if (instruction == ifnull) {
|
||||
c->je(target);
|
||||
} else {
|
||||
@ -2145,7 +2159,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
Operand* found = c->directCall
|
||||
(c->constant
|
||||
(reinterpret_cast<intptr_t>(findInterfaceMethodFromInstance)),
|
||||
3, c->thread(), frame->append(target), c->stack(instance));
|
||||
3, c->thread(), frame->append(target),
|
||||
c->stack(frame->stack, instance));
|
||||
|
||||
c->mov(c->memory(found, MethodCompiled), found);
|
||||
|
||||
@ -2195,7 +2210,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
unsigned offset = ClassVtable + (methodOffset(t, target) * BytesPerWord);
|
||||
|
||||
Operand* instance = c->stack(parameterFootprint - 1);
|
||||
Operand* instance = c->stack(frame->stack, parameterFootprint - 1);
|
||||
Operand* class_ = c->temporary();
|
||||
|
||||
c->mov(c->memory(instance), class_);
|
||||
@ -2432,30 +2447,28 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
||||
assert(t, defaultIp < codeLength(t, code));
|
||||
|
||||
compile(t, frame, defaultIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* default_ = c->poolAppend(c->logicalIp(defaultIp));
|
||||
Operand* default_ = c->absolute
|
||||
(c->poolAppendPromise(c->machineIp(defaultIp)));
|
||||
|
||||
int32_t pairCount = codeReadInt32(t, code, ip);
|
||||
|
||||
Operand* start;
|
||||
Operand* start = 0;
|
||||
uint32_t ipTable[pairCount];
|
||||
for (int32_t i = 0; i < pairCount; ++i) {
|
||||
unsigned index = ip + (i * 8);
|
||||
int32_t key = codeReadInt32(t, code, index);
|
||||
uint32_t newIp = base + codeReadInt32(t, code, index);
|
||||
assert(t, newIp < codeLength(t, code));
|
||||
|
||||
compile(t, frame, newIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* result = c->poolAppend(c->constant(key));
|
||||
c->poolAppend(c->logicalIp(newIp));
|
||||
ipTable[i] = newIp;
|
||||
|
||||
Promise* p = c->poolAppend(key);
|
||||
if (i == 0) {
|
||||
start = result;
|
||||
start = c->promiseConstant(p);
|
||||
}
|
||||
c->poolAppendPromise(c->machineIp(newIp));
|
||||
}
|
||||
assert(t, start);
|
||||
|
||||
c->jmp
|
||||
(c->directCall
|
||||
@ -2463,6 +2476,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
4, key, start, c->constant(pairCount), default_));
|
||||
|
||||
c->release(key);
|
||||
|
||||
for (int32_t i = 0; i < pairCount; ++i) {
|
||||
compile(t, frame, ipTable[i]);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
}
|
||||
|
||||
compile(t, frame, defaultIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
} return;
|
||||
|
||||
case lor: {
|
||||
@ -2611,7 +2632,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
Operand* size = frame->popInt();
|
||||
c->cmp(c->constant(0), size);
|
||||
c->release(size);
|
||||
|
||||
c->jge(nonnegative);
|
||||
|
||||
@ -2658,7 +2678,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
Operand* result = c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
|
||||
2, c->constant(reinterpret_cast<intptr_t>(constructor)), size);
|
||||
3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
|
||||
size);
|
||||
|
||||
c->release(size);
|
||||
|
||||
frame->trace();
|
||||
|
||||
@ -2782,29 +2805,25 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
||||
assert(t, defaultIp < codeLength(t, code));
|
||||
|
||||
compile(t, frame, defaultIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* default_ = c->poolAppend(c->logicalIp(defaultIp));
|
||||
|
||||
int32_t bottom = codeReadInt32(t, code, ip);
|
||||
int32_t top = codeReadInt32(t, code, ip);
|
||||
|
||||
Operand* start;
|
||||
for (int32_t i = 0; i < bottom - top + 1; ++i) {
|
||||
Operand* start = 0;
|
||||
uint32_t ipTable[top - bottom + 1];
|
||||
for (int32_t i = 0; i < top - bottom + 1; ++i) {
|
||||
unsigned index = ip + (i * 4);
|
||||
uint32_t newIp = base + codeReadInt32(t, code, index);
|
||||
assert(t, newIp < codeLength(t, code));
|
||||
|
||||
compile(t, frame, newIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* result = c->poolAppend(c->logicalIp(newIp));
|
||||
ipTable[i] = newIp;
|
||||
|
||||
Promise* p = c->poolAppendPromise(c->machineIp(newIp));
|
||||
if (i == 0) {
|
||||
start = result;
|
||||
start = c->promiseConstant(p);
|
||||
}
|
||||
}
|
||||
assert(t, start);
|
||||
|
||||
Operand* defaultCase = c->label();
|
||||
|
||||
@ -2814,13 +2833,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->cmp(c->constant(top), key);
|
||||
c->jg(defaultCase);
|
||||
|
||||
c->shl(c->constant(1), key);
|
||||
c->sub(c->constant(bottom), key);
|
||||
c->jmp(c->memory(start, 0, key, BytesPerWord));
|
||||
|
||||
c->mark(defaultCase);
|
||||
c->jmp(default_);
|
||||
c->jmp(frame->machineIp(defaultIp));
|
||||
|
||||
c->release(key);
|
||||
|
||||
for (int32_t i = 0; i < top - bottom + 1; ++i) {
|
||||
compile(t, frame, ipTable[i]);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
}
|
||||
|
||||
compile(t, frame, defaultIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
} return;
|
||||
|
||||
case wide: {
|
||||
@ -2887,10 +2914,12 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
|
||||
for (unsigned i = 0; i < objectPool->length(); i += sizeof(PoolElement)) {
|
||||
PoolElement* e = objectPool->peek<PoolElement>(i);
|
||||
intptr_t offset = e->address->value(c)
|
||||
- reinterpret_cast<intptr_t>(start);
|
||||
|
||||
singletonMarkObject(t, result, e->offset->value(c) / BytesPerWord);
|
||||
singletonMarkObject(t, result, offset / BytesPerWord);
|
||||
|
||||
set(t, result, SingletonBody + e->offset->value(c), e->value);
|
||||
set(t, result, SingletonBody + offset, e->value);
|
||||
}
|
||||
|
||||
unsigned traceSize = Frame::traceSizeInBytes(t, method);
|
||||
@ -2899,9 +2928,8 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
TraceElement* e = traceLog->peek<TraceElement>(i);
|
||||
|
||||
object node = makeTraceNode
|
||||
(t, reinterpret_cast<intptr_t>(start + e->offset->value(c)),
|
||||
0, method, e->target, e->virtualCall, mapSize / BytesPerWord,
|
||||
false);
|
||||
(t, e->machineIp->value(c), 0, method, e->target, e->virtualCall,
|
||||
mapSize / BytesPerWord, false);
|
||||
|
||||
if (mapSize) {
|
||||
memcpy(&traceNodeMap(t, node, 0), e->map, mapSize);
|
||||
@ -2927,16 +2955,16 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
(t, newTable, i);
|
||||
|
||||
exceptionHandlerStart(newHandler)
|
||||
= c->logicalIpToOffset(exceptionHandlerStart(oldHandler))
|
||||
->value(c);
|
||||
= c->machineIp(exceptionHandlerStart(oldHandler))->value(c)
|
||||
- reinterpret_cast<intptr_t>(start);
|
||||
|
||||
exceptionHandlerEnd(newHandler)
|
||||
= c->logicalIpToOffset(exceptionHandlerEnd(oldHandler))
|
||||
->value(c);
|
||||
= c->machineIp(exceptionHandlerEnd(oldHandler))->value(c)
|
||||
- reinterpret_cast<intptr_t>(start);
|
||||
|
||||
exceptionHandlerIp(newHandler)
|
||||
= c->logicalIpToOffset(exceptionHandlerIp(oldHandler))
|
||||
->value(c);
|
||||
= c->machineIp(exceptionHandlerIp(oldHandler))->value(c)
|
||||
- reinterpret_cast<intptr_t>(start);
|
||||
|
||||
exceptionHandlerCatchType(newHandler)
|
||||
= exceptionHandlerCatchType(oldHandler);
|
||||
@ -2957,8 +2985,9 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
LineNumber* oldLine = lineNumberTableBody(t, oldTable, i);
|
||||
LineNumber* newLine = lineNumberTableBody(t, newTable, i);
|
||||
|
||||
lineNumberIp(newLine) = c->logicalIpToOffset(lineNumberIp(oldLine))
|
||||
->value(c);
|
||||
lineNumberIp(newLine)
|
||||
= c->machineIp(lineNumberIp(oldLine))->value(c)
|
||||
- reinterpret_cast<intptr_t>(start);
|
||||
|
||||
lineNumberLine(newLine) = lineNumberLine(oldLine);
|
||||
}
|
||||
@ -2979,10 +3008,10 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
if (false and
|
||||
strcmp(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
|
||||
"java/lang/Boolean") == 0 and
|
||||
"Enums") == 0 and
|
||||
strcmp(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodName(t, method), 0)),
|
||||
"booleanValue") == 0)
|
||||
"checkFaceCard") == 0)
|
||||
{
|
||||
asm("int3");
|
||||
}
|
||||
@ -3474,8 +3503,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
r = (result == 0 ? 0 :
|
||||
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
||||
r = reinterpret_cast<object>(result);
|
||||
break;
|
||||
|
||||
case VoidField:
|
||||
|
468
src/compiler.cpp
468
src/compiler.cpp
@ -36,13 +36,14 @@ enum SelectionType {
|
||||
const bool Verbose = false;
|
||||
|
||||
const unsigned RegisterCount = BytesPerWord * 2;
|
||||
const unsigned GprParameterCount = 6;
|
||||
|
||||
class Context;
|
||||
class MyOperand;
|
||||
class ImmediateOperand;
|
||||
class AbsoluteOperand;
|
||||
class RegisterOperand;
|
||||
class MemoryOperand;
|
||||
class StackOperand;
|
||||
class CodePromise;
|
||||
class MyPromise;
|
||||
|
||||
@ -64,6 +65,16 @@ isInt32(intptr_t v)
|
||||
return v == static_cast<int32_t>(v);
|
||||
}
|
||||
|
||||
class RegisterNode {
|
||||
public:
|
||||
RegisterNode(Register value, RegisterNode* next):
|
||||
value(value), next(next)
|
||||
{ }
|
||||
|
||||
Register value;
|
||||
RegisterNode* next;
|
||||
};
|
||||
|
||||
class Task {
|
||||
public:
|
||||
Task(Task* next): next(next) { }
|
||||
@ -105,6 +116,17 @@ class Segment {
|
||||
Event* event;
|
||||
};
|
||||
|
||||
class MyStack: public Stack {
|
||||
public:
|
||||
MyStack(MyOperand* value, int index, MyStack* next):
|
||||
value(value), index(index), next(next)
|
||||
{ }
|
||||
|
||||
MyOperand* value;
|
||||
int index;
|
||||
MyStack* next;
|
||||
};
|
||||
|
||||
class MyOperand: public Operand {
|
||||
public:
|
||||
enum Operation {
|
||||
@ -144,9 +166,12 @@ class MyOperand: public Operand {
|
||||
|
||||
virtual Register asRegister(Context* c) { abort(c); }
|
||||
|
||||
virtual RegisterNode* dependencies(Context*, RegisterNode* next)
|
||||
{ return next; }
|
||||
|
||||
virtual void release(Context*) { /* ignore */ }
|
||||
|
||||
virtual void setLabelValue(Context* c, CodePromise*) { abort(c); }
|
||||
virtual void setLabelValue(Context* c, MyPromise*) { abort(c); }
|
||||
|
||||
virtual void apply(Context*, Operation) = 0;
|
||||
|
||||
@ -181,6 +206,8 @@ class RegisterOperand: public MyOperand {
|
||||
return value;
|
||||
}
|
||||
|
||||
virtual RegisterNode* dependencies(Context* c, RegisterNode* next);
|
||||
|
||||
void acquire(Context* c UNUSED) {
|
||||
assert(c, not reserved);
|
||||
// fprintf(stderr, "acquire %d\n", value);
|
||||
@ -253,7 +280,9 @@ class AddressOperand: public MyOperand {
|
||||
promise(promise)
|
||||
{ }
|
||||
|
||||
virtual void setLabelValue(Context*, CodePromise*);
|
||||
virtual Register asRegister(Context* c);
|
||||
|
||||
virtual void setLabelValue(Context*, MyPromise*);
|
||||
|
||||
virtual void apply(Context*, Operation);
|
||||
virtual void apply(Context* c, Operation, MyOperand*) { abort(c); }
|
||||
@ -313,6 +342,15 @@ class MemoryOperand: public MyOperand {
|
||||
|
||||
virtual Register asRegister(Context*);
|
||||
|
||||
virtual RegisterNode* dependencies(Context* c, RegisterNode* next) {
|
||||
next = base->dependencies(c, next);
|
||||
if (index) {
|
||||
return index->dependencies(c, next);
|
||||
} else {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(Context*, Operation);
|
||||
|
||||
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
|
||||
@ -404,6 +442,10 @@ class WrapperOperand: public MyOperand {
|
||||
return base->asRegister(c);
|
||||
}
|
||||
|
||||
virtual RegisterNode* dependencies(Context* c, RegisterNode* next) {
|
||||
return base->dependencies(c, next);
|
||||
}
|
||||
|
||||
virtual void apply(Context* c, Operation operation) {
|
||||
base->apply(c, operation);
|
||||
}
|
||||
@ -461,16 +503,6 @@ class WrapperOperand: public MyOperand {
|
||||
MyOperand* base;
|
||||
};
|
||||
|
||||
class StackOperand: public WrapperOperand {
|
||||
public:
|
||||
StackOperand(MyOperand* base, int index, StackOperand* next):
|
||||
WrapperOperand(base), index(index), next(next)
|
||||
{ }
|
||||
|
||||
int index;
|
||||
StackOperand* next;
|
||||
};
|
||||
|
||||
class TemporaryOperand: public WrapperOperand {
|
||||
public:
|
||||
TemporaryOperand(MyOperand* base):
|
||||
@ -497,7 +529,6 @@ class Context {
|
||||
zone(s, 8 * 1024),
|
||||
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
|
||||
segmentTable(0),
|
||||
stack(0),
|
||||
reserved(0),
|
||||
codeLength(-1)
|
||||
{
|
||||
@ -529,7 +560,6 @@ class Context {
|
||||
Zone zone;
|
||||
intptr_t indirectCaller;
|
||||
Segment** segmentTable;
|
||||
StackOperand* stack;
|
||||
unsigned reserved;
|
||||
int codeLength;
|
||||
RegisterOperand* registers[RegisterCount];
|
||||
@ -585,7 +615,7 @@ class PoolPromise: public MyPromise {
|
||||
|
||||
virtual intptr_t value(Context* c) {
|
||||
if (resolved(c)) {
|
||||
return c->codeLength + key;
|
||||
return reinterpret_cast<intptr_t>(c->code.data + c->codeLength + key);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
@ -600,17 +630,13 @@ class PoolPromise: public MyPromise {
|
||||
|
||||
class CodePromise: public MyPromise {
|
||||
public:
|
||||
CodePromise(bool absolute):
|
||||
offset(-1), absolute(absolute)
|
||||
CodePromise():
|
||||
offset(-1)
|
||||
{ }
|
||||
|
||||
virtual intptr_t value(Context* c) {
|
||||
if (resolved(c)) {
|
||||
if (absolute) {
|
||||
return reinterpret_cast<intptr_t>(c->code.data + offset);
|
||||
} else {
|
||||
return offset;
|
||||
}
|
||||
return reinterpret_cast<intptr_t>(c->code.data + offset);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
@ -621,13 +647,12 @@ class CodePromise: public MyPromise {
|
||||
}
|
||||
|
||||
intptr_t offset;
|
||||
bool absolute;
|
||||
};
|
||||
|
||||
class IpPromise: public MyPromise {
|
||||
public:
|
||||
IpPromise(intptr_t logicalIp, bool absolute):
|
||||
logicalIp(logicalIp), absolute(absolute)
|
||||
IpPromise(intptr_t logicalIp):
|
||||
logicalIp(logicalIp)
|
||||
{ }
|
||||
|
||||
virtual intptr_t value(Context* c) {
|
||||
@ -639,11 +664,7 @@ class IpPromise: public MyPromise {
|
||||
Segment* s = c->segmentTable[middle];
|
||||
|
||||
if (logicalIp == s->logicalIp) {
|
||||
if (absolute) {
|
||||
return reinterpret_cast<intptr_t>(c->code.data + s->offset);
|
||||
} else {
|
||||
return s->offset;
|
||||
}
|
||||
return reinterpret_cast<intptr_t>(c->code.data + s->offset);
|
||||
} else if (logicalIp < s->logicalIp) {
|
||||
top = middle;
|
||||
} else if (logicalIp > s->logicalIp) {
|
||||
@ -660,7 +681,6 @@ class IpPromise: public MyPromise {
|
||||
}
|
||||
|
||||
intptr_t logicalIp;
|
||||
bool absolute;
|
||||
};
|
||||
|
||||
AddressOperand*
|
||||
@ -837,6 +857,99 @@ class ReleaseEvent: public Event {
|
||||
MyOperand* operand;
|
||||
};
|
||||
|
||||
|
||||
class Movement {
|
||||
public:
|
||||
MyOperand* source;
|
||||
Register destination;
|
||||
RegisterNode* dependencies;
|
||||
};
|
||||
|
||||
void
|
||||
push(Context* c, Movement* table, unsigned size)
|
||||
{
|
||||
int pushed[size];
|
||||
unsigned pushIndex = 0;
|
||||
for (unsigned i = 0; i < size; ++i) {
|
||||
Movement* mi = table + i;
|
||||
for (unsigned j = i + 1; j < size; ++j) {
|
||||
Movement* mj = table + j;
|
||||
for (RegisterNode* d = mj->dependencies; d; d = d->next) {
|
||||
if (mi->destination == d->value) {
|
||||
mi->source->apply(c, MyOperand::push);
|
||||
pushed[pushIndex++] = i;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mi->source->apply(c, MyOperand::mov, register_(c, mi->destination));
|
||||
loop:;
|
||||
}
|
||||
|
||||
for (int i = pushIndex - 1; i >= 0; --i) {
|
||||
register_(c, table[pushed[i]].destination)->apply
|
||||
(c, MyOperand::pop);
|
||||
}
|
||||
}
|
||||
|
||||
Register
|
||||
gpRegister(Context* c, unsigned index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
return rdi;
|
||||
case 1:
|
||||
return rsi;
|
||||
case 2:
|
||||
return rdx;
|
||||
case 3:
|
||||
return rcx;
|
||||
case 4:
|
||||
return r8;
|
||||
case 5:
|
||||
return r9;
|
||||
default:
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
class ArgumentEvent: public Event {
|
||||
public:
|
||||
ArgumentEvent(MyOperand** arguments, unsigned count, Event* next):
|
||||
Event(next),
|
||||
arguments(arguments),
|
||||
count(count)
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c) {
|
||||
if (BytesPerWord == 8) {
|
||||
const unsigned size = min(count, GprParameterCount);
|
||||
Movement moveTable[size];
|
||||
|
||||
for (int i = count - 1; i >= 0; --i) {
|
||||
if (static_cast<unsigned>(i) < GprParameterCount) {
|
||||
Movement* m = moveTable + (size - i - 1);
|
||||
m->source = arguments[i];
|
||||
m->destination = gpRegister(c, i);
|
||||
m->dependencies = arguments[i]->dependencies(c, 0);
|
||||
} else {
|
||||
arguments[i]->apply(c, MyOperand::push);
|
||||
}
|
||||
}
|
||||
|
||||
push(c, moveTable, size);
|
||||
} else {
|
||||
for (int i = count - 1; i >= 0; --i) {
|
||||
arguments[i]->apply(c, MyOperand::push);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MyOperand** arguments;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
void
|
||||
appendOperation(Context* c, MyOperand::Operation operation)
|
||||
{
|
||||
@ -877,105 +990,88 @@ appendRelease(Context* c, Operand* operand)
|
||||
ReleaseEvent(operand, s->event);
|
||||
}
|
||||
|
||||
StackOperand*
|
||||
pushed(Context* c)
|
||||
void
|
||||
appendArgumentEvent(Context* c, MyOperand** arguments, unsigned count)
|
||||
{
|
||||
int index = (c->stack ?
|
||||
c->stack->index + (c->stack->footprint() / BytesPerWord) :
|
||||
0);
|
||||
|
||||
MyOperand* base = memory
|
||||
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1);
|
||||
|
||||
return c->stack = new (c->zone.allocate(sizeof(StackOperand)))
|
||||
StackOperand(base, index, c->stack);
|
||||
Segment* s = currentSegment(c);
|
||||
s->event = new (c->zone.allocate(sizeof(ArgumentEvent)))
|
||||
ArgumentEvent(arguments, count, s->event);
|
||||
}
|
||||
|
||||
void
|
||||
push(Context* c, int count)
|
||||
MyStack*
|
||||
pushed(Context* c, MyStack* stack)
|
||||
{
|
||||
int index = (stack ?
|
||||
stack->index + (stack->value->footprint() / BytesPerWord) :
|
||||
0);
|
||||
|
||||
MyOperand* value = memory
|
||||
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1);
|
||||
|
||||
return new (c->zone.allocate(sizeof(MyStack))) MyStack(value, index, stack);
|
||||
}
|
||||
|
||||
MyStack*
|
||||
push(Context* c, MyStack* stack, int count)
|
||||
{
|
||||
appendOperation
|
||||
(c, MyOperand::sub, immediate(c, count * BytesPerWord), register_(c, rsp));
|
||||
|
||||
while (count) {
|
||||
-- count;
|
||||
pushed(c);
|
||||
stack = pushed(c, stack);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
StackOperand*
|
||||
push(Context* c, MyOperand* v)
|
||||
MyStack*
|
||||
push(Context* c, MyStack* stack, MyOperand* v)
|
||||
{
|
||||
appendOperation(c, MyOperand::push, v);
|
||||
|
||||
return pushed(c);
|
||||
return pushed(c, stack);
|
||||
}
|
||||
|
||||
void
|
||||
pop(Context* c, int count)
|
||||
MyStack*
|
||||
pop(Context* c, MyStack* stack, int count)
|
||||
{
|
||||
appendOperation
|
||||
(c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp));
|
||||
|
||||
while (count) {
|
||||
count -= (c->stack->footprint() / BytesPerWord);
|
||||
count -= (stack->value->footprint() / BytesPerWord);
|
||||
assert(c, count >= 0);
|
||||
c->stack = c->stack->next;
|
||||
stack = stack->next;
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
void
|
||||
pop(Context* c, MyOperand* dst)
|
||||
MyStack*
|
||||
pop(Context* c, MyStack* stack, MyOperand* dst)
|
||||
{
|
||||
appendOperation(c, MyOperand::pop, dst);
|
||||
|
||||
c->stack = c->stack->next;
|
||||
}
|
||||
|
||||
Register
|
||||
gpRegister(Context* c, unsigned index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
return rdi;
|
||||
case 1:
|
||||
return rsi;
|
||||
case 2:
|
||||
return rdx;
|
||||
case 3:
|
||||
return rcx;
|
||||
case 4:
|
||||
return r8;
|
||||
case 5:
|
||||
return r9;
|
||||
default:
|
||||
abort(c);
|
||||
}
|
||||
return stack->next;
|
||||
}
|
||||
|
||||
unsigned
|
||||
pushArguments(Context* c, unsigned count, va_list list)
|
||||
{
|
||||
MyOperand* arguments[count];
|
||||
MyOperand** arguments = static_cast<MyOperand**>
|
||||
(c->zone.allocate(count * BytesPerWord));
|
||||
unsigned footprint = 0;
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
arguments[i] = va_arg(list, MyOperand*);
|
||||
footprint += pad(arguments[i]->footprint());
|
||||
}
|
||||
|
||||
const int GprCount = 6;
|
||||
for (int i = count - 1; i >= 0; --i) {
|
||||
if (BytesPerWord == 8 and i < GprCount) {
|
||||
appendOperation
|
||||
(c, MyOperand::mov, arguments[i], register_(c, gpRegister(c, i)));
|
||||
} else {
|
||||
appendOperation(c, MyOperand::push, arguments[i]);
|
||||
}
|
||||
}
|
||||
appendArgumentEvent(c, arguments, count);
|
||||
|
||||
if (BytesPerWord == 8) {
|
||||
if (footprint > GprCount * BytesPerWord) {
|
||||
return footprint - GprCount * BytesPerWord;
|
||||
if (footprint > GprParameterCount * BytesPerWord) {
|
||||
return footprint - GprParameterCount * BytesPerWord;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -1038,6 +1134,13 @@ encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex)
|
||||
encode(c, instruction, a, r, b->displacement, index, b->scale);
|
||||
}
|
||||
|
||||
RegisterNode*
|
||||
RegisterOperand::dependencies(Context* c, RegisterNode* next)
|
||||
{
|
||||
return new (c->zone.allocate(sizeof(RegisterNode)))
|
||||
RegisterNode(value, next);
|
||||
}
|
||||
|
||||
void
|
||||
RegisterOperand::apply(Context* c, Operation operation)
|
||||
{
|
||||
@ -1142,19 +1245,17 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
} break;
|
||||
|
||||
case and_: {
|
||||
if (operand->value) {
|
||||
rex(c);
|
||||
if (isInt8(operand->value)) {
|
||||
c->code.append(0x83);
|
||||
c->code.append(0xe0 | value);
|
||||
c->code.append(operand->value);
|
||||
} else {
|
||||
assert(c, isInt32(operand->value));
|
||||
rex(c);
|
||||
if (isInt8(operand->value)) {
|
||||
c->code.append(0x83);
|
||||
c->code.append(0xe0 | value);
|
||||
c->code.append(operand->value);
|
||||
} else {
|
||||
assert(c, isInt32(operand->value));
|
||||
|
||||
c->code.append(0x81);
|
||||
c->code.append(0xe0 | value);
|
||||
c->code.append(operand->value);
|
||||
}
|
||||
c->code.append(0x81);
|
||||
c->code.append(0xe0 | value);
|
||||
c->code.append(operand->value);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1173,6 +1274,22 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
c->code.appendAddress(operand->value);
|
||||
} break;
|
||||
|
||||
case shl: {
|
||||
if (operand->value) {
|
||||
rex(c);
|
||||
if (operand->value == 1) {
|
||||
c->code.append(0xd1);
|
||||
c->code.append(0xe0 | value);
|
||||
} else {
|
||||
assert(c, isInt8(operand->value));
|
||||
|
||||
c->code.append(0xc1);
|
||||
c->code.append(0xe0 | value);
|
||||
c->code.append(operand->value);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case sub: {
|
||||
if (operand->value) {
|
||||
assert(c, isInt8(operand->value)); // todo
|
||||
@ -1243,9 +1360,7 @@ ImmediateOperand*
|
||||
value(Context* c, AbsoluteOperand* operand)
|
||||
{
|
||||
if (c->codeLength >= 0) {
|
||||
return immediate
|
||||
(c, reinterpret_cast<intptr_t>
|
||||
(c->code.data + operand->promise->value(c)));
|
||||
return immediate(c, operand->promise->value(c));
|
||||
} else {
|
||||
return immediate(c, 0);
|
||||
}
|
||||
@ -1306,7 +1421,7 @@ conditional(Context* c, unsigned condition, AddressOperand* operand)
|
||||
}
|
||||
|
||||
void
|
||||
AddressOperand::setLabelValue(Context*, CodePromise* p)
|
||||
AddressOperand::setLabelValue(Context*, MyPromise* p)
|
||||
{
|
||||
promise = p;
|
||||
}
|
||||
@ -1358,6 +1473,22 @@ AddressOperand::apply(Context* c, Operation operation)
|
||||
}
|
||||
}
|
||||
|
||||
Register
|
||||
AddressOperand::asRegister(Context* c)
|
||||
{
|
||||
intptr_t v;
|
||||
if (c->codeLength >= 0) {
|
||||
v = promise->value(c);
|
||||
} else {
|
||||
v = 0;
|
||||
}
|
||||
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
tmp->accept(c, mov, immediate(c, v));
|
||||
tmp->release(c);
|
||||
return tmp->value;
|
||||
}
|
||||
|
||||
void
|
||||
ImmediateOperand::apply(Context* c, Operation operation)
|
||||
{
|
||||
@ -1436,6 +1567,10 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
encode(c, 0xff, 2, this, false);
|
||||
break;
|
||||
|
||||
case jmp:
|
||||
encode(c, 0xff, 4, this, false);
|
||||
break;
|
||||
|
||||
case neg:
|
||||
encode(c, 0xf7, 2, this, true);
|
||||
break;
|
||||
@ -1472,6 +1607,10 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
RegisterOperand* operand)
|
||||
{
|
||||
switch (operation) {
|
||||
case and_: {
|
||||
encode(c, 0x21, operand->value, this, true);
|
||||
} break;
|
||||
|
||||
case add: {
|
||||
encode(c, 0x01, operand->value, this, true);
|
||||
} break;
|
||||
@ -1656,14 +1795,8 @@ class MyCompiler: public Compiler {
|
||||
c(s, indirectCaller)
|
||||
{ }
|
||||
|
||||
virtual Promise* poolOffset() {
|
||||
return new (c.zone.allocate(sizeof(PoolPromise)))
|
||||
PoolPromise(c.constantPool.length());
|
||||
}
|
||||
|
||||
virtual Promise* codeOffset() {
|
||||
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise)))
|
||||
CodePromise(false);
|
||||
virtual Promise* machineIp() {
|
||||
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise))) CodePromise();
|
||||
|
||||
Segment* s = currentSegment(&c);
|
||||
s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
|
||||
@ -1672,64 +1805,77 @@ class MyCompiler: public Compiler {
|
||||
return p;
|
||||
}
|
||||
|
||||
virtual Operand* poolAppend(Operand* v) {
|
||||
Operand* r = absolute(&c, static_cast<MyPromise*>(poolOffset()));
|
||||
virtual Promise* machineIp(unsigned logicalIp) {
|
||||
return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(logicalIp);
|
||||
}
|
||||
|
||||
virtual Promise* poolAppend(intptr_t v) {
|
||||
return poolAppendPromise
|
||||
(new (c.zone.allocate(sizeof(ResolvedPromise))) ResolvedPromise(v));
|
||||
}
|
||||
|
||||
virtual Promise* poolAppendPromise(Promise* v) {
|
||||
Promise* p = new (c.zone.allocate(sizeof(PoolPromise)))
|
||||
PoolPromise(c.constantPool.length());
|
||||
c.constantPool.appendAddress(v);
|
||||
return r;
|
||||
return p;
|
||||
}
|
||||
|
||||
virtual Operand* constant(intptr_t v) {
|
||||
return immediate(&c, v);
|
||||
}
|
||||
|
||||
virtual void push(unsigned count) {
|
||||
::push(&c, count);
|
||||
virtual Operand* promiseConstant(Promise* p) {
|
||||
return address(&c, static_cast<MyPromise*>(p));
|
||||
}
|
||||
|
||||
virtual void push(Operand* v) {
|
||||
::push(&c, static_cast<MyOperand*>(v));
|
||||
virtual Operand* absolute(Promise* p) {
|
||||
return ::absolute(&c, static_cast<MyPromise*>(p));
|
||||
}
|
||||
|
||||
virtual void push2(Operand* v) {
|
||||
push(v);
|
||||
if (BytesPerWord == 8) push(immediate(&c, 0));
|
||||
virtual Stack* push(Stack* s, unsigned count) {
|
||||
return ::push(&c, static_cast<MyStack*>(s), count);
|
||||
}
|
||||
|
||||
virtual Operand* stack(unsigned index) {
|
||||
StackOperand* s = c.stack;
|
||||
unsigned i = 0;
|
||||
if (s->footprint() / BytesPerWord == 2) ++ i;
|
||||
|
||||
for (; i < index; ++i) {
|
||||
s = s->next;
|
||||
if (s->footprint() / BytesPerWord == 2) ++ i;
|
||||
}
|
||||
virtual Stack* push(Stack* s, Operand* v) {
|
||||
return ::push(&c, static_cast<MyStack*>(s), static_cast<MyOperand*>(v));
|
||||
}
|
||||
|
||||
virtual Stack* push2(Stack* s, Operand* v) {
|
||||
s = push(s, v);
|
||||
if (BytesPerWord == 8) s = push(s, immediate(&c, 0));
|
||||
return s;
|
||||
}
|
||||
|
||||
virtual void pop(unsigned count) {
|
||||
::pop(&c, count);
|
||||
virtual Operand* stack(Stack* s, unsigned index) {
|
||||
MyStack* stack = static_cast<MyStack*>(s);
|
||||
unsigned i = 0;
|
||||
|
||||
if (stack->value->footprint() / BytesPerWord == 2) {
|
||||
++ i;
|
||||
}
|
||||
|
||||
for (; i < index; ++i) {
|
||||
stack = stack->next;
|
||||
if (stack->value->footprint() / BytesPerWord == 2) {
|
||||
++ i;
|
||||
}
|
||||
}
|
||||
|
||||
return stack->value;
|
||||
}
|
||||
|
||||
virtual Operand* pop() {
|
||||
Operand* tmp = static_cast<MyOperand*>(temporary());
|
||||
pop(tmp);
|
||||
return tmp;
|
||||
virtual Stack* pop(Stack* s, unsigned count) {
|
||||
return ::pop(&c, static_cast<MyStack*>(s), count);
|
||||
}
|
||||
|
||||
virtual Operand* pop2() {
|
||||
if (BytesPerWord == 8) pop(1);
|
||||
return pop();
|
||||
virtual Stack* pop(Stack* s, Operand* dst) {
|
||||
return ::pop(&c, static_cast<MyStack*>(s), static_cast<MyOperand*>(dst));
|
||||
}
|
||||
|
||||
virtual void pop(Operand* dst) {
|
||||
::pop(&c, static_cast<MyOperand*>(dst));
|
||||
}
|
||||
|
||||
virtual void pop2(Operand* dst) {
|
||||
if (BytesPerWord == 8) pop(1);
|
||||
pop(dst);
|
||||
virtual Stack* pop2(Stack* s, Operand* dst) {
|
||||
if (BytesPerWord == 8) s = pop(s, 1);
|
||||
return pop(s, dst);
|
||||
}
|
||||
|
||||
virtual Operand* stack() {
|
||||
@ -1764,14 +1910,8 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual void mark(Operand* label) {
|
||||
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise)))
|
||||
CodePromise(true);
|
||||
|
||||
Segment* s = currentSegment(&c);
|
||||
s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
|
||||
CodePromiseTask(p, s->event->task);
|
||||
|
||||
static_cast<MyOperand*>(label)->setLabelValue(&c, p);
|
||||
static_cast<MyOperand*>(label)->setLabelValue
|
||||
(&c, static_cast<MyPromise*>(machineIp()));
|
||||
}
|
||||
|
||||
virtual Operand* indirectCall
|
||||
@ -1972,15 +2112,6 @@ class MyCompiler: public Compiler {
|
||||
Segment(ip, new (c.zone.allocate(sizeof(Event))) Event(0)));
|
||||
}
|
||||
|
||||
virtual Operand* logicalIp(unsigned ip) {
|
||||
return address
|
||||
(&c, new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, true));
|
||||
}
|
||||
|
||||
virtual Promise* logicalIpToOffset(unsigned ip) {
|
||||
return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, false);
|
||||
}
|
||||
|
||||
virtual unsigned codeSize() {
|
||||
if (c.codeLength < 0) {
|
||||
assert(&c, c.code.length() == 0);
|
||||
@ -1997,9 +2128,10 @@ class MyCompiler: public Compiler {
|
||||
c.code.wrap(out, codeSize());
|
||||
writeCode(&c);
|
||||
|
||||
memcpy(out + codeSize(),
|
||||
c.constantPool.data,
|
||||
c.constantPool.length());
|
||||
for (unsigned i = 0; i < c.constantPool.length(); i += BytesPerWord) {
|
||||
Promise* p; c.constantPool.get(i, &p, BytesPerWord);
|
||||
*reinterpret_cast<intptr_t*>(out + codeSize() + i) = p->value(this);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void updateCall(void* returnAddress, void* newTarget) {
|
||||
|
@ -7,6 +7,8 @@ namespace vm {
|
||||
|
||||
class Operand { };
|
||||
|
||||
class Stack { };
|
||||
|
||||
class Compiler;
|
||||
|
||||
class Promise {
|
||||
@ -20,20 +22,29 @@ class Compiler {
|
||||
public:
|
||||
virtual ~Compiler() { }
|
||||
|
||||
virtual Promise* poolOffset() = 0;
|
||||
virtual Promise* codeOffset() = 0;
|
||||
virtual Promise* logicalIpToOffset(unsigned) = 0;
|
||||
virtual Promise* machineIp() = 0;
|
||||
virtual Promise* machineIp(unsigned logicalIp) = 0;
|
||||
|
||||
virtual Operand* poolAppend(Operand*) = 0;
|
||||
virtual Promise* poolAppend(intptr_t) = 0;
|
||||
virtual Promise* poolAppendPromise(Promise*) = 0;
|
||||
|
||||
virtual Operand* constant(intptr_t) = 0;
|
||||
virtual Operand* promiseConstant(Promise*) = 0;
|
||||
virtual Operand* absolute(Promise*) = 0;
|
||||
virtual Operand* memory(Operand* base, int displacement = 0,
|
||||
Operand* index = 0, unsigned scale = 1) = 0;
|
||||
|
||||
virtual Operand* select1(Operand*) = 0;
|
||||
virtual Operand* select2(Operand*) = 0;
|
||||
virtual Operand* select2z(Operand*) = 0;
|
||||
virtual Operand* select4(Operand*) = 0;
|
||||
virtual Operand* select8(Operand*) = 0;
|
||||
|
||||
virtual Operand* stack() = 0;
|
||||
virtual Operand* base() = 0;
|
||||
virtual Operand* thread() = 0;
|
||||
virtual Operand* indirectTarget() = 0;
|
||||
virtual Operand* temporary() = 0;
|
||||
virtual Operand* stack(unsigned) = 0;
|
||||
virtual void release(Operand*) = 0;
|
||||
|
||||
virtual Operand* label() = 0;
|
||||
@ -46,19 +57,19 @@ class Compiler {
|
||||
virtual Operand* directCall
|
||||
(Operand* address, unsigned argumentCount, ...) = 0;
|
||||
|
||||
virtual Operand* call(Operand*) = 0;
|
||||
virtual Operand* alignedCall(Operand*) = 0;
|
||||
virtual void return_(Operand*) = 0;
|
||||
virtual void ret() = 0;
|
||||
|
||||
virtual void push(unsigned count) = 0;
|
||||
virtual void push(Operand*) = 0;
|
||||
virtual void push2(Operand*) = 0;
|
||||
virtual void pop(unsigned count) = 0;
|
||||
virtual Operand* pop() = 0;
|
||||
virtual Operand* pop2() = 0;
|
||||
virtual void pop(Operand*) = 0;
|
||||
virtual void pop2(Operand*) = 0;
|
||||
virtual Operand* call(Operand*) = 0;
|
||||
virtual Operand* alignedCall(Operand*) = 0;
|
||||
virtual Stack* push(Stack*, unsigned count) = 0;
|
||||
virtual Stack* push(Stack*, Operand*) = 0;
|
||||
virtual Stack* push2(Stack*, Operand*) = 0;
|
||||
virtual Stack* pop(Stack*, unsigned count) = 0;
|
||||
virtual Stack* pop(Stack*, Operand*) = 0;
|
||||
virtual Stack* pop2(Stack*, Operand*) = 0;
|
||||
virtual Operand* stack(Stack*, unsigned) = 0;
|
||||
|
||||
virtual void mov(Operand* src, Operand* dst) = 0;
|
||||
virtual void cmp(Operand* subtrahend, Operand* minuend) = 0;
|
||||
virtual void jl(Operand*) = 0;
|
||||
@ -81,21 +92,11 @@ class Compiler {
|
||||
virtual void xor_(Operand* v, Operand* dst) = 0;
|
||||
virtual void neg(Operand*) = 0;
|
||||
|
||||
virtual Operand* memory(Operand* base, int displacement = 0,
|
||||
Operand* index = 0, unsigned scale = 1) = 0;
|
||||
|
||||
virtual Operand* select1(Operand*) = 0;
|
||||
virtual Operand* select2(Operand*) = 0;
|
||||
virtual Operand* select2z(Operand*) = 0;
|
||||
virtual Operand* select4(Operand*) = 0;
|
||||
virtual Operand* select8(Operand*) = 0;
|
||||
|
||||
virtual void prologue() = 0;
|
||||
virtual void reserve(unsigned size) = 0;
|
||||
virtual void epilogue() = 0;
|
||||
|
||||
virtual void startLogicalIp(unsigned) = 0;
|
||||
virtual Operand* logicalIp(unsigned) = 0;
|
||||
|
||||
virtual unsigned codeSize() = 0;
|
||||
virtual unsigned poolSize() = 0;
|
||||
|
@ -1,6 +1,7 @@
|
||||
public class Misc {
|
||||
private static int alpha;
|
||||
private static int beta;
|
||||
private int gamma;
|
||||
|
||||
private String foo(String s) {
|
||||
return s;
|
||||
@ -13,11 +14,15 @@ public class Misc {
|
||||
private static String baz(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
private static void expect(boolean v) {
|
||||
if (! v) throw new RuntimeException();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
boolean v = Boolean.valueOf("true");
|
||||
|
||||
// ClassLoader.getSystemClassLoader().toString();
|
||||
ClassLoader.getSystemClassLoader().toString();
|
||||
|
||||
int a = 2;
|
||||
int b = 2;
|
||||
@ -29,10 +34,15 @@ public class Misc {
|
||||
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;
|
||||
m.gamma = 44;
|
||||
|
||||
expect(beta == 42);
|
||||
expect(alpha == 43);
|
||||
expect(m.gamma == 44);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user