Merge pull request #400 from dicej/master

use unconditional branch to stack overflow thunk on ARM64
This commit is contained in:
Joshua Warner 2015-01-21 08:28:42 -07:00
commit bd22daccff
3 changed files with 21 additions and 15 deletions

View File

@ -95,7 +95,7 @@ void nextFrame(ArchitectureContext* con,
if ((*start >> 20) == (TargetBytesPerWord == 8 ? 0xf94 : 0xe59)) {
// skip stack overflow check
start += 3;
start += TargetBytesPerWord == 8 ? 4 : 3;
}
if (instruction <= start) {

View File

@ -102,22 +102,23 @@ void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value)
int32_t v;
int32_t mask;
if (vm::TargetBytesPerWord == 8) {
if ((*p >> 24) == 0x54) {
// conditional branch
v = ((reinterpret_cast<uint8_t*>(value) - instruction) >> 2) << 5;
mask = 0xFFFFE0;
} else {
// unconditional branch
v = (reinterpret_cast<uint8_t*>(value) - instruction) >> 2;
mask = 0x3FFFFFF;
}
if ((*p >> 24) == 0x54) {
// conditional branch
v = ((reinterpret_cast<uint8_t*>(value) - instruction) >> 2) << 5;
mask = 0xFFFFE0;
expect(s, bounded(5, 8, v));
} else {
// unconditional branch
v = (reinterpret_cast<uint8_t*>(value) - instruction) >> 2;
mask = 0x3FFFFFF;
expect(s, bounded(0, 6, v));
}
} else {
v = (reinterpret_cast<uint8_t*>(value) - (instruction + 8)) >> 2;
mask = 0xFFFFFF;
expect(s, bounded(0, 8, v));
}
expect(s, bounded(0, 8, v));
*p = (v & mask) | ((~mask) & *p);
return instruction + InstructionSize;

View File

@ -1483,12 +1483,17 @@ void branchRM(Context* c,
assertT(c, size <= vm::TargetBytesPerWord);
if (a->low.index() == 31) {
// stack overflow checks need to compare to the stack pointer, but
// Stack overflow checks need to compare to the stack pointer, but
// we can only encode that in the opposite operand order we're
// given, so we need to reverse everything:
// given, so we need to reverse everything. Also, we can't do a
// conditional jump further than 2^19 instructions away, which can
// cause trouble with large code, so we branch past an
// unconditional branch which can jump further, which reverses the
// logic again. Confused? Good.
assertT(c, op == lir::JumpIfGreaterOrEqual);
compareMR(c, size, b, size, a);
branch(c, lir::JumpIfLess, target);
append(c, bge(8));
jumpC(c, vm::TargetBytesPerWord, target);
} else {
compareRM(c, size, a, size, b);
branch(c, op, target);