Home | History | Annotate | Download | only in src
      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 #ifndef V8_SAFEPOINT_TABLE_H_
      6 #define V8_SAFEPOINT_TABLE_H_
      7 
      8 #include "src/allocation.h"
      9 #include "src/heap/heap.h"
     10 #include "src/v8memory.h"
     11 #include "src/zone/zone.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 struct Register;
     17 
     18 class SafepointEntry BASE_EMBEDDED {
     19  public:
     20   SafepointEntry() : info_(0), bits_(NULL) {}
     21 
     22   SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
     23     DCHECK(is_valid());
     24   }
     25 
     26   bool is_valid() const { return bits_ != NULL; }
     27 
     28   bool Equals(const SafepointEntry& other) const {
     29     return info_ == other.info_ && bits_ == other.bits_;
     30   }
     31 
     32   void Reset() {
     33     info_ = 0;
     34     bits_ = NULL;
     35   }
     36 
     37   int deoptimization_index() const {
     38     DCHECK(is_valid());
     39     return DeoptimizationIndexField::decode(info_);
     40   }
     41 
     42   static const int kArgumentsFieldBits = 3;
     43   static const int kSaveDoublesFieldBits = 1;
     44   static const int kDeoptIndexBits =
     45       32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
     46   class DeoptimizationIndexField:
     47     public BitField<int, 0, kDeoptIndexBits> {};  // NOLINT
     48   class ArgumentsField:
     49     public BitField<unsigned,
     50                     kDeoptIndexBits,
     51                     kArgumentsFieldBits> {};  // NOLINT
     52   class SaveDoublesField:
     53     public BitField<bool,
     54                     kDeoptIndexBits + kArgumentsFieldBits,
     55                     kSaveDoublesFieldBits> { }; // NOLINT
     56 
     57   int argument_count() const {
     58     DCHECK(is_valid());
     59     return ArgumentsField::decode(info_);
     60   }
     61 
     62   bool has_doubles() const {
     63     DCHECK(is_valid());
     64     return SaveDoublesField::decode(info_);
     65   }
     66 
     67   uint8_t* bits() {
     68     DCHECK(is_valid());
     69     return bits_;
     70   }
     71 
     72   bool HasRegisters() const;
     73   bool HasRegisterAt(int reg_index) const;
     74 
     75  private:
     76   unsigned info_;
     77   uint8_t* bits_;
     78 };
     79 
     80 
     81 class SafepointTable BASE_EMBEDDED {
     82  public:
     83   explicit SafepointTable(Code* code);
     84 
     85   int size() const {
     86     return kHeaderSize +
     87            (length_ * (kPcAndDeoptimizationIndexSize + entry_size_));
     88   }
     89   unsigned length() const { return length_; }
     90   unsigned entry_size() const { return entry_size_; }
     91 
     92   unsigned GetPcOffset(unsigned index) const {
     93     DCHECK(index < length_);
     94     return Memory::uint32_at(GetPcOffsetLocation(index));
     95   }
     96 
     97   SafepointEntry GetEntry(unsigned index) const {
     98     DCHECK(index < length_);
     99     unsigned info = Memory::uint32_at(GetInfoLocation(index));
    100     uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
    101     return SafepointEntry(info, bits);
    102   }
    103 
    104   // Returns the entry for the given pc.
    105   SafepointEntry FindEntry(Address pc) const;
    106 
    107   void PrintEntry(unsigned index, std::ostream& os) const;  // NOLINT
    108 
    109  private:
    110   static const uint8_t kNoRegisters = 0xFF;
    111 
    112   static const int kLengthOffset = 0;
    113   static const int kEntrySizeOffset = kLengthOffset + kIntSize;
    114   static const int kHeaderSize = kEntrySizeOffset + kIntSize;
    115 
    116   static const int kPcSize = kIntSize;
    117   static const int kDeoptimizationIndexSize = kIntSize;
    118   static const int kPcAndDeoptimizationIndexSize =
    119       kPcSize + kDeoptimizationIndexSize;
    120 
    121   Address GetPcOffsetLocation(unsigned index) const {
    122     return pc_and_deoptimization_indexes_ +
    123            (index * kPcAndDeoptimizationIndexSize);
    124   }
    125 
    126   Address GetInfoLocation(unsigned index) const {
    127     return GetPcOffsetLocation(index) + kPcSize;
    128   }
    129 
    130   static void PrintBits(std::ostream& os,  // NOLINT
    131                         uint8_t byte, int digits);
    132 
    133   DisallowHeapAllocation no_allocation_;
    134   Code* code_;
    135   unsigned length_;
    136   unsigned entry_size_;
    137 
    138   Address pc_and_deoptimization_indexes_;
    139   Address entries_;
    140 
    141   friend class SafepointTableBuilder;
    142   friend class SafepointEntry;
    143 
    144   DISALLOW_COPY_AND_ASSIGN(SafepointTable);
    145 };
    146 
    147 
    148 class Safepoint BASE_EMBEDDED {
    149  public:
    150   typedef enum {
    151     kSimple = 0,
    152     kWithRegisters = 1 << 0,
    153     kWithDoubles = 1 << 1,
    154     kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
    155   } Kind;
    156 
    157   enum DeoptMode {
    158     kNoLazyDeopt,
    159     kLazyDeopt
    160   };
    161 
    162   static const int kNoDeoptimizationIndex =
    163       (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
    164 
    165   void DefinePointerSlot(int index, Zone* zone) { indexes_->Add(index, zone); }
    166   void DefinePointerRegister(Register reg, Zone* zone);
    167 
    168  private:
    169   Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers)
    170       : indexes_(indexes), registers_(registers) {}
    171   ZoneList<int>* indexes_;
    172   ZoneList<int>* registers_;
    173 
    174   friend class SafepointTableBuilder;
    175 };
    176 
    177 
    178 class SafepointTableBuilder BASE_EMBEDDED {
    179  public:
    180   explicit SafepointTableBuilder(Zone* zone)
    181       : deoptimization_info_(32, zone),
    182         deopt_index_list_(32, zone),
    183         indexes_(32, zone),
    184         registers_(32, zone),
    185         emitted_(false),
    186         last_lazy_safepoint_(0),
    187         zone_(zone) { }
    188 
    189   // Get the offset of the emitted safepoint table in the code.
    190   unsigned GetCodeOffset() const;
    191 
    192   // Define a new safepoint for the current position in the body.
    193   Safepoint DefineSafepoint(Assembler* assembler,
    194                             Safepoint::Kind kind,
    195                             int arguments,
    196                             Safepoint::DeoptMode mode);
    197 
    198   // Record deoptimization index for lazy deoptimization for the last
    199   // outstanding safepoints.
    200   void RecordLazyDeoptimizationIndex(int index);
    201   void BumpLastLazySafepointIndex() {
    202     last_lazy_safepoint_ = deopt_index_list_.length();
    203   }
    204 
    205   // Emit the safepoint table after the body. The number of bits per
    206   // entry must be enough to hold all the pointer indexes.
    207   void Emit(Assembler* assembler, int bits_per_entry);
    208 
    209 
    210  private:
    211   struct DeoptimizationInfo {
    212     unsigned pc;
    213     unsigned arguments;
    214     bool has_doubles;
    215   };
    216 
    217   uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
    218 
    219   ZoneList<DeoptimizationInfo> deoptimization_info_;
    220   ZoneList<unsigned> deopt_index_list_;
    221   ZoneList<ZoneList<int>*> indexes_;
    222   ZoneList<ZoneList<int>*> registers_;
    223 
    224   unsigned offset_;
    225   bool emitted_;
    226   int last_lazy_safepoint_;
    227 
    228   Zone* zone_;
    229 
    230   DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
    231 };
    232 
    233 }  // namespace internal
    234 }  // namespace v8
    235 
    236 #endif  // V8_SAFEPOINT_TABLE_H_
    237