blob: 017fc5d6a00347f2709ee0e5d243da4b576c8f1f [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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/hashmap.h"
10#include "src/objects.h"
11
12namespace v8 {
13namespace internal {
14
15class AddressMapBase {
16 protected:
17 static void SetValue(HashMap::Entry* entry, uint32_t v) {
18 entry->value = reinterpret_cast<void*>(v);
19 }
20
21 static uint32_t GetValue(HashMap::Entry* entry) {
22 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
23 }
24
25 inline static HashMap::Entry* LookupEntry(HashMap* map, HeapObject* obj,
26 bool insert) {
27 if (insert) {
28 map->LookupOrInsert(Key(obj), Hash(obj));
29 }
30 return map->Lookup(Key(obj), Hash(obj));
31 }
32
33 private:
34 static uint32_t Hash(HeapObject* obj) {
35 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
36 }
37
38 static void* Key(HeapObject* obj) {
39 return reinterpret_cast<void*>(obj->address());
40 }
41};
42
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043class RootIndexMap : public AddressMapBase {
44 public:
45 explicit RootIndexMap(Isolate* isolate);
46
47 static const int kInvalidRootIndex = -1;
48
49 int Lookup(HeapObject* obj) {
50 HashMap::Entry* entry = LookupEntry(map_, obj, false);
51 if (entry) return GetValue(entry);
52 return kInvalidRootIndex;
53 }
54
55 private:
56 HashMap* map_;
57
58 DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
59};
60
Ben Murdochc5610432016-08-08 18:44:38 +010061class SerializerReference {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 public:
Ben Murdochc5610432016-08-08 18:44:38 +010063 SerializerReference() : bitfield_(Special(kInvalidValue)) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064
Ben Murdochc5610432016-08-08 18:44:38 +010065 static SerializerReference FromBitfield(uint32_t bitfield) {
66 return SerializerReference(bitfield);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 }
68
Ben Murdochc5610432016-08-08 18:44:38 +010069 static SerializerReference BackReference(AllocationSpace space,
70 uint32_t chunk_index,
71 uint32_t chunk_offset) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 DCHECK(IsAligned(chunk_offset, kObjectAlignment));
73 DCHECK_NE(LO_SPACE, space);
Ben Murdochc5610432016-08-08 18:44:38 +010074 return SerializerReference(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) |
76 ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits));
77 }
78
Ben Murdochc5610432016-08-08 18:44:38 +010079 static SerializerReference LargeObjectReference(uint32_t index) {
80 return SerializerReference(SpaceBits::encode(LO_SPACE) |
81 ValueIndexBits::encode(index));
82 }
83
84 static SerializerReference AttachedReference(uint32_t index) {
85 return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) |
86 ValueIndexBits::encode(index));
87 }
88
89 static SerializerReference DummyReference() {
90 return SerializerReference(Special(kDummyValue));
91 }
92
93 bool is_valid() const { return bitfield_ != Special(kInvalidValue); }
94
95 bool is_back_reference() const {
96 return SpaceBits::decode(bitfield_) <= LAST_SPACE;
97 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098
99 AllocationSpace space() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100100 DCHECK(is_back_reference());
101 return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 }
103
104 uint32_t chunk_offset() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100105 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits;
107 }
108
109 uint32_t large_object_index() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100110 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 DCHECK(chunk_index() == 0);
112 return ChunkOffsetBits::decode(bitfield_);
113 }
114
115 uint32_t chunk_index() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100116 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 return ChunkIndexBits::decode(bitfield_);
118 }
119
Ben Murdochc5610432016-08-08 18:44:38 +0100120 uint32_t back_reference() const {
121 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask);
123 }
124
Ben Murdochc5610432016-08-08 18:44:38 +0100125 bool is_attached_reference() const {
126 return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace;
127 }
128
129 int attached_reference_index() const {
130 DCHECK(is_attached_reference());
131 return ValueIndexBits::decode(bitfield_);
132 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133
134 private:
Ben Murdochc5610432016-08-08 18:44:38 +0100135 explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {}
136
137 inline static uint32_t Special(int value) {
138 return SpaceBits::encode(kSpecialValueSpace) |
139 ValueIndexBits::encode(value);
140 }
141
142 // We use the 32-bit bitfield to encode either a back reference, a special
143 // value, or an attached reference index.
144 // Back reference:
145 // [ Space index ] [ Chunk index ] [ Chunk offset ]
146 // [ LO_SPACE ] [ large object index ]
147 // Special value
148 // [ kSpecialValueSpace ] [ Special value index ]
149 // Attached reference
150 // [ kAttachedReferenceSpace ] [ Attached reference index ]
151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
153 static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
Ben Murdochc5610432016-08-08 18:44:38 +0100154 static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155
Ben Murdochc5610432016-08-08 18:44:38 +0100156 static const int kSpecialValueSpace = LAST_SPACE + 1;
157 static const int kAttachedReferenceSpace = kSpecialValueSpace + 1;
158 STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159
Ben Murdochc5610432016-08-08 18:44:38 +0100160 static const int kInvalidValue = 0;
161 static const int kDummyValue = 1;
162
163 // The chunk offset can also be used to encode the index of special values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {};
165 class ChunkIndexBits
166 : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {};
Ben Murdochc5610432016-08-08 18:44:38 +0100167 class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {};
168 STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext);
169 class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {};
170 STATIC_ASSERT(SpaceBits::kNext == 32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171
172 uint32_t bitfield_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173
Ben Murdochc5610432016-08-08 18:44:38 +0100174 friend class SerializerReferenceMap;
175};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176
177// Mapping objects to their location after deserialization.
178// This is used during building, but not at runtime by V8.
Ben Murdochc5610432016-08-08 18:44:38 +0100179class SerializerReferenceMap : public AddressMapBase {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 public:
Ben Murdochc5610432016-08-08 18:44:38 +0100181 SerializerReferenceMap()
182 : no_allocation_(),
183 map_(HashMap::PointersMatch),
184 attached_reference_index_(0) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185
Ben Murdochc5610432016-08-08 18:44:38 +0100186 SerializerReference Lookup(HeapObject* obj) {
187 HashMap::Entry* entry = LookupEntry(&map_, obj, false);
188 return entry ? SerializerReference(GetValue(entry)) : SerializerReference();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 }
190
Ben Murdochc5610432016-08-08 18:44:38 +0100191 void Add(HeapObject* obj, SerializerReference b) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 DCHECK(b.is_valid());
Ben Murdochc5610432016-08-08 18:44:38 +0100193 DCHECK_NULL(LookupEntry(&map_, obj, false));
194 HashMap::Entry* entry = LookupEntry(&map_, obj, true);
195 SetValue(entry, b.bitfield_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 }
197
Ben Murdochc5610432016-08-08 18:44:38 +0100198 SerializerReference AddAttachedReference(HeapObject* attached_reference) {
199 SerializerReference reference =
200 SerializerReference::AttachedReference(attached_reference_index_++);
201 Add(attached_reference, reference);
202 return reference;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 }
204
205 private:
206 DisallowHeapAllocation no_allocation_;
Ben Murdochc5610432016-08-08 18:44:38 +0100207 HashMap map_;
208 int attached_reference_index_;
209 DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210};
211
212} // namespace internal
213} // namespace v8
214
215#endif // V8_ADDRESS_MAP_H_