LCOV - code coverage report
Current view: top level - src/snapshot - startup-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 62 65 95.4 %
Date: 2019-02-19 Functions: 13 14 92.9 %

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

Generated by: LCOV version 1.10