lots of JIT bugfixes and cleanups

This commit is contained in:
Joel Dice 2007-12-15 17:24:15 -07:00
parent 924a588cdf
commit 796a64a426
6 changed files with 480 additions and 307 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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:

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}
}