Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     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.
     27 
     28 #ifndef V8_SAFEPOINT_TABLE_H_
     29 #define V8_SAFEPOINT_TABLE_H_
     30 
     31 #include "allocation.h"
     32 #include "heap.h"
     33 #include "v8memory.h"
     34 #include "zone.h"
     35 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 struct Register;
     40 
     41 class SafepointEntry BASE_EMBEDDED {
     42  public:
     43   SafepointEntry() : info_(0), bits_(NULL) {}
     44 
     45   SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
     46     ASSERT(is_valid());
     47   }
     48 
     49   bool is_valid() const { return bits_ != NULL; }
     50 
     51   bool Equals(const SafepointEntry& other) const {
     52     return info_ == other.info_ && bits_ == other.bits_;
     53   }
     54 
     55   void Reset() {
     56     info_ = 0;
     57     bits_ = NULL;
     58   }
     59 
     60   int deoptimization_index() const {
     61     ASSERT(is_valid());
     62     return DeoptimizationIndexField::decode(info_);
     63   }
     64 
     65   static const int kArgumentsFieldBits = 3;
     66   static const int kSaveDoublesFieldBits = 1;
     67   static const int kDeoptIndexBits =
     68       32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
     69   class DeoptimizationIndexField:
     70     public BitField<int, 0, kDeoptIndexBits> {};  // NOLINT
     71   class ArgumentsField:
     72     public BitField<unsigned,
     73                     kDeoptIndexBits,
     74                     kArgumentsFieldBits> {};  // NOLINT
     75   class SaveDoublesField:
     76     public BitField<bool,
     77                     kDeoptIndexBits + kArgumentsFieldBits,
     78                     kSaveDoublesFieldBits> { }; // NOLINT
     79 
     80   int argument_count() const {
     81     ASSERT(is_valid());
     82     return ArgumentsField::decode(info_);
     83   }
     84 
     85   bool has_doubles() const {
     86     ASSERT(is_valid());
     87     return SaveDoublesField::decode(info_);
     88   }
     89 
     90   uint8_t* bits() {
     91     ASSERT(is_valid());
     92     return bits_;
     93   }
     94 
     95   bool HasRegisters() const;
     96   bool HasRegisterAt(int reg_index) const;
     97 
     98  private:
     99   unsigned info_;
    100   uint8_t* bits_;
    101 };
    102 
    103 
    104 class SafepointTable BASE_EMBEDDED {
    105  public:
    106   explicit SafepointTable(Code* code);
    107 
    108   int size() const {
    109     return kHeaderSize +
    110            (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
    111   unsigned length() const { return length_; }
    112   unsigned entry_size() const { return entry_size_; }
    113 
    114   unsigned GetPcOffset(unsigned index) const {
    115     ASSERT(index < length_);
    116     return Memory::uint32_at(GetPcOffsetLocation(index));
    117   }
    118 
    119   SafepointEntry GetEntry(unsigned index) const {
    120     ASSERT(index < length_);
    121     unsigned info = Memory::uint32_at(GetInfoLocation(index));
    122     uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
    123     return SafepointEntry(info, bits);
    124   }
    125 
    126   // Returns the entry for the given pc.
    127   SafepointEntry FindEntry(Address pc) const;
    128 
    129   void PrintEntry(unsigned index) const;
    130 
    131  private:
    132   static const uint8_t kNoRegisters = 0xFF;
    133 
    134   static const int kLengthOffset = 0;
    135   static const int kEntrySizeOffset = kLengthOffset + kIntSize;
    136   static const int kHeaderSize = kEntrySizeOffset + kIntSize;
    137 
    138   static const int kPcSize = kIntSize;
    139   static const int kDeoptimizationIndexSize = kIntSize;
    140   static const int kPcAndDeoptimizationIndexSize =
    141       kPcSize + kDeoptimizationIndexSize;
    142 
    143   Address GetPcOffsetLocation(unsigned index) const {
    144     return pc_and_deoptimization_indexes_ +
    145            (index * kPcAndDeoptimizationIndexSize);
    146   }
    147 
    148   Address GetInfoLocation(unsigned index) const {
    149     return GetPcOffsetLocation(index) + kPcSize;
    150   }
    151 
    152   static void PrintBits(uint8_t byte, int digits);
    153 
    154   AssertNoAllocation no_allocation_;
    155   Code* code_;
    156   unsigned length_;
    157   unsigned entry_size_;
    158 
    159   Address pc_and_deoptimization_indexes_;
    160   Address entries_;
    161 
    162   friend class SafepointTableBuilder;
    163   friend class SafepointEntry;
    164 
    165   DISALLOW_COPY_AND_ASSIGN(SafepointTable);
    166 };
    167 
    168 
    169 class Safepoint BASE_EMBEDDED {
    170  public:
    171   typedef enum {
    172     kSimple = 0,
    173     kWithRegisters = 1 << 0,
    174     kWithDoubles = 1 << 1,
    175     kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
    176   } Kind;
    177 
    178   enum DeoptMode {
    179     kNoLazyDeopt,
    180     kLazyDeopt
    181   };
    182 
    183   static const int kNoDeoptimizationIndex =
    184       (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
    185 
    186   void DefinePointerSlot(int index) { indexes_->Add(index); }
    187   void DefinePointerRegister(Register reg);
    188 
    189  private:
    190   Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
    191       indexes_(indexes), registers_(registers) { }
    192   ZoneList<int>* indexes_;
    193   ZoneList<int>* registers_;
    194 
    195   friend class SafepointTableBuilder;
    196 };
    197 
    198 
    199 class SafepointTableBuilder BASE_EMBEDDED {
    200  public:
    201   SafepointTableBuilder()
    202       : deoptimization_info_(32),
    203         deopt_index_list_(32),
    204         indexes_(32),
    205         registers_(32),
    206         emitted_(false),
    207         last_lazy_safepoint_(0) { }
    208 
    209   // Get the offset of the emitted safepoint table in the code.
    210   unsigned GetCodeOffset() const;
    211 
    212   // Define a new safepoint for the current position in the body.
    213   Safepoint DefineSafepoint(Assembler* assembler,
    214                             Safepoint::Kind kind,
    215                             int arguments,
    216                             Safepoint::DeoptMode mode);
    217 
    218   // Record deoptimization index for lazy deoptimization for the last
    219   // outstanding safepoints.
    220   void RecordLazyDeoptimizationIndex(int index);
    221 
    222   // Emit the safepoint table after the body. The number of bits per
    223   // entry must be enough to hold all the pointer indexes.
    224   void Emit(Assembler* assembler, int bits_per_entry);
    225 
    226 
    227  private:
    228   struct DeoptimizationInfo {
    229     unsigned pc;
    230     unsigned arguments;
    231     bool has_doubles;
    232   };
    233 
    234   uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
    235 
    236   ZoneList<DeoptimizationInfo> deoptimization_info_;
    237   ZoneList<unsigned> deopt_index_list_;
    238   ZoneList<ZoneList<int>*> indexes_;
    239   ZoneList<ZoneList<int>*> registers_;
    240 
    241   unsigned offset_;
    242   bool emitted_;
    243   int last_lazy_safepoint_;
    244 
    245   DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
    246 };
    247 
    248 } }  // namespace v8::internal
    249 
    250 #endif  // V8_SAFEPOINT_TABLE_H_
    251