blob: e79dcff09a2ccb9504cac4fc3cefc496456d5527 [file] [log] [blame]
Ben Murdochb0fe1622011-05-05 13:52:32 +01001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "safepoint-table.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010029
Ben Murdochb0fe1622011-05-05 13:52:32 +010030#include "disasm.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010031#include "macro-assembler.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010032
33namespace v8 {
34namespace internal {
35
Ben Murdochb8e0da22011-05-16 14:20:40 +010036
37bool SafepointEntry::HasRegisters() const {
38 ASSERT(is_valid());
39 ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
40 const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
41 for (int i = 0; i < num_reg_bytes; i++) {
42 if (bits_[i] != SafepointTable::kNoRegisters) return true;
43 }
44 return false;
45}
46
47
48bool SafepointEntry::HasRegisterAt(int reg_index) const {
49 ASSERT(is_valid());
50 ASSERT(reg_index >= 0 && reg_index < kNumSafepointRegisters);
51 int byte_index = reg_index >> kBitsPerByteLog2;
52 int bit_index = reg_index & (kBitsPerByte - 1);
53 return (bits_[byte_index] & (1 << bit_index)) != 0;
54}
55
56
Ben Murdochb0fe1622011-05-05 13:52:32 +010057SafepointTable::SafepointTable(Code* code) {
58 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
59 code_ = code;
60 Address header = code->instruction_start() + code->safepoint_table_start();
61 length_ = Memory::uint32_at(header + kLengthOffset);
62 entry_size_ = Memory::uint32_at(header + kEntrySizeOffset);
63 pc_and_deoptimization_indexes_ = header + kHeaderSize;
64 entries_ = pc_and_deoptimization_indexes_ +
65 (length_ * kPcAndDeoptimizationIndexSize);
66 ASSERT(entry_size_ > 0);
Ben Murdochb8e0da22011-05-16 14:20:40 +010067 ASSERT_EQ(SafepointEntry::DeoptimizationIndexField::max(),
68 Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +010069}
70
71
Ben Murdochb8e0da22011-05-16 14:20:40 +010072SafepointEntry SafepointTable::FindEntry(Address pc) const {
73 unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start());
74 for (unsigned i = 0; i < length(); i++) {
75 // TODO(kasperl): Replace the linear search with binary search.
76 if (GetPcOffset(i) == pc_offset) return GetEntry(i);
Ben Murdochb0fe1622011-05-05 13:52:32 +010077 }
Ben Murdochb8e0da22011-05-16 14:20:40 +010078 return SafepointEntry();
Ben Murdochb0fe1622011-05-05 13:52:32 +010079}
80
81
82void SafepointTable::PrintEntry(unsigned index) const {
83 disasm::NameConverter converter;
Ben Murdochb8e0da22011-05-16 14:20:40 +010084 SafepointEntry entry = GetEntry(index);
85 uint8_t* bits = entry.bits();
Ben Murdochb0fe1622011-05-05 13:52:32 +010086
87 // Print the stack slot bits.
88 if (entry_size_ > 0) {
89 ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
90 const int first = kNumSafepointRegisters >> kBitsPerByteLog2;
91 int last = entry_size_ - 1;
Ben Murdochb8e0da22011-05-16 14:20:40 +010092 for (int i = first; i < last; i++) PrintBits(bits[i], kBitsPerByte);
Ben Murdochb0fe1622011-05-05 13:52:32 +010093 int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte);
Ben Murdochb8e0da22011-05-16 14:20:40 +010094 PrintBits(bits[last], last_bits);
Ben Murdochb0fe1622011-05-05 13:52:32 +010095
96 // Print the registers (if any).
Ben Murdochb8e0da22011-05-16 14:20:40 +010097 if (!entry.HasRegisters()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +010098 for (int j = 0; j < kNumSafepointRegisters; j++) {
Ben Murdochb8e0da22011-05-16 14:20:40 +010099 if (entry.HasRegisterAt(j)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100100 PrintF(" | %s", converter.NameOfCPURegister(j));
101 }
102 }
103 }
104}
105
106
107void SafepointTable::PrintBits(uint8_t byte, int digits) {
108 ASSERT(digits >= 0 && digits <= kBitsPerByte);
109 for (int i = 0; i < digits; i++) {
110 PrintF("%c", ((byte & (1 << i)) == 0) ? '0' : '1');
111 }
112}
113
114
Ben Murdochb8e0da22011-05-16 14:20:40 +0100115void Safepoint::DefinePointerRegister(Register reg) {
116 registers_->Add(reg.code());
117}
118
119
Ben Murdochb0fe1622011-05-05 13:52:32 +0100120Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler,
121 int deoptimization_index) {
122 ASSERT(deoptimization_index != -1);
123 DeoptimizationInfo pc_and_deoptimization_index;
124 pc_and_deoptimization_index.pc = assembler->pc_offset();
125 pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
126 pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100127 pc_and_deoptimization_index.arguments = 0;
128 pc_and_deoptimization_index.has_doubles = false;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100129 deoptimization_info_.Add(pc_and_deoptimization_index);
130 indexes_.Add(new ZoneList<int>(8));
131 registers_.Add(NULL);
132 return Safepoint(indexes_.last(), registers_.last());
133}
134
135
136Safepoint SafepointTableBuilder::DefineSafepointWithRegisters(
137 Assembler* assembler, int arguments, int deoptimization_index) {
138 ASSERT(deoptimization_index != -1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100139 ASSERT(arguments >= 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100140 DeoptimizationInfo pc_and_deoptimization_index;
141 pc_and_deoptimization_index.pc = assembler->pc_offset();
142 pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
143 pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100144 pc_and_deoptimization_index.arguments = arguments;
145 pc_and_deoptimization_index.has_doubles = false;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100146 deoptimization_info_.Add(pc_and_deoptimization_index);
147 indexes_.Add(new ZoneList<int>(8));
148 registers_.Add(new ZoneList<int>(4));
149 return Safepoint(indexes_.last(), registers_.last());
150}
151
152
Ben Murdochb8e0da22011-05-16 14:20:40 +0100153Safepoint SafepointTableBuilder::DefineSafepointWithRegistersAndDoubles(
154 Assembler* assembler, int arguments, int deoptimization_index) {
155 ASSERT(deoptimization_index != -1);
156 ASSERT(arguments >= 0);
157 DeoptimizationInfo pc_and_deoptimization_index;
158 pc_and_deoptimization_index.pc = assembler->pc_offset();
159 pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
160 pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
161 pc_and_deoptimization_index.arguments = arguments;
162 pc_and_deoptimization_index.has_doubles = true;
163 deoptimization_info_.Add(pc_and_deoptimization_index);
164 indexes_.Add(new ZoneList<int>(8));
165 registers_.Add(new ZoneList<int>(4));
166 return Safepoint(indexes_.last(), registers_.last());
167}
168
Ben Murdochb0fe1622011-05-05 13:52:32 +0100169unsigned SafepointTableBuilder::GetCodeOffset() const {
170 ASSERT(emitted_);
171 return offset_;
172}
173
174
175void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
176 // Make sure the safepoint table is properly aligned. Pad with nops.
177 assembler->Align(kIntSize);
178 assembler->RecordComment(";;; Safepoint table.");
179 offset_ = assembler->pc_offset();
180
181 // Take the register bits into account.
182 bits_per_entry += kNumSafepointRegisters;
183
184 // Compute the number of bytes per safepoint entry.
185 int bytes_per_entry =
186 RoundUp(bits_per_entry, kBitsPerByte) >> kBitsPerByteLog2;
187
188 // Emit the table header.
189 int length = deoptimization_info_.length();
190 assembler->dd(length);
191 assembler->dd(bytes_per_entry);
192
193 // Emit sorted table of pc offsets together with deoptimization indexes and
194 // pc after gap information.
195 for (int i = 0; i < length; i++) {
196 assembler->dd(deoptimization_info_[i].pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100197 assembler->dd(EncodeExceptPC(deoptimization_info_[i]));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100198 }
199
200 // Emit table of bitmaps.
201 ZoneList<uint8_t> bits(bytes_per_entry);
202 for (int i = 0; i < length; i++) {
203 ZoneList<int>* indexes = indexes_[i];
204 ZoneList<int>* registers = registers_[i];
205 bits.Clear();
206 bits.AddBlock(0, bytes_per_entry);
207
208 // Run through the registers (if any).
209 ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
210 if (registers == NULL) {
211 const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
212 for (int j = 0; j < num_reg_bytes; j++) {
213 bits[j] = SafepointTable::kNoRegisters;
214 }
215 } else {
216 for (int j = 0; j < registers->length(); j++) {
217 int index = registers->at(j);
218 ASSERT(index >= 0 && index < kNumSafepointRegisters);
219 int byte_index = index >> kBitsPerByteLog2;
220 int bit_index = index & (kBitsPerByte - 1);
221 bits[byte_index] |= (1 << bit_index);
222 }
223 }
224
225 // Run through the indexes and build a bitmap.
226 for (int j = 0; j < indexes->length(); j++) {
227 int index = bits_per_entry - 1 - indexes->at(j);
228 int byte_index = index >> kBitsPerByteLog2;
229 int bit_index = index & (kBitsPerByte - 1);
230 bits[byte_index] |= (1U << bit_index);
231 }
232
233 // Emit the bitmap for the current entry.
234 for (int k = 0; k < bytes_per_entry; k++) {
235 assembler->db(bits[k]);
236 }
237 }
238 emitted_ = true;
239}
240
241
Ben Murdochb8e0da22011-05-16 14:20:40 +0100242uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100243 unsigned index = info.deoptimization_index;
244 unsigned gap_size = info.pc_after_gap - info.pc;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100245 uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
246 encoding |= SafepointEntry::GapCodeSizeField::encode(gap_size);
247 encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
248 encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100249 return encoding;
250}
251
252
253} } // namespace v8::internal