implement checkcast and instanceof

This commit is contained in:
Joel Dice 2007-09-29 15:08:29 -06:00
parent 569cfa9e07
commit b0500a881c
2 changed files with 119 additions and 32 deletions

View File

@ -18,6 +18,20 @@ const unsigned FrameMethod = FrameThread + BytesPerWord;
const unsigned FrameNext = FrameNext + BytesPerWord;
const unsigned FrameFootprint = BytesPerWord * 3;
void
unwind(Thread* t)
{
// todo
abort(t);
}
void
throwNew(Thread* t, object class_)
{
t->exception = makeNew(t, class_);
unwind(t);
}
class Buffer {
public:
Buffer(System* s, unsigned minimumCapacity):
@ -456,7 +470,7 @@ class Assembler {
code.append(0xe0 | reg);
}
void jz(Label& label) {
void je(Label& label) {
code.append(0x0f);
code.append(0x84);
label.reference();
@ -472,17 +486,17 @@ class Assembler {
code.append4(0);
}
void jz(unsigned javaIP) {
void je(unsigned javaIP) {
conditional(javaIP, 0x84);
}
void jnz(Label& label) {
void jne(Label& label) {
code.append(0x0f);
code.append(0x85);
label.reference();
}
void jnz(unsigned javaIP) {
void jne(unsigned javaIP) {
conditional(javaIP, 0x85);
}
@ -619,7 +633,7 @@ class Compiler: public Assembler {
pushReturnValue(t, methodReturnCode(t, target));
}
void compileCall1(uintptr_t function, uintptr_t arg1) {
void compileCall(uintptr_t function, uintptr_t arg1) {
if (BytesPerWord == 4) {
pushAddress(arg1);
push(rbp, FrameThread);
@ -636,6 +650,25 @@ class Compiler: public Assembler {
}
}
void compileCall(uintptr_t function, Register arg1, Register arg2) {
if (BytesPerWord == 4) {
push(arg2);
push(arg1);
push(rbp, FrameThread);
} else {
mov(arg2, rdx);
mov(arg1, rsi);
mov(rbp, FrameThread, rdi);
}
mov(function, rax);
call(rax);
if (BytesPerWord == 4) {
add(BytesPerWord * 3, rsp);
}
}
void compile(MyThread* t, object method) {
if (methodFlags(t, method) & ACC_NATIVE) {
compileNative(t, method);
@ -865,6 +898,8 @@ class Compiler: public Assembler {
break;
case areturn:
case ireturn:
case freturn:
pop(rax);
mov(rbp, rsp);
pop(rbp);
@ -905,6 +940,35 @@ class Compiler: public Assembler {
push(static_cast<int8_t>(codeBody(t, code, ip++)));
} break;
case checkcast: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
Label next(this);
pop(rax);
cmp(0, rax);
je(next);
mov(reinterpret_cast<uintptr_t>(class_), rcx);
mov(rax, 0, rax);
cmp(rcx, rax);
je(next);
compileCall(reinterpret_cast<uintptr_t>(isAssignableFrom), rcx, rax);
cmp(0, rax);
jne(next);
compileCall
(reinterpret_cast<uintptr_t>(throwNew),
reinterpret_cast<uintptr_t>
(arrayBody(t, t->m->types, Machine::ClassCastExceptionType)));
next.mark();
} break;
case dup:
push(rsp, BytesPerWord);
break;
@ -980,7 +1044,7 @@ class Compiler: public Assembler {
Label next(this);
cmp(0, rax);
jz(zero);
je(zero);
push4(rax, IntValue);
jmp(next);
@ -997,7 +1061,7 @@ class Compiler: public Assembler {
Label next(this);
cmp(0, rax);
jz(zero);
je(zero);
push4(rax, LongValue);
push4(rax, LongValue + 4);
@ -1060,7 +1124,7 @@ class Compiler: public Assembler {
pop(rax);
pop(rcx);
cmp(rax, rcx);
jz((ip - 3) + offset);
je((ip - 3) + offset);
} break;
case if_acmpne:
@ -1070,7 +1134,7 @@ class Compiler: public Assembler {
pop(rax);
pop(rcx);
cmp(rax, rcx);
jnz((ip - 3) + offset);
jne((ip - 3) + offset);
} break;
case if_icmpgt: {
@ -1115,7 +1179,7 @@ class Compiler: public Assembler {
pop(rax);
cmp(0, rax);
jz((ip - 3) + offset);
je((ip - 3) + offset);
} break;
case ifne:
@ -1124,7 +1188,7 @@ class Compiler: public Assembler {
pop(rax);
cmp(0, rax);
jnz((ip - 3) + offset);
jne((ip - 3) + offset);
} break;
case ifgt: {
@ -1169,6 +1233,39 @@ class Compiler: public Assembler {
jmp((ip - 5) + offset);
} break;
case instanceof: {
uint16_t index = codeReadInt16(t, code, ip);
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
Label call(this);
Label zero(this);
Label next(this);
pop(rax);
cmp(0, rax);
je(zero);
mov(reinterpret_cast<uintptr_t>(class_), rcx);
mov(rax, 0, rax);
cmp(rcx, rax);
jne(call);
push(1);
jmp(next);
call.mark();
compileCall(reinterpret_cast<uintptr_t>(isAssignableFrom), rcx, rax);
push(rax);
jmp(next);
zero.mark();
push(0);
next.mark();
} break;
case invokespecial: {
uint16_t index = codeReadInt16(t, code, ip);
@ -1271,11 +1368,11 @@ class Compiler: public Assembler {
if (UNLIKELY(t->exception)) return;
if (classVmFlags(t, class_) & WeakReferenceFlag) {
compileCall1(reinterpret_cast<uintptr_t>(makeNewWeakReference),
reinterpret_cast<uintptr_t>(class_));
compileCall(reinterpret_cast<uintptr_t>(makeNewWeakReference),
reinterpret_cast<uintptr_t>(class_));
} else {
compileCall1(reinterpret_cast<uintptr_t>(makeNew),
reinterpret_cast<uintptr_t>(class_));
compileCall(reinterpret_cast<uintptr_t>(makeNew),
reinterpret_cast<uintptr_t>(class_));
}
push(rax);
@ -1358,18 +1455,18 @@ class Compiler: public Assembler {
case ShortField:
case FloatField:
case IntField: {
compileCall1(reinterpret_cast<uintptr_t>(makeNew),
reinterpret_cast<uintptr_t>
(arrayBody(t, t->m->types, Machine::IntType)));
compileCall(reinterpret_cast<uintptr_t>(makeNew),
reinterpret_cast<uintptr_t>
(arrayBody(t, t->m->types, Machine::IntType)));
pop4(rax, IntValue);
} break;
case DoubleField:
case LongField: {
compileCall1(reinterpret_cast<uintptr_t>(makeNew),
reinterpret_cast<uintptr_t>
(arrayBody(t, t->m->types, Machine::LongType)));
compileCall(reinterpret_cast<uintptr_t>(makeNew),
reinterpret_cast<uintptr_t>
(arrayBody(t, t->m->types, Machine::LongType)));
pop4(rax, LongValue);
pop4(rax, LongValue + 4);
@ -1520,13 +1617,6 @@ updateCaller(MyThread* t, object method)
}
}
void
unwind(Thread* t)
{
// todo
abort(t);
}
void
compileMethod(MyThread* t, object method)
{

View File

@ -1713,12 +1713,9 @@ interpret(Thread* t)
} goto loop;
case instanceof: {
uint8_t index1 = codeBody(t, code, ip++);
uint8_t index2 = codeBody(t, code, ip++);
uint16_t index = codeReadInt16(t, code, ip);
if (peekObject(t, sp - 1)) {
uint16_t index = (index1 << 8) | index2;
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;