various bugfixes; majority of tests now pass

This commit is contained in:
Joel Dice 2008-04-27 14:15:18 -06:00
parent d5137a7cdf
commit 5b7372a3bb
4 changed files with 176 additions and 55 deletions

View File

@ -136,6 +136,9 @@ class Assembler {
virtual int acquireTemporary(int r = NoRegister) = 0;
virtual void releaseTemporary(int r) = 0;
virtual void save(int r) = 0;
virtual void restore(int r) = 0;
};
virtual ~Assembler() { }

View File

@ -3828,11 +3828,11 @@ finish(MyThread* t, Context* context)
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"java/lang/StringBuilder") == 0 and
"java/lang/Class") == 0 and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)),
"<init>") == 0)
"replace") == 0)
{
asm("int3");
}

View File

@ -15,10 +15,10 @@ using namespace vm;
namespace {
const bool DebugAppend = true;
const bool DebugCompile = true;
const bool DebugStack = true;
const bool DebugRegisters = true;
const bool DebugAppend = false;
const bool DebugCompile = false;
const bool DebugStack = false;
const bool DebugRegisters = false;
class Context;
class Value;
@ -101,6 +101,7 @@ class Register {
unsigned size;
unsigned refCount;
bool reserved;
bool pushed;
};
class ConstantPoolNode {
@ -826,6 +827,42 @@ pushNow(Context* c, Stack* start)
pushNow(c, start, count);
}
bool
trySteal(Context* c, int r, Stack* stack)
{
Value* v = c->registers[r].value;
assert(c, c->registers[r].refCount == 0);
if (DebugRegisters) {
fprintf(stderr, "try steal %d from %p: next: %p\n",
r, v, v->sites->next);
}
if (v->sites->next == 0) {
unsigned count = 0;
Stack* start = 0;
for (Stack* s = stack; s and (not s->pushed); s = s->next) {
if (s->value == v) {
start = s;
}
if (start) {
++ count;
}
}
if (start) {
pushNow(c, start, count);
} else {
return false;
}
}
removeSite(c, v, c->registers[r].site);
return true;
}
bool
tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue,
Site* newSite)
@ -842,33 +879,9 @@ tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue,
and oldValue != newValue
and findSite(c, oldValue, c->registers[r].site))
{
assert(c, c->registers[r].refCount == 0);
if (DebugRegisters) {
fprintf(stderr, "try steal %d from %p: next: %p\n",
r, oldValue, oldValue->sites->next);
if (not trySteal(c, r, stack)) {
return false;
}
if (oldValue->sites->next == 0) {
unsigned count = 0;
Stack* start = 0;
for (Stack* s = stack; s and (not s->pushed); s = s->next) {
if (s->value == oldValue) {
start = s;
}
if (start) {
++ count;
}
}
if (start) {
pushNow(c, start, count);
} else {
return false;
}
}
removeSite(c, oldValue, c->registers[r].site);
}
c->registers[r].size = newSize;
@ -1182,15 +1195,15 @@ class MoveEvent: public Event {
nextRead(c, src);
if (cost) {
apply(c, type, size, src->source, target);
}
if (dst->reads) {
addSite(c, stack, size, dst, target);
} else {
removeSite(c, dst, target);
}
if (cost) {
apply(c, type, size, src->source, target);
}
}
BinaryOperation type;
@ -1730,7 +1743,7 @@ compile(Context* c)
for (Event* e = li->firstEvent; e; e = e->next) {
if (e->stackReset) {
fprintf(stderr, "stack reset\n");
// fprintf(stderr, "stack reset\n");
for (Stack* s = e->stack; s; s = s->next) {
if (s->value->sites) {
assert(c, s->value->sites->next == 0);
@ -1863,16 +1876,16 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired)
}
}
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (i != except
and c->registers[i].refCount == 0
and (not usedExclusively(c, i)))
{
return i;
}
}
if (allowAcquired) {
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (i != except
and c->registers[i].refCount == 0
and (not usedExclusively(c, i)))
{
return i;
}
}
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if (i != except
and c->registers[i].refCount == 0)
@ -1924,8 +1937,9 @@ class Client: public Assembler::Client {
if (r == NoRegister) {
r = freeRegisterExcept(c, NoRegister, false);
} else {
expect(c, c->registers[r].refCount == 0);
expect(c, c->registers[r].value == 0);
expect(c, (c->registers[r].refCount == 0
and c->registers[r].value == 0)
or c->registers[r].pushed);
}
increment(c, r);
return r;
@ -1935,6 +1949,22 @@ class Client: public Assembler::Client {
decrement(c, r);
}
virtual void save(int r) {
if (c->registers[r].refCount or c->registers[r].value) {
Assembler::Register operand(r);
c->assembler->apply(Push, BytesPerWord, RegisterOperand, &operand);
c->registers[r].pushed = true;
}
}
virtual void restore(int r) {
if (c->registers[r].pushed) {
Assembler::Register operand(r);
c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &operand);
c->registers[r].pushed = false;
}
}
Context* c;
};
@ -2092,7 +2122,10 @@ class MyCompiler: public Compiler {
}
virtual void push(unsigned size) {
::push(&c, size, value(&c));
assert(&c, ceiling(size, BytesPerWord));
c.state->stack = ::stack
(&c, value(&c), ceiling(size, BytesPerWord), c.state->stack);
}
virtual void push(unsigned size, Operand* value) {

View File

@ -598,6 +598,7 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
} else {
switch (size) {
case 1:
rex(c);
if (BytesPerWord == 8) {
c->code.append(0x0f);
}
@ -606,6 +607,7 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
break;
case 2:
rex(c);
if (BytesPerWord == 8) {
c->code.append(0x0f);
}
@ -675,7 +677,7 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a,
if (BytesPerWord == 8) {
rex(c);
c->code.append(0x63);
c->code.append(0xc0 | (a->low << 3) | b->low);
c->code.append(0xc0 | (b->low << 3) | a->low);
} else {
if (a->low == rax and b->low == rax and b->high == rdx) {
c->code.append(0x99); // cdq
@ -897,6 +899,8 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
abort(c); // todo: sync stack first
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
@ -918,10 +922,18 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
c->client->releaseTemporary(axdx.high);
} else {
Assembler::Register ax(rax);
Assembler::Register dx(c->client->acquireTemporary(rdx));
Assembler::Register divisor(a->low);
if (a->low == rdx) {
divisor.low = c->client->acquireTemporary();
moveRR(c, BytesPerWord, a, &divisor);
} else if (b->low != rdx) {
c->client->save(rdx);
}
if (b->low != rax) {
c->client->acquireTemporary(ax.low);
c->client->save(rax);
c->client->acquireTemporary(rax);
moveRR(c, BytesPerWord, b, &ax);
}
@ -929,14 +941,85 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | a->low);
c->code.append(0xf8 | divisor.low);
if (b->low != rax) {
moveRR(c, BytesPerWord, &ax, b);
c->client->releaseTemporary(ax.low);
c->client->releaseTemporary(rax);
c->client->restore(rax);
}
c->client->releaseTemporary(dx.low);
if (a->low == rdx) {
moveRR(c, BytesPerWord, &divisor, a);
c->client->releaseTemporary(divisor.low);
} else if (b->low != rdx) {
c->client->restore(rdx);
}
}
}
void
remainderRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
abort(c); // todo: sync stack first
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
pushR(c, size, a);
pushR(c, size, b);
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(moduloLong));
Assembler::Constant address(&addressPromise);
callC(c, BytesPerWord, &address);
ResolvedPromise offsetPromise(16);
Assembler::Constant offset(&offsetPromise);
Assembler::Register stack(rsp);
addCR(c, BytesPerWord, &offset, &stack);
moveRR(c, size, &axdx, b);
c->client->releaseTemporary(axdx.low);
c->client->releaseTemporary(axdx.high);
} else {
Assembler::Register ax(rax);
Assembler::Register dx(rdx);
Assembler::Register divisor(a->low);
if (a->low == rdx) {
divisor.low = c->client->acquireTemporary();
moveRR(c, BytesPerWord, a, &divisor);
} else if (b->low != rdx) {
c->client->save(rdx);
}
if (b->low != rax) {
c->client->save(rax);
c->client->acquireTemporary(rax);
moveRR(c, BytesPerWord, b, &ax);
}
rex(c);
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | divisor.low);
if (b->low != rdx) {
moveRR(c, BytesPerWord, &dx, b);
c->client->releaseTemporary(rax);
c->client->restore(rax);
}
if (a->low == rdx) {
moveRR(c, BytesPerWord, &divisor, a);
c->client->releaseTemporary(divisor.low);
} else if (b->low != rdx) {
c->client->restore(rdx);
}
}
}
@ -1167,6 +1250,8 @@ populateTables()
BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR);
BinaryOperations[INDEX2(Remainder, Register, Register)] = CAST2(remainderRR);
BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR);
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);