• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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