[wasm] Fix jump table for long jumps on arm

Direct jumps only work for offset up to 64 MB on arm. For longer jumps,
use indirect branches (load target from constant pool into the pc
register).

R=mstarzinger@chromium.org
CC=pierre.langlois@arm.com

Bug: v8:7758
Change-Id: I1cf66b7d1bfb62cfcd6b1619c02816909a1f651e
Reviewed-on: https://chromium-review.googlesource.com/1105996
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53847}
This commit is contained in:
Clemens Hammacher 2018-06-19 17:16:14 +02:00 committed by Commit Bot
parent 928e28cddd
commit d5177a02c9
2 changed files with 19 additions and 11 deletions

View File

@ -85,22 +85,30 @@ void JumpTableAssembler::NopBytes(int bytes) {
void JumpTableAssembler::EmitLazyCompileJumpSlot(uint32_t func_index,
Address lazy_compile_target) {
// Load function index to r4.
// This generates <= 3 instructions: ldr, const pool start, constant
// This generates [movw, movt] on ARMv7 and later, [ldr, constant pool marker,
// constant] on ARMv6.
Move32BitImmediate(r4, Operand(func_index));
// Jump to {lazy_compile_target}.
int offset =
lazy_compile_target - reinterpret_cast<Address>(pc_) - kPcLoadDelta;
DCHECK_EQ(0, offset % kInstrSize);
DCHECK(is_int26(offset)); // 26 bit imm
b(offset); // 1 instr
CheckConstPool(true, false); // force emit of const pool
// EmitJumpSlot emits either [b], [movw, movt, mov] (ARMv7+), or [ldr,
// constant].
// In total, this is <=5 instructions on all architectures.
// TODO(arm): Optimize this for code size; lazy compile is not performance
// critical, as it's only executed once per function.
EmitJumpSlot(lazy_compile_target);
}
void JumpTableAssembler::EmitJumpSlot(Address target) {
int offset = target - reinterpret_cast<Address>(pc_) - kPcLoadDelta;
DCHECK_EQ(0, offset % kInstrSize);
DCHECK(is_int26(offset)); // 26 bit imm
b(offset);
// If the offset is within 64 MB, emit a direct jump. Otherwise jump
// indirectly.
if (is_int26(offset)) {
b(offset); // 1 instr
} else {
// {Move32BitImmediate} emits either [movw, movt, mov] or [ldr, constant].
Move32BitImmediate(pc, Operand(target));
}
CheckConstPool(true, false); // force emit of const pool
}
void JumpTableAssembler::NopBytes(int bytes) {

View File

@ -40,7 +40,7 @@ class JumpTableAssembler : public TurboAssembler {
#elif V8_TARGET_ARCH_IA32
static constexpr int kJumpTableSlotSize = 10;
#elif V8_TARGET_ARCH_ARM
static constexpr int kJumpTableSlotSize = 4 * kInstrSize;
static constexpr int kJumpTableSlotSize = 5 * kInstrSize;
#elif V8_TARGET_ARCH_ARM64
static constexpr int kJumpTableSlotSize = 3 * kInstructionSize;
#else