#ifndef V8_SNAPSHOT_DESERIALIZER_H_
#define V8_SNAPSHOT_DESERIALIZER_H_
#include <utility>
#include <vector>
#include "src/base/macros.h"
#include "src/common/globals.h"
#include "src/execution/local-isolate.h"
#include "src/handles/global-handles.h"
#include "src/objects/allocation-site.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/backing-store.h"
#include "src/objects/code.h"
#include "src/objects/map.h"
#include "src/objects/objects.h"
#include "src/objects/string-table.h"
#include "src/objects/string.h"
#include "src/snapshot/serializer-deserializer.h"
#include "src/snapshot/snapshot-source-sink.h"
namespace v8 {
namespace internal {
class HeapObject;
class Object;
#if defined(V8_TARGET_ARCH_MIPS64) || defined(V8_TARGET_ARCH_S390X) || \
defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_RISCV32) || \
defined(V8_TARGET_ARCH_RISCV64) || V8_EMBEDDED_CONSTANT_POOL_BOOL
#define V8_CODE_EMBEDS_OBJECT_POINTER 1
#else
#define V8_CODE_EMBEDS_OBJECT_POINTER 0
#endif
template <typename IsolateT>
class Deserializer : public SerializerDeserializer {
public:
~Deserializer() override;
Deserializer(const Deserializer&) = delete;
Deserializer& operator=(const Deserializer&) = delete;
protected:
Deserializer(IsolateT* isolate, base::Vector<const uint8_t> payload,
uint32_t magic_number, bool deserializing_user_code,
bool can_rehash);
void DeserializeDeferredObjects();
void LogNewObjectEvents();
void LogScriptEvents(Tagged<Script> script);
void LogNewMapEvents();
void WeakenDescriptorArrays();
Handle<HeapObject> GetBackReferencedObject();
Handle<HeapObject> GetBackReferencedObject(uint32_t index);
void AddAttachedObject(DirectHandle<HeapObject> attached_object) {
attached_objects_.push_back(attached_object);
}
IsolateT* isolate() const { return isolate_; }
Isolate* main_thread_isolate() const { return isolate_->AsIsolate(); }
SnapshotByteSource* source() { return &source_; }
base::Vector<const DirectHandle<AllocationSite>> new_allocation_sites()
const {
return {new_allocation_sites_.data(), new_allocation_sites_.size()};
}
base::Vector<const DirectHandle<InstructionStream>> new_code_objects() const {
return {new_code_objects_.data(), new_code_objects_.size()};
}
base::Vector<const DirectHandle<Map>> new_maps() const {
return {new_maps_.data(), new_maps_.size()};
}
base::Vector<const DirectHandle<AccessorInfo>> accessor_infos() const {
return {accessor_infos_.data(), accessor_infos_.size()};
}
base::Vector<const DirectHandle<InterceptorInfo>> interceptor_infos() const {
return {interceptor_infos_.data(), interceptor_infos_.size()};
}
base::Vector<const DirectHandle<FunctionTemplateInfo>>
function_template_infos() const {
return {function_template_infos_.data(), function_template_infos_.size()};
}
base::Vector<const DirectHandle<Script>> new_scripts() const {
return {new_scripts_.data(), new_scripts_.size()};
}
std::shared_ptr<BackingStore> backing_store(size_t i) {
DCHECK_LT(i, backing_stores_.size());
return backing_stores_[i];
}
bool deserializing_user_code() const { return deserializing_user_code_; }
bool should_rehash() const { return should_rehash_; }
void PushObjectToRehash(DirectHandle<HeapObject> object) {
to_rehash_.push_back(object);
}
void Rehash();
DirectHandle<HeapObject> ReadObject();
private:
class HotObjectsList {
public:
HotObjectsList() = default;
HotObjectsList(const HotObjectsList&) = delete;
HotObjectsList& operator=(const HotObjectsList&) = delete;
void Add(DirectHandle<HeapObject> object) {
circular_queue_[index_] = object;
index_ = (index_ + 1) & kSizeMask;
}
DirectHandle<HeapObject> Get(int index) {
DCHECK(!circular_queue_[index].is_null());
return circular_queue_[index];
}
private:
static const int kSize = kHotObjectCount;
static const int kSizeMask = kSize - 1;
static_assert(base::bits::IsPowerOfTwo(kSize));
DirectHandle<HeapObject> circular_queue_[kSize];
int index_ = 0;
};
struct ReferenceDescriptor {
HeapObjectReferenceType type;
bool is_indirect_pointer;
bool is_protected_pointer;
};
void VisitRootPointers(Root root, const char* description,
FullObjectSlot start, FullObjectSlot end) override;
void Synchronize(VisitorSynchronization::SyncTag tag) override;
template <typename SlotAccessor>
int WriteHeapPointer(SlotAccessor slot_accessor,
Tagged<HeapObject> heap_object,
ReferenceDescriptor descr,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
template <typename SlotAccessor>
int WriteHeapPointer(SlotAccessor slot_accessor,
DirectHandle<HeapObject> heap_object,
ReferenceDescriptor descr,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline int WriteExternalPointer(Tagged<HeapObject> host,
ExternalPointerSlot dest, Address value,
ExternalPointerTag tag);
inline int WriteIndirectPointer(IndirectPointerSlot dest,
Tagged<HeapObject> value);
void ReadData(Handle<HeapObject> object, int start_slot_index,
int end_slot_index);
void ReadData(FullMaybeObjectSlot start, FullMaybeObjectSlot end);
template <typename SlotAccessor>
int ReadSingleBytecodeData(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadNewObject(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadBackref(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadReadOnlyHeapRef(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadRootArray(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadStartupObjectCache(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadSharedHeapObjectCache(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadNewMetaMap(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadExternalReference(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadRawExternalReference(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadAttachedReference(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadRegisterPendingForwardRef(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadResolvePendingForwardRef(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadVariableRawData(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadVariableRepeatRoot(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadOffHeapBackingStore(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadApiReference(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadClearedWeakReference(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadWeakPrefix(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadIndirectPointerPrefix(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadInitializeSelfIndirectPointer(uint8_t data,
SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadAllocateJSDispatchEntry(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadJSDispatchEntry(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadProtectedPointerPrefix(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadRootArrayConstants(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadHotObject(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadFixedRawData(uint8_t data, SlotAccessor slot_accessor);
template <typename SlotAccessor>
int ReadFixedRepeatRoot(uint8_t data, SlotAccessor slot_accessor);
inline Address ReadExternalReferenceCase();
ExternalPointerTag ReadExternalPointerTag();
Handle<HeapObject> ReadObject(SnapshotSpace space);
Handle<HeapObject> ReadMetaMap(SnapshotSpace space);
ReferenceDescriptor GetAndResetNextReferenceDescriptor();
template <typename SlotGetter>
int ReadRepeatedRoot(SlotGetter slot_getter, int repeat_count);
void PostProcessNewObject(DirectHandle<Map> map, Handle<HeapObject> obj,
SnapshotSpace space);
void PostProcessNewJSReceiver(Tagged<Map> map, DirectHandle<JSReceiver> obj,
InstanceType instance_type,
SnapshotSpace space);
Tagged<HeapObject> Allocate(AllocationType allocation, int size,
AllocationAlignment alignment);
IsolateT* isolate_;
DirectHandleVector<HeapObject> attached_objects_;
SnapshotByteSource source_;
uint32_t magic_number_;
HotObjectsList hot_objects_;
DirectHandleVector<Map> new_maps_;
DirectHandleVector<AllocationSite> new_allocation_sites_;
DirectHandleVector<InstructionStream> new_code_objects_;
DirectHandleVector<AccessorInfo> accessor_infos_;
DirectHandleVector<InterceptorInfo> interceptor_infos_;
DirectHandleVector<FunctionTemplateInfo> function_template_infos_;
DirectHandleVector<Script> new_scripts_;
std::vector<std::shared_ptr<BackingStore>> backing_stores_;
GlobalHandleVector<DescriptorArray> new_descriptor_arrays_;
std::vector<IndirectHandle<HeapObject>> back_refs_;
std::vector<JSDispatchHandle> js_dispatch_entries_;
struct UnresolvedForwardRef {
UnresolvedForwardRef(Handle<HeapObject> object, int offset,
ReferenceDescriptor descr)
: object(object), offset(offset), descr(descr) {}
IndirectHandle<HeapObject> object;
int offset;
ReferenceDescriptor descr;
};
std::vector<UnresolvedForwardRef> unresolved_forward_refs_;
int num_unresolved_forward_refs_ = 0;
const bool deserializing_user_code_;
bool next_reference_is_weak_ = false;
bool next_reference_is_indirect_pointer_ = false;
bool next_reference_is_protected_pointer = false;
const bool should_rehash_;
DirectHandleVector<HeapObject> to_rehash_;
class V8_NODISCARD DisableGCStats {
public:
DisableGCStats() {
original_gc_stats_ = TracingFlags::gc_stats;
TracingFlags::gc_stats = 0;
}
~DisableGCStats() { TracingFlags::gc_stats = original_gc_stats_; }
private:
unsigned int original_gc_stats_;
};
DisableGCStats no_gc_stats_;
int depth_ = 0;
#ifdef DEBUG
uint32_t num_api_references_;
DirectHandle<HeapObject> previous_allocation_obj_;
int previous_allocation_size_ = 0;
#endif
};
enum class DeserializingUserCodeOption {
kNotDeserializingUserCode,
kIsDeserializingUserCode
};
class StringTableInsertionKey final : public StringTableKey {
public:
explicit StringTableInsertionKey(
Isolate* isolate, DirectHandle<String> string,
DeserializingUserCodeOption deserializing_user_code);
explicit StringTableInsertionKey(
LocalIsolate* isolate, DirectHandle<String> string,
DeserializingUserCodeOption deserializing_user_code);
template <typename IsolateT>
bool IsMatch(IsolateT* isolate, Tagged<String> string);
void PrepareForInsertion(Isolate* isolate) {
DCHECK(isolate->OwnsStringTables() ||
deserializing_user_code_ ==
DeserializingUserCodeOption::kIsDeserializingUserCode);
}
void PrepareForInsertion(LocalIsolate* isolate) {}
V8_WARN_UNUSED_RESULT DirectHandle<String> GetHandleForInsertion(
Isolate* isolate) {
return string_;
}
private:
DirectHandle<String> string_;
#ifdef DEBUG
DeserializingUserCodeOption deserializing_user_code_;
#endif
DISALLOW_GARBAGE_COLLECTION(no_gc)
};
}
}
#endif