LCOV - code coverage report
Current view: top level - src/snapshot - startup-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 84 86 97.7 %
Date: 2017-04-26 Functions: 8 10 80.0 %

          Line data    Source code
       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         151 : StartupSerializer::StartupSerializer(
      14             :     Isolate* isolate,
      15             :     v8::SnapshotCreator::FunctionCodeHandling function_code_handling)
      16             :     : Serializer(isolate),
      17         151 :       clear_function_code_(function_code_handling ==
      18             :                            v8::SnapshotCreator::FunctionCodeHandling::kClear),
      19         302 :       serializing_builtins_(false) {
      20         151 :   InitializeCodeAddressMap();
      21         151 : }
      22             : 
      23         302 : StartupSerializer::~StartupSerializer() {
      24         151 :   RestoreExternalReferenceRedirectors(&accessor_infos_);
      25         151 :   OutputStatistics("StartupSerializer");
      26         151 : }
      27             : 
      28     5950826 : void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
      29             :                                         WhereToPoint where_to_point, int skip) {
      30             :   DCHECK(!obj->IsJSFunction());
      31             : 
      32     5950826 :   if (clear_function_code_) {
      33     5514124 :     if (obj->IsCode()) {
      34             :       Code* code = Code::cast(obj);
      35             :       // If the function code is compiled (either as native code or bytecode),
      36             :       // replace it with lazy-compile builtin. Only exception is when we are
      37             :       // serializing the canonical interpreter-entry-trampoline builtin.
      38     3954786 :       if (code->kind() == Code::FUNCTION ||
      39     2298160 :           (!serializing_builtins_ &&
      40      980234 :            code->is_interpreter_trampoline_builtin())) {
      41        3427 :         obj = isolate()->builtins()->builtin(Builtins::kCompileLazy);
      42             :       }
      43     4195694 :     } else if (obj->IsBytecodeArray()) {
      44        1451 :       obj = isolate()->heap()->undefined_value();
      45             :     }
      46      436702 :   } else if (obj->IsCode()) {
      47             :     Code* code = Code::cast(obj);
      48      109636 :     if (code->kind() == Code::FUNCTION) {
      49           2 :       code->ClearInlineCaches();
      50             :       code->set_profiler_ticks(0);
      51             :     }
      52             :   }
      53             : 
      54    10896625 :   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
      55             : 
      56     5244715 :   int root_index = root_index_map_.Lookup(obj);
      57             :   // We can only encode roots as such if it has already been serialized.
      58             :   // That applies to root indices below the wave front.
      59     5244715 :   if (root_index != RootIndexMap::kInvalidRootIndex) {
      60     2977959 :     if (root_has_been_serialized_.test(root_index)) {
      61     2909403 :       PutRoot(root_index, obj, how_to_code, where_to_point, skip);
      62     2909403 :       return;
      63             :     }
      64             :   }
      65             : 
      66     2335312 :   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
      67             : 
      68     1005027 :   FlushSkip(skip);
      69             : 
      70     1005027 :   if (isolate_->external_reference_redirector() && obj->IsAccessorInfo()) {
      71             :     // Wipe external reference redirects in the accessor info.
      72             :     AccessorInfo* info = AccessorInfo::cast(obj);
      73             :     Address original_address = Foreign::cast(info->getter())->foreign_address();
      74             :     Foreign::cast(info->js_getter())->set_foreign_address(original_address);
      75           0 :     accessor_infos_.Add(info);
      76     1005027 :   } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
      77             :     Script::cast(obj)->set_context_data(
      78          72 :         isolate_->heap()->uninitialized_symbol());
      79             :   }
      80             : 
      81             :   // Object has not yet been serialized.  Serialize it here.
      82             :   ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
      83     1005027 :                                      where_to_point);
      84     1005027 :   object_serializer.Serialize();
      85             : 
      86     1005027 :   if (serializing_immortal_immovables_roots_ &&
      87             :       root_index != RootIndexMap::kInvalidRootIndex) {
      88             :     // Make sure that the immortal immovable root has been included in the first
      89             :     // chunk of its reserved space , so that it is deserialized onto the first
      90             :     // page of its space and stays immortal immovable.
      91       51532 :     SerializerReference ref = reference_map_.Lookup(obj);
      92      103064 :     CHECK(ref.is_back_reference() && ref.chunk_index() == 0);
      93             :   }
      94             : }
      95             : 
      96         151 : void StartupSerializer::SerializeWeakReferencesAndDeferred() {
      97             :   // This comes right after serialization of the partial snapshot, where we
      98             :   // add entries to the partial snapshot cache of the startup snapshot. Add
      99             :   // one entry with 'undefined' to terminate the partial snapshot cache.
     100         302 :   Object* undefined = isolate()->heap()->undefined_value();
     101         151 :   VisitRootPointer(Root::kPartialSnapshotCache, &undefined);
     102         151 :   isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
     103         151 :   SerializeDeferredObjects();
     104         151 :   Pad();
     105         151 : }
     106             : 
     107      452284 : int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
     108             :   int index;
     109      452284 :   if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) {
     110             :     // This object is not part of the partial snapshot cache yet. Add it to the
     111             :     // startup snapshot so we can refer to it via partial snapshot index from
     112             :     // the partial snapshot.
     113             :     VisitRootPointer(Root::kPartialSnapshotCache,
     114      246883 :                      reinterpret_cast<Object**>(&heap_object));
     115             :   }
     116      452284 :   return index;
     117             : }
     118             : 
     119        2718 : void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
     120             :   // We expect the builtins tag after builtins have been serialized.
     121             :   DCHECK(!serializing_builtins_ || tag == VisitorSynchronization::kBuiltins);
     122        2718 :   serializing_builtins_ = (tag == VisitorSynchronization::kHandleScope);
     123             :   sink_.Put(kSynchronize, "Synchronize");
     124        2718 : }
     125             : 
     126         151 : void StartupSerializer::SerializeStrongReferences() {
     127         604 :   Isolate* isolate = this->isolate();
     128             :   // No active threads.
     129         151 :   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
     130             :   // No active or weak handles.
     131         151 :   CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
     132         151 :   CHECK_EQ(0, isolate->global_handles()->global_handles_count());
     133         151 :   CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
     134             :   // First visit immortal immovables to make sure they end up in the first page.
     135         151 :   serializing_immortal_immovables_roots_ = true;
     136         151 :   isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG_ROOT_LIST);
     137             :   // Check that immortal immovable roots are allocated on the first page.
     138         151 :   CHECK(HasNotExceededFirstPageOfEachSpace());
     139         151 :   serializing_immortal_immovables_roots_ = false;
     140             :   // Visit the rest of the strong roots.
     141             :   // Clear the stack limits to make the snapshot reproducible.
     142             :   // Reset it again afterwards.
     143         151 :   isolate->heap()->ClearStackLimits();
     144         151 :   isolate->heap()->IterateSmiRoots(this);
     145         151 :   isolate->heap()->SetStackLimits();
     146             : 
     147             :   isolate->heap()->IterateStrongRoots(this,
     148         151 :                                       VISIT_ONLY_STRONG_FOR_SERIALIZATION);
     149         151 : }
     150             : 
     151      365684 : void StartupSerializer::VisitRootPointers(Root root, Object** start,
     152             :                                           Object** end) {
     153      365684 :   if (start == isolate()->heap()->roots_array_start()) {
     154             :     // Serializing the root list needs special handling:
     155             :     // - The first pass over the root list only serializes immortal immovables.
     156             :     // - The second pass over the root list serializes the rest.
     157             :     // - Only root list elements that have been fully serialized can be
     158             :     //   referenced via as root by using kRootArray bytecodes.
     159             :     int skip = 0;
     160      123216 :     for (Object** current = start; current < end; current++) {
     161      123216 :       int root_index = static_cast<int>(current - start);
     162      123216 :       if (RootShouldBeSkipped(root_index)) {
     163       61608 :         skip += kPointerSize;
     164       61608 :         continue;
     165             :       } else {
     166      123216 :         if ((*current)->IsSmi()) {
     167         604 :           FlushSkip(skip);
     168         604 :           PutSmi(Smi::cast(*current));
     169             :         } else {
     170             :           SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject,
     171       61004 :                           skip);
     172             :         }
     173       61608 :         root_has_been_serialized_.set(root_index);
     174             :         skip = 0;
     175             :       }
     176             :     }
     177         302 :     FlushSkip(skip);
     178             :   } else {
     179      365382 :     Serializer::VisitRootPointers(root, start, end);
     180             :   }
     181      365684 : }
     182             : 
     183           0 : bool StartupSerializer::RootShouldBeSkipped(int root_index) {
     184      123216 :   if (root_index == Heap::kStackLimitRootIndex ||
     185             :       root_index == Heap::kRealStackLimitRootIndex) {
     186             :     return true;
     187             :   }
     188      123216 :   return Heap::RootIsImmortalImmovable(root_index) !=
     189      123216 :          serializing_immortal_immovables_roots_;
     190             : }
     191             : 
     192             : }  // namespace internal
     193             : }  // namespace v8

Generated by: LCOV version 1.10