1 // Copyright 2020 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_ZONE_COMPRESSED_ZONE_PTR_H_ 6 #define V8_ZONE_COMPRESSED_ZONE_PTR_H_ 7 8 #include <type_traits> 9 10 #include "src/base/logging.h" 11 #include "src/common/globals.h" 12 #include "src/zone/zone-compression.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // 18 // Compressed pointer to T using aligned-base-relative addressing compression. 19 // 20 // Note that the CompressedZonePtr<T> is implicitly convertible to T*. 21 // Such an approach provides the benefit of almost seamless migration of a code 22 // using full pointers to compressed pointers. 23 // However, using CompressedZonePtr<T> in containers is not allowed yet. 24 // 25 // It's not recommended to use this class directly, use ZoneTypeTraits::Ptr<T> 26 // instead. 27 template <typename T> 28 class CompressedZonePtr { 29 public: 30 CompressedZonePtr() = default; CompressedZonePtr(std::nullptr_t)31 explicit CompressedZonePtr(std::nullptr_t) : CompressedZonePtr() {} CompressedZonePtr(T * value)32 explicit CompressedZonePtr(T* value) { *this = value; } 33 // Move- and copy-constructors are explicitly deleted in order to avoid 34 // creation of temporary objects which we can't uncompress because they will 35 // live outside of the zone memory. 36 CompressedZonePtr(const CompressedZonePtr& other) V8_NOEXCEPT = delete; 37 CompressedZonePtr(CompressedZonePtr&&) V8_NOEXCEPT = delete; 38 39 CompressedZonePtr& operator=(const CompressedZonePtr& other) V8_NOEXCEPT { 40 DCHECK(ZoneCompression::CheckSameBase(this, &other)); 41 compressed_value_ = other.compressed_value_; 42 return *this; 43 } 44 CompressedZonePtr& operator=(CompressedZonePtr&& other) V8_NOEXCEPT = delete; 45 46 CompressedZonePtr& operator=(T* value) { 47 compressed_value_ = ZoneCompression::Compress(value); 48 DCHECK_EQ(value, Decompress()); 49 return *this; 50 } 51 52 bool operator==(std::nullptr_t) const { return compressed_value_ == 0; } 53 bool operator!=(std::nullptr_t) const { return compressed_value_ != 0; } 54 55 // The equality comparisons assume that both operands point to objects 56 // allocated by the same allocator supporting pointer compression, therefore 57 // it's enough to compare compressed values. 58 bool operator==(const CompressedZonePtr& other) const { 59 return compressed_value_ == other.compressed_value_; 60 } 61 bool operator!=(const CompressedZonePtr& other) const { 62 return !(*this == other); 63 } 64 bool operator==(T* other) const { 65 return compressed_value_ == ZoneCompression::Compress(other); 66 } 67 bool operator!=(T* other) const { return !(*this == other); } 68 69 T& operator*() const { return *Decompress(); } 70 T* operator->() const { return Decompress(); } 71 72 operator T*() const { return Decompress(); } 73 operator bool() const { return compressed_value_ != 0; } 74 75 private: Decompress()76 T* Decompress() const { 77 return reinterpret_cast<T*>( 78 ZoneCompression::Decompress(this, compressed_value_)); 79 } 80 81 uint32_t compressed_value_ = 0; 82 }; 83 84 // This requirement is necessary for being able to use memcopy in containers 85 // of zone pointers. 86 // TODO(ishell): Re-enable once compressed pointers are supported in containers. 87 // static_assert(std::is_trivially_copyable<CompressedZonePtr<int>>::value, 88 // "CompressedZonePtr must be trivially copyable"); 89 90 } // namespace internal 91 } // namespace v8 92 93 #endif // V8_ZONE_COMPRESSED_ZONE_PTR_H_ 94