LCOV - code coverage report
Current view: top level - src/snapshot - snapshot-common.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 153 158 96.8 %
Date: 2017-10-20 Functions: 20 20 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/objects-inl.h"
      12             : #include "src/snapshot/builtin-deserializer.h"
      13             : #include "src/snapshot/builtin-serializer.h"
      14             : #include "src/snapshot/partial-deserializer.h"
      15             : #include "src/snapshot/snapshot-source-sink.h"
      16             : #include "src/snapshot/startup-deserializer.h"
      17             : #include "src/utils.h"
      18             : #include "src/version.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23             : #ifdef DEBUG
      24             : bool Snapshot::SnapshotIsValid(const v8::StartupData* snapshot_blob) {
      25             :   return Snapshot::ExtractNumContexts(snapshot_blob) > 0;
      26             : }
      27             : #endif  // DEBUG
      28             : 
      29          38 : bool Snapshot::HasContextSnapshot(Isolate* isolate, size_t index) {
      30             :   // Do not use snapshots if the isolate is used to create snapshots.
      31             :   const v8::StartupData* blob = isolate->snapshot_blob();
      32          38 :   if (blob == nullptr) return false;
      33          38 :   if (blob->data == nullptr) return false;
      34          38 :   size_t num_contexts = static_cast<size_t>(ExtractNumContexts(blob));
      35          38 :   return index < num_contexts;
      36             : }
      37             : 
      38      109875 : bool Snapshot::Initialize(Isolate* isolate) {
      39       54937 :   if (!isolate->snapshot_available()) return false;
      40             :   base::ElapsedTimer timer;
      41       54938 :   if (FLAG_profile_deserialization) timer.Start();
      42             : 
      43             :   const v8::StartupData* blob = isolate->snapshot_blob();
      44       54938 :   CheckVersion(blob);
      45       54938 :   Vector<const byte> startup_data = ExtractStartupData(blob);
      46             :   SnapshotData startup_snapshot_data(startup_data);
      47       54938 :   Vector<const byte> builtin_data = ExtractBuiltinData(blob);
      48             :   BuiltinSnapshotData builtin_snapshot_data(builtin_data);
      49             :   StartupDeserializer deserializer(&startup_snapshot_data,
      50             :                                    &builtin_snapshot_data);
      51       54938 :   deserializer.SetRehashability(ExtractRehashability(blob));
      52       54938 :   bool success = isolate->Init(&deserializer);
      53       54938 :   if (FLAG_profile_deserialization) {
      54           5 :     double ms = timer.Elapsed().InMillisecondsF();
      55             :     int bytes = startup_data.length();
      56           5 :     PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms);
      57             :   }
      58             :   return success;
      59             : }
      60             : 
      61       83556 : MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
      62      167092 :     Isolate* isolate, Handle<JSGlobalProxy> global_proxy, size_t context_index,
      63             :     v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
      64       83556 :   if (!isolate->snapshot_available()) return Handle<Context>();
      65             :   base::ElapsedTimer timer;
      66       83536 :   if (FLAG_profile_deserialization) timer.Start();
      67             : 
      68             :   const v8::StartupData* blob = isolate->snapshot_blob();
      69       83536 :   bool can_rehash = ExtractRehashability(blob);
      70             :   Vector<const byte> context_data =
      71       83536 :       ExtractContextData(blob, static_cast<uint32_t>(context_index));
      72             :   SnapshotData snapshot_data(context_data);
      73             : 
      74             :   MaybeHandle<Context> maybe_result = PartialDeserializer::DeserializeContext(
      75             :       isolate, &snapshot_data, can_rehash, global_proxy,
      76       83536 :       embedder_fields_deserializer);
      77             : 
      78             :   Handle<Context> result;
      79       83536 :   if (!maybe_result.ToHandle(&result)) return MaybeHandle<Context>();
      80             : 
      81       83536 :   if (FLAG_profile_deserialization) {
      82           5 :     double ms = timer.Elapsed().InMillisecondsF();
      83             :     int bytes = context_data.length();
      84             :     PrintF("[Deserializing context #%zu (%d bytes) took %0.3f ms]\n",
      85           5 :            context_index, bytes, ms);
      86             :   }
      87       83536 :   return result;
      88             : }
      89             : 
      90             : // static
      91      201524 : Code* Snapshot::DeserializeBuiltin(Isolate* isolate, int builtin_id) {
      92             :   base::ElapsedTimer timer;
      93      100762 :   if (FLAG_profile_deserialization) timer.Start();
      94             : 
      95             :   const v8::StartupData* blob = isolate->snapshot_blob();
      96      100762 :   Vector<const byte> builtin_data = Snapshot::ExtractBuiltinData(blob);
      97             :   BuiltinSnapshotData builtin_snapshot_data(builtin_data);
      98             : 
      99      100762 :   CodeSpaceMemoryModificationScope code_allocation(isolate->heap());
     100      100762 :   BuiltinDeserializer builtin_deserializer(isolate, &builtin_snapshot_data);
     101      100762 :   Code* code = builtin_deserializer.DeserializeBuiltin(builtin_id);
     102             :   DCHECK_EQ(code, isolate->builtins()->builtin(builtin_id));
     103             : 
     104      100762 :   if (FLAG_profile_deserialization) {
     105           0 :     double ms = timer.Elapsed().InMillisecondsF();
     106           0 :     int bytes = code->Size();
     107             :     PrintF("[Deserializing builtin %s (%d bytes) took %0.3f ms]\n",
     108           0 :            Builtins::name(builtin_id), bytes, ms);
     109             :   }
     110             : 
     111      100762 :   return code;
     112             : }
     113             : 
     114         121 : void ProfileDeserialization(
     115             :     const SnapshotData* startup_snapshot, const SnapshotData* builtin_snapshot,
     116          10 :     const std::vector<SnapshotData*>& context_snapshots) {
     117         121 :   if (FLAG_profile_deserialization) {
     118             :     int startup_total = 0;
     119           5 :     PrintF("Deserialization will reserve:\n");
     120          30 :     for (const auto& reservation : startup_snapshot->Reservations()) {
     121          25 :       startup_total += reservation.chunk_size();
     122             :     }
     123           5 :     for (const auto& reservation : builtin_snapshot->Reservations()) {
     124           0 :       startup_total += reservation.chunk_size();
     125             :     }
     126           5 :     PrintF("%10d bytes per isolate\n", startup_total);
     127          20 :     for (size_t i = 0; i < context_snapshots.size(); i++) {
     128             :       int context_total = 0;
     129          35 :       for (const auto& reservation : context_snapshots[i]->Reservations()) {
     130          25 :         context_total += reservation.chunk_size();
     131             :       }
     132           5 :       PrintF("%10d bytes per context #%zu\n", context_total, i);
     133             :     }
     134             :   }
     135         121 : }
     136             : 
     137         121 : v8::StartupData Snapshot::CreateSnapshotBlob(
     138         242 :     const SnapshotData* startup_snapshot,
     139             :     const BuiltinSnapshotData* builtin_snapshot,
     140         262 :     const std::vector<SnapshotData*>& context_snapshots, bool can_be_rehashed) {
     141         121 :   uint32_t num_contexts = static_cast<uint32_t>(context_snapshots.size());
     142         121 :   uint32_t startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
     143             :   uint32_t total_length = startup_snapshot_offset;
     144         121 :   total_length += static_cast<uint32_t>(startup_snapshot->RawData().length());
     145         242 :   total_length += static_cast<uint32_t>(builtin_snapshot->RawData().length());
     146         383 :   for (const auto context_snapshot : context_snapshots) {
     147         141 :     total_length += static_cast<uint32_t>(context_snapshot->RawData().length());
     148             :   }
     149             : 
     150         121 :   ProfileDeserialization(startup_snapshot, builtin_snapshot, context_snapshots);
     151             : 
     152         121 :   char* data = new char[total_length];
     153             :   SetHeaderValue(data, kNumberOfContextsOffset, num_contexts);
     154         121 :   SetHeaderValue(data, kRehashabilityOffset, can_be_rehashed ? 1 : 0);
     155             : 
     156             :   // Write version string into snapshot data.
     157         121 :   memset(data + kVersionStringOffset, 0, kVersionStringLength);
     158             :   Version::GetString(
     159         121 :       Vector<char>(data + kVersionStringOffset, kVersionStringLength));
     160             : 
     161             :   // Startup snapshot (isolate-specific data).
     162             :   uint32_t payload_offset = startup_snapshot_offset;
     163             :   uint32_t payload_length =
     164             :       static_cast<uint32_t>(startup_snapshot->RawData().length());
     165             :   CopyBytes(data + payload_offset,
     166             :             reinterpret_cast<const char*>(startup_snapshot->RawData().start()),
     167         121 :             payload_length);
     168         121 :   if (FLAG_profile_deserialization) {
     169             :     PrintF("Snapshot blob consists of:\n%10d bytes for startup\n",
     170           5 :            payload_length);
     171             :   }
     172         121 :   payload_offset += payload_length;
     173             : 
     174             :   // Builtins.
     175             :   SetHeaderValue(data, kBuiltinOffsetOffset, payload_offset);
     176             :   payload_length = builtin_snapshot->RawData().length();
     177             :   CopyBytes(data + payload_offset,
     178             :             reinterpret_cast<const char*>(builtin_snapshot->RawData().start()),
     179         121 :             payload_length);
     180         121 :   if (FLAG_profile_deserialization) {
     181           5 :     PrintF("%10d bytes for builtins\n", payload_length);
     182             :   }
     183         121 :   payload_offset += payload_length;
     184             : 
     185             :   // Partial snapshots (context-specific data).
     186         262 :   for (uint32_t i = 0; i < num_contexts; i++) {
     187         141 :     SetHeaderValue(data, ContextSnapshotOffsetOffset(i), payload_offset);
     188         282 :     SnapshotData* context_snapshot = context_snapshots[i];
     189             :     payload_length = context_snapshot->RawData().length();
     190             :     CopyBytes(
     191             :         data + payload_offset,
     192             :         reinterpret_cast<const char*>(context_snapshot->RawData().start()),
     193         141 :         payload_length);
     194         141 :     if (FLAG_profile_deserialization) {
     195           5 :       PrintF("%10d bytes for context #%d\n", payload_length, i);
     196             :     }
     197         141 :     payload_offset += payload_length;
     198             :   }
     199             : 
     200         121 :   v8::StartupData result = {data, static_cast<int>(total_length)};
     201             :   DCHECK_EQ(total_length, payload_offset);
     202         121 :   return result;
     203             : }
     204             : 
     205      277024 : uint32_t Snapshot::ExtractNumContexts(const v8::StartupData* data) {
     206      277024 :   CHECK_LT(kNumberOfContextsOffset, data->raw_size);
     207             :   uint32_t num_contexts = GetHeaderValue(data, kNumberOfContextsOffset);
     208      138512 :   return num_contexts;
     209             : }
     210             : 
     211      167102 : uint32_t Snapshot::ExtractContextOffset(const v8::StartupData* data,
     212             :                                         uint32_t index) {
     213             :   // Extract the offset of the context at a given index from the StartupData,
     214             :   // and check that it is within bounds.
     215             :   uint32_t context_offset =
     216       83551 :       GetHeaderValue(data, ContextSnapshotOffsetOffset(index));
     217       83551 :   CHECK_LT(context_offset, static_cast<uint32_t>(data->raw_size));
     218       83551 :   return context_offset;
     219             : }
     220             : 
     221      276948 : bool Snapshot::ExtractRehashability(const v8::StartupData* data) {
     222      138474 :   CHECK_LT(kRehashabilityOffset, static_cast<uint32_t>(data->raw_size));
     223      138474 :   return GetHeaderValue(data, kRehashabilityOffset) != 0;
     224             : }
     225             : 
     226      109876 : Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
     227       54938 :   uint32_t num_contexts = ExtractNumContexts(data);
     228       54938 :   uint32_t startup_offset = StartupSnapshotOffset(num_contexts);
     229      109876 :   CHECK_LT(startup_offset, data->raw_size);
     230             :   uint32_t builtin_offset = GetHeaderValue(data, kBuiltinOffsetOffset);
     231       54938 :   CHECK_LT(builtin_offset, data->raw_size);
     232       54938 :   CHECK_GT(builtin_offset, startup_offset);
     233       54938 :   uint32_t startup_length = builtin_offset - startup_offset;
     234             :   const byte* startup_data =
     235       54938 :       reinterpret_cast<const byte*>(data->data + startup_offset);
     236       54938 :   return Vector<const byte>(startup_data, startup_length);
     237             : }
     238             : 
     239      155700 : Vector<const byte> Snapshot::ExtractBuiltinData(const v8::StartupData* data) {
     240             :   DCHECK(SnapshotIsValid(data));
     241             : 
     242             :   uint32_t from_offset = GetHeaderValue(data, kBuiltinOffsetOffset);
     243      311400 :   CHECK_LT(from_offset, data->raw_size);
     244             : 
     245             :   uint32_t to_offset = GetHeaderValue(data, ContextSnapshotOffsetOffset(0));
     246      155700 :   CHECK_LT(to_offset, data->raw_size);
     247             : 
     248      155700 :   CHECK_GT(to_offset, from_offset);
     249      155700 :   uint32_t length = to_offset - from_offset;
     250             :   const byte* builtin_data =
     251      155700 :       reinterpret_cast<const byte*>(data->data + from_offset);
     252      155700 :   return Vector<const byte>(builtin_data, length);
     253             : }
     254             : 
     255       83536 : Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
     256             :                                                 uint32_t index) {
     257       83536 :   uint32_t num_contexts = ExtractNumContexts(data);
     258       83536 :   CHECK_LT(index, num_contexts);
     259             : 
     260       83536 :   uint32_t context_offset = ExtractContextOffset(data, index);
     261             :   uint32_t next_context_offset;
     262       83536 :   if (index == num_contexts - 1) {
     263       83521 :     next_context_offset = data->raw_size;
     264             :   } else {
     265          15 :     next_context_offset = ExtractContextOffset(data, index + 1);
     266          30 :     CHECK_LT(next_context_offset, data->raw_size);
     267             :   }
     268             : 
     269             :   const byte* context_data =
     270       83536 :       reinterpret_cast<const byte*>(data->data + context_offset);
     271       83536 :   uint32_t context_length = next_context_offset - context_offset;
     272       83536 :   return Vector<const byte>(context_data, context_length);
     273             : }
     274             : 
     275       54937 : void Snapshot::CheckVersion(const v8::StartupData* data) {
     276             :   char version[kVersionStringLength];
     277             :   memset(version, 0, kVersionStringLength);
     278       54937 :   CHECK_LT(kVersionStringOffset + kVersionStringLength,
     279             :            static_cast<uint32_t>(data->raw_size));
     280       54937 :   Version::GetString(Vector<char>(version, kVersionStringLength));
     281      109876 :   if (memcmp(version, data->data + kVersionStringOffset,
     282      109876 :              kVersionStringLength) != 0) {
     283             :     V8_Fatal(__FILE__, __LINE__,
     284             :              "Version mismatch between V8 binary and snapshot.\n"
     285             :              "#   V8 binary version: %.*s\n"
     286             :              "#    Snapshot version: %.*s\n"
     287             :              "# The snapshot consists of %d bytes and contains %d context(s).",
     288             :              kVersionStringLength, version, kVersionStringLength,
     289             :              data->data + kVersionStringOffset, data->raw_size,
     290           0 :              ExtractNumContexts(data));
     291             :   }
     292       54938 : }
     293             : 
     294             : template <class AllocatorT>
     295        2365 : SnapshotData::SnapshotData(const Serializer<AllocatorT>* serializer) {
     296             :   DisallowHeapAllocation no_gc;
     297             :   std::vector<Reservation> reservations = serializer->EncodeReservations();
     298        1419 :   const std::vector<byte>* payload = serializer->Payload();
     299             : 
     300             :   // Calculate sizes.
     301             :   uint32_t reservation_size =
     302         946 :       static_cast<uint32_t>(reservations.size()) * kUInt32Size;
     303             :   uint32_t size =
     304         473 :       kHeaderSize + reservation_size + static_cast<uint32_t>(payload->size());
     305             : 
     306             :   // Allocate backing store and create result data.
     307         473 :   AllocateData(size);
     308             : 
     309             :   // Set header values.
     310         473 :   SetMagicNumber(serializer->isolate());
     311         946 :   SetHeaderValue(kNumReservationsOffset, static_cast<int>(reservations.size()));
     312         473 :   SetHeaderValue(kPayloadLengthOffset, static_cast<int>(payload->size()));
     313             : 
     314             :   // Copy reservation chunk sizes.
     315         473 :   CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.data()),
     316         946 :             reservation_size);
     317             : 
     318             :   // Copy serialized data.
     319         946 :   CopyBytes(data_ + kHeaderSize + reservation_size, payload->data(),
     320         946 :             static_cast<size_t>(payload->size()));
     321         473 : }
     322             : 
     323             : // Explicit instantiation.
     324             : template SnapshotData::SnapshotData(
     325             :     const Serializer<DefaultSerializerAllocator>* serializer);
     326             : 
     327      239311 : Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
     328             :   return Vector<const Reservation>(
     329             :       reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
     330      588528 :       GetHeaderValue(kNumReservationsOffset));
     331             : }
     332             : 
     333      138519 : Vector<const byte> SnapshotData::Payload() const {
     334             :   uint32_t reservations_size =
     335      277038 :       GetHeaderValue(kNumReservationsOffset) * kUInt32Size;
     336      138519 :   const byte* payload = data_ + kHeaderSize + reservations_size;
     337             :   uint32_t length = GetHeaderValue(kPayloadLengthOffset);
     338             :   DCHECK_EQ(data_ + size_, payload + length);
     339      138519 :   return Vector<const byte>(payload, length);
     340             : }
     341             : 
     342         161 : BuiltinSnapshotData::BuiltinSnapshotData(const BuiltinSerializer* serializer)
     343         161 :     : SnapshotData(serializer) {}
     344             : 
     345      155730 : Vector<const byte> BuiltinSnapshotData::Payload() const {
     346             :   uint32_t reservations_size =
     347      311460 :       GetHeaderValue(kNumReservationsOffset) * kUInt32Size;
     348      155730 :   const byte* payload = data_ + kHeaderSize + reservations_size;
     349             :   int builtin_offsets_size = Builtins::builtin_count * kUInt32Size;
     350             :   uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
     351             :   DCHECK_EQ(data_ + size_, payload + payload_length);
     352             :   DCHECK_GT(payload_length, builtin_offsets_size);
     353      155730 :   return Vector<const byte>(payload, payload_length - builtin_offsets_size);
     354             : }
     355             : 
     356      155730 : Vector<const uint32_t> BuiltinSnapshotData::BuiltinOffsets() const {
     357             :   uint32_t reservations_size =
     358      311460 :       GetHeaderValue(kNumReservationsOffset) * kUInt32Size;
     359      155730 :   const byte* payload = data_ + kHeaderSize + reservations_size;
     360             :   int builtin_offsets_size = Builtins::builtin_count * kUInt32Size;
     361             :   uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
     362             :   DCHECK_EQ(data_ + size_, payload + payload_length);
     363             :   DCHECK_GT(payload_length, builtin_offsets_size);
     364             :   const uint32_t* data = reinterpret_cast<const uint32_t*>(
     365      155730 :       payload + payload_length - builtin_offsets_size);
     366      155730 :   return Vector<const uint32_t>(data, Builtins::builtin_count);
     367             : }
     368             : 
     369             : }  // namespace internal
     370             : }  // namespace v8

Generated by: LCOV version 1.10