LCOV - code coverage report
Current view: top level - src/snapshot - startup-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 74 95.9 %
Date: 2019-01-20 Functions: 14 15 93.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/global-handles.h"
      11             : #include "src/objects-inl.h"
      12             : #include "src/objects/foreign-inl.h"
      13             : #include "src/objects/slots.h"
      14             : #include "src/snapshot/read-only-serializer.h"
      15             : #include "src/v8threads.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20         251 : StartupSerializer::StartupSerializer(Isolate* isolate,
      21             :                                      ReadOnlySerializer* read_only_serializer)
      22             :     : RootsSerializer(isolate, RootIndex::kFirstStrongRoot),
      23         251 :       read_only_serializer_(read_only_serializer) {
      24         251 :   InitializeCodeAddressMap();
      25         251 : }
      26             : 
      27         251 : StartupSerializer::~StartupSerializer() {
      28         251 :   RestoreExternalReferenceRedirectors(accessor_infos_);
      29         251 :   RestoreExternalReferenceRedirectors(call_handler_infos_);
      30         251 :   OutputStatistics("StartupSerializer");
      31         251 : }
      32             : 
      33             : namespace {
      34             : 
      35             : // Due to how we currently create the embedded blob, we may encounter both
      36             : // off-heap trampolines and old, outdated full Code objects during
      37             : // serialization. This ensures that we only serialize the canonical version of
      38             : // each builtin.
      39             : // See also CreateOffHeapTrampolines().
      40     4944775 : HeapObject MaybeCanonicalizeBuiltin(Isolate* isolate, HeapObject obj) {
      41     4944775 :   if (!obj->IsCode()) return obj;
      42             : 
      43             :   const int builtin_index = Code::cast(obj)->builtin_index();
      44      481550 :   if (!Builtins::IsBuiltinId(builtin_index)) return obj;
      45             : 
      46      481522 :   return isolate->builtins()->builtin(builtin_index);
      47             : }
      48             : 
      49             : }  // namespace
      50             : 
      51     4944775 : void StartupSerializer::SerializeObject(HeapObject obj, HowToCode how_to_code,
      52             :                                         WhereToPoint where_to_point, int skip) {
      53             :   DCHECK(!obj->IsJSFunction());
      54             : 
      55             :   // TODO(jgruber): Remove canonicalization once off-heap trampoline creation
      56             :   // moves to Isolate::Init().
      57     4946649 :   obj = MaybeCanonicalizeBuiltin(isolate(), obj);
      58             : 
      59     8790912 :   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
      60     5536104 :   if (IsRootAndHasBeenSerialized(obj) &&
      61     1959949 :       SerializeRoot(obj, how_to_code, where_to_point, skip))
      62             :     return;
      63     1616206 :   if (SerializeUsingReadOnlyObjectCache(&sink_, obj, how_to_code,
      64     1616206 :                                         where_to_point, skip))
      65             :     return;
      66     1507732 :   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
      67             : 
      68             :   FlushSkip(skip);
      69             :   bool use_simulator = false;
      70             : #ifdef USE_SIMULATOR
      71             :   use_simulator = true;
      72             : #endif
      73             : 
      74             :   if (use_simulator && obj->IsAccessorInfo()) {
      75             :     // Wipe external reference redirects in the accessor info.
      76             :     AccessorInfo info = AccessorInfo::cast(obj);
      77             :     Address original_address = Foreign::cast(info->getter())->foreign_address();
      78             :     Foreign::cast(info->js_getter())->set_foreign_address(original_address);
      79             :     accessor_infos_.push_back(info);
      80             :   } else if (use_simulator && obj->IsCallHandlerInfo()) {
      81             :     CallHandlerInfo info = CallHandlerInfo::cast(obj);
      82             :     Address original_address =
      83             :         Foreign::cast(info->callback())->foreign_address();
      84             :     Foreign::cast(info->js_callback())->set_foreign_address(original_address);
      85             :     call_handler_infos_.push_back(info);
      86     1099391 :   } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
      87             :     Script::cast(obj)->set_context_data(
      88         220 :         ReadOnlyRoots(isolate()).uninitialized_symbol());
      89     1098528 :   } else if (obj->IsSharedFunctionInfo()) {
      90             :     // Clear inferred name for native functions.
      91      169999 :     SharedFunctionInfo shared = SharedFunctionInfo::cast(obj);
      92      169999 :     if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) {
      93             :       shared->uncompiled_data()->set_inferred_name(
      94        1764 :           ReadOnlyRoots(isolate()).empty_string());
      95             :     }
      96             :   }
      97             : 
      98     1098638 :   CheckRehashability(obj);
      99             : 
     100             :   // Object has not yet been serialized.  Serialize it here.
     101             :   DCHECK(!isolate()->heap()->read_only_space()->Contains(obj));
     102             :   ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
     103             :                                      where_to_point);
     104     1098638 :   object_serializer.Serialize();
     105             : }
     106             : 
     107         251 : void StartupSerializer::SerializeWeakReferencesAndDeferred() {
     108             :   // This comes right after serialization of the partial snapshot, where we
     109             :   // add entries to the partial snapshot cache of the startup snapshot. Add
     110             :   // one entry with 'undefined' to terminate the partial snapshot cache.
     111         753 :   Object undefined = ReadOnlyRoots(isolate()).undefined_value();
     112             :   VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
     113         502 :                    FullObjectSlot(&undefined));
     114         251 :   isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
     115         251 :   SerializeDeferredObjects();
     116         251 :   Pad();
     117         251 : }
     118             : 
     119         251 : void StartupSerializer::SerializeStrongReferences() {
     120         502 :   Isolate* isolate = this->isolate();
     121             :   // No active threads.
     122         251 :   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
     123             :   // No active or weak handles.
     124         251 :   CHECK(isolate->handle_scope_implementer()->blocks()->empty());
     125             : 
     126             :   // Visit smi roots.
     127             :   // Clear the stack limits to make the snapshot reproducible.
     128             :   // Reset it again afterwards.
     129         251 :   isolate->heap()->ClearStackLimits();
     130         251 :   isolate->heap()->IterateSmiRoots(this);
     131         251 :   isolate->heap()->SetStackLimits();
     132             :   // First visit immortal immovables to make sure they end up in the first page.
     133         251 :   isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
     134         251 : }
     135             : 
     136         186 : SerializedHandleChecker::SerializedHandleChecker(Isolate* isolate,
     137             :                                                  std::vector<Context>* contexts)
     138         372 :     : isolate_(isolate) {
     139         186 :   AddToSet(isolate->heap()->serialized_objects());
     140         593 :   for (auto const& context : *contexts) {
     141         221 :     AddToSet(context->serialized_objects());
     142             :   }
     143         186 : }
     144             : 
     145      997802 : bool StartupSerializer::SerializeUsingReadOnlyObjectCache(
     146             :     SnapshotByteSink* sink, HeapObject obj, HowToCode how_to_code,
     147             :     WhereToPoint where_to_point, int skip) {
     148             :   return read_only_serializer_->SerializeUsingReadOnlyObjectCache(
     149     2614008 :       sink, obj, how_to_code, where_to_point, skip);
     150             : }
     151             : 
     152      481210 : void StartupSerializer::SerializeUsingPartialSnapshotCache(
     153             :     SnapshotByteSink* sink, HeapObject obj, HowToCode how_to_code,
     154             :     WhereToPoint where_to_point, int skip) {
     155      481210 :   FlushSkip(sink, skip);
     156             : 
     157      481210 :   int cache_index = SerializeInObjectCache(obj);
     158             :   sink->Put(kPartialSnapshotCache + how_to_code + where_to_point,
     159      481210 :             "PartialSnapshotCache");
     160      481210 :   sink->PutInt(cache_index, "partial_snapshot_cache_index");
     161      481210 : }
     162             : 
     163         407 : void SerializedHandleChecker::AddToSet(FixedArray serialized) {
     164             :   int length = serialized->length();
     165         577 :   for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i));
     166         407 : }
     167             : 
     168          20 : void SerializedHandleChecker::VisitRootPointers(Root root,
     169             :                                                 const char* description,
     170             :                                                 FullObjectSlot start,
     171             :                                                 FullObjectSlot end) {
     172          60 :   for (FullObjectSlot p = start; p < end; ++p) {
     173          40 :     if (serialized_.find(*p) != serialized_.end()) continue;
     174             :     PrintF("%s handle not serialized: ",
     175           0 :            root == Root::kGlobalHandles ? "global" : "eternal");
     176           0 :     (*p)->Print();
     177           0 :     ok_ = false;
     178             :   }
     179          20 : }
     180             : 
     181         186 : bool SerializedHandleChecker::CheckGlobalAndEternalHandles() {
     182         372 :   isolate_->global_handles()->IterateAllRoots(this);
     183         372 :   isolate_->eternal_handles()->IterateAllRoots(this);
     184         186 :   return ok_;
     185             : }
     186             : 
     187             : }  // namespace internal
     188      183867 : }  // namespace v8

Generated by: LCOV version 1.10