Index: src/arm/deoptimizer-arm.cc |
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc |
index caec55affb5d7a60874f368e055d003dbc3e1c4d..9af7a8d190706092f6d2e6e49ac1483343d5bb77 100644 |
--- a/src/arm/deoptimizer-arm.cc |
+++ b/src/arm/deoptimizer-arm.cc |
@@ -124,14 +124,62 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
void Deoptimizer::PatchStackCheckCodeAt(Address pc_after, |
Code* check_code, |
Code* replacement_code) { |
- UNIMPLEMENTED(); |
+ const int kInstrSize = Assembler::kInstrSize; |
+ // The call of the stack guard check has the following form: |
+ // e1 5d 00 0c cmp sp, <limit> |
+ // 2a 00 00 01 bcs ok |
+ // e5 9f c? ?? ldr ip, [pc, <stack guard address>] |
+ // e1 2f ff 3c blx ip |
+ ASSERT(Memory::int32_at(pc_after - kInstrSize) == |
+ (al | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | ip.code())); |
+ ASSERT(Assembler::IsLdrPcImmediateOffset( |
+ Assembler::instr_at(pc_after - 2 * kInstrSize))); |
+ |
+ // We patch the code to the following form: |
+ // e1 5d 00 0c cmp sp, <limit> |
+ // 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. |
+ 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 - |
+ 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) = |
+ reinterpret_cast<uint32_t>(replacement_code->entry()); |
} |
void Deoptimizer::RevertStackCheckCodeAt(Address pc_after, |
Code* check_code, |
Code* replacement_code) { |
- UNIMPLEMENTED(); |
+ const int kInstrSize = Assembler::kInstrSize; |
+ ASSERT(Memory::uint32_at(pc_after - kInstrSize) == 0xe12fff3c); |
+ ASSERT(Memory::uint8_at(pc_after - kInstrSize - 1) == 0xe5); |
+ ASSERT(Memory::uint8_at(pc_after - kInstrSize - 2) == 0x9f); |
+ |
+ // Replace NOP with conditional jump. |
+ CodePatcher patcher(pc_after - 3 * kInstrSize, 1); |
+ patcher.masm()->b(+4, cs); |
+ |
+ // 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 - |
+ 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()); |
} |