| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/safepoint-table.h" | 7 #include "src/safepoint-table.h" |
| 8 | 8 |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
| 11 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
| 12 #include "src/ostreams.h" | 12 #include "src/ostreams.h" |
| 13 #include "src/zone-inl.h" | 13 #include "src/zone-inl.h" |
| 14 | 14 |
| 15 namespace v8 { | 15 namespace v8 { |
| 16 namespace internal { | 16 namespace internal { |
| 17 | 17 |
| 18 | 18 |
| 19 bool SafepointEntry::HasRegisters() const { | 19 bool SafepointEntry::HasRegisters() const { |
| 20 ASSERT(is_valid()); | 20 DCHECK(is_valid()); |
| 21 ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte)); | 21 DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte)); |
| 22 const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2; | 22 const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2; |
| 23 for (int i = 0; i < num_reg_bytes; i++) { | 23 for (int i = 0; i < num_reg_bytes; i++) { |
| 24 if (bits_[i] != SafepointTable::kNoRegisters) return true; | 24 if (bits_[i] != SafepointTable::kNoRegisters) return true; |
| 25 } | 25 } |
| 26 return false; | 26 return false; |
| 27 } | 27 } |
| 28 | 28 |
| 29 | 29 |
| 30 bool SafepointEntry::HasRegisterAt(int reg_index) const { | 30 bool SafepointEntry::HasRegisterAt(int reg_index) const { |
| 31 ASSERT(is_valid()); | 31 DCHECK(is_valid()); |
| 32 ASSERT(reg_index >= 0 && reg_index < kNumSafepointRegisters); | 32 DCHECK(reg_index >= 0 && reg_index < kNumSafepointRegisters); |
| 33 int byte_index = reg_index >> kBitsPerByteLog2; | 33 int byte_index = reg_index >> kBitsPerByteLog2; |
| 34 int bit_index = reg_index & (kBitsPerByte - 1); | 34 int bit_index = reg_index & (kBitsPerByte - 1); |
| 35 return (bits_[byte_index] & (1 << bit_index)) != 0; | 35 return (bits_[byte_index] & (1 << bit_index)) != 0; |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 SafepointTable::SafepointTable(Code* code) { | 39 SafepointTable::SafepointTable(Code* code) { |
| 40 ASSERT(code->is_crankshafted()); | 40 DCHECK(code->is_crankshafted()); |
| 41 code_ = code; | 41 code_ = code; |
| 42 Address header = code->instruction_start() + code->safepoint_table_offset(); | 42 Address header = code->instruction_start() + code->safepoint_table_offset(); |
| 43 length_ = Memory::uint32_at(header + kLengthOffset); | 43 length_ = Memory::uint32_at(header + kLengthOffset); |
| 44 entry_size_ = Memory::uint32_at(header + kEntrySizeOffset); | 44 entry_size_ = Memory::uint32_at(header + kEntrySizeOffset); |
| 45 pc_and_deoptimization_indexes_ = header + kHeaderSize; | 45 pc_and_deoptimization_indexes_ = header + kHeaderSize; |
| 46 entries_ = pc_and_deoptimization_indexes_ + | 46 entries_ = pc_and_deoptimization_indexes_ + |
| 47 (length_ * kPcAndDeoptimizationIndexSize); | 47 (length_ * kPcAndDeoptimizationIndexSize); |
| 48 ASSERT(entry_size_ > 0); | 48 DCHECK(entry_size_ > 0); |
| 49 STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax == | 49 STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax == |
| 50 Safepoint::kNoDeoptimizationIndex); | 50 Safepoint::kNoDeoptimizationIndex); |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 SafepointEntry SafepointTable::FindEntry(Address pc) const { | 54 SafepointEntry SafepointTable::FindEntry(Address pc) const { |
| 55 unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start()); | 55 unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start()); |
| 56 for (unsigned i = 0; i < length(); i++) { | 56 for (unsigned i = 0; i < length(); i++) { |
| 57 // TODO(kasperl): Replace the linear search with binary search. | 57 // TODO(kasperl): Replace the linear search with binary search. |
| 58 if (GetPcOffset(i) == pc_offset) return GetEntry(i); | 58 if (GetPcOffset(i) == pc_offset) return GetEntry(i); |
| 59 } | 59 } |
| 60 return SafepointEntry(); | 60 return SafepointEntry(); |
| 61 } | 61 } |
| 62 | 62 |
| 63 | 63 |
| 64 void SafepointTable::PrintEntry(unsigned index, OStream& os) const { // NOLINT | 64 void SafepointTable::PrintEntry(unsigned index, OStream& os) const { // NOLINT |
| 65 disasm::NameConverter converter; | 65 disasm::NameConverter converter; |
| 66 SafepointEntry entry = GetEntry(index); | 66 SafepointEntry entry = GetEntry(index); |
| 67 uint8_t* bits = entry.bits(); | 67 uint8_t* bits = entry.bits(); |
| 68 | 68 |
| 69 // Print the stack slot bits. | 69 // Print the stack slot bits. |
| 70 if (entry_size_ > 0) { | 70 if (entry_size_ > 0) { |
| 71 ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte)); | 71 DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte)); |
| 72 const int first = kNumSafepointRegisters >> kBitsPerByteLog2; | 72 const int first = kNumSafepointRegisters >> kBitsPerByteLog2; |
| 73 int last = entry_size_ - 1; | 73 int last = entry_size_ - 1; |
| 74 for (int i = first; i < last; i++) PrintBits(os, bits[i], kBitsPerByte); | 74 for (int i = first; i < last; i++) PrintBits(os, bits[i], kBitsPerByte); |
| 75 int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte); | 75 int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte); |
| 76 PrintBits(os, bits[last], last_bits); | 76 PrintBits(os, bits[last], last_bits); |
| 77 | 77 |
| 78 // Print the registers (if any). | 78 // Print the registers (if any). |
| 79 if (!entry.HasRegisters()) return; | 79 if (!entry.HasRegisters()) return; |
| 80 for (int j = 0; j < kNumSafepointRegisters; j++) { | 80 for (int j = 0; j < kNumSafepointRegisters; j++) { |
| 81 if (entry.HasRegisterAt(j)) { | 81 if (entry.HasRegisterAt(j)) { |
| 82 os << " | " << converter.NameOfCPURegister(j); | 82 os << " | " << converter.NameOfCPURegister(j); |
| 83 } | 83 } |
| 84 } | 84 } |
| 85 } | 85 } |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 void SafepointTable::PrintBits(OStream& os, // NOLINT | 89 void SafepointTable::PrintBits(OStream& os, // NOLINT |
| 90 uint8_t byte, int digits) { | 90 uint8_t byte, int digits) { |
| 91 ASSERT(digits >= 0 && digits <= kBitsPerByte); | 91 DCHECK(digits >= 0 && digits <= kBitsPerByte); |
| 92 for (int i = 0; i < digits; i++) { | 92 for (int i = 0; i < digits; i++) { |
| 93 os << (((byte & (1 << i)) == 0) ? "0" : "1"); | 93 os << (((byte & (1 << i)) == 0) ? "0" : "1"); |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 | 97 |
| 98 void Safepoint::DefinePointerRegister(Register reg, Zone* zone) { | 98 void Safepoint::DefinePointerRegister(Register reg, Zone* zone) { |
| 99 registers_->Add(reg.code(), zone); | 99 registers_->Add(reg.code(), zone); |
| 100 } | 100 } |
| 101 | 101 |
| 102 | 102 |
| 103 Safepoint SafepointTableBuilder::DefineSafepoint( | 103 Safepoint SafepointTableBuilder::DefineSafepoint( |
| 104 Assembler* assembler, | 104 Assembler* assembler, |
| 105 Safepoint::Kind kind, | 105 Safepoint::Kind kind, |
| 106 int arguments, | 106 int arguments, |
| 107 Safepoint::DeoptMode deopt_mode) { | 107 Safepoint::DeoptMode deopt_mode) { |
| 108 ASSERT(arguments >= 0); | 108 DCHECK(arguments >= 0); |
| 109 DeoptimizationInfo info; | 109 DeoptimizationInfo info; |
| 110 info.pc = assembler->pc_offset(); | 110 info.pc = assembler->pc_offset(); |
| 111 info.arguments = arguments; | 111 info.arguments = arguments; |
| 112 info.has_doubles = (kind & Safepoint::kWithDoubles); | 112 info.has_doubles = (kind & Safepoint::kWithDoubles); |
| 113 deoptimization_info_.Add(info, zone_); | 113 deoptimization_info_.Add(info, zone_); |
| 114 deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex, zone_); | 114 deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex, zone_); |
| 115 if (deopt_mode == Safepoint::kNoLazyDeopt) { | 115 if (deopt_mode == Safepoint::kNoLazyDeopt) { |
| 116 last_lazy_safepoint_ = deopt_index_list_.length(); | 116 last_lazy_safepoint_ = deopt_index_list_.length(); |
| 117 } | 117 } |
| 118 indexes_.Add(new(zone_) ZoneList<int>(8, zone_), zone_); | 118 indexes_.Add(new(zone_) ZoneList<int>(8, zone_), zone_); |
| 119 registers_.Add((kind & Safepoint::kWithRegisters) | 119 registers_.Add((kind & Safepoint::kWithRegisters) |
| 120 ? new(zone_) ZoneList<int>(4, zone_) | 120 ? new(zone_) ZoneList<int>(4, zone_) |
| 121 : NULL, | 121 : NULL, |
| 122 zone_); | 122 zone_); |
| 123 return Safepoint(indexes_.last(), registers_.last()); | 123 return Safepoint(indexes_.last(), registers_.last()); |
| 124 } | 124 } |
| 125 | 125 |
| 126 | 126 |
| 127 void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) { | 127 void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) { |
| 128 while (last_lazy_safepoint_ < deopt_index_list_.length()) { | 128 while (last_lazy_safepoint_ < deopt_index_list_.length()) { |
| 129 deopt_index_list_[last_lazy_safepoint_++] = index; | 129 deopt_index_list_[last_lazy_safepoint_++] = index; |
| 130 } | 130 } |
| 131 } | 131 } |
| 132 | 132 |
| 133 unsigned SafepointTableBuilder::GetCodeOffset() const { | 133 unsigned SafepointTableBuilder::GetCodeOffset() const { |
| 134 ASSERT(emitted_); | 134 DCHECK(emitted_); |
| 135 return offset_; | 135 return offset_; |
| 136 } | 136 } |
| 137 | 137 |
| 138 | 138 |
| 139 void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) { | 139 void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) { |
| 140 // Make sure the safepoint table is properly aligned. Pad with nops. | 140 // Make sure the safepoint table is properly aligned. Pad with nops. |
| 141 assembler->Align(kIntSize); | 141 assembler->Align(kIntSize); |
| 142 assembler->RecordComment(";;; Safepoint table."); | 142 assembler->RecordComment(";;; Safepoint table."); |
| 143 offset_ = assembler->pc_offset(); | 143 offset_ = assembler->pc_offset(); |
| 144 | 144 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 163 | 163 |
| 164 // Emit table of bitmaps. | 164 // Emit table of bitmaps. |
| 165 ZoneList<uint8_t> bits(bytes_per_entry, zone_); | 165 ZoneList<uint8_t> bits(bytes_per_entry, zone_); |
| 166 for (int i = 0; i < length; i++) { | 166 for (int i = 0; i < length; i++) { |
| 167 ZoneList<int>* indexes = indexes_[i]; | 167 ZoneList<int>* indexes = indexes_[i]; |
| 168 ZoneList<int>* registers = registers_[i]; | 168 ZoneList<int>* registers = registers_[i]; |
| 169 bits.Clear(); | 169 bits.Clear(); |
| 170 bits.AddBlock(0, bytes_per_entry, zone_); | 170 bits.AddBlock(0, bytes_per_entry, zone_); |
| 171 | 171 |
| 172 // Run through the registers (if any). | 172 // Run through the registers (if any). |
| 173 ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte)); | 173 DCHECK(IsAligned(kNumSafepointRegisters, kBitsPerByte)); |
| 174 if (registers == NULL) { | 174 if (registers == NULL) { |
| 175 const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2; | 175 const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2; |
| 176 for (int j = 0; j < num_reg_bytes; j++) { | 176 for (int j = 0; j < num_reg_bytes; j++) { |
| 177 bits[j] = SafepointTable::kNoRegisters; | 177 bits[j] = SafepointTable::kNoRegisters; |
| 178 } | 178 } |
| 179 } else { | 179 } else { |
| 180 for (int j = 0; j < registers->length(); j++) { | 180 for (int j = 0; j < registers->length(); j++) { |
| 181 int index = registers->at(j); | 181 int index = registers->at(j); |
| 182 ASSERT(index >= 0 && index < kNumSafepointRegisters); | 182 DCHECK(index >= 0 && index < kNumSafepointRegisters); |
| 183 int byte_index = index >> kBitsPerByteLog2; | 183 int byte_index = index >> kBitsPerByteLog2; |
| 184 int bit_index = index & (kBitsPerByte - 1); | 184 int bit_index = index & (kBitsPerByte - 1); |
| 185 bits[byte_index] |= (1 << bit_index); | 185 bits[byte_index] |= (1 << bit_index); |
| 186 } | 186 } |
| 187 } | 187 } |
| 188 | 188 |
| 189 // Run through the indexes and build a bitmap. | 189 // Run through the indexes and build a bitmap. |
| 190 for (int j = 0; j < indexes->length(); j++) { | 190 for (int j = 0; j < indexes->length(); j++) { |
| 191 int index = bits_per_entry - 1 - indexes->at(j); | 191 int index = bits_per_entry - 1 - indexes->at(j); |
| 192 int byte_index = index >> kBitsPerByteLog2; | 192 int byte_index = index >> kBitsPerByteLog2; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 207 unsigned index) { | 207 unsigned index) { |
| 208 uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index); | 208 uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index); |
| 209 encoding |= SafepointEntry::ArgumentsField::encode(info.arguments); | 209 encoding |= SafepointEntry::ArgumentsField::encode(info.arguments); |
| 210 encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles); | 210 encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles); |
| 211 return encoding; | 211 return encoding; |
| 212 } | 212 } |
| 213 | 213 |
| 214 | 214 |
| 215 | 215 |
| 216 } } // namespace v8::internal | 216 } } // namespace v8::internal |
| OLD | NEW |