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

Generated by: LCOV version 1.10