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);
SerializeInternalFieldsCallbackv8::SerializeInternalFieldsCallback45 SerializeInternalFieldsCallback(CallbackFunction function = nullptr,
46 void* data_arg = nullptr)
47 : 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);
DeserializeInternalFieldsCallbackv8::DeserializeInternalFieldsCallback62 DeserializeInternalFieldsCallback(CallbackFunction function = nullptr,
63 void* data_arg = nullptr)
64 : 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 * \param owns_isolate whether this SnapshotCreator should call
92 * v8::Isolate::Dispose() during its destructor.
93 */
94 SnapshotCreator(Isolate* isolate,
95 const intptr_t* external_references = nullptr,
96 const StartupData* existing_blob = nullptr,
97 bool owns_isolate = true);
98
99 /**
100 * Create and enter an isolate, and set it up for serialization.
101 * The isolate is either created from scratch or from an existing snapshot.
102 * The caller keeps ownership of the argument snapshot.
103 * \param existing_blob existing snapshot from which to create this one.
104 * \param external_references a null-terminated array of external references
105 * that must be equivalent to CreateParams::external_references.
106 */
107 SnapshotCreator(const intptr_t* external_references = nullptr,
108 const StartupData* existing_blob = nullptr);
109
110 /**
111 * Destroy the snapshot creator, and exit and dispose of the Isolate
112 * associated with it.
113 */
114 ~SnapshotCreator();
115
116 /**
117 * \returns the isolate prepared by the snapshot creator.
118 */
119 Isolate* GetIsolate();
120
121 /**
122 * Set the default context to be included in the snapshot blob.
123 * The snapshot will not contain the global proxy, and we expect one or a
124 * global object template to create one, to be provided upon deserialization.
125 *
126 * \param callback optional callback to serialize internal fields.
127 */
128 void SetDefaultContext(Local<Context> context,
129 SerializeInternalFieldsCallback callback =
130 SerializeInternalFieldsCallback());
131
132 /**
133 * Add additional context to be included in the snapshot blob.
134 * The snapshot will include the global proxy.
135 *
136 * \param callback optional callback to serialize internal fields.
137 *
138 * \returns the index of the context in the snapshot blob.
139 */
140 size_t AddContext(Local<Context> context,
141 SerializeInternalFieldsCallback callback =
142 SerializeInternalFieldsCallback());
143
144 /**
145 * Attach arbitrary V8::Data to the context snapshot, which can be retrieved
146 * via Context::GetDataFromSnapshotOnce after deserialization. This data does
147 * not survive when a new snapshot is created from an existing snapshot.
148 * \returns the index for retrieval.
149 */
150 template <class T>
151 V8_INLINE size_t AddData(Local<Context> context, Local<T> object);
152
153 /**
154 * Attach arbitrary V8::Data to the isolate snapshot, which can be retrieved
155 * via Isolate::GetDataFromSnapshotOnce after deserialization. This data does
156 * not survive when a new snapshot is created from an existing snapshot.
157 * \returns the index for retrieval.
158 */
159 template <class T>
160 V8_INLINE size_t AddData(Local<T> object);
161
162 /**
163 * Created a snapshot data blob.
164 * This must not be called from within a handle scope.
165 * \param function_code_handling whether to include compiled function code
166 * in the snapshot.
167 * \returns { nullptr, 0 } on failure, and a startup snapshot on success. The
168 * caller acquires ownership of the data array in the return value.
169 */
170 StartupData CreateBlob(FunctionCodeHandling function_code_handling);
171
172 // Disallow copying and assigning.
173 SnapshotCreator(const SnapshotCreator&) = delete;
174 void operator=(const SnapshotCreator&) = delete;
175
176 private:
177 size_t AddData(Local<Context> context, internal::Address object);
178 size_t AddData(internal::Address object);
179
180 void* data_;
181 };
182
183 template <class T>
AddData(Local<Context> context, Local<T> object)184 size_t SnapshotCreator::AddData(Local<Context> context, Local<T> object) {
185 return AddData(context, internal::ValueHelper::ValueAsAddress(*object));
186 }
187
188 template <class T>
AddData(Local<T> object)189 size_t SnapshotCreator::AddData(Local<T> object) {
190 return AddData(internal::ValueHelper::ValueAsAddress(*object));
191 }
192
193 } // namespace v8
194
195 #endif // INCLUDE_V8_SNAPSHOT_H_
196