mirror of
https://github.com/corda/corda.git
synced 2025-01-01 10:46:46 +00:00
implement invokestatic, putstatic, and bipush; respect special handling of rsp and rbp in Assembler
This commit is contained in:
parent
37ccb6cb46
commit
ddab82996c
249
src/compile.cpp
249
src/compile.cpp
@ -194,48 +194,52 @@ class Assembler {
|
|||||||
code.append(0xc0 | (src << 3) | dst);
|
code.append(0xc0 | (src << 3) | dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void offsetInstruction(uint8_t instruction, uint8_t zeroPrefix,
|
||||||
|
uint8_t bytePrefix, uint8_t wordPrefix,
|
||||||
|
Register a, Register b, int32_t offset)
|
||||||
|
{
|
||||||
|
code.append(instruction);
|
||||||
|
|
||||||
|
uint8_t prefix;
|
||||||
|
if (offset == 0 and b != rbp) {
|
||||||
|
prefix = zeroPrefix;
|
||||||
|
} else if (isByte(offset)) {
|
||||||
|
prefix = bytePrefix;
|
||||||
|
} else {
|
||||||
|
prefix = wordPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(prefix | (a << 3) | b);
|
||||||
|
|
||||||
|
if (b == rsp) {
|
||||||
|
code.append(0x24);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == 0 and b != rbp) {
|
||||||
|
// do nothing
|
||||||
|
} else if (isByte(offset)) {
|
||||||
|
code.append(offset);
|
||||||
|
} else {
|
||||||
|
code.append4(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov4(Register src, int32_t srcOffset, Register dst) {
|
||||||
|
offsetInstruction(0x8b, 0, 0x40, 0x80, dst, src, srcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov4(Register src, Register dst, int32_t dstOffset) {
|
||||||
|
offsetInstruction(0x89, 0, 0x40, 0x80, src, dst, dstOffset);
|
||||||
|
}
|
||||||
|
|
||||||
void mov(Register src, int32_t srcOffset, Register dst) {
|
void mov(Register src, int32_t srcOffset, Register dst) {
|
||||||
rex();
|
rex();
|
||||||
code.append(0x8b);
|
mov4(src, srcOffset, dst);
|
||||||
if (srcOffset) {
|
|
||||||
if (isByte(srcOffset)) {
|
|
||||||
code.append(0x40 | (dst << 3) | src);
|
|
||||||
if (src == rsp) {
|
|
||||||
code.append(0x24);
|
|
||||||
}
|
|
||||||
code.append(srcOffset);
|
|
||||||
} else {
|
|
||||||
code.append(0x80 | (dst << 3) | src);
|
|
||||||
if (src == rsp) {
|
|
||||||
code.append(0x24);
|
|
||||||
}
|
|
||||||
code.append4(srcOffset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
code.append((dst << 3) | src);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mov(Register src, Register dst, int32_t dstOffset) {
|
void mov(Register src, Register dst, int32_t dstOffset) {
|
||||||
rex();
|
rex();
|
||||||
code.append(0x89);
|
mov4(src, dst, dstOffset);
|
||||||
if (dstOffset) {
|
|
||||||
if (isByte(dstOffset)) {
|
|
||||||
code.append(0x40 | (src << 3) | dst);
|
|
||||||
if (dst == rsp) {
|
|
||||||
code.append(0x24);
|
|
||||||
}
|
|
||||||
code.append(dstOffset);
|
|
||||||
} else {
|
|
||||||
code.append(0x80 | (src << 3) | dst);
|
|
||||||
if (dst == rsp) {
|
|
||||||
code.append(0x24);
|
|
||||||
}
|
|
||||||
code.append4(dstOffset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
code.append((src << 3) | dst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mov(uintptr_t v, Register dst) {
|
void mov(uintptr_t v, Register dst) {
|
||||||
@ -262,14 +266,7 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void push(Register reg, int32_t offset) {
|
void push(Register reg, int32_t offset) {
|
||||||
assert(code.s, isByte(offset)); // todo
|
offsetInstruction(0xff, 0x30, 0x70, 0xb0, rax, reg, offset);
|
||||||
|
|
||||||
code.append(0xff);
|
|
||||||
code.append(0x70 | reg);
|
|
||||||
if (reg == rsp) {
|
|
||||||
code.append(0x24);
|
|
||||||
}
|
|
||||||
code.append(offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(int32_t v) {
|
void push(int32_t v) {
|
||||||
@ -288,16 +285,30 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push4(Register reg, int32_t offset) {
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
mov4(reg, offset, rsi);
|
||||||
|
push(rsi);
|
||||||
|
} else {
|
||||||
|
push(reg, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pop(Register dst) {
|
void pop(Register dst) {
|
||||||
code.append(0x58 | dst);
|
code.append(0x58 | dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop(Register dst, int32_t offset) {
|
void pop(Register dst, int32_t offset) {
|
||||||
assert(code.s, isByte(offset)); // todo
|
offsetInstruction(0x8f, 0, 0x40, 0x80, rax, dst, offset);
|
||||||
|
}
|
||||||
|
|
||||||
code.append(0x8f);
|
void pop4(Register reg, int32_t offset) {
|
||||||
code.append(0x40 | dst);
|
if (BytesPerWord == 8) {
|
||||||
code.append(offset);
|
pop(rsi);
|
||||||
|
mov4(rsi, reg, offset);
|
||||||
|
} else {
|
||||||
|
pop(reg, offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(Register src, Register dst) {
|
void add(Register src, Register dst) {
|
||||||
@ -454,6 +465,42 @@ class Compiler: public Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compileDirectInvoke(Thread* t, object target) {
|
||||||
|
unsigned footprint = FrameFootprint
|
||||||
|
+ (methodParameterFootprint(t, target) * BytesPerWord);
|
||||||
|
|
||||||
|
uint8_t* code = &compiledBody(t, methodCompiled(t, target), 0);
|
||||||
|
|
||||||
|
push(rbp);
|
||||||
|
pushAddress(reinterpret_cast<uintptr_t>(target));
|
||||||
|
push(rbp, FrameThread);
|
||||||
|
|
||||||
|
alignedMov(reinterpret_cast<uintptr_t>(code), rax);
|
||||||
|
call(rax);
|
||||||
|
|
||||||
|
add(footprint, rsp); // pop arguments
|
||||||
|
|
||||||
|
pushReturnValue(t, methodReturnCode(t, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
void compileCall1(uintptr_t function, uintptr_t arg1) {
|
||||||
|
if (BytesPerWord == 4) {
|
||||||
|
pushAddress(arg1);
|
||||||
|
push(rbp, FrameThread);
|
||||||
|
} else {
|
||||||
|
mov(arg1, rsi);
|
||||||
|
mov(rbp, FrameThread, rdi);
|
||||||
|
}
|
||||||
|
|
||||||
|
mov(function, rax);
|
||||||
|
|
||||||
|
call(rax);
|
||||||
|
|
||||||
|
if (BytesPerWord == 4) {
|
||||||
|
add(BytesPerWord * 2, rsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void compile(Thread* t, object method) {
|
void compile(Thread* t, object method) {
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -484,6 +531,10 @@ class Compiler: public Assembler {
|
|||||||
ret();
|
ret();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case bipush: {
|
||||||
|
push(static_cast<int8_t>(codeBody(t, code, ip++)));
|
||||||
|
} break;
|
||||||
|
|
||||||
case dup:
|
case dup:
|
||||||
push(rsp, BytesPerWord);
|
push(rsp, BytesPerWord);
|
||||||
break;
|
break;
|
||||||
@ -516,7 +567,7 @@ class Compiler: public Assembler {
|
|||||||
cmp(0, rax);
|
cmp(0, rax);
|
||||||
je(zero);
|
je(zero);
|
||||||
|
|
||||||
push(rax, IntValue);
|
push4(rax, IntValue);
|
||||||
jmp(next);
|
jmp(next);
|
||||||
|
|
||||||
zero.mark();
|
zero.mark();
|
||||||
@ -533,8 +584,8 @@ class Compiler: public Assembler {
|
|||||||
cmp(0, rax);
|
cmp(0, rax);
|
||||||
je(zero);
|
je(zero);
|
||||||
|
|
||||||
push(rax, LongValue);
|
push4(rax, LongValue);
|
||||||
push(rax, LongValue + 4);
|
push4(rax, LongValue + 4);
|
||||||
jmp(next);
|
jmp(next);
|
||||||
|
|
||||||
zero.mark();
|
zero.mark();
|
||||||
@ -545,7 +596,7 @@ class Compiler: public Assembler {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ObjectField: {
|
case ObjectField: {
|
||||||
push(rax);
|
push(rax, 0);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
@ -625,25 +676,23 @@ class Compiler: public Assembler {
|
|||||||
|
|
||||||
object class_ = methodClass(t, method);
|
object class_ = methodClass(t, method);
|
||||||
if (isSpecialMethod(t, target, class_)) {
|
if (isSpecialMethod(t, target, class_)) {
|
||||||
class_ = classSuper(t, class_);
|
target = findMethod(t, target, classSuper(t, class_));
|
||||||
target = findMethod(t, target, class_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned footprint = FrameFootprint
|
compileDirectInvoke(t, target);
|
||||||
+ (methodParameterFootprint(t, target) * BytesPerWord);
|
} break;
|
||||||
|
|
||||||
uint8_t* code = &compiledBody(t, methodCompiled(t, target), 0);
|
case invokestatic: {
|
||||||
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
push(rbp);
|
|
||||||
pushAddress(reinterpret_cast<uintptr_t>(target));
|
|
||||||
push(rbp, FrameThread);
|
|
||||||
|
|
||||||
alignedMov(reinterpret_cast<uintptr_t>(code), rax);
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
call(rax);
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
PROTECT(t, target);
|
||||||
|
|
||||||
add(footprint, rsp); // pop arguments
|
initClass(t, methodClass(t, method));
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
pushReturnValue(t, methodReturnCode(t, method));
|
compileDirectInvoke(t, target);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case invokevirtual: {
|
case invokevirtual: {
|
||||||
@ -666,7 +715,7 @@ class Compiler: public Assembler {
|
|||||||
mov(rax, ClassVirtualTable, rax); // load vtable
|
mov(rax, ClassVirtualTable, rax); // load vtable
|
||||||
mov(rax, offset, rax); // load method
|
mov(rax, offset, rax); // load method
|
||||||
|
|
||||||
push(rbp, 0);
|
push(rbp);
|
||||||
push(rax);
|
push(rax);
|
||||||
push(rbp, FrameThread);
|
push(rbp, FrameThread);
|
||||||
|
|
||||||
@ -749,25 +798,13 @@ class Compiler: public Assembler {
|
|||||||
|
|
||||||
initClass(t, class_);
|
initClass(t, class_);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
if (BytesPerWord == 4) {
|
|
||||||
pushAddress(reinterpret_cast<uintptr_t>(class_));
|
|
||||||
push(rbp, FrameThread);
|
|
||||||
} else {
|
|
||||||
mov(reinterpret_cast<uintptr_t>(class_), rsi);
|
|
||||||
mov(rbp, FrameThread, rdi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
||||||
mov(reinterpret_cast<uintptr_t>(makeNewWeakReference), rax);
|
compileCall1(reinterpret_cast<uintptr_t>(makeNewWeakReference),
|
||||||
|
reinterpret_cast<uintptr_t>(class_));
|
||||||
} else {
|
} else {
|
||||||
mov(reinterpret_cast<uintptr_t>(makeNew), rax);
|
compileCall1(reinterpret_cast<uintptr_t>(makeNew),
|
||||||
}
|
reinterpret_cast<uintptr_t>(class_));
|
||||||
|
|
||||||
call(rax);
|
|
||||||
|
|
||||||
if (BytesPerWord == 4) {
|
|
||||||
add(BytesPerWord * 2, rsp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
push(rax);
|
push(rax);
|
||||||
@ -777,6 +814,52 @@ class Compiler: public Assembler {
|
|||||||
add(BytesPerWord, rsp);
|
add(BytesPerWord, rsp);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case putstatic: {
|
||||||
|
uint16_t index = codeReadInt16(t, code, ip);
|
||||||
|
|
||||||
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
|
initClass(t, fieldClass(t, field));
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
|
object table = classStaticTable(t, fieldClass(t, field));
|
||||||
|
|
||||||
|
mov(reinterpret_cast<uintptr_t>(table), rax);
|
||||||
|
add(fieldOffset(t, field), rax);
|
||||||
|
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
case CharField:
|
||||||
|
case ShortField:
|
||||||
|
case FloatField:
|
||||||
|
case IntField: {
|
||||||
|
compileCall1(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)));
|
||||||
|
|
||||||
|
pop4(rax, LongValue);
|
||||||
|
pop4(rax, LongValue + 4);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
pop(rax, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case return_:
|
case return_:
|
||||||
mov(rbp, rsp);
|
mov(rbp, rsp);
|
||||||
pop(rbp);
|
pop(rbp);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
public class Instructions {
|
public class Instructions {
|
||||||
|
private static int alpha;
|
||||||
|
private static int beta;
|
||||||
|
|
||||||
private String foo(String s) {
|
private String foo(String s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -7,6 +10,10 @@ public class Instructions {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String baz(String s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int a = 2;
|
int a = 2;
|
||||||
int b = 2;
|
int b = 2;
|
||||||
@ -15,5 +22,12 @@ public class Instructions {
|
|||||||
Instructions i = new Instructions();
|
Instructions i = new Instructions();
|
||||||
i.foo("hello");
|
i.foo("hello");
|
||||||
i.bar("hello");
|
i.bar("hello");
|
||||||
|
baz("hello");
|
||||||
|
|
||||||
|
int d = alpha;
|
||||||
|
beta = 42;
|
||||||
|
alpha = 43;
|
||||||
|
int e = beta;
|
||||||
|
int f = alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user