• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SNAPSHOT_REFERENCES_H_
6 #define V8_SNAPSHOT_REFERENCES_H_
7 
8 #include "src/assert-scope.h"
9 #include "src/base/hashmap.h"
10 #include "src/utils.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 class SerializerReference {
16  private:
17   enum SpecialValueType {
18     kInvalidValue,
19     kAttachedReference,
20     kOffHeapBackingStore,
21     kBuiltinReference,
22   };
23 
24   static const int kSpecialValueSpace = LAST_SPACE + 1;
25   STATIC_ASSERT(kSpecialValueSpace < (1 << kSpaceTagSize));
26 
SerializerReference(SpecialValueType type,uint32_t value)27   SerializerReference(SpecialValueType type, uint32_t value)
28       : bitfield_(SpaceBits::encode(kSpecialValueSpace) |
29                   SpecialValueTypeBits::encode(type)),
30         value_(value) {}
31 
32  public:
SerializerReference()33   SerializerReference() : SerializerReference(kInvalidValue, 0) {}
34 
SerializerReference(uint32_t space,uint32_t chunk_index,uint32_t chunk_offset)35   SerializerReference(uint32_t space, uint32_t chunk_index,
36                       uint32_t chunk_offset)
37       : bitfield_(SpaceBits::encode(space) |
38                   ChunkIndexBits::encode(chunk_index)),
39         value_(chunk_offset) {}
40 
BackReference(AllocationSpace space,uint32_t chunk_index,uint32_t chunk_offset)41   static SerializerReference BackReference(AllocationSpace space,
42                                            uint32_t chunk_index,
43                                            uint32_t chunk_offset) {
44     DCHECK(IsAligned(chunk_offset, kObjectAlignment));
45     DCHECK_LT(space, LO_SPACE);
46     return SerializerReference(space, chunk_index, chunk_offset);
47   }
48 
MapReference(uint32_t index)49   static SerializerReference MapReference(uint32_t index) {
50     return SerializerReference(MAP_SPACE, 0, index);
51   }
52 
OffHeapBackingStoreReference(uint32_t index)53   static SerializerReference OffHeapBackingStoreReference(uint32_t index) {
54     return SerializerReference(kOffHeapBackingStore, index);
55   }
56 
LargeObjectReference(uint32_t index)57   static SerializerReference LargeObjectReference(uint32_t index) {
58     return SerializerReference(LO_SPACE, 0, index);
59   }
60 
AttachedReference(uint32_t index)61   static SerializerReference AttachedReference(uint32_t index) {
62     return SerializerReference(kAttachedReference, index);
63   }
64 
BuiltinReference(uint32_t index)65   static SerializerReference BuiltinReference(uint32_t index) {
66     return SerializerReference(kBuiltinReference, index);
67   }
68 
is_valid()69   bool is_valid() const {
70     return SpaceBits::decode(bitfield_) != kSpecialValueSpace ||
71            SpecialValueTypeBits::decode(bitfield_) != kInvalidValue;
72   }
73 
is_back_reference()74   bool is_back_reference() const {
75     return SpaceBits::decode(bitfield_) <= LAST_SPACE;
76   }
77 
space()78   AllocationSpace space() const {
79     DCHECK(is_back_reference());
80     return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_));
81   }
82 
chunk_offset()83   uint32_t chunk_offset() const {
84     DCHECK(is_back_reference());
85     return value_;
86   }
87 
chunk_index()88   uint32_t chunk_index() const {
89     DCHECK(space() != MAP_SPACE && space() != LO_SPACE);
90     return ChunkIndexBits::decode(bitfield_);
91   }
92 
map_index()93   uint32_t map_index() const {
94     DCHECK_EQ(MAP_SPACE, SpaceBits::decode(bitfield_));
95     return value_;
96   }
97 
is_off_heap_backing_store_reference()98   bool is_off_heap_backing_store_reference() const {
99     return SpaceBits::decode(bitfield_) == kSpecialValueSpace &&
100            SpecialValueTypeBits::decode(bitfield_) == kOffHeapBackingStore;
101   }
102 
off_heap_backing_store_index()103   uint32_t off_heap_backing_store_index() const {
104     DCHECK(is_off_heap_backing_store_reference());
105     return value_;
106   }
107 
large_object_index()108   uint32_t large_object_index() const {
109     DCHECK_EQ(LO_SPACE, SpaceBits::decode(bitfield_));
110     return value_;
111   }
112 
is_attached_reference()113   bool is_attached_reference() const {
114     return SpaceBits::decode(bitfield_) == kSpecialValueSpace &&
115            SpecialValueTypeBits::decode(bitfield_) == kAttachedReference;
116   }
117 
attached_reference_index()118   uint32_t attached_reference_index() const {
119     DCHECK(is_attached_reference());
120     return value_;
121   }
122 
is_builtin_reference()123   bool is_builtin_reference() const {
124     return SpaceBits::decode(bitfield_) == kSpecialValueSpace &&
125            SpecialValueTypeBits::decode(bitfield_) == kBuiltinReference;
126   }
127 
builtin_index()128   uint32_t builtin_index() const {
129     DCHECK(is_builtin_reference());
130     return value_;
131   }
132 
133  private:
134   class SpaceBits : public BitField<int, 0, kSpaceTagSize> {};
135   class ChunkIndexBits
136       : public BitField<uint32_t, SpaceBits::kNext, 32 - kSpaceTagSize> {};
137   class SpecialValueTypeBits
138       : public BitField<SpecialValueType, SpaceBits::kNext,
139                         32 - kSpaceTagSize> {};
140 
141   // We use two fields to store a reference.
142   // In case of a normal back reference, the bitfield_ stores the space and
143   // the chunk index. In case of special references, it uses a special value
144   // for space and stores the special value type.
145   uint32_t bitfield_;
146   // value_ stores either chunk offset or special value.
147   uint32_t value_;
148 
149   friend class SerializerReferenceMap;
150 };
151 
152 class SerializerReferenceMap
153     : public base::TemplateHashMapImpl<uintptr_t, SerializerReference,
154                                        base::KeyEqualityMatcher<intptr_t>,
155                                        base::DefaultAllocationPolicy> {
156  public:
157   typedef base::TemplateHashMapEntry<uintptr_t, SerializerReference> Entry;
158 
SerializerReferenceMap()159   SerializerReferenceMap() : no_allocation_(), attached_reference_index_(0) {}
160 
LookupReference(void * value)161   SerializerReference LookupReference(void* value) const {
162     uintptr_t key = Key(value);
163     Entry* entry = Lookup(key, Hash(key));
164     if (entry == nullptr) return SerializerReference();
165     return entry->value;
166   }
167 
Add(void * obj,SerializerReference reference)168   void Add(void* obj, SerializerReference reference) {
169     DCHECK(reference.is_valid());
170     DCHECK(!LookupReference(obj).is_valid());
171     uintptr_t key = Key(obj);
172     LookupOrInsert(key, Hash(key))->value = reference;
173   }
174 
AddAttachedReference(void * attached_reference)175   SerializerReference AddAttachedReference(void* attached_reference) {
176     SerializerReference reference =
177         SerializerReference::AttachedReference(attached_reference_index_++);
178     Add(attached_reference, reference);
179     return reference;
180   }
181 
182  private:
Key(void * value)183   static inline uintptr_t Key(void* value) {
184     return reinterpret_cast<uintptr_t>(value);
185   }
186 
Hash(uintptr_t key)187   static uint32_t Hash(uintptr_t key) { return static_cast<uint32_t>(key); }
188 
189   DisallowHeapAllocation no_allocation_;
190   int attached_reference_index_;
191   DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
192 };
193 
194 }  // namespace internal
195 }  // namespace v8
196 
197 #endif  // V8_SNAPSHOT_REFERENCES_H_
198