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#ifndef V8_SNAPSHOT_CODE_SERIALIZER_H_
6#define V8_SNAPSHOT_CODE_SERIALIZER_H_
7
8#include "src/parsing/preparse-data.h"
9#include "src/snapshot/serializer.h"
10
11namespace v8 {
12namespace internal {
13
14class CodeSerializer : public Serializer {
15 public:
16  static ScriptData* Serialize(Isolate* isolate,
17                               Handle<SharedFunctionInfo> info,
18                               Handle<String> source);
19
20  ScriptData* Serialize(Handle<HeapObject> obj);
21
22  MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize(
23      Isolate* isolate, ScriptData* cached_data, Handle<String> source);
24
25  const List<uint32_t>* stub_keys() const { return &stub_keys_; }
26
27  uint32_t source_hash() const { return source_hash_; }
28
29 protected:
30  explicit CodeSerializer(Isolate* isolate, uint32_t source_hash)
31      : Serializer(isolate), source_hash_(source_hash) {}
32  ~CodeSerializer() override { OutputStatistics("CodeSerializer"); }
33
34  virtual void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
35                                   WhereToPoint where_to_point) {
36    UNREACHABLE();
37  }
38
39  virtual bool ElideObject(Object* obj) { return false; }
40  void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code,
41                        WhereToPoint where_to_point);
42
43 private:
44  void SerializeObject(HeapObject* o, HowToCode how_to_code,
45                       WhereToPoint where_to_point, int skip) override;
46
47  void SerializeBuiltin(int builtin_index, HowToCode how_to_code,
48                        WhereToPoint where_to_point);
49  void SerializeCodeStub(Code* code_stub, HowToCode how_to_code,
50                         WhereToPoint where_to_point);
51
52  DisallowHeapAllocation no_gc_;
53  uint32_t source_hash_;
54  List<uint32_t> stub_keys_;
55  DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
56};
57
58class WasmCompiledModuleSerializer : public CodeSerializer {
59 public:
60  static std::unique_ptr<ScriptData> SerializeWasmModule(
61      Isolate* isolate, Handle<FixedArray> compiled_module);
62  static MaybeHandle<FixedArray> DeserializeWasmModule(
63      Isolate* isolate, ScriptData* data, Vector<const byte> wire_bytes);
64
65 protected:
66  void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
67                           WhereToPoint where_to_point) override {
68    Code::Kind kind = code_object->kind();
69    if (kind == Code::WASM_FUNCTION || kind == Code::WASM_TO_JS_FUNCTION ||
70        kind == Code::JS_TO_WASM_FUNCTION) {
71      SerializeGeneric(code_object, how_to_code, where_to_point);
72    } else {
73      UNREACHABLE();
74    }
75  }
76
77  bool ElideObject(Object* obj) override {
78    return obj->IsWeakCell() || obj->IsForeign();
79  };
80
81 private:
82  WasmCompiledModuleSerializer(Isolate* isolate, uint32_t source_hash)
83      : CodeSerializer(isolate, source_hash) {}
84  DISALLOW_COPY_AND_ASSIGN(WasmCompiledModuleSerializer);
85};
86
87// Wrapper around ScriptData to provide code-serializer-specific functionality.
88class SerializedCodeData : public SerializedData {
89 public:
90  enum SanityCheckResult {
91    CHECK_SUCCESS = 0,
92    MAGIC_NUMBER_MISMATCH = 1,
93    VERSION_MISMATCH = 2,
94    SOURCE_MISMATCH = 3,
95    CPU_FEATURES_MISMATCH = 4,
96    FLAGS_MISMATCH = 5,
97    CHECKSUM_MISMATCH = 6,
98    INVALID_HEADER = 7
99  };
100
101  // The data header consists of uint32_t-sized entries:
102  // [0] magic number and external reference count
103  // [1] version hash
104  // [2] source hash
105  // [3] cpu features
106  // [4] flag hash
107  // [5] number of code stub keys
108  // [6] number of reservation size entries
109  // [7] payload length
110  // [8] payload checksum part 1
111  // [9] payload checksum part 2
112  // ...  reservations
113  // ...  code stub keys
114  // ...  serialized payload
115  static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size;
116  static const int kSourceHashOffset = kVersionHashOffset + kInt32Size;
117  static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size;
118  static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size;
119  static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size;
120  static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size;
121  static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size;
122  static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size;
123  static const int kChecksum2Offset = kChecksum1Offset + kInt32Size;
124  static const int kHeaderSize = kChecksum2Offset + kInt32Size;
125
126  // Used when consuming.
127  static const SerializedCodeData FromCachedData(
128      Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash,
129      SanityCheckResult* rejection_result);
130
131  // Used when producing.
132  SerializedCodeData(const List<byte>* payload, const CodeSerializer* cs);
133
134  // Return ScriptData object and relinquish ownership over it to the caller.
135  ScriptData* GetScriptData();
136
137  Vector<const Reservation> Reservations() const;
138  Vector<const byte> Payload() const;
139
140  Vector<const uint32_t> CodeStubKeys() const;
141
142  static uint32_t SourceHash(Handle<String> source);
143
144 private:
145  explicit SerializedCodeData(ScriptData* data);
146  SerializedCodeData(const byte* data, int size)
147      : SerializedData(const_cast<byte*>(data), size) {}
148
149  Vector<const byte> DataWithoutHeader() const {
150    return Vector<const byte>(data_ + kHeaderSize, size_ - kHeaderSize);
151  }
152
153  SanityCheckResult SanityCheck(Isolate* isolate,
154                                uint32_t expected_source_hash) const;
155};
156
157}  // namespace internal
158}  // namespace v8
159
160#endif  // V8_SNAPSHOT_CODE_SERIALIZER_H_
161