#include "src/execution/isolate.h"
#include "src/wasm/streaming-decoder.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-serialization.h"
namespace v8::internal::wasm {
class V8_EXPORT_PRIVATE SyncStreamingDecoder final : public StreamingDecoder {
public:
SyncStreamingDecoder(WasmEnabledFeatures enabled,
CompileTimeImports compile_imports,
const char* api_method_name_for_errors,
std::shared_ptr<CompilationResultResolver> resolver)
: enabled_(enabled),
compile_imports_(std::move(compile_imports)),
api_method_name_for_errors_(api_method_name_for_errors),
resolver_(resolver) {}
void InitializeIsolateSpecificInfo(Isolate* isolate) override {
isolate_ = isolate;
context_ =
indirect_handle(direct_handle(isolate->raw_native_context(), isolate));
}
void OnBytesReceived(base::Vector<const uint8_t> bytes) override {
buffer_.emplace_back(bytes.size());
CHECK_EQ(buffer_.back().size(), bytes.size());
std::memcpy(buffer_.back().data(), bytes.data(), bytes.size());
buffer_size_ += bytes.size();
}
void SetHasCompiledModuleBytes() override {
if (buffer_size_ != 0) {
FATAL(
"SetHasCompiledModuleBytes has to be called before OnBytesReceived");
}
has_compiled_module_bytes_ = true;
}
void Finish(
const WasmStreaming::ModuleCachingCallback& caching_callback) override {
base::OwnedVector<const uint8_t> bytes_copy;
{
auto bytes = base::OwnedVector<uint8_t>::NewForOverwrite(buffer_size_);
uint8_t* destination = bytes.begin();
for (auto& chunk : buffer_) {
std::memcpy(destination, chunk.data(), chunk.size());
destination += chunk.size();
}
CHECK_EQ(destination - bytes.begin(), buffer_size_);
bytes_copy = std::move(bytes);
}
if (caching_callback) {
CHECK(has_compiled_module_bytes_);
HandleScope scope(isolate_);
SaveAndSwitchContext saved_context(isolate_, *context_);
struct CachingInterface : public WasmStreaming::ModuleCachingInterface {
SyncStreamingDecoder* const decoder;
base::OwnedVector<const uint8_t>& wire_bytes;
bool did_try_deserialization = false;
MaybeDirectHandle<WasmModuleObject> deserialized_module_object;
CachingInterface(SyncStreamingDecoder* decoder,
base::OwnedVector<const uint8_t>& wire_bytes)
: decoder(decoder), wire_bytes(wire_bytes) {}
MemorySpan<const uint8_t> GetWireBytes() const override {
return {wire_bytes.data(), wire_bytes.size()};
}
bool SetCachedCompiledModuleBytes(
MemorySpan<const uint8_t> module_bytes) override {
CHECK(!did_try_deserialization);
did_try_deserialization = true;
deserialized_module_object =
decoder->Deserialize(wire_bytes, base::VectorOf(module_bytes));
return !deserialized_module_object.IsEmpty();
}
} caching_interface{this, bytes_copy};
caching_callback(caching_interface);
if (DirectHandle<WasmModuleObject> module_object;
caching_interface.deserialized_module_object.ToHandle(
&module_object)) {
resolver_->OnCompilationSucceeded(module_object);
return;
}
}
DCHECK_EQ(buffer_size_, bytes_copy.size());
ErrorThrower thrower(isolate_, api_method_name_for_errors_);
MaybeDirectHandle<WasmModuleObject> module_object =
GetWasmEngine()->SyncCompile(isolate_, enabled_,
std::move(compile_imports_), &thrower,
std::move(bytes_copy));
if (thrower.error()) {
resolver_->OnCompilationFailed(thrower.Reify());
return;
}
DirectHandle<WasmModuleObject> module = module_object.ToHandleChecked();
resolver_->OnCompilationSucceeded(module);
}
void Abort() override {
buffer_.clear();
}
void NotifyCompilationDiscarded() override { buffer_.clear(); }
void NotifyNativeModuleCreated(
const std::shared_ptr<NativeModule>&) override {
UNREACHABLE();
}
private:
MaybeDirectHandle<WasmModuleObject> Deserialize(
base::OwnedVector<const uint8_t>& wire_bytes,
base::Vector<const uint8_t> cached_module_bytes) {
return DeserializeNativeModule(isolate_, enabled_, cached_module_bytes,
wire_bytes, compile_imports_,
base::VectorOf(url()));
}
Isolate* isolate_;
const WasmEnabledFeatures enabled_;
CompileTimeImports compile_imports_;
IndirectHandle<Context> context_;
const char* api_method_name_for_errors_;
std::shared_ptr<CompilationResultResolver> resolver_;
bool has_compiled_module_bytes_ = false;
std::vector<std::vector<uint8_t>> buffer_;
size_t buffer_size_ = 0;
};
std::unique_ptr<StreamingDecoder> StreamingDecoder::CreateSyncStreamingDecoder(
WasmEnabledFeatures enabled, CompileTimeImports compile_imports,
const char* api_method_name_for_errors,
std::shared_ptr<CompilationResultResolver> resolver) {
return std::make_unique<SyncStreamingDecoder>(
enabled, std::move(compile_imports), api_method_name_for_errors,
std::move(resolver));
}
}