// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_ZONE_COMPRESSED_ZONE_PTR_H_ #define V8_ZONE_COMPRESSED_ZONE_PTR_H_ #include <type_traits> #include "src/base/logging.h" #include "src/common/globals.h" #include "src/zone/zone-compression.h" namespace v8 { namespace internal { // // Compressed pointer to T using aligned-base-relative addressing compression. // // Note that the CompressedZonePtr<T> is implicitly convertible to T*. // Such an approach provides the benefit of almost seamless migration of a code // using full pointers to compressed pointers. // However, using CompressedZonePtr<T> in containers is not allowed yet. // // It's not recommended to use this class directly, use ZoneTypeTraits::Ptr<T> // instead. template <typename T> class CompressedZonePtr { public: CompressedZonePtr() = default; explicit CompressedZonePtr(std::nullptr_t) : CompressedZonePtr() {} explicit CompressedZonePtr(T* value) { *this = value; } // Move- and copy-constructors are explicitly deleted in order to avoid // creation of temporary objects which we can't uncompress because they will // live outside of the zone memory. CompressedZonePtr(const CompressedZonePtr& other) V8_NOEXCEPT = delete; CompressedZonePtr(CompressedZonePtr&&) V8_NOEXCEPT = delete; CompressedZonePtr& operator=(const CompressedZonePtr& other) V8_NOEXCEPT { DCHECK(ZoneCompression::CheckSameBase(this, &other)); compressed_value_ = other.compressed_value_; return *this; } CompressedZonePtr& operator=(CompressedZonePtr&& other) V8_NOEXCEPT = delete; CompressedZonePtr& operator=(T* value) { compressed_value_ = ZoneCompression::Compress(value); DCHECK_EQ(value, Decompress()); return *this; } bool operator==(std::nullptr_t) const { return compressed_value_ == 0; } bool operator!=(std::nullptr_t) const { return compressed_value_ != 0; } // The equality comparisons assume that both operands point to objects // allocated by the same allocator supporting pointer compression, therefore // it's enough to compare compressed values. bool operator==(const CompressedZonePtr& other) const { return compressed_value_ == other.compressed_value_; } bool operator!=(const CompressedZonePtr& other) const { return !(*this == other); } bool operator==(T* other) const { return compressed_value_ == ZoneCompression::Compress(other); } bool operator!=(T* other) const { return !(*this == other); } T& operator*() const { return *Decompress(); } T* operator->() const { return Decompress(); } operator T*() const { return Decompress(); } operator bool() const { return compressed_value_ != 0; } private: T* Decompress() const { return reinterpret_cast<T*>( ZoneCompression::Decompress(this, compressed_value_)); } uint32_t compressed_value_ = 0; }; // This requirement is necessary for being able to use memcopy in containers // of zone pointers. // TODO(ishell): Re-enable once compressed pointers are supported in containers. // static_assert(std::is_trivially_copyable<CompressedZonePtr<int>>::value, // "CompressedZonePtr must be trivially copyable"); } // namespace internal } // namespace v8 #endif // V8_ZONE_COMPRESSED_ZONE_PTR_H_