blob: ce2170576a89025b6377658ec22779bb6f848b3c [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"
Ben Murdoch61f157c2016-09-16 13:49:30 +01009#include "src/base/hashmap.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/objects.h"
11
12namespace v8 {
13namespace internal {
14
15class AddressMapBase {
16 protected:
Ben Murdoch61f157c2016-09-16 13:49:30 +010017 static void SetValue(base::HashMap::Entry* entry, uint32_t v) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018 entry->value = reinterpret_cast<void*>(v);
19 }
20
Ben Murdoch61f157c2016-09-16 13:49:30 +010021 static uint32_t GetValue(base::HashMap::Entry* entry) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
23 }
24
Ben Murdoch61f157c2016-09-16 13:49:30 +010025 inline static base::HashMap::Entry* LookupEntry(base::HashMap* map,
26 HeapObject* obj,
27 bool insert) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 if (insert) {
29 map->LookupOrInsert(Key(obj), Hash(obj));
30 }
31 return map->Lookup(Key(obj), Hash(obj));
32 }
33
34 private:
35 static uint32_t Hash(HeapObject* obj) {
36 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
37 }
38
39 static void* Key(HeapObject* obj) {
40 return reinterpret_cast<void*>(obj->address());
41 }
42};
43
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044class RootIndexMap : public AddressMapBase {
45 public:
46 explicit RootIndexMap(Isolate* isolate);
47
48 static const int kInvalidRootIndex = -1;
49
50 int Lookup(HeapObject* obj) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010051 base::HashMap::Entry* entry = LookupEntry(map_, obj, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 if (entry) return GetValue(entry);
53 return kInvalidRootIndex;
54 }
55
56 private:
Ben Murdoch61f157c2016-09-16 13:49:30 +010057 base::HashMap* map_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058
59 DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
60};
61
Ben Murdochc5610432016-08-08 18:44:38 +010062class SerializerReference {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 public:
Ben Murdochc5610432016-08-08 18:44:38 +010064 SerializerReference() : bitfield_(Special(kInvalidValue)) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065
Ben Murdochc5610432016-08-08 18:44:38 +010066 static SerializerReference FromBitfield(uint32_t bitfield) {
67 return SerializerReference(bitfield);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 }
69
Ben Murdochc5610432016-08-08 18:44:38 +010070 static SerializerReference BackReference(AllocationSpace space,
71 uint32_t chunk_index,
72 uint32_t chunk_offset) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 DCHECK(IsAligned(chunk_offset, kObjectAlignment));
74 DCHECK_NE(LO_SPACE, space);
Ben Murdochc5610432016-08-08 18:44:38 +010075 return SerializerReference(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) |
77 ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits));
78 }
79
Ben Murdochc5610432016-08-08 18:44:38 +010080 static SerializerReference LargeObjectReference(uint32_t index) {
81 return SerializerReference(SpaceBits::encode(LO_SPACE) |
82 ValueIndexBits::encode(index));
83 }
84
85 static SerializerReference AttachedReference(uint32_t index) {
86 return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) |
87 ValueIndexBits::encode(index));
88 }
89
90 static SerializerReference DummyReference() {
91 return SerializerReference(Special(kDummyValue));
92 }
93
94 bool is_valid() const { return bitfield_ != Special(kInvalidValue); }
95
96 bool is_back_reference() const {
97 return SpaceBits::decode(bitfield_) <= LAST_SPACE;
98 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099
100 AllocationSpace space() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100101 DCHECK(is_back_reference());
102 return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 }
104
105 uint32_t chunk_offset() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100106 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits;
108 }
109
110 uint32_t large_object_index() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100111 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 DCHECK(chunk_index() == 0);
113 return ChunkOffsetBits::decode(bitfield_);
114 }
115
116 uint32_t chunk_index() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100117 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 return ChunkIndexBits::decode(bitfield_);
119 }
120
Ben Murdochc5610432016-08-08 18:44:38 +0100121 uint32_t back_reference() const {
122 DCHECK(is_back_reference());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask);
124 }
125
Ben Murdochc5610432016-08-08 18:44:38 +0100126 bool is_attached_reference() const {
127 return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace;
128 }
129
130 int attached_reference_index() const {
131 DCHECK(is_attached_reference());
132 return ValueIndexBits::decode(bitfield_);
133 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134
135 private:
Ben Murdochc5610432016-08-08 18:44:38 +0100136 explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {}
137
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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
154 static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
Ben Murdochc5610432016-08-08 18:44:38 +0100155 static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156
Ben Murdochc5610432016-08-08 18:44:38 +0100157 static const int kSpecialValueSpace = LAST_SPACE + 1;
158 static const int kAttachedReferenceSpace = kSpecialValueSpace + 1;
159 STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160
Ben Murdochc5610432016-08-08 18:44:38 +0100161 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.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {};
166 class ChunkIndexBits
167 : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {};
Ben Murdochc5610432016-08-08 18:44:38 +0100168 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172
173 uint32_t bitfield_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174
Ben Murdochc5610432016-08-08 18:44:38 +0100175 friend class SerializerReferenceMap;
176};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177
178// Mapping objects to their location after deserialization.
179// This is used during building, but not at runtime by V8.
Ben Murdochc5610432016-08-08 18:44:38 +0100180class SerializerReferenceMap : public AddressMapBase {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 public:
Ben Murdochc5610432016-08-08 18:44:38 +0100182 SerializerReferenceMap()
183 : no_allocation_(),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100184 map_(base::HashMap::PointersMatch),
Ben Murdochc5610432016-08-08 18:44:38 +0100185 attached_reference_index_(0) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186
Ben Murdochc5610432016-08-08 18:44:38 +0100187 SerializerReference Lookup(HeapObject* obj) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100188 base::HashMap::Entry* entry = LookupEntry(&map_, obj, false);
Ben Murdochc5610432016-08-08 18:44:38 +0100189 return entry ? SerializerReference(GetValue(entry)) : SerializerReference();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000190 }
191
Ben Murdochc5610432016-08-08 18:44:38 +0100192 void Add(HeapObject* obj, SerializerReference b) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 DCHECK(b.is_valid());
Ben Murdochc5610432016-08-08 18:44:38 +0100194 DCHECK_NULL(LookupEntry(&map_, obj, false));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100195 base::HashMap::Entry* entry = LookupEntry(&map_, obj, true);
Ben Murdochc5610432016-08-08 18:44:38 +0100196 SetValue(entry, b.bitfield_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 }
198
Ben Murdochc5610432016-08-08 18:44:38 +0100199 SerializerReference AddAttachedReference(HeapObject* attached_reference) {
200 SerializerReference reference =
201 SerializerReference::AttachedReference(attached_reference_index_++);
202 Add(attached_reference, reference);
203 return reference;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 }
205
206 private:
207 DisallowHeapAllocation no_allocation_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100208 base::HashMap map_;
Ben Murdochc5610432016-08-08 18:44:38 +0100209 int attached_reference_index_;
210 DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211};
212
213} // namespace internal
214} // namespace v8
215
216#endif // V8_ADDRESS_MAP_H_