• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_ADDRESS_MAP_H_
6 #define V8_ADDRESS_MAP_H_
7 
8 #include "src/assert-scope.h"
9 #include "src/base/hashmap.h"
10 #include "src/objects.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 class AddressMapBase {
16  protected:
SetValue(base::HashMap::Entry * entry,uint32_t v)17   static void SetValue(base::HashMap::Entry* entry, uint32_t v) {
18     entry->value = reinterpret_cast<void*>(v);
19   }
20 
GetValue(base::HashMap::Entry * entry)21   static uint32_t GetValue(base::HashMap::Entry* entry) {
22     return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
23   }
24 
LookupEntry(base::HashMap * map,HeapObject * obj,bool insert)25   inline static base::HashMap::Entry* LookupEntry(base::HashMap* map,
26                                                   HeapObject* obj,
27                                                   bool insert) {
28     if (insert) {
29       map->LookupOrInsert(Key(obj), Hash(obj));
30     }
31     return map->Lookup(Key(obj), Hash(obj));
32   }
33 
34  private:
Hash(HeapObject * obj)35   static uint32_t Hash(HeapObject* obj) {
36     return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
37   }
38 
Key(HeapObject * obj)39   static void* Key(HeapObject* obj) {
40     return reinterpret_cast<void*>(obj->address());
41   }
42 };
43 
44 class RootIndexMap : public AddressMapBase {
45  public:
46   explicit RootIndexMap(Isolate* isolate);
47 
48   static const int kInvalidRootIndex = -1;
49 
Lookup(HeapObject * obj)50   int Lookup(HeapObject* obj) {
51     base::HashMap::Entry* entry = LookupEntry(map_, obj, false);
52     if (entry) return GetValue(entry);
53     return kInvalidRootIndex;
54   }
55 
56  private:
57   base::HashMap* map_;
58 
59   DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
60 };
61 
62 class SerializerReference {
63  public:
SerializerReference()64   SerializerReference() : bitfield_(Special(kInvalidValue)) {}
65 
FromBitfield(uint32_t bitfield)66   static SerializerReference FromBitfield(uint32_t bitfield) {
67     return SerializerReference(bitfield);
68   }
69 
BackReference(AllocationSpace space,uint32_t chunk_index,uint32_t chunk_offset)70   static SerializerReference BackReference(AllocationSpace space,
71                                            uint32_t chunk_index,
72                                            uint32_t chunk_offset) {
73     DCHECK(IsAligned(chunk_offset, kObjectAlignment));
74     DCHECK_NE(LO_SPACE, space);
75     return SerializerReference(
76         SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) |
77         ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits));
78   }
79 
LargeObjectReference(uint32_t index)80   static SerializerReference LargeObjectReference(uint32_t index) {
81     return SerializerReference(SpaceBits::encode(LO_SPACE) |
82                                ValueIndexBits::encode(index));
83   }
84 
AttachedReference(uint32_t index)85   static SerializerReference AttachedReference(uint32_t index) {
86     return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) |
87                                ValueIndexBits::encode(index));
88   }
89 
DummyReference()90   static SerializerReference DummyReference() {
91     return SerializerReference(Special(kDummyValue));
92   }
93 
is_valid()94   bool is_valid() const { return bitfield_ != Special(kInvalidValue); }
95 
is_back_reference()96   bool is_back_reference() const {
97     return SpaceBits::decode(bitfield_) <= LAST_SPACE;
98   }
99 
space()100   AllocationSpace space() const {
101     DCHECK(is_back_reference());
102     return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_));
103   }
104 
chunk_offset()105   uint32_t chunk_offset() const {
106     DCHECK(is_back_reference());
107     return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits;
108   }
109 
large_object_index()110   uint32_t large_object_index() const {
111     DCHECK(is_back_reference());
112     DCHECK(chunk_index() == 0);
113     return ChunkOffsetBits::decode(bitfield_);
114   }
115 
chunk_index()116   uint32_t chunk_index() const {
117     DCHECK(is_back_reference());
118     return ChunkIndexBits::decode(bitfield_);
119   }
120 
back_reference()121   uint32_t back_reference() const {
122     DCHECK(is_back_reference());
123     return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask);
124   }
125 
is_attached_reference()126   bool is_attached_reference() const {
127     return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace;
128   }
129 
attached_reference_index()130   int attached_reference_index() const {
131     DCHECK(is_attached_reference());
132     return ValueIndexBits::decode(bitfield_);
133   }
134 
135  private:
SerializerReference(uint32_t bitfield)136   explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {}
137 
Special(int value)138   inline static uint32_t Special(int value) {
139     return SpaceBits::encode(kSpecialValueSpace) |
140            ValueIndexBits::encode(value);
141   }
142 
143   // We use the 32-bit bitfield to encode either a back reference, a special
144   // value, or an attached reference index.
145   // Back reference:
146   //   [ Space index             ] [ Chunk index ] [ Chunk offset ]
147   //   [ LO_SPACE                ] [ large object index           ]
148   // Special value
149   //   [ kSpecialValueSpace      ] [ Special value index          ]
150   // Attached reference
151   //   [ kAttachedReferenceSpace ] [ Attached reference index     ]
152 
153   static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
154   static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
155   static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize;
156 
157   static const int kSpecialValueSpace = LAST_SPACE + 1;
158   static const int kAttachedReferenceSpace = kSpecialValueSpace + 1;
159   STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize));
160 
161   static const int kInvalidValue = 0;
162   static const int kDummyValue = 1;
163 
164   // The chunk offset can also be used to encode the index of special values.
165   class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {};
166   class ChunkIndexBits
167       : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {};
168   class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {};
169   STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext);
170   class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {};
171   STATIC_ASSERT(SpaceBits::kNext == 32);
172 
173   uint32_t bitfield_;
174 
175   friend class SerializerReferenceMap;
176 };
177 
178 // Mapping objects to their location after deserialization.
179 // This is used during building, but not at runtime by V8.
180 class SerializerReferenceMap : public AddressMapBase {
181  public:
SerializerReferenceMap()182   SerializerReferenceMap()
183       : no_allocation_(),
184         map_(base::HashMap::PointersMatch),
185         attached_reference_index_(0) {}
186 
Lookup(HeapObject * obj)187   SerializerReference Lookup(HeapObject* obj) {
188     base::HashMap::Entry* entry = LookupEntry(&map_, obj, false);
189     return entry ? SerializerReference(GetValue(entry)) : SerializerReference();
190   }
191 
Add(HeapObject * obj,SerializerReference b)192   void Add(HeapObject* obj, SerializerReference b) {
193     DCHECK(b.is_valid());
194     DCHECK_NULL(LookupEntry(&map_, obj, false));
195     base::HashMap::Entry* entry = LookupEntry(&map_, obj, true);
196     SetValue(entry, b.bitfield_);
197   }
198 
AddAttachedReference(HeapObject * attached_reference)199   SerializerReference AddAttachedReference(HeapObject* attached_reference) {
200     SerializerReference reference =
201         SerializerReference::AttachedReference(attached_reference_index_++);
202     Add(attached_reference, reference);
203     return reference;
204   }
205 
206  private:
207   DisallowHeapAllocation no_allocation_;
208   base::HashMap map_;
209   int attached_reference_index_;
210   DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
211 };
212 
213 }  // namespace internal
214 }  // namespace v8
215 
216 #endif  // V8_ADDRESS_MAP_H_
217