Commit 451854fa authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

Revert "[snapshot] Expose the serializer through %SerializeDeserializeNow"

This reverts commit ad5b005e.

Reason for revert: https://ci.chromium.org/p/v8/builders/ci/V8%20Linux%20-%20shared/36070?

Original change's description:
> [snapshot] Expose the serializer through %SerializeDeserializeNow
> 
> ... in order to exercise the snapshot/ component from mjsunit tests
> and fuzzers.
> 
> * Since the serializer and deserializer can now be called at any time
> instead of only in a tightly controlled environment, several
> assumptions (such as an empty execution stack, no microtasks, no
> handles) no longer hold and had to be made configurable through
> SerializerFlags.
> 
> * Root iteration now skips more root categories which were previously
> guaranteed to be empty (e.g. the stack, microtask queue, handles).
> 
> * The %SerializeDeserializeNow runtime function triggers
> serialization, deserialization, and heap verification on the current
> isolate and native context.
> 
> Support is not yet complete and will be extended in future work. Once
> all mjsunit tests successfully run, we can add a new test mode to
> stress serialization.
> 
> Bug: v8:10416
> Change-Id: Ie7ff441a761257dd7f256d0a33e73227850074ac
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2159495
> Commit-Queue: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Dan Elphick <delphick@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#67423}

TBR=ulan@chromium.org,jgruber@chromium.org,delphick@chromium.org

Change-Id: Ie30b94c9ec6e4463bed6cc87dd6525f469fdf84a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:10416
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2170089Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67424}
parent ad5b005e
...@@ -4456,6 +4456,11 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -4456,6 +4456,11 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
isolate_->bootstrapper()->Iterate(v); isolate_->bootstrapper()->Iterate(v);
v->Synchronize(VisitorSynchronization::kBootstrapper); v->Synchronize(VisitorSynchronization::kBootstrapper);
if (mode != VISIT_ONLY_STRONG_IGNORE_STACK) {
isolate_->Iterate(v);
isolate_->global_handles()->IterateStrongStackRoots(v);
v->Synchronize(VisitorSynchronization::kTop);
}
Relocatable::Iterate(isolate_, v); Relocatable::Iterate(isolate_, v);
v->Synchronize(VisitorSynchronization::kRelocatable); v->Synchronize(VisitorSynchronization::kRelocatable);
isolate_->debug()->Iterate(v); isolate_->debug()->Iterate(v);
...@@ -4464,6 +4469,22 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -4464,6 +4469,22 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
isolate_->compilation_cache()->Iterate(v); isolate_->compilation_cache()->Iterate(v);
v->Synchronize(VisitorSynchronization::kCompilationCache); v->Synchronize(VisitorSynchronization::kCompilationCache);
// Iterate over local handles in handle scopes.
FixStaleLeftTrimmedHandlesVisitor left_trim_visitor(this);
isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor);
isolate_->handle_scope_implementer()->Iterate(v);
if (FLAG_local_heaps) {
safepoint_->Iterate(&left_trim_visitor);
safepoint_->Iterate(v);
isolate_->persistent_handles_list()->Iterate(&left_trim_visitor);
isolate_->persistent_handles_list()->Iterate(v);
}
isolate_->IterateDeferredHandles(&left_trim_visitor);
isolate_->IterateDeferredHandles(v);
v->Synchronize(VisitorSynchronization::kHandleScope);
// Iterate over the builtin code objects in the heap. Note that it is not // Iterate over the builtin code objects in the heap. Note that it is not
// necessary to iterate over code objects on scavenge collections. // necessary to iterate over code objects on scavenge collections.
if (!isMinorGC) { if (!isMinorGC) {
...@@ -4495,6 +4516,17 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -4495,6 +4516,17 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
} }
v->Synchronize(VisitorSynchronization::kGlobalHandles); v->Synchronize(VisitorSynchronization::kGlobalHandles);
// Iterate over eternal handles. Eternal handles are not iterated by the
// serializer. Values referenced by eternal handles need to be added manually.
if (mode != VISIT_FOR_SERIALIZATION) {
if (isMinorGC) {
isolate_->eternal_handles()->IterateYoungRoots(v);
} else {
isolate_->eternal_handles()->IterateAllRoots(v);
}
}
v->Synchronize(VisitorSynchronization::kEternalHandles);
// Iterate over pointers being held by inactive threads. // Iterate over pointers being held by inactive threads.
isolate_->thread_manager()->Iterate(v); isolate_->thread_manager()->Iterate(v);
v->Synchronize(VisitorSynchronization::kThreadManager); v->Synchronize(VisitorSynchronization::kThreadManager);
...@@ -4505,57 +4537,8 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -4505,57 +4537,8 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
} }
v->Synchronize(VisitorSynchronization::kStrongRoots); v->Synchronize(VisitorSynchronization::kStrongRoots);
// Visitors in this block only run when not serializing. These include:
//
// - Thread-local and stack.
// - Handles.
// - Microtasks.
// - The startup object cache.
//
// When creating real startup snapshot, these areas are expected to be empty.
// It is also possible to create a snapshot of a *running* isolate for testing
// purposes. In this case, these areas are likely not empty and will simply be
// skipped.
//
// The general guideline for adding visitors to this section vs. adding them
// above is that non-transient heap state is always visited, transient heap
// state is visited only when not serializing.
if (mode != VISIT_FOR_SERIALIZATION) {
if (mode != VISIT_ONLY_STRONG_IGNORE_STACK) {
isolate_->Iterate(v);
isolate_->global_handles()->IterateStrongStackRoots(v);
v->Synchronize(VisitorSynchronization::kTop);
}
// Iterate over local handles in handle scopes.
FixStaleLeftTrimmedHandlesVisitor left_trim_visitor(this);
isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor);
isolate_->handle_scope_implementer()->Iterate(v);
if (FLAG_local_heaps) {
safepoint_->Iterate(&left_trim_visitor);
safepoint_->Iterate(v);
isolate_->persistent_handles_list()->Iterate(&left_trim_visitor);
isolate_->persistent_handles_list()->Iterate(v);
}
isolate_->IterateDeferredHandles(&left_trim_visitor);
isolate_->IterateDeferredHandles(v);
v->Synchronize(VisitorSynchronization::kHandleScope);
// Iterate over eternal handles. Eternal handles are not iterated by the
// serializer. Values referenced by eternal handles need to be added
// manually.
if (isMinorGC) {
isolate_->eternal_handles()->IterateYoungRoots(v);
} else {
isolate_->eternal_handles()->IterateAllRoots(v);
}
v->Synchronize(VisitorSynchronization::kEternalHandles);
// Iterate over pending Microtasks stored in MicrotaskQueues. // Iterate over pending Microtasks stored in MicrotaskQueues.
MicrotaskQueue* default_microtask_queue = MicrotaskQueue* default_microtask_queue = isolate_->default_microtask_queue();
isolate_->default_microtask_queue();
if (default_microtask_queue) { if (default_microtask_queue) {
MicrotaskQueue* microtask_queue = default_microtask_queue; MicrotaskQueue* microtask_queue = default_microtask_queue;
do { do {
...@@ -4564,8 +4547,8 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -4564,8 +4547,8 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
} while (microtask_queue != default_microtask_queue); } while (microtask_queue != default_microtask_queue);
} }
// Iterate over the startup object cache unless serializing or // Iterate over the startup object cache unless serializing or deserializing.
// deserializing. if (mode != VISIT_FOR_SERIALIZATION) {
SerializerDeserializer::Iterate(isolate_, v); SerializerDeserializer::Iterate(isolate_, v);
v->Synchronize(VisitorSynchronization::kStartupObjectCache); v->Synchronize(VisitorSynchronization::kStartupObjectCache);
} }
......
...@@ -55,20 +55,6 @@ class Bootstrapper final { ...@@ -55,20 +55,6 @@ class Bootstrapper final {
v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer, v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer,
v8::MicrotaskQueue* microtask_queue); v8::MicrotaskQueue* microtask_queue);
// Used for testing context deserialization. No code runs in the generated
// context. It only needs to pass heap verification.
Handle<Context> CreateEnvironmentForTesting() {
MaybeHandle<JSGlobalProxy> no_global_proxy;
v8::Local<v8::ObjectTemplate> no_global_object_template;
ExtensionConfiguration no_extensions;
static constexpr int kDefaultContextIndex = 0;
v8::DeserializeEmbedderFieldsCallback no_callback;
v8::MicrotaskQueue* no_microtask_queue = nullptr;
return CreateEnvironment(no_global_proxy, no_global_object_template,
&no_extensions, kDefaultContextIndex, no_callback,
no_microtask_queue);
}
Handle<JSGlobalProxy> NewRemoteContext( Handle<JSGlobalProxy> NewRemoteContext(
MaybeHandle<JSGlobalProxy> maybe_global_proxy, MaybeHandle<JSGlobalProxy> maybe_global_proxy,
v8::Local<v8::ObjectTemplate> global_object_template); v8::Local<v8::ObjectTemplate> global_object_template);
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "src/objects/js-array-inl.h" #include "src/objects/js-array-inl.h"
#include "src/objects/js-regexp-inl.h" #include "src/objects/js-regexp-inl.h"
#include "src/objects/smi.h" #include "src/objects/smi.h"
#include "src/snapshot/snapshot.h"
#include "src/trap-handler/trap-handler.h" #include "src/trap-handler/trap-handler.h"
#include "src/utils/ostreams.h" #include "src/utils/ostreams.h"
#include "src/wasm/memory-tracing.h" #include "src/wasm/memory-tracing.h"
...@@ -1188,22 +1187,6 @@ RUNTIME_FUNCTION(Runtime_StringIteratorProtector) { ...@@ -1188,22 +1187,6 @@ RUNTIME_FUNCTION(Runtime_StringIteratorProtector) {
Protectors::IsStringIteratorLookupChainIntact(isolate)); Protectors::IsStringIteratorLookupChainIntact(isolate));
} }
// For use by tests and fuzzers. It
//
// 1. serializes a snapshot of the current isolate,
// 2. deserializes the snapshot,
// 3. and runs VerifyHeap on the resulting isolate.
//
// The current isolate should not be modified by this call and can keep running
// once it completes.
RUNTIME_FUNCTION(Runtime_SerializeDeserializeNow) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
Snapshot::SerializeDeserializeAndVerifyForTesting(isolate,
isolate->native_context());
return ReadOnlyRoots(isolate).undefined_value();
}
// Take a compiled wasm module and serialize it into an array buffer, which is // Take a compiled wasm module and serialize it into an array buffer, which is
// then returned. // then returned.
RUNTIME_FUNCTION(Runtime_SerializeWasmModule) { RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
......
...@@ -522,7 +522,6 @@ namespace internal { ...@@ -522,7 +522,6 @@ namespace internal {
F(RedirectToWasmInterpreter, 2, 1) \ F(RedirectToWasmInterpreter, 2, 1) \
F(RunningInSimulator, 0, 1) \ F(RunningInSimulator, 0, 1) \
F(RuntimeEvaluateREPL, 1, 1) \ F(RuntimeEvaluateREPL, 1, 1) \
F(SerializeDeserializeNow, 0, 1) \
F(SerializeWasmModule, 1, 1) \ F(SerializeWasmModule, 1, 1) \
F(SetAllocationTimeout, -1 /* 2 || 3 */, 1) \ F(SetAllocationTimeout, -1 /* 2 || 3 */, 1) \
F(SetForceSlowPath, 1, 1) \ F(SetForceSlowPath, 1, 1) \
......
...@@ -32,8 +32,7 @@ ScriptData::ScriptData(const byte* data, int length) ...@@ -32,8 +32,7 @@ ScriptData::ScriptData(const byte* data, int length)
} }
CodeSerializer::CodeSerializer(Isolate* isolate, uint32_t source_hash) CodeSerializer::CodeSerializer(Isolate* isolate, uint32_t source_hash)
: Serializer(isolate, Snapshot::kDefaultSerializerFlags), : Serializer(isolate), source_hash_(source_hash) {
source_hash_(source_hash) {
allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size); allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size);
} }
......
...@@ -16,10 +16,9 @@ namespace v8 { ...@@ -16,10 +16,9 @@ namespace v8 {
namespace internal { namespace internal {
ContextSerializer::ContextSerializer( ContextSerializer::ContextSerializer(
Isolate* isolate, Snapshot::SerializerFlags flags, Isolate* isolate, StartupSerializer* startup_serializer,
StartupSerializer* startup_serializer,
v8::SerializeEmbedderFieldsCallback callback) v8::SerializeEmbedderFieldsCallback callback)
: Serializer(isolate, flags), : Serializer(isolate),
startup_serializer_(startup_serializer), startup_serializer_(startup_serializer),
serialize_embedder_fields_(callback), serialize_embedder_fields_(callback),
can_be_rehashed_(true) { can_be_rehashed_(true) {
...@@ -47,14 +46,12 @@ void ContextSerializer::Serialize(Context* o, bool include_global_proxy) { ...@@ -47,14 +46,12 @@ void ContextSerializer::Serialize(Context* o, bool include_global_proxy) {
// Reset math random cache to get fresh random numbers. // Reset math random cache to get fresh random numbers.
MathRandom::ResetContext(context_); MathRandom::ResetContext(context_);
MicrotaskQueue* microtask_queue = context_.native_context().microtask_queue();
#ifdef DEBUG #ifdef DEBUG
if (!allow_microtasks_for_testing()) { MicrotaskQueue* microtask_queue = context_.native_context().microtask_queue();
DCHECK_EQ(0, microtask_queue->size()); DCHECK_EQ(0, microtask_queue->size());
DCHECK(!microtask_queue->HasMicrotasksSuppressions()); DCHECK(!microtask_queue->HasMicrotasksSuppressions());
DCHECK_EQ(0, microtask_queue->GetMicrotasksScopeDepth()); DCHECK_EQ(0, microtask_queue->GetMicrotasksScopeDepth());
DCHECK(microtask_queue->DebugMicrotasksScopeDepthIsZero()); DCHECK(microtask_queue->DebugMicrotasksScopeDepthIsZero());
}
#endif #endif
context_.native_context().set_microtask_queue(nullptr); context_.native_context().set_microtask_queue(nullptr);
...@@ -69,9 +66,6 @@ void ContextSerializer::Serialize(Context* o, bool include_global_proxy) { ...@@ -69,9 +66,6 @@ void ContextSerializer::Serialize(Context* o, bool include_global_proxy) {
} }
Pad(); Pad();
// Restore the microtask queue.
context_.native_context().set_microtask_queue(microtask_queue);
} }
void ContextSerializer::SerializeObject(HeapObject obj) { void ContextSerializer::SerializeObject(HeapObject obj) {
......
...@@ -16,8 +16,7 @@ class StartupSerializer; ...@@ -16,8 +16,7 @@ class StartupSerializer;
class V8_EXPORT_PRIVATE ContextSerializer : public Serializer { class V8_EXPORT_PRIVATE ContextSerializer : public Serializer {
public: public:
ContextSerializer(Isolate* isolate, Snapshot::SerializerFlags flags, ContextSerializer(Isolate* isolate, StartupSerializer* startup_serializer,
StartupSerializer* startup_serializer,
v8::SerializeEmbedderFieldsCallback callback); v8::SerializeEmbedderFieldsCallback callback);
~ContextSerializer() override; ~ContextSerializer() override;
......
...@@ -16,9 +16,8 @@ ...@@ -16,9 +16,8 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
ReadOnlySerializer::ReadOnlySerializer(Isolate* isolate, ReadOnlySerializer::ReadOnlySerializer(Isolate* isolate)
Snapshot::SerializerFlags flags) : RootsSerializer(isolate, RootIndex::kFirstReadOnlyRoot) {
: RootsSerializer(isolate, flags, RootIndex::kFirstReadOnlyRoot) {
STATIC_ASSERT(RootIndex::kFirstReadOnlyRoot == RootIndex::kFirstRoot); STATIC_ASSERT(RootIndex::kFirstReadOnlyRoot == RootIndex::kFirstRoot);
allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size); allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size);
} }
...@@ -51,8 +50,7 @@ void ReadOnlySerializer::SerializeReadOnlyRoots() { ...@@ -51,8 +50,7 @@ void ReadOnlySerializer::SerializeReadOnlyRoots() {
// No active threads. // No active threads.
CHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse()); CHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse());
// No active or weak handles. // No active or weak handles.
CHECK_IMPLIES(!allow_open_handles_for_testing(), CHECK(isolate()->handle_scope_implementer()->blocks()->empty());
isolate()->handle_scope_implementer()->blocks()->empty());
ReadOnlyRoots(isolate()).Iterate(this); ReadOnlyRoots(isolate()).Iterate(this);
} }
......
...@@ -17,7 +17,7 @@ class SnapshotByteSink; ...@@ -17,7 +17,7 @@ class SnapshotByteSink;
class V8_EXPORT_PRIVATE ReadOnlySerializer : public RootsSerializer { class V8_EXPORT_PRIVATE ReadOnlySerializer : public RootsSerializer {
public: public:
ReadOnlySerializer(Isolate* isolate, Snapshot::SerializerFlags flags); explicit ReadOnlySerializer(Isolate* isolate);
~ReadOnlySerializer() override; ~ReadOnlySerializer() override;
void SerializeReadOnlyRoots(); void SerializeReadOnlyRoots();
......
...@@ -13,9 +13,8 @@ namespace v8 { ...@@ -13,9 +13,8 @@ namespace v8 {
namespace internal { namespace internal {
RootsSerializer::RootsSerializer(Isolate* isolate, RootsSerializer::RootsSerializer(Isolate* isolate,
Snapshot::SerializerFlags flags,
RootIndex first_root_to_be_serialized) RootIndex first_root_to_be_serialized)
: Serializer(isolate, flags), : Serializer(isolate),
first_root_to_be_serialized_(first_root_to_be_serialized), first_root_to_be_serialized_(first_root_to_be_serialized),
can_be_rehashed_(true) { can_be_rehashed_(true) {
for (size_t i = 0; i < static_cast<size_t>(first_root_to_be_serialized); for (size_t i = 0; i < static_cast<size_t>(first_root_to_be_serialized);
......
...@@ -24,8 +24,7 @@ class RootsSerializer : public Serializer { ...@@ -24,8 +24,7 @@ class RootsSerializer : public Serializer {
public: public:
// The serializer expects that all roots before |first_root_to_be_serialized| // The serializer expects that all roots before |first_root_to_be_serialized|
// are already serialized. // are already serialized.
RootsSerializer(Isolate* isolate, Snapshot::SerializerFlags flags, RootsSerializer(Isolate* isolate, RootIndex first_root_to_be_serialized);
RootIndex first_root_to_be_serialized);
bool can_be_rehashed() const { return can_be_rehashed_; } bool can_be_rehashed() const { return can_be_rehashed_; }
bool root_has_been_serialized(RootIndex root_index) const { bool root_has_been_serialized(RootIndex root_index) const {
......
...@@ -14,15 +14,15 @@ ...@@ -14,15 +14,15 @@
#include "src/objects/map.h" #include "src/objects/map.h"
#include "src/objects/slots-inl.h" #include "src/objects/slots-inl.h"
#include "src/objects/smi.h" #include "src/objects/smi.h"
#include "src/snapshot/snapshot.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
Serializer::Serializer(Isolate* isolate, Snapshot::SerializerFlags flags) Serializer::Serializer(Isolate* isolate)
: isolate_(isolate), : isolate_(isolate),
external_reference_encoder_(isolate), external_reference_encoder_(isolate),
root_index_map_(isolate), root_index_map_(isolate),
flags_(flags),
allocator_(this) { allocator_(this) {
#ifdef OBJECT_PRINT #ifdef OBJECT_PRINT
if (FLAG_serialization_statistics) { if (FLAG_serialization_statistics) {
...@@ -718,53 +718,32 @@ void Serializer::ObjectSerializer::VisitEmbeddedPointer(Code host, ...@@ -718,53 +718,32 @@ void Serializer::ObjectSerializer::VisitEmbeddedPointer(Code host,
bytes_processed_so_far_ += rinfo->target_address_size(); bytes_processed_so_far_ += rinfo->target_address_size();
} }
void Serializer::ObjectSerializer::OutputExternalReference(Address target, void Serializer::ObjectSerializer::VisitExternalReference(Foreign host,
int target_size) { Address* p) {
DCHECK_LE(target_size, sizeof(target)); // Must fit in Address. auto encoded_reference =
ExternalReferenceEncoder::Value encoded_reference; serializer_->EncodeExternalReference(host.foreign_address());
bool encoded_successfully; if (encoded_reference.is_from_api()) {
if (serializer_->allow_unknown_external_references_for_testing()) {
encoded_successfully =
serializer_->TryEncodeExternalReference(target).To(&encoded_reference);
} else {
encoded_reference = serializer_->EncodeExternalReference(target);
encoded_successfully = true;
}
if (!encoded_successfully) {
// In this case the serialized snapshot will not be used in a different
// Isolate and thus the target address will not change between
// serialization and deserialization. We can serialize seen external
// references verbatim.
CHECK(serializer_->allow_unknown_external_references_for_testing());
CHECK(IsAligned(target_size, kObjectAlignment));
CHECK_LE(target_size, kNumberOfFixedRawData * kTaggedSize);
int size_in_tagged = target_size >> kTaggedSizeLog2;
sink_->PutSection(kFixedRawDataStart + size_in_tagged, "FixedRawData");
sink_->PutRaw(reinterpret_cast<byte*>(&target), target_size, "Bytes");
} else if (encoded_reference.is_from_api()) {
sink_->Put(kApiReference, "ApiRef"); sink_->Put(kApiReference, "ApiRef");
sink_->PutInt(encoded_reference.index(), "reference index");
} else { } else {
sink_->Put(kExternalReference, "ExternalRef"); sink_->Put(kExternalReference, "ExternalRef");
sink_->PutInt(encoded_reference.index(), "reference index");
} }
bytes_processed_so_far_ += target_size; sink_->PutInt(encoded_reference.index(), "reference index");
} bytes_processed_so_far_ += kSystemPointerSize;
void Serializer::ObjectSerializer::VisitExternalReference(Foreign host,
Address* p) {
OutputExternalReference(host.foreign_address(), kSystemPointerSize);
} }
void Serializer::ObjectSerializer::VisitExternalReference(Code host, void Serializer::ObjectSerializer::VisitExternalReference(Code host,
RelocInfo* rinfo) { RelocInfo* rinfo) {
Address target = rinfo->target_external_reference(); Address target = rinfo->target_external_reference();
auto encoded_reference = serializer_->EncodeExternalReference(target);
if (encoded_reference.is_from_api()) {
DCHECK(!rinfo->IsCodedSpecially());
sink_->Put(kApiReference, "ApiRef");
} else {
sink_->Put(kExternalReference, "ExternalRef");
}
DCHECK_NE(target, kNullAddress); // Code does not reference null. DCHECK_NE(target, kNullAddress); // Code does not reference null.
DCHECK_IMPLIES(serializer_->EncodeExternalReference(target).is_from_api(), sink_->PutInt(encoded_reference.index(), "reference index");
!rinfo->IsCodedSpecially()); bytes_processed_so_far_ += rinfo->target_address_size();
OutputExternalReference(target, rinfo->target_address_size());
} }
void Serializer::ObjectSerializer::VisitInternalReference(Code host, void Serializer::ObjectSerializer::VisitInternalReference(Code host,
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "src/snapshot/serializer-allocator.h" #include "src/snapshot/serializer-allocator.h"
#include "src/snapshot/serializer-deserializer.h" #include "src/snapshot/serializer-deserializer.h"
#include "src/snapshot/snapshot-source-sink.h" #include "src/snapshot/snapshot-source-sink.h"
#include "src/snapshot/snapshot.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -159,7 +158,7 @@ class ObjectCacheIndexMap { ...@@ -159,7 +158,7 @@ class ObjectCacheIndexMap {
class Serializer : public SerializerDeserializer { class Serializer : public SerializerDeserializer {
public: public:
Serializer(Isolate* isolate, Snapshot::SerializerFlags flags); explicit Serializer(Isolate* isolate);
std::vector<SerializedData::Reservation> EncodeReservations() const { std::vector<SerializedData::Reservation> EncodeReservations() const {
return allocator_.EncodeReservations(); return allocator_.EncodeReservations();
...@@ -225,10 +224,6 @@ class Serializer : public SerializerDeserializer { ...@@ -225,10 +224,6 @@ class Serializer : public SerializerDeserializer {
ExternalReferenceEncoder::Value EncodeExternalReference(Address addr) { ExternalReferenceEncoder::Value EncodeExternalReference(Address addr) {
return external_reference_encoder_.Encode(addr); return external_reference_encoder_.Encode(addr);
} }
Maybe<ExternalReferenceEncoder::Value> TryEncodeExternalReference(
Address addr) {
return external_reference_encoder_.TryEncode(addr);
}
// GetInt reads 4 bytes at once, requiring padding at the end. // GetInt reads 4 bytes at once, requiring padding at the end.
// Use padding_offset to specify the space you want to use after padding. // Use padding_offset to specify the space you want to use after padding.
...@@ -265,16 +260,6 @@ class Serializer : public SerializerDeserializer { ...@@ -265,16 +260,6 @@ class Serializer : public SerializerDeserializer {
SnapshotByteSink sink_; // Used directly by subclasses. SnapshotByteSink sink_; // Used directly by subclasses.
bool allow_unknown_external_references_for_testing() const {
return (flags_ & Snapshot::kAllowUnknownExternalReferencesForTesting) != 0;
}
bool allow_open_handles_for_testing() const {
return (flags_ & Snapshot::kAllowOpenHandlesForTesting) != 0;
}
bool allow_microtasks_for_testing() const {
return (flags_ & Snapshot::kAllowMicrotasksForTesting) != 0;
}
private: private:
Isolate* isolate_; Isolate* isolate_;
SerializerReferenceMap reference_map_; SerializerReferenceMap reference_map_;
...@@ -284,7 +269,6 @@ class Serializer : public SerializerDeserializer { ...@@ -284,7 +269,6 @@ class Serializer : public SerializerDeserializer {
std::vector<byte> code_buffer_; std::vector<byte> code_buffer_;
std::vector<HeapObject> deferred_objects_; // To handle stack overflow. std::vector<HeapObject> deferred_objects_; // To handle stack overflow.
int recursion_depth_ = 0; int recursion_depth_ = 0;
const Snapshot::SerializerFlags flags_;
SerializerAllocator allocator_; SerializerAllocator allocator_;
#ifdef OBJECT_PRINT #ifdef OBJECT_PRINT
...@@ -343,7 +327,6 @@ class Serializer::ObjectSerializer : public ObjectVisitor { ...@@ -343,7 +327,6 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
// This function outputs or skips the raw data between the last pointer and // This function outputs or skips the raw data between the last pointer and
// up to the current position. // up to the current position.
void SerializeContent(Map map, int size); void SerializeContent(Map map, int size);
void OutputExternalReference(Address target, int target_size);
void OutputRawData(Address up_to); void OutputRawData(Address up_to);
void OutputCode(int size); void OutputCode(int size);
uint32_t SerializeBackingStore(void* backing_store, int32_t byte_length); uint32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#include "src/snapshot/snapshot.h" #include "src/snapshot/snapshot.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/execution/isolate-inl.h"
#include "src/init/bootstrapper.h"
#include "src/logging/counters.h" #include "src/logging/counters.h"
#include "src/snapshot/context-deserializer.h" #include "src/snapshot/context-deserializer.h"
#include "src/snapshot/context-serializer.h" #include "src/snapshot/context-serializer.h"
...@@ -188,52 +186,6 @@ MaybeHandle<Context> Snapshot::NewContextFromSnapshot( ...@@ -188,52 +186,6 @@ MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
return result; return result;
} }
// static
void Snapshot::SerializeDeserializeAndVerifyForTesting(
Isolate* isolate, Handle<Context> default_context) {
StartupData serialized_data;
std::unique_ptr<const char[]> auto_delete_serialized_data;
isolate->heap()->CollectAllAvailableGarbage(
i::GarbageCollectionReason::kSnapshotCreator);
// Test serialization.
{
DisallowHeapAllocation no_gc;
Snapshot::SerializerFlags flags(
Snapshot::kAllowUnknownExternalReferencesForTesting |
Snapshot::kAllowOpenHandlesForTesting |
Snapshot::kAllowMicrotasksForTesting);
serialized_data =
Snapshot::Create(isolate, *default_context, &no_gc, flags);
auto_delete_serialized_data.reset(serialized_data.data);
}
// Test deserialization.
Isolate* new_isolate = Isolate::New();
{
// Set serializer_enabled() to not install extensions and experimental
// natives on the new isolate.
// TODO(v8:10416): This should be a separate setting on the isolate.
new_isolate->enable_serializer();
new_isolate->Enter();
new_isolate->set_snapshot_blob(&serialized_data);
CHECK(Snapshot::Initialize(new_isolate));
HandleScope scope(new_isolate);
Handle<Context> new_native_context =
new_isolate->bootstrapper()->CreateEnvironmentForTesting();
CHECK(new_native_context->IsNativeContext());
#ifdef VERIFY_HEAP
new_isolate->heap()->Verify();
#endif // VERIFY_HEAP
}
new_isolate->Exit();
Isolate::Delete(new_isolate);
}
void ProfileDeserialization( void ProfileDeserialization(
const SnapshotData* read_only_snapshot, const SnapshotData* read_only_snapshot,
const SnapshotData* startup_snapshot, const SnapshotData* startup_snapshot,
...@@ -258,22 +210,19 @@ void ProfileDeserialization( ...@@ -258,22 +210,19 @@ void ProfileDeserialization(
} }
} }
// static
constexpr Snapshot::SerializerFlags Snapshot::kDefaultSerializerFlags;
// static // static
v8::StartupData Snapshot::Create( v8::StartupData Snapshot::Create(
Isolate* isolate, std::vector<Context>* contexts, Isolate* isolate, std::vector<Context>* contexts,
const std::vector<SerializeInternalFieldsCallback>& const std::vector<SerializeInternalFieldsCallback>&
embedder_fields_serializers, embedder_fields_serializers,
const DisallowHeapAllocation* no_gc, SerializerFlags flags) { const DisallowHeapAllocation* no_gc) {
DCHECK_EQ(contexts->size(), embedder_fields_serializers.size()); DCHECK_EQ(contexts->size(), embedder_fields_serializers.size());
DCHECK_GT(contexts->size(), 0); DCHECK_GT(contexts->size(), 0);
ReadOnlySerializer read_only_serializer(isolate, flags); ReadOnlySerializer read_only_serializer(isolate);
read_only_serializer.SerializeReadOnlyRoots(); read_only_serializer.SerializeReadOnlyRoots();
StartupSerializer startup_serializer(isolate, flags, &read_only_serializer); StartupSerializer startup_serializer(isolate, &read_only_serializer);
startup_serializer.SerializeStrongReferences(); startup_serializer.SerializeStrongReferences();
// Serialize each context with a new serializer. // Serialize each context with a new serializer.
...@@ -287,7 +236,7 @@ v8::StartupData Snapshot::Create( ...@@ -287,7 +236,7 @@ v8::StartupData Snapshot::Create(
for (int i = 0; i < num_contexts; i++) { for (int i = 0; i < num_contexts; i++) {
const bool is_default_context = (i == 0); const bool is_default_context = (i == 0);
const bool include_global_proxy = !is_default_context; const bool include_global_proxy = !is_default_context;
ContextSerializer context_serializer(isolate, flags, &startup_serializer, ContextSerializer context_serializer(isolate, &startup_serializer,
embedder_fields_serializers[i]); embedder_fields_serializers[i]);
context_serializer.Serialize(&contexts->at(i), include_global_proxy); context_serializer.Serialize(&contexts->at(i), include_global_proxy);
can_be_rehashed = can_be_rehashed && context_serializer.can_be_rehashed(); can_be_rehashed = can_be_rehashed && context_serializer.can_be_rehashed();
...@@ -316,11 +265,10 @@ v8::StartupData Snapshot::Create( ...@@ -316,11 +265,10 @@ v8::StartupData Snapshot::Create(
// static // static
v8::StartupData Snapshot::Create(Isolate* isolate, Context default_context, v8::StartupData Snapshot::Create(Isolate* isolate, Context default_context,
const DisallowHeapAllocation* no_gc, const DisallowHeapAllocation* no_gc) {
SerializerFlags flags) {
std::vector<Context> contexts{default_context}; std::vector<Context> contexts{default_context};
std::vector<SerializeInternalFieldsCallback> callbacks{{}}; std::vector<SerializeInternalFieldsCallback> callbacks{{}};
return Snapshot::Create(isolate, &contexts, callbacks, no_gc, flags); return Snapshot::Create(isolate, &contexts, callbacks, no_gc);
} }
v8::StartupData SnapshotImpl::CreateSnapshotBlob( v8::StartupData SnapshotImpl::CreateSnapshotBlob(
......
...@@ -21,24 +21,6 @@ class Snapshot : public AllStatic { ...@@ -21,24 +21,6 @@ class Snapshot : public AllStatic {
public: public:
// ---------------- Serialization ------------------------------------------- // ---------------- Serialization -------------------------------------------
enum SerializerFlag {
// If set, serializes unknown external references as verbatim data. This
// usually leads to invalid state if the snapshot is deserialized in a
// different isolate or a different process.
// If unset, all external references must be known to the encoder.
kAllowUnknownExternalReferencesForTesting = 1 << 0,
// If set, serialization can succeed even with open handles. The
// contents of open handle scopes are *not* serialized.
// If unset, no open handles are allowed to ensure the snapshot
// contains no unexpected objects.
kAllowOpenHandlesForTesting = 1 << 1,
// As above, if set we allow but do *not* serialize existing microtasks.
// If unset, the microtask queue must be empty.
kAllowMicrotasksForTesting = 1 << 2,
};
using SerializerFlags = base::Flags<SerializerFlag>;
static constexpr SerializerFlags kDefaultSerializerFlags = {};
// Serializes the given isolate and contexts. Each context may have an // Serializes the given isolate and contexts. Each context may have an
// associated callback to serialize internal fields. The default context must // associated callback to serialize internal fields. The default context must
// be passed at index 0. // be passed at index 0.
...@@ -46,14 +28,11 @@ class Snapshot : public AllStatic { ...@@ -46,14 +28,11 @@ class Snapshot : public AllStatic {
Isolate* isolate, std::vector<Context>* contexts, Isolate* isolate, std::vector<Context>* contexts,
const std::vector<SerializeInternalFieldsCallback>& const std::vector<SerializeInternalFieldsCallback>&
embedder_fields_serializers, embedder_fields_serializers,
const DisallowHeapAllocation* no_gc, const DisallowHeapAllocation* no_gc);
SerializerFlags flags = kDefaultSerializerFlags);
// Convenience helper for the above when only serializing a single context. // Convenience helper for the above when only serializing a single context.
static v8::StartupData Create( static v8::StartupData Create(Isolate* isolate, Context default_context,
Isolate* isolate, Context default_context, const DisallowHeapAllocation* no_gc);
const DisallowHeapAllocation* no_gc,
SerializerFlags flags = kDefaultSerializerFlags);
// ---------------- Deserialization ----------------------------------------- // ---------------- Deserialization -----------------------------------------
...@@ -67,15 +46,6 @@ class Snapshot : public AllStatic { ...@@ -67,15 +46,6 @@ class Snapshot : public AllStatic {
size_t context_index, size_t context_index,
v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer); v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer);
// ---------------- Testing -------------------------------------------------
// This function is used to stress the snapshot component. It serializes the
// current isolate and context into a snapshot, deserializes the snapshot into
// a new isolate and context, and finally runs VerifyHeap on the fresh
// isolate.
static void SerializeDeserializeAndVerifyForTesting(
Isolate* isolate, Handle<Context> default_context);
// ---------------- Helper methods ------------------------------------------ // ---------------- Helper methods ------------------------------------------
static bool HasContextSnapshot(Isolate* isolate, size_t index); static bool HasContextSnapshot(Isolate* isolate, size_t index);
......
...@@ -20,9 +20,8 @@ namespace v8 { ...@@ -20,9 +20,8 @@ namespace v8 {
namespace internal { namespace internal {
StartupSerializer::StartupSerializer(Isolate* isolate, StartupSerializer::StartupSerializer(Isolate* isolate,
Snapshot::SerializerFlags flags,
ReadOnlySerializer* read_only_serializer) ReadOnlySerializer* read_only_serializer)
: RootsSerializer(isolate, flags, RootIndex::kFirstStrongRoot), : RootsSerializer(isolate, RootIndex::kFirstStrongRoot),
read_only_serializer_(read_only_serializer) { read_only_serializer_(read_only_serializer) {
allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size); allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size);
InitializeCodeAddressMap(); InitializeCodeAddressMap();
...@@ -142,8 +141,7 @@ void StartupSerializer::SerializeStrongReferences() { ...@@ -142,8 +141,7 @@ void StartupSerializer::SerializeStrongReferences() {
// No active threads. // No active threads.
CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
// No active or weak handles. // No active or weak handles.
CHECK_IMPLIES(!allow_open_handles_for_testing(), CHECK(isolate->handle_scope_implementer()->blocks()->empty());
isolate->handle_scope_implementer()->blocks()->empty());
// Visit smi roots and immortal immovables first to make sure they end up in // Visit smi roots and immortal immovables first to make sure they end up in
// the first page. // the first page.
......
...@@ -18,8 +18,7 @@ class ReadOnlySerializer; ...@@ -18,8 +18,7 @@ class ReadOnlySerializer;
class V8_EXPORT_PRIVATE StartupSerializer : public RootsSerializer { class V8_EXPORT_PRIVATE StartupSerializer : public RootsSerializer {
public: public:
StartupSerializer(Isolate* isolate, Snapshot::SerializerFlags flags, StartupSerializer(Isolate* isolate, ReadOnlySerializer* read_only_serializer);
ReadOnlySerializer* read_only_serializer);
~StartupSerializer() override; ~StartupSerializer() override;
// Serialize the current state of the heap. The order is: // Serialize the current state of the heap. The order is:
......
...@@ -172,12 +172,10 @@ static StartupBlobs Serialize(v8::Isolate* isolate) { ...@@ -172,12 +172,10 @@ static StartupBlobs Serialize(v8::Isolate* isolate) {
internal_isolate->heap()->CollectAllAvailableGarbage( internal_isolate->heap()->CollectAllAvailableGarbage(
i::GarbageCollectionReason::kTesting); i::GarbageCollectionReason::kTesting);
ReadOnlySerializer read_only_serializer(internal_isolate, ReadOnlySerializer read_only_serializer(internal_isolate);
Snapshot::kDefaultSerializerFlags);
read_only_serializer.SerializeReadOnlyRoots(); read_only_serializer.SerializeReadOnlyRoots();
StartupSerializer ser(internal_isolate, Snapshot::kDefaultSerializerFlags, StartupSerializer ser(internal_isolate, &read_only_serializer);
&read_only_serializer);
ser.SerializeStrongReferences(); ser.SerializeStrongReferences();
ser.SerializeWeakReferencesAndDeferred(); ser.SerializeWeakReferencesAndDeferred();
...@@ -387,18 +385,15 @@ static void SerializeContext(Vector<const byte>* startup_blob_out, ...@@ -387,18 +385,15 @@ static void SerializeContext(Vector<const byte>* startup_blob_out,
env.Reset(); env.Reset();
SnapshotByteSink read_only_sink; SnapshotByteSink read_only_sink;
ReadOnlySerializer read_only_serializer(isolate, ReadOnlySerializer read_only_serializer(isolate);
Snapshot::kDefaultSerializerFlags);
read_only_serializer.SerializeReadOnlyRoots(); read_only_serializer.SerializeReadOnlyRoots();
SnapshotByteSink startup_sink; SnapshotByteSink startup_sink;
StartupSerializer startup_serializer( StartupSerializer startup_serializer(isolate, &read_only_serializer);
isolate, Snapshot::kDefaultSerializerFlags, &read_only_serializer);
startup_serializer.SerializeStrongReferences(); startup_serializer.SerializeStrongReferences();
SnapshotByteSink context_sink; SnapshotByteSink context_sink;
ContextSerializer context_serializer( ContextSerializer context_serializer(isolate, &startup_serializer,
isolate, Snapshot::kDefaultSerializerFlags, &startup_serializer,
v8::SerializeInternalFieldsCallback()); v8::SerializeInternalFieldsCallback());
context_serializer.Serialize(&raw_context, false); context_serializer.Serialize(&raw_context, false);
...@@ -537,18 +532,15 @@ static void SerializeCustomContext(Vector<const byte>* startup_blob_out, ...@@ -537,18 +532,15 @@ static void SerializeCustomContext(Vector<const byte>* startup_blob_out,
env.Reset(); env.Reset();
SnapshotByteSink read_only_sink; SnapshotByteSink read_only_sink;
ReadOnlySerializer read_only_serializer(isolate, ReadOnlySerializer read_only_serializer(isolate);
Snapshot::kDefaultSerializerFlags);
read_only_serializer.SerializeReadOnlyRoots(); read_only_serializer.SerializeReadOnlyRoots();
SnapshotByteSink startup_sink; SnapshotByteSink startup_sink;
StartupSerializer startup_serializer( StartupSerializer startup_serializer(isolate, &read_only_serializer);
isolate, Snapshot::kDefaultSerializerFlags, &read_only_serializer);
startup_serializer.SerializeStrongReferences(); startup_serializer.SerializeStrongReferences();
SnapshotByteSink context_sink; SnapshotByteSink context_sink;
ContextSerializer context_serializer( ContextSerializer context_serializer(isolate, &startup_serializer,
isolate, Snapshot::kDefaultSerializerFlags, &startup_serializer,
v8::SerializeInternalFieldsCallback()); v8::SerializeInternalFieldsCallback());
context_serializer.Serialize(&raw_context, false); context_serializer.Serialize(&raw_context, false);
......
...@@ -65,10 +65,6 @@ ...@@ -65,10 +65,6 @@
# BUG(v8:10197) # BUG(v8:10197)
'regress/regress-748069': [SKIP], 'regress/regress-748069': [SKIP],
# https://crbug.com/1043058
# Enable once serializing a running isolate is fully implemented.
'serialize-deserialize-now': [SKIP],
############################################################################## ##############################################################################
# Tests where variants make no sense. # Tests where variants make no sense.
'd8/enable-tracing': [PASS, NO_VARIANTS], 'd8/enable-tracing': [PASS, NO_VARIANTS],
......
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
%SerializeDeserializeNow();
const xs = [0, 1, 2];
var o = { a: 0, b: 1, c: 2 };
%SerializeDeserializeNow();
const p = new Promise((resolve, reject) => { resolve("Promise"); });
p.then((msg) => console.log(msg));
%SerializeDeserializeNow();
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