Home | History | Annotate | Download | only in snapshot
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/snapshot/startup-serializer.h"
      6 
      7 #include "src/objects-inl.h"
      8 #include "src/v8threads.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 StartupSerializer::StartupSerializer(
     14     Isolate* isolate,
     15     v8::SnapshotCreator::FunctionCodeHandling function_code_handling)
     16     : Serializer(isolate),
     17       clear_function_code_(function_code_handling ==
     18                            v8::SnapshotCreator::FunctionCodeHandling::kClear),
     19       serializing_builtins_(false) {
     20   InitializeCodeAddressMap();
     21 }
     22 
     23 StartupSerializer::~StartupSerializer() {
     24   OutputStatistics("StartupSerializer");
     25 }
     26 
     27 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
     28                                         WhereToPoint where_to_point, int skip) {
     29   DCHECK(!obj->IsJSFunction());
     30 
     31   if (clear_function_code_) {
     32     if (obj->IsCode()) {
     33       Code* code = Code::cast(obj);
     34       // If the function code is compiled (either as native code or bytecode),
     35       // replace it with lazy-compile builtin. Only exception is when we are
     36       // serializing the canonical interpreter-entry-trampoline builtin.
     37       if (code->kind() == Code::FUNCTION ||
     38           (!serializing_builtins_ &&
     39            code->is_interpreter_trampoline_builtin())) {
     40         obj = isolate()->builtins()->builtin(Builtins::kCompileLazy);
     41       }
     42     } else if (obj->IsBytecodeArray()) {
     43       obj = isolate()->heap()->undefined_value();
     44     }
     45   } else if (obj->IsCode()) {
     46     Code* code = Code::cast(obj);
     47     if (code->kind() == Code::FUNCTION) {
     48       code->ClearInlineCaches();
     49       code->set_profiler_ticks(0);
     50     }
     51   }
     52 
     53   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
     54 
     55   int root_index = root_index_map_.Lookup(obj);
     56   // We can only encode roots as such if it has already been serialized.
     57   // That applies to root indices below the wave front.
     58   if (root_index != RootIndexMap::kInvalidRootIndex) {
     59     if (root_has_been_serialized_.test(root_index)) {
     60       PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     61       return;
     62     }
     63   }
     64 
     65   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
     66 
     67   FlushSkip(skip);
     68 
     69   // Object has not yet been serialized.  Serialize it here.
     70   ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
     71                                      where_to_point);
     72   object_serializer.Serialize();
     73 
     74   if (serializing_immortal_immovables_roots_ &&
     75       root_index != RootIndexMap::kInvalidRootIndex) {
     76     // Make sure that the immortal immovable root has been included in the first
     77     // chunk of its reserved space , so that it is deserialized onto the first
     78     // page of its space and stays immortal immovable.
     79     SerializerReference ref = reference_map_.Lookup(obj);
     80     CHECK(ref.is_back_reference() && ref.chunk_index() == 0);
     81   }
     82 }
     83 
     84 void StartupSerializer::SerializeWeakReferencesAndDeferred() {
     85   // This comes right after serialization of the partial snapshot, where we
     86   // add entries to the partial snapshot cache of the startup snapshot. Add
     87   // one entry with 'undefined' to terminate the partial snapshot cache.
     88   Object* undefined = isolate()->heap()->undefined_value();
     89   VisitPointer(&undefined);
     90   isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
     91   SerializeDeferredObjects();
     92   Pad();
     93 }
     94 
     95 int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
     96   int index;
     97   if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) {
     98     // This object is not part of the partial snapshot cache yet. Add it to the
     99     // startup snapshot so we can refer to it via partial snapshot index from
    100     // the partial snapshot.
    101     VisitPointer(reinterpret_cast<Object**>(&heap_object));
    102   }
    103   return index;
    104 }
    105 
    106 void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
    107   // We expect the builtins tag after builtins have been serialized.
    108   DCHECK(!serializing_builtins_ || tag == VisitorSynchronization::kBuiltins);
    109   serializing_builtins_ = (tag == VisitorSynchronization::kHandleScope);
    110   sink_.Put(kSynchronize, "Synchronize");
    111 }
    112 
    113 void StartupSerializer::SerializeStrongReferences() {
    114   Isolate* isolate = this->isolate();
    115   // No active threads.
    116   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
    117   // No active or weak handles.
    118   CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
    119   CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
    120   CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
    121   // We don't support serializing installed extensions.
    122   CHECK(!isolate->has_installed_extensions());
    123   // First visit immortal immovables to make sure they end up in the first page.
    124   serializing_immortal_immovables_roots_ = true;
    125   isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG_ROOT_LIST);
    126   // Check that immortal immovable roots are allocated on the first page.
    127   CHECK(HasNotExceededFirstPageOfEachSpace());
    128   serializing_immortal_immovables_roots_ = false;
    129   // Visit the rest of the strong roots.
    130   // Clear the stack limits to make the snapshot reproducible.
    131   // Reset it again afterwards.
    132   isolate->heap()->ClearStackLimits();
    133   isolate->heap()->IterateSmiRoots(this);
    134   isolate->heap()->SetStackLimits();
    135 
    136   isolate->heap()->IterateStrongRoots(this,
    137                                       VISIT_ONLY_STRONG_FOR_SERIALIZATION);
    138 }
    139 
    140 void StartupSerializer::VisitPointers(Object** start, Object** end) {
    141   if (start == isolate()->heap()->roots_array_start()) {
    142     // Serializing the root list needs special handling:
    143     // - The first pass over the root list only serializes immortal immovables.
    144     // - The second pass over the root list serializes the rest.
    145     // - Only root list elements that have been fully serialized can be
    146     //   referenced via as root by using kRootArray bytecodes.
    147     int skip = 0;
    148     for (Object** current = start; current < end; current++) {
    149       int root_index = static_cast<int>(current - start);
    150       if (RootShouldBeSkipped(root_index)) {
    151         skip += kPointerSize;
    152         continue;
    153       } else {
    154         if ((*current)->IsSmi()) {
    155           FlushSkip(skip);
    156           PutSmi(Smi::cast(*current));
    157         } else {
    158           SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject,
    159                           skip);
    160         }
    161         root_has_been_serialized_.set(root_index);
    162         skip = 0;
    163       }
    164     }
    165     FlushSkip(skip);
    166   } else {
    167     Serializer::VisitPointers(start, end);
    168   }
    169 }
    170 
    171 bool StartupSerializer::RootShouldBeSkipped(int root_index) {
    172   if (root_index == Heap::kStackLimitRootIndex ||
    173       root_index == Heap::kRealStackLimitRootIndex) {
    174     return true;
    175   }
    176   return Heap::RootIsImmortalImmovable(root_index) !=
    177          serializing_immortal_immovables_roots_;
    178 }
    179 
    180 }  // namespace internal
    181 }  // namespace v8
    182