Line data Source code
1 : // Copyright 2011 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/safepoint-table.h"
6 :
7 : #include "src/assembler-inl.h"
8 : #include "src/deoptimizer.h"
9 : #include "src/disasm.h"
10 : #include "src/frames-inl.h"
11 : #include "src/macro-assembler.h"
12 : #include "src/ostreams.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 :
18 1665019 : bool SafepointEntry::HasRegisters() const {
19 : DCHECK(is_valid());
20 : DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte));
21 : const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
22 4964817 : for (int i = 0; i < num_reg_bytes; i++) {
23 3314918 : if (bits_[i] != SafepointTable::kNoRegisters) return true;
24 : }
25 : return false;
26 : }
27 :
28 :
29 241920 : bool SafepointEntry::HasRegisterAt(int reg_index) const {
30 : DCHECK(is_valid());
31 : DCHECK(reg_index >= 0 && reg_index < kNumSafepointRegisters);
32 241920 : int byte_index = reg_index >> kBitsPerByteLog2;
33 241920 : int bit_index = reg_index & (kBitsPerByte - 1);
34 241920 : return (bits_[byte_index] & (1 << bit_index)) != 0;
35 : }
36 :
37 :
38 1732479 : SafepointTable::SafepointTable(Code* code) {
39 : DCHECK(code->is_crankshafted());
40 1732479 : code_ = code;
41 3464958 : Address header = code->instruction_start() + code->safepoint_table_offset();
42 1732479 : length_ = Memory::uint32_at(header + kLengthOffset);
43 1732479 : entry_size_ = Memory::uint32_at(header + kEntrySizeOffset);
44 1732479 : pc_and_deoptimization_indexes_ = header + kHeaderSize;
45 1732479 : entries_ = pc_and_deoptimization_indexes_ +
46 3464958 : (length_ * kPcAndDeoptimizationIndexSize);
47 : DCHECK(entry_size_ > 0);
48 : STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax ==
49 : Safepoint::kNoDeoptimizationIndex);
50 1732479 : }
51 :
52 :
53 27605757 : SafepointEntry SafepointTable::FindEntry(Address pc) const {
54 1732479 : unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start());
55 51746556 : for (unsigned i = 0; i < length(); i++) {
56 : // TODO(kasperl): Replace the linear search with binary search.
57 25873278 : if (GetPcOffset(i) == pc_offset) return GetEntry(i);
58 : }
59 0 : return SafepointEntry();
60 : }
61 :
62 :
63 0 : void SafepointTable::PrintEntry(unsigned index,
64 : std::ostream& os) const { // NOLINT
65 : disasm::NameConverter converter;
66 : SafepointEntry entry = GetEntry(index);
67 : uint8_t* bits = entry.bits();
68 :
69 : // Print the stack slot bits.
70 0 : if (entry_size_ > 0) {
71 : DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte));
72 : const int first = kNumSafepointRegisters >> kBitsPerByteLog2;
73 0 : int last = entry_size_ - 1;
74 0 : for (int i = first; i < last; i++) PrintBits(os, bits[i], kBitsPerByte);
75 0 : int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte);
76 0 : PrintBits(os, bits[last], last_bits);
77 :
78 : // Print the registers (if any).
79 0 : if (!entry.HasRegisters()) return;
80 0 : for (int j = 0; j < kNumSafepointRegisters; j++) {
81 0 : if (entry.HasRegisterAt(j)) {
82 0 : os << " | " << converter.NameOfCPURegister(j);
83 : }
84 : }
85 : }
86 : }
87 :
88 :
89 0 : void SafepointTable::PrintBits(std::ostream& os, // NOLINT
90 : uint8_t byte, int digits) {
91 : DCHECK(digits >= 0 && digits <= kBitsPerByte);
92 0 : for (int i = 0; i < digits; i++) {
93 0 : os << (((byte & (1 << i)) == 0) ? "0" : "1");
94 : }
95 0 : }
96 :
97 :
98 159432 : void Safepoint::DefinePointerRegister(Register reg, Zone* zone) {
99 318864 : registers_->Add(reg.code(), zone);
100 159432 : }
101 :
102 :
103 5154056 : Safepoint SafepointTableBuilder::DefineSafepoint(
104 : Assembler* assembler,
105 : Safepoint::Kind kind,
106 : int arguments,
107 : Safepoint::DeoptMode deopt_mode) {
108 : DCHECK(arguments >= 0);
109 : DeoptimizationInfo info;
110 10308112 : info.pc = assembler->pc_offset();
111 5154056 : info.arguments = arguments;
112 5154056 : info.has_doubles = (kind & Safepoint::kWithDoubles);
113 5154056 : deoptimization_info_.Add(info, zone_);
114 10308118 : deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex, zone_);
115 5154059 : if (deopt_mode == Safepoint::kNoLazyDeopt) {
116 1049679 : last_lazy_safepoint_ = deopt_index_list_.length();
117 : }
118 10308118 : indexes_.Add(new(zone_) ZoneList<int>(8, zone_), zone_);
119 5154056 : registers_.Add((kind & Safepoint::kWithRegisters)
120 84995 : ? new(zone_) ZoneList<int>(4, zone_)
121 : : NULL,
122 10308112 : zone_);
123 10308110 : return Safepoint(indexes_.last(), registers_.last());
124 : }
125 :
126 :
127 4106719 : void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) {
128 20524135 : while (last_lazy_safepoint_ < deopt_index_list_.length()) {
129 16412686 : deopt_index_list_[last_lazy_safepoint_++] = index;
130 : }
131 4106719 : }
132 :
133 1191440 : unsigned SafepointTableBuilder::GetCodeOffset() const {
134 : DCHECK(emitted_);
135 1191440 : return offset_;
136 : }
137 :
138 :
139 1191440 : void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
140 : // Make sure the safepoint table is properly aligned. Pad with nops.
141 1191440 : assembler->Align(kIntSize);
142 1191439 : assembler->RecordComment(";;; Safepoint table.");
143 2382880 : offset_ = assembler->pc_offset();
144 :
145 : // Take the register bits into account.
146 1191440 : bits_per_entry += kNumSafepointRegisters;
147 :
148 : // Compute the number of bytes per safepoint entry.
149 : int bytes_per_entry =
150 1191440 : RoundUp(bits_per_entry, kBitsPerByte) >> kBitsPerByteLog2;
151 :
152 : // Emit the table header.
153 11499232 : int length = deoptimization_info_.length();
154 1191440 : assembler->dd(length);
155 1191438 : assembler->dd(bytes_per_entry);
156 :
157 : // Emit sorted table of pc offsets together with deoptimization indexes.
158 6345335 : for (int i = 0; i < length; i++) {
159 5153895 : assembler->dd(deoptimization_info_[i].pc);
160 : assembler->dd(EncodeExceptPC(deoptimization_info_[i],
161 15461691 : deopt_index_list_[i]));
162 : }
163 :
164 : // Emit table of bitmaps.
165 1191440 : ZoneList<uint8_t> bits(bytes_per_entry, zone_);
166 6345339 : for (int i = 0; i < length; i++) {
167 10307798 : ZoneList<int>* indexes = indexes_[i];
168 10307798 : ZoneList<int>* registers = registers_[i];
169 : bits.Clear();
170 5153899 : bits.AddBlock(0, bytes_per_entry, zone_);
171 :
172 : // Run through the registers (if any).
173 : DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte));
174 5153898 : if (registers == NULL) {
175 : const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
176 10137806 : for (int j = 0; j < num_reg_bytes; j++) {
177 20275612 : bits[j] = SafepointTable::kNoRegisters;
178 : }
179 : } else {
180 403860 : for (int j = 0; j < registers->length(); j++) {
181 403860 : int index = registers->at(j);
182 : DCHECK(index >= 0 && index < kNumSafepointRegisters);
183 159432 : int byte_index = index >> kBitsPerByteLog2;
184 159432 : int bit_index = index & (kBitsPerByte - 1);
185 318864 : bits[byte_index] |= (1 << bit_index);
186 : }
187 : }
188 :
189 : // Run through the indexes and build a bitmap.
190 26517032 : for (int j = 0; j < indexes->length(); j++) {
191 37198599 : int index = bits_per_entry - 1 - indexes->at(j);
192 10681567 : int byte_index = index >> kBitsPerByteLog2;
193 10681567 : int bit_index = index & (kBitsPerByte - 1);
194 21363134 : bits[byte_index] |= (1U << bit_index);
195 : }
196 :
197 : // Emit the bitmap for the current entry.
198 37967845 : for (int k = 0; k < bytes_per_entry; k++) {
199 75935688 : assembler->db(bits[k]);
200 : }
201 : }
202 1191440 : emitted_ = true;
203 1191440 : }
204 :
205 :
206 0 : uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info,
207 : unsigned index) {
208 : uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
209 10307794 : encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
210 10307794 : encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles);
211 0 : return encoding;
212 : }
213 :
214 :
215 : } // namespace internal
216 : } // namespace v8
|