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