Commit e24fa913 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[offthread] Template deserializer on Isolate

Make the deserializer class templated on Isolate/LocalIsolate. This
allows the ObjectSerializer to be split into a main-thread and offthread
variant, with the latter taking a LocalIsolate.

Eventually, we probably want to anyway split off the code-cache de/serializer
to a separate implementation (for various reasons), and this the only one that
wants off-thread finalization, and at this point the deserializer can revert
back to being un-templated, used only for bootstrapping. However, this is the
simplest way, for now, to enable off-thread deserialization.

Bug: chromium:1075999
Change-Id: I49c0d2c5409f0aa58183673785296756c3714f22
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2562254Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75834}
parent 7179c71e
...@@ -1768,6 +1768,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { ...@@ -1768,6 +1768,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
return main_thread_local_isolate_.get(); return main_thread_local_isolate_.get();
} }
Isolate* AsIsolate() { return this; }
LocalIsolate* AsLocalIsolate() { return main_thread_local_isolate(); } LocalIsolate* AsLocalIsolate() { return main_thread_local_isolate(); }
LocalHeap* main_thread_local_heap(); LocalHeap* main_thread_local_heap();
......
...@@ -22,6 +22,11 @@ Object LocalIsolate::root(RootIndex index) const { ...@@ -22,6 +22,11 @@ Object LocalIsolate::root(RootIndex index) const {
return isolate_->root(index); return isolate_->root(index);
} }
Handle<Object> LocalIsolate::root_handle(RootIndex index) const {
DCHECK(RootsTable::IsImmortalImmovable(index));
return isolate_->root_handle(index);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -26,6 +26,13 @@ LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind, ...@@ -26,6 +26,13 @@ LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind,
LocalIsolate::~LocalIsolate() = default; LocalIsolate::~LocalIsolate() = default;
void LocalIsolate::RegisterDeserializerStarted() {
return isolate_->RegisterDeserializerStarted();
}
void LocalIsolate::RegisterDeserializerFinished() {
return isolate_->RegisterDeserializerFinished();
}
int LocalIsolate::GetNextScriptId() { return isolate_->GetNextScriptId(); } int LocalIsolate::GetNextScriptId() { return isolate_->GetNextScriptId(); }
#if V8_SFI_HAS_UNIQUE_ID #if V8_SFI_HAS_UNIQUE_ID
......
...@@ -48,11 +48,14 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { ...@@ -48,11 +48,14 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
OFFSET_OF(LocalIsolate, heap_)); OFFSET_OF(LocalIsolate, heap_));
} }
bool is_main_thread() { return heap()->is_main_thread(); }
LocalHeap* heap() { return &heap_; } LocalHeap* heap() { return &heap_; }
inline Address cage_base() const; inline Address cage_base() const;
inline ReadOnlyHeap* read_only_heap() const; inline ReadOnlyHeap* read_only_heap() const;
inline Object root(RootIndex index) const; inline Object root(RootIndex index) const;
inline Handle<Object> root_handle(RootIndex index) const;
StringTable* string_table() const { return isolate_->string_table(); } StringTable* string_table() const { return isolate_->string_table(); }
base::SharedMutex* internalized_string_access() { base::SharedMutex* internalized_string_access() {
...@@ -67,6 +70,9 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { ...@@ -67,6 +70,9 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
bool has_pending_exception() const { return false; } bool has_pending_exception() const { return false; }
void RegisterDeserializerStarted();
void RegisterDeserializerFinished();
template <typename T> template <typename T>
Handle<T> Throw(Handle<Object> exception) { Handle<T> Throw(Handle<Object> exception) {
UNREACHABLE(); UNREACHABLE();
...@@ -89,6 +95,12 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { ...@@ -89,6 +95,12 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
bool is_main_thread() const { return heap_.is_main_thread(); } bool is_main_thread() const { return heap_.is_main_thread(); }
// AsIsolate is only allowed on the main-thread.
Isolate* AsIsolate() {
DCHECK(is_main_thread());
DCHECK_EQ(ThreadId::Current(), isolate_->thread_id());
return isolate_;
}
LocalIsolate* AsLocalIsolate() { return this; } LocalIsolate* AsLocalIsolate() { return this; }
private: private:
......
...@@ -335,14 +335,11 @@ HeapObject Heap::AllocateRawWith(int size, AllocationType allocation, ...@@ -335,14 +335,11 @@ HeapObject Heap::AllocateRawWith(int size, AllocationType allocation,
UNREACHABLE(); UNREACHABLE();
} }
Address Heap::DeserializerAllocate(AllocationType type, int size_in_bytes) { Address Heap::AllocateRawOrFail(int size, AllocationType allocation,
if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) { AllocationOrigin origin,
AllocationResult allocation = tp_heap_->Allocate( AllocationAlignment alignment) {
size_in_bytes, type, AllocationAlignment::kDoubleAligned); return AllocateRawWith<kRetryOrFail>(size, allocation, origin, alignment)
return allocation.ToObjectChecked().ptr(); .address();
} else {
UNIMPLEMENTED(); // unimplemented
}
} }
void Heap::OnAllocationEvent(HeapObject object, int size_in_bytes) { void Heap::OnAllocationEvent(HeapObject object, int size_in_bytes) {
......
...@@ -567,11 +567,6 @@ class Heap { ...@@ -567,11 +567,6 @@ class Heap {
V8_EXPORT_PRIVATE static bool IsLargeObject(HeapObject object); V8_EXPORT_PRIVATE static bool IsLargeObject(HeapObject object);
// This method supports the deserialization allocator. All allocations
// are word-aligned. The method should never fail to allocate since the
// total space requirements of the deserializer are known at build time.
inline Address DeserializerAllocate(AllocationType type, int size_in_bytes);
// Trim the given array from the left. Note that this relocates the object // Trim the given array from the left. Note that this relocates the object
// start and hence is only valid if there is only a single reference to it. // start and hence is only valid if there is only a single reference to it.
V8_EXPORT_PRIVATE FixedArrayBase LeftTrimFixedArray(FixedArrayBase obj, V8_EXPORT_PRIVATE FixedArrayBase LeftTrimFixedArray(FixedArrayBase obj,
...@@ -2105,6 +2100,12 @@ class Heap { ...@@ -2105,6 +2100,12 @@ class Heap {
AllocationOrigin origin = AllocationOrigin::kRuntime, AllocationOrigin origin = AllocationOrigin::kRuntime,
AllocationAlignment alignment = kWordAligned); AllocationAlignment alignment = kWordAligned);
// Call AllocateRawWith with kRetryOrFail. Matches the method in LocalHeap.
V8_WARN_UNUSED_RESULT inline Address AllocateRawOrFail(
int size, AllocationType allocation,
AllocationOrigin origin = AllocationOrigin::kRuntime,
AllocationAlignment alignment = kWordAligned);
// This method will try to perform an allocation of a given size of a given // This method will try to perform an allocation of a given size of a given
// AllocationType. If the allocation fails, a regular full garbage collection // AllocationType. If the allocation fails, a regular full garbage collection
// is triggered and the allocation is retried. This is performed multiple // is triggered and the allocation is retried. This is performed multiple
...@@ -2527,6 +2528,7 @@ class Heap { ...@@ -2527,6 +2528,7 @@ class Heap {
// The allocator interface. // The allocator interface.
friend class Factory; friend class Factory;
template <typename IsolateT>
friend class Deserializer; friend class Deserializer;
// The Isolate constructs us. // The Isolate constructs us.
...@@ -2580,8 +2582,6 @@ class V8_NODISCARD AlwaysAllocateScope { ...@@ -2580,8 +2582,6 @@ class V8_NODISCARD AlwaysAllocateScope {
private: private:
friend class AlwaysAllocateScopeForTesting; friend class AlwaysAllocateScopeForTesting;
friend class Deserializer;
friend class DeserializerAllocator;
friend class Evacuator; friend class Evacuator;
friend class Heap; friend class Heap;
friend class Isolate; friend class Isolate;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
#include "src/handles/persistent-handles.h" #include "src/handles/persistent-handles.h"
#include "src/heap/concurrent-allocator-inl.h" #include "src/heap/concurrent-allocator-inl.h"
#include "src/heap/heap.h"
#include "src/heap/local-heap.h" #include "src/heap/local-heap.h"
namespace v8 { namespace v8 {
...@@ -53,6 +54,13 @@ Address LocalHeap::AllocateRawOrFail(int object_size, AllocationType type, ...@@ -53,6 +54,13 @@ Address LocalHeap::AllocateRawOrFail(int object_size, AllocationType type,
alignment); alignment);
} }
void LocalHeap::CreateFillerObjectAt(Address addr, int size,
ClearRecordedSlots clear_slots_mode) {
DCHECK_EQ(clear_slots_mode, ClearRecordedSlots::kNo);
heap()->CreateFillerObjectAtBackground(
addr, size, ClearFreedMemoryMode::kDontClearFreedMemory);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -130,7 +130,14 @@ class V8_EXPORT_PRIVATE LocalHeap { ...@@ -130,7 +130,14 @@ class V8_EXPORT_PRIVATE LocalHeap {
AllocationOrigin origin = AllocationOrigin::kRuntime, AllocationOrigin origin = AllocationOrigin::kRuntime,
AllocationAlignment alignment = kWordAligned); AllocationAlignment alignment = kWordAligned);
inline void CreateFillerObjectAt(Address addr, int size,
ClearRecordedSlots clear_slots_mode);
bool is_main_thread() const { return is_main_thread_; } bool is_main_thread() const { return is_main_thread_; }
bool deserialization_complete() const {
return heap_->deserialization_complete();
}
ReadOnlySpace* read_only_space() { return heap_->read_only_space(); }
// Requests GC and blocks until the collection finishes. // Requests GC and blocks until the collection finishes.
bool TryPerformCollection(); bool TryPerformCollection();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/logging/local-logger.h" #include "src/logging/local-logger.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/objects/map.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -27,5 +28,9 @@ void LocalLogger::CodeLinePosInfoRecordEvent(Address code_start, ...@@ -27,5 +28,9 @@ void LocalLogger::CodeLinePosInfoRecordEvent(Address code_start,
logger_->CodeLinePosInfoRecordEvent(code_start, source_position_table); logger_->CodeLinePosInfoRecordEvent(code_start, source_position_table);
} }
void LocalLogger::MapCreate(Map map) { logger_->MapCreate(map); }
void LocalLogger::MapDetails(Map map) { logger_->MapDetails(map); }
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -25,6 +25,9 @@ class LocalLogger { ...@@ -25,6 +25,9 @@ class LocalLogger {
void CodeLinePosInfoRecordEvent(Address code_start, void CodeLinePosInfoRecordEvent(Address code_start,
ByteArray source_position_table); ByteArray source_position_table);
void MapCreate(Map map);
void MapDetails(Map map);
private: private:
Logger* logger_; Logger* logger_;
bool is_logging_; bool is_logging_;
......
...@@ -195,7 +195,8 @@ class HeapObject : public Object { ...@@ -195,7 +195,8 @@ class HeapObject : public Object {
bool CanBeRehashed() const; bool CanBeRehashed() const;
// Rehash the object based on the layout inferred from its map. // Rehash the object based on the layout inferred from its map.
void RehashBasedOnMap(Isolate* isolate); template <typename IsolateT>
void RehashBasedOnMap(IsolateT* isolate);
// Layout description. // Layout description.
#define HEAP_OBJECT_FIELDS(V) \ #define HEAP_OBJECT_FIELDS(V) \
......
...@@ -364,6 +364,7 @@ class JSTypedArray ...@@ -364,6 +364,7 @@ class JSTypedArray
#endif #endif
private: private:
template <typename IsolateT>
friend class Deserializer; friend class Deserializer;
friend class Factory; friend class Factory;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/objects/map-inl.h" #include "src/objects/map-inl.h"
#include "src/objects/name.h" #include "src/objects/name.h"
#include "src/objects/primitive-heap-object-inl.h" #include "src/objects/primitive-heap-object-inl.h"
#include "src/objects/string-inl.h"
// Has to be the last include (doesn't have include guards): // Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h" #include "src/objects/object-macros.h"
...@@ -97,6 +98,14 @@ uint32_t Name::EnsureHash() { ...@@ -97,6 +98,14 @@ uint32_t Name::EnsureHash() {
return String::cast(*this).ComputeAndSetHash(); return String::cast(*this).ComputeAndSetHash();
} }
uint32_t Name::EnsureHash(const SharedStringAccessGuardIfNeeded& access_guard) {
// Fast case: has hash code already been computed?
uint32_t field = raw_hash_field();
if (IsHashFieldComputed(field)) return field >> kHashShift;
// Slow case: compute hash code and set it. Has to be a string.
return String::cast(*this).ComputeAndSetHash(access_guard);
}
uint32_t Name::hash() const { uint32_t Name::hash() const {
uint32_t field = raw_hash_field(); uint32_t field = raw_hash_field();
DCHECK(IsHashFieldComputed(field)); DCHECK(IsHashFieldComputed(field));
......
...@@ -18,6 +18,8 @@ namespace internal { ...@@ -18,6 +18,8 @@ namespace internal {
#include "torque-generated/src/objects/name-tq.inc" #include "torque-generated/src/objects/name-tq.inc"
class SharedStringAccessGuardIfNeeded;
// The Name abstract class captures anything that can be used as a property // The Name abstract class captures anything that can be used as a property
// name, i.e., strings and symbols. All names store a hash value. // name, i.e., strings and symbols. All names store a hash value.
class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> { class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
...@@ -27,7 +29,11 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> { ...@@ -27,7 +29,11 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
// Returns a hash value used for the property table. Ensures that the hash // Returns a hash value used for the property table. Ensures that the hash
// value is computed. // value is computed.
//
// The overload without SharedStringAccessGuardIfNeeded can only be called on
// the main thread.
inline uint32_t EnsureHash(); inline uint32_t EnsureHash();
inline uint32_t EnsureHash(const SharedStringAccessGuardIfNeeded&);
// Returns a hash value used for the property table (same as Hash()), assumes // Returns a hash value used for the property table (same as Hash()), assumes
// the hash is already computed. // the hash is already computed.
......
...@@ -2363,7 +2363,8 @@ bool HeapObject::CanBeRehashed() const { ...@@ -2363,7 +2363,8 @@ bool HeapObject::CanBeRehashed() const {
} }
} }
void HeapObject::RehashBasedOnMap(Isolate* isolate) { template <typename IsolateT>
void HeapObject::RehashBasedOnMap(IsolateT* isolate) {
switch (map().instance_type()) { switch (map().instance_type()) {
case HASH_TABLE_TYPE: case HASH_TABLE_TYPE:
UNREACHABLE(); UNREACHABLE();
...@@ -2399,11 +2400,11 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) { ...@@ -2399,11 +2400,11 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) {
case ORDERED_HASH_SET_TYPE: case ORDERED_HASH_SET_TYPE:
UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them. UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them.
case JS_MAP_TYPE: { case JS_MAP_TYPE: {
JSMap::cast(*this).Rehash(isolate); JSMap::cast(*this).Rehash(isolate->AsIsolate());
break; break;
} }
case JS_SET_TYPE: { case JS_SET_TYPE: {
JSSet::cast(*this).Rehash(isolate); JSSet::cast(*this).Rehash(isolate->AsIsolate());
break; break;
} }
case SMALL_ORDERED_NAME_DICTIONARY_TYPE: case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
...@@ -2419,6 +2420,8 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) { ...@@ -2419,6 +2420,8 @@ void HeapObject::RehashBasedOnMap(Isolate* isolate) {
UNREACHABLE(); UNREACHABLE();
} }
} }
template void HeapObject::RehashBasedOnMap(Isolate* isolate);
template void HeapObject::RehashBasedOnMap(LocalIsolate* isolate);
bool HeapObject::IsExternal(Isolate* isolate) const { bool HeapObject::IsExternal(Isolate* isolate) const {
return map().FindRootMap(isolate) == isolate->heap()->external_map(); return map().FindRootMap(isolate) == isolate->heap()->external_map();
......
...@@ -9,17 +9,19 @@ ...@@ -9,17 +9,19 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
void StringComparator::State::Init(String string) { void StringComparator::State::Init(
ConsString cons_string = String::VisitFlat(this, string); String string, const SharedStringAccessGuardIfNeeded& access_guard) {
ConsString cons_string = String::VisitFlat(this, string, 0, access_guard);
iter_.Reset(cons_string); iter_.Reset(cons_string);
if (!cons_string.is_null()) { if (!cons_string.is_null()) {
int offset; int offset;
string = iter_.Next(&offset); string = iter_.Next(&offset);
String::VisitFlat(this, string, offset); String::VisitFlat(this, string, offset, access_guard);
} }
} }
void StringComparator::State::Advance(int consumed) { void StringComparator::State::Advance(
int consumed, const SharedStringAccessGuardIfNeeded& access_guard) {
DCHECK(consumed <= length_); DCHECK(consumed <= length_);
// Still in buffer. // Still in buffer.
if (length_ != consumed) { if (length_ != consumed) {
...@@ -36,13 +38,15 @@ void StringComparator::State::Advance(int consumed) { ...@@ -36,13 +38,15 @@ void StringComparator::State::Advance(int consumed) {
String next = iter_.Next(&offset); String next = iter_.Next(&offset);
DCHECK_EQ(0, offset); DCHECK_EQ(0, offset);
DCHECK(!next.is_null()); DCHECK(!next.is_null());
String::VisitFlat(this, next); String::VisitFlat(this, next, 0, access_guard);
} }
bool StringComparator::Equals(String string_1, String string_2) { bool StringComparator::Equals(
String string_1, String string_2,
const SharedStringAccessGuardIfNeeded& access_guard) {
int length = string_1.length(); int length = string_1.length();
state_1_.Init(string_1); state_1_.Init(string_1, access_guard);
state_2_.Init(string_2); state_2_.Init(string_2, access_guard);
while (true) { while (true) {
int to_check = std::min(state_1_.length_, state_2_.length_); int to_check = std::min(state_1_.length_, state_2_.length_);
DCHECK(to_check > 0 && to_check <= length); DCHECK(to_check > 0 && to_check <= length);
...@@ -65,8 +69,8 @@ bool StringComparator::Equals(String string_1, String string_2) { ...@@ -65,8 +69,8 @@ bool StringComparator::Equals(String string_1, String string_2) {
length -= to_check; length -= to_check;
// Exit condition. Strings are equal. // Exit condition. Strings are equal.
if (length == 0) return true; if (length == 0) return true;
state_1_.Advance(to_check); state_1_.Advance(to_check, access_guard);
state_2_.Advance(to_check); state_2_.Advance(to_check, access_guard);
} }
} }
......
...@@ -20,7 +20,8 @@ class StringComparator { ...@@ -20,7 +20,8 @@ class StringComparator {
State(const State&) = delete; State(const State&) = delete;
State& operator=(const State&) = delete; State& operator=(const State&) = delete;
void Init(String string); void Init(String string,
const SharedStringAccessGuardIfNeeded& access_guard);
inline void VisitOneByteString(const uint8_t* chars, int length) { inline void VisitOneByteString(const uint8_t* chars, int length) {
is_one_byte_ = true; is_one_byte_ = true;
...@@ -34,7 +35,8 @@ class StringComparator { ...@@ -34,7 +35,8 @@ class StringComparator {
length_ = length; length_ = length;
} }
void Advance(int consumed); void Advance(int consumed,
const SharedStringAccessGuardIfNeeded& access_guard);
ConsStringIterator iter_; ConsStringIterator iter_;
bool is_one_byte_; bool is_one_byte_;
...@@ -57,7 +59,8 @@ class StringComparator { ...@@ -57,7 +59,8 @@ class StringComparator {
return CompareCharsEqual(a, b, to_check); return CompareCharsEqual(a, b, to_check);
} }
bool Equals(String string_1, String string_2); bool Equals(String string_1, String string_2,
const SharedStringAccessGuardIfNeeded& access_guard);
private: private:
State state_1_; State state_1_;
......
...@@ -510,6 +510,8 @@ template Handle<String> StringTable::LookupKey(LocalIsolate* isolate, ...@@ -510,6 +510,8 @@ template Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
template Handle<String> StringTable::LookupKey(Isolate* isolate, template Handle<String> StringTable::LookupKey(Isolate* isolate,
StringTableInsertionKey* key); StringTableInsertionKey* key);
template Handle<String> StringTable::LookupKey(LocalIsolate* isolate,
StringTableInsertionKey* key);
StringTable::Data* StringTable::EnsureCapacity(PtrComprCageBase cage_base, StringTable::Data* StringTable::EnsureCapacity(PtrComprCageBase cage_base,
int additional_elements) { int additional_elements) {
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "src/execution/thread-id.h" #include "src/execution/thread-id.h"
#include "src/handles/handles-inl.h" #include "src/handles/handles-inl.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/heap/local-heap-inl.h"
#include "src/heap/memory-chunk.h" #include "src/heap/memory-chunk.h"
#include "src/heap/read-only-heap.h" #include "src/heap/read-only-heap.h"
#include "src/numbers/conversions.h" #include "src/numbers/conversions.h"
...@@ -93,26 +95,32 @@ void MigrateExternalStringResource(Isolate* isolate, ExternalString from, ...@@ -93,26 +95,32 @@ void MigrateExternalStringResource(Isolate* isolate, ExternalString from,
} }
} }
void MigrateExternalString(Isolate* isolate, String string,
String internalized) {
if (internalized.IsExternalOneByteString()) {
MigrateExternalStringResource(isolate, ExternalString::cast(string),
ExternalOneByteString::cast(internalized));
} else if (internalized.IsExternalTwoByteString()) {
MigrateExternalStringResource(isolate, ExternalString::cast(string),
ExternalTwoByteString::cast(internalized));
} else {
// If the external string is duped into an existing non-external
// internalized string, free its resource (it's about to be rewritten
// into a ThinString below).
isolate->heap()->FinalizeExternalString(string);
}
}
} // namespace } // namespace
void String::MakeThin(Isolate* isolate, String internalized) { template <typename IsolateT>
void String::MakeThin(IsolateT* isolate, String internalized) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
DCHECK_NE(*this, internalized); DCHECK_NE(*this, internalized);
DCHECK(internalized.IsInternalizedString()); DCHECK(internalized.IsInternalizedString());
if (this->IsExternalString()) { if (this->IsExternalString()) {
if (internalized.IsExternalOneByteString()) { MigrateExternalString(isolate->AsIsolate(), *this, internalized);
MigrateExternalStringResource(isolate, ExternalString::cast(*this),
ExternalOneByteString::cast(internalized));
} else if (internalized.IsExternalTwoByteString()) {
MigrateExternalStringResource(isolate, ExternalString::cast(*this),
ExternalTwoByteString::cast(internalized));
} else {
// If the external string is duped into an existing non-external
// internalized string, free its resource (it's about to be rewritten
// into a ThinString below).
isolate->heap()->FinalizeExternalString(*this);
}
} }
bool has_pointers = StringShape(*this).IsIndirect(); bool has_pointers = StringShape(*this).IsIndirect();
...@@ -131,9 +139,8 @@ void String::MakeThin(Isolate* isolate, String internalized) { ...@@ -131,9 +139,8 @@ void String::MakeThin(Isolate* isolate, String internalized) {
Address thin_end = thin.address() + ThinString::kSize; Address thin_end = thin.address() + ThinString::kSize;
int size_delta = old_size - ThinString::kSize; int size_delta = old_size - ThinString::kSize;
if (size_delta != 0) { if (size_delta != 0) {
Heap* heap = isolate->heap(); if (!Heap::IsLargeObject(thin)) {
if (!heap->IsLargeObject(thin)) { isolate->heap()->CreateFillerObjectAt(
heap->CreateFillerObjectAt(
thin_end, size_delta, thin_end, size_delta,
has_pointers ? ClearRecordedSlots::kYes : ClearRecordedSlots::kNo); has_pointers ? ClearRecordedSlots::kYes : ClearRecordedSlots::kNo);
} else { } else {
...@@ -144,6 +151,9 @@ void String::MakeThin(Isolate* isolate, String internalized) { ...@@ -144,6 +151,9 @@ void String::MakeThin(Isolate* isolate, String internalized) {
} }
} }
template void String::MakeThin(Isolate* isolate, String internalized);
template void String::MakeThin(LocalIsolate* isolate, String internalized);
bool String::MakeExternal(v8::String::ExternalStringResource* resource) { bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
// Disallow garbage collection to avoid possible GC vs string access deadlock. // Disallow garbage collection to avoid possible GC vs string access deadlock.
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
...@@ -633,6 +643,7 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls, ...@@ -633,6 +643,7 @@ std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
return ToCString(allow_nulls, robust_flag, 0, -1, length_return); return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
} }
// static
template <typename sinkchar> template <typename sinkchar>
void String::WriteToFlat(String source, sinkchar* sink, int from, int to) { void String::WriteToFlat(String source, sinkchar* sink, int from, int to) {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source)); DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(source));
...@@ -640,6 +651,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to) { ...@@ -640,6 +651,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to) {
SharedStringAccessGuardIfNeeded::NotNeeded()); SharedStringAccessGuardIfNeeded::NotNeeded());
} }
// static
template <typename sinkchar> template <typename sinkchar>
void String::WriteToFlat(String source, sinkchar* sink, int from, int to, void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
const SharedStringAccessGuardIfNeeded& access_guard) { const SharedStringAccessGuardIfNeeded& access_guard) {
...@@ -794,6 +806,13 @@ template Handle<FixedArray> String::CalculateLineEnds(LocalIsolate* isolate, ...@@ -794,6 +806,13 @@ template Handle<FixedArray> String::CalculateLineEnds(LocalIsolate* isolate,
bool include_ending_line); bool include_ending_line);
bool String::SlowEquals(String other) const { bool String::SlowEquals(String other) const {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(other));
return SlowEquals(other, SharedStringAccessGuardIfNeeded::NotNeeded());
}
bool String::SlowEquals(
String other, const SharedStringAccessGuardIfNeeded& access_guard) const {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
// Fast check: negative check with lengths. // Fast check: negative check with lengths.
int len = length(); int len = length();
...@@ -833,16 +852,18 @@ bool String::SlowEquals(String other) const { ...@@ -833,16 +852,18 @@ bool String::SlowEquals(String other) const {
// We know the strings are both non-empty. Compare the first chars // We know the strings are both non-empty. Compare the first chars
// before we try to flatten the strings. // before we try to flatten the strings.
if (this->Get(0) != other.Get(0)) return false; if (this->Get(0, access_guard) != other.Get(0, access_guard)) return false;
if (IsSeqOneByteString() && other.IsSeqOneByteString()) { if (IsSeqOneByteString() && other.IsSeqOneByteString()) {
const uint8_t* str1 = SeqOneByteString::cast(*this).GetChars(no_gc); const uint8_t* str1 =
const uint8_t* str2 = SeqOneByteString::cast(other).GetChars(no_gc); SeqOneByteString::cast(*this).GetChars(no_gc, access_guard);
const uint8_t* str2 =
SeqOneByteString::cast(other).GetChars(no_gc, access_guard);
return CompareCharsEqual(str1, str2, len); return CompareCharsEqual(str1, str2, len);
} }
StringComparator comparator; StringComparator comparator;
return comparator.Equals(*this, other); return comparator.Equals(*this, other, access_guard);
} }
// static // static
...@@ -1326,7 +1347,8 @@ bool String::HasOneBytePrefix(base::Vector<const char> str) { ...@@ -1326,7 +1347,8 @@ bool String::HasOneBytePrefix(base::Vector<const char> str) {
namespace { namespace {
template <typename Char> template <typename Char>
uint32_t HashString(String string, size_t start, int length, uint64_t seed) { uint32_t HashString(String string, size_t start, int length, uint64_t seed,
const SharedStringAccessGuardIfNeeded& access_guard) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
if (length > String::kMaxHashCalcLength) { if (length > String::kMaxHashCalcLength) {
...@@ -1340,10 +1362,10 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) { ...@@ -1340,10 +1362,10 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) {
DCHECK_EQ(0, start); DCHECK_EQ(0, start);
DCHECK(!string.IsFlat()); DCHECK(!string.IsFlat());
buffer.reset(new Char[length]); buffer.reset(new Char[length]);
String::WriteToFlat(string, buffer.get(), 0, length); String::WriteToFlat(string, buffer.get(), 0, length, access_guard);
chars = buffer.get(); chars = buffer.get();
} else { } else {
chars = string.GetChars<Char>(no_gc) + start; chars = string.GetChars<Char>(no_gc, access_guard) + start;
} }
return StringHasher::HashSequentialString<Char>(chars, length, seed); return StringHasher::HashSequentialString<Char>(chars, length, seed);
...@@ -1352,6 +1374,11 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) { ...@@ -1352,6 +1374,11 @@ uint32_t HashString(String string, size_t start, int length, uint64_t seed) {
} // namespace } // namespace
uint32_t String::ComputeAndSetHash() { uint32_t String::ComputeAndSetHash() {
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
return ComputeAndSetHash(SharedStringAccessGuardIfNeeded::NotNeeded());
}
uint32_t String::ComputeAndSetHash(
const SharedStringAccessGuardIfNeeded& access_guard) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
// Should only be called if hash code has not yet been computed. // Should only be called if hash code has not yet been computed.
DCHECK(!HasHashCode()); DCHECK(!HasHashCode());
...@@ -1377,8 +1404,8 @@ uint32_t String::ComputeAndSetHash() { ...@@ -1377,8 +1404,8 @@ uint32_t String::ComputeAndSetHash() {
} }
uint32_t raw_hash_field = uint32_t raw_hash_field =
string.IsOneByteRepresentation() string.IsOneByteRepresentation()
? HashString<uint8_t>(string, start, length(), seed) ? HashString<uint8_t>(string, start, length(), seed, access_guard)
: HashString<uint16_t>(string, start, length(), seed); : HashString<uint16_t>(string, start, length(), seed, access_guard);
set_raw_hash_field(raw_hash_field); set_raw_hash_field(raw_hash_field);
// Check the hash code is there. // Check the hash code is there.
......
...@@ -172,7 +172,8 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -172,7 +172,8 @@ class String : public TorqueGeneratedString<String, Name> {
friend class IterableSubString; friend class IterableSubString;
}; };
void MakeThin(Isolate* isolate, String canonical); template <typename IsolateT>
void MakeThin(IsolateT* isolate, String canonical);
template <typename Char> template <typename Char>
V8_INLINE base::Vector<const Char> GetCharVector( V8_INLINE base::Vector<const Char> GetCharVector(
...@@ -570,6 +571,8 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -570,6 +571,8 @@ class String : public TorqueGeneratedString<String, Name> {
// Slow case of String::Equals. This implementation works on any strings // Slow case of String::Equals. This implementation works on any strings
// but it is most efficient on strings that are almost flat. // but it is most efficient on strings that are almost flat.
V8_EXPORT_PRIVATE bool SlowEquals(String other) const; V8_EXPORT_PRIVATE bool SlowEquals(String other) const;
V8_EXPORT_PRIVATE bool SlowEquals(
String other, const SharedStringAccessGuardIfNeeded&) const;
V8_EXPORT_PRIVATE static bool SlowEquals(Isolate* isolate, Handle<String> one, V8_EXPORT_PRIVATE static bool SlowEquals(Isolate* isolate, Handle<String> one,
Handle<String> two); Handle<String> two);
...@@ -580,6 +583,8 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -580,6 +583,8 @@ class String : public TorqueGeneratedString<String, Name> {
// Compute and set the hash code. // Compute and set the hash code.
V8_EXPORT_PRIVATE uint32_t ComputeAndSetHash(); V8_EXPORT_PRIVATE uint32_t ComputeAndSetHash();
V8_EXPORT_PRIVATE uint32_t
ComputeAndSetHash(const SharedStringAccessGuardIfNeeded&);
TQ_OBJECT_CONSTRUCTORS(String) TQ_OBJECT_CONSTRUCTORS(String)
}; };
......
...@@ -207,7 +207,8 @@ Handle<SwissNameDictionary> SwissNameDictionary::Shrink( ...@@ -207,7 +207,8 @@ Handle<SwissNameDictionary> SwissNameDictionary::Shrink(
// storing it somewhere in the main table or the meta table, for those // storing it somewhere in the main table or the meta table, for those
// SwissNameDictionaries that we know will be in-place rehashed, most notably // SwissNameDictionaries that we know will be in-place rehashed, most notably
// those stored in the snapshot. // those stored in the snapshot.
void SwissNameDictionary::Rehash(Isolate* isolate) { template <typename IsolateT>
void SwissNameDictionary::Rehash(IsolateT* isolate) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
struct Entry { struct Entry {
...@@ -307,6 +308,10 @@ template V8_EXPORT_PRIVATE Handle<SwissNameDictionary> ...@@ -307,6 +308,10 @@ template V8_EXPORT_PRIVATE Handle<SwissNameDictionary>
SwissNameDictionary::Rehash(Isolate* isolate, Handle<SwissNameDictionary> table, SwissNameDictionary::Rehash(Isolate* isolate, Handle<SwissNameDictionary> table,
int new_capacity); int new_capacity);
template V8_EXPORT_PRIVATE void SwissNameDictionary::Rehash(
LocalIsolate* isolate);
template V8_EXPORT_PRIVATE void SwissNameDictionary::Rehash(Isolate* isolate);
constexpr int SwissNameDictionary::kInitialCapacity; constexpr int SwissNameDictionary::kInitialCapacity;
constexpr int SwissNameDictionary::kGroupWidth; constexpr int SwissNameDictionary::kGroupWidth;
......
...@@ -133,7 +133,8 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject { ...@@ -133,7 +133,8 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject {
static Handle<SwissNameDictionary> Rehash(IsolateT* isolate, static Handle<SwissNameDictionary> Rehash(IsolateT* isolate,
Handle<SwissNameDictionary> table, Handle<SwissNameDictionary> table,
int new_capacity); int new_capacity);
void Rehash(Isolate* isolate); template <typename IsolateT>
void Rehash(IsolateT* isolate);
inline void SetHash(int hash); inline void SetHash(int hash);
inline int Hash(); inline int Hash();
......
...@@ -4,12 +4,16 @@ ...@@ -4,12 +4,16 @@
#include "src/snapshot/code-serializer.h" #include "src/snapshot/code-serializer.h"
#include <memory>
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/codegen/macro-assembler.h" #include "src/codegen/macro-assembler.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/handles/persistent-handles.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/heap/local-factory-inl.h" #include "src/heap/local-factory-inl.h"
#include "src/heap/parked-scope.h"
#include "src/logging/counters.h" #include "src/logging/counters.h"
#include "src/logging/log.h" #include "src/logging/log.h"
#include "src/logging/runtime-call-stats-scope.h" #include "src/logging/runtime-call-stats-scope.h"
...@@ -277,18 +281,39 @@ class StressOffThreadDeserializeThread final : public base::Thread { ...@@ -277,18 +281,39 @@ class StressOffThreadDeserializeThread final : public base::Thread {
void Run() final { void Run() final {
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground); LocalIsolate local_isolate(isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&local_isolate);
LocalHandleScope handle_scope(&local_isolate);
MaybeHandle<SharedFunctionInfo> local_maybe_result = MaybeHandle<SharedFunctionInfo> local_maybe_result =
ObjectDeserializer::DeserializeSharedFunctionInfoOffThread( OffThreadObjectDeserializer::DeserializeSharedFunctionInfo(
&local_isolate, scd_, local_isolate.factory()->empty_string()); &local_isolate, scd_, &scripts_);
maybe_result_ = maybe_result_ =
local_isolate.heap()->NewPersistentMaybeHandle(local_maybe_result); local_isolate.heap()->NewPersistentMaybeHandle(local_maybe_result);
persistent_handles_ = local_isolate.heap()->DetachPersistentHandles();
}
void Finalize(Isolate* isolate) {
Handle<WeakArrayList> list = isolate->factory()->script_list();
for (Handle<Script> script : scripts_) {
DCHECK(persistent_handles_->Contains(script.location()));
list = WeakArrayList::AddToEnd(isolate, list,
MaybeObjectHandle::Weak(script));
}
isolate->heap()->SetRootScriptList(*list);
Handle<SharedFunctionInfo> result;
if (maybe_result_.ToHandle(&result)) {
maybe_result_ = handle(*result, isolate);
}
} }
private: private:
Isolate* isolate_; Isolate* isolate_;
const SerializedCodeData* scd_; const SerializedCodeData* scd_;
MaybeHandle<SharedFunctionInfo> maybe_result_; MaybeHandle<SharedFunctionInfo> maybe_result_;
std::vector<Handle<Script>> scripts_;
std::unique_ptr<PersistentHandles> persistent_handles_;
}; };
} // namespace } // namespace
...@@ -315,12 +340,12 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( ...@@ -315,12 +340,12 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
// Deserialize. // Deserialize.
MaybeHandle<SharedFunctionInfo> maybe_result; MaybeHandle<SharedFunctionInfo> maybe_result;
// TODO(leszeks): Add LocalHeap support to deserializer if (FLAG_stress_background_compile) {
if (false && FLAG_stress_background_compile) {
StressOffThreadDeserializeThread thread(isolate, &scd); StressOffThreadDeserializeThread thread(isolate, &scd);
CHECK(thread.Start()); CHECK(thread.Start());
thread.Join(); thread.Join();
thread.Finalize(isolate);
maybe_result = thread.maybe_result(); maybe_result = thread.maybe_result();
// Fix-up result script source. // Fix-up result script source.
......
...@@ -17,7 +17,8 @@ class Isolate; ...@@ -17,7 +17,8 @@ class Isolate;
// Deserializes the context-dependent object graph rooted at a given object. // Deserializes the context-dependent object graph rooted at a given object.
// The ContextDeserializer is not expected to deserialize any code objects. // The ContextDeserializer is not expected to deserialize any code objects.
class V8_EXPORT_PRIVATE ContextDeserializer final : public Deserializer { class V8_EXPORT_PRIVATE ContextDeserializer final
: public Deserializer<Isolate> {
public: public:
static MaybeHandle<Context> DeserializeContext( static MaybeHandle<Context> DeserializeContext(
Isolate* isolate, const SnapshotData* data, bool can_rehash, Isolate* isolate, const SnapshotData* data, bool can_rehash,
......
...@@ -14,10 +14,14 @@ ...@@ -14,10 +14,14 @@
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/heap/heap-write-barrier-inl.h" #include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/heap-write-barrier.h" #include "src/heap/heap-write-barrier.h"
#include "src/heap/heap.h"
#include "src/heap/local-heap-inl.h"
#include "src/heap/read-only-heap.h" #include "src/heap/read-only-heap.h"
#include "src/interpreter/interpreter.h" #include "src/interpreter/interpreter.h"
#include "src/logging/local-logger.h"
#include "src/logging/log.h" #include "src/logging/log.h"
#include "src/objects/api-callbacks.h" #include "src/objects/api-callbacks.h"
#include "src/objects/backing-store.h"
#include "src/objects/cell-inl.h" #include "src/objects/cell-inl.h"
#include "src/objects/embedder-data-array-inl.h" #include "src/objects/embedder-data-array-inl.h"
#include "src/objects/hash-table.h" #include "src/objects/hash-table.h"
...@@ -149,9 +153,10 @@ class SlotAccessorForRootSlots { ...@@ -149,9 +153,10 @@ class SlotAccessorForRootSlots {
// A SlotAccessor for creating a Handle, which saves a Handle allocation when // A SlotAccessor for creating a Handle, which saves a Handle allocation when
// a Handle already exists. // a Handle already exists.
template <typename IsolateT>
class SlotAccessorForHandle { class SlotAccessorForHandle {
public: public:
SlotAccessorForHandle(Handle<HeapObject>* handle, Isolate* isolate) SlotAccessorForHandle(Handle<HeapObject>* handle, IsolateT* isolate)
: handle_(handle), isolate_(isolate) {} : handle_(handle), isolate_(isolate) {}
MaybeObjectSlot slot() const { UNREACHABLE(); } MaybeObjectSlot slot() const { UNREACHABLE(); }
...@@ -185,36 +190,62 @@ class SlotAccessorForHandle { ...@@ -185,36 +190,62 @@ class SlotAccessorForHandle {
private: private:
Handle<HeapObject>* handle_; Handle<HeapObject>* handle_;
Isolate* isolate_; IsolateT* isolate_;
}; };
template <typename IsolateT>
template <typename TSlot> template <typename TSlot>
int Deserializer::WriteAddress(TSlot dest, Address value) { int Deserializer<IsolateT>::WriteAddress(TSlot dest, Address value) {
DCHECK(!next_reference_is_weak_); DCHECK(!next_reference_is_weak_);
memcpy(dest.ToVoidPtr(), &value, kSystemPointerSize); memcpy(dest.ToVoidPtr(), &value, kSystemPointerSize);
STATIC_ASSERT(IsAligned(kSystemPointerSize, TSlot::kSlotDataSize)); STATIC_ASSERT(IsAligned(kSystemPointerSize, TSlot::kSlotDataSize));
return (kSystemPointerSize / TSlot::kSlotDataSize); return (kSystemPointerSize / TSlot::kSlotDataSize);
} }
template <typename IsolateT>
template <typename TSlot> template <typename TSlot>
int Deserializer::WriteExternalPointer(TSlot dest, Address value, int Deserializer<IsolateT>::WriteExternalPointer(TSlot dest, Address value,
ExternalPointerTag tag) { ExternalPointerTag tag) {
DCHECK(!next_reference_is_weak_); DCHECK(!next_reference_is_weak_);
InitExternalPointerField(dest.address(), isolate(), value, tag); InitExternalPointerField(dest.address(), main_thread_isolate(), value, tag);
STATIC_ASSERT(IsAligned(kExternalPointerSize, TSlot::kSlotDataSize)); STATIC_ASSERT(IsAligned(kExternalPointerSize, TSlot::kSlotDataSize));
return (kExternalPointerSize / TSlot::kSlotDataSize); return (kExternalPointerSize / TSlot::kSlotDataSize);
} }
Deserializer::Deserializer(Isolate* isolate, base::Vector<const byte> payload, namespace {
uint32_t magic_number, bool deserializing_user_code, #ifdef DEBUG
bool can_rehash) int GetNumApiReferences(Isolate* isolate) {
int num_api_references = 0;
// The read-only deserializer is run by read-only heap set-up before the
// heap is fully set up. External reference table relies on a few parts of
// this set-up (like old-space), so it may be uninitialized at this point.
if (isolate->isolate_data()->external_reference_table()->is_initialized()) {
// Count the number of external references registered through the API.
if (isolate->api_external_references() != nullptr) {
while (isolate->api_external_references()[num_api_references] != 0) {
num_api_references++;
}
}
}
return num_api_references;
}
int GetNumApiReferences(LocalIsolate* isolate) { return 0; }
#endif
} // namespace
template <typename IsolateT>
Deserializer<IsolateT>::Deserializer(IsolateT* isolate,
base::Vector<const byte> payload,
uint32_t magic_number,
bool deserializing_user_code,
bool can_rehash)
: isolate_(isolate), : isolate_(isolate),
source_(payload), source_(payload),
magic_number_(magic_number), magic_number_(magic_number),
deserializing_user_code_(deserializing_user_code), deserializing_user_code_(deserializing_user_code),
can_rehash_(can_rehash) { can_rehash_(can_rehash) {
DCHECK_NOT_NULL(isolate); DCHECK_NOT_NULL(isolate);
isolate_->RegisterDeserializerStarted(); isolate->RegisterDeserializerStarted();
// We start the indices here at 1, so that we can distinguish between an // We start the indices here at 1, so that we can distinguish between an
// actual index and a nullptr (serialized as kNullRefSentinel) in a // actual index and a nullptr (serialized as kNullRefSentinel) in a
...@@ -223,30 +254,21 @@ Deserializer::Deserializer(Isolate* isolate, base::Vector<const byte> payload, ...@@ -223,30 +254,21 @@ Deserializer::Deserializer(Isolate* isolate, base::Vector<const byte> payload,
backing_stores_.push_back({}); backing_stores_.push_back({});
#ifdef DEBUG #ifdef DEBUG
num_api_references_ = 0; num_api_references_ = GetNumApiReferences(isolate);
// The read-only deserializer is run by read-only heap set-up before the
// heap is fully set up. External reference table relies on a few parts of
// this set-up (like old-space), so it may be uninitialized at this point.
if (isolate->isolate_data()->external_reference_table()->is_initialized()) {
// Count the number of external references registered through the API.
if (isolate->api_external_references() != nullptr) {
while (isolate->api_external_references()[num_api_references_] != 0) {
num_api_references_++;
}
}
}
#endif // DEBUG #endif // DEBUG
CHECK_EQ(magic_number_, SerializedData::kMagicNumber); CHECK_EQ(magic_number_, SerializedData::kMagicNumber);
} }
void Deserializer::Rehash() { template <typename IsolateT>
void Deserializer<IsolateT>::Rehash() {
DCHECK(can_rehash() || deserializing_user_code()); DCHECK(can_rehash() || deserializing_user_code());
for (Handle<HeapObject> item : to_rehash_) { for (Handle<HeapObject> item : to_rehash_) {
item->RehashBasedOnMap(isolate()); item->RehashBasedOnMap(isolate());
} }
} }
Deserializer::~Deserializer() { template <typename IsolateT>
Deserializer<IsolateT>::~Deserializer() {
#ifdef DEBUG #ifdef DEBUG
// Do not perform checks if we aborted deserialization. // Do not perform checks if we aborted deserialization.
if (source_.position() == 0) return; if (source_.position() == 0) return;
...@@ -261,24 +283,30 @@ Deserializer::~Deserializer() { ...@@ -261,24 +283,30 @@ Deserializer::~Deserializer() {
// This is called on the roots. It is the driver of the deserialization // This is called on the roots. It is the driver of the deserialization
// process. It is also called on the body of each function. // process. It is also called on the body of each function.
void Deserializer::VisitRootPointers(Root root, const char* description, template <typename IsolateT>
FullObjectSlot start, FullObjectSlot end) { void Deserializer<IsolateT>::VisitRootPointers(Root root,
const char* description,
FullObjectSlot start,
FullObjectSlot end) {
ReadData(FullMaybeObjectSlot(start), FullMaybeObjectSlot(end)); ReadData(FullMaybeObjectSlot(start), FullMaybeObjectSlot(end));
} }
void Deserializer::Synchronize(VisitorSynchronization::SyncTag tag) { template <typename IsolateT>
void Deserializer<IsolateT>::Synchronize(VisitorSynchronization::SyncTag tag) {
static const byte expected = kSynchronize; static const byte expected = kSynchronize;
CHECK_EQ(expected, source_.Get()); CHECK_EQ(expected, source_.Get());
} }
void Deserializer::DeserializeDeferredObjects() { template <typename IsolateT>
void Deserializer<IsolateT>::DeserializeDeferredObjects() {
for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) { for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) {
SnapshotSpace space = NewObject::Decode(code); SnapshotSpace space = NewObject::Decode(code);
ReadObject(space); ReadObject(space);
} }
} }
void Deserializer::LogNewMapEvents() { template <typename IsolateT>
void Deserializer<IsolateT>::LogNewMapEvents() {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
for (Handle<Map> map : new_maps_) { for (Handle<Map> map : new_maps_) {
DCHECK(FLAG_log_maps); DCHECK(FLAG_log_maps);
...@@ -287,7 +315,8 @@ void Deserializer::LogNewMapEvents() { ...@@ -287,7 +315,8 @@ void Deserializer::LogNewMapEvents() {
} }
} }
void Deserializer::WeakenDescriptorArrays() { template <typename IsolateT>
void Deserializer<IsolateT>::WeakenDescriptorArrays() {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
for (Handle<DescriptorArray> descriptor_array : new_descriptor_arrays_) { for (Handle<DescriptorArray> descriptor_array : new_descriptor_arrays_) {
DCHECK(descriptor_array->IsStrongDescriptorArray()); DCHECK(descriptor_array->IsStrongDescriptorArray());
...@@ -297,36 +326,66 @@ void Deserializer::WeakenDescriptorArrays() { ...@@ -297,36 +326,66 @@ void Deserializer::WeakenDescriptorArrays() {
} }
} }
void Deserializer::LogScriptEvents(Script script) { template <typename IsolateT>
void Deserializer<IsolateT>::LogScriptEvents(Script script) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
LOG(isolate(), LOG(isolate(),
ScriptEvent(Logger::ScriptEventType::kDeserialize, script.id())); ScriptEvent(Logger::ScriptEventType::kDeserialize, script.id()));
LOG(isolate(), ScriptDetails(script)); LOG(isolate(), ScriptDetails(script));
} }
StringTableInsertionKey::StringTableInsertionKey(Handle<String> string) namespace {
: StringTableKey(ComputeRawHashField(*string), string->length()), template <typename IsolateT>
uint32_t ComputeRawHashField(IsolateT* isolate, String string) {
// Make sure raw_hash_field() is computed.
string.EnsureHash(SharedStringAccessGuardIfNeeded(isolate));
return string.raw_hash_field();
}
} // namespace
StringTableInsertionKey::StringTableInsertionKey(Isolate* isolate,
Handle<String> string)
: StringTableKey(ComputeRawHashField(isolate, *string), string->length()),
string_(string) { string_(string) {
DCHECK(string->IsInternalizedString()); DCHECK(string->IsInternalizedString());
} }
bool StringTableInsertionKey::IsMatch(Isolate* isolate, String string) { StringTableInsertionKey::StringTableInsertionKey(LocalIsolate* isolate,
// We want to compare the content of two strings here. Handle<String> string)
return string_->SlowEquals(string); : StringTableKey(ComputeRawHashField(isolate, *string), string->length()),
string_(string) {
DCHECK(string->IsInternalizedString());
} }
Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) { template <typename IsolateT>
return string_; bool StringTableInsertionKey::IsMatch(IsolateT* isolate, String string) {
// We want to compare the content of two strings here.
return string_->SlowEquals(string, SharedStringAccessGuardIfNeeded(isolate));
} }
template bool StringTableInsertionKey::IsMatch(Isolate* isolate, String string);
template bool StringTableInsertionKey::IsMatch(LocalIsolate* isolate,
String string);
uint32_t StringTableInsertionKey::ComputeRawHashField(String string) { namespace {
// Make sure raw_hash_field() is computed.
string.EnsureHash(); void PostProcessExternalString(Handle<ExternalString> string,
return string.raw_hash_field(); Isolate* isolate) {
uint32_t index = string->GetResourceRefForDeserialization();
Address address =
static_cast<Address>(isolate->api_external_references()[index]);
string->AllocateExternalPointerEntries(isolate);
string->set_address_as_resource(isolate, address);
isolate->heap()->UpdateExternalString(*string, 0,
string->ExternalPayloadSize());
isolate->heap()->RegisterExternalString(*string);
} }
void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, } // namespace
SnapshotSpace space) {
template <typename IsolateT>
void Deserializer<IsolateT>::PostProcessNewObject(Handle<Map> map,
Handle<HeapObject> obj,
SnapshotSpace space) {
DCHECK_EQ(*map, obj->map()); DCHECK_EQ(*map, obj->map());
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
InstanceType instance_type = map->instance_type(); InstanceType instance_type = map->instance_type();
...@@ -349,15 +408,20 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -349,15 +408,20 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
if (deserializing_user_code()) { if (deserializing_user_code()) {
if (InstanceTypeChecker::IsInternalizedString(instance_type)) { if (InstanceTypeChecker::IsInternalizedString(instance_type)) {
// Canonicalize the internalized string. If it already exists in the // Canonicalize the internalized string. If it already exists in the
// string table, set it to forward to the existing one. // string table, patch the deserialized string handle to point to the
// existing one.
// TODO(leszeks): This handle patching is ugly, consider adding an
// explicit internalized string bytecode.
Handle<String> string = Handle<String>::cast(obj); Handle<String> string = Handle<String>::cast(obj);
StringTableInsertionKey key(string); StringTableInsertionKey key(isolate(), string);
Handle<String> result = Handle<String> result =
isolate()->string_table()->LookupKey(isolate(), &key); isolate()->string_table()->LookupKey(isolate(), &key);
if (*result != *string) { if (*result != *string) {
string->MakeThin(isolate(), *result); // Invalidate the original string.
isolate()->heap()->CreateFillerObjectAt(
string->address(), string->Size(), ClearRecordedSlots::kNo);
// Mutate the given object handle so that the backreference entry is // Mutate the given object handle so that the backreference entry is
// also updated. // also updated.
obj.PatchValue(*result); obj.PatchValue(*result);
...@@ -388,8 +452,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -388,8 +452,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
} else if (V8_EXTERNAL_CODE_SPACE_BOOL && } else if (V8_EXTERNAL_CODE_SPACE_BOOL &&
InstanceTypeChecker::IsCodeDataContainer(instance_type)) { InstanceTypeChecker::IsCodeDataContainer(instance_type)) {
auto code_data_container = Handle<CodeDataContainer>::cast(obj); auto code_data_container = Handle<CodeDataContainer>::cast(obj);
code_data_container->AllocateExternalPointerEntries(isolate()); code_data_container->AllocateExternalPointerEntries(main_thread_isolate());
code_data_container->UpdateCodeEntryPoint(isolate(), code_data_container->UpdateCodeEntryPoint(main_thread_isolate(),
code_data_container->code()); code_data_container->code());
} else if (InstanceTypeChecker::IsMap(instance_type)) { } else if (InstanceTypeChecker::IsMap(instance_type)) {
if (FLAG_log_maps) { if (FLAG_log_maps) {
...@@ -406,15 +470,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -406,15 +470,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
call_handler_infos_.push_back(Handle<CallHandlerInfo>::cast(obj)); call_handler_infos_.push_back(Handle<CallHandlerInfo>::cast(obj));
#endif #endif
} else if (InstanceTypeChecker::IsExternalString(instance_type)) { } else if (InstanceTypeChecker::IsExternalString(instance_type)) {
Handle<ExternalString> string = Handle<ExternalString>::cast(obj); PostProcessExternalString(Handle<ExternalString>::cast(obj),
uint32_t index = string->GetResourceRefForDeserialization(); main_thread_isolate());
Address address =
static_cast<Address>(isolate()->api_external_references()[index]);
string->AllocateExternalPointerEntries(isolate());
string->set_address_as_resource(isolate(), address);
isolate()->heap()->UpdateExternalString(*string, 0,
string->ExternalPayloadSize());
isolate()->heap()->RegisterExternalString(*string);
} else if (InstanceTypeChecker::IsJSDataView(instance_type)) { } else if (InstanceTypeChecker::IsJSDataView(instance_type)) {
Handle<JSDataView> data_view = Handle<JSDataView>::cast(obj); Handle<JSDataView> data_view = Handle<JSDataView>::cast(obj);
JSArrayBuffer buffer = JSArrayBuffer::cast(data_view->buffer()); JSArrayBuffer buffer = JSArrayBuffer::cast(data_view->buffer());
...@@ -426,18 +483,18 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -426,18 +483,18 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
// a numbered reference to an already deserialized backing store. // a numbered reference to an already deserialized backing store.
backing_store = backing_stores_[store_index]->buffer_start(); backing_store = backing_stores_[store_index]->buffer_start();
} }
data_view->AllocateExternalPointerEntries(isolate()); data_view->AllocateExternalPointerEntries(main_thread_isolate());
data_view->set_data_pointer( data_view->set_data_pointer(
isolate(), main_thread_isolate(),
reinterpret_cast<uint8_t*>(backing_store) + data_view->byte_offset()); reinterpret_cast<uint8_t*>(backing_store) + data_view->byte_offset());
} else if (InstanceTypeChecker::IsJSTypedArray(instance_type)) { } else if (InstanceTypeChecker::IsJSTypedArray(instance_type)) {
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(obj); Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(obj);
// Fixup typed array pointers. // Fixup typed array pointers.
if (typed_array->is_on_heap()) { if (typed_array->is_on_heap()) {
Address raw_external_pointer = typed_array->external_pointer_raw(); Address raw_external_pointer = typed_array->external_pointer_raw();
typed_array->AllocateExternalPointerEntries(isolate()); typed_array->AllocateExternalPointerEntries(main_thread_isolate());
typed_array->SetOnHeapDataPtr( typed_array->SetOnHeapDataPtr(
isolate(), HeapObject::cast(typed_array->base_pointer()), main_thread_isolate(), HeapObject::cast(typed_array->base_pointer()),
raw_external_pointer); raw_external_pointer);
} else { } else {
// Serializer writes backing store ref as a DataPtr() value. // Serializer writes backing store ref as a DataPtr() value.
...@@ -447,8 +504,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -447,8 +504,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
auto start = backing_store auto start = backing_store
? reinterpret_cast<byte*>(backing_store->buffer_start()) ? reinterpret_cast<byte*>(backing_store->buffer_start())
: nullptr; : nullptr;
typed_array->AllocateExternalPointerEntries(isolate()); typed_array->AllocateExternalPointerEntries(main_thread_isolate());
typed_array->SetOffHeapDataPtr(isolate(), start, typed_array->SetOffHeapDataPtr(main_thread_isolate(), start,
typed_array->byte_offset()); typed_array->byte_offset());
} }
} else if (InstanceTypeChecker::IsJSArrayBuffer(instance_type)) { } else if (InstanceTypeChecker::IsJSArrayBuffer(instance_type)) {
...@@ -457,8 +514,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -457,8 +514,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
if (buffer->GetBackingStoreRefForDeserialization() != kNullRefSentinel) { if (buffer->GetBackingStoreRefForDeserialization() != kNullRefSentinel) {
new_off_heap_array_buffers_.push_back(buffer); new_off_heap_array_buffers_.push_back(buffer);
} else { } else {
buffer->AllocateExternalPointerEntries(isolate()); buffer->AllocateExternalPointerEntries(main_thread_isolate());
buffer->set_backing_store(isolate(), nullptr); buffer->set_backing_store(main_thread_isolate(), nullptr);
} }
} else if (InstanceTypeChecker::IsBytecodeArray(instance_type)) { } else if (InstanceTypeChecker::IsBytecodeArray(instance_type)) {
// TODO(mythria): Remove these once we store the default values for these // TODO(mythria): Remove these once we store the default values for these
...@@ -471,7 +528,7 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -471,7 +528,7 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
new_descriptor_arrays_.push_back(descriptors); new_descriptor_arrays_.push_back(descriptors);
} else if (InstanceTypeChecker::IsNativeContext(instance_type)) { } else if (InstanceTypeChecker::IsNativeContext(instance_type)) {
Handle<NativeContext> context = Handle<NativeContext>::cast(obj); Handle<NativeContext> context = Handle<NativeContext>::cast(obj);
context->AllocateExternalPointerEntries(isolate()); context->AllocateExternalPointerEntries(main_thread_isolate());
} }
// Check alignment. // Check alignment.
...@@ -479,7 +536,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj, ...@@ -479,7 +536,8 @@ void Deserializer::PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
HeapObject::RequiredAlignment(*map))); HeapObject::RequiredAlignment(*map)));
} }
HeapObjectReferenceType Deserializer::GetAndResetNextReferenceType() { template <typename IsolateT>
HeapObjectReferenceType Deserializer<IsolateT>::GetAndResetNextReferenceType() {
HeapObjectReferenceType type = next_reference_is_weak_ HeapObjectReferenceType type = next_reference_is_weak_
? HeapObjectReferenceType::WEAK ? HeapObjectReferenceType::WEAK
: HeapObjectReferenceType::STRONG; : HeapObjectReferenceType::STRONG;
...@@ -487,7 +545,8 @@ HeapObjectReferenceType Deserializer::GetAndResetNextReferenceType() { ...@@ -487,7 +545,8 @@ HeapObjectReferenceType Deserializer::GetAndResetNextReferenceType() {
return type; return type;
} }
Handle<HeapObject> Deserializer::GetBackReferencedObject() { template <typename IsolateT>
Handle<HeapObject> Deserializer<IsolateT>::GetBackReferencedObject() {
Handle<HeapObject> obj = back_refs_[source_.GetInt()]; Handle<HeapObject> obj = back_refs_[source_.GetInt()];
// We don't allow ThinStrings in backreferences -- if internalization produces // We don't allow ThinStrings in backreferences -- if internalization produces
...@@ -499,15 +558,17 @@ Handle<HeapObject> Deserializer::GetBackReferencedObject() { ...@@ -499,15 +558,17 @@ Handle<HeapObject> Deserializer::GetBackReferencedObject() {
return obj; return obj;
} }
Handle<HeapObject> Deserializer::ReadObject() { template <typename IsolateT>
Handle<HeapObject> Deserializer<IsolateT>::ReadObject() {
Handle<HeapObject> ret; Handle<HeapObject> ret;
CHECK_EQ(ReadSingleBytecodeData(source_.Get(), CHECK_EQ(ReadSingleBytecodeData(
SlotAccessorForHandle(&ret, isolate())), source_.Get(), SlotAccessorForHandle<IsolateT>(&ret, isolate())),
1); 1);
return ret; return ret;
} }
Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) { template <typename IsolateT>
Handle<HeapObject> Deserializer<IsolateT>::ReadObject(SnapshotSpace space) {
const int size_in_tagged = source_.GetInt(); const int size_in_tagged = source_.GetInt();
const int size_in_bytes = size_in_tagged * kTaggedSize; const int size_in_bytes = size_in_tagged * kTaggedSize;
...@@ -555,8 +616,8 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) { ...@@ -555,8 +616,8 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) {
JSObject js_obj = JSObject::cast(raw_obj); JSObject js_obj = JSObject::cast(raw_obj);
for (int i = 0; i < js_obj.GetEmbedderFieldCount(); ++i) { for (int i = 0; i < js_obj.GetEmbedderFieldCount(); ++i) {
void* pointer; void* pointer;
CHECK(EmbedderDataSlot(js_obj, i).ToAlignedPointerSafe(isolate(), CHECK(EmbedderDataSlot(js_obj, i).ToAlignedPointerSafe(
&pointer)); main_thread_isolate(), &pointer));
CHECK_NULL(pointer); CHECK_NULL(pointer);
} }
} else if (raw_obj.IsEmbedderDataArray()) { } else if (raw_obj.IsEmbedderDataArray()) {
...@@ -565,7 +626,7 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) { ...@@ -565,7 +626,7 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) {
EmbedderDataSlot end(array, array.length()); EmbedderDataSlot end(array, array.length());
for (EmbedderDataSlot slot = start; slot < end; ++slot) { for (EmbedderDataSlot slot = start; slot < end; ++slot) {
void* pointer; void* pointer;
CHECK(slot.ToAlignedPointerSafe(isolate(), &pointer)); CHECK(slot.ToAlignedPointerSafe(main_thread_isolate(), &pointer));
CHECK_NULL(pointer); CHECK_NULL(pointer);
} }
} }
...@@ -577,8 +638,6 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) { ...@@ -577,8 +638,6 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) {
ReadData(obj, 1, size_in_tagged); ReadData(obj, 1, size_in_tagged);
PostProcessNewObject(map, obj, space); PostProcessNewObject(map, obj, space);
DCHECK(!obj->IsThinString(isolate()));
#ifdef DEBUG #ifdef DEBUG
if (obj->IsCode()) { if (obj->IsCode()) {
DCHECK(space == SnapshotSpace::kCode || DCHECK(space == SnapshotSpace::kCode ||
...@@ -591,7 +650,8 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) { ...@@ -591,7 +650,8 @@ Handle<HeapObject> Deserializer::ReadObject(SnapshotSpace space) {
return obj; return obj;
} }
Handle<HeapObject> Deserializer::ReadMetaMap() { template <typename IsolateT>
Handle<HeapObject> Deserializer<IsolateT>::ReadMetaMap() {
const SnapshotSpace space = SnapshotSpace::kReadOnlyHeap; const SnapshotSpace space = SnapshotSpace::kReadOnlyHeap;
const int size_in_bytes = Map::kSize; const int size_in_bytes = Map::kSize;
const int size_in_tagged = size_in_bytes / kTaggedSize; const int size_in_tagged = size_in_bytes / kTaggedSize;
...@@ -613,12 +673,20 @@ Handle<HeapObject> Deserializer::ReadMetaMap() { ...@@ -613,12 +673,20 @@ Handle<HeapObject> Deserializer::ReadMetaMap() {
return obj; return obj;
} }
class Deserializer::RelocInfoVisitor { class DeserializerRelocInfoVisitor {
public: public:
RelocInfoVisitor(Deserializer* deserializer, DeserializerRelocInfoVisitor(Deserializer<Isolate>* deserializer,
const std::vector<Handle<HeapObject>>* objects) const std::vector<Handle<HeapObject>>* objects)
: deserializer_(deserializer), objects_(objects), current_object_(0) {} : deserializer_(deserializer), objects_(objects), current_object_(0) {}
~RelocInfoVisitor() { DCHECK_EQ(current_object_, objects_->size()); }
DeserializerRelocInfoVisitor(Deserializer<LocalIsolate>* deserializer,
const std::vector<Handle<HeapObject>>* objects) {
UNREACHABLE();
}
~DeserializerRelocInfoVisitor() {
DCHECK_EQ(current_object_, objects_->size());
}
void VisitCodeTarget(Code host, RelocInfo* rinfo); void VisitCodeTarget(Code host, RelocInfo* rinfo);
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo); void VisitEmbeddedPointer(Code host, RelocInfo* rinfo);
...@@ -631,34 +699,34 @@ class Deserializer::RelocInfoVisitor { ...@@ -631,34 +699,34 @@ class Deserializer::RelocInfoVisitor {
Isolate* isolate() { return deserializer_->isolate(); } Isolate* isolate() { return deserializer_->isolate(); }
SnapshotByteSource& source() { return deserializer_->source_; } SnapshotByteSource& source() { return deserializer_->source_; }
Deserializer* deserializer_; Deserializer<Isolate>* deserializer_;
const std::vector<Handle<HeapObject>>* objects_; const std::vector<Handle<HeapObject>>* objects_;
int current_object_; int current_object_;
}; };
void Deserializer::RelocInfoVisitor::VisitCodeTarget(Code host, void DeserializerRelocInfoVisitor::VisitCodeTarget(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
HeapObject object = *objects_->at(current_object_++); HeapObject object = *objects_->at(current_object_++);
rinfo->set_target_address(Code::cast(object).raw_instruction_start()); rinfo->set_target_address(Code::cast(object).raw_instruction_start());
} }
void Deserializer::RelocInfoVisitor::VisitEmbeddedPointer(Code host, void DeserializerRelocInfoVisitor::VisitEmbeddedPointer(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
HeapObject object = *objects_->at(current_object_++); HeapObject object = *objects_->at(current_object_++);
// Embedded object reference must be a strong one. // Embedded object reference must be a strong one.
rinfo->set_target_object(isolate()->heap(), object); rinfo->set_target_object(isolate()->heap(), object);
} }
void Deserializer::RelocInfoVisitor::VisitRuntimeEntry(Code host, void DeserializerRelocInfoVisitor::VisitRuntimeEntry(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
// We no longer serialize code that contains runtime entries. // We no longer serialize code that contains runtime entries.
UNREACHABLE(); UNREACHABLE();
} }
void Deserializer::RelocInfoVisitor::VisitExternalReference(Code host, void DeserializerRelocInfoVisitor::VisitExternalReference(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
byte data = source().Get(); byte data = source().Get();
CHECK_EQ(data, kExternalReference); CHECK_EQ(data, Deserializer<Isolate>::kExternalReference);
Address address = deserializer_->ReadExternalReferenceCase(); Address address = deserializer_->ReadExternalReferenceCase();
...@@ -671,10 +739,10 @@ void Deserializer::RelocInfoVisitor::VisitExternalReference(Code host, ...@@ -671,10 +739,10 @@ void Deserializer::RelocInfoVisitor::VisitExternalReference(Code host,
} }
} }
void Deserializer::RelocInfoVisitor::VisitInternalReference(Code host, void DeserializerRelocInfoVisitor::VisitInternalReference(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
byte data = source().Get(); byte data = source().Get();
CHECK_EQ(data, kInternalReference); CHECK_EQ(data, Deserializer<Isolate>::kInternalReference);
// Internal reference target is encoded as an offset from code entry. // Internal reference target is encoded as an offset from code entry.
int target_offset = source().GetInt(); int target_offset = source().GetInt();
...@@ -689,10 +757,10 @@ void Deserializer::RelocInfoVisitor::VisitInternalReference(Code host, ...@@ -689,10 +757,10 @@ void Deserializer::RelocInfoVisitor::VisitInternalReference(Code host,
rinfo->pc(), target, rinfo->rmode()); rinfo->pc(), target, rinfo->rmode());
} }
void Deserializer::RelocInfoVisitor::VisitOffHeapTarget(Code host, void DeserializerRelocInfoVisitor::VisitOffHeapTarget(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
byte data = source().Get(); byte data = source().Get();
CHECK_EQ(data, kOffHeapTarget); CHECK_EQ(data, Deserializer<Isolate>::kOffHeapTarget);
Builtin builtin = Builtins::FromInt(source().GetInt()); Builtin builtin = Builtins::FromInt(source().GetInt());
...@@ -711,9 +779,10 @@ void Deserializer::RelocInfoVisitor::VisitOffHeapTarget(Code host, ...@@ -711,9 +779,10 @@ void Deserializer::RelocInfoVisitor::VisitOffHeapTarget(Code host,
} }
} }
template <typename IsolateT>
template <typename SlotAccessor> template <typename SlotAccessor>
int Deserializer::ReadRepeatedObject(SlotAccessor slot_accessor, int Deserializer<IsolateT>::ReadRepeatedObject(SlotAccessor slot_accessor,
int repeat_count) { int repeat_count) {
CHECK_LE(2, repeat_count); CHECK_LE(2, repeat_count);
Handle<HeapObject> heap_object = ReadObject(); Handle<HeapObject> heap_object = ReadObject();
...@@ -765,8 +834,10 @@ constexpr byte VerifyBytecodeCount(byte bytecode) { ...@@ -765,8 +834,10 @@ constexpr byte VerifyBytecodeCount(byte bytecode) {
: case SpaceEncoder<bytecode>::Encode(SnapshotSpace::kMap) \ : case SpaceEncoder<bytecode>::Encode(SnapshotSpace::kMap) \
: case SpaceEncoder<bytecode>::Encode(SnapshotSpace::kReadOnlyHeap) : case SpaceEncoder<bytecode>::Encode(SnapshotSpace::kReadOnlyHeap)
void Deserializer::ReadData(Handle<HeapObject> object, int start_slot_index, template <typename IsolateT>
int end_slot_index) { void Deserializer<IsolateT>::ReadData(Handle<HeapObject> object,
int start_slot_index,
int end_slot_index) {
int current = start_slot_index; int current = start_slot_index;
while (current < end_slot_index) { while (current < end_slot_index) {
byte data = source_.Get(); byte data = source_.Get();
...@@ -776,8 +847,9 @@ void Deserializer::ReadData(Handle<HeapObject> object, int start_slot_index, ...@@ -776,8 +847,9 @@ void Deserializer::ReadData(Handle<HeapObject> object, int start_slot_index,
CHECK_EQ(current, end_slot_index); CHECK_EQ(current, end_slot_index);
} }
void Deserializer::ReadData(FullMaybeObjectSlot start, template <typename IsolateT>
FullMaybeObjectSlot end) { void Deserializer<IsolateT>::ReadData(FullMaybeObjectSlot start,
FullMaybeObjectSlot end) {
FullMaybeObjectSlot current = start; FullMaybeObjectSlot current = start;
while (current < end) { while (current < end) {
byte data = source_.Get(); byte data = source_.Get();
...@@ -786,9 +858,10 @@ void Deserializer::ReadData(FullMaybeObjectSlot start, ...@@ -786,9 +858,10 @@ void Deserializer::ReadData(FullMaybeObjectSlot start,
CHECK_EQ(current, end); CHECK_EQ(current, end);
} }
template <typename IsolateT>
template <typename SlotAccessor> template <typename SlotAccessor>
int Deserializer::ReadSingleBytecodeData(byte data, int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data,
SlotAccessor slot_accessor) { SlotAccessor slot_accessor) {
using TSlot = decltype(slot_accessor.slot()); using TSlot = decltype(slot_accessor.slot());
switch (data) { switch (data) {
...@@ -841,8 +914,8 @@ int Deserializer::ReadSingleBytecodeData(byte data, ...@@ -841,8 +914,8 @@ int Deserializer::ReadSingleBytecodeData(byte data,
int cache_index = source_.GetInt(); int cache_index = source_.GetInt();
// TODO(leszeks): Could we use the address of the startup_object_cache // TODO(leszeks): Could we use the address of the startup_object_cache
// entry as a Handle backing? // entry as a Handle backing?
HeapObject heap_object = HeapObject heap_object = HeapObject::cast(
HeapObject::cast(isolate()->startup_object_cache()->at(cache_index)); main_thread_isolate()->startup_object_cache()->at(cache_index));
return slot_accessor.Write(heap_object, GetAndResetNextReferenceType()); return slot_accessor.Write(heap_object, GetAndResetNextReferenceType());
} }
...@@ -989,7 +1062,7 @@ int Deserializer::ReadSingleBytecodeData(byte data, ...@@ -989,7 +1062,7 @@ int Deserializer::ReadSingleBytecodeData(byte data,
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Code code = Code::cast(*slot_accessor.object()); Code code = Code::cast(*slot_accessor.object());
RelocInfoVisitor visitor(this, &preserialized_objects); DeserializerRelocInfoVisitor visitor(this, &preserialized_objects);
for (RelocIterator it(code, Code::BodyDescriptor::kRelocModeMask); for (RelocIterator it(code, Code::BodyDescriptor::kRelocModeMask);
!it.done(); it.next()) { !it.done(); it.next()) {
it.rinfo()->Visit(&visitor); it.rinfo()->Visit(&visitor);
...@@ -1007,11 +1080,10 @@ int Deserializer::ReadSingleBytecodeData(byte data, ...@@ -1007,11 +1080,10 @@ int Deserializer::ReadSingleBytecodeData(byte data,
} }
case kOffHeapBackingStore: { case kOffHeapBackingStore: {
AlwaysAllocateScope scope(isolate()->heap());
int byte_length = source_.GetInt(); int byte_length = source_.GetInt();
std::unique_ptr<BackingStore> backing_store = std::unique_ptr<BackingStore> backing_store = BackingStore::Allocate(
BackingStore::Allocate(isolate(), byte_length, SharedFlag::kNotShared, main_thread_isolate(), byte_length, SharedFlag::kNotShared,
InitializedFlag::kUninitialized); InitializedFlag::kUninitialized);
CHECK_NOT_NULL(backing_store); CHECK_NOT_NULL(backing_store);
source_.CopyRaw(backing_store->buffer_start(), byte_length); source_.CopyRaw(backing_store->buffer_start(), byte_length);
backing_stores_.push_back(std::move(backing_store)); backing_stores_.push_back(std::move(backing_store));
...@@ -1022,11 +1094,11 @@ int Deserializer::ReadSingleBytecodeData(byte data, ...@@ -1022,11 +1094,11 @@ int Deserializer::ReadSingleBytecodeData(byte data,
case kApiReference: { case kApiReference: {
uint32_t reference_id = static_cast<uint32_t>(source_.GetInt()); uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
Address address; Address address;
if (isolate()->api_external_references()) { if (main_thread_isolate()->api_external_references()) {
DCHECK_WITH_MSG(reference_id < num_api_references_, DCHECK_WITH_MSG(reference_id < num_api_references_,
"too few external references provided through the API"); "too few external references provided through the API");
address = static_cast<Address>( address = static_cast<Address>(
isolate()->api_external_references()[reference_id]); main_thread_isolate()->api_external_references()[reference_id]);
} else { } else {
address = reinterpret_cast<Address>(NoExternalReferencesCallback); address = reinterpret_cast<Address>(NoExternalReferencesCallback);
} }
...@@ -1117,9 +1189,11 @@ int Deserializer::ReadSingleBytecodeData(byte data, ...@@ -1117,9 +1189,11 @@ int Deserializer::ReadSingleBytecodeData(byte data,
#undef CASE_R2 #undef CASE_R2
#undef CASE_R1 #undef CASE_R1
Address Deserializer::ReadExternalReferenceCase() { template <typename IsolateT>
Address Deserializer<IsolateT>::ReadExternalReferenceCase() {
uint32_t reference_id = static_cast<uint32_t>(source_.GetInt()); uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
return isolate()->external_reference_table()->address(reference_id); return main_thread_isolate()->external_reference_table()->address(
reference_id);
} }
namespace { namespace {
...@@ -1137,8 +1211,9 @@ AllocationType SpaceToType(SnapshotSpace space) { ...@@ -1137,8 +1211,9 @@ AllocationType SpaceToType(SnapshotSpace space) {
} }
} // namespace } // namespace
HeapObject Deserializer::Allocate(SnapshotSpace space, int size, template <typename IsolateT>
AllocationAlignment alignment) { HeapObject Deserializer<IsolateT>::Allocate(SnapshotSpace space, int size,
AllocationAlignment alignment) {
#ifdef DEBUG #ifdef DEBUG
if (!previous_allocation_obj_.is_null()) { if (!previous_allocation_obj_.is_null()) {
// Make sure that the previous object is initialized sufficiently to // Make sure that the previous object is initialized sufficiently to
...@@ -1148,8 +1223,8 @@ HeapObject Deserializer::Allocate(SnapshotSpace space, int size, ...@@ -1148,8 +1223,8 @@ HeapObject Deserializer::Allocate(SnapshotSpace space, int size,
} }
#endif #endif
HeapObject obj = isolate()->heap()->AllocateRawWith<Heap::kRetryOrFail>( HeapObject obj = HeapObject::FromAddress(isolate()->heap()->AllocateRawOrFail(
size, SpaceToType(space), AllocationOrigin::kRuntime, alignment); size, SpaceToType(space), AllocationOrigin::kRuntime, alignment));
#ifdef DEBUG #ifdef DEBUG
previous_allocation_obj_ = handle(obj, isolate()); previous_allocation_obj_ = handle(obj, isolate());
...@@ -1159,5 +1234,9 @@ HeapObject Deserializer::Allocate(SnapshotSpace space, int size, ...@@ -1159,5 +1234,9 @@ HeapObject Deserializer::Allocate(SnapshotSpace space, int size,
return obj; return obj;
} }
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) Deserializer<Isolate>;
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Deserializer<LocalIsolate>;
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -8,7 +8,10 @@ ...@@ -8,7 +8,10 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "src/base/macros.h"
#include "src/base/optional.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/execution/local-isolate.h"
#include "src/objects/allocation-site.h" #include "src/objects/allocation-site.h"
#include "src/objects/api-callbacks.h" #include "src/objects/api-callbacks.h"
#include "src/objects/backing-store.h" #include "src/objects/backing-store.h"
...@@ -39,7 +42,8 @@ class Object; ...@@ -39,7 +42,8 @@ class Object;
#endif #endif
// A Deserializer reads a snapshot and reconstructs the Object graph it defines. // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { template <typename IsolateT>
class Deserializer : public SerializerDeserializer {
public: public:
~Deserializer() override; ~Deserializer() override;
Deserializer(const Deserializer&) = delete; Deserializer(const Deserializer&) = delete;
...@@ -49,7 +53,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -49,7 +53,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
protected: protected:
// Create a deserializer from a snapshot byte source. // Create a deserializer from a snapshot byte source.
Deserializer(Isolate* isolate, base::Vector<const byte> payload, Deserializer(IsolateT* isolate, base::Vector<const byte> payload,
uint32_t magic_number, bool deserializing_user_code, uint32_t magic_number, bool deserializing_user_code,
bool can_rehash); bool can_rehash);
...@@ -79,7 +83,9 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -79,7 +83,9 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
CHECK_EQ(new_off_heap_array_buffers().size(), 0); CHECK_EQ(new_off_heap_array_buffers().size(), 0);
} }
Isolate* isolate() const { return isolate_; } IsolateT* isolate() const { return isolate_; }
Isolate* main_thread_isolate() const { return isolate_->AsIsolate(); }
SnapshotByteSource* source() { return &source_; } SnapshotByteSource* source() { return &source_; }
const std::vector<Handle<AllocationSite>>& new_allocation_sites() const { const std::vector<Handle<AllocationSite>>& new_allocation_sites() const {
...@@ -120,7 +126,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -120,7 +126,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
Handle<HeapObject> ReadObject(); Handle<HeapObject> ReadObject();
private: private:
class RelocInfoVisitor; friend class DeserializerRelocInfoVisitor;
// A circular queue of hot objects. This is added to in the same order as in // A circular queue of hot objects. This is added to in the same order as in
// Serializer::HotObjectsList, but this stores the objects as a vector of // Serializer::HotObjectsList, but this stores the objects as a vector of
// existing handles. This allows us to add Handles to the queue without having // existing handles. This allows us to add Handles to the queue without having
...@@ -196,7 +202,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -196,7 +202,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
AllocationAlignment alignment); AllocationAlignment alignment);
// Cached current isolate. // Cached current isolate.
Isolate* isolate_; IsolateT* isolate_;
// Objects from the attached object descriptions in the serialized user code. // Objects from the attached object descriptions in the serialized user code.
std::vector<Handle<HeapObject>> attached_objects_; std::vector<Handle<HeapObject>> attached_objects_;
...@@ -253,19 +259,27 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -253,19 +259,27 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
#endif // DEBUG #endif // DEBUG
}; };
extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
Deserializer<Isolate>;
extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
Deserializer<LocalIsolate>;
// Used to insert a deserialized internalized string into the string table. // Used to insert a deserialized internalized string into the string table.
class StringTableInsertionKey final : public StringTableKey { class StringTableInsertionKey final : public StringTableKey {
public: public:
explicit StringTableInsertionKey(Handle<String> string); explicit StringTableInsertionKey(Isolate* isolate, Handle<String> string);
explicit StringTableInsertionKey(LocalIsolate* isolate,
Handle<String> string);
bool IsMatch(Isolate* isolate, String string); template <typename IsolateT>
bool IsMatch(IsolateT* isolate, String string);
V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate); template <typename IsolateT>
V8_WARN_UNUSED_RESULT Handle<String> AsHandle(LocalIsolate* isolate); V8_WARN_UNUSED_RESULT Handle<String> AsHandle(IsolateT* isolate) {
return string_;
}
private: private:
uint32_t ComputeRawHashField(String string);
Handle<String> string_; Handle<String> string_;
DISALLOW_GARBAGE_COLLECTION(no_gc) DISALLOW_GARBAGE_COLLECTION(no_gc)
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/codegen/assembler-inl.h" #include "src/codegen/assembler-inl.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/objects/allocation-site-inl.h" #include "src/objects/allocation-site-inl.h"
#include "src/objects/js-array-buffer-inl.h" #include "src/objects/js-array-buffer-inl.h"
#include "src/objects/objects.h" #include "src/objects/objects.h"
...@@ -34,14 +35,6 @@ ObjectDeserializer::DeserializeSharedFunctionInfo( ...@@ -34,14 +35,6 @@ ObjectDeserializer::DeserializeSharedFunctionInfo(
: MaybeHandle<SharedFunctionInfo>(); : MaybeHandle<SharedFunctionInfo>();
} }
MaybeHandle<SharedFunctionInfo>
ObjectDeserializer::DeserializeSharedFunctionInfoOffThread(
LocalIsolate* isolate, const SerializedCodeData* data,
Handle<String> source) {
// TODO(leszeks): Add LocalHeap support to deserializer
UNREACHABLE();
}
MaybeHandle<HeapObject> ObjectDeserializer::Deserialize() { MaybeHandle<HeapObject> ObjectDeserializer::Deserialize() {
DCHECK(deserializing_user_code()); DCHECK(deserializing_user_code());
HandleScope scope(isolate()); HandleScope scope(isolate());
...@@ -102,5 +95,56 @@ void ObjectDeserializer::LinkAllocationSites() { ...@@ -102,5 +95,56 @@ void ObjectDeserializer::LinkAllocationSites() {
} }
} }
OffThreadObjectDeserializer::OffThreadObjectDeserializer(
LocalIsolate* isolate, const SerializedCodeData* data)
: Deserializer(isolate, data->Payload(), data->GetMagicNumber(), true,
false) {}
MaybeHandle<SharedFunctionInfo>
OffThreadObjectDeserializer::DeserializeSharedFunctionInfo(
LocalIsolate* isolate, const SerializedCodeData* data,
std::vector<Handle<Script>>* deserialized_scripts) {
OffThreadObjectDeserializer d(isolate, data);
// Attach the empty string as the source.
d.AddAttachedObject(isolate->factory()->empty_string());
Handle<HeapObject> result;
if (!d.Deserialize(deserialized_scripts).ToHandle(&result)) {
return MaybeHandle<SharedFunctionInfo>();
}
return Handle<SharedFunctionInfo>::cast(result);
}
MaybeHandle<HeapObject> OffThreadObjectDeserializer::Deserialize(
std::vector<Handle<Script>>* deserialized_scripts) {
DCHECK(deserializing_user_code());
LocalHandleScope scope(isolate());
Handle<HeapObject> result;
{
result = ReadObject();
DeserializeDeferredObjects();
CHECK(new_code_objects().empty());
CHECK(new_allocation_sites().empty());
CHECK(new_maps().empty());
WeakenDescriptorArrays();
}
Rehash();
CHECK(new_off_heap_array_buffers().empty());
// TODO(leszeks): Figure out a better way of dealing with scripts.
CHECK_EQ(new_scripts().size(), 1);
for (Handle<Script> script : new_scripts()) {
// Assign a new script id to avoid collision.
script->set_id(isolate()->GetNextScriptId());
LogScriptEvents(*script);
deserialized_scripts->push_back(
isolate()->heap()->NewPersistentHandle(script));
}
return scope.CloseAndEscape(result);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -14,13 +14,10 @@ class SerializedCodeData; ...@@ -14,13 +14,10 @@ class SerializedCodeData;
class SharedFunctionInfo; class SharedFunctionInfo;
// Deserializes the object graph rooted at a given object. // Deserializes the object graph rooted at a given object.
class ObjectDeserializer final : public Deserializer { class ObjectDeserializer final : public Deserializer<Isolate> {
public: public:
static MaybeHandle<SharedFunctionInfo> DeserializeSharedFunctionInfo( static MaybeHandle<SharedFunctionInfo> DeserializeSharedFunctionInfo(
Isolate* isolate, const SerializedCodeData* data, Handle<String> source); Isolate* isolate, const SerializedCodeData* data, Handle<String> source);
static MaybeHandle<SharedFunctionInfo> DeserializeSharedFunctionInfoOffThread(
LocalIsolate* isolate, const SerializedCodeData* data,
Handle<String> source);
private: private:
explicit ObjectDeserializer(Isolate* isolate, const SerializedCodeData* data); explicit ObjectDeserializer(Isolate* isolate, const SerializedCodeData* data);
...@@ -32,6 +29,22 @@ class ObjectDeserializer final : public Deserializer { ...@@ -32,6 +29,22 @@ class ObjectDeserializer final : public Deserializer {
void CommitPostProcessedObjects(); void CommitPostProcessedObjects();
}; };
// Deserializes the object graph rooted at a given object.
class OffThreadObjectDeserializer final : public Deserializer<LocalIsolate> {
public:
static MaybeHandle<SharedFunctionInfo> DeserializeSharedFunctionInfo(
LocalIsolate* isolate, const SerializedCodeData* data,
std::vector<Handle<Script>>* deserialized_scripts);
private:
explicit OffThreadObjectDeserializer(LocalIsolate* isolate,
const SerializedCodeData* data);
// Deserialize an object graph. Fail gracefully.
MaybeHandle<HeapObject> Deserialize(
std::vector<Handle<Script>>* deserialized_scripts);
};
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -14,7 +14,7 @@ namespace internal { ...@@ -14,7 +14,7 @@ namespace internal {
// Deserializes the read-only blob, creating the read-only roots and the // Deserializes the read-only blob, creating the read-only roots and the
// Read-only object cache used by the other deserializers. // Read-only object cache used by the other deserializers.
class ReadOnlyDeserializer final : public Deserializer { class ReadOnlyDeserializer final : public Deserializer<Isolate> {
public: public:
explicit ReadOnlyDeserializer(Isolate* isolate, const SnapshotData* data, explicit ReadOnlyDeserializer(Isolate* isolate, const SnapshotData* data,
bool can_rehash) bool can_rehash)
......
...@@ -85,7 +85,7 @@ void StartupDeserializer::DeserializeStringTable() { ...@@ -85,7 +85,7 @@ void StartupDeserializer::DeserializeStringTable() {
// TODO(leszeks): Consider pre-sizing the string table. // TODO(leszeks): Consider pre-sizing the string table.
for (int i = 0; i < string_table_size; ++i) { for (int i = 0; i < string_table_size; ++i) {
Handle<String> string = Handle<String>::cast(ReadObject()); Handle<String> string = Handle<String>::cast(ReadObject());
StringTableInsertionKey key(string); StringTableInsertionKey key(isolate(), string);
Handle<String> result = Handle<String> result =
isolate()->string_table()->LookupKey(isolate(), &key); isolate()->string_table()->LookupKey(isolate(), &key);
USE(result); USE(result);
......
...@@ -13,7 +13,7 @@ namespace v8 { ...@@ -13,7 +13,7 @@ namespace v8 {
namespace internal { namespace internal {
// Initializes an isolate with context-independent data from a given snapshot. // Initializes an isolate with context-independent data from a given snapshot.
class StartupDeserializer final : public Deserializer { class StartupDeserializer final : public Deserializer<Isolate> {
public: public:
explicit StartupDeserializer(Isolate* isolate, explicit StartupDeserializer(Isolate* isolate,
const SnapshotData* startup_data, const SnapshotData* startup_data,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment