1 // Copyright 2020 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 #include "src/execution/isolate.h"
6 #include "src/wasm/streaming-decoder.h"
7 #include "src/wasm/wasm-engine.h"
8 #include "src/wasm/wasm-objects-inl.h"
9 #include "src/wasm/wasm-serialization.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace wasm {
14
15 class V8_EXPORT_PRIVATE SyncStreamingDecoder : public StreamingDecoder {
16 public:
SyncStreamingDecoder(Isolate * isolate,const WasmFeatures & enabled,Handle<Context> context,const char * api_method_name_for_errors,std::shared_ptr<CompilationResultResolver> resolver)17 SyncStreamingDecoder(Isolate* isolate, const WasmFeatures& enabled,
18 Handle<Context> context,
19 const char* api_method_name_for_errors,
20 std::shared_ptr<CompilationResultResolver> resolver)
21 : isolate_(isolate),
22 enabled_(enabled),
23 context_(context),
24 api_method_name_for_errors_(api_method_name_for_errors),
25 resolver_(resolver) {}
26
27 // The buffer passed into OnBytesReceived is owned by the caller.
OnBytesReceived(Vector<const uint8_t> bytes)28 void OnBytesReceived(Vector<const uint8_t> bytes) override {
29 buffer_.emplace_back(bytes.size());
30 CHECK_EQ(buffer_.back().size(), bytes.size());
31 std::memcpy(buffer_.back().data(), bytes.data(), bytes.size());
32 buffer_size_ += bytes.size();
33 }
34
Finish()35 void Finish() override {
36 // We copy all received chunks into one byte buffer.
37 auto bytes = std::make_unique<uint8_t[]>(buffer_size_);
38 uint8_t* destination = bytes.get();
39 for (auto& chunk : buffer_) {
40 std::memcpy(destination, chunk.data(), chunk.size());
41 destination += chunk.size();
42 }
43 CHECK_EQ(destination - bytes.get(), buffer_size_);
44
45 // Check if we can deserialize the module from cache.
46 if (deserializing()) {
47 HandleScope scope(isolate_);
48 SaveAndSwitchContext saved_context(isolate_, *context_);
49
50 MaybeHandle<WasmModuleObject> module_object = DeserializeNativeModule(
51 isolate_, compiled_module_bytes_,
52 Vector<const uint8_t>(bytes.get(), buffer_size_), url());
53
54 if (!module_object.is_null()) {
55 Handle<WasmModuleObject> module = module_object.ToHandleChecked();
56 resolver_->OnCompilationSucceeded(module);
57 return;
58 }
59 }
60
61 // Compile the received bytes synchronously.
62 ModuleWireBytes wire_bytes(bytes.get(), bytes.get() + buffer_size_);
63 ErrorThrower thrower(isolate_, api_method_name_for_errors_);
64 MaybeHandle<WasmModuleObject> module_object =
65 isolate_->wasm_engine()->SyncCompile(isolate_, enabled_, &thrower,
66 wire_bytes);
67 if (thrower.error()) {
68 resolver_->OnCompilationFailed(thrower.Reify());
69 return;
70 }
71 Handle<WasmModuleObject> module = module_object.ToHandleChecked();
72 if (module_compiled_callback_) {
73 module_compiled_callback_(module->shared_native_module());
74 }
75 resolver_->OnCompilationSucceeded(module);
76 }
77
Abort()78 void Abort() override {
79 // Abort is fully handled by the API, we only clear the buffer.
80 buffer_.clear();
81 }
82
NotifyCompilationEnded()83 void NotifyCompilationEnded() override { buffer_.clear(); }
84
NotifyNativeModuleCreated(const std::shared_ptr<NativeModule> &)85 void NotifyNativeModuleCreated(
86 const std::shared_ptr<NativeModule>&) override {
87 // This function is only called from the {AsyncCompileJob}.
88 UNREACHABLE();
89 }
90
91 private:
92 Isolate* isolate_;
93 const WasmFeatures enabled_;
94 Handle<Context> context_;
95 const char* api_method_name_for_errors_;
96 std::shared_ptr<CompilationResultResolver> resolver_;
97
98 std::vector<std::vector<uint8_t>> buffer_;
99 size_t buffer_size_ = 0;
100 };
101
CreateSyncStreamingDecoder(Isolate * isolate,const WasmFeatures & enabled,Handle<Context> context,const char * api_method_name_for_errors,std::shared_ptr<CompilationResultResolver> resolver)102 std::unique_ptr<StreamingDecoder> StreamingDecoder::CreateSyncStreamingDecoder(
103 Isolate* isolate, const WasmFeatures& enabled, Handle<Context> context,
104 const char* api_method_name_for_errors,
105 std::shared_ptr<CompilationResultResolver> resolver) {
106 return std::make_unique<SyncStreamingDecoder>(isolate, enabled, context,
107 api_method_name_for_errors,
108 std::move(resolver));
109 }
110 } // namespace wasm
111 } // namespace internal
112 } // namespace v8
113