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:
parent
6c01c3fd56
commit
be0bc25bbb
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user