| // Copyright 2010 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #ifndef V8_SAFEPOINT_TABLE_H_ |
| #define V8_SAFEPOINT_TABLE_H_ |
| |
| #include "v8.h" |
| |
| #include "macro-assembler.h" |
| #include "zone.h" |
| #include "zone-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class SafepointTable BASE_EMBEDDED { |
| public: |
| explicit SafepointTable(Code* code); |
| |
| int size() const { |
| return kHeaderSize + |
| (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); } |
| unsigned length() const { return length_; } |
| unsigned entry_size() const { return entry_size_; } |
| |
| unsigned GetPcOffset(unsigned index) const { |
| ASSERT(index < length_); |
| return Memory::uint32_at(GetPcOffsetLocation(index)); |
| } |
| |
| int GetDeoptimizationIndex(unsigned index) const { |
| ASSERT(index < length_); |
| unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index)); |
| return DeoptimizationIndexField::decode(value); |
| } |
| |
| unsigned GetGapCodeSize(unsigned index) const { |
| ASSERT(index < length_); |
| unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index)); |
| return GapCodeSizeField::decode(value); |
| } |
| |
| uint8_t* GetEntry(unsigned index) const { |
| ASSERT(index < length_); |
| return &Memory::uint8_at(entries_ + (index * entry_size_)); |
| } |
| |
| class GapCodeSizeField: public BitField<unsigned, 0, 8> {}; |
| class DeoptimizationIndexField: public BitField<int, 8, 24> {}; |
| |
| static bool HasRegisters(uint8_t* entry); |
| static bool HasRegisterAt(uint8_t* entry, int reg_index); |
| |
| void PrintEntry(unsigned index) const; |
| |
| private: |
| static const uint8_t kNoRegisters = 0xFF; |
| |
| static const int kLengthOffset = 0; |
| static const int kEntrySizeOffset = kLengthOffset + kIntSize; |
| static const int kHeaderSize = kEntrySizeOffset + kIntSize; |
| |
| static const int kPcSize = kIntSize; |
| static const int kDeoptimizationIndexSize = kIntSize; |
| static const int kPcAndDeoptimizationIndexSize = |
| kPcSize + kDeoptimizationIndexSize; |
| |
| Address GetPcOffsetLocation(unsigned index) const { |
| return pc_and_deoptimization_indexes_ + |
| (index * kPcAndDeoptimizationIndexSize); |
| } |
| |
| Address GetDeoptimizationLocation(unsigned index) const { |
| return GetPcOffsetLocation(index) + kPcSize; |
| } |
| |
| static void PrintBits(uint8_t byte, int digits); |
| |
| AssertNoAllocation no_allocation_; |
| Code* code_; |
| unsigned length_; |
| unsigned entry_size_; |
| |
| Address pc_and_deoptimization_indexes_; |
| Address entries_; |
| |
| friend class SafepointTableBuilder; |
| }; |
| |
| |
| class Safepoint BASE_EMBEDDED { |
| public: |
| static const int kNoDeoptimizationIndex = 0x00ffffff; |
| |
| void DefinePointerSlot(int index) { indexes_->Add(index); } |
| void DefinePointerRegister(Register reg) { registers_->Add(reg.code()); } |
| |
| private: |
| Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) : |
| indexes_(indexes), registers_(registers) { } |
| ZoneList<int>* indexes_; |
| ZoneList<int>* registers_; |
| |
| friend class SafepointTableBuilder; |
| }; |
| |
| |
| class SafepointTableBuilder BASE_EMBEDDED { |
| public: |
| SafepointTableBuilder() |
| : deoptimization_info_(32), |
| indexes_(32), |
| registers_(32), |
| emitted_(false) { } |
| |
| // Get the offset of the emitted safepoint table in the code. |
| unsigned GetCodeOffset() const; |
| |
| // Define a new safepoint for the current position in the body. |
| Safepoint DefineSafepoint( |
| Assembler* assembler, |
| int deoptimization_index = Safepoint::kNoDeoptimizationIndex); |
| |
| // Define a new safepoint with registers on the stack for the |
| // current position in the body and take the number of arguments on |
| // top of the registers into account. |
| Safepoint DefineSafepointWithRegisters( |
| Assembler* assembler, |
| int arguments, |
| int deoptimization_index = Safepoint::kNoDeoptimizationIndex); |
| |
| // Update the last safepoint with the size of the code generated for the gap |
| // following it. |
| void SetPcAfterGap(int pc) { |
| ASSERT(!deoptimization_info_.is_empty()); |
| int index = deoptimization_info_.length() - 1; |
| deoptimization_info_[index].pc_after_gap = pc; |
| } |
| |
| // Emit the safepoint table after the body. The number of bits per |
| // entry must be enough to hold all the pointer indexes. |
| void Emit(Assembler* assembler, int bits_per_entry); |
| |
| private: |
| struct DeoptimizationInfo { |
| unsigned pc; |
| unsigned deoptimization_index; |
| unsigned pc_after_gap; |
| }; |
| |
| uint32_t EncodeDeoptimizationIndexAndGap(DeoptimizationInfo info); |
| |
| ZoneList<DeoptimizationInfo> deoptimization_info_; |
| ZoneList<ZoneList<int>*> indexes_; |
| ZoneList<ZoneList<int>*> registers_; |
| |
| bool emitted_; |
| unsigned offset_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder); |
| }; |
| |
| } } // namespace v8::internal |
| |
| #endif // V8_SAFEPOINT_TABLE_H_ |