1 | // Copyright 2016 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "src/compiler/backend/x64/unwinding-info-writer-x64.h" |
6 | #include "src/compiler/backend/instruction.h" |
7 | |
8 | namespace v8 { |
9 | namespace internal { |
10 | namespace compiler { |
11 | |
12 | void UnwindingInfoWriter::BeginInstructionBlock(int pc_offset, |
13 | const InstructionBlock* block) { |
14 | if (!enabled()) return; |
15 | |
16 | block_will_exit_ = false; |
17 | |
18 | DCHECK_LT(block->rpo_number().ToInt(), |
19 | static_cast<int>(block_initial_states_.size())); |
20 | const BlockInitialState* initial_state = |
21 | block_initial_states_[block->rpo_number().ToInt()]; |
22 | if (!initial_state) return; |
23 | if (initial_state->register_ != eh_frame_writer_.base_register() && |
24 | initial_state->offset_ != eh_frame_writer_.base_offset()) { |
25 | eh_frame_writer_.AdvanceLocation(pc_offset); |
26 | eh_frame_writer_.SetBaseAddressRegisterAndOffset(initial_state->register_, |
27 | initial_state->offset_); |
28 | } else if (initial_state->register_ != eh_frame_writer_.base_register()) { |
29 | eh_frame_writer_.AdvanceLocation(pc_offset); |
30 | eh_frame_writer_.SetBaseAddressRegister(initial_state->register_); |
31 | } else if (initial_state->offset_ != eh_frame_writer_.base_offset()) { |
32 | eh_frame_writer_.AdvanceLocation(pc_offset); |
33 | eh_frame_writer_.SetBaseAddressOffset(initial_state->offset_); |
34 | } |
35 | |
36 | tracking_fp_ = initial_state->tracking_fp_; |
37 | } |
38 | |
39 | void UnwindingInfoWriter::EndInstructionBlock(const InstructionBlock* block) { |
40 | if (!enabled() || block_will_exit_) return; |
41 | |
42 | for (const RpoNumber& successor : block->successors()) { |
43 | int successor_index = successor.ToInt(); |
44 | DCHECK_LT(successor_index, static_cast<int>(block_initial_states_.size())); |
45 | const BlockInitialState* existing_state = |
46 | block_initial_states_[successor_index]; |
47 | // If we already had an entry for this BB, check that the values are the |
48 | // same we are trying to insert. |
49 | if (existing_state) { |
50 | DCHECK(existing_state->register_ == eh_frame_writer_.base_register()); |
51 | DCHECK_EQ(existing_state->offset_, eh_frame_writer_.base_offset()); |
52 | DCHECK_EQ(existing_state->tracking_fp_, tracking_fp_); |
53 | } else { |
54 | block_initial_states_[successor_index] = new (zone_) |
55 | BlockInitialState(eh_frame_writer_.base_register(), |
56 | eh_frame_writer_.base_offset(), tracking_fp_); |
57 | } |
58 | } |
59 | } |
60 | |
61 | void UnwindingInfoWriter::MarkFrameConstructed(int pc_base) { |
62 | if (!enabled()) return; |
63 | |
64 | // push rbp |
65 | eh_frame_writer_.AdvanceLocation(pc_base + 1); |
66 | eh_frame_writer_.IncreaseBaseAddressOffset(kInt64Size); |
67 | // <base address> points at the bottom of the current frame on x64 and |
68 | // <base register> is rsp, which points to the top of the frame by definition. |
69 | // Thus, the distance between <base address> and the top is -<base offset>. |
70 | int top_of_stack = -eh_frame_writer_.base_offset(); |
71 | eh_frame_writer_.RecordRegisterSavedToStack(rbp, top_of_stack); |
72 | |
73 | // mov rbp, rsp |
74 | eh_frame_writer_.AdvanceLocation(pc_base + 4); |
75 | eh_frame_writer_.SetBaseAddressRegister(rbp); |
76 | |
77 | tracking_fp_ = true; |
78 | } |
79 | |
80 | void UnwindingInfoWriter::MarkFrameDeconstructed(int pc_base) { |
81 | if (!enabled()) return; |
82 | |
83 | // mov rsp, rbp |
84 | eh_frame_writer_.AdvanceLocation(pc_base + 3); |
85 | eh_frame_writer_.SetBaseAddressRegister(rsp); |
86 | |
87 | // pop rbp |
88 | eh_frame_writer_.AdvanceLocation(pc_base + 4); |
89 | eh_frame_writer_.IncreaseBaseAddressOffset(-kInt64Size); |
90 | |
91 | tracking_fp_ = false; |
92 | } |
93 | |
94 | } // namespace compiler |
95 | } // namespace internal |
96 | } // namespace v8 |
97 | |