Add support for movw/movt immediate loads to BackEdgeTable on ARM to enable ool constant pool.

R=rodolph.perfetta@arm.com, ulan@chromium.org

Review URL: https://codereview.chromium.org/190833002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20023 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
rmcilroy@chromium.org 2014-03-18 11:36:19 +00:00
parent 6c01c3fd56
commit be0bc25bbb

View File

@ -4827,7 +4827,19 @@ FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
#undef __ #undef __
static const int32_t kBranchBeforeInterrupt = 0x5a000004; static Address GetInterruptImmediateLoadAddress(Address pc) {
Address load_address = pc - 2 * Assembler::kInstrSize;
if (!FLAG_enable_ool_constant_pool) {
ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address)));
} else if (Assembler::IsMovT(Memory::int32_at(load_address))) {
load_address -= Assembler::kInstrSize;
ASSERT(Assembler::IsMovW(Memory::int32_at(load_address)));
} else {
// TODO(rmcilroy): uncomment when IsLdrPpImmediateOffset lands.
// ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(load_address)));
}
return load_address;
}
void BackEdgeTable::PatchAt(Code* unoptimized_code, void BackEdgeTable::PatchAt(Code* unoptimized_code,
@ -4835,37 +4847,42 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code,
BackEdgeState target_state, BackEdgeState target_state,
Code* replacement_code) { Code* replacement_code) {
static const int kInstrSize = Assembler::kInstrSize; static const int kInstrSize = Assembler::kInstrSize;
Address branch_address = pc - 3 * kInstrSize; Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
Address branch_address = pc_immediate_load_address - kInstrSize;
CodePatcher patcher(branch_address, 1); CodePatcher patcher(branch_address, 1);
switch (target_state) { switch (target_state) {
case INTERRUPT: case INTERRUPT:
{
// <decrement profiling counter> // <decrement profiling counter>
// 2a 00 00 01 bpl ok // bpl ok
// e5 9f c? ?? ldr ip, [pc, <interrupt stub address>] // ; load interrupt stub address into ip - either of:
// e1 2f ff 3c blx ip // ldr ip, [pc/pp, <constant pool offset>] | movw ip, <immed low>
// | movt ip, <immed high>
// blx ip
// ok-label // ok-label
patcher.masm()->b(4 * kInstrSize, pl); // Jump offset is 4 instructions.
ASSERT_EQ(kBranchBeforeInterrupt, Memory::int32_at(branch_address)); // Calculate branch offet to the ok-label - this is the difference between
// the branch address and |pc| (which points at <blx ip>) plus one instr.
int branch_offset = pc + kInstrSize - branch_address;
patcher.masm()->b(branch_offset, pl);
break; break;
}
case ON_STACK_REPLACEMENT: case ON_STACK_REPLACEMENT:
case OSR_AFTER_STACK_CHECK: case OSR_AFTER_STACK_CHECK:
// <decrement profiling counter> // <decrement profiling counter>
// e1 a0 00 00 mov r0, r0 (NOP) // mov r0, r0 (NOP)
// e5 9f c? ?? ldr ip, [pc, <on-stack replacement address>] // ; load on-stack replacement address into ip - either of:
// e1 2f ff 3c blx ip // ldr ip, [pc/pp, <constant pool offset>] | movw ip, <immed low>
// | movt ip, <immed high>
// blx ip
// ok-label // ok-label
patcher.masm()->nop(); patcher.masm()->nop();
break; break;
} }
Address pc_immediate_load_address = pc - 2 * kInstrSize;
// Replace the call address. // Replace the call address.
uint32_t interrupt_address_offset = Assembler::set_target_address_at(pc_immediate_load_address, unoptimized_code,
Memory::uint16_at(pc_immediate_load_address) & 0xfff; replacement_code->entry());
Address interrupt_address_pointer = pc + interrupt_address_offset;
Memory::uint32_at(interrupt_address_pointer) =
reinterpret_cast<uint32_t>(replacement_code->entry());
unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
unoptimized_code, pc_immediate_load_address, replacement_code); unoptimized_code, pc_immediate_load_address, replacement_code);
@ -4879,34 +4896,26 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
static const int kInstrSize = Assembler::kInstrSize; static const int kInstrSize = Assembler::kInstrSize;
ASSERT(Memory::int32_at(pc - kInstrSize) == kBlxIp); ASSERT(Memory::int32_at(pc - kInstrSize) == kBlxIp);
Address branch_address = pc - 3 * kInstrSize; Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
Address pc_immediate_load_address = pc - 2 * kInstrSize; Address branch_address = pc_immediate_load_address - kInstrSize;
uint32_t interrupt_address_offset = Address interrupt_address = Assembler::target_address_at(
Memory::uint16_at(pc_immediate_load_address) & 0xfff; pc_immediate_load_address, unoptimized_code);
Address interrupt_address_pointer = pc + interrupt_address_offset;
if (Memory::int32_at(branch_address) == kBranchBeforeInterrupt) { if (Assembler::IsBranch(Assembler::instr_at(branch_address))) {
ASSERT(Memory::uint32_at(interrupt_address_pointer) == ASSERT(interrupt_address ==
reinterpret_cast<uint32_t>( isolate->builtins()->InterruptCheck()->entry());
isolate->builtins()->InterruptCheck()->entry()));
ASSERT(Assembler::IsLdrPcImmediateOffset(
Assembler::instr_at(pc_immediate_load_address)));
return INTERRUPT; return INTERRUPT;
} }
ASSERT(Assembler::IsNop(Assembler::instr_at(branch_address))); ASSERT(Assembler::IsNop(Assembler::instr_at(branch_address)));
ASSERT(Assembler::IsLdrPcImmediateOffset(
Assembler::instr_at(pc_immediate_load_address)));
if (Memory::uint32_at(interrupt_address_pointer) == if (interrupt_address ==
reinterpret_cast<uint32_t>( isolate->builtins()->OnStackReplacement()->entry()) {
isolate->builtins()->OnStackReplacement()->entry())) {
return ON_STACK_REPLACEMENT; return ON_STACK_REPLACEMENT;
} }
ASSERT(Memory::uint32_at(interrupt_address_pointer) == ASSERT(interrupt_address ==
reinterpret_cast<uint32_t>( isolate->builtins()->OsrAfterStackCheck()->entry());
isolate->builtins()->OsrAfterStackCheck()->entry()));
return OSR_AFTER_STACK_CHECK; return OSR_AFTER_STACK_CHECK;
} }