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/base/bit-field.h"
9 #include "src/base/hashmap.h"
10 #include "src/common/assert-scope.h"
11 #include "src/execution/isolate.h"
12 #include "src/utils/identity-map.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 enum class SnapshotSpace : byte {
18   kReadOnlyHeap,
19   kOld,
20   kCode,
21   kMap,
22 };
23 static constexpr int kNumberOfSnapshotSpaces =
24     static_cast<int>(SnapshotSpace::kMap) + 1;
25 
26 class SerializerReference {
27  private:
28   enum SpecialValueType {
29     kBackReference,
30     kAttachedReference,
31     kOffHeapBackingStore,
32     kBuiltinReference,
33   };
34 
SerializerReference(SpecialValueType type,uint32_t value)35   SerializerReference(SpecialValueType type, uint32_t value)
36       : bit_field_(TypeBits::encode(type) | ValueBits::encode(value)) {}
37 
38  public:
BackReference(uint32_t index)39   static SerializerReference BackReference(uint32_t index) {
40     return SerializerReference(kBackReference, index);
41   }
42 
OffHeapBackingStoreReference(uint32_t index)43   static SerializerReference OffHeapBackingStoreReference(uint32_t index) {
44     return SerializerReference(kOffHeapBackingStore, index);
45   }
46 
AttachedReference(uint32_t index)47   static SerializerReference AttachedReference(uint32_t index) {
48     return SerializerReference(kAttachedReference, index);
49   }
50 
BuiltinReference(uint32_t index)51   static SerializerReference BuiltinReference(uint32_t index) {
52     return SerializerReference(kBuiltinReference, index);
53   }
54 
is_back_reference()55   bool is_back_reference() const {
56     return TypeBits::decode(bit_field_) == kBackReference;
57   }
58 
back_ref_index()59   uint32_t back_ref_index() const {
60     DCHECK(is_back_reference());
61     return ValueBits::decode(bit_field_);
62   }
63 
is_off_heap_backing_store_reference()64   bool is_off_heap_backing_store_reference() const {
65     return TypeBits::decode(bit_field_) == kOffHeapBackingStore;
66   }
67 
off_heap_backing_store_index()68   uint32_t off_heap_backing_store_index() const {
69     DCHECK(is_off_heap_backing_store_reference());
70     return ValueBits::decode(bit_field_);
71   }
72 
is_attached_reference()73   bool is_attached_reference() const {
74     return TypeBits::decode(bit_field_) == kAttachedReference;
75   }
76 
attached_reference_index()77   uint32_t attached_reference_index() const {
78     DCHECK(is_attached_reference());
79     return ValueBits::decode(bit_field_);
80   }
81 
is_builtin_reference()82   bool is_builtin_reference() const {
83     return TypeBits::decode(bit_field_) == kBuiltinReference;
84   }
85 
builtin_index()86   uint32_t builtin_index() const {
87     DCHECK(is_builtin_reference());
88     return ValueBits::decode(bit_field_);
89   }
90 
91  private:
92   using TypeBits = base::BitField<SpecialValueType, 0, 2>;
93   using ValueBits = TypeBits::Next<uint32_t, 32 - TypeBits::kSize>;
94 
95   uint32_t bit_field_;
96 
97   friend class SerializerReferenceMap;
98 };
99 
100 // SerializerReference has to fit in an IdentityMap value field.
101 STATIC_ASSERT(sizeof(SerializerReference) <= sizeof(void*));
102 
103 class SerializerReferenceMap {
104  public:
SerializerReferenceMap(Isolate * isolate)105   explicit SerializerReferenceMap(Isolate* isolate)
106       : map_(isolate->heap()), attached_reference_index_(0) {}
107 
LookupReference(HeapObject object)108   const SerializerReference* LookupReference(HeapObject object) const {
109     return map_.Find(object);
110   }
111 
LookupReference(Handle<HeapObject> object)112   const SerializerReference* LookupReference(Handle<HeapObject> object) const {
113     return map_.Find(object);
114   }
115 
LookupBackingStore(void * backing_store)116   const SerializerReference* LookupBackingStore(void* backing_store) const {
117     auto it = backing_store_map_.find(backing_store);
118     if (it == backing_store_map_.end()) return nullptr;
119     return &it->second;
120   }
121 
Add(HeapObject object,SerializerReference reference)122   void Add(HeapObject object, SerializerReference reference) {
123     DCHECK_NULL(LookupReference(object));
124     map_.Insert(object, reference);
125   }
126 
AddBackingStore(void * backing_store,SerializerReference reference)127   void AddBackingStore(void* backing_store, SerializerReference reference) {
128     DCHECK(backing_store_map_.find(backing_store) == backing_store_map_.end());
129     backing_store_map_.emplace(backing_store, reference);
130   }
131 
AddAttachedReference(HeapObject object)132   SerializerReference AddAttachedReference(HeapObject object) {
133     SerializerReference reference =
134         SerializerReference::AttachedReference(attached_reference_index_++);
135     map_.Insert(object, reference);
136     return reference;
137   }
138 
139  private:
140   IdentityMap<SerializerReference, base::DefaultAllocationPolicy> map_;
141   std::unordered_map<void*, SerializerReference> backing_store_map_;
142   int attached_reference_index_;
143 };
144 
145 }  // namespace internal
146 }  // namespace v8
147 
148 #endif  // V8_SNAPSHOT_REFERENCES_H_
149