| Index: src/arm/deoptimizer-arm.cc
|
| diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
|
| index 3b50ad4ae4d2bb84c6736cc67487d1ecb8d76b02..a31195c1713a81c2a26b3094a053fadc717ffb17 100644
|
| --- a/src/arm/deoptimizer-arm.cc
|
| +++ b/src/arm/deoptimizer-arm.cc
|
| @@ -117,45 +117,39 @@ void Deoptimizer::DeoptimizeFunctionWithPreparedFunctionList(
|
|
|
| static const int32_t kBranchBeforeInterrupt = 0x5a000004;
|
|
|
| -
|
| -void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
|
| - Address pc_after,
|
| - Code* check_code,
|
| - Code* replacement_code) {
|
| - const int kInstrSize = Assembler::kInstrSize;
|
| - // The back edge bookkeeping code matches the pattern:
|
| - //
|
| - // <decrement profiling counter>
|
| - // 2a 00 00 01 bpl ok
|
| - // e5 9f c? ?? ldr ip, [pc, <stack guard address>]
|
| - // e1 2f ff 3c blx ip
|
| - ASSERT(Memory::int32_at(pc_after - kInstrSize) == kBlxIp);
|
| - ASSERT(Assembler::IsLdrPcImmediateOffset(
|
| - Assembler::instr_at(pc_after - 2 * kInstrSize)));
|
| - ASSERT_EQ(kBranchBeforeInterrupt,
|
| - Memory::int32_at(pc_after - 3 * kInstrSize));
|
| -
|
| - // We patch the code to the following form:
|
| - //
|
| - // <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
|
| - // and overwrite the constant containing the
|
| - // address of the stack check stub.
|
| -
|
| - // Replace conditional jump with NOP.
|
| +// The back edge bookkeeping code matches the pattern:
|
| +//
|
| +// <decrement profiling counter>
|
| +// 2a 00 00 01 bpl ok
|
| +// e5 9f c? ?? ldr ip, [pc, <interrupt stub address>]
|
| +// e1 2f ff 3c blx ip
|
| +// ok-label
|
| +//
|
| +// We patch the code to the following form:
|
| +//
|
| +// <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
|
| +// ok-label
|
| +
|
| +void Deoptimizer::PatchInterruptCodeAt(Code* unoptimized_code,
|
| + Address pc_after,
|
| + Code* interrupt_code,
|
| + Code* replacement_code) {
|
| + ASSERT(!InterruptCodeIsPatched(unoptimized_code,
|
| + pc_after,
|
| + interrupt_code,
|
| + replacement_code));
|
| + static const int kInstrSize = Assembler::kInstrSize;
|
| + // Turn the jump into nops.
|
| CodePatcher patcher(pc_after - 3 * kInstrSize, 1);
|
| patcher.masm()->nop();
|
| -
|
| - // Replace the stack check address in the constant pool
|
| - // with the entry address of the replacement code.
|
| - uint32_t stack_check_address_offset = Memory::uint16_at(pc_after -
|
| + // Replace the call address.
|
| + uint32_t interrupt_address_offset = Memory::uint16_at(pc_after -
|
| 2 * kInstrSize) & 0xfff;
|
| - Address stack_check_address_pointer = pc_after + stack_check_address_offset;
|
| - ASSERT(Memory::uint32_at(stack_check_address_pointer) ==
|
| - reinterpret_cast<uint32_t>(check_code->entry()));
|
| - Memory::uint32_at(stack_check_address_pointer) =
|
| + Address interrupt_address_pointer = pc_after + interrupt_address_offset;
|
| + Memory::uint32_at(interrupt_address_pointer) =
|
| reinterpret_cast<uint32_t>(replacement_code->entry());
|
|
|
| unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
|
| @@ -163,34 +157,61 @@ void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
|
| }
|
|
|
|
|
| -void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code,
|
| - Address pc_after,
|
| - Code* check_code,
|
| - Code* replacement_code) {
|
| - const int kInstrSize = Assembler::kInstrSize;
|
| - ASSERT(Memory::int32_at(pc_after - kInstrSize) == kBlxIp);
|
| - ASSERT(Assembler::IsLdrPcImmediateOffset(
|
| - Assembler::instr_at(pc_after - 2 * kInstrSize)));
|
| -
|
| - // Replace NOP with conditional jump.
|
| +void Deoptimizer::RevertInterruptCodeAt(Code* unoptimized_code,
|
| + Address pc_after,
|
| + Code* interrupt_code,
|
| + Code* replacement_code) {
|
| + ASSERT(InterruptCodeIsPatched(unoptimized_code,
|
| + pc_after,
|
| + interrupt_code,
|
| + replacement_code));
|
| + static const int kInstrSize = Assembler::kInstrSize;
|
| + // Restore the original jump.
|
| CodePatcher patcher(pc_after - 3 * kInstrSize, 1);
|
| - patcher.masm()->b(+16, pl);
|
| - ASSERT_EQ(kBranchBeforeInterrupt,
|
| - Memory::int32_at(pc_after - 3 * kInstrSize));
|
| -
|
| - // Replace the stack check address in the constant pool
|
| - // with the entry address of the replacement code.
|
| - uint32_t stack_check_address_offset = Memory::uint16_at(pc_after -
|
| + patcher.masm()->b(4 * kInstrSize, pl); // ok-label is 4 instructions later.
|
| + // Restore the original call address.
|
| + uint32_t interrupt_address_offset = Memory::uint16_at(pc_after -
|
| 2 * kInstrSize) & 0xfff;
|
| - Address stack_check_address_pointer = pc_after + stack_check_address_offset;
|
| - ASSERT(Memory::uint32_at(stack_check_address_pointer) ==
|
| - reinterpret_cast<uint32_t>(replacement_code->entry()));
|
| - Memory::uint32_at(stack_check_address_pointer) =
|
| - reinterpret_cast<uint32_t>(check_code->entry());
|
| -
|
| - check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
|
| - unoptimized_code, pc_after - 2 * kInstrSize, check_code);
|
| + Address interrupt_address_pointer = pc_after + interrupt_address_offset;
|
| + Memory::uint32_at(interrupt_address_pointer) =
|
| + reinterpret_cast<uint32_t>(interrupt_code->entry());
|
| +
|
| + interrupt_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
|
| + unoptimized_code, pc_after - 2 * kInstrSize, interrupt_code);
|
| +}
|
| +
|
| +
|
| +#ifdef DEBUG
|
| +bool Deoptimizer::InterruptCodeIsPatched(Code* unoptimized_code,
|
| + Address pc_after,
|
| + Code* interrupt_code,
|
| + Code* replacement_code) {
|
| + Address call_target_address = pc_after - kIntSize;
|
| + ASSERT_EQ(kBlxIp, Memory::int32_at(pc_after - kInstrSize));
|
| +
|
| + uint32_t interrupt_address_offset =
|
| + Memory::uint16_at(pc_after - 2 * kInstrSize) & 0xfff;
|
| + Address interrupt_address_pointer = pc_after + interrupt_address_offset;
|
| +
|
| + if (Assembler::IsNop(Assembler::instr_at(pc_after - 3 * kInstrSize))) {
|
| + ASSERT(Assembler::IsLdrPcImmediateOffset(
|
| + Assembler::instr_at(pc_after - 2 * kInstrSize)));
|
| + ASSERT_EQ(kBranchBeforeInterrupt,
|
| + Memory::int32_at(pc_after - 3 * kInstrSize));
|
| + ASSERT_EQ(reinterpret_cast<uint32_t>(replacement_code->entry()),
|
| + Memory::uint32_at(interrupt_address_pointer));
|
| + return true;
|
| + } else {
|
| + ASSERT(Assembler::IsLdrPcImmediateOffset(
|
| + Assembler::instr_at(pc_after - 2 * kInstrSize)));
|
| + ASSERT_EQ(kBranchBeforeInterrupt,
|
| + Memory::int32_at(pc_after - 3 * kInstrSize));
|
| + ASSERT_EQ(reinterpret_cast<uint32_t>(interrupt_code->entry()),
|
| + Memory::uint32_at(interrupt_address_pointer));
|
| + return false;
|
| + }
|
| }
|
| +#endif // DEBUG
|
|
|
|
|
| static int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) {
|
|
|