| // Copyright 2016 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/compiler/backend/x64/unwinding-info-writer-x64.h" |
| #include "src/compiler/backend/instruction.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace compiler { |
| |
| void UnwindingInfoWriter::BeginInstructionBlock(int pc_offset, |
| const InstructionBlock* block) { |
| if (!enabled()) return; |
| |
| block_will_exit_ = false; |
| |
| DCHECK_LT(block->rpo_number().ToInt(), |
| static_cast<int>(block_initial_states_.size())); |
| const BlockInitialState* initial_state = |
| block_initial_states_[block->rpo_number().ToInt()]; |
| if (!initial_state) return; |
| if (initial_state->register_ != eh_frame_writer_.base_register() && |
| initial_state->offset_ != eh_frame_writer_.base_offset()) { |
| eh_frame_writer_.AdvanceLocation(pc_offset); |
| eh_frame_writer_.SetBaseAddressRegisterAndOffset(initial_state->register_, |
| initial_state->offset_); |
| } else if (initial_state->register_ != eh_frame_writer_.base_register()) { |
| eh_frame_writer_.AdvanceLocation(pc_offset); |
| eh_frame_writer_.SetBaseAddressRegister(initial_state->register_); |
| } else if (initial_state->offset_ != eh_frame_writer_.base_offset()) { |
| eh_frame_writer_.AdvanceLocation(pc_offset); |
| eh_frame_writer_.SetBaseAddressOffset(initial_state->offset_); |
| } |
| |
| tracking_fp_ = initial_state->tracking_fp_; |
| } |
| |
| void UnwindingInfoWriter::EndInstructionBlock(const InstructionBlock* block) { |
| if (!enabled() || block_will_exit_) return; |
| |
| for (const RpoNumber& successor : block->successors()) { |
| int successor_index = successor.ToInt(); |
| DCHECK_LT(successor_index, static_cast<int>(block_initial_states_.size())); |
| const BlockInitialState* existing_state = |
| block_initial_states_[successor_index]; |
| // If we already had an entry for this BB, check that the values are the |
| // same we are trying to insert. |
| if (existing_state) { |
| DCHECK(existing_state->register_ == eh_frame_writer_.base_register()); |
| DCHECK_EQ(existing_state->offset_, eh_frame_writer_.base_offset()); |
| DCHECK_EQ(existing_state->tracking_fp_, tracking_fp_); |
| } else { |
| block_initial_states_[successor_index] = new (zone_) |
| BlockInitialState(eh_frame_writer_.base_register(), |
| eh_frame_writer_.base_offset(), tracking_fp_); |
| } |
| } |
| } |
| |
| void UnwindingInfoWriter::MarkFrameConstructed(int pc_base) { |
| if (!enabled()) return; |
| |
| // push rbp |
| eh_frame_writer_.AdvanceLocation(pc_base + 1); |
| eh_frame_writer_.IncreaseBaseAddressOffset(kInt64Size); |
| // <base address> points at the bottom of the current frame on x64 and |
| // <base register> is rsp, which points to the top of the frame by definition. |
| // Thus, the distance between <base address> and the top is -<base offset>. |
| int top_of_stack = -eh_frame_writer_.base_offset(); |
| eh_frame_writer_.RecordRegisterSavedToStack(rbp, top_of_stack); |
| |
| // mov rbp, rsp |
| eh_frame_writer_.AdvanceLocation(pc_base + 4); |
| eh_frame_writer_.SetBaseAddressRegister(rbp); |
| |
| tracking_fp_ = true; |
| } |
| |
| void UnwindingInfoWriter::MarkFrameDeconstructed(int pc_base) { |
| if (!enabled()) return; |
| |
| // mov rsp, rbp |
| eh_frame_writer_.AdvanceLocation(pc_base + 3); |
| eh_frame_writer_.SetBaseAddressRegister(rsp); |
| |
| // pop rbp |
| eh_frame_writer_.AdvanceLocation(pc_base + 4); |
| eh_frame_writer_.IncreaseBaseAddressOffset(-kInt64Size); |
| |
| tracking_fp_ = false; |
| } |
| |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |