• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_WASM_H_
6 #define INCLUDE_V8_WASM_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "v8-local-handle.h"  // NOLINT(build/include_directory)
12 #include "v8-memory-span.h"   // NOLINT(build/include_directory)
13 #include "v8-object.h"        // NOLINT(build/include_directory)
14 #include "v8config.h"         // NOLINT(build/include_directory)
15 
16 namespace v8 {
17 
18 class ArrayBuffer;
19 class Promise;
20 
21 namespace internal {
22 namespace wasm {
23 class NativeModule;
24 class StreamingDecoder;
25 }  // namespace wasm
26 }  // namespace internal
27 
28 /**
29  * An owned byte buffer with associated size.
30  */
31 struct OwnedBuffer {
32   std::unique_ptr<const uint8_t[]> buffer;
33   size_t size = 0;
OwnedBufferOwnedBuffer34   OwnedBuffer(std::unique_ptr<const uint8_t[]> buffer, size_t size)
35       : buffer(std::move(buffer)), size(size) {}
36   OwnedBuffer() = default;
37 };
38 
39 // Wrapper around a compiled WebAssembly module, which is potentially shared by
40 // different WasmModuleObjects.
41 class V8_EXPORT CompiledWasmModule {
42  public:
43   /**
44    * Serialize the compiled module. The serialized data does not include the
45    * wire bytes.
46    */
47   OwnedBuffer Serialize();
48 
49   /**
50    * Get the (wasm-encoded) wire bytes that were used to compile this module.
51    */
52   MemorySpan<const uint8_t> GetWireBytesRef();
53 
source_url()54   const std::string& source_url() const { return source_url_; }
55 
56  private:
57   friend class WasmModuleObject;
58   friend class WasmStreaming;
59 
60   explicit CompiledWasmModule(std::shared_ptr<internal::wasm::NativeModule>,
61                               const char* source_url, size_t url_length);
62 
63   const std::shared_ptr<internal::wasm::NativeModule> native_module_;
64   const std::string source_url_;
65 };
66 
67 // An instance of WebAssembly.Memory.
68 class V8_EXPORT WasmMemoryObject : public Object {
69  public:
70   WasmMemoryObject() = delete;
71 
72   /**
73    * Returns underlying ArrayBuffer.
74    */
75   Local<ArrayBuffer> Buffer();
76 
Cast(Value * value)77   V8_INLINE static WasmMemoryObject* Cast(Value* value) {
78 #ifdef V8_ENABLE_CHECKS
79     CheckCast(value);
80 #endif
81     return static_cast<WasmMemoryObject*>(value);
82   }
83 
84  private:
85   static void CheckCast(Value* object);
86 };
87 
88 // An instance of WebAssembly.Module.
89 class V8_EXPORT WasmModuleObject : public Object {
90  public:
91   WasmModuleObject() = delete;
92 
93   /**
94    * Efficiently re-create a WasmModuleObject, without recompiling, from
95    * a CompiledWasmModule.
96    */
97   static MaybeLocal<WasmModuleObject> FromCompiledModule(
98       Isolate* isolate, const CompiledWasmModule&);
99 
100   /**
101    * Get the compiled module for this module object. The compiled module can be
102    * shared by several module objects.
103    */
104   CompiledWasmModule GetCompiledModule();
105 
106   /**
107    * Compile a Wasm module from the provided uncompiled bytes.
108    */
109   static MaybeLocal<WasmModuleObject> Compile(
110       Isolate* isolate, MemorySpan<const uint8_t> wire_bytes);
111 
Cast(Value * value)112   V8_INLINE static WasmModuleObject* Cast(Value* value) {
113 #ifdef V8_ENABLE_CHECKS
114     CheckCast(value);
115 #endif
116     return static_cast<WasmModuleObject*>(value);
117   }
118 
119  private:
120   static void CheckCast(Value* obj);
121 };
122 
123 /**
124  * The V8 interface for WebAssembly streaming compilation. When streaming
125  * compilation is initiated, V8 passes a {WasmStreaming} object to the embedder
126  * such that the embedder can pass the input bytes for streaming compilation to
127  * V8.
128  */
129 class V8_EXPORT WasmStreaming final {
130  public:
131   class WasmStreamingImpl;
132 
133   /**
134    * Client to receive streaming event notifications.
135    */
136   class Client {
137    public:
138     virtual ~Client() = default;
139     /**
140      * Passes the fully compiled module to the client. This can be used to
141      * implement code caching.
142      */
143     virtual void OnModuleCompiled(CompiledWasmModule compiled_module) = 0;
144   };
145 
146   explicit WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl);
147 
148   ~WasmStreaming();
149 
150   /**
151    * Pass a new chunk of bytes to WebAssembly streaming compilation.
152    * The buffer passed into {OnBytesReceived} is owned by the caller.
153    */
154   void OnBytesReceived(const uint8_t* bytes, size_t size);
155 
156   /**
157    * {Finish} should be called after all received bytes where passed to
158    * {OnBytesReceived} to tell V8 that there will be no more bytes. {Finish}
159    * does not have to be called after {Abort} has been called already.
160    * If {can_use_compiled_module} is true and {SetCompiledModuleBytes} was
161    * previously called, the compiled module bytes can be used.
162    * If {can_use_compiled_module} is false, the compiled module bytes previously
163    * set by {SetCompiledModuleBytes} should not be used.
164    */
165   void Finish(bool can_use_compiled_module = true);
166 
167   /**
168    * Abort streaming compilation. If {exception} has a value, then the promise
169    * associated with streaming compilation is rejected with that value. If
170    * {exception} does not have value, the promise does not get rejected.
171    */
172   void Abort(MaybeLocal<Value> exception);
173 
174   /**
175    * Passes previously compiled module bytes. This must be called before
176    * {OnBytesReceived}, {Finish}, or {Abort}. Returns true if the module bytes
177    * can be used, false otherwise. The buffer passed via {bytes} and {size}
178    * is owned by the caller. If {SetCompiledModuleBytes} returns true, the
179    * buffer must remain valid until either {Finish} or {Abort} completes.
180    * The compiled module bytes should not be used until {Finish(true)} is
181    * called, because they can be invalidated later by {Finish(false)}.
182    */
183   bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size);
184 
185   /**
186    * Sets the client object that will receive streaming event notifications.
187    * This must be called before {OnBytesReceived}, {Finish}, or {Abort}.
188    */
189   void SetClient(std::shared_ptr<Client> client);
190 
191   /*
192    * Sets the UTF-8 encoded source URL for the {Script} object. This must be
193    * called before {Finish}.
194    */
195   void SetUrl(const char* url, size_t length);
196 
197   /**
198    * Unpacks a {WasmStreaming} object wrapped in a  {Managed} for the embedder.
199    * Since the embedder is on the other side of the API, it cannot unpack the
200    * {Managed} itself.
201    */
202   static std::shared_ptr<WasmStreaming> Unpack(Isolate* isolate,
203                                                Local<Value> value);
204 
205  private:
206   std::unique_ptr<WasmStreamingImpl> impl_;
207 };
208 
209 // TODO(mtrofin): when streaming compilation is done, we can rename this
210 // to simply WasmModuleObjectBuilder
211 class V8_EXPORT WasmModuleObjectBuilderStreaming final {
212  public:
213   explicit WasmModuleObjectBuilderStreaming(Isolate* isolate);
214   /**
215    * The buffer passed into OnBytesReceived is owned by the caller.
216    */
217   void OnBytesReceived(const uint8_t*, size_t size);
218   void Finish();
219   /**
220    * Abort streaming compilation. If {exception} has a value, then the promise
221    * associated with streaming compilation is rejected with that value. If
222    * {exception} does not have value, the promise does not get rejected.
223    */
224   void Abort(MaybeLocal<Value> exception);
225   Local<Promise> GetPromise();
226 
227   ~WasmModuleObjectBuilderStreaming() = default;
228 
229  private:
230   WasmModuleObjectBuilderStreaming(const WasmModuleObjectBuilderStreaming&) =
231       delete;
232   WasmModuleObjectBuilderStreaming(WasmModuleObjectBuilderStreaming&&) =
233       default;
234   WasmModuleObjectBuilderStreaming& operator=(
235       const WasmModuleObjectBuilderStreaming&) = delete;
236   WasmModuleObjectBuilderStreaming& operator=(
237       WasmModuleObjectBuilderStreaming&&) = default;
238   Isolate* isolate_ = nullptr;
239 
240 #if V8_CC_MSVC
241   /**
242    * We don't need the static Copy API, so the default
243    * NonCopyablePersistentTraits would be sufficient, however,
244    * MSVC eagerly instantiates the Copy.
245    * We ensure we don't use Copy, however, by compiling with the
246    * defaults everywhere else.
247    */
248   Persistent<Promise, CopyablePersistentTraits<Promise>> promise_;
249 #else
250   Persistent<Promise> promise_;
251 #endif
252   std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
253 };
254 
255 }  // namespace v8
256 
257 #endif  // INCLUDE_V8_WASM_H_
258