Commit c212d10d authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[serializer] Introduce HandleScopes for object contents

Create a HandleScope when serializing an object's contents, to reduce
the number of live handles during serialization. There's only a couple
of cases where these handles have to outlive the serialized contents,
and for these cases we introduce GlobalHandleVector or similar manual
strong root mechanisms.

In particular, backrefs don't actually need to exist as a handle vector
(the object addresses are already referred to by the reference map's
IdentityMap), except for DCHECKs, so this becomes a DEBUG-only global
handle vector.

To support this manual strong-rooting, the HotObjectList is split up
into a strong-rooted find-only class in Serializer, and a Handle
vector in Deserializer.

Bug: chromium:1075999
Change-Id: I586eeeb543e3f6c934c168961b068f2c34e72456
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2449980Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70411}
parent 4ddb0347
...@@ -371,6 +371,18 @@ class Recorder; ...@@ -371,6 +371,18 @@ class Recorder;
} \ } \
} while (false) } while (false)
#define WHILE_WITH_HANDLE_SCOPE(isolate, limit_check, body) \
do { \
Isolate* for_with_handle_isolate = isolate; \
while (limit_check) { \
HandleScope loop_scope(for_with_handle_isolate); \
for (int for_with_handle_it = 0; \
limit_check && for_with_handle_it < 1024; ++for_with_handle_it) { \
body \
} \
} \
} while (false)
#define FIELD_ACCESSOR(type, name) \ #define FIELD_ACCESSOR(type, name) \
inline void set_##name(type v) { name##_ = v; } \ inline void set_##name(type v) { name##_ = v; } \
inline type name() const { return name##_; } inline type name() const { return name##_; }
......
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "include/v8.h"
#include "include/v8-profiler.h" #include "include/v8-profiler.h"
#include "include/v8.h"
#include "src/utils/utils.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/heap/heap.h"
#include "src/objects/objects.h" #include "src/objects/objects.h"
#include "src/utils/utils.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -323,6 +323,52 @@ class EternalHandles final { ...@@ -323,6 +323,52 @@ class EternalHandles final {
DISALLOW_COPY_AND_ASSIGN(EternalHandles); DISALLOW_COPY_AND_ASSIGN(EternalHandles);
}; };
// A vector of global Handles which automatically manages the backing of those
// Handles as a vector of strong-rooted addresses. Handles returned by the
// vector are valid as long as they are present in the vector.
template <typename T>
class GlobalHandleVector {
public:
class Iterator {
public:
explicit Iterator(
std::vector<Address, StrongRootBlockAllocator>::iterator it)
: it_(it) {}
Iterator& operator++() {
++it_;
return *this;
}
Handle<T> operator*() { return Handle<T>(&*it_); }
bool operator!=(Iterator& that) { return it_ != that.it_; }
private:
std::vector<Address, StrongRootBlockAllocator>::iterator it_;
};
explicit GlobalHandleVector(Heap* heap)
: locations_(StrongRootBlockAllocator(heap)) {}
Handle<T> operator[](size_t i) { return Handle<T>(&locations_[i]); }
size_t size() const { return locations_.size(); }
bool empty() const { return locations_.empty(); }
void Push(T val) { locations_.push_back(val.ptr()); }
// Handles into the GlobalHandleVector become invalid when they are removed,
// so "pop" returns a raw object rather than a handle.
T Pop() {
T obj = T::cast(Object(locations_.back()));
locations_.pop_back();
return obj;
}
Iterator begin() { return Iterator(locations_.begin()); }
Iterator end() { return Iterator(locations_.end()); }
private:
std::vector<Address, StrongRootBlockAllocator> locations_;
};
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -248,7 +248,7 @@ class HandleScope { ...@@ -248,7 +248,7 @@ class HandleScope {
// Limit for number of handles with --check-handle-count. This is // Limit for number of handles with --check-handle-count. This is
// large enough to compile natives and pass unit tests with some // large enough to compile natives and pass unit tests with some
// slack for future changes to natives. // slack for future changes to natives.
static const int kCheckHandleThreshold = 42 * 1024; static const int kCheckHandleThreshold = 30 * 1024;
private: private:
Isolate* isolate_; Isolate* isolate_;
......
...@@ -6746,5 +6746,41 @@ void Heap::IncrementObjectCounters() { ...@@ -6746,5 +6746,41 @@ void Heap::IncrementObjectCounters() {
} }
#endif // DEBUG #endif // DEBUG
// StrongRootBlocks are allocated as a block of addresses, prefixed with a
// StrongRootsEntry pointer:
//
// | StrongRootsEntry*
// | Address 1
// | ...
// | Address N
//
// The allocate method registers the range "Address 1" to "Address N" with the
// heap as a strong root array, saves that entry in StrongRootsEntry*, and
// returns a pointer to Address 1.
Address* StrongRootBlockAllocator::allocate(size_t n) {
void* block = malloc(sizeof(StrongRootsEntry*) + n * sizeof(Address));
StrongRootsEntry** header = reinterpret_cast<StrongRootsEntry**>(block);
Address* ret = reinterpret_cast<Address*>(reinterpret_cast<char*>(block) +
sizeof(StrongRootsEntry*));
memset(ret, kNullAddress, n * sizeof(Address));
*header =
heap_->RegisterStrongRoots(FullObjectSlot(ret), FullObjectSlot(ret + n));
return ret;
}
void StrongRootBlockAllocator::deallocate(Address* p, size_t n) noexcept {
// The allocate method returns a pointer to Address 1, so the deallocate
// method has to offset that pointer back by sizeof(StrongRootsEntry*).
void* block = reinterpret_cast<char*>(p) - sizeof(StrongRootsEntry*);
StrongRootsEntry** header = reinterpret_cast<StrongRootsEntry**>(block);
heap_->UnregisterStrongRoots(*header);
free(block);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -2653,6 +2653,32 @@ T ForwardingAddress(T heap_obj) { ...@@ -2653,6 +2653,32 @@ T ForwardingAddress(T heap_obj) {
} }
} }
// Address block allocator compatible with standard containers which registers
// its allocated range as strong roots.
class StrongRootBlockAllocator {
public:
using pointer = Address*;
using const_pointer = const Address*;
using reference = Address&;
using const_reference = const Address&;
using value_type = Address;
using size_type = size_t;
using difference_type = ptrdiff_t;
template <class U>
struct rebind {
STATIC_ASSERT((std::is_same<Address, U>::value));
using other = StrongRootBlockAllocator;
};
explicit StrongRootBlockAllocator(Heap* heap) : heap_(heap) {}
Address* allocate(size_t n);
void deallocate(Address* p, size_t n) noexcept;
private:
Heap* heap_;
};
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -195,8 +195,7 @@ bool ContextSerializer::ShouldBeInTheStartupObjectCache(HeapObject o) { ...@@ -195,8 +195,7 @@ bool ContextSerializer::ShouldBeInTheStartupObjectCache(HeapObject o) {
return o.IsName() || o.IsSharedFunctionInfo() || o.IsHeapNumber() || return o.IsName() || o.IsSharedFunctionInfo() || o.IsHeapNumber() ||
o.IsCode() || o.IsScopeInfo() || o.IsAccessorInfo() || o.IsCode() || o.IsScopeInfo() || o.IsAccessorInfo() ||
o.IsTemplateInfo() || o.IsClassPositions() || o.IsTemplateInfo() || o.IsClassPositions() ||
o.map() == ReadOnlyRoots(startup_serializer_->isolate()) o.map() == ReadOnlyRoots(isolate()).fixed_cow_array_map();
.fixed_cow_array_map();
} }
namespace { namespace {
......
...@@ -1124,11 +1124,11 @@ HeapObject Deserializer::Allocate(SnapshotSpace space, int size, ...@@ -1124,11 +1124,11 @@ HeapObject Deserializer::Allocate(SnapshotSpace space, int size,
} }
#endif #endif
HeapObject obj = isolate_->heap()->AllocateRawWith<Heap::kRetryOrFail>( HeapObject obj = isolate()->heap()->AllocateRawWith<Heap::kRetryOrFail>(
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());
previous_allocation_size_ = size; previous_allocation_size_ = size;
#endif #endif
......
...@@ -130,6 +130,34 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -130,6 +130,34 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
private: private:
class RelocInfoVisitor; class RelocInfoVisitor;
// 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
// existing handles. This allows us to add Handles to the queue without having
// to create new handles. Note that this depends on those Handles staying
// valid as long as the HotObjectsList is alive.
class HotObjectsList {
public:
HotObjectsList() = default;
void Add(Handle<HeapObject> object) {
circular_queue_[index_] = object;
index_ = (index_ + 1) & kSizeMask;
}
Handle<HeapObject> Get(int index) {
DCHECK(!circular_queue_[index].is_null());
return circular_queue_[index];
}
private:
static const int kSize = kHotObjectCount;
static const int kSizeMask = kSize - 1;
STATIC_ASSERT(base::bits::IsPowerOfTwo(kSize));
Handle<HeapObject> circular_queue_[kSize];
int index_ = 0;
DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
};
void VisitRootPointers(Root root, const char* description, void VisitRootPointers(Root root, const char* description,
FullObjectSlot start, FullObjectSlot end) override; FullObjectSlot start, FullObjectSlot end) override;
...@@ -184,6 +212,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { ...@@ -184,6 +212,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
SnapshotByteSource source_; SnapshotByteSource source_;
uint32_t magic_number_; uint32_t magic_number_;
HotObjectsList hot_objects_;
std::vector<Handle<Map>> new_maps_; std::vector<Handle<Map>> new_maps_;
std::vector<Handle<AllocationSite>> new_allocation_sites_; std::vector<Handle<AllocationSite>> new_allocation_sites_;
std::vector<Handle<Code>> new_code_objects_; std::vector<Handle<Code>> new_code_objects_;
......
...@@ -39,22 +39,17 @@ bool SerializerDeserializer::CanBeDeferred(HeapObject o) { ...@@ -39,22 +39,17 @@ bool SerializerDeserializer::CanBeDeferred(HeapObject o) {
return !o.IsMap() && !o.IsInternalizedString(); return !o.IsMap() && !o.IsInternalizedString();
} }
void SerializerDeserializer::RestoreExternalReferenceRedirectors( void SerializerDeserializer::RestoreExternalReferenceRedirector(
Isolate* isolate, const std::vector<Handle<AccessorInfo>>& accessor_infos) { Isolate* isolate, Handle<AccessorInfo> accessor_info) {
// Restore wiped accessor infos. // Restore wiped accessor infos.
for (Handle<AccessorInfo> info : accessor_infos) { Foreign::cast(accessor_info->js_getter())
Foreign::cast(info->js_getter()) .set_foreign_address(isolate, accessor_info->redirected_getter());
.set_foreign_address(isolate, info->redirected_getter());
}
} }
void SerializerDeserializer::RestoreExternalReferenceRedirectors( void SerializerDeserializer::RestoreExternalReferenceRedirector(
Isolate* isolate, Isolate* isolate, Handle<CallHandlerInfo> call_handler_info) {
const std::vector<Handle<CallHandlerInfo>>& call_handler_infos) { Foreign::cast(call_handler_info->js_callback())
for (Handle<CallHandlerInfo> info : call_handler_infos) { .set_foreign_address(isolate, call_handler_info->redirected_callback());
Foreign::cast(info->js_callback())
.set_foreign_address(isolate, info->redirected_callback());
}
} }
} // namespace internal } // namespace internal
......
...@@ -23,51 +23,12 @@ class SerializerDeserializer : public RootVisitor { ...@@ -23,51 +23,12 @@ class SerializerDeserializer : public RootVisitor {
static void Iterate(Isolate* isolate, RootVisitor* visitor); static void Iterate(Isolate* isolate, RootVisitor* visitor);
protected: protected:
class HotObjectsList {
public:
HotObjectsList() = default;
void Add(Handle<HeapObject> object) {
circular_queue_[index_] = object;
index_ = (index_ + 1) & kSizeMask;
}
Handle<HeapObject> Get(int index) {
DCHECK(!circular_queue_[index].is_null());
return circular_queue_[index];
}
static const int kNotFound = -1;
int Find(HeapObject object) {
DCHECK(!AllowGarbageCollection::IsAllowed());
for (int i = 0; i < kSize; i++) {
if (!circular_queue_[i].is_null() && *circular_queue_[i] == object) {
return i;
}
}
return kNotFound;
}
static const int kSize = 8;
private:
STATIC_ASSERT(base::bits::IsPowerOfTwo(kSize));
static const int kSizeMask = kSize - 1;
Handle<HeapObject> circular_queue_[kSize];
int index_ = 0;
DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
};
static bool CanBeDeferred(HeapObject o); static bool CanBeDeferred(HeapObject o);
void RestoreExternalReferenceRedirectors( void RestoreExternalReferenceRedirector(Isolate* isolate,
Isolate* isolate, Handle<AccessorInfo> accessor_info);
const std::vector<Handle<AccessorInfo>>& accessor_infos); void RestoreExternalReferenceRedirector(
void RestoreExternalReferenceRedirectors( Isolate* isolate, Handle<CallHandlerInfo> call_handler_info);
Isolate* isolate,
const std::vector<Handle<CallHandlerInfo>>& call_handler_infos);
// clang-format off // clang-format off
#define UNUSED_SERIALIZER_BYTE_CODES(V) \ #define UNUSED_SERIALIZER_BYTE_CODES(V) \
...@@ -116,7 +77,6 @@ class SerializerDeserializer : public RootVisitor { ...@@ -116,7 +77,6 @@ class SerializerDeserializer : public RootVisitor {
// 8 hot (recently seen or back-referenced) objects with optional skip. // 8 hot (recently seen or back-referenced) objects with optional skip.
static const int kHotObjectCount = 8; static const int kHotObjectCount = 8;
STATIC_ASSERT(kHotObjectCount == HotObjectsList::kSize);
enum Bytecode : byte { enum Bytecode : byte {
// //
...@@ -298,9 +258,6 @@ class SerializerDeserializer : public RootVisitor { ...@@ -298,9 +258,6 @@ class SerializerDeserializer : public RootVisitor {
// This backing store reference value represents nullptr values during // This backing store reference value represents nullptr values during
// serialization/deserialization. // serialization/deserialization.
static const uint32_t kNullRefSentinel = 0; static const uint32_t kNullRefSentinel = 0;
// ---------- member variable ----------
HotObjectsList hot_objects_;
}; };
} // namespace internal } // namespace internal
......
This diff is collapsed.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/codegen/external-reference-encoder.h" #include "src/codegen/external-reference-encoder.h"
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/handles/global-handles.h"
#include "src/logging/log.h" #include "src/logging/log.h"
#include "src/objects/objects.h" #include "src/objects/objects.h"
#include "src/snapshot/embedded/embedded-data.h" #include "src/snapshot/embedded/embedded-data.h"
...@@ -250,7 +251,7 @@ class Serializer : public SerializerDeserializer { ...@@ -250,7 +251,7 @@ class Serializer : public SerializerDeserializer {
void QueueDeferredObject(Handle<HeapObject> obj) { void QueueDeferredObject(Handle<HeapObject> obj) {
DCHECK_NULL(reference_map_.LookupReference(obj)); DCHECK_NULL(reference_map_.LookupReference(obj));
deferred_objects_.push_back(obj); deferred_objects_.Push(*obj);
} }
// Register that the the given object shouldn't be immediately serialized, but // Register that the the given object shouldn't be immediately serialized, but
...@@ -266,8 +267,8 @@ class Serializer : public SerializerDeserializer { ...@@ -266,8 +267,8 @@ class Serializer : public SerializerDeserializer {
void CountAllocation(Map map, int size, SnapshotSpace space); void CountAllocation(Map map, int size, SnapshotSpace space);
#ifdef DEBUG #ifdef DEBUG
void PushStack(Handle<HeapObject> o) { stack_.push_back(o); } void PushStack(Handle<HeapObject> o) { stack_.Push(*o); }
void PopStack() { stack_.pop_back(); } void PopStack() { stack_.Pop(); }
void PrintStack(); void PrintStack();
void PrintStack(std::ostream&); void PrintStack(std::ostream&);
#endif // DEBUG #endif // DEBUG
...@@ -284,21 +285,63 @@ class Serializer : public SerializerDeserializer { ...@@ -284,21 +285,63 @@ class Serializer : public SerializerDeserializer {
return (flags_ & Snapshot::kAllowActiveIsolateForTesting) != 0; return (flags_ & Snapshot::kAllowActiveIsolateForTesting) != 0;
} }
std::vector<Handle<HeapObject>> back_refs_;
private: private:
// A circular queue of hot objects. This is added to in the same order as in
// Deserializer::HotObjectsList, but this stores the objects as an array of
// raw addresses that are considered strong roots. This allows objects to be
// added to the list without having to extend their handle's lifetime.
//
// We should never allow this class to return Handles to objects in the queue,
// as the object in the queue may change if kSize other objects are added to
// the queue during that Handle's lifetime.
class HotObjectsList {
public:
explicit HotObjectsList(Heap* heap);
~HotObjectsList();
void Add(HeapObject object) {
circular_queue_[index_] = object.ptr();
index_ = (index_ + 1) & kSizeMask;
}
static const int kNotFound = -1;
int Find(HeapObject object) {
DCHECK(!AllowGarbageCollection::IsAllowed());
for (int i = 0; i < kSize; i++) {
if (circular_queue_[i] == object.ptr()) {
return i;
}
}
return kNotFound;
}
private:
static const int kSize = kHotObjectCount;
static const int kSizeMask = kSize - 1;
STATIC_ASSERT(base::bits::IsPowerOfTwo(kSize));
Heap* heap_;
StrongRootsEntry* strong_roots_entry_;
Address circular_queue_[kSize] = {kNullAddress};
int index_ = 0;
DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
};
// Disallow GC during serialization. // Disallow GC during serialization.
// TODO(leszeks, v8:10815): Remove this constraint. // TODO(leszeks, v8:10815): Remove this constraint.
DISALLOW_HEAP_ALLOCATION(no_gc) DISALLOW_HEAP_ALLOCATION(no_gc)
Isolate* isolate_; Isolate* isolate_;
HotObjectsList hot_objects_;
SerializerReferenceMap reference_map_; SerializerReferenceMap reference_map_;
ExternalReferenceEncoder external_reference_encoder_; ExternalReferenceEncoder external_reference_encoder_;
RootIndexMap root_index_map_; RootIndexMap root_index_map_;
std::unique_ptr<CodeAddressMap> code_address_map_; std::unique_ptr<CodeAddressMap> code_address_map_;
std::vector<byte> code_buffer_; std::vector<byte> code_buffer_;
std::vector<Handle<HeapObject>> GlobalHandleVector<HeapObject>
deferred_objects_; // To handle stack overflow. deferred_objects_; // To handle stack overflow.
int num_back_refs_ = 0;
// Objects which have started being serialized, but haven't yet been allocated // Objects which have started being serialized, but haven't yet been allocated
// with the allocator, are considered "pending". References to them don't have // with the allocator, are considered "pending". References to them don't have
...@@ -334,7 +377,8 @@ class Serializer : public SerializerDeserializer { ...@@ -334,7 +377,8 @@ class Serializer : public SerializerDeserializer {
#endif // OBJECT_PRINT #endif // OBJECT_PRINT
#ifdef DEBUG #ifdef DEBUG
std::vector<Handle<HeapObject>> stack_; GlobalHandleVector<HeapObject> back_refs_;
GlobalHandleVector<HeapObject> stack_;
#endif // DEBUG #endif // DEBUG
DISALLOW_COPY_AND_ASSIGN(Serializer); DISALLOW_COPY_AND_ASSIGN(Serializer);
...@@ -346,7 +390,8 @@ class Serializer::ObjectSerializer : public ObjectVisitor { ...@@ -346,7 +390,8 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
public: public:
ObjectSerializer(Serializer* serializer, Handle<HeapObject> obj, ObjectSerializer(Serializer* serializer, Handle<HeapObject> obj,
SnapshotByteSink* sink) SnapshotByteSink* sink)
: serializer_(serializer), : isolate_(serializer->isolate()),
serializer_(serializer),
object_(obj), object_(obj),
sink_(sink), sink_(sink),
bytes_processed_so_far_(0) { bytes_processed_so_far_(0) {
...@@ -375,6 +420,8 @@ class Serializer::ObjectSerializer : public ObjectVisitor { ...@@ -375,6 +420,8 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
void VisitRuntimeEntry(Code host, RelocInfo* reloc) override; void VisitRuntimeEntry(Code host, RelocInfo* reloc) override;
void VisitOffHeapTarget(Code host, RelocInfo* target) override; void VisitOffHeapTarget(Code host, RelocInfo* target) override;
Isolate* isolate() { return isolate_; }
private: private:
class RelocInfoObjectPreSerializer; class RelocInfoObjectPreSerializer;
...@@ -393,6 +440,7 @@ class Serializer::ObjectSerializer : public ObjectVisitor { ...@@ -393,6 +440,7 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
void SerializeExternalString(); void SerializeExternalString();
void SerializeExternalStringAsSequentialString(); void SerializeExternalStringAsSequentialString();
Isolate* isolate_;
Serializer* serializer_; Serializer* serializer_;
Handle<HeapObject> object_; Handle<HeapObject> object_;
SnapshotByteSink* sink_; SnapshotByteSink* sink_;
......
...@@ -37,8 +37,12 @@ void StartupDeserializer::DeserializeIntoIsolate() { ...@@ -37,8 +37,12 @@ void StartupDeserializer::DeserializeIntoIsolate() {
isolate()->heap()->IterateWeakRoots( isolate()->heap()->IterateWeakRoots(
this, base::EnumSet<SkipRoot>{SkipRoot::kUnserializable}); this, base::EnumSet<SkipRoot>{SkipRoot::kUnserializable});
DeserializeDeferredObjects(); DeserializeDeferredObjects();
RestoreExternalReferenceRedirectors(isolate(), accessor_infos()); for (Handle<AccessorInfo> info : accessor_infos()) {
RestoreExternalReferenceRedirectors(isolate(), call_handler_infos()); RestoreExternalReferenceRedirector(isolate(), info);
}
for (Handle<CallHandlerInfo> info : call_handler_infos()) {
RestoreExternalReferenceRedirector(isolate(), info);
}
// Flush the instruction cache for the entire code-space. Must happen after // Flush the instruction cache for the entire code-space. Must happen after
// builtins deserialization. // builtins deserialization.
......
...@@ -66,13 +66,19 @@ StartupSerializer::StartupSerializer(Isolate* isolate, ...@@ -66,13 +66,19 @@ StartupSerializer::StartupSerializer(Isolate* isolate,
Snapshot::SerializerFlags flags, Snapshot::SerializerFlags flags,
ReadOnlySerializer* read_only_serializer) ReadOnlySerializer* read_only_serializer)
: RootsSerializer(isolate, flags, RootIndex::kFirstStrongRoot), : RootsSerializer(isolate, flags, RootIndex::kFirstStrongRoot),
read_only_serializer_(read_only_serializer) { read_only_serializer_(read_only_serializer),
accessor_infos_(isolate->heap()),
call_handler_infos_(isolate->heap()) {
InitializeCodeAddressMap(); InitializeCodeAddressMap();
} }
StartupSerializer::~StartupSerializer() { StartupSerializer::~StartupSerializer() {
RestoreExternalReferenceRedirectors(isolate(), accessor_infos_); for (Handle<AccessorInfo> info : accessor_infos_) {
RestoreExternalReferenceRedirectors(isolate(), call_handler_infos_); RestoreExternalReferenceRedirector(isolate(), info);
}
for (Handle<CallHandlerInfo> info : call_handler_infos_) {
RestoreExternalReferenceRedirector(isolate(), info);
}
OutputStatistics("StartupSerializer"); OutputStatistics("StartupSerializer");
} }
...@@ -144,14 +150,14 @@ void StartupSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -144,14 +150,14 @@ void StartupSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
Foreign::cast(info->getter()).foreign_address(isolate()); Foreign::cast(info->getter()).foreign_address(isolate());
Foreign::cast(info->js_getter()) Foreign::cast(info->js_getter())
.set_foreign_address(isolate(), original_address); .set_foreign_address(isolate(), original_address);
accessor_infos_.push_back(info); accessor_infos_.Push(*info);
} else if (use_simulator && obj->IsCallHandlerInfo()) { } else if (use_simulator && obj->IsCallHandlerInfo()) {
Handle<CallHandlerInfo> info = Handle<CallHandlerInfo>::cast(obj); Handle<CallHandlerInfo> info = Handle<CallHandlerInfo>::cast(obj);
Address original_address = Address original_address =
Foreign::cast(info->callback()).foreign_address(isolate()); Foreign::cast(info->callback()).foreign_address(isolate());
Foreign::cast(info->js_callback()) Foreign::cast(info->js_callback())
.set_foreign_address(isolate(), original_address); .set_foreign_address(isolate(), original_address);
call_handler_infos_.push_back(info); call_handler_infos_.Push(*info);
} else if (obj->IsScript() && Handle<Script>::cast(obj)->IsUserJavaScript()) { } else if (obj->IsScript() && Handle<Script>::cast(obj)->IsUserJavaScript()) {
Handle<Script>::cast(obj)->set_context_data( Handle<Script>::cast(obj)->set_context_data(
ReadOnlyRoots(isolate()).uninitialized_symbol()); ReadOnlyRoots(isolate()).uninitialized_symbol());
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <unordered_set> #include <unordered_set>
#include "src/handles/global-handles.h"
#include "src/snapshot/roots-serializer.h" #include "src/snapshot/roots-serializer.h"
namespace v8 { namespace v8 {
...@@ -51,8 +52,8 @@ class V8_EXPORT_PRIVATE StartupSerializer : public RootsSerializer { ...@@ -51,8 +52,8 @@ class V8_EXPORT_PRIVATE StartupSerializer : public RootsSerializer {
void SerializeStringTable(StringTable* string_table); void SerializeStringTable(StringTable* string_table);
ReadOnlySerializer* read_only_serializer_; ReadOnlySerializer* read_only_serializer_;
std::vector<Handle<AccessorInfo>> accessor_infos_; GlobalHandleVector<AccessorInfo> accessor_infos_;
std::vector<Handle<CallHandlerInfo>> call_handler_infos_; GlobalHandleVector<CallHandlerInfo> call_handler_infos_;
DISALLOW_COPY_AND_ASSIGN(StartupSerializer); DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
}; };
......
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