1 // Copyright 2021 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 INCLUDE_V8_SNAPSHOT_H_
6 #define INCLUDE_V8_SNAPSHOT_H_
7
8 #include "v8-internal.h" // NOLINT(build/include_directory)
9 #include "v8-local-handle.h" // NOLINT(build/include_directory)
10 #include "v8config.h" // NOLINT(build/include_directory)
11
12 namespace v8 {
13
14 class Object;
15
16 class V8_EXPORT StartupData {
17 public:
18 /**
19 * Whether the data created can be rehashed and and the hash seed can be
20 * recomputed when deserialized.
21 * Only valid for StartupData returned by SnapshotCreator::CreateBlob().
22 */
23 bool CanBeRehashed() const;
24 /**
25 * Allows embedders to verify whether the data is valid for the current
26 * V8 instance.
27 */
28 bool IsValid() const;
29
30 const char* data;
31 int raw_size;
32 };
33
34 /**
35 * Callback and supporting data used in SnapshotCreator to implement embedder
36 * logic to serialize internal fields.
37 * Internal fields that directly reference V8 objects are serialized without
38 * calling this callback. Internal fields that contain aligned pointers are
39 * serialized by this callback if it returns non-zero result. Otherwise it is
40 * serialized verbatim.
41 */
42 struct SerializeInternalFieldsCallback {
43 using CallbackFunction = StartupData (*)(Local<Object> holder, int index,
44 void* data);
45 SerializeInternalFieldsCallback(CallbackFunction function = nullptr,
46 void* data_arg = nullptr)
callbackSerializeInternalFieldsCallback47 : callback(function), data(data_arg) {}
48 CallbackFunction callback;
49 void* data;
50 };
51 // Note that these fields are called "internal fields" in the API and called
52 // "embedder fields" within V8.
53 using SerializeEmbedderFieldsCallback = SerializeInternalFieldsCallback;
54
55 /**
56 * Callback and supporting data used to implement embedder logic to deserialize
57 * internal fields.
58 */
59 struct DeserializeInternalFieldsCallback {
60 using CallbackFunction = void (*)(Local<Object> holder, int index,
61 StartupData payload, void* data);
62 DeserializeInternalFieldsCallback(CallbackFunction function = nullptr,
63 void* data_arg = nullptr)
callbackDeserializeInternalFieldsCallback64 : callback(function), data(data_arg) {}
65 void (*callback)(Local<Object> holder, int index, StartupData payload,
66 void* data);
67 void* data;
68 };
69
70 using DeserializeEmbedderFieldsCallback = DeserializeInternalFieldsCallback;
71
72 /**
73 * Helper class to create a snapshot data blob.
74 *
75 * The Isolate used by a SnapshotCreator is owned by it, and will be entered
76 * and exited by the constructor and destructor, respectively; The destructor
77 * will also destroy the Isolate. Experimental language features, including
78 * those available by default, are not available while creating a snapshot.
79 */
80 class V8_EXPORT SnapshotCreator {
81 public:
82 enum class FunctionCodeHandling { kClear, kKeep };
83
84 /**
85 * Initialize and enter an isolate, and set it up for serialization.
86 * The isolate is either created from scratch or from an existing snapshot.
87 * The caller keeps ownership of the argument snapshot.
88 * \param existing_blob existing snapshot from which to create this one.
89 * \param external_references a null-terminated array of external references
90 * that must be equivalent to CreateParams::external_references.
91 */
92 SnapshotCreator(Isolate* isolate,
93 const intptr_t* external_references = nullptr,
94 StartupData* existing_blob = nullptr);
95
96 /**
97 * Create and enter an isolate, and set it up for serialization.
98 * The isolate is either created from scratch or from an existing snapshot.
99 * The caller keeps ownership of the argument snapshot.
100 * \param existing_blob existing snapshot from which to create this one.
101 * \param external_references a null-terminated array of external references
102 * that must be equivalent to CreateParams::external_references.
103 */
104 SnapshotCreator(const intptr_t* external_references = nullptr,
105 StartupData* existing_blob = nullptr);
106
107 /**
108 * Destroy the snapshot creator, and exit and dispose of the Isolate
109 * associated with it.
110 */
111 ~SnapshotCreator();
112
113 /**
114 * \returns the isolate prepared by the snapshot creator.
115 */
116 Isolate* GetIsolate();
117
118 /**
119 * Set the default context to be included in the snapshot blob.
120 * The snapshot will not contain the global proxy, and we expect one or a
121 * global object template to create one, to be provided upon deserialization.
122 *
123 * \param callback optional callback to serialize internal fields.
124 */
125 void SetDefaultContext(Local<Context> context,
126 SerializeInternalFieldsCallback callback =
127 SerializeInternalFieldsCallback());
128
129 /**
130 * Add additional context to be included in the snapshot blob.
131 * The snapshot will include the global proxy.
132 *
133 * \param callback optional callback to serialize internal fields.
134 *
135 * \returns the index of the context in the snapshot blob.
136 */
137 size_t AddContext(Local<Context> context,
138 SerializeInternalFieldsCallback callback =
139 SerializeInternalFieldsCallback());
140
141 /**
142 * Attach arbitrary V8::Data to the context snapshot, which can be retrieved
143 * via Context::GetDataFromSnapshotOnce after deserialization. This data does
144 * not survive when a new snapshot is created from an existing snapshot.
145 * \returns the index for retrieval.
146 */
147 template <class T>
148 V8_INLINE size_t AddData(Local<Context> context, Local<T> object);
149
150 /**
151 * Attach arbitrary V8::Data to the isolate snapshot, which can be retrieved
152 * via Isolate::GetDataFromSnapshotOnce after deserialization. This data does
153 * not survive when a new snapshot is created from an existing snapshot.
154 * \returns the index for retrieval.
155 */
156 template <class T>
157 V8_INLINE size_t AddData(Local<T> object);
158
159 /**
160 * Created a snapshot data blob.
161 * This must not be called from within a handle scope.
162 * \param function_code_handling whether to include compiled function code
163 * in the snapshot.
164 * \returns { nullptr, 0 } on failure, and a startup snapshot on success. The
165 * caller acquires ownership of the data array in the return value.
166 */
167 StartupData CreateBlob(FunctionCodeHandling function_code_handling);
168
169 // Disallow copying and assigning.
170 SnapshotCreator(const SnapshotCreator&) = delete;
171 void operator=(const SnapshotCreator&) = delete;
172
173 private:
174 size_t AddData(Local<Context> context, internal::Address object);
175 size_t AddData(internal::Address object);
176
177 void* data_;
178 };
179
180 template <class T>
AddData(Local<Context> context,Local<T> object)181 size_t SnapshotCreator::AddData(Local<Context> context, Local<T> object) {
182 T* object_ptr = *object;
183 internal::Address* p = reinterpret_cast<internal::Address*>(object_ptr);
184 return AddData(context, *p);
185 }
186
187 template <class T>
AddData(Local<T> object)188 size_t SnapshotCreator::AddData(Local<T> object) {
189 T* object_ptr = *object;
190 internal::Address* p = reinterpret_cast<internal::Address*>(object_ptr);
191 return AddData(*p);
192 }
193
194 } // namespace v8
195
196 #endif // INCLUDE_V8_SNAPSHOT_H_
197