LCOV - code coverage report
Current view: top level - src/objects - slots.h (source / functions) Hit Total Coverage
Test: app.info Lines: 24 26 92.3 %
Date: 2019-04-18 Functions: 11 12 91.7 %

          Line data    Source code
       1             : // Copyright 2018 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_OBJECTS_SLOTS_H_
       6             : #define V8_OBJECTS_SLOTS_H_
       7             : 
       8             : #include "src/globals.h"
       9             : #include "src/v8memory.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : class Object;
      15             : 
      16             : template <typename Subclass, typename Data,
      17             :           size_t SlotDataAlignment = sizeof(Data)>
      18             : class SlotBase {
      19             :  public:
      20             :   using TData = Data;
      21             : 
      22             :   static constexpr size_t kSlotDataSize = sizeof(Data);
      23             :   static constexpr size_t kSlotDataAlignment = SlotDataAlignment;
      24             : 
      25   399619004 :   Subclass& operator++() {  // Prefix increment.
      26  9755662632 :     ptr_ += kSlotDataSize;
      27   399619004 :     return *static_cast<Subclass*>(this);
      28             :   }
      29             :   Subclass operator++(int) {  // Postfix increment.
      30             :     Subclass result = *static_cast<Subclass*>(this);
      31     2309910 :     ptr_ += kSlotDataSize;
      32             :     return result;
      33             :   }
      34             :   Subclass& operator--() {  // Prefix decrement.
      35   318116808 :     ptr_ -= kSlotDataSize;
      36             :     return *static_cast<Subclass*>(this);
      37             :   }
      38             :   Subclass operator--(int) {  // Postfix decrement.
      39             :     Subclass result = *static_cast<Subclass*>(this);
      40             :     ptr_ -= kSlotDataSize;
      41             :     return result;
      42             :   }
      43             : 
      44  4581826351 :   bool operator<(const SlotBase& other) const { return ptr_ < other.ptr_; }
      45    13468208 :   bool operator<=(const SlotBase& other) const { return ptr_ <= other.ptr_; }
      46             :   bool operator>(const SlotBase& other) const { return ptr_ > other.ptr_; }
      47             :   bool operator>=(const SlotBase& other) const { return ptr_ >= other.ptr_; }
      48     7282168 :   bool operator==(const SlotBase& other) const { return ptr_ == other.ptr_; }
      49      522268 :   bool operator!=(const SlotBase& other) const { return ptr_ != other.ptr_; }
      50             :   size_t operator-(const SlotBase& other) const {
      51             :     DCHECK_GE(ptr_, other.ptr_);
      52    22815363 :     return static_cast<size_t>((ptr_ - other.ptr_) / kSlotDataSize);
      53             :   }
      54             :   Subclass operator-(int i) const { return Subclass(ptr_ - i * kSlotDataSize); }
      55  3378032836 :   Subclass operator+(int i) const { return Subclass(ptr_ + i * kSlotDataSize); }
      56             :   friend Subclass operator+(int i, const Subclass& slot) {
      57             :     return Subclass(slot.ptr_ + i * kSlotDataSize);
      58             :   }
      59             :   Subclass& operator+=(int i) {
      60   489524615 :     ptr_ += i * kSlotDataSize;
      61             :     return *static_cast<Subclass*>(this);
      62             :   }
      63     1400848 :   Subclass operator-(int i) { return Subclass(ptr_ - i * kSlotDataSize); }
      64             :   Subclass& operator-=(int i) {
      65             :     ptr_ -= i * kSlotDataSize;
      66             :     return *static_cast<Subclass*>(this);
      67             :   }
      68             : 
      69   495333487 :   void* ToVoidPtr() const { return reinterpret_cast<void*>(address()); }
      70             : 
      71  2149703936 :   Address address() const { return ptr_; }
      72             :   // For symmetry with Handle.
      73 66238413463 :   TData* location() const { return reinterpret_cast<TData*>(ptr_); }
      74             : 
      75             :  protected:
      76  5477029928 :   explicit SlotBase(Address ptr) : ptr_(ptr) {
      77             :     DCHECK(IsAligned(ptr, kSlotDataAlignment));
      78     1155115 :   }
      79             : 
      80             :  private:
      81             :   // This field usually describes an on-heap address (a slot within an object),
      82             :   // so its type should not be a pointer to another C++ wrapper class.
      83             :   // Type safety is provided by well-defined conversion operations.
      84             :   Address ptr_;
      85             : };
      86             : 
      87             : // An FullObjectSlot instance describes a kSystemPointerSize-sized field
      88             : // ("slot") holding a tagged pointer (smi or strong heap object).
      89             : // Its address() is the address of the slot.
      90             : // The slot's contents can be read and written using operator* and store().
      91             : class FullObjectSlot : public SlotBase<FullObjectSlot, Address> {
      92             :  public:
      93             :   using TObject = Object;
      94             :   using THeapObjectSlot = FullHeapObjectSlot;
      95             : 
      96             :   // Tagged value stored in this slot is guaranteed to never be a weak pointer.
      97             :   static constexpr bool kCanBeWeak = false;
      98             : 
      99             :   FullObjectSlot() : SlotBase(kNullAddress) {}
     100   347353372 :   explicit FullObjectSlot(Address ptr) : SlotBase(ptr) {}
     101             :   explicit FullObjectSlot(const Address* ptr)
     102    68594020 :       : SlotBase(reinterpret_cast<Address>(ptr)) {}
     103             :   inline explicit FullObjectSlot(Object* object);
     104             :   template <typename T>
     105             :   explicit FullObjectSlot(SlotBase<T, TData, kSlotDataAlignment> slot)
     106             :       : SlotBase(slot.address()) {}
     107             : 
     108             :   // Compares memory representation of a value stored in the slot with given
     109             :   // raw value.
     110             :   inline bool contains_value(Address raw_value) const;
     111             : 
     112             :   inline const Object operator*() const;
     113             :   inline void store(Object value) const;
     114             : 
     115             :   inline Object Acquire_Load() const;
     116             :   inline Object Relaxed_Load() const;
     117             :   inline void Relaxed_Store(Object value) const;
     118             :   inline void Release_Store(Object value) const;
     119             :   inline Object Release_CompareAndSwap(Object old, Object target) const;
     120             : };
     121             : 
     122             : // A FullMaybeObjectSlot instance describes a kSystemPointerSize-sized field
     123             : // ("slot") holding a possibly-weak tagged pointer (think: MaybeObject).
     124             : // Its address() is the address of the slot.
     125             : // The slot's contents can be read and written using operator* and store().
     126             : class FullMaybeObjectSlot
     127             :     : public SlotBase<FullMaybeObjectSlot, Address, kSystemPointerSize> {
     128             :  public:
     129             :   using TObject = MaybeObject;
     130             :   using THeapObjectSlot = FullHeapObjectSlot;
     131             : 
     132             :   // Tagged value stored in this slot can be a weak pointer.
     133             :   static constexpr bool kCanBeWeak = true;
     134             : 
     135             :   FullMaybeObjectSlot() : SlotBase(kNullAddress) {}
     136             :   explicit FullMaybeObjectSlot(Address ptr) : SlotBase(ptr) {}
     137             :   explicit FullMaybeObjectSlot(Object* ptr)
     138      389672 :       : SlotBase(reinterpret_cast<Address>(ptr)) {}
     139             :   explicit FullMaybeObjectSlot(MaybeObject* ptr)
     140   175945290 :       : SlotBase(reinterpret_cast<Address>(ptr)) {}
     141             :   template <typename T>
     142             :   explicit FullMaybeObjectSlot(SlotBase<T, TData, kSlotDataAlignment> slot)
     143             :       : SlotBase(slot.address()) {}
     144             : 
     145             :   inline const MaybeObject operator*() const;
     146             :   inline void store(MaybeObject value) const;
     147             : 
     148             :   inline MaybeObject Relaxed_Load() const;
     149             :   inline void Relaxed_Store(MaybeObject value) const;
     150             :   inline void Release_CompareAndSwap(MaybeObject old, MaybeObject target) const;
     151             : };
     152             : 
     153             : // A FullHeapObjectSlot instance describes a kSystemPointerSize-sized field
     154             : // ("slot") holding a weak or strong pointer to a heap object (think:
     155             : // HeapObjectReference).
     156             : // Its address() is the address of the slot.
     157             : // The slot's contents can be read and written using operator* and store().
     158             : // In case it is known that that slot contains a strong heap object pointer,
     159             : // ToHeapObject() can be used to retrieve that heap object.
     160             : class FullHeapObjectSlot : public SlotBase<FullHeapObjectSlot, Address> {
     161             :  public:
     162             :   FullHeapObjectSlot() : SlotBase(kNullAddress) {}
     163             :   explicit FullHeapObjectSlot(Address ptr) : SlotBase(ptr) {}
     164           0 :   explicit FullHeapObjectSlot(Object* ptr)
     165           0 :       : SlotBase(reinterpret_cast<Address>(ptr)) {}
     166             :   template <typename T>
     167     5701012 :   explicit FullHeapObjectSlot(SlotBase<T, TData, kSlotDataAlignment> slot)
     168     5701012 :       : SlotBase(slot.address()) {}
     169             : 
     170             :   inline const HeapObjectReference operator*() const;
     171             :   inline void store(HeapObjectReference value) const;
     172             : 
     173             :   inline HeapObject ToHeapObject() const;
     174             : 
     175             :   inline void StoreHeapObject(HeapObject value) const;
     176             : };
     177             : 
     178             : // TODO(ishell, v8:8875): When pointer compression is enabled the [u]intptr_t
     179             : // and double fields are only kTaggedSize aligned so in order to avoid undefined
     180             : // behavior in C++ code we use this iterator adaptor when using STL algorithms
     181             : // with unaligned pointers.
     182             : // It will be removed once all v8:8875 is fixed and all the full pointer and
     183             : // double values in compressed V8 heap are properly aligned.
     184             : template <typename T>
     185             : class UnalignedSlot : public SlotBase<UnalignedSlot<T>, T, 1> {
     186             :  public:
     187             :   // This class is a stand-in for "T&" that uses custom read/write operations
     188             :   // for the actual memory accesses.
     189             :   class Reference {
     190             :    public:
     191             :     explicit Reference(Address address) : address_(address) {}
     192             :     Reference(const Reference&) V8_NOEXCEPT = default;
     193             : 
     194             :     Reference& operator=(const Reference& other) V8_NOEXCEPT {
     195             :       WriteUnalignedValue<T>(address_, other.value());
     196             :       return *this;
     197             :     }
     198             :     Reference& operator=(T value) {
     199             :       WriteUnalignedValue<T>(address_, value);
     200             :       return *this;
     201             :     }
     202             : 
     203             :     // Values of type UnalignedSlot::reference must be implicitly convertible
     204             :     // to UnalignedSlot::value_type.
     205             :     operator T() const { return value(); }
     206             : 
     207             :     void swap(Reference& other) {
     208             :       T tmp = value();
     209             :       WriteUnalignedValue<T>(address_, other.value());
     210             :       WriteUnalignedValue<T>(other.address_, tmp);
     211             :     }
     212             : 
     213             :     bool operator<(const Reference& other) const {
     214             :       return value() < other.value();
     215             :     }
     216             : 
     217             :     bool operator==(const Reference& other) const {
     218             :       return value() == other.value();
     219             :     }
     220             : 
     221             :    private:
     222             :     T value() const { return ReadUnalignedValue<T>(address_); }
     223             : 
     224             :     Address address_;
     225             :   };
     226             : 
     227             :   // The rest of this class follows C++'s "RandomAccessIterator" requirements.
     228             :   // Most of the heavy lifting is inherited from SlotBase.
     229             :   using difference_type = int;
     230             :   using value_type = T;
     231             :   using reference = Reference;
     232             :   using pointer = T*;
     233             :   using iterator_category = std::random_access_iterator_tag;
     234             : 
     235             :   UnalignedSlot() : SlotBase<UnalignedSlot<T>, T, 1>(kNullAddress) {}
     236             :   explicit UnalignedSlot(Address address)
     237             :       : SlotBase<UnalignedSlot<T>, T, 1>(address) {}
     238             :   explicit UnalignedSlot(T* address)
     239             :       : SlotBase<UnalignedSlot<T>, T, 1>(reinterpret_cast<Address>(address)) {}
     240             : 
     241             :   Reference operator*() const {
     242             :     return Reference(SlotBase<UnalignedSlot<T>, T, 1>::address());
     243             :   }
     244             :   Reference operator[](difference_type i) const {
     245             :     return Reference(SlotBase<UnalignedSlot<T>, T, 1>::address() +
     246             :                      i * sizeof(T));
     247             :   }
     248             : 
     249             :   friend void swap(Reference lhs, Reference rhs) { lhs.swap(rhs); }
     250             : 
     251             :   friend difference_type operator-(UnalignedSlot a, UnalignedSlot b) {
     252             :     return static_cast<int>(a.address() - b.address()) / sizeof(T);
     253             :   }
     254             : };
     255             : 
     256             : }  // namespace internal
     257             : }  // namespace v8
     258             : 
     259             : #endif  // V8_OBJECTS_SLOTS_H_

Generated by: LCOV version 1.10