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

Generated by: LCOV version 1.10