| Index: src/snapshot/startup-serializer.cc
|
| diff --git a/src/snapshot/startup-serializer.cc b/src/snapshot/startup-serializer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fdaf3cf660300d8247e68d025130dc547bfda4a4
|
| --- /dev/null
|
| +++ b/src/snapshot/startup-serializer.cc
|
| @@ -0,0 +1,132 @@
|
| +// Copyright 2016 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.
|
| +
|
| +#include "src/snapshot/startup-serializer.h"
|
| +
|
| +#include "src/objects-inl.h"
|
| +#include "src/v8threads.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +StartupSerializer::StartupSerializer(Isolate* isolate, SnapshotByteSink* sink)
|
| + : Serializer(isolate, sink),
|
| + root_index_wave_front_(0),
|
| + serializing_builtins_(false) {
|
| + // Clear the cache of objects used by the partial snapshot. After the
|
| + // strong roots have been serialized we can create a partial snapshot
|
| + // which will repopulate the cache with objects needed by that partial
|
| + // snapshot.
|
| + isolate->partial_snapshot_cache()->Clear();
|
| + InitializeCodeAddressMap();
|
| +}
|
| +
|
| +StartupSerializer::~StartupSerializer() {
|
| + OutputStatistics("StartupSerializer");
|
| +}
|
| +
|
| +void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
| + WhereToPoint where_to_point, int skip) {
|
| + DCHECK(!obj->IsJSFunction());
|
| +
|
| + if (obj->IsCode()) {
|
| + Code* code = Code::cast(obj);
|
| + // If the function code is compiled (either as native code or bytecode),
|
| + // replace it with lazy-compile builtin. Only exception is when we are
|
| + // serializing the canonical interpreter-entry-trampoline builtin.
|
| + if (code->kind() == Code::FUNCTION ||
|
| + (!serializing_builtins_ && code->is_interpreter_entry_trampoline())) {
|
| + obj = isolate()->builtins()->builtin(Builtins::kCompileLazy);
|
| + }
|
| + } else if (obj->IsBytecodeArray()) {
|
| + obj = isolate()->heap()->undefined_value();
|
| + }
|
| +
|
| + int root_index = root_index_map_.Lookup(obj);
|
| + bool is_immortal_immovable_root = false;
|
| + // We can only encode roots as such if it has already been serialized.
|
| + // That applies to root indices below the wave front.
|
| + if (root_index != RootIndexMap::kInvalidRootIndex) {
|
| + if (root_index < root_index_wave_front_) {
|
| + PutRoot(root_index, obj, how_to_code, where_to_point, skip);
|
| + return;
|
| + } else {
|
| + is_immortal_immovable_root = Heap::RootIsImmortalImmovable(root_index);
|
| + }
|
| + }
|
| +
|
| + if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
|
| +
|
| + FlushSkip(skip);
|
| +
|
| + // Object has not yet been serialized. Serialize it here.
|
| + ObjectSerializer object_serializer(this, obj, sink_, how_to_code,
|
| + where_to_point);
|
| + object_serializer.Serialize();
|
| +
|
| + if (is_immortal_immovable_root) {
|
| + // Make sure that the immortal immovable root has been included in the first
|
| + // chunk of its reserved space , so that it is deserialized onto the first
|
| + // page of its space and stays immortal immovable.
|
| + BackReference ref = back_reference_map_.Lookup(obj);
|
| + CHECK(ref.is_valid() && ref.chunk_index() == 0);
|
| + }
|
| +}
|
| +
|
| +void StartupSerializer::SerializeWeakReferencesAndDeferred() {
|
| + // This phase comes right after the serialization (of the snapshot).
|
| + // After we have done the partial serialization the partial snapshot cache
|
| + // will contain some references needed to decode the partial snapshot. We
|
| + // add one entry with 'undefined' which is the sentinel that the deserializer
|
| + // uses to know it is done deserializing the array.
|
| + Object* undefined = isolate()->heap()->undefined_value();
|
| + VisitPointer(&undefined);
|
| + isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
|
| + SerializeDeferredObjects();
|
| + Pad();
|
| +}
|
| +
|
| +void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
|
| + // We expect the builtins tag after builtins have been serialized.
|
| + DCHECK(!serializing_builtins_ || tag == VisitorSynchronization::kBuiltins);
|
| + serializing_builtins_ = (tag == VisitorSynchronization::kHandleScope);
|
| + sink_->Put(kSynchronize, "Synchronize");
|
| +}
|
| +
|
| +void StartupSerializer::SerializeStrongReferences() {
|
| + Isolate* isolate = this->isolate();
|
| + // No active threads.
|
| + CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
|
| + // No active or weak handles.
|
| + CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
|
| + CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
|
| + CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
|
| + // We don't support serializing installed extensions.
|
| + CHECK(!isolate->has_installed_extensions());
|
| + isolate->heap()->IterateSmiRoots(this);
|
| + isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
|
| +}
|
| +
|
| +void StartupSerializer::VisitPointers(Object** start, Object** end) {
|
| + for (Object** current = start; current < end; current++) {
|
| + if (start == isolate()->heap()->roots_array_start()) {
|
| + root_index_wave_front_ =
|
| + Max(root_index_wave_front_, static_cast<intptr_t>(current - start));
|
| + }
|
| + if (ShouldBeSkipped(current)) {
|
| + sink_->Put(kSkip, "Skip");
|
| + sink_->PutInt(kPointerSize, "SkipOneWord");
|
| + } else if ((*current)->IsSmi()) {
|
| + sink_->Put(kOnePointerRawData, "Smi");
|
| + for (int i = 0; i < kPointerSize; i++) {
|
| + sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
|
| + }
|
| + } else {
|
| + SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0);
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace internal
|
| +} // namespace v8
|
|
|