| Index: src/arm/full-codegen-arm.cc
|
| diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
|
| index 2eb5ccf974be3810a51f89c244bd661ff3e83ada..aa412fb2a39fe5a41d55d340f353126d03201285 100644
|
| --- a/src/arm/full-codegen-arm.cc
|
| +++ b/src/arm/full-codegen-arm.cc
|
| @@ -4838,7 +4838,19 @@ FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
|
| #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,
|
| @@ -4846,37 +4858,42 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code,
|
| BackEdgeState target_state,
|
| Code* replacement_code) {
|
| 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);
|
| -
|
| switch (target_state) {
|
| case INTERRUPT:
|
| + {
|
| // <decrement profiling counter>
|
| - // 2a 00 00 01 bpl ok
|
| - // e5 9f c? ?? ldr ip, [pc, <interrupt stub address>]
|
| - // e1 2f ff 3c blx ip
|
| + // bpl ok
|
| + // ; load interrupt stub address into ip - either of:
|
| + // ldr ip, [pc/pp, <constant pool offset>] | movw ip, <immed low>
|
| + // | movt ip, <immed high>
|
| + // blx ip
|
| // 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;
|
| + }
|
| case ON_STACK_REPLACEMENT:
|
| case OSR_AFTER_STACK_CHECK:
|
| // <decrement profiling counter>
|
| - // e1 a0 00 00 mov r0, r0 (NOP)
|
| - // e5 9f c? ?? ldr ip, [pc, <on-stack replacement address>]
|
| - // e1 2f ff 3c blx ip
|
| + // mov r0, r0 (NOP)
|
| + // ; load on-stack replacement address into ip - either of:
|
| + // ldr ip, [pc/pp, <constant pool offset>] | movw ip, <immed low>
|
| + // | movt ip, <immed high>
|
| + // blx ip
|
| // ok-label
|
| patcher.masm()->nop();
|
| break;
|
| }
|
|
|
| - Address pc_immediate_load_address = pc - 2 * kInstrSize;
|
| // Replace the call address.
|
| - uint32_t interrupt_address_offset =
|
| - Memory::uint16_at(pc_immediate_load_address) & 0xfff;
|
| - Address interrupt_address_pointer = pc + interrupt_address_offset;
|
| - Memory::uint32_at(interrupt_address_pointer) =
|
| - reinterpret_cast<uint32_t>(replacement_code->entry());
|
| + Assembler::set_target_address_at(pc_immediate_load_address, unoptimized_code,
|
| + replacement_code->entry());
|
|
|
| unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
|
| unoptimized_code, pc_immediate_load_address, replacement_code);
|
| @@ -4890,34 +4907,26 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
|
| static const int kInstrSize = Assembler::kInstrSize;
|
| ASSERT(Memory::int32_at(pc - kInstrSize) == kBlxIp);
|
|
|
| - Address branch_address = pc - 3 * kInstrSize;
|
| - Address pc_immediate_load_address = pc - 2 * kInstrSize;
|
| - uint32_t interrupt_address_offset =
|
| - Memory::uint16_at(pc_immediate_load_address) & 0xfff;
|
| - Address interrupt_address_pointer = pc + interrupt_address_offset;
|
| -
|
| - if (Memory::int32_at(branch_address) == kBranchBeforeInterrupt) {
|
| - ASSERT(Memory::uint32_at(interrupt_address_pointer) ==
|
| - reinterpret_cast<uint32_t>(
|
| - isolate->builtins()->InterruptCheck()->entry()));
|
| - ASSERT(Assembler::IsLdrPcImmediateOffset(
|
| - Assembler::instr_at(pc_immediate_load_address)));
|
| + Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc);
|
| + Address branch_address = pc_immediate_load_address - kInstrSize;
|
| + Address interrupt_address = Assembler::target_address_at(
|
| + pc_immediate_load_address, unoptimized_code);
|
| +
|
| + if (Assembler::IsBranch(Assembler::instr_at(branch_address))) {
|
| + ASSERT(interrupt_address ==
|
| + isolate->builtins()->InterruptCheck()->entry());
|
| return INTERRUPT;
|
| }
|
|
|
| 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) ==
|
| - reinterpret_cast<uint32_t>(
|
| - isolate->builtins()->OnStackReplacement()->entry())) {
|
| + if (interrupt_address ==
|
| + isolate->builtins()->OnStackReplacement()->entry()) {
|
| return ON_STACK_REPLACEMENT;
|
| }
|
|
|
| - ASSERT(Memory::uint32_at(interrupt_address_pointer) ==
|
| - reinterpret_cast<uint32_t>(
|
| - isolate->builtins()->OsrAfterStackCheck()->entry()));
|
| + ASSERT(interrupt_address ==
|
| + isolate->builtins()->OsrAfterStackCheck()->entry());
|
| return OSR_AFTER_STACK_CHECK;
|
| }
|
|
|
|
|