// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_SNAPSHOT_REFERENCES_H_ #define V8_SNAPSHOT_REFERENCES_H_ #include "src/base/bit-field.h" #include "src/base/hashmap.h" #include "src/common/assert-scope.h" #include "src/execution/isolate.h" #include "src/utils/identity-map.h" namespace v8 { namespace internal { enum class SnapshotSpace : byte { kReadOnlyHeap, kOld, kCode, kMap, }; static constexpr int kNumberOfSnapshotSpaces = static_cast<int>(SnapshotSpace::kMap) + 1; class SerializerReference { private: enum SpecialValueType { kBackReference, kAttachedReference, kOffHeapBackingStore, kBuiltinReference, }; SerializerReference(SpecialValueType type, uint32_t value) : bit_field_(TypeBits::encode(type) | ValueBits::encode(value)) {} public: static SerializerReference BackReference(uint32_t index) { return SerializerReference(kBackReference, index); } static SerializerReference OffHeapBackingStoreReference(uint32_t index) { return SerializerReference(kOffHeapBackingStore, index); } static SerializerReference AttachedReference(uint32_t index) { return SerializerReference(kAttachedReference, index); } static SerializerReference BuiltinReference(uint32_t index) { return SerializerReference(kBuiltinReference, index); } bool is_back_reference() const { return TypeBits::decode(bit_field_) == kBackReference; } uint32_t back_ref_index() const { DCHECK(is_back_reference()); return ValueBits::decode(bit_field_); } bool is_off_heap_backing_store_reference() const { return TypeBits::decode(bit_field_) == kOffHeapBackingStore; } uint32_t off_heap_backing_store_index() const { DCHECK(is_off_heap_backing_store_reference()); return ValueBits::decode(bit_field_); } bool is_attached_reference() const { return TypeBits::decode(bit_field_) == kAttachedReference; } uint32_t attached_reference_index() const { DCHECK(is_attached_reference()); return ValueBits::decode(bit_field_); } bool is_builtin_reference() const { return TypeBits::decode(bit_field_) == kBuiltinReference; } uint32_t builtin_index() const { DCHECK(is_builtin_reference()); return ValueBits::decode(bit_field_); } private: using TypeBits = base::BitField<SpecialValueType, 0, 2>; using ValueBits = TypeBits::Next<uint32_t, 32 - TypeBits::kSize>; uint32_t bit_field_; friend class SerializerReferenceMap; }; // SerializerReference has to fit in an IdentityMap value field. STATIC_ASSERT(sizeof(SerializerReference) <= sizeof(void*)); class SerializerReferenceMap { public: explicit SerializerReferenceMap(Isolate* isolate) : map_(isolate->heap()), attached_reference_index_(0) {} const SerializerReference* LookupReference(HeapObject object) const { return map_.Find(object); } const SerializerReference* LookupReference(Handle<HeapObject> object) const { return map_.Find(object); } const SerializerReference* LookupBackingStore(void* backing_store) const { auto it = backing_store_map_.find(backing_store); if (it == backing_store_map_.end()) return nullptr; return &it->second; } void Add(HeapObject object, SerializerReference reference) { DCHECK_NULL(LookupReference(object)); map_.Insert(object, reference); } void AddBackingStore(void* backing_store, SerializerReference reference) { DCHECK(backing_store_map_.find(backing_store) == backing_store_map_.end()); backing_store_map_.emplace(backing_store, reference); } SerializerReference AddAttachedReference(HeapObject object) { SerializerReference reference = SerializerReference::AttachedReference(attached_reference_index_++); map_.Insert(object, reference); return reference; } private: IdentityMap<SerializerReference, base::DefaultAllocationPolicy> map_; std::unordered_map<void*, SerializerReference> backing_store_map_; int attached_reference_index_; }; } // namespace internal } // namespace v8 #endif // V8_SNAPSHOT_REFERENCES_H_