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

Reland "[offthread] Template deserializer on Isolate"

This is a reland of e24fa913
It fixes the heap verification errors by going back to using MakeThin
instead of manually creating a filler (that then makes the verifier
think that this was array left-trimming).

Original change's description:
> [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/+/2562254
> Reviewed-by: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
> Commit-Queue: Leszek Swirski <leszeks@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#75834}

Bug: chromium:1075999
Change-Id: I1d81fad2550a2a9f04dd0f9d8e66422d28faf378
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3043960Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75918}
parent bf83100b
...@@ -1766,6 +1766,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { ...@@ -1766,6 +1766,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,
...@@ -2114,6 +2109,12 @@ class Heap { ...@@ -2114,6 +2109,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
...@@ -2536,6 +2537,7 @@ class Heap { ...@@ -2536,6 +2537,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.
...@@ -2589,8 +2591,6 @@ class V8_NODISCARD AlwaysAllocateScope { ...@@ -2589,8 +2591,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,
......
This diff is collapsed.
...@@ -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