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