implement additional instructions for JIT; fix bug in dispose(Thread*,Reference*)

This commit is contained in:
Joel Dice 2007-10-08 15:41:41 -06:00
parent e32a335079
commit c7d7c4ca0a
2 changed files with 339 additions and 63 deletions

View File

@ -353,6 +353,18 @@ throw_(MyThread* t, object o)
unwind(t); unwind(t);
} }
int64_t
divideLong(MyThread*, int64_t a, int64_t b)
{
return a / b;
}
int64_t
moduloLong(MyThread*, int64_t a, int64_t b)
{
return a % b;
}
object object
makeBlankObjectArray(Thread* t, object class_, int32_t length) makeBlankObjectArray(Thread* t, object class_, int32_t length)
{ {
@ -800,6 +812,25 @@ class Assembler {
} }
} }
void adc(int32_t v, Register dst) {
assert(code.s, isByte(v)); // todo
rex();
code.append(0x83);
code.append(0xd0 | dst);
code.append(v);
}
void adc(Register src, Register dst, unsigned dstOffset) {
rex();
offsetInstruction(0x11, 0, 0x40, 0x80, src, dst, dstOffset);
}
void sub(Register src, Register dst, unsigned dstOffset) {
rex();
offsetInstruction(0x29, 0, 0x40, 0x80, src, dst, dstOffset);
}
void sub(Register src, Register dst) { void sub(Register src, Register dst) {
rex(); rex();
code.append(0x29); code.append(0x29);
@ -815,6 +846,11 @@ class Assembler {
code.append(v); code.append(v);
} }
void sbb(Register src, Register dst, unsigned dstOffset) {
rex();
offsetInstruction(0x19, 0, 0x40, 0x80, src, dst, dstOffset);
}
void or_(Register src, Register dst) { void or_(Register src, Register dst) {
rex(); rex();
code.append(0x09); code.append(0x09);
@ -944,6 +980,14 @@ class Assembler {
conditional(javaIP, 0x8e); conditional(javaIP, 0x8e);
} }
void jb(Label& label) {
conditional(label, 0x82);
}
void ja(Label& label) {
conditional(label, 0x87);
}
void cmp(int v, Register reg) { void cmp(int v, Register reg) {
assert(code.s, isByte(v)); // todo assert(code.s, isByte(v)); // todo
@ -962,6 +1006,48 @@ class Assembler {
code.append(0xd0 | reg); code.append(0xd0 | reg);
} }
void cdq() {
code.append(0x99);
}
void imul4(Register src, unsigned srcOffset, Register dst) {
code.append(0x0f);
offsetInstruction(0xaf, 0, 0x40, 0x80, dst, src, srcOffset);
}
void imul(Register src, unsigned srcOffset, Register dst) {
rex();
imul4(src, srcOffset, dst);
}
void imul(Register src) {
rex();
code.append(0xf7);
code.append(0xe8 | src);
}
void idiv(Register src) {
rex();
code.append(0xf7);
code.append(0xf8 | src);
}
void mul(Register src, unsigned offset) {
rex();
offsetInstruction(0xf7, 0x20, 0x60, 0xa0, rax, src, offset);
}
void neg(Register reg, unsigned offset) {
rex();
offsetInstruction(0xf7, 0x10, 0x50, 0x90, rax, reg, offset);
}
void neg(Register reg) {
rex();
code.append(0xf7);
code.append(0xd8 | reg);
}
Buffer code; Buffer code;
Buffer jumps; Buffer jumps;
}; };
@ -1028,6 +1114,54 @@ class Compiler: public Assembler {
pool(t->m->system, 256) pool(t->m->system, 256)
{ } { }
void pushLong(uint64_t v) {
if (BytesPerWord == 8) {
pushAddress(v);
sub(8, rsp);
} else {
push((v >> 32) & 0xFFFFFFFF);
push((v ) & 0xFFFFFFFF);
}
}
void pushLong(Register low, Register high) {
assert(t, BytesPerWord == 4);
push(high);
push(low);
}
void popLong(Register r) {
assert(t, BytesPerWord == 8);
add(8, rsp);
pop(r);
}
void popLong(Register low, Register high) {
assert(t, BytesPerWord == 4);
pop(low);
pop(high);
}
void loadLong(uint64_t index, unsigned parameterFootprint) {
if (BytesPerWord == 8) {
push(rbp, localOffset(index, parameterFootprint));
sub(8, rsp);
} else {
push(rbp, localOffset(index + 1, parameterFootprint));
push(rbp, localOffset(index, parameterFootprint));
}
}
void storeLong(uint64_t index, unsigned parameterFootprint) {
if (BytesPerWord == 8) {
add(8, rsp);
pop(rbp, localOffset(index, parameterFootprint));
} else {
pop(rbp, localOffset(index, parameterFootprint));
pop(rbp, localOffset(index + 1, parameterFootprint));
}
}
void pushReturnValue(unsigned code) { void pushReturnValue(unsigned code) {
switch (code) { switch (code) {
case ByteField: case ByteField:
@ -1087,6 +1221,10 @@ class Compiler: public Assembler {
} }
} }
void compileCall(void* function) {
compileCall2(function, 1);
}
void compileCall(void* function, object arg1) { void compileCall(void* function, object arg1) {
if (BytesPerWord == 4) { if (BytesPerWord == 4) {
push(poolRegister(), poolReference(arg1)); push(poolRegister(), poolReference(arg1));
@ -1613,7 +1751,13 @@ class Compiler: public Assembler {
break; break;
case i2l: case i2l:
push(0); if (BytesPerWord == 8) {
sub(8, rsp);
} else {
pop(rax);
cdq();
pushLong(rax, rdx);
}
break; break;
case iadd: case iadd:
@ -1764,6 +1908,17 @@ class Compiler: public Assembler {
add(c, rbp, localOffset(index, parameterFootprint)); add(c, rbp, localOffset(index, parameterFootprint));
} break; } break;
case vm::imul:
pop(rax);
pop(rcx);
Assembler::imul(rcx);
push(rax);
break;
case ineg:
neg(rsp, 0);
break;
case instanceof: { case instanceof: {
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
@ -1860,9 +2015,28 @@ class Compiler: public Assembler {
case isub: case isub:
pop(rax); pop(rax);
pop(rcx); sub(rax, rsp, 0);
sub(rax, rcx); break;
push(rcx);
case l2i:
if (BytesPerWord == 8) {
add(BytesPerWord, rsp);
} else {
pop(rax);
mov(rax, rsp, 0);
}
break;
case ladd:
if (BytesPerWord == 8) {
add(8, rsp);
pop(rax);
add(rax, rsp, BytesPerWord);
} else {
popLong(rax, rdx);
add(rax, rsp, 0);
adc(rdx, rsp, BytesPerWord);
}
break; break;
case ldc: case ldc:
@ -1901,91 +2075,190 @@ class Compiler: public Assembler {
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType)) if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType))
{ {
push((longValue(t, v) ) & 0xFFFFFFFF); pushLong(longValue(t, v));
push((longValue(t, v) >> 32) & 0xFFFFFFFF);
} else if (objectClass(t, v) } else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::DoubleType)) == arrayBody(t, t->m->types, Machine::DoubleType))
{ {
push((doubleValue(t, v) ) & 0xFFFFFFFF); pushLong(doubleValue(t, v));
push((doubleValue(t, v) >> 32) & 0xFFFFFFFF);
} else { } else {
abort(t); abort(t);
} }
} break; } break;
case lconst_0: case lconst_0:
push(0); pushLong(0);
push(0);
break; break;
case lconst_1: case lconst_1:
push(0); pushLong(1);
push(1);
break; break;
// todo: case lcmp: {
// case lcmp: { Label next(this);
// pop(rax); Label less(this);
// pop(rdx); Label greater(this);
// if (BytesPerWord == 8) { if (BytesPerWord == 8) {
// shl(32, rax); popLong(rdx);
// } popLong(rax);
// pushInt(t, a > b ? 1 : a == b ? 0 : -1); cmp(rax, rdx);
// } goto loop; jl(less);
jg(greater);
case lload: { push(0);
unsigned index = codeBody(t, code, ip++); jmp(next);
push(rbp, localOffset(index, parameterFootprint));
push(rbp, localOffset(index + 1, parameterFootprint)); less.mark();
push(-1);
jmp(next);
greater.mark();
push(1);
next.mark();
} else {
popLong(rcx, rbx);
popLong(rax, rdx);
cmp(rdx, rbx);
jl(less);
jg(greater);
cmp(rax, rcx);
jb(less);
ja(greater);
push(0);
jmp(next);
less.mark();
push(-1);
jmp(next);
greater.mark();
push(1);
next.mark();
}
} break; } break;
case lload_0: { case ldiv_:
push(rbp, localOffset(0, parameterFootprint)); if (BytesPerWord == 8) {
push(rbp, localOffset(1, parameterFootprint)); popLong(rax);
} break; popLong(rcx);
Assembler::idiv(rcx);
pushLong(rax);
} else {
compileCall(reinterpret_cast<void*>(divideLong));
add(4, rsp);
mov(rax, rsp, 0);
mov(rdx, rsp, 4);
}
break;
case lload_1: { case lload:
push(rbp, localOffset(1, parameterFootprint)); loadLong(codeBody(t, code, ip++), parameterFootprint);
push(rbp, localOffset(2, parameterFootprint)); break;
} break;
case lload_2: { case lload_0:
push(rbp, localOffset(2, parameterFootprint)); loadLong(0, parameterFootprint);
push(rbp, localOffset(3, parameterFootprint)); break;
} break;
case lload_3: { case lload_1:
push(rbp, localOffset(3, parameterFootprint)); loadLong(1, parameterFootprint);
push(rbp, localOffset(4, parameterFootprint)); break;
} break;
case lstore: { case lload_2:
unsigned index = codeBody(t, code, ip++); loadLong(2, parameterFootprint);
pop(rbp, localOffset(index + 1, parameterFootprint)); break;
pop(rbp, localOffset(index, parameterFootprint));
} break;
case lstore_0: { case lload_3:
pop(rbp, localOffset(1, parameterFootprint)); loadLong(3, parameterFootprint);
pop(rbp, localOffset(0, parameterFootprint)); break;
} break;
case lstore_1: { case lmul:
pop(rbp, localOffset(2, parameterFootprint)); if (BytesPerWord == 8) {
pop(rbp, localOffset(1, parameterFootprint)); popLong(rax);
} break; popLong(rcx);
Assembler::imul(rcx);
pushLong(rax);
} else {
mov(rsp, 4, rcx);
Assembler::imul(rsp, 8, rcx);
mov(rsp, 12, rax);
Assembler::imul(rsp, 0, rax);
add(rax, rcx);
mov(rsp, 8, rax);
mul(rsp, 0);
add(rcx, rdx);
case lstore_2: { add(4, rsp);
pop(rbp, localOffset(3, parameterFootprint)); mov(rax, rsp, 0);
pop(rbp, localOffset(2, parameterFootprint)); mov(rdx, rsp, 4);
} break; }
break;
case lstore_3: { case lneg:
pop(rbp, localOffset(4, parameterFootprint)); if (BytesPerWord == 8) {
pop(rbp, localOffset(3, parameterFootprint)); neg(rsp, 8);
} break; } else {
mov(rsp, 0, rax);
mov(rsp, 4, rdx);
neg(rax);
adc(0, rdx);
neg(rdx);
mov(rax, rsp, 0);
mov(rdx, rsp, 4);
}
break;
case lrem:
if (BytesPerWord == 8) {
popLong(rax);
popLong(rcx);
Assembler::idiv(rcx);
pushLong(rdx);
} else {
compileCall(reinterpret_cast<void*>(moduloLong));
add(4, rsp);
mov(rax, rsp, 0);
mov(rdx, rsp, 4);
}
break;
case lstore:
storeLong(codeBody(t, code, ip++), parameterFootprint);
break;
case lstore_0:
storeLong(0, parameterFootprint);
break;
case lstore_1:
storeLong(1, parameterFootprint);
break;
case lstore_2:
storeLong(2, parameterFootprint);
break;
case lstore_3:
storeLong(3, parameterFootprint);
break;
case lsub:
if (BytesPerWord == 8) {
add(8, rsp);
pop(rax);
sub(rax, rsp, BytesPerWord);
} else {
popLong(rax, rdx);
sub(rax, rsp, 0);
sbb(rdx, rsp, BytesPerWord);
}
break;
case new_: { case new_: {
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);

View File

@ -1266,6 +1266,9 @@ inline void
dispose(Thread* t, Reference* r) dispose(Thread* t, Reference* r)
{ {
*(r->handle) = r->next; *(r->handle) = r->next;
if (r->next) {
r->next->handle = r->handle;
}
t->m->system->free(r); t->m->system->free(r);
} }