mirror of
https://github.com/corda/corda.git
synced 2025-01-01 10:46:46 +00:00
implement more instructions; various bugfixes
This commit is contained in:
parent
f2ec75e202
commit
569cfa9e07
2
makefile
2
makefile
@ -34,7 +34,7 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(cls)/Instructions.class
|
input = $(cls)/Hello.class
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
|
329
src/compile.cpp
329
src/compile.cpp
@ -52,46 +52,38 @@ class Buffer {
|
|||||||
data[position++] = v;
|
data[position++] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append2(uint32_t v) {
|
void append2(uint16_t v) {
|
||||||
ensure(2);
|
ensure(2);
|
||||||
data[position++] = (v >> 0) & 0xFF;
|
memcpy(data + position, &v, 2);
|
||||||
data[position++] = (v >> 8) & 0xFF;
|
position += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append4(uint32_t v) {
|
void append4(uint32_t v) {
|
||||||
ensure(4);
|
ensure(4);
|
||||||
data[position++] = (v >> 0) & 0xFF;
|
memcpy(data + position, &v, 4);
|
||||||
data[position++] = (v >> 8) & 0xFF;
|
position += 4;
|
||||||
data[position++] = (v >> 16) & 0xFF;
|
|
||||||
data[position++] = (v >> 24) & 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set2(unsigned offset, uint32_t v) {
|
void set2(unsigned offset, uint32_t v) {
|
||||||
assert(s, offset + 2 < position);
|
assert(s, offset + 2 <= position);
|
||||||
data[offset++] = (v >> 0) & 0xFF;
|
memcpy(data + offset, &v, 2);
|
||||||
data[offset++] = (v >> 8) & 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set4(unsigned offset, uint32_t v) {
|
void set4(unsigned offset, uint32_t v) {
|
||||||
assert(s, offset + 4 < position);
|
assert(s, offset + 4 <= position);
|
||||||
data[offset++] = (v >> 0) & 0xFF;
|
memcpy(data + offset, &v, 4);
|
||||||
data[offset++] = (v >> 8) & 0xFF;
|
|
||||||
data[offset++] = (v >> 16) & 0xFF;
|
|
||||||
data[offset++] = (v >> 24) & 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get2(unsigned offset) {
|
uint16_t get2(unsigned offset) {
|
||||||
assert(s, offset + 2 < position);
|
assert(s, offset + 2 <= position);
|
||||||
return ((data[offset++] << 0) |
|
uint16_t v; memcpy(&v, data + offset, 2);
|
||||||
(data[offset++] << 8));
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get4(unsigned offset) {
|
uint32_t get4(unsigned offset) {
|
||||||
assert(s, offset + 4 < position);
|
assert(s, offset + 4 <= position);
|
||||||
return ((data[offset++] << 0) |
|
uint32_t v; memcpy(&v, data + offset, 4);
|
||||||
(data[offset++] << 8) |
|
return v;
|
||||||
(data[offset++] << 16) |
|
|
||||||
(data[offset++] << 24));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAddress(uintptr_t v) {
|
void appendAddress(uintptr_t v) {
|
||||||
@ -256,10 +248,39 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void movz1(Register src, int32_t srcOffset, Register dst) {
|
||||||
|
code.append(0x0f);
|
||||||
|
offsetInstruction(0x86, 0, 0x40, 0x80, dst, src, srcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void movs1(Register src, int32_t srcOffset, Register dst) {
|
||||||
|
code.append(0x0f);
|
||||||
|
offsetInstruction(0x8e, 0, 0x40, 0x80, dst, src, srcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void movz2(Register src, int32_t srcOffset, Register dst) {
|
||||||
|
code.append(0x0f);
|
||||||
|
offsetInstruction(0x87, 0, 0x40, 0x80, dst, src, srcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void movs2(Register src, int32_t srcOffset, Register dst) {
|
||||||
|
code.append(0x0f);
|
||||||
|
offsetInstruction(0x8f, 0, 0x40, 0x80, dst, src, srcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
void mov4(Register src, int32_t srcOffset, Register dst) {
|
void mov4(Register src, int32_t srcOffset, Register dst) {
|
||||||
offsetInstruction(0x8b, 0, 0x40, 0x80, dst, src, srcOffset);
|
offsetInstruction(0x8b, 0, 0x40, 0x80, dst, src, srcOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mov1(Register src, Register dst, int32_t dstOffset) {
|
||||||
|
offsetInstruction(0x88, 0, 0x40, 0x80, src, dst, dstOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov2(Register src, Register dst, int32_t dstOffset) {
|
||||||
|
code.append(0x66);
|
||||||
|
offsetInstruction(0x89, 0, 0x40, 0x80, src, dst, dstOffset);
|
||||||
|
}
|
||||||
|
|
||||||
void mov4(Register src, Register dst, int32_t dstOffset) {
|
void mov4(Register src, Register dst, int32_t dstOffset) {
|
||||||
offsetInstruction(0x89, 0, 0x40, 0x80, src, dst, dstOffset);
|
offsetInstruction(0x89, 0, 0x40, 0x80, src, dst, dstOffset);
|
||||||
}
|
}
|
||||||
@ -436,14 +457,14 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void jz(Label& label) {
|
void jz(Label& label) {
|
||||||
code.append(0x0F);
|
code.append(0x0f);
|
||||||
code.append(0x84);
|
code.append(0x84);
|
||||||
label.reference();
|
label.reference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void jz(unsigned javaIP) {
|
void conditional(unsigned javaIP, unsigned condition) {
|
||||||
code.append(0x0F);
|
code.append(0x0f);
|
||||||
code.append(0x84);
|
code.append(condition);
|
||||||
|
|
||||||
jumps.append4(javaIP);
|
jumps.append4(javaIP);
|
||||||
jumps.append4(code.length());
|
jumps.append4(code.length());
|
||||||
@ -451,20 +472,34 @@ class Assembler {
|
|||||||
code.append4(0);
|
code.append4(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void jz(unsigned javaIP) {
|
||||||
|
conditional(javaIP, 0x84);
|
||||||
|
}
|
||||||
|
|
||||||
void jnz(Label& label) {
|
void jnz(Label& label) {
|
||||||
code.append(0x0F);
|
code.append(0x0f);
|
||||||
code.append(0x85);
|
code.append(0x85);
|
||||||
label.reference();
|
label.reference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void jnz(unsigned javaIP) {
|
void jnz(unsigned javaIP) {
|
||||||
code.append(0x0F);
|
conditional(javaIP, 0x85);
|
||||||
code.append(0x85);
|
}
|
||||||
|
|
||||||
jumps.append4(javaIP);
|
void jg(unsigned javaIP) {
|
||||||
jumps.append4(code.length());
|
conditional(javaIP, 0x8f);
|
||||||
|
}
|
||||||
|
|
||||||
code.append4(0);
|
void jge(unsigned javaIP) {
|
||||||
|
conditional(javaIP, 0x8d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jl(unsigned javaIP) {
|
||||||
|
conditional(javaIP, 0x8c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jle(unsigned javaIP) {
|
||||||
|
conditional(javaIP, 0x8e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmp(int v, Register reg) {
|
void cmp(int v, Register reg) {
|
||||||
@ -795,6 +830,10 @@ class Compiler: public Assembler {
|
|||||||
unsigned instruction = codeBody(t, code, ip++);
|
unsigned instruction = codeBody(t, code, ip++);
|
||||||
|
|
||||||
switch (instruction) {
|
switch (instruction) {
|
||||||
|
case aconst_null:
|
||||||
|
push(0);
|
||||||
|
break;
|
||||||
|
|
||||||
case aload:
|
case aload:
|
||||||
case iload:
|
case iload:
|
||||||
case fload:
|
case fload:
|
||||||
@ -870,6 +909,51 @@ class Compiler: public Assembler {
|
|||||||
push(rsp, BytesPerWord);
|
push(rsp, BytesPerWord);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case getfield: {
|
||||||
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
movs1(rax, fieldOffset(t, field), rax);
|
||||||
|
push(rax);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CharField:
|
||||||
|
movz2(rax, fieldOffset(t, field), rax);
|
||||||
|
push(rax);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ShortField:
|
||||||
|
movs2(rax, fieldOffset(t, field), rax);
|
||||||
|
push(rax);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
case IntField:
|
||||||
|
push4(rax, fieldOffset(t, field));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DoubleField:
|
||||||
|
case LongField:
|
||||||
|
push4(rax, fieldOffset(t, field));
|
||||||
|
push4(rax, fieldOffset(t, field) + 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
push(rax, fieldOffset(t, field));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case getstatic: {
|
case getstatic: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
@ -969,6 +1053,63 @@ class Compiler: public Assembler {
|
|||||||
push(5);
|
push(5);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case if_acmpeq:
|
||||||
|
case if_icmpeq: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
pop(rcx);
|
||||||
|
cmp(rax, rcx);
|
||||||
|
jz((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case if_acmpne:
|
||||||
|
case if_icmpne: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
pop(rcx);
|
||||||
|
cmp(rax, rcx);
|
||||||
|
jnz((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case if_icmpgt: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
pop(rcx);
|
||||||
|
cmp(rax, rcx);
|
||||||
|
jg((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case if_icmpge: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
pop(rcx);
|
||||||
|
cmp(rax, rcx);
|
||||||
|
jge((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case if_icmplt: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
pop(rcx);
|
||||||
|
cmp(rax, rcx);
|
||||||
|
jl((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case if_icmple: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
pop(rcx);
|
||||||
|
cmp(rax, rcx);
|
||||||
|
jle((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ifeq:
|
||||||
case ifnull: {
|
case ifnull: {
|
||||||
int16_t offset = codeReadInt16(t, code, ip);
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
@ -977,13 +1118,64 @@ class Compiler: public Assembler {
|
|||||||
jz((ip - 3) + offset);
|
jz((ip - 3) + offset);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ifne:
|
||||||
|
case ifnonnull: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
cmp(0, rax);
|
||||||
|
jnz((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ifgt: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
cmp(0, rax);
|
||||||
|
jg((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ifge: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
cmp(0, rax);
|
||||||
|
jge((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case iflt: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
cmp(0, rax);
|
||||||
|
jl((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ifle: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
pop(rax);
|
||||||
|
cmp(0, rax);
|
||||||
|
jle((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case goto_: {
|
||||||
|
int16_t offset = codeReadInt16(t, code, ip);
|
||||||
|
jmp((ip - 3) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case goto_w: {
|
||||||
|
int32_t offset = codeReadInt32(t, code, ip);
|
||||||
|
jmp((ip - 5) + offset);
|
||||||
|
} break;
|
||||||
|
|
||||||
case invokespecial: {
|
case invokespecial: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
object target = resolveMethod(t, codePool(t, code), index - 1);
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
object class_ = methodClass(t, method);
|
object class_ = methodClass(t, target);
|
||||||
if (isSpecialMethod(t, target, class_)) {
|
if (isSpecialMethod(t, target, class_)) {
|
||||||
target = findMethod(t, target, classSuper(t, class_));
|
target = findMethod(t, target, classSuper(t, class_));
|
||||||
}
|
}
|
||||||
@ -998,7 +1190,7 @@ class Compiler: public Assembler {
|
|||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
PROTECT(t, target);
|
PROTECT(t, target);
|
||||||
|
|
||||||
initClass(t, methodClass(t, method));
|
initClass(t, methodClass(t, target));
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
compileDirectInvoke(t, target);
|
compileDirectInvoke(t, target);
|
||||||
@ -1034,7 +1226,7 @@ class Compiler: public Assembler {
|
|||||||
|
|
||||||
add(footprint, rsp); // pop arguments
|
add(footprint, rsp); // pop arguments
|
||||||
|
|
||||||
pushReturnValue(t, methodReturnCode(t, method));
|
pushReturnValue(t, methodReturnCode(t, target));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ldc:
|
case ldc:
|
||||||
@ -1093,6 +1285,58 @@ class Compiler: public Assembler {
|
|||||||
add(BytesPerWord, rsp);
|
add(BytesPerWord, rsp);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case putfield: {
|
||||||
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
case CharField:
|
||||||
|
case ShortField:
|
||||||
|
case FloatField:
|
||||||
|
case IntField: {
|
||||||
|
pop(rcx);
|
||||||
|
pop(rax);
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
mov1(rcx, rax, fieldOffset(t, field));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CharField:
|
||||||
|
case ShortField:
|
||||||
|
mov2(rcx, rax, fieldOffset(t, field));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
case IntField:
|
||||||
|
mov4(rcx, rax, fieldOffset(t, field));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DoubleField:
|
||||||
|
case LongField: {
|
||||||
|
pop(rcx);
|
||||||
|
pop(rdx);
|
||||||
|
pop(rax);
|
||||||
|
mov4(rcx, rax, fieldOffset(t, field));
|
||||||
|
mov4(rdx, rax, fieldOffset(t, field) + 4);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ObjectField: {
|
||||||
|
pop(rcx);
|
||||||
|
pop(rax);
|
||||||
|
mov(rcx, rax, fieldOffset(t, field));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case putstatic: {
|
case putstatic: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
@ -1160,6 +1404,7 @@ class Compiler: public Assembler {
|
|||||||
|
|
||||||
unsigned bottom = 0;
|
unsigned bottom = 0;
|
||||||
unsigned top = javaIPs.length() / 2;
|
unsigned top = javaIPs.length() / 2;
|
||||||
|
bool success = false;
|
||||||
for (unsigned span = top - bottom; span; span = top - bottom) {
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
||||||
unsigned middle = bottom + (span / 2);
|
unsigned middle = bottom + (span / 2);
|
||||||
uint32_t k = javaIPs.get2(middle * 2);
|
uint32_t k = javaIPs.get2(middle * 2);
|
||||||
@ -1170,9 +1415,11 @@ class Compiler: public Assembler {
|
|||||||
bottom = middle + 1;
|
bottom = middle + 1;
|
||||||
} else {
|
} else {
|
||||||
code.set4(offset, machineIPs.get4(middle * 4) - (offset + 4));
|
code.set4(offset, machineIPs.get4(middle * 4) - (offset + 4));
|
||||||
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(code.s, success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1224,6 +1471,10 @@ compileMethod2(MyThread* t, object method)
|
|||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
if (methodCompiled(t, method) == t->m->processor->methodStub(t)) {
|
if (methodCompiled(t, method) == t->m->processor->methodStub(t)) {
|
||||||
|
fprintf(stderr, "compiling %s.%s\n",
|
||||||
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||||
|
&byteArrayBody(t, methodName(t, method), 0));
|
||||||
|
|
||||||
Compiler c(t->m->system);
|
Compiler c(t->m->system);
|
||||||
c.compile(t, method);
|
c.compile(t, method);
|
||||||
|
|
||||||
@ -1232,6 +1483,12 @@ compileMethod2(MyThread* t, object method)
|
|||||||
|
|
||||||
c.code.copyTo(&compiledBody(t, compiled, 0));
|
c.code.copyTo(&compiledBody(t, compiled, 0));
|
||||||
|
|
||||||
|
fprintf(stderr, "compiled %s.%s from %p to %p\n",
|
||||||
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||||
|
&byteArrayBody(t, methodName(t, method), 0),
|
||||||
|
&compiledBody(t, compiled, 0),
|
||||||
|
&compiledBody(t, compiled, 0) + compiledLength(t, compiled));
|
||||||
|
|
||||||
set(t, methodCompiled(t, method), compiled);
|
set(t, methodCompiled(t, method), compiled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1003,7 +1003,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
arrayBody(t, pool, spec - 1),
|
arrayBody(t, pool, spec - 1),
|
||||||
class_,
|
class_,
|
||||||
code,
|
code,
|
||||||
(code ? t->m->processor->methodStub(t) : 0));
|
t->m->processor->methodStub(t));
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
if (flags & ACC_STATIC) {
|
if (flags & ACC_STATIC) {
|
||||||
|
Loading…
Reference in New Issue
Block a user