LCOV - code coverage report
Current view: top level - src/snapshot - partial-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 71 100.0 %
Date: 2017-10-20 Functions: 7 8 87.5 %

          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/partial-serializer.h"
       6             : #include "src/snapshot/startup-serializer.h"
       7             : 
       8             : #include "src/api.h"
       9             : #include "src/objects-inl.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14         151 : PartialSerializer::PartialSerializer(
      15             :     Isolate* isolate, StartupSerializer* startup_serializer,
      16             :     v8::SerializeEmbedderFieldsCallback callback)
      17             :     : Serializer(isolate),
      18             :       startup_serializer_(startup_serializer),
      19             :       serialize_embedder_fields_(callback),
      20             :       rehashable_global_dictionary_(nullptr),
      21         302 :       can_be_rehashed_(true) {
      22         151 :   InitializeCodeAddressMap();
      23         151 : }
      24             : 
      25         302 : PartialSerializer::~PartialSerializer() {
      26         151 :   OutputStatistics("PartialSerializer");
      27         151 : }
      28             : 
      29         151 : void PartialSerializer::Serialize(Object** o, bool include_global_proxy) {
      30             :   DCHECK((*o)->IsNativeContext());
      31             : 
      32         151 :   Context* context = Context::cast(*o);
      33         302 :   reference_map()->AddAttachedReference(context->global_proxy());
      34             :   // The bootstrap snapshot has a code-stub context. When serializing the
      35             :   // partial snapshot, it is chained into the weak context list on the isolate
      36             :   // and it's next context pointer may point to the code-stub context.  Clear
      37             :   // it before serializing, it will get re-added to the context list
      38             :   // explicitly when it's loaded.
      39             :   context->set(Context::NEXT_CONTEXT_LINK,
      40         151 :                isolate()->heap()->undefined_value());
      41             :   DCHECK(!context->global_object()->IsUndefined(context->GetIsolate()));
      42             :   // Reset math random cache to get fresh random numbers.
      43             :   context->set_math_random_index(Smi::kZero);
      44         151 :   context->set_math_random_cache(isolate()->heap()->undefined_value());
      45             :   DCHECK_NULL(rehashable_global_dictionary_);
      46         302 :   rehashable_global_dictionary_ = context->global_object()->global_dictionary();
      47             : 
      48         151 :   VisitRootPointer(Root::kPartialSnapshotCache, o);
      49         151 :   SerializeDeferredObjects();
      50         151 :   SerializeEmbedderFields();
      51         151 :   Pad();
      52         151 : }
      53             : 
      54     2618614 : void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
      55             :                                         WhereToPoint where_to_point, int skip) {
      56             :   BuiltinReferenceSerializationMode mode =
      57     2618614 :       startup_serializer_->clear_function_code() ? kCanonicalizeCompileLazy
      58     2618614 :                                                  : kDefault;
      59     2628161 :   if (SerializeBuiltinReference(obj, how_to_code, where_to_point, skip, mode)) {
      60     2133277 :     return;
      61             :   }
      62     2457736 :   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
      63             : 
      64     1827383 :   int root_index = root_index_map()->Lookup(obj);
      65     1827383 :   if (root_index != RootIndexMap::kInvalidRootIndex) {
      66      832993 :     PutRoot(root_index, obj, how_to_code, where_to_point, skip);
      67      832993 :     return;
      68             :   }
      69             : 
      70      994390 :   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
      71             : 
      72      773247 :   if (ShouldBeInThePartialSnapshotCache(obj)) {
      73      287910 :     FlushSkip(skip);
      74             : 
      75      287910 :     int cache_index = startup_serializer_->PartialSnapshotCacheIndex(obj);
      76             :     sink_.Put(kPartialSnapshotCache + how_to_code + where_to_point,
      77      287910 :               "PartialSnapshotCache");
      78      287910 :     sink_.PutInt(cache_index, "partial_snapshot_cache_index");
      79      287910 :     return;
      80             :   }
      81             : 
      82             :   // Pointers from the partial snapshot to the objects in the startup snapshot
      83             :   // should go through the root array or through the partial snapshot cache.
      84             :   // If this is not the case you may have to add something to the root array.
      85             :   DCHECK(!startup_serializer_->ReferenceMapContains(obj));
      86             :   // All the internalized strings that the partial snapshot needs should be
      87             :   // either in the root table or in the partial snapshot cache.
      88             :   DCHECK(!obj->IsInternalizedString());
      89             :   // Function and object templates are not context specific.
      90             :   DCHECK(!obj->IsTemplateInfo());
      91             : 
      92      485337 :   FlushSkip(skip);
      93             : 
      94             :   // Clear literal boilerplates and feedback.
      95      494884 :   if (obj->IsFeedbackVector()) FeedbackVector::cast(obj)->ClearSlots(isolate());
      96             : 
      97      485337 :   if (obj->IsJSObject()) {
      98      223872 :     JSObject* jsobj = JSObject::cast(obj);
      99      223872 :     if (jsobj->GetEmbedderFieldCount() > 0) {
     100             :       DCHECK_NOT_NULL(serialize_embedder_fields_.callback);
     101         150 :       embedder_field_holders_.push_back(jsobj);
     102             :     }
     103             :   }
     104             : 
     105      485337 :   if (obj->IsHashTable()) CheckRehashability(obj);
     106             : 
     107             :   // Object has not yet been serialized.  Serialize it here.
     108      485337 :   ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point);
     109      485337 :   serializer.Serialize();
     110             : }
     111             : 
     112      773247 : bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) {
     113             :   // Scripts should be referred only through shared function infos.  We can't
     114             :   // allow them to be part of the partial snapshot because they contain a
     115             :   // unique ID, and deserializing several partial snapshots containing script
     116             :   // would cause dupes.
     117             :   DCHECK(!o->IsScript());
     118     1737229 :   return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
     119     1528415 :          o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
     120     1258589 :          o->IsTemplateInfo() ||
     121             :          o->map() ==
     122     1258589 :              startup_serializer_->isolate()->heap()->fixed_cow_array_map();
     123             : }
     124             : 
     125         151 : void PartialSerializer::SerializeEmbedderFields() {
     126         267 :   if (embedder_field_holders_.empty()) return;
     127             :   DisallowHeapAllocation no_gc;
     128         335 :   DisallowJavascriptExecution no_js(isolate());
     129             :   DisallowCompilation no_compile(isolate());
     130             :   DCHECK_NOT_NULL(serialize_embedder_fields_.callback);
     131             :   sink_.Put(kEmbedderFieldsData, "embedder fields data");
     132         185 :   while (!embedder_field_holders_.empty()) {
     133             :     HandleScope scope(isolate());
     134         150 :     Handle<JSObject> obj(embedder_field_holders_.back(), isolate());
     135             :     embedder_field_holders_.pop_back();
     136         150 :     SerializerReference reference = reference_map()->Lookup(*obj);
     137             :     DCHECK(reference.is_back_reference());
     138         150 :     int embedder_fields_count = obj->GetEmbedderFieldCount();
     139         480 :     for (int i = 0; i < embedder_fields_count; i++) {
     140         445 :       if (obj->GetEmbedderField(i)->IsHeapObject()) continue;
     141             : 
     142             :       StartupData data = serialize_embedder_fields_.callback(
     143         215 :           v8::Utils::ToLocal(obj), i, serialize_embedder_fields_.data);
     144             :       sink_.Put(kNewObject + reference.space(), "embedder field holder");
     145         215 :       PutBackReference(*obj, reference);
     146         215 :       sink_.PutInt(i, "embedder field index");
     147         215 :       sink_.PutInt(data.raw_size, "embedder fields data size");
     148             :       sink_.PutRaw(reinterpret_cast<const byte*>(data.data), data.raw_size,
     149         215 :                    "embedder fields data");
     150         215 :       delete[] data.data;
     151             :     }
     152             :   }
     153          35 :   sink_.Put(kSynchronize, "Finished with embedder fields data");
     154             : }
     155             : 
     156         327 : void PartialSerializer::CheckRehashability(HeapObject* table) {
     157             :   DCHECK(table->IsHashTable());
     158         327 :   if (!can_be_rehashed_) return;
     159         302 :   if (table->IsUnseededNumberDictionary()) return;
     160         176 :   if (table->IsOrderedHashMap() &&
     161             :       OrderedHashMap::cast(table)->NumberOfElements() == 0) {
     162             :     return;
     163             :   }
     164             :   // We can only correctly rehash if the global dictionary is the only hash
     165             :   // table that we deserialize.
     166         176 :   if (table == rehashable_global_dictionary_) return;
     167          25 :   can_be_rehashed_ = false;
     168             : }
     169             : 
     170             : }  // namespace internal
     171             : }  // namespace v8

Generated by: LCOV version 1.10