LCOV - code coverage report
Current view: top level - src/snapshot - startup-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 64 68 94.1 %
Date: 2019-04-17 Functions: 12 13 92.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/code-tracer.h"
       9             : #include "src/contexts.h"
      10             : #include "src/deoptimizer.h"
      11             : #include "src/global-handles.h"
      12             : #include "src/heap/heap-inl.h"
      13             : #include "src/heap/read-only-heap.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/foreign-inl.h"
      16             : #include "src/objects/slots.h"
      17             : #include "src/snapshot/read-only-serializer.h"
      18             : #include "src/v8threads.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23         261 : StartupSerializer::StartupSerializer(Isolate* isolate,
      24             :                                      ReadOnlySerializer* read_only_serializer)
      25             :     : RootsSerializer(isolate, RootIndex::kFirstStrongRoot),
      26         261 :       read_only_serializer_(read_only_serializer) {
      27         261 :   InitializeCodeAddressMap();
      28         261 : }
      29             : 
      30         522 : StartupSerializer::~StartupSerializer() {
      31         261 :   RestoreExternalReferenceRedirectors(accessor_infos_);
      32         261 :   RestoreExternalReferenceRedirectors(call_handler_infos_);
      33         261 :   OutputStatistics("StartupSerializer");
      34         261 : }
      35             : 
      36             : #ifdef DEBUG
      37             : namespace {
      38             : 
      39             : bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) {
      40             :   if (!obj->IsCode()) return false;
      41             : 
      42             :   Code code = Code::cast(obj);
      43             : 
      44             :   // TODO(v8:8768): Deopt entry code should not be serialized.
      45             :   if (code->kind() == Code::STUB && isolate->deoptimizer_data() != nullptr) {
      46             :     if (isolate->deoptimizer_data()->IsDeoptEntryCode(code)) return false;
      47             :   }
      48             : 
      49             :   if (code->kind() == Code::REGEXP) return false;
      50             :   if (!code->is_builtin()) return true;
      51             :   if (!FLAG_embedded_builtins) return false;
      52             :   if (code->is_off_heap_trampoline()) return false;
      53             : 
      54             :   // An on-heap builtin. We only expect this for the interpreter entry
      55             :   // trampoline copy stored on the root list and transitively called builtins.
      56             :   // See Heap::interpreter_entry_trampoline_for_profiling.
      57             : 
      58             :   switch (code->builtin_index()) {
      59             :     case Builtins::kAbort:
      60             :     case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
      61             :     case Builtins::kInterpreterEntryTrampoline:
      62             :     case Builtins::kRecordWrite:
      63             :       return false;
      64             :     default:
      65             :       return true;
      66             :   }
      67             : 
      68             :   UNREACHABLE();
      69             : }
      70             : 
      71             : }  // namespace
      72             : #endif  // DEBUG
      73             : 
      74     5176296 : void StartupSerializer::SerializeObject(HeapObject obj) {
      75             :   DCHECK(!obj->IsJSFunction());
      76             :   DCHECK(!IsUnexpectedCodeObject(isolate(), obj));
      77             : 
      78     9204117 :   if (SerializeHotObject(obj)) return;
      79     3740411 :   if (IsRootAndHasBeenSerialized(obj) && SerializeRoot(obj)) return;
      80     3385836 :   if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return;
      81     1578376 :   if (SerializeBackReference(obj)) return;
      82             : 
      83             :   bool use_simulator = false;
      84             : #ifdef USE_SIMULATOR
      85             :   use_simulator = true;
      86             : #endif
      87             : 
      88             :   if (use_simulator && obj->IsAccessorInfo()) {
      89             :     // Wipe external reference redirects in the accessor info.
      90             :     AccessorInfo info = AccessorInfo::cast(obj);
      91             :     Address original_address = Foreign::cast(info->getter())->foreign_address();
      92             :     Foreign::cast(info->js_getter())->set_foreign_address(original_address);
      93             :     accessor_infos_.push_back(info);
      94             :   } else if (use_simulator && obj->IsCallHandlerInfo()) {
      95             :     CallHandlerInfo info = CallHandlerInfo::cast(obj);
      96             :     Address original_address =
      97             :         Foreign::cast(info->callback())->foreign_address();
      98             :     Foreign::cast(info->js_callback())->set_foreign_address(original_address);
      99             :     call_handler_infos_.push_back(info);
     100     1148475 :   } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
     101         230 :     Script::cast(obj)->set_context_data(
     102         345 :         ReadOnlyRoots(isolate()).uninitialized_symbol());
     103     1148360 :   } else if (obj->IsSharedFunctionInfo()) {
     104             :     // Clear inferred name for native functions.
     105      178596 :     SharedFunctionInfo shared = SharedFunctionInfo::cast(obj);
     106      178596 :     if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) {
     107        3708 :       shared->uncompiled_data()->set_inferred_name(
     108        1854 :           ReadOnlyRoots(isolate()).empty_string());
     109             :     }
     110             :   }
     111             : 
     112     1148475 :   CheckRehashability(obj);
     113             : 
     114             :   // Object has not yet been serialized.  Serialize it here.
     115             :   DCHECK(!ReadOnlyHeap::Contains(obj));
     116             :   ObjectSerializer object_serializer(this, obj, &sink_);
     117     1148475 :   object_serializer.Serialize();
     118             : }
     119             : 
     120         261 : void StartupSerializer::SerializeWeakReferencesAndDeferred() {
     121             :   // This comes right after serialization of the partial snapshot, where we
     122             :   // add entries to the partial snapshot cache of the startup snapshot. Add
     123             :   // one entry with 'undefined' to terminate the partial snapshot cache.
     124         261 :   Object undefined = ReadOnlyRoots(isolate()).undefined_value();
     125         522 :   VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
     126         522 :                    FullObjectSlot(&undefined));
     127         261 :   isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
     128         261 :   SerializeDeferredObjects();
     129         261 :   Pad();
     130         261 : }
     131             : 
     132         261 : void StartupSerializer::SerializeStrongReferences() {
     133             :   Isolate* isolate = this->isolate();
     134             :   // No active threads.
     135         261 :   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
     136             :   // No active or weak handles.
     137         261 :   CHECK(isolate->handle_scope_implementer()->blocks()->empty());
     138             : 
     139             :   // Visit smi roots.
     140             :   // Clear the stack limits to make the snapshot reproducible.
     141             :   // Reset it again afterwards.
     142         261 :   isolate->heap()->ClearStackLimits();
     143         261 :   isolate->heap()->IterateSmiRoots(this);
     144         261 :   isolate->heap()->SetStackLimits();
     145             :   // First visit immortal immovables to make sure they end up in the first page.
     146         261 :   isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
     147         261 : }
     148             : 
     149         196 : SerializedHandleChecker::SerializedHandleChecker(Isolate* isolate,
     150             :                                                  std::vector<Context>* contexts)
     151         392 :     : isolate_(isolate) {
     152         196 :   AddToSet(isolate->heap()->serialized_objects());
     153         427 :   for (auto const& context : *contexts) {
     154         231 :     AddToSet(context->serialized_objects());
     155             :   }
     156         196 : }
     157             : 
     158     1050771 : bool StartupSerializer::SerializeUsingReadOnlyObjectCache(
     159             :     SnapshotByteSink* sink, HeapObject obj) {
     160     2743689 :   return read_only_serializer_->SerializeUsingReadOnlyObjectCache(sink, obj);
     161             : }
     162             : 
     163      502891 : void StartupSerializer::SerializeUsingPartialSnapshotCache(
     164             :     SnapshotByteSink* sink, HeapObject obj) {
     165      502891 :   int cache_index = SerializeInObjectCache(obj);
     166             :   sink->Put(kPartialSnapshotCache, "PartialSnapshotCache");
     167      502891 :   sink->PutInt(cache_index, "partial_snapshot_cache_index");
     168      502891 : }
     169             : 
     170         427 : void SerializedHandleChecker::AddToSet(FixedArray serialized) {
     171             :   int length = serialized->length();
     172         682 :   for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i));
     173         427 : }
     174             : 
     175          20 : void SerializedHandleChecker::VisitRootPointers(Root root,
     176             :                                                 const char* description,
     177             :                                                 FullObjectSlot start,
     178             :                                                 FullObjectSlot end) {
     179          60 :   for (FullObjectSlot p = start; p < end; ++p) {
     180          40 :     if (serialized_.find(*p) != serialized_.end()) continue;
     181           0 :     PrintF("%s handle not serialized: ",
     182           0 :            root == Root::kGlobalHandles ? "global" : "eternal");
     183           0 :     (*p)->Print();
     184           0 :     ok_ = false;
     185             :   }
     186          20 : }
     187             : 
     188         196 : bool SerializedHandleChecker::CheckGlobalAndEternalHandles() {
     189         196 :   isolate_->global_handles()->IterateAllRoots(this);
     190         196 :   isolate_->eternal_handles()->IterateAllRoots(this);
     191         196 :   return ok_;
     192             : }
     193             : 
     194             : }  // namespace internal
     195      121996 : }  // namespace v8

Generated by: LCOV version 1.10