LCOV - code coverage report
Current view: top level - src/snapshot - startup-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 92 95 96.8 %
Date: 2017-10-20 Functions: 10 12 83.3 %

          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/api.h"
       8             : #include "src/objects-inl.h"
       9             : #include "src/v8threads.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14         161 : StartupSerializer::StartupSerializer(
      15             :     Isolate* isolate,
      16             :     v8::SnapshotCreator::FunctionCodeHandling function_code_handling)
      17             :     : Serializer(isolate),
      18         161 :       clear_function_code_(function_code_handling ==
      19             :                            v8::SnapshotCreator::FunctionCodeHandling::kClear),
      20         483 :       can_be_rehashed_(true) {
      21         161 :   InitializeCodeAddressMap();
      22         161 : }
      23             : 
      24         161 : StartupSerializer::~StartupSerializer() {
      25         161 :   RestoreExternalReferenceRedirectors(accessor_infos_);
      26         161 :   OutputStatistics("StartupSerializer");
      27         161 : }
      28             : 
      29     4358756 : void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
      30     8717512 :                                         WhereToPoint where_to_point, int skip) {
      31             :   DCHECK(!obj->IsJSFunction());
      32             : 
      33     8351937 :   if (clear_function_code() && obj->IsBytecodeArray()) {
      34      893303 :     obj = isolate()->heap()->undefined_value();
      35             :   }
      36             : 
      37             :   BuiltinReferenceSerializationMode mode =
      38     4358756 :       clear_function_code() ? kCanonicalizeCompileLazy : kDefault;
      39     4358756 :   if (SerializeBuiltinReference(obj, how_to_code, where_to_point, skip, mode)) {
      40     3496037 :     return;
      41             :   }
      42     3944887 :   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
      43             : 
      44     3529520 :   int root_index = root_index_map()->Lookup(obj);
      45             :   // We can only encode roots as such if it has already been serialized.
      46             :   // That applies to root indices below the wave front.
      47     3529520 :   if (root_index != RootIndexMap::kInvalidRootIndex) {
      48     2262453 :     if (root_has_been_serialized(root_index)) {
      49     2186357 :       PutRoot(root_index, obj, how_to_code, where_to_point, skip);
      50     2186357 :       return;
      51             :     }
      52             :   }
      53             : 
      54     1343163 :   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
      55             : 
      56      862719 :   FlushSkip(skip);
      57             : 
      58      862719 :   if (isolate()->external_reference_redirector() && obj->IsAccessorInfo()) {
      59             :     // Wipe external reference redirects in the accessor info.
      60           0 :     AccessorInfo* info = AccessorInfo::cast(obj);
      61             :     Address original_address = Foreign::cast(info->getter())->foreign_address();
      62             :     Foreign::cast(info->js_getter())->set_foreign_address(original_address);
      63           0 :     accessor_infos_.push_back(info);
      64      862719 :   } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
      65             :     Script::cast(obj)->set_context_data(
      66          60 :         isolate()->heap()->uninitialized_symbol());
      67      862659 :   } else if (obj->IsSharedFunctionInfo()) {
      68             :     // Clear inferred name for native functions.
      69             :     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
      70      150620 :     if (!shared->IsSubjectToDebugging() && shared->HasInferredName()) {
      71       29737 :       shared->set_inferred_name(isolate()->heap()->empty_string());
      72             :     }
      73             :   }
      74             : 
      75      862719 :   if (obj->IsHashTable()) CheckRehashability(obj);
      76             : 
      77             :   // Object has not yet been serialized.  Serialize it here.
      78             :   ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
      79      862719 :                                      where_to_point);
      80      862719 :   object_serializer.Serialize();
      81             : }
      82             : 
      83         161 : void StartupSerializer::SerializeWeakReferencesAndDeferred() {
      84             :   // This comes right after serialization of the partial snapshot, where we
      85             :   // add entries to the partial snapshot cache of the startup snapshot. Add
      86             :   // one entry with 'undefined' to terminate the partial snapshot cache.
      87         322 :   Object* undefined = isolate()->heap()->undefined_value();
      88         161 :   VisitRootPointer(Root::kPartialSnapshotCache, &undefined);
      89         161 :   isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
      90         161 :   SerializeDeferredObjects();
      91         161 :   Pad();
      92         161 : }
      93             : 
      94      791196 : int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
      95             :   int index;
      96      791196 :   if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) {
      97             :     // This object is not part of the partial snapshot cache yet. Add it to the
      98             :     // startup snapshot so we can refer to it via partial snapshot index from
      99             :     // the partial snapshot.
     100             :     VisitRootPointer(Root::kPartialSnapshotCache,
     101      362513 :                      reinterpret_cast<Object**>(&heap_object));
     102             :   }
     103      791196 :   return index;
     104             : }
     105             : 
     106        2898 : void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
     107             :   sink_.Put(kSynchronize, "Synchronize");
     108        2898 : }
     109             : 
     110         161 : void StartupSerializer::SerializeStrongReferences() {
     111         644 :   Isolate* isolate = this->isolate();
     112             :   // No active threads.
     113         161 :   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
     114             :   // No active or weak handles.
     115         161 :   CHECK(isolate->handle_scope_implementer()->blocks()->empty());
     116         161 :   CHECK_EQ(0, isolate->global_handles()->global_handles_count());
     117         161 :   CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
     118             :   // First visit immortal immovables to make sure they end up in the first page.
     119         161 :   serializing_immortal_immovables_roots_ = true;
     120         161 :   isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG_ROOT_LIST);
     121             :   // Check that immortal immovable roots are allocated on the first page.
     122             :   DCHECK(allocator()->HasNotExceededFirstPageOfEachSpace());
     123         161 :   serializing_immortal_immovables_roots_ = false;
     124             :   // Visit the rest of the strong roots.
     125             :   // Clear the stack limits to make the snapshot reproducible.
     126             :   // Reset it again afterwards.
     127         161 :   isolate->heap()->ClearStackLimits();
     128         161 :   isolate->heap()->IterateSmiRoots(this);
     129         161 :   isolate->heap()->SetStackLimits();
     130             : 
     131             :   isolate->heap()->IterateStrongRoots(this,
     132         161 :                                       VISIT_ONLY_STRONG_FOR_SERIALIZATION);
     133         161 : }
     134             : 
     135      489351 : void StartupSerializer::VisitRootPointers(Root root, Object** start,
     136             :                                           Object** end) {
     137      489351 :   if (start == isolate()->heap()->roots_array_start()) {
     138             :     // Serializing the root list needs special handling:
     139             :     // - The first pass over the root list only serializes immortal immovables.
     140             :     // - The second pass over the root list serializes the rest.
     141             :     // - Only root list elements that have been fully serialized can be
     142             :     //   referenced via as root by using kRootArray bytecodes.
     143             :     int skip = 0;
     144      138782 :     for (Object** current = start; current < end; current++) {
     145      138782 :       int root_index = static_cast<int>(current - start);
     146      138782 :       if (RootShouldBeSkipped(root_index)) {
     147       69391 :         skip += kPointerSize;
     148       69391 :         continue;
     149             :       } else {
     150      138782 :         if ((*current)->IsSmi()) {
     151         161 :           FlushSkip(skip);
     152         161 :           PutSmi(Smi::cast(*current));
     153             :         } else {
     154             :           SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject,
     155       69230 :                           skip);
     156             :         }
     157       69391 :         root_has_been_serialized_.set(root_index);
     158             :         skip = 0;
     159             :       }
     160             :     }
     161         322 :     FlushSkip(skip);
     162             :   } else {
     163      489029 :     Serializer::VisitRootPointers(root, start, end);
     164             :   }
     165      489351 : }
     166             : 
     167           0 : bool StartupSerializer::RootShouldBeSkipped(int root_index) {
     168      138782 :   if (root_index == Heap::kStackLimitRootIndex ||
     169             :       root_index == Heap::kRealStackLimitRootIndex) {
     170             :     return true;
     171             :   }
     172      138782 :   return Heap::RootIsImmortalImmovable(root_index) !=
     173      138782 :          serializing_immortal_immovables_roots_;
     174             : }
     175             : 
     176         971 : void StartupSerializer::CheckRehashability(HeapObject* table) {
     177             :   DCHECK(table->IsHashTable());
     178         971 :   if (!can_be_rehashed_) return;
     179             :   // We can only correctly rehash if the four hash tables below are the only
     180             :   // ones that we deserialize.
     181         956 :   if (table->IsUnseededNumberDictionary()) return;
     182         800 :   if (table == isolate()->heap()->empty_ordered_hash_table()) return;
     183         639 :   if (table == isolate()->heap()->empty_slow_element_dictionary()) return;
     184         478 :   if (table == isolate()->heap()->empty_property_dictionary()) return;
     185         317 :   if (table == isolate()->heap()->weak_object_to_code_table()) return;
     186         161 :   if (table == isolate()->heap()->string_table()) return;
     187           5 :   can_be_rehashed_ = false;
     188             : }
     189             : 
     190      862714 : bool StartupSerializer::MustBeDeferred(HeapObject* object) {
     191     2587015 :   if (root_has_been_serialized_.test(Heap::kFreeSpaceMapRootIndex) &&
     192     1724140 :       root_has_been_serialized_.test(Heap::kOnePointerFillerMapRootIndex) &&
     193      861426 :       root_has_been_serialized_.test(Heap::kTwoPointerFillerMapRootIndex)) {
     194             :     // All required root objects are serialized, so any aligned objects can
     195             :     // be saved without problems.
     196             :     return false;
     197             :   }
     198             :   // Just defer everything except of Map objects until all required roots are
     199             :   // serialized. Some objects may have special alignment requirements, that may
     200             :   // not be fulfilled during deserialization until few first root objects are
     201             :   // serialized. But we must serialize Map objects since deserializer checks
     202             :   // that these root objects are indeed Maps.
     203        1449 :   return !object->IsMap();
     204             : }
     205             : 
     206             : }  // namespace internal
     207             : }  // namespace v8

Generated by: LCOV version 1.10