From be0bc25bbb5e0b0faa00849b3cb348222396b834 Mon Sep 17 00:00:00 2001 From: "rmcilroy@chromium.org" Date: Tue, 18 Mar 2014 11:36:19 +0000 Subject: [PATCH] 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 --- src/arm/full-codegen-arm.cc | 83 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 7a2fb6d..ef5aee6 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -4827,7 +4827,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, @@ -4835,37 +4847,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: + { // - // 2a 00 00 01 bpl ok - // e5 9f c? ?? ldr ip, [pc, ] - // e1 2f ff 3c blx ip + // bpl ok + // ; load interrupt stub address into ip - either of: + // ldr ip, [pc/pp, ] | movw ip, + // | movt ip, + // 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 ) 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: // - // e1 a0 00 00 mov r0, r0 (NOP) - // e5 9f c? ?? ldr ip, [pc, ] - // e1 2f ff 3c blx ip + // mov r0, r0 (NOP) + // ; load on-stack replacement address into ip - either of: + // ldr ip, [pc/pp, ] | movw ip, + // | movt ip, + // 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(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); @@ -4879,34 +4896,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( - 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( - isolate->builtins()->OnStackReplacement()->entry())) { + if (interrupt_address == + isolate->builtins()->OnStackReplacement()->entry()) { return ON_STACK_REPLACEMENT; } - ASSERT(Memory::uint32_at(interrupt_address_pointer) == - reinterpret_cast( - isolate->builtins()->OsrAfterStackCheck()->entry())); + ASSERT(interrupt_address == + isolate->builtins()->OsrAfterStackCheck()->entry()); return OSR_AFTER_STACK_CHECK; } -- 2.7.4