32-bit JIT bugfixes; still broken

This commit is contained in:
Joel Dice 2007-12-19 18:42:12 -07:00
parent fc6beb852b
commit be42c325d8
4 changed files with 178 additions and 59 deletions

View File

@ -28,7 +28,7 @@ src = src
classpath = classpath classpath = classpath
test = test test = test
input = $(test-build)/Enums.class input = $(test-build)/Exceptions.class
build-cxx = g++ build-cxx = g++
build-cc = gcc build-cc = gcc

View File

@ -19,7 +19,7 @@ vmInvoke:
// %r8 : returnType // %r8 : returnType
mov %rdi,%rbx mov %rdi,%rbx
// copy memory arguments into place // copy memory arguments into place
pushq %rcx pushq %rcx
movq $0,%r9 movq $0,%r9
@ -37,7 +37,11 @@ test:
call *%rsi call *%rsi
// pop arguments // pop arguments
addq -16(%rbp),%rsp mov -16(%rbp),%rcx
sal $3,%rcx
addq %rcx,%rsp
// pop argument stack size
addq $8,%rsp addq $8,%rsp
popq %rbx popq %rbx
@ -77,7 +81,7 @@ vmInvoke:
jmp test jmp test
loop: loop:
push (%rdx,%rcx,4) push (%edx,%ecx,4)
inc %ecx inc %ecx
test: test:
@ -88,7 +92,9 @@ test:
call *12(%ebp) call *12(%ebp)
// pop arguments // pop arguments
addl 20(%ebp),%esp mov 20(%ebp),%ecx
sal $2,%ecx
addl %ecx,%esp
// handle return value based on expected type // handle return value based on expected type
movl 24(%ebp),%ecx movl 24(%ebp),%ecx
@ -118,8 +124,8 @@ exit:
vmJump: vmJump:
movl 4(%esp),%eax movl 4(%esp),%eax
movl 8(%esp),%ebp movl 8(%esp),%ebp
movl 12(%esp),%esp
movl 16(%esp),%ebx movl 16(%esp),%ebx
movl 12(%esp),%esp
jmp *%eax jmp *%eax
#else #else

View File

@ -18,7 +18,7 @@ vmJump(void* address, void* base, void* stack, void* thread);
namespace { namespace {
const bool Verbose = false; const bool Verbose = true;
const bool DebugTraces = false; const bool DebugTraces = false;
class MyThread: public Thread { class MyThread: public Thread {
@ -660,7 +660,7 @@ class Frame {
} }
Operand* popLong() { Operand* popLong() {
Operand* tmp = c->temporary(); Operand* tmp = c->select8(c->temporary());
popLong(tmp); popLong(tmp);
return tmp; return tmp;
} }
@ -3000,10 +3000,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/reflect/Method") == 0 and "java/lang/Throwable") == 0 and
strcmp(reinterpret_cast<const char*> strcmp(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, method), 0)), (&byteArrayBody(t, methodName(t, method), 0)),
"invoke") == 0) "init") == 0)
{ {
asm("int3"); asm("int3");
} }

View File

@ -305,7 +305,8 @@ RegisterOperand*
register_(Context* c, RegisterReference*, SelectionType = DefaultSelection); register_(Context* c, RegisterReference*, SelectionType = DefaultSelection);
RegisterOperand* RegisterOperand*
register_(Context* c, Register, SelectionType = DefaultSelection); register_(Context* c, Register, Register = NoRegister,
SelectionType = DefaultSelection);
MemoryOperand* MemoryOperand*
memory(Context* c, MyOperand* base, int displacement, memory(Context* c, MyOperand* base, int displacement,
@ -410,14 +411,15 @@ release(Context* c, Register v)
class RegisterReference { class RegisterReference {
public: public:
RegisterReference(Register v = NoRegister): value_(v), high_(NoRegister) { } RegisterReference(Register value = NoRegister, Register high = NoRegister):
value_(value), high_(high), acquireHigh(false)
{ }
void acquireValue(Context* c) { void acquire(Context* c) {
value_ = ::acquire(c); value_ = ::acquire(c);
} if (acquireHigh) {
high_ = ::acquire(c);
void acquireHigh(Context* c) { }
high_ = ::acquire(c);
} }
void release(Context* c) { void release(Context* c) {
@ -441,6 +443,7 @@ class RegisterReference {
Register value_; Register value_;
Register high_; Register high_;
bool acquireHigh;
}; };
class RegisterOperand: public MyOperand { class RegisterOperand: public MyOperand {
@ -469,10 +472,8 @@ class RegisterOperand: public MyOperand {
if (selection == this->selection) { if (selection == this->selection) {
return this; return this;
} else { } else {
if (selection == S8Selection and BytesPerWord == 4 if (selection == S8Selection and BytesPerWord == 4) {
and reference->high_ == NoRegister) reference->acquireHigh = true;
{
reference->acquireHigh(c);
} }
return register_(c, reference, selection); return register_(c, reference, selection);
} }
@ -656,10 +657,10 @@ register_(Context* c, RegisterReference* r, SelectionType selection)
} }
RegisterOperand* RegisterOperand*
register_(Context* c, Register v, SelectionType selection) register_(Context* c, Register v, Register h, SelectionType selection)
{ {
RegisterReference* r = new (c->zone.allocate(sizeof(RegisterReference))) RegisterReference* r = new (c->zone.allocate(sizeof(RegisterReference)))
RegisterReference(v); RegisterReference(v, h);
return register_(c, r, selection); return register_(c, r, selection);
} }
@ -677,6 +678,16 @@ temporary(Context* c)
return register_(c, acquire(c)); return register_(c, acquire(c));
} }
RegisterOperand*
temporary(Context* c, SelectionType selection)
{
if (BytesPerWord == 4 and selection == S8Selection) {
return register_(c, acquire(c), acquire(c), selection);
} else {
return register_(c, acquire(c), NoRegister, selection);
}
}
RegisterOperand* RegisterOperand*
temporary(Context* c, Register v) temporary(Context* c, Register v)
{ {
@ -765,7 +776,7 @@ class AcquireEvent: public Event {
{ } { }
virtual void run(Context* c) { virtual void run(Context* c) {
operand->reference->acquireValue(c); operand->reference->acquire(c);
} }
RegisterOperand* operand; RegisterOperand* operand;
@ -1064,7 +1075,9 @@ encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex)
void void
RegisterOperand::apply(Context* c, Operation operation) RegisterOperand::apply(Context* c, Operation operation)
{ {
assert(c, selection == DefaultSelection); assert(c, operation == push
or operation == pop
or selection == DefaultSelection);
switch (operation) { switch (operation) {
case call: case call:
@ -1078,11 +1091,43 @@ RegisterOperand::apply(Context* c, Operation operation)
break; break;
case pop: case pop:
c->code.append(0x58 | value(c)); if (selection == DefaultSelection) {
c->code.append(0x58 | value(c));
} else {
switch (selection) {
case S8Selection:
assert(c, selection == S8Selection);
register_(c, high(c))->apply(c, pop);
register_(c, value(c))->apply(c, pop);
break;
default: abort(c);
}
}
break; break;
case push: case push:
c->code.append(0x50 | value(c)); if (selection == DefaultSelection) {
c->code.append(0x50 | value(c));
} else {
switch (selection) {
case S8Selection:
assert(c, selection == S8Selection);
register_(c, value(c))->apply(c, push);
register_(c, high(c))->apply(c, push);
break;
default: abort(c);
}
}
break;
case neg:
rex(c);
c->code.append(0xf7);
c->code.append(0xd8 | value(c));
break; break;
default: abort(c); default: abort(c);
@ -1093,9 +1138,6 @@ void
RegisterOperand::accept(Context* c, Operation operation, RegisterOperand::accept(Context* c, Operation operation,
RegisterOperand* operand) RegisterOperand* operand)
{ {
assert(c, selection == DefaultSelection);
assert(c, operation == mov or operand->selection == DefaultSelection);
switch (operation) { switch (operation) {
case add: case add:
rex(c); rex(c);
@ -1104,9 +1146,25 @@ RegisterOperand::accept(Context* c, Operation operation,
break; break;
case cmp: case cmp:
rex(c); if (selection == DefaultSelection) {
c->code.append(0x39); rex(c);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0x39);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
} else {
assert(c, selection == S8Selection);
register_(c, high(c))->accept
(c, mov, register_(c, operand->high(c)));
// if the high order bits are equal, we compare the low order
// bits; otherwise, we jump past that comparison
c->code.append(0x0f);
c->code.append(0x85); // jne
c->code.append4(2);
register_(c, value(c))->accept
(c, mov, register_(c, operand->value(c)));
}
break; break;
case mov: case mov:
@ -1119,24 +1177,36 @@ RegisterOperand::accept(Context* c, Operation operation,
switch (operand->selection) { switch (operand->selection) {
case S1Selection: case S1Selection:
c->code.append(0xbe); c->code.append(0xbe);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case S2Selection: case S2Selection:
c->code.append(0xbf); c->code.append(0xbf);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case Z2Selection: case Z2Selection:
c->code.append(0xb7); c->code.append(0xb7);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case S4Selection: case S4Selection:
c->code.append(0x89); c->code.append(0x89);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break;
case S8Selection:
assert(c, selection == S8Selection);
register_(c, value(c))->accept
(c, mov, register_(c, operand->value(c)));
register_(c, high(c))->accept
(c, mov, register_(c, operand->high(c)));
break; break;
default: abort(c); default: abort(c);
} }
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
} }
} }
break; break;
@ -1272,7 +1342,7 @@ void
RegisterOperand::accept(Context* c, Operation operation, RegisterOperand::accept(Context* c, Operation operation,
MemoryOperand* operand) MemoryOperand* operand)
{ {
assert(c, selection == DefaultSelection); assert(c, operation == mov or selection == DefaultSelection);
assert(c, operation == mov or operand->selection == DefaultSelection); assert(c, operation == mov or operand->selection == DefaultSelection);
switch (operation) { switch (operation) {
@ -1540,8 +1610,6 @@ MemoryOperand::asRegister(Context* c)
void void
MemoryOperand::apply(Context* c, Operation operation) MemoryOperand::apply(Context* c, Operation operation)
{ {
assert(c, operation == push or selection == DefaultSelection);
switch (operation) { switch (operation) {
case call: case call:
encode(c, 0xff, 2, this, false); encode(c, 0xff, 2, this, false);
@ -1552,7 +1620,36 @@ MemoryOperand::apply(Context* c, Operation operation)
break; break;
case neg: case neg:
encode(c, 0xf7, 2, this, true); if (selection == DefaultSelection) {
encode(c, 0xf7, 2, this, true);
} else {
assert(c, selection == S8Selection);
RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx);
MemoryOperand* low = memory(c, base, displacement, index, scale);
MemoryOperand* high = memory
(c, base, displacement + BytesPerWord, index, scale);
ax->accept(c, mov, low);
dx->accept(c, mov, high);
ax->apply(c, neg);
// adc 0,%rdx
c->code.append(0x83);
c->code.append(0xd0 | rdx);
c->code.append(0);
dx->apply(c, neg);
low->accept(c, mov, ax);
high->accept(c, mov, dx);
ax->release(c);
dx->release(c);
}
break; break;
case pop: case pop:
@ -1563,7 +1660,8 @@ MemoryOperand::apply(Context* c, Operation operation)
if (selection == DefaultSelection) { if (selection == DefaultSelection) {
encode(c, 0xff, 6, this, false); encode(c, 0xff, 6, this, false);
} else { } else {
RegisterOperand* tmp = temporary(c); RegisterOperand* tmp = temporary
(c, selection == S8Selection ? S8Selection : DefaultSelection);
tmp->accept(c, mov, this); tmp->accept(c, mov, this);
tmp->apply(c, operation); tmp->apply(c, operation);
tmp->release(c); tmp->release(c);
@ -1578,9 +1676,6 @@ void
MemoryOperand::accept(Context* c, Operation operation, MemoryOperand::accept(Context* c, Operation operation,
RegisterOperand* operand) RegisterOperand* operand)
{ {
assert(c, operation == mov or selection == DefaultSelection);
assert(c, operand->selection == DefaultSelection);
switch (operation) { switch (operation) {
case and_: { case and_: {
encode(c, 0x21, operand->value(c), this, true); encode(c, 0x21, operand->value(c), this, true);
@ -1591,20 +1686,24 @@ MemoryOperand::accept(Context* c, Operation operation,
} break; } break;
case div: { case div: {
RegisterOperand* ax = temporary(c, rax); if (selection == DefaultSelection) {
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* ax = temporary(c, rax);
ax->accept(c, mov, this); RegisterOperand* dx = temporary(c, rdx);
ax->accept(c, mov, this);
rex(c); rex(c);
c->code.append(0x99); c->code.append(0x99);
rex(c); rex(c);
c->code.append(0xf7); c->code.append(0xf7);
c->code.append(0xf8 | operand->value(c)); c->code.append(0xf8 | operand->value(c));
accept(c, mov, ax); accept(c, mov, ax);
ax->release(c); ax->release(c);
dx->release(c); dx->release(c);
} else {
abort(c);
}
} break; } break;
case mov: { case mov: {
@ -1629,19 +1728,33 @@ MemoryOperand::accept(Context* c, Operation operation,
encode(c, 0x89, operand->value(c), this, false); encode(c, 0x89, operand->value(c), this, false);
break; break;
case S8Selection:
assert(c, operand->selection == S8Selection);
memory(c, base, displacement, index, scale)->accept
(c, mov, register_(c, operand->value(c)));
memory(c, base, displacement + BytesPerWord, index, scale)->accept
(c, mov, register_(c, operand->high(c)));
break;
default: abort(c); default: abort(c);
} }
} }
} break; } break;
case mul: { case mul: {
RegisterOperand* tmp = temporary(c); if (selection == DefaultSelection) {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, this); tmp->accept(c, mov, this);
tmp->accept(c, mul, operand); tmp->accept(c, mul, operand);
accept(c, mov, tmp); accept(c, mov, tmp);
tmp->release(c); tmp->release(c);
} else {
abort(c);
}
} break; } break;
case or_: { case or_: {