aboutsummaryrefslogtreecommitdiff
path: root/src/snapshot/code-serializer.h
blob: 4d87a731f7587a1462fc506fbe440251762a948a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_SNAPSHOT_CODE_SERIALIZER_H_
#define V8_SNAPSHOT_CODE_SERIALIZER_H_

#include "src/parsing/preparse-data.h"
#include "src/snapshot/serializer.h"

namespace v8 {
namespace internal {

class CodeSerializer : public Serializer {
 public:
  static ScriptData* Serialize(Isolate* isolate,
                               Handle<SharedFunctionInfo> info,
                               Handle<String> source);

  ScriptData* Serialize(Handle<HeapObject> obj);

  MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize(
      Isolate* isolate, ScriptData* cached_data, Handle<String> source);

  const List<uint32_t>* stub_keys() const { return &stub_keys_; }

  uint32_t source_hash() const { return source_hash_; }

 protected:
  explicit CodeSerializer(Isolate* isolate, uint32_t source_hash)
      : Serializer(isolate), source_hash_(source_hash) {}
  ~CodeSerializer() override { OutputStatistics("CodeSerializer"); }

  virtual void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
                                   WhereToPoint where_to_point) {
    UNREACHABLE();
  }

  virtual bool ElideObject(Object* obj) { return false; }
  void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code,
                        WhereToPoint where_to_point);

 private:
  void SerializeObject(HeapObject* o, HowToCode how_to_code,
                       WhereToPoint where_to_point, int skip) override;

  void SerializeBuiltin(int builtin_index, HowToCode how_to_code,
                        WhereToPoint where_to_point);
  void SerializeCodeStub(Code* code_stub, HowToCode how_to_code,
                         WhereToPoint where_to_point);

  DisallowHeapAllocation no_gc_;
  uint32_t source_hash_;
  List<uint32_t> stub_keys_;
  DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
};

class WasmCompiledModuleSerializer : public CodeSerializer {
 public:
  static std::unique_ptr<ScriptData> SerializeWasmModule(
      Isolate* isolate, Handle<FixedArray> compiled_module);
  static MaybeHandle<FixedArray> DeserializeWasmModule(
      Isolate* isolate, ScriptData* data, Vector<const byte> wire_bytes);

 protected:
  void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
                           WhereToPoint where_to_point) override;
  bool ElideObject(Object* obj) override;

 private:
  WasmCompiledModuleSerializer(Isolate* isolate, uint32_t source_hash,
                               Handle<Context> native_context,
                               Handle<SeqOneByteString> module_bytes);
  DISALLOW_COPY_AND_ASSIGN(WasmCompiledModuleSerializer);
};

// Wrapper around ScriptData to provide code-serializer-specific functionality.
class SerializedCodeData : public SerializedData {
 public:
  enum SanityCheckResult {
    CHECK_SUCCESS = 0,
    MAGIC_NUMBER_MISMATCH = 1,
    VERSION_MISMATCH = 2,
    SOURCE_MISMATCH = 3,
    CPU_FEATURES_MISMATCH = 4,
    FLAGS_MISMATCH = 5,
    CHECKSUM_MISMATCH = 6,
    INVALID_HEADER = 7
  };

  // The data header consists of uint32_t-sized entries:
  // [0] magic number and external reference count
  // [1] version hash
  // [2] source hash
  // [3] cpu features
  // [4] flag hash
  // [5] number of code stub keys
  // [6] number of reservation size entries
  // [7] payload length
  // [8] payload checksum part 1
  // [9] payload checksum part 2
  // ...  reservations
  // ...  code stub keys
  // ...  serialized payload
  static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size;
  static const int kSourceHashOffset = kVersionHashOffset + kInt32Size;
  static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size;
  static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size;
  static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size;
  static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size;
  static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size;
  static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size;
  static const int kChecksum2Offset = kChecksum1Offset + kInt32Size;
  static const int kHeaderSize = kChecksum2Offset + kInt32Size;

  // Used when consuming.
  static const SerializedCodeData FromCachedData(
      Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash,
      SanityCheckResult* rejection_result);

  // Used when producing.
  SerializedCodeData(const List<byte>* payload, const CodeSerializer* cs);

  // Return ScriptData object and relinquish ownership over it to the caller.
  ScriptData* GetScriptData();

  Vector<const Reservation> Reservations() const;
  Vector<const byte> Payload() const;

  Vector<const uint32_t> CodeStubKeys() const;

  static uint32_t SourceHash(Handle<String> source);

 private:
  explicit SerializedCodeData(ScriptData* data);
  SerializedCodeData(const byte* data, int size)
      : SerializedData(const_cast<byte*>(data), size) {}

  Vector<const byte> DataWithoutHeader() const {
    return Vector<const byte>(data_ + kHeaderSize, size_ - kHeaderSize);
  }

  SanityCheckResult SanityCheck(Isolate* isolate,
                                uint32_t expected_source_hash) const;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_CODE_SERIALIZER_H_