Home | History | Annotate | Download | only in snapshot
      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 #ifndef V8_SNAPSHOT_SNAPSHOT_H_
      6 #define V8_SNAPSHOT_SNAPSHOT_H_
      7 
      8 #include "src/snapshot/partial-serializer.h"
      9 #include "src/snapshot/startup-serializer.h"
     10 
     11 #include "src/utils.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 // Forward declarations.
     17 class Isolate;
     18 class BuiltinSerializer;
     19 class PartialSerializer;
     20 class StartupSerializer;
     21 
     22 // Wrapper around reservation sizes and the serialization payload.
     23 class SnapshotData : public SerializedData {
     24  public:
     25   // Used when producing.
     26   template <class AllocatorT>
     27   explicit SnapshotData(const Serializer<AllocatorT>* serializer);
     28 
     29   // Used when consuming.
     30   explicit SnapshotData(const Vector<const byte> snapshot)
     31       : SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) {
     32   }
     33 
     34   std::vector<Reservation> Reservations() const;
     35   virtual Vector<const byte> Payload() const;
     36 
     37   Vector<const byte> RawData() const {
     38     return Vector<const byte>(data_, size_);
     39   }
     40 
     41  protected:
     42   // The data header consists of uint32_t-sized entries:
     43   // [0] magic number and (internal) external reference count
     44   // [1] number of reservation size entries
     45   // [2] payload length
     46   // ... reservations
     47   // ... serialized payload
     48   static const uint32_t kNumReservationsOffset =
     49       kMagicNumberOffset + kUInt32Size;
     50   static const uint32_t kPayloadLengthOffset =
     51       kNumReservationsOffset + kUInt32Size;
     52   static const uint32_t kHeaderSize = kPayloadLengthOffset + kUInt32Size;
     53 };
     54 
     55 class BuiltinSnapshotData final : public SnapshotData {
     56  public:
     57   // Used when producing.
     58   // This simply forwards to the SnapshotData constructor.
     59   // The BuiltinSerializer appends the builtin offset table to the payload.
     60   explicit BuiltinSnapshotData(const BuiltinSerializer* serializer);
     61 
     62   // Used when consuming.
     63   explicit BuiltinSnapshotData(const Vector<const byte> snapshot)
     64       : SnapshotData(snapshot) {
     65   }
     66 
     67   // Returns the serialized payload without the builtin offsets table.
     68   Vector<const byte> Payload() const override;
     69 
     70   // Returns only the builtin offsets table.
     71   Vector<const uint32_t> BuiltinOffsets() const;
     72 
     73  private:
     74   // In addition to the format specified in SnapshotData, BuiltinsSnapshotData
     75   // includes a list of builtin at the end of the serialized payload:
     76   //
     77   // ...
     78   // ... serialized payload
     79   // ... list of builtins offsets
     80 };
     81 
     82 class EmbeddedData final {
     83  public:
     84   static EmbeddedData FromIsolate(Isolate* isolate);
     85   static EmbeddedData FromBlob();
     86 
     87   const uint8_t* data() const { return data_; }
     88   uint32_t size() const { return size_; }
     89 
     90   void Dispose() { delete[] data_; }
     91 
     92   Address InstructionStartOfBuiltin(int i) const;
     93   uint32_t InstructionSizeOfBuiltin(int i) const;
     94 
     95   bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; }
     96 
     97   // Padded with kCodeAlignment.
     98   uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
     99     return PadAndAlign(InstructionSizeOfBuiltin(i));
    100   }
    101 
    102   size_t CreateHash() const;
    103   size_t Hash() const {
    104     return *reinterpret_cast<const size_t*>(data_ + HashOffset());
    105   }
    106 
    107   struct Metadata {
    108     // Blob layout information.
    109     uint32_t instructions_offset;
    110     uint32_t instructions_length;
    111   };
    112   STATIC_ASSERT(offsetof(Metadata, instructions_offset) == 0);
    113   STATIC_ASSERT(offsetof(Metadata, instructions_length) == kUInt32Size);
    114   STATIC_ASSERT(sizeof(Metadata) == kUInt32Size + kUInt32Size);
    115 
    116   // The layout of the blob is as follows:
    117   //
    118   // [0] hash of the remaining blob
    119   // [1] metadata of instruction stream 0
    120   // ... metadata
    121   // ... instruction streams
    122 
    123   static constexpr uint32_t kTableSize = Builtins::builtin_count;
    124   static constexpr uint32_t HashOffset() { return 0; }
    125   static constexpr uint32_t HashSize() { return kSizetSize; }
    126   static constexpr uint32_t MetadataOffset() {
    127     return HashOffset() + HashSize();
    128   }
    129   static constexpr uint32_t MetadataSize() {
    130     return sizeof(struct Metadata) * kTableSize;
    131   }
    132   static constexpr uint32_t RawDataOffset() {
    133     return PadAndAlign(MetadataOffset() + MetadataSize());
    134   }
    135 
    136  private:
    137   EmbeddedData(const uint8_t* data, uint32_t size) : data_(data), size_(size) {}
    138 
    139   const Metadata* Metadata() const {
    140     return reinterpret_cast<const struct Metadata*>(data_ + MetadataOffset());
    141   }
    142   const uint8_t* RawData() const { return data_ + RawDataOffset(); }
    143 
    144   static constexpr int PadAndAlign(int size) {
    145     // Ensure we have at least one byte trailing the actual builtin
    146     // instructions which we can later fill with int3.
    147     return RoundUp<kCodeAlignment>(size + 1);
    148   }
    149 
    150   void PrintStatistics() const;
    151 
    152   const uint8_t* data_;
    153   uint32_t size_;
    154 };
    155 
    156 class Snapshot : public AllStatic {
    157  public:
    158   // ---------------- Deserialization ----------------
    159 
    160   // Initialize the Isolate from the internal snapshot. Returns false if no
    161   // snapshot could be found.
    162   static bool Initialize(Isolate* isolate);
    163 
    164   // Create a new context using the internal partial snapshot.
    165   static MaybeHandle<Context> NewContextFromSnapshot(
    166       Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
    167       size_t context_index,
    168       v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer);
    169 
    170   // Deserializes a single given builtin code object. Intended to be called at
    171   // runtime after the isolate (and the builtins table) has been fully
    172   // initialized.
    173   static Code* DeserializeBuiltin(Isolate* isolate, int builtin_id);
    174   static void EnsureAllBuiltinsAreDeserialized(Isolate* isolate);
    175   static Code* EnsureBuiltinIsDeserialized(Isolate* isolate,
    176                                            Handle<SharedFunctionInfo> shared);
    177 
    178   // Deserializes a single given handler code object. Intended to be called at
    179   // runtime after the isolate has been fully initialized.
    180   static Code* DeserializeHandler(Isolate* isolate,
    181                                   interpreter::Bytecode bytecode,
    182                                   interpreter::OperandScale operand_scale);
    183 
    184   // ---------------- Helper methods ----------------
    185 
    186   static bool HasContextSnapshot(Isolate* isolate, size_t index);
    187   static bool EmbedsScript(Isolate* isolate);
    188 
    189   // To be implemented by the snapshot source.
    190   static const v8::StartupData* DefaultSnapshotBlob();
    191 
    192   // ---------------- Serialization ----------------
    193 
    194   static v8::StartupData CreateSnapshotBlob(
    195       const SnapshotData* startup_snapshot,
    196       const BuiltinSnapshotData* builtin_snapshot,
    197       const std::vector<SnapshotData*>& context_snapshots,
    198       bool can_be_rehashed);
    199 
    200 #ifdef DEBUG
    201   static bool SnapshotIsValid(const v8::StartupData* snapshot_blob);
    202 #endif  // DEBUG
    203 
    204  private:
    205   static uint32_t ExtractNumContexts(const v8::StartupData* data);
    206   static uint32_t ExtractContextOffset(const v8::StartupData* data,
    207                                        uint32_t index);
    208   static bool ExtractRehashability(const v8::StartupData* data);
    209   static Vector<const byte> ExtractStartupData(const v8::StartupData* data);
    210   static Vector<const byte> ExtractBuiltinData(const v8::StartupData* data);
    211   static Vector<const byte> ExtractContextData(const v8::StartupData* data,
    212                                                uint32_t index);
    213 
    214   static uint32_t GetHeaderValue(const v8::StartupData* data, uint32_t offset) {
    215     return ReadLittleEndianValue<uint32_t>(
    216         reinterpret_cast<Address>(data->data) + offset);
    217   }
    218   static void SetHeaderValue(char* data, uint32_t offset, uint32_t value) {
    219     WriteLittleEndianValue(reinterpret_cast<Address>(data) + offset, value);
    220   }
    221 
    222   static void CheckVersion(const v8::StartupData* data);
    223 
    224   // Snapshot blob layout:
    225   // [0] number of contexts N
    226   // [1] rehashability
    227   // [2] (128 bytes) version string
    228   // [3] offset to builtins
    229   // [4] offset to context 0
    230   // [5] offset to context 1
    231   // ...
    232   // ... offset to context N - 1
    233   // ... startup snapshot data
    234   // ... builtin snapshot data
    235   // ... context 0 snapshot data
    236   // ... context 1 snapshot data
    237 
    238   static const uint32_t kNumberOfContextsOffset = 0;
    239   // TODO(yangguo): generalize rehashing, and remove this flag.
    240   static const uint32_t kRehashabilityOffset =
    241       kNumberOfContextsOffset + kUInt32Size;
    242   static const uint32_t kVersionStringOffset =
    243       kRehashabilityOffset + kUInt32Size;
    244   static const uint32_t kVersionStringLength = 64;
    245   static const uint32_t kBuiltinOffsetOffset =
    246       kVersionStringOffset + kVersionStringLength;
    247   static const uint32_t kFirstContextOffsetOffset =
    248       kBuiltinOffsetOffset + kUInt32Size;
    249 
    250   static uint32_t StartupSnapshotOffset(int num_contexts) {
    251     return kFirstContextOffsetOffset + num_contexts * kInt32Size;
    252   }
    253 
    254   static uint32_t ContextSnapshotOffsetOffset(int index) {
    255     return kFirstContextOffsetOffset + index * kInt32Size;
    256   }
    257 
    258   DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
    259 };
    260 
    261 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
    262 void SetSnapshotFromFile(StartupData* snapshot_blob);
    263 #endif
    264 
    265 }  // namespace internal
    266 }  // namespace v8
    267 
    268 #endif  // V8_SNAPSHOT_SNAPSHOT_H_
    269