| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_SAFEPOINT_TABLE_H_ | 28 #ifndef V8_SAFEPOINT_TABLE_H_ |
| 29 #define V8_SAFEPOINT_TABLE_H_ | 29 #define V8_SAFEPOINT_TABLE_H_ |
| 30 | 30 |
| 31 #include "v8.h" | 31 #include "v8.h" |
| 32 | 32 |
| 33 #include "macro-assembler.h" | 33 #include "heap.h" |
| 34 #include "zone.h" | 34 #include "zone.h" |
| 35 #include "zone-inl.h" | 35 #include "zone-inl.h" |
| 36 | 36 |
| 37 namespace v8 { | 37 namespace v8 { |
| 38 namespace internal { | 38 namespace internal { |
| 39 | 39 |
| 40 struct Register; |
| 41 |
| 42 class SafepointEntry BASE_EMBEDDED { |
| 43 public: |
| 44 SafepointEntry() : info_(0), bits_(NULL) {} |
| 45 |
| 46 SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) { |
| 47 ASSERT(is_valid()); |
| 48 } |
| 49 |
| 50 bool is_valid() const { return bits_ != NULL; } |
| 51 |
| 52 bool Equals(const SafepointEntry& other) const { |
| 53 return info_ == other.info_ && bits_ == other.bits_; |
| 54 } |
| 55 |
| 56 void Reset() { |
| 57 info_ = 0; |
| 58 bits_ = NULL; |
| 59 } |
| 60 |
| 61 int deoptimization_index() const { |
| 62 ASSERT(is_valid()); |
| 63 return DeoptimizationIndexField::decode(info_); |
| 64 } |
| 65 |
| 66 int gap_code_size() const { |
| 67 ASSERT(is_valid()); |
| 68 return GapCodeSizeField::decode(info_); |
| 69 } |
| 70 |
| 71 int argument_count() const { |
| 72 ASSERT(is_valid()); |
| 73 return ArgumentsField::decode(info_); |
| 74 } |
| 75 |
| 76 bool has_doubles() const { |
| 77 ASSERT(is_valid()); |
| 78 return SaveDoublesField::decode(info_); |
| 79 } |
| 80 |
| 81 uint8_t* bits() { |
| 82 ASSERT(is_valid()); |
| 83 return bits_; |
| 84 } |
| 85 |
| 86 bool HasRegisters() const; |
| 87 bool HasRegisterAt(int reg_index) const; |
| 88 |
| 89 // Reserve 13 bits for the gap code size. On ARM a constant pool can be |
| 90 // emitted when generating the gap code. The size of the const pool is less |
| 91 // than what can be represented in 12 bits, so 13 bits gives room for having |
| 92 // instructions before potentially emitting a constant pool. |
| 93 static const int kGapCodeSizeBits = 13; |
| 94 static const int kArgumentsFieldBits = 3; |
| 95 static const int kSaveDoublesFieldBits = 1; |
| 96 static const int kDeoptIndexBits = |
| 97 32 - kGapCodeSizeBits - kArgumentsFieldBits - kSaveDoublesFieldBits; |
| 98 class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {}; |
| 99 class DeoptimizationIndexField: public BitField<int, |
| 100 kGapCodeSizeBits, |
| 101 kDeoptIndexBits> {}; // NOLIN
T |
| 102 class ArgumentsField: public BitField<unsigned, |
| 103 kGapCodeSizeBits + kDeoptIndexBits, |
| 104 kArgumentsFieldBits> {}; // NOLINT |
| 105 class SaveDoublesField: public BitField<bool, |
| 106 kGapCodeSizeBits + kDeoptIndexBits + |
| 107 kArgumentsFieldBits, |
| 108 kSaveDoublesFieldBits> { }; // NOLINT |
| 109 |
| 110 private: |
| 111 unsigned info_; |
| 112 uint8_t* bits_; |
| 113 }; |
| 114 |
| 115 |
| 40 class SafepointTable BASE_EMBEDDED { | 116 class SafepointTable BASE_EMBEDDED { |
| 41 public: | 117 public: |
| 42 explicit SafepointTable(Code* code); | 118 explicit SafepointTable(Code* code); |
| 43 | 119 |
| 44 int size() const { | 120 int size() const { |
| 45 return kHeaderSize + | 121 return kHeaderSize + |
| 46 (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); } | 122 (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); } |
| 47 unsigned length() const { return length_; } | 123 unsigned length() const { return length_; } |
| 48 unsigned entry_size() const { return entry_size_; } | 124 unsigned entry_size() const { return entry_size_; } |
| 49 | 125 |
| 50 unsigned GetPcOffset(unsigned index) const { | 126 unsigned GetPcOffset(unsigned index) const { |
| 51 ASSERT(index < length_); | 127 ASSERT(index < length_); |
| 52 return Memory::uint32_at(GetPcOffsetLocation(index)); | 128 return Memory::uint32_at(GetPcOffsetLocation(index)); |
| 53 } | 129 } |
| 54 | 130 |
| 55 int GetDeoptimizationIndex(unsigned index) const { | 131 SafepointEntry GetEntry(unsigned index) const { |
| 56 ASSERT(index < length_); | 132 ASSERT(index < length_); |
| 57 unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index)); | 133 unsigned info = Memory::uint32_at(GetInfoLocation(index)); |
| 58 return DeoptimizationIndexField::decode(value); | 134 uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_)); |
| 135 return SafepointEntry(info, bits); |
| 59 } | 136 } |
| 60 | 137 |
| 61 unsigned GetGapCodeSize(unsigned index) const { | 138 // Returns the entry for the given pc. |
| 62 ASSERT(index < length_); | 139 SafepointEntry FindEntry(Address pc) const; |
| 63 unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index)); | |
| 64 return GapCodeSizeField::decode(value); | |
| 65 } | |
| 66 | |
| 67 uint8_t* GetEntry(unsigned index) const { | |
| 68 ASSERT(index < length_); | |
| 69 return &Memory::uint8_at(entries_ + (index * entry_size_)); | |
| 70 } | |
| 71 | |
| 72 class GapCodeSizeField: public BitField<unsigned, 0, 8> {}; | |
| 73 class DeoptimizationIndexField: public BitField<int, 8, 24> {}; | |
| 74 | |
| 75 static bool HasRegisters(uint8_t* entry); | |
| 76 static bool HasRegisterAt(uint8_t* entry, int reg_index); | |
| 77 | 140 |
| 78 void PrintEntry(unsigned index) const; | 141 void PrintEntry(unsigned index) const; |
| 79 | 142 |
| 80 private: | 143 private: |
| 81 static const uint8_t kNoRegisters = 0xFF; | 144 static const uint8_t kNoRegisters = 0xFF; |
| 82 | 145 |
| 83 static const int kLengthOffset = 0; | 146 static const int kLengthOffset = 0; |
| 84 static const int kEntrySizeOffset = kLengthOffset + kIntSize; | 147 static const int kEntrySizeOffset = kLengthOffset + kIntSize; |
| 85 static const int kHeaderSize = kEntrySizeOffset + kIntSize; | 148 static const int kHeaderSize = kEntrySizeOffset + kIntSize; |
| 86 | 149 |
| 87 static const int kPcSize = kIntSize; | 150 static const int kPcSize = kIntSize; |
| 88 static const int kDeoptimizationIndexSize = kIntSize; | 151 static const int kDeoptimizationIndexSize = kIntSize; |
| 89 static const int kPcAndDeoptimizationIndexSize = | 152 static const int kPcAndDeoptimizationIndexSize = |
| 90 kPcSize + kDeoptimizationIndexSize; | 153 kPcSize + kDeoptimizationIndexSize; |
| 91 | 154 |
| 92 Address GetPcOffsetLocation(unsigned index) const { | 155 Address GetPcOffsetLocation(unsigned index) const { |
| 93 return pc_and_deoptimization_indexes_ + | 156 return pc_and_deoptimization_indexes_ + |
| 94 (index * kPcAndDeoptimizationIndexSize); | 157 (index * kPcAndDeoptimizationIndexSize); |
| 95 } | 158 } |
| 96 | 159 |
| 97 Address GetDeoptimizationLocation(unsigned index) const { | 160 Address GetInfoLocation(unsigned index) const { |
| 98 return GetPcOffsetLocation(index) + kPcSize; | 161 return GetPcOffsetLocation(index) + kPcSize; |
| 99 } | 162 } |
| 100 | 163 |
| 101 static void PrintBits(uint8_t byte, int digits); | 164 static void PrintBits(uint8_t byte, int digits); |
| 102 | 165 |
| 103 AssertNoAllocation no_allocation_; | 166 AssertNoAllocation no_allocation_; |
| 104 Code* code_; | 167 Code* code_; |
| 105 unsigned length_; | 168 unsigned length_; |
| 106 unsigned entry_size_; | 169 unsigned entry_size_; |
| 107 | 170 |
| 108 Address pc_and_deoptimization_indexes_; | 171 Address pc_and_deoptimization_indexes_; |
| 109 Address entries_; | 172 Address entries_; |
| 110 | 173 |
| 111 friend class SafepointTableBuilder; | 174 friend class SafepointTableBuilder; |
| 175 friend class SafepointEntry; |
| 176 |
| 177 DISALLOW_COPY_AND_ASSIGN(SafepointTable); |
| 112 }; | 178 }; |
| 113 | 179 |
| 114 | 180 |
| 115 class Safepoint BASE_EMBEDDED { | 181 class Safepoint BASE_EMBEDDED { |
| 116 public: | 182 public: |
| 117 static const int kNoDeoptimizationIndex = 0x00ffffff; | 183 typedef enum { |
| 184 kSimple = 0, |
| 185 kWithRegisters = 1 << 0, |
| 186 kWithDoubles = 1 << 1, |
| 187 kWithRegistersAndDoubles = kWithRegisters | kWithDoubles |
| 188 } Kind; |
| 189 |
| 190 static const int kNoDeoptimizationIndex = |
| 191 (1 << (SafepointEntry::kDeoptIndexBits)) - 1; |
| 118 | 192 |
| 119 void DefinePointerSlot(int index) { indexes_->Add(index); } | 193 void DefinePointerSlot(int index) { indexes_->Add(index); } |
| 120 void DefinePointerRegister(Register reg) { registers_->Add(reg.code()); } | 194 void DefinePointerRegister(Register reg); |
| 121 | 195 |
| 122 private: | 196 private: |
| 123 Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) : | 197 Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) : |
| 124 indexes_(indexes), registers_(registers) { } | 198 indexes_(indexes), registers_(registers) { } |
| 125 ZoneList<int>* indexes_; | 199 ZoneList<int>* indexes_; |
| 126 ZoneList<int>* registers_; | 200 ZoneList<int>* registers_; |
| 127 | 201 |
| 128 friend class SafepointTableBuilder; | 202 friend class SafepointTableBuilder; |
| 129 }; | 203 }; |
| 130 | 204 |
| 131 | 205 |
| 132 class SafepointTableBuilder BASE_EMBEDDED { | 206 class SafepointTableBuilder BASE_EMBEDDED { |
| 133 public: | 207 public: |
| 134 SafepointTableBuilder() | 208 SafepointTableBuilder() |
| 135 : deoptimization_info_(32), | 209 : deoptimization_info_(32), |
| 136 indexes_(32), | 210 indexes_(32), |
| 137 registers_(32), | 211 registers_(32), |
| 138 emitted_(false) { } | 212 emitted_(false) { } |
| 139 | 213 |
| 140 // Get the offset of the emitted safepoint table in the code. | 214 // Get the offset of the emitted safepoint table in the code. |
| 141 unsigned GetCodeOffset() const; | 215 unsigned GetCodeOffset() const; |
| 142 | 216 |
| 143 // Define a new safepoint for the current position in the body. | 217 // Define a new safepoint for the current position in the body. |
| 144 Safepoint DefineSafepoint( | 218 Safepoint DefineSafepoint(Assembler* assembler, |
| 145 Assembler* assembler, | 219 Safepoint::Kind kind, |
| 146 int deoptimization_index = Safepoint::kNoDeoptimizationIndex); | 220 int arguments, |
| 221 int deoptimization_index); |
| 147 | 222 |
| 148 // Define a new safepoint with registers on the stack for the | 223 // Update the last safepoint with the size of the code generated until the |
| 149 // current position in the body and take the number of arguments on | 224 // end of the gap following it. |
| 150 // top of the registers into account. | |
| 151 Safepoint DefineSafepointWithRegisters( | |
| 152 Assembler* assembler, | |
| 153 int arguments, | |
| 154 int deoptimization_index = Safepoint::kNoDeoptimizationIndex); | |
| 155 | |
| 156 // Update the last safepoint with the size of the code generated for the gap | |
| 157 // following it. | |
| 158 void SetPcAfterGap(int pc) { | 225 void SetPcAfterGap(int pc) { |
| 159 ASSERT(!deoptimization_info_.is_empty()); | 226 ASSERT(!deoptimization_info_.is_empty()); |
| 160 int index = deoptimization_info_.length() - 1; | 227 int index = deoptimization_info_.length() - 1; |
| 161 deoptimization_info_[index].pc_after_gap = pc; | 228 deoptimization_info_[index].pc_after_gap = pc; |
| 162 } | 229 } |
| 163 | 230 |
| 164 // Emit the safepoint table after the body. The number of bits per | 231 // Emit the safepoint table after the body. The number of bits per |
| 165 // entry must be enough to hold all the pointer indexes. | 232 // entry must be enough to hold all the pointer indexes. |
| 166 void Emit(Assembler* assembler, int bits_per_entry); | 233 void Emit(Assembler* assembler, int bits_per_entry); |
| 167 | 234 |
| 235 // Count the number of deoptimization points where the next |
| 236 // following deoptimization point comes less than limit bytes |
| 237 // after the end of this point's gap. |
| 238 int CountShortDeoptimizationIntervals(unsigned limit); |
| 239 |
| 168 private: | 240 private: |
| 169 struct DeoptimizationInfo { | 241 struct DeoptimizationInfo { |
| 170 unsigned pc; | 242 unsigned pc; |
| 171 unsigned deoptimization_index; | 243 unsigned deoptimization_index; |
| 172 unsigned pc_after_gap; | 244 unsigned pc_after_gap; |
| 245 unsigned arguments; |
| 246 bool has_doubles; |
| 173 }; | 247 }; |
| 174 | 248 |
| 175 uint32_t EncodeDeoptimizationIndexAndGap(DeoptimizationInfo info); | 249 uint32_t EncodeExceptPC(const DeoptimizationInfo& info); |
| 176 | 250 |
| 177 ZoneList<DeoptimizationInfo> deoptimization_info_; | 251 ZoneList<DeoptimizationInfo> deoptimization_info_; |
| 178 ZoneList<ZoneList<int>*> indexes_; | 252 ZoneList<ZoneList<int>*> indexes_; |
| 179 ZoneList<ZoneList<int>*> registers_; | 253 ZoneList<ZoneList<int>*> registers_; |
| 180 | 254 |
| 255 unsigned offset_; |
| 181 bool emitted_; | 256 bool emitted_; |
| 182 unsigned offset_; | |
| 183 | 257 |
| 184 DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder); | 258 DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder); |
| 185 }; | 259 }; |
| 186 | 260 |
| 187 } } // namespace v8::internal | 261 } } // namespace v8::internal |
| 188 | 262 |
| 189 #endif // V8_SAFEPOINT_TABLE_H_ | 263 #endif // V8_SAFEPOINT_TABLE_H_ |
| OLD | NEW |