Index: src/address-map.h |
diff --git a/src/address-map.h b/src/address-map.h |
index df32f89c1ea33cd78bf6c386245b013ac2c1832c..017fc5d6a00347f2709ee0e5d243da4b576c8f1f 100644 |
--- a/src/address-map.h |
+++ b/src/address-map.h |
@@ -40,7 +40,6 @@ class AddressMapBase { |
} |
}; |
- |
class RootIndexMap : public AddressMapBase { |
public: |
explicit RootIndexMap(Isolate* isolate); |
@@ -59,123 +58,155 @@ class RootIndexMap : public AddressMapBase { |
DISALLOW_COPY_AND_ASSIGN(RootIndexMap); |
}; |
- |
-class BackReference { |
+class SerializerReference { |
public: |
- explicit BackReference(uint32_t bitfield) : bitfield_(bitfield) {} |
- |
- BackReference() : bitfield_(kInvalidValue) {} |
- |
- static BackReference SourceReference() { return BackReference(kSourceValue); } |
+ SerializerReference() : bitfield_(Special(kInvalidValue)) {} |
- static BackReference GlobalProxyReference() { |
- return BackReference(kGlobalProxyValue); |
+ static SerializerReference FromBitfield(uint32_t bitfield) { |
+ return SerializerReference(bitfield); |
} |
- static BackReference LargeObjectReference(uint32_t index) { |
- return BackReference(SpaceBits::encode(LO_SPACE) | |
- ChunkOffsetBits::encode(index)); |
- } |
- |
- static BackReference DummyReference() { return BackReference(kDummyValue); } |
- |
- static BackReference Reference(AllocationSpace space, uint32_t chunk_index, |
- uint32_t chunk_offset) { |
+ static SerializerReference BackReference(AllocationSpace space, |
+ uint32_t chunk_index, |
+ uint32_t chunk_offset) { |
DCHECK(IsAligned(chunk_offset, kObjectAlignment)); |
DCHECK_NE(LO_SPACE, space); |
- return BackReference( |
+ return SerializerReference( |
SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) | |
ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits)); |
} |
- bool is_valid() const { return bitfield_ != kInvalidValue; } |
- bool is_source() const { return bitfield_ == kSourceValue; } |
- bool is_global_proxy() const { return bitfield_ == kGlobalProxyValue; } |
+ static SerializerReference LargeObjectReference(uint32_t index) { |
+ return SerializerReference(SpaceBits::encode(LO_SPACE) | |
+ ValueIndexBits::encode(index)); |
+ } |
+ |
+ static SerializerReference AttachedReference(uint32_t index) { |
+ return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) | |
+ ValueIndexBits::encode(index)); |
+ } |
+ |
+ static SerializerReference DummyReference() { |
+ return SerializerReference(Special(kDummyValue)); |
+ } |
+ |
+ bool is_valid() const { return bitfield_ != Special(kInvalidValue); } |
+ |
+ bool is_back_reference() const { |
+ return SpaceBits::decode(bitfield_) <= LAST_SPACE; |
+ } |
AllocationSpace space() const { |
- DCHECK(is_valid()); |
- return SpaceBits::decode(bitfield_); |
+ DCHECK(is_back_reference()); |
+ return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_)); |
} |
uint32_t chunk_offset() const { |
- DCHECK(is_valid()); |
+ DCHECK(is_back_reference()); |
return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits; |
} |
uint32_t large_object_index() const { |
- DCHECK(is_valid()); |
+ DCHECK(is_back_reference()); |
DCHECK(chunk_index() == 0); |
return ChunkOffsetBits::decode(bitfield_); |
} |
uint32_t chunk_index() const { |
- DCHECK(is_valid()); |
+ DCHECK(is_back_reference()); |
return ChunkIndexBits::decode(bitfield_); |
} |
- uint32_t reference() const { |
- DCHECK(is_valid()); |
+ uint32_t back_reference() const { |
+ DCHECK(is_back_reference()); |
return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask); |
} |
- uint32_t bitfield() const { return bitfield_; } |
+ bool is_attached_reference() const { |
+ return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace; |
+ } |
+ |
+ int attached_reference_index() const { |
+ DCHECK(is_attached_reference()); |
+ return ValueIndexBits::decode(bitfield_); |
+ } |
private: |
- static const uint32_t kInvalidValue = 0xFFFFFFFF; |
- static const uint32_t kSourceValue = 0xFFFFFFFE; |
- static const uint32_t kGlobalProxyValue = 0xFFFFFFFD; |
- static const uint32_t kDummyValue = 0xFFFFFFFC; |
+ explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {} |
+ |
+ inline static uint32_t Special(int value) { |
+ return SpaceBits::encode(kSpecialValueSpace) | |
+ ValueIndexBits::encode(value); |
+ } |
+ |
+ // We use the 32-bit bitfield to encode either a back reference, a special |
+ // value, or an attached reference index. |
+ // Back reference: |
+ // [ Space index ] [ Chunk index ] [ Chunk offset ] |
+ // [ LO_SPACE ] [ large object index ] |
+ // Special value |
+ // [ kSpecialValueSpace ] [ Special value index ] |
+ // Attached reference |
+ // [ kAttachedReferenceSpace ] [ Attached reference index ] |
+ |
static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits; |
static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize; |
+ static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize; |
- public: |
- static const int kMaxChunkIndex = (1 << kChunkIndexSize) - 1; |
+ static const int kSpecialValueSpace = LAST_SPACE + 1; |
+ static const int kAttachedReferenceSpace = kSpecialValueSpace + 1; |
+ STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize)); |
- private: |
+ static const int kInvalidValue = 0; |
+ static const int kDummyValue = 1; |
+ |
+ // The chunk offset can also be used to encode the index of special values. |
class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {}; |
class ChunkIndexBits |
: public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {}; |
- class SpaceBits |
- : public BitField<AllocationSpace, ChunkIndexBits::kNext, kSpaceTagSize> { |
- }; |
+ class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {}; |
+ STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext); |
+ class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {}; |
+ STATIC_ASSERT(SpaceBits::kNext == 32); |
uint32_t bitfield_; |
-}; |
+ friend class SerializerReferenceMap; |
+}; |
// Mapping objects to their location after deserialization. |
// This is used during building, but not at runtime by V8. |
-class BackReferenceMap : public AddressMapBase { |
+class SerializerReferenceMap : public AddressMapBase { |
public: |
- BackReferenceMap() |
- : no_allocation_(), map_(new HashMap(HashMap::PointersMatch)) {} |
- |
- ~BackReferenceMap() { delete map_; } |
+ SerializerReferenceMap() |
+ : no_allocation_(), |
+ map_(HashMap::PointersMatch), |
+ attached_reference_index_(0) {} |
- BackReference Lookup(HeapObject* obj) { |
- HashMap::Entry* entry = LookupEntry(map_, obj, false); |
- return entry ? BackReference(GetValue(entry)) : BackReference(); |
+ SerializerReference Lookup(HeapObject* obj) { |
+ HashMap::Entry* entry = LookupEntry(&map_, obj, false); |
+ return entry ? SerializerReference(GetValue(entry)) : SerializerReference(); |
} |
- void Add(HeapObject* obj, BackReference b) { |
+ void Add(HeapObject* obj, SerializerReference b) { |
DCHECK(b.is_valid()); |
- DCHECK_NULL(LookupEntry(map_, obj, false)); |
- HashMap::Entry* entry = LookupEntry(map_, obj, true); |
- SetValue(entry, b.bitfield()); |
- } |
- |
- void AddSourceString(String* string) { |
- Add(string, BackReference::SourceReference()); |
+ DCHECK_NULL(LookupEntry(&map_, obj, false)); |
+ HashMap::Entry* entry = LookupEntry(&map_, obj, true); |
+ SetValue(entry, b.bitfield_); |
} |
- void AddGlobalProxy(HeapObject* global_proxy) { |
- Add(global_proxy, BackReference::GlobalProxyReference()); |
+ SerializerReference AddAttachedReference(HeapObject* attached_reference) { |
+ SerializerReference reference = |
+ SerializerReference::AttachedReference(attached_reference_index_++); |
+ Add(attached_reference, reference); |
+ return reference; |
} |
private: |
DisallowHeapAllocation no_allocation_; |
- HashMap* map_; |
- DISALLOW_COPY_AND_ASSIGN(BackReferenceMap); |
+ HashMap map_; |
+ int attached_reference_index_; |
+ DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap); |
}; |
} // namespace internal |