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