LCOV - code coverage report
Current view: top level - src/snapshot - partial-serializer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 63 63 100.0 %
Date: 2017-04-26 Functions: 6 7 85.7 %

          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/objects-inl.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13         139 : PartialSerializer::PartialSerializer(
      14             :     Isolate* isolate, StartupSerializer* startup_serializer,
      15             :     v8::SerializeEmbedderFieldsCallback callback)
      16             :     : Serializer(isolate),
      17             :       startup_serializer_(startup_serializer),
      18         278 :       serialize_embedder_fields_(callback) {
      19         139 :   InitializeCodeAddressMap();
      20         139 : }
      21             : 
      22         278 : PartialSerializer::~PartialSerializer() {
      23         139 :   OutputStatistics("PartialSerializer");
      24         139 : }
      25             : 
      26         139 : void PartialSerializer::Serialize(Object** o, bool include_global_proxy) {
      27         278 :   if ((*o)->IsContext()) {
      28         133 :     Context* context = Context::cast(*o);
      29         133 :     reference_map()->AddAttachedReference(context->global_proxy());
      30             :     // The bootstrap snapshot has a code-stub context. When serializing the
      31             :     // partial snapshot, it is chained into the weak context list on the isolate
      32             :     // and it's next context pointer may point to the code-stub context.  Clear
      33             :     // it before serializing, it will get re-added to the context list
      34             :     // explicitly when it's loaded.
      35         133 :     if (context->IsNativeContext()) {
      36             :       context->set(Context::NEXT_CONTEXT_LINK,
      37         133 :                    isolate_->heap()->undefined_value());
      38             :       DCHECK(!context->global_object()->IsUndefined(context->GetIsolate()));
      39             :       // Reset math random cache to get fresh random numbers.
      40             :       context->set_math_random_index(Smi::kZero);
      41         133 :       context->set_math_random_cache(isolate_->heap()->undefined_value());
      42             :     }
      43             :   }
      44         139 :   VisitRootPointer(Root::kPartialSnapshotCache, o);
      45         139 :   SerializeDeferredObjects();
      46         139 :   SerializeEmbedderFields();
      47         139 :   Pad();
      48         139 : }
      49             : 
      50     3130480 : void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
      51             :                                         WhereToPoint where_to_point, int skip) {
      52             :   if (obj->IsMap()) {
      53             :     // The code-caches link to context-specific code objects, which
      54             :     // the startup and context serializes cannot currently handle.
      55             :     DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
      56             :   }
      57             : 
      58             :   // Replace typed arrays by undefined.
      59     3130480 :   if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
      60             : 
      61     5706797 :   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
      62             : 
      63     2471613 :   int root_index = root_index_map_.Lookup(obj);
      64     2471613 :   if (root_index != RootIndexMap::kInvalidRootIndex) {
      65     1172549 :     PutRoot(root_index, obj, how_to_code, where_to_point, skip);
      66     1172549 :     return;
      67             :   }
      68             : 
      69     1299064 :   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
      70             : 
      71     1006447 :   if (ShouldBeInThePartialSnapshotCache(obj)) {
      72      452284 :     FlushSkip(skip);
      73             : 
      74      452284 :     int cache_index = startup_serializer_->PartialSnapshotCacheIndex(obj);
      75             :     sink_.Put(kPartialSnapshotCache + how_to_code + where_to_point,
      76      452284 :               "PartialSnapshotCache");
      77      452284 :     sink_.PutInt(cache_index, "partial_snapshot_cache_index");
      78      452284 :     return;
      79             :   }
      80             : 
      81             :   // Pointers from the partial snapshot to the objects in the startup snapshot
      82             :   // should go through the root array or through the partial snapshot cache.
      83             :   // If this is not the case you may have to add something to the root array.
      84             :   DCHECK(!startup_serializer_->reference_map()->Lookup(obj).is_valid());
      85             :   // All the internalized strings that the partial snapshot needs should be
      86             :   // either in the root table or in the partial snapshot cache.
      87             :   DCHECK(!obj->IsInternalizedString());
      88             :   // Function and object templates are not context specific.
      89             :   DCHECK(!obj->IsTemplateInfo());
      90             : 
      91      554163 :   FlushSkip(skip);
      92             : 
      93             :   // Clear literal boilerplates.
      94      554163 :   if (obj->IsJSFunction()) {
      95             :     JSFunction* function = JSFunction::cast(obj);
      96      160111 :     function->ClearTypeFeedbackInfo();
      97             :   }
      98             : 
      99      554163 :   if (obj->IsJSObject()) {
     100             :     JSObject* jsobj = JSObject::cast(obj);
     101      232448 :     if (jsobj->GetEmbedderFieldCount() > 0) {
     102             :       DCHECK_NOT_NULL(serialize_embedder_fields_.callback);
     103          60 :       embedder_field_holders_.Add(jsobj);
     104             :     }
     105             :   }
     106             : 
     107             :   // Object has not yet been serialized.  Serialize it here.
     108      554163 :   ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point);
     109      554163 :   serializer.Serialize();
     110             : }
     111             : 
     112     1006447 : 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     2407652 :   return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
     119     1719104 :          o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
     120     1560616 :          o->IsTemplateInfo() ||
     121             :          o->map() ==
     122     1560616 :              startup_serializer_->isolate()->heap()->fixed_cow_array_map();
     123             : }
     124             : 
     125         139 : void PartialSerializer::SerializeEmbedderFields() {
     126         211 :   int count = embedder_field_holders_.length();
     127         266 :   if (count == 0) return;
     128             :   DisallowHeapAllocation no_gc;
     129          72 :   DisallowJavascriptExecution no_js(isolate());
     130             :   DisallowCompilation no_compile(isolate());
     131             :   DCHECK_NOT_NULL(serialize_embedder_fields_.callback);
     132             :   sink_.Put(kEmbedderFieldsData, "embedder fields data");
     133          72 :   while (embedder_field_holders_.length() > 0) {
     134             :     HandleScope scope(isolate());
     135          60 :     Handle<JSObject> obj(embedder_field_holders_.RemoveLast(), isolate());
     136          60 :     SerializerReference reference = reference_map_.Lookup(*obj);
     137             :     DCHECK(reference.is_back_reference());
     138          60 :     int embedder_fields_count = obj->GetEmbedderFieldCount();
     139         216 :     for (int i = 0; i < embedder_fields_count; i++) {
     140         294 :       if (obj->GetEmbedderField(i)->IsHeapObject()) continue;
     141             :       StartupData data = serialize_embedder_fields_.callback(
     142          18 :           v8::Utils::ToLocal(obj), i, serialize_embedder_fields_.data);
     143             :       sink_.Put(kNewObject + reference.space(), "embedder field holder");
     144          18 :       PutBackReference(*obj, reference);
     145          18 :       sink_.PutInt(i, "embedder field index");
     146          18 :       sink_.PutInt(data.raw_size, "embedder fields data size");
     147             :       sink_.PutRaw(reinterpret_cast<const byte*>(data.data), data.raw_size,
     148          18 :                    "embedder fields data");
     149          18 :       delete[] data.data;
     150             :     }
     151             :   }
     152          12 :   sink_.Put(kSynchronize, "Finished with embedder fields data");
     153             : }
     154             : 
     155             : }  // namespace internal
     156             : }  // namespace v8

Generated by: LCOV version 1.10