LCOV - code coverage report
Current view: top level - src/snapshot - snapshot-common.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 114 114 100.0 %
Date: 2017-04-26 Functions: 12 12 100.0 %

          Line data    Source code
       1             : // Copyright 2006-2008 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             : // The common functionality when building with or without snapshots.
       6             : 
       7             : #include "src/snapshot/snapshot.h"
       8             : 
       9             : #include "src/api.h"
      10             : #include "src/base/platform/platform.h"
      11             : #include "src/full-codegen/full-codegen.h"
      12             : #include "src/objects-inl.h"
      13             : #include "src/snapshot/deserializer.h"
      14             : #include "src/snapshot/snapshot-source-sink.h"
      15             : #include "src/version.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : #ifdef DEBUG
      21             : bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) {
      22             :   return Snapshot::ExtractNumContexts(snapshot_blob) > 0;
      23             : }
      24             : #endif  // DEBUG
      25             : 
      26          45 : bool Snapshot::HasContextSnapshot(Isolate* isolate, size_t index) {
      27             :   // Do not use snapshots if the isolate is used to create snapshots.
      28             :   const v8::StartupData* blob = isolate->snapshot_blob();
      29          45 :   if (blob == nullptr) return false;
      30          45 :   if (blob->data == nullptr) return false;
      31          45 :   size_t num_contexts = static_cast<size_t>(ExtractNumContexts(blob));
      32          45 :   return index < num_contexts;
      33             : }
      34             : 
      35      121394 : bool Snapshot::Initialize(Isolate* isolate) {
      36       60697 :   if (!isolate->snapshot_available()) return false;
      37             :   base::ElapsedTimer timer;
      38       60697 :   if (FLAG_profile_deserialization) timer.Start();
      39             : 
      40             :   const v8::StartupData* blob = isolate->snapshot_blob();
      41       60697 :   Vector<const byte> startup_data = ExtractStartupData(blob);
      42       60697 :   SnapshotData snapshot_data(startup_data);
      43      121394 :   Deserializer deserializer(&snapshot_data);
      44       60697 :   bool success = isolate->Init(&deserializer);
      45       60697 :   if (FLAG_profile_deserialization) {
      46           6 :     double ms = timer.Elapsed().InMillisecondsF();
      47           6 :     int bytes = startup_data.length();
      48           6 :     PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms);
      49             :   }
      50             :   return success;
      51             : }
      52             : 
      53      106872 : MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
      54      213720 :     Isolate* isolate, Handle<JSGlobalProxy> global_proxy, size_t context_index,
      55             :     v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
      56      106872 :   if (!isolate->snapshot_available()) return Handle<Context>();
      57             :   base::ElapsedTimer timer;
      58      106848 :   if (FLAG_profile_deserialization) timer.Start();
      59             : 
      60             :   const v8::StartupData* blob = isolate->snapshot_blob();
      61             :   Vector<const byte> context_data =
      62      106848 :       ExtractContextData(blob, static_cast<int>(context_index));
      63      106848 :   SnapshotData snapshot_data(context_data);
      64      213696 :   Deserializer deserializer(&snapshot_data);
      65             : 
      66             :   MaybeHandle<Object> maybe_context = deserializer.DeserializePartial(
      67      106848 :       isolate, global_proxy, embedder_fields_deserializer);
      68             :   Handle<Object> result;
      69      106848 :   if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>();
      70      106848 :   CHECK(result->IsContext());
      71      106848 :   if (FLAG_profile_deserialization) {
      72           6 :     double ms = timer.Elapsed().InMillisecondsF();
      73           6 :     int bytes = context_data.length();
      74             :     PrintF("[Deserializing context #%zu (%d bytes) took %0.3f ms]\n",
      75           6 :            context_index, bytes, ms);
      76             :   }
      77             :   return Handle<Context>::cast(result);
      78             : }
      79             : 
      80          97 : void ProfileDeserialization(const SnapshotData* startup_snapshot,
      81          12 :                             const List<SnapshotData*>* context_snapshots) {
      82          97 :   if (FLAG_profile_deserialization) {
      83             :     int startup_total = 0;
      84           6 :     PrintF("Deserialization will reserve:\n");
      85          48 :     for (const auto& reservation : startup_snapshot->Reservations()) {
      86          42 :       startup_total += reservation.chunk_size();
      87             :     }
      88           6 :     PrintF("%10d bytes per isolate\n", startup_total);
      89          24 :     for (int i = 0; i < context_snapshots->length(); i++) {
      90             :       int context_total = 0;
      91          42 :       for (const auto& reservation : context_snapshots->at(i)->Reservations()) {
      92          30 :         context_total += reservation.chunk_size();
      93             :       }
      94           6 :       PrintF("%10d bytes per context #%d\n", context_total, i);
      95             :     }
      96             :   }
      97          97 : }
      98             : 
      99          97 : v8::StartupData Snapshot::CreateSnapshotBlob(
     100         194 :     const SnapshotData* startup_snapshot,
     101          97 :     const List<SnapshotData*>* context_snapshots) {
     102          97 :   int num_contexts = context_snapshots->length();
     103             :   int startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
     104             :   int total_length = startup_snapshot_offset;
     105          97 :   total_length += startup_snapshot->RawData().length();
     106         315 :   for (const auto& context_snapshot : *context_snapshots) {
     107         121 :     total_length += context_snapshot->RawData().length();
     108             :   }
     109             : 
     110          97 :   ProfileDeserialization(startup_snapshot, context_snapshots);
     111             : 
     112          97 :   char* data = new char[total_length];
     113             :   memcpy(data + kNumberOfContextsOffset, &num_contexts, kInt32Size);
     114          97 :   int payload_offset = StartupSnapshotOffset(num_contexts);
     115             :   int payload_length = startup_snapshot->RawData().length();
     116          97 :   memcpy(data + payload_offset, startup_snapshot->RawData().start(),
     117          97 :          payload_length);
     118          97 :   if (FLAG_profile_deserialization) {
     119             :     PrintF("Snapshot blob consists of:\n%10d bytes for startup\n",
     120           6 :            payload_length);
     121             :   }
     122          97 :   payload_offset += payload_length;
     123         315 :   for (int i = 0; i < num_contexts; i++) {
     124         121 :     memcpy(data + ContextSnapshotOffsetOffset(i), &payload_offset, kInt32Size);
     125         121 :     SnapshotData* context_snapshot = context_snapshots->at(i);
     126             :     payload_length = context_snapshot->RawData().length();
     127         121 :     memcpy(data + payload_offset, context_snapshot->RawData().start(),
     128         121 :            payload_length);
     129         121 :     if (FLAG_profile_deserialization) {
     130           6 :       PrintF("%10d bytes for context #%d\n", payload_length, i);
     131             :     }
     132         121 :     payload_offset += payload_length;
     133             :   }
     134             : 
     135             :   v8::StartupData result = {data, total_length};
     136          97 :   return result;
     137             : }
     138             : 
     139      167590 : int Snapshot::ExtractNumContexts(const v8::StartupData* data) {
     140      167590 :   CHECK_LT(kNumberOfContextsOffset, data->raw_size);
     141             :   int num_contexts;
     142      167590 :   memcpy(&num_contexts, data->data + kNumberOfContextsOffset, kInt32Size);
     143      167590 :   return num_contexts;
     144             : }
     145             : 
     146       60697 : Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
     147       60697 :   int num_contexts = ExtractNumContexts(data);
     148             :   int startup_offset = StartupSnapshotOffset(num_contexts);
     149       60697 :   CHECK_LT(startup_offset, data->raw_size);
     150             :   int first_context_offset;
     151             :   memcpy(&first_context_offset, data->data + ContextSnapshotOffsetOffset(0),
     152       60697 :          kInt32Size);
     153       60697 :   CHECK_LT(first_context_offset, data->raw_size);
     154       60697 :   int startup_length = first_context_offset - startup_offset;
     155             :   const byte* startup_data =
     156       60697 :       reinterpret_cast<const byte*>(data->data + startup_offset);
     157       60697 :   return Vector<const byte>(startup_data, startup_length);
     158             : }
     159             : 
     160      106848 : Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
     161             :                                                 int index) {
     162      106848 :   int num_contexts = ExtractNumContexts(data);
     163      106848 :   CHECK_LT(index, num_contexts);
     164             : 
     165             :   int context_offset;
     166      106848 :   memcpy(&context_offset, data->data + ContextSnapshotOffsetOffset(index),
     167      213696 :          kInt32Size);
     168             :   int next_context_offset;
     169      106848 :   if (index == num_contexts - 1) {
     170      106830 :     next_context_offset = data->raw_size;
     171             :   } else {
     172             :     memcpy(&next_context_offset,
     173          18 :            data->data + ContextSnapshotOffsetOffset(index + 1), kInt32Size);
     174          18 :     CHECK_LT(next_context_offset, data->raw_size);
     175             :   }
     176             : 
     177             :   const byte* context_data =
     178      106848 :       reinterpret_cast<const byte*>(data->data + context_offset);
     179      106848 :   int context_length = next_context_offset - context_offset;
     180      106848 :   return Vector<const byte>(context_data, context_length);
     181             : }
     182             : 
     183        1450 : SnapshotData::SnapshotData(const Serializer* serializer) {
     184             :   DisallowHeapAllocation no_gc;
     185             :   List<Reservation> reservations;
     186         290 :   serializer->EncodeReservations(&reservations);
     187        1160 :   const List<byte>* payload = serializer->sink()->data();
     188             : 
     189             :   // Calculate sizes.
     190         290 :   int reservation_size = reservations.length() * kInt32Size;
     191         580 :   int size = kHeaderSize + reservation_size + payload->length();
     192             : 
     193             :   // Allocate backing store and create result data.
     194         290 :   AllocateData(size);
     195             : 
     196             :   // Set header values.
     197         290 :   SetMagicNumber(serializer->isolate());
     198         290 :   SetHeaderValue(kVersionHashOffset, Version::Hash());
     199         290 :   SetHeaderValue(kNumReservationsOffset, reservations.length());
     200         290 :   SetHeaderValue(kPayloadLengthOffset, payload->length());
     201             : 
     202             :   // Copy reservation chunk sizes.
     203         290 :   CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
     204         580 :             reservation_size);
     205             : 
     206             :   // Copy serialized data.
     207         290 :   CopyBytes(data_ + kHeaderSize + reservation_size, payload->begin(),
     208         870 :             static_cast<size_t>(payload->length()));
     209         290 : }
     210             : 
     211          72 : bool SnapshotData::IsSane() {
     212      167689 :   return GetHeaderValue(kVersionHashOffset) == Version::Hash();
     213             : }
     214             : 
     215          72 : Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
     216             :   return Vector<const Reservation>(
     217             :       reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
     218      167713 :       GetHeaderValue(kNumReservationsOffset));
     219             : }
     220             : 
     221          72 : Vector<const byte> SnapshotData::Payload() const {
     222      335234 :   int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
     223      167617 :   const byte* payload = data_ + kHeaderSize + reservations_size;
     224      167617 :   int length = GetHeaderValue(kPayloadLengthOffset);
     225             :   DCHECK_EQ(data_ + size_, payload + length);
     226          72 :   return Vector<const byte>(payload, length);
     227             : }
     228             : 
     229             : }  // namespace internal
     230             : }  // namespace v8

Generated by: LCOV version 1.10