Home | History | Annotate | Download | only in snapshot
      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/global-handles.h"
     10 #include "src/objects-inl.h"
     11 #include "src/v8threads.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 StartupSerializer::StartupSerializer(Isolate* isolate)
     17     : Serializer(isolate), can_be_rehashed_(true) {
     18   InitializeCodeAddressMap();
     19 }
     20 
     21 StartupSerializer::~StartupSerializer() {
     22   RestoreExternalReferenceRedirectors(accessor_infos_);
     23   RestoreExternalReferenceRedirectors(call_handler_infos_);
     24   OutputStatistics("StartupSerializer");
     25 }
     26 
     27 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
     28                                         WhereToPoint where_to_point, int skip) {
     29   DCHECK(!ObjectIsBytecodeHandler(obj));  // Only referenced in dispatch table.
     30   DCHECK(!obj->IsJSFunction());
     31 
     32   if (SerializeBuiltinReference(obj, how_to_code, where_to_point, skip)) {
     33     return;
     34   }
     35   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
     36 
     37   int root_index = root_index_map()->Lookup(obj);
     38   // We can only encode roots as such if it has already been serialized.
     39   // That applies to root indices below the wave front.
     40   if (root_index != RootIndexMap::kInvalidRootIndex) {
     41     if (root_has_been_serialized(root_index)) {
     42       PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     43       return;
     44     }
     45   }
     46 
     47   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
     48 
     49   FlushSkip(skip);
     50   bool use_simulator = false;
     51 #ifdef USE_SIMULATOR
     52   use_simulator = true;
     53 #endif
     54 
     55   if (use_simulator && obj->IsAccessorInfo()) {
     56     // Wipe external reference redirects in the accessor info.
     57     AccessorInfo* info = AccessorInfo::cast(obj);
     58     Address original_address = Foreign::cast(info->getter())->foreign_address();
     59     Foreign::cast(info->js_getter())->set_foreign_address(original_address);
     60     accessor_infos_.push_back(info);
     61   } else if (use_simulator && obj->IsCallHandlerInfo()) {
     62     CallHandlerInfo* info = CallHandlerInfo::cast(obj);
     63     Address original_address =
     64         Foreign::cast(info->callback())->foreign_address();
     65     Foreign::cast(info->js_callback())->set_foreign_address(original_address);
     66     call_handler_infos_.push_back(info);
     67   } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
     68     Script::cast(obj)->set_context_data(
     69         ReadOnlyRoots(isolate()).uninitialized_symbol());
     70   } else if (obj->IsSharedFunctionInfo()) {
     71     // Clear inferred name for native functions.
     72     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
     73     if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) {
     74       shared->uncompiled_data()->set_inferred_name(
     75           ReadOnlyRoots(isolate()).empty_string());
     76     }
     77   }
     78 
     79   CheckRehashability(obj);
     80 
     81   // Object has not yet been serialized.  Serialize it here.
     82   ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
     83                                      where_to_point);
     84   object_serializer.Serialize();
     85 }
     86 
     87 void StartupSerializer::SerializeWeakReferencesAndDeferred() {
     88   // This comes right after serialization of the partial snapshot, where we
     89   // add entries to the partial snapshot cache of the startup snapshot. Add
     90   // one entry with 'undefined' to terminate the partial snapshot cache.
     91   Object* undefined = ReadOnlyRoots(isolate()).undefined_value();
     92   VisitRootPointer(Root::kPartialSnapshotCache, nullptr, &undefined);
     93   isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
     94   SerializeDeferredObjects();
     95   Pad();
     96 }
     97 
     98 int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
     99   int index;
    100   if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) {
    101     // This object is not part of the partial snapshot cache yet. Add it to the
    102     // startup snapshot so we can refer to it via partial snapshot index from
    103     // the partial snapshot.
    104     VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
    105                      reinterpret_cast<Object**>(&heap_object));
    106   }
    107   return index;
    108 }
    109 
    110 void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
    111   sink_.Put(kSynchronize, "Synchronize");
    112 }
    113 
    114 void StartupSerializer::SerializeStrongReferences() {
    115   Isolate* isolate = this->isolate();
    116   // No active threads.
    117   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
    118   // No active or weak handles.
    119   CHECK(isolate->handle_scope_implementer()->blocks()->empty());
    120 
    121   // Visit smi roots.
    122   // Clear the stack limits to make the snapshot reproducible.
    123   // Reset it again afterwards.
    124   isolate->heap()->ClearStackLimits();
    125   isolate->heap()->IterateSmiRoots(this);
    126   isolate->heap()->SetStackLimits();
    127   // First visit immortal immovables to make sure they end up in the first page.
    128   isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
    129 }
    130 
    131 void StartupSerializer::VisitRootPointers(Root root, const char* description,
    132                                           Object** start, Object** end) {
    133   if (start == isolate()->heap()->roots_array_start()) {
    134     // Serializing the root list needs special handling:
    135     // - Only root list elements that have been fully serialized can be
    136     //   referenced using kRootArray bytecodes.
    137     for (Object** current = start; current < end; current++) {
    138       SerializeRootObject(*current);
    139       int root_index = static_cast<int>(current - start);
    140       root_has_been_serialized_.set(root_index);
    141     }
    142   } else {
    143     Serializer::VisitRootPointers(root, description, start, end);
    144   }
    145 }
    146 
    147 void StartupSerializer::CheckRehashability(HeapObject* obj) {
    148   if (!can_be_rehashed_) return;
    149   if (!obj->NeedsRehashing()) return;
    150   if (obj->CanBeRehashed()) return;
    151   can_be_rehashed_ = false;
    152 }
    153 
    154 bool StartupSerializer::MustBeDeferred(HeapObject* object) {
    155   if (root_has_been_serialized_.test(Heap::kFreeSpaceMapRootIndex) &&
    156       root_has_been_serialized_.test(Heap::kOnePointerFillerMapRootIndex) &&
    157       root_has_been_serialized_.test(Heap::kTwoPointerFillerMapRootIndex)) {
    158     // All required root objects are serialized, so any aligned objects can
    159     // be saved without problems.
    160     return false;
    161   }
    162   // Just defer everything except of Map objects until all required roots are
    163   // serialized. Some objects may have special alignment requirements, that may
    164   // not be fulfilled during deserialization until few first root objects are
    165   // serialized. But we must serialize Map objects since deserializer checks
    166   // that these root objects are indeed Maps.
    167   return !object->IsMap();
    168 }
    169 
    170 SerializedHandleChecker::SerializedHandleChecker(
    171     Isolate* isolate, std::vector<Context*>* contexts)
    172     : isolate_(isolate) {
    173   AddToSet(isolate->heap()->serialized_objects());
    174   for (auto const& context : *contexts) {
    175     AddToSet(context->serialized_objects());
    176   }
    177 }
    178 
    179 void SerializedHandleChecker::AddToSet(FixedArray* serialized) {
    180   int length = serialized->length();
    181   for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i));
    182 }
    183 
    184 void SerializedHandleChecker::VisitRootPointers(Root root,
    185                                                 const char* description,
    186                                                 Object** start, Object** end) {
    187   for (Object** p = start; p < end; p++) {
    188     if (serialized_.find(*p) != serialized_.end()) continue;
    189     PrintF("%s handle not serialized: ",
    190            root == Root::kGlobalHandles ? "global" : "eternal");
    191     (*p)->Print();
    192     ok_ = false;
    193   }
    194 }
    195 
    196 bool SerializedHandleChecker::CheckGlobalAndEternalHandles() {
    197   isolate_->global_handles()->IterateAllRoots(this);
    198   isolate_->eternal_handles()->IterateAllRoots(this);
    199   return ok_;
    200 }
    201 
    202 }  // namespace internal
    203 }  // namespace v8
    204