LCOV - code coverage report
Current view: top level - src - safepoint-table.h (source / functions) Hit Total Coverage
Test: app.info Lines: 22 22 100.0 %
Date: 2019-01-20 Functions: 1 1 100.0 %

          Line data    Source code
       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/assert-scope.h"
      10             : #include "src/v8memory.h"
      11             : #include "src/zone/zone-chunk-list.h"
      12             : #include "src/zone/zone.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : class Register;
      18             : 
      19             : class SafepointEntry {
      20             :  public:
      21    65273941 :   SafepointEntry() : info_(0), bits_(nullptr), trampoline_pc_(-1) {}
      22             : 
      23             :   SafepointEntry(unsigned info, uint8_t* bits, int trampoline_pc)
      24     3029955 :       : info_(info), bits_(bits), trampoline_pc_(trampoline_pc) {
      25             :     DCHECK(is_valid());
      26             :   }
      27             : 
      28             :   bool is_valid() const { return bits_ != nullptr; }
      29             : 
      30             :   bool Equals(const SafepointEntry& other) const {
      31             :     return info_ == other.info_ && bits_ == other.bits_;
      32             :   }
      33             : 
      34             :   void Reset() {
      35     1091438 :     info_ = 0;
      36     1091438 :     bits_ = nullptr;
      37             :   }
      38             : 
      39             :   int trampoline_pc() { return trampoline_pc_; }
      40             : 
      41             :   static const int kHasArgumentsFieldBits = 1;
      42             :   static const int kSaveDoublesFieldBits = 1;
      43             :   static const int kDeoptIndexOrArgumentsBits =
      44             :       32 - kHasArgumentsFieldBits - kSaveDoublesFieldBits;
      45             : 
      46             :   class DeoptimizationIndexOrArgumentsField                      // --
      47             :       : public BitField<int, 0, kDeoptIndexOrArgumentsBits> {};  // --
      48             :   class HasArgumentsField                                        // --
      49             :       : public BitField<bool, kDeoptIndexOrArgumentsBits,        // --
      50             :                         kHasArgumentsFieldBits> {};              // --
      51             :   class SaveDoublesField                                         // --
      52             :       : public BitField<bool, HasArgumentsField::kNext,          // --
      53             :                         kSaveDoublesFieldBits> {};               // --
      54             : 
      55             :   int deoptimization_index() const {
      56             :     DCHECK(is_valid() && has_deoptimization_index());
      57             :     return DeoptimizationIndexOrArgumentsField::decode(info_);
      58             :   }
      59             : 
      60             :   bool has_deoptimization_index() const {
      61             :     DCHECK(is_valid());
      62     5279274 :     return !HasArgumentsField::decode(info_) &&
      63             :            DeoptimizationIndexOrArgumentsField::decode(info_) !=
      64             :                DeoptimizationIndexOrArgumentsField::kMax;
      65             :   }
      66             : 
      67             :   int argument_count() const {
      68             :     DCHECK(is_valid() && has_argument_count());
      69             :     return DeoptimizationIndexOrArgumentsField::decode(info_);
      70             :   }
      71             : 
      72             :   bool has_argument_count() const {
      73             :     DCHECK(is_valid());
      74             :     return HasArgumentsField::decode(info_);
      75             :   }
      76             : 
      77             :   bool has_doubles() const {
      78             :     DCHECK(is_valid());
      79             :     return SaveDoublesField::decode(info_);
      80             :   }
      81             : 
      82             :   uint8_t* bits() {
      83             :     DCHECK(is_valid());
      84             :     return bits_;
      85             :   }
      86             : 
      87             :   bool HasRegisters() const;
      88             :   bool HasRegisterAt(int reg_index) const;
      89             : 
      90             :  private:
      91             :   unsigned info_;
      92             :   uint8_t* bits_;
      93             :   // It needs to be an integer as it is -1 for eager deoptimizations.
      94             :   int trampoline_pc_;
      95             : };
      96             : 
      97             : class SafepointTable {
      98             :  public:
      99             :   explicit SafepointTable(Code code);
     100             :   explicit SafepointTable(Address instruction_start,
     101             :                           size_t safepoint_table_offset, uint32_t stack_slots,
     102             :                           bool has_deopt = false);
     103             : 
     104             :   int size() const {
     105             :     return kHeaderSize + (length_ * (kFixedEntrySize + entry_size_));
     106             :   }
     107             :   unsigned length() const { return length_; }
     108             :   unsigned entry_size() const { return entry_size_; }
     109             : 
     110    31705352 :   unsigned GetPcOffset(unsigned index) const {
     111             :     DCHECK(index < length_);
     112    31751366 :     return Memory<uint32_t>(GetPcOffsetLocation(index));
     113             :   }
     114             : 
     115             :   int GetTrampolinePcOffset(unsigned index) const {
     116             :     DCHECK(index < length_);
     117    28837961 :     return Memory<int>(GetTrampolineLocation(index));
     118             :   }
     119             : 
     120             :   unsigned find_return_pc(unsigned pc_offset);
     121             : 
     122             :   SafepointEntry GetEntry(unsigned index) const {
     123             :     DCHECK(index < length_);
     124     3029955 :     unsigned info = Memory<uint32_t>(GetEncodedInfoLocation(index));
     125     3029955 :     uint8_t* bits = &Memory<uint8_t>(entries_ + (index * entry_size_));
     126             :     int trampoline_pc =
     127     6047261 :         has_deopt_ ? Memory<int>(GetTrampolineLocation(index)) : -1;
     128             :     return SafepointEntry(info, bits, trampoline_pc);
     129             :   }
     130             : 
     131             :   // Returns the entry for the given pc.
     132             :   SafepointEntry FindEntry(Address pc) const;
     133             : 
     134             :   void PrintEntry(unsigned index, std::ostream& os) const;  // NOLINT
     135             : 
     136             :  private:
     137             :   static const uint8_t kNoRegisters = 0xFF;
     138             : 
     139             :   // Layout information
     140             :   static const int kLengthOffset = 0;
     141             :   static const int kEntrySizeOffset = kLengthOffset + kIntSize;
     142             :   static const int kHeaderSize = kEntrySizeOffset + kIntSize;
     143             :   static const int kPcOffset = 0;
     144             :   static const int kEncodedInfoOffset = kPcOffset + kIntSize;
     145             :   static const int kTrampolinePcOffset = kEncodedInfoOffset + kIntSize;
     146             :   static const int kFixedEntrySize = kTrampolinePcOffset + kIntSize;
     147             : 
     148             :   Address GetPcOffsetLocation(unsigned index) const {
     149    31720487 :     return pc_and_deoptimization_indexes_ + (index * kFixedEntrySize);
     150             :   }
     151             : 
     152       10879 :   Address GetEncodedInfoLocation(unsigned index) const {
     153     3029955 :     return GetPcOffsetLocation(index) + kEncodedInfoOffset;
     154             :   }
     155             : 
     156       46014 :   Address GetTrampolineLocation(unsigned index) const {
     157    31855267 :     return GetPcOffsetLocation(index) + kTrampolinePcOffset;
     158             :   }
     159             : 
     160             :   static void PrintBits(std::ostream& os,  // NOLINT
     161             :                         uint8_t byte, int digits);
     162             : 
     163             :   DISALLOW_HEAP_ALLOCATION(no_allocation_);
     164             :   Address instruction_start_;
     165             :   uint32_t stack_slots_;
     166             :   unsigned length_;
     167             :   unsigned entry_size_;
     168             : 
     169             :   Address pc_and_deoptimization_indexes_;
     170             :   Address entries_;
     171             :   bool has_deopt_;
     172             : 
     173             :   friend class SafepointTableBuilder;
     174             :   friend class SafepointEntry;
     175             : 
     176             :   DISALLOW_COPY_AND_ASSIGN(SafepointTable);
     177             : };
     178             : 
     179             : class Safepoint {
     180             :  public:
     181             :   typedef enum {
     182             :     kSimple = 0,
     183             :     kWithRegisters = 1 << 0,
     184             :     kWithDoubles = 1 << 1,
     185             :     kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
     186             :   } Kind;
     187             : 
     188             :   enum DeoptMode {
     189             :     kNoLazyDeopt,
     190             :     kLazyDeopt
     191             :   };
     192             : 
     193             :   static const int kNoDeoptimizationIndex =
     194             :       SafepointEntry::DeoptimizationIndexOrArgumentsField::kMax;
     195             : 
     196    13998004 :   void DefinePointerSlot(int index) { indexes_->push_back(index); }
     197             :   void DefinePointerRegister(Register reg);
     198             : 
     199             :  private:
     200             :   Safepoint(ZoneChunkList<int>* indexes, ZoneChunkList<int>* registers)
     201             :       : indexes_(indexes), registers_(registers) {}
     202             :   ZoneChunkList<int>* const indexes_;
     203             :   ZoneChunkList<int>* const registers_;
     204             : 
     205             :   friend class SafepointTableBuilder;
     206             : };
     207             : 
     208             : class SafepointTableBuilder {
     209             :  public:
     210             :   explicit SafepointTableBuilder(Zone* zone)
     211             :       : deoptimization_info_(zone),
     212             :         emitted_(false),
     213             :         last_lazy_safepoint_(0),
     214     3661470 :         zone_(zone) {}
     215             : 
     216             :   // Get the offset of the emitted safepoint table in the code.
     217             :   unsigned GetCodeOffset() const;
     218             : 
     219             :   // Define a new safepoint for the current position in the body.
     220             :   Safepoint DefineSafepoint(Assembler* assembler,
     221             :                             Safepoint::Kind kind,
     222             :                             int arguments,
     223             :                             Safepoint::DeoptMode mode);
     224             : 
     225             :   // Record deoptimization index for lazy deoptimization for the last
     226             :   // outstanding safepoints.
     227             :   void RecordLazyDeoptimizationIndex(int index);
     228             :   void BumpLastLazySafepointIndex() {
     229             :     last_lazy_safepoint_ = deoptimization_info_.size();
     230             :   }
     231             : 
     232             :   // Emit the safepoint table after the body. The number of bits per
     233             :   // entry must be enough to hold all the pointer indexes.
     234             :   void Emit(Assembler* assembler, int bits_per_entry);
     235             : 
     236             :   // Find the Deoptimization Info with pc offset {pc} and update its
     237             :   // trampoline field. Calling this function ensures that the safepoint
     238             :   // table contains the trampoline PC {trampoline} that replaced the
     239             :   // return PC {pc} on the stack.
     240             :   int UpdateDeoptimizationInfo(int pc, int trampoline, int start);
     241             : 
     242             :  private:
     243             :   struct DeoptimizationInfo {
     244             :     unsigned pc;
     245             :     unsigned arguments;    // Only available if {deopt_index} unused.
     246             :     unsigned deopt_index;  // Only available if {arguments == 0}.
     247             :     bool has_doubles;
     248             :     int trampoline;
     249             :     ZoneChunkList<int>* indexes;
     250             :     ZoneChunkList<int>* registers;
     251     5991354 :     DeoptimizationInfo(Zone* zone, unsigned pc, unsigned arguments,
     252             :                        Safepoint::Kind kind)
     253             :         : pc(pc),
     254             :           arguments(arguments),
     255             :           deopt_index(Safepoint::kNoDeoptimizationIndex),
     256     5991354 :           has_doubles(kind & Safepoint::kWithDoubles),
     257             :           trampoline(-1),
     258             :           indexes(new (zone) ZoneChunkList<int>(
     259             :               zone, ZoneChunkList<int>::StartMode::kSmall)),
     260     5991252 :           registers(kind & Safepoint::kWithRegisters
     261             :                         ? new (zone) ZoneChunkList<int>(
     262             :                               zone, ZoneChunkList<int>::StartMode::kSmall)
     263    29956464 :                         : nullptr) {}
     264             :   };
     265             : 
     266             :   // Encodes all fields of a {DeoptimizationInfo} except {pc} and {trampoline}.
     267             :   uint32_t EncodeExceptPC(const DeoptimizationInfo&);
     268             : 
     269             :   // Compares all fields of a {DeoptimizationInfo} except {pc} and {trampoline}.
     270             :   bool IsIdenticalExceptForPc(const DeoptimizationInfo&,
     271             :                               const DeoptimizationInfo&) const;
     272             : 
     273             :   // If all entries are identical, replace them by 1 entry with pc = kMaxUInt32.
     274             :   void RemoveDuplicates();
     275             : 
     276             :   ZoneChunkList<DeoptimizationInfo> deoptimization_info_;
     277             : 
     278             :   unsigned offset_;
     279             :   bool emitted_;
     280             :   size_t last_lazy_safepoint_;
     281             : 
     282             :   Zone* zone_;
     283             : 
     284             :   DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
     285             : };
     286             : 
     287             : }  // namespace internal
     288             : }  // namespace v8
     289             : 
     290             : #endif  // V8_SAFEPOINT_TABLE_H_

Generated by: LCOV version 1.10