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 1672122 : bool SafepointEntry::HasRegisters() const {
19 : DCHECK(is_valid());
20 : DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte));
21 : const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
22 4986064 : for (int i = 0; i < num_reg_bytes; i++) {
23 3329093 : if (bits_[i] != SafepointTable::kNoRegisters) return true;
24 : }
25 : return false;
26 : }
27 :
28 :
29 242416 : bool SafepointEntry::HasRegisterAt(int reg_index) const {
30 : DCHECK(is_valid());
31 : DCHECK(reg_index >= 0 && reg_index < kNumSafepointRegisters);
32 242416 : int byte_index = reg_index >> kBitsPerByteLog2;
33 242416 : int bit_index = reg_index & (kBitsPerByte - 1);
34 242416 : return (bits_[byte_index] & (1 << bit_index)) != 0;
35 : }
36 :
37 :
38 1736619 : SafepointTable::SafepointTable(Code* code) {
39 : DCHECK(code->is_crankshafted());
40 1736619 : code_ = code;
41 3473238 : Address header = code->instruction_start() + code->safepoint_table_offset();
42 1736619 : length_ = Memory::uint32_at(header + kLengthOffset);
43 1736619 : entry_size_ = Memory::uint32_at(header + kEntrySizeOffset);
44 1736619 : pc_and_deoptimization_indexes_ = header + kHeaderSize;
45 1736619 : entries_ = pc_and_deoptimization_indexes_ +
46 3473238 : (length_ * kPcAndDeoptimizationIndexSize);
47 : DCHECK(entry_size_ > 0);
48 : STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax ==
49 : Safepoint::kNoDeoptimizationIndex);
50 1736619 : }
51 :
52 :
53 27661641 : SafepointEntry SafepointTable::FindEntry(Address pc) const {
54 1736619 : unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start());
55 51850044 : for (unsigned i = 0; i < length(); i++) {
56 : // TODO(kasperl): Replace the linear search with binary search.
57 25925022 : 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 157635 : void Safepoint::DefinePointerRegister(Register reg, Zone* zone) {
99 315270 : registers_->Add(reg.code(), zone);
100 157635 : }
101 :
102 :
103 5150854 : 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 10301708 : info.pc = assembler->pc_offset();
111 5150854 : info.arguments = arguments;
112 5150854 : info.has_doubles = (kind & Safepoint::kWithDoubles);
113 5150854 : deoptimization_info_.Add(info, zone_);
114 10301725 : deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex, zone_);
115 5150861 : if (deopt_mode == Safepoint::kNoLazyDeopt) {
116 1050191 : last_lazy_safepoint_ = deopt_index_list_.length();
117 : }
118 10301726 : indexes_.Add(new(zone_) ZoneList<int>(8, zone_), zone_);
119 5150864 : registers_.Add((kind & Safepoint::kWithRegisters)
120 84601 : ? new(zone_) ZoneList<int>(4, zone_)
121 : : NULL,
122 10301728 : zone_);
123 10301718 : return Safepoint(indexes_.last(), registers_.last());
124 : }
125 :
126 :
127 4103040 : void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) {
128 20505706 : while (last_lazy_safepoint_ < deopt_index_list_.length()) {
129 16397919 : deopt_index_list_[last_lazy_safepoint_++] = index;
130 : }
131 4103040 : }
132 :
133 1190793 : unsigned SafepointTableBuilder::GetCodeOffset() const {
134 : DCHECK(emitted_);
135 1190793 : return offset_;
136 : }
137 :
138 :
139 1190793 : void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
140 : // Make sure the safepoint table is properly aligned. Pad with nops.
141 1190793 : assembler->Align(kIntSize);
142 1190792 : assembler->RecordComment(";;; Safepoint table.");
143 2381582 : offset_ = assembler->pc_offset();
144 :
145 : // Take the register bits into account.
146 1190791 : bits_per_entry += kNumSafepointRegisters;
147 :
148 : // Compute the number of bytes per safepoint entry.
149 : int bytes_per_entry =
150 1190791 : RoundUp(bits_per_entry, kBitsPerByte) >> kBitsPerByteLog2;
151 :
152 : // Emit the table header.
153 11492283 : int length = deoptimization_info_.length();
154 1190791 : assembler->dd(length);
155 1190792 : assembler->dd(bytes_per_entry);
156 :
157 : // Emit sorted table of pc offsets together with deoptimization indexes.
158 6341538 : for (int i = 0; i < length; i++) {
159 5150745 : assembler->dd(deoptimization_info_[i].pc);
160 : assembler->dd(EncodeExceptPC(deoptimization_info_[i],
161 15452241 : deopt_index_list_[i]));
162 : }
163 :
164 : // Emit table of bitmaps.
165 1190793 : ZoneList<uint8_t> bits(bytes_per_entry, zone_);
166 6341541 : for (int i = 0; i < length; i++) {
167 10301496 : ZoneList<int>* indexes = indexes_[i];
168 10301496 : ZoneList<int>* registers = registers_[i];
169 : bits.Clear();
170 5150748 : bits.AddBlock(0, bytes_per_entry, zone_);
171 :
172 : // Run through the registers (if any).
173 : DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte));
174 5150748 : if (registers == NULL) {
175 : const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
176 10132296 : for (int j = 0; j < num_reg_bytes; j++) {
177 20264592 : bits[j] = SafepointTable::kNoRegisters;
178 : }
179 : } else {
180 399870 : for (int j = 0; j < registers->length(); j++) {
181 399870 : int index = registers->at(j);
182 : DCHECK(index >= 0 && index < kNumSafepointRegisters);
183 157635 : int byte_index = index >> kBitsPerByteLog2;
184 157635 : int bit_index = index & (kBitsPerByte - 1);
185 315270 : bits[byte_index] |= (1 << bit_index);
186 : }
187 : }
188 :
189 : // Run through the indexes and build a bitmap.
190 26510942 : for (int j = 0; j < indexes->length(); j++) {
191 37191039 : int index = bits_per_entry - 1 - indexes->at(j);
192 10680097 : int byte_index = index >> kBitsPerByteLog2;
193 10680097 : int bit_index = index & (kBitsPerByte - 1);
194 21360194 : bits[byte_index] |= (1U << bit_index);
195 : }
196 :
197 : // Emit the bitmap for the current entry.
198 37967118 : for (int k = 0; k < bytes_per_entry; k++) {
199 75934234 : assembler->db(bits[k]);
200 : }
201 : }
202 1190793 : emitted_ = true;
203 1190793 : }
204 :
205 :
206 0 : uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info,
207 : unsigned index) {
208 : uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
209 10301494 : encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
210 10301494 : encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles);
211 0 : return encoding;
212 : }
213 :
214 :
215 : } // namespace internal
216 : } // namespace v8
|