diff options
Diffstat (limited to 'deps/v8/src/wasm/streaming-decoder.cc')
-rw-r--r-- | deps/v8/src/wasm/streaming-decoder.cc | 301 |
1 files changed, 183 insertions, 118 deletions
diff --git a/deps/v8/src/wasm/streaming-decoder.cc b/deps/v8/src/wasm/streaming-decoder.cc index 15ced2316b..1896178c48 100644 --- a/deps/v8/src/wasm/streaming-decoder.cc +++ b/deps/v8/src/wasm/streaming-decoder.cc @@ -12,6 +12,7 @@ #include "src/wasm/decoder.h" #include "src/wasm/leb-helper.h" #include "src/wasm/module-decoder.h" +#include "src/wasm/wasm-code-manager.h" #include "src/wasm/wasm-limits.h" #include "src/wasm/wasm-objects.h" #include "src/wasm/wasm-result.h" @@ -26,14 +27,21 @@ namespace internal { namespace wasm { void StreamingDecoder::OnBytesReceived(Vector<const uint8_t> bytes) { + if (deserializing()) { + wire_bytes_for_deserializing_.insert(wire_bytes_for_deserializing_.end(), + bytes.begin(), bytes.end()); + return; + } + TRACE_STREAMING("OnBytesReceived(%zu bytes)\n", bytes.size()); + size_t current = 0; while (ok() && current < bytes.size()) { size_t num_bytes = state_->ReadBytes(this, bytes.SubVector(current, bytes.size())); current += num_bytes; module_offset_ += num_bytes; - if (state_->is_finished()) { + if (state_->offset() == state_->buffer().size()) { state_ = state_->Next(this); } } @@ -45,17 +53,28 @@ void StreamingDecoder::OnBytesReceived(Vector<const uint8_t> bytes) { size_t StreamingDecoder::DecodingState::ReadBytes(StreamingDecoder* streaming, Vector<const uint8_t> bytes) { - size_t num_bytes = std::min(bytes.size(), remaining()); + Vector<uint8_t> remaining_buf = buffer() + offset(); + size_t num_bytes = std::min(bytes.size(), remaining_buf.size()); TRACE_STREAMING("ReadBytes(%zu bytes)\n", num_bytes); - memcpy(buffer() + offset(), &bytes.first(), num_bytes); + memcpy(remaining_buf.start(), &bytes.first(), num_bytes); set_offset(offset() + num_bytes); return num_bytes; } void StreamingDecoder::Finish() { TRACE_STREAMING("Finish\n"); - if (!ok()) { - return; + if (!ok()) return; + + if (deserializing()) { + Vector<const uint8_t> wire_bytes = VectorOf(wire_bytes_for_deserializing_); + // Try to deserialize the module from wire bytes and module bytes. + if (processor_->Deserialize(compiled_module_bytes_, wire_bytes)) return; + + // Deserialization failed. Restart decoding using |wire_bytes|. + compiled_module_bytes_ = {}; + DCHECK(!deserializing()); + OnBytesReceived(wire_bytes); + // The decoder has received all wire bytes; fall through and finish. } if (!state_->is_finishing_allowed()) { @@ -73,9 +92,9 @@ void StreamingDecoder::Finish() { memcpy(cursor, module_header, arraysize(module_header)); cursor += arraysize(module_header); } - for (auto&& buffer : section_buffers_) { + for (const auto& buffer : section_buffers_) { DCHECK_LE(cursor - bytes.start() + buffer->length(), total_size_); - memcpy(cursor, buffer->bytes(), buffer->length()); + memcpy(cursor, buffer->bytes().start(), buffer->length()); cursor += buffer->length(); } processor_->OnFinishedStream(std::move(bytes)); @@ -83,10 +102,59 @@ void StreamingDecoder::Finish() { void StreamingDecoder::Abort() { TRACE_STREAMING("Abort\n"); - if (ok()) { - ok_ = false; - processor_->OnAbort(); + if (!ok()) return; // Failed already. + processor_->OnAbort(); + Fail(); +} + +void StreamingDecoder::SetModuleCompiledCallback( + ModuleCompiledCallback callback) { + DCHECK_NULL(module_compiled_callback_); + module_compiled_callback_ = callback; +} + +bool StreamingDecoder::SetCompiledModuleBytes( + Vector<const uint8_t> compiled_module_bytes) { + compiled_module_bytes_ = compiled_module_bytes; + return true; +} + +namespace { + +class TopTierCompiledCallback { + public: + TopTierCompiledCallback(std::shared_ptr<NativeModule> native_module, + StreamingDecoder::ModuleCompiledCallback callback) + : native_module_(std::move(native_module)), + callback_(std::move(callback)) {} + + void operator()(CompilationEvent event, const WasmError* error) const { + if (event != CompilationEvent::kFinishedTopTierCompilation) return; + DCHECK_NULL(error); + callback_(native_module_); +#ifdef DEBUG + DCHECK(!called_); + called_ = true; +#endif } + + private: + const std::shared_ptr<NativeModule> native_module_; + const StreamingDecoder::ModuleCompiledCallback callback_; +#ifdef DEBUG + mutable bool called_ = false; +#endif +}; + +} // namespace + +void StreamingDecoder::NotifyNativeModuleCreated( + const std::shared_ptr<NativeModule>& native_module) { + if (!module_compiled_callback_) return; + auto* comp_state = native_module->compilation_state(); + comp_state->AddCallback(TopTierCompiledCallback{ + std::move(native_module), std::move(module_compiled_callback_)}); + module_compiled_callback_ = {}; } // An abstract class to share code among the states which decode VarInts. This @@ -97,9 +165,7 @@ class StreamingDecoder::DecodeVarInt32 : public DecodingState { explicit DecodeVarInt32(size_t max_value, const char* field_name) : max_value_(max_value), field_name_(field_name) {} - uint8_t* buffer() override { return byte_buffer_; } - - size_t size() const override { return kMaxVarInt32Size; } + Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); } size_t ReadBytes(StreamingDecoder* streaming, Vector<const uint8_t> bytes) override; @@ -113,16 +179,15 @@ class StreamingDecoder::DecodeVarInt32 : public DecodingState { uint8_t byte_buffer_[kMaxVarInt32Size]; // The maximum valid value decoded in this state. {Next} returns an error if // this value is exceeded. - size_t max_value_; - const char* field_name_; + const size_t max_value_; + const char* const field_name_; size_t value_ = 0; size_t bytes_consumed_ = 0; }; class StreamingDecoder::DecodeModuleHeader : public DecodingState { public: - size_t size() const override { return kModuleHeaderSize; } - uint8_t* buffer() override { return byte_buffer_; } + Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); } std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override; @@ -140,8 +205,7 @@ class StreamingDecoder::DecodeSectionID : public DecodingState { explicit DecodeSectionID(uint32_t module_offset) : module_offset_(module_offset) {} - size_t size() const override { return 1; } - uint8_t* buffer() override { return &id_; } + Vector<uint8_t> buffer() override { return {&id_, 1}; } bool is_finishing_allowed() const override { return true; } std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override; @@ -149,7 +213,7 @@ class StreamingDecoder::DecodeSectionID : public DecodingState { private: uint8_t id_ = 0; // The start offset of this section in the module. - uint32_t module_offset_; + const uint32_t module_offset_; }; class StreamingDecoder::DecodeSectionLength : public DecodeVarInt32 { @@ -163,9 +227,9 @@ class StreamingDecoder::DecodeSectionLength : public DecodeVarInt32 { StreamingDecoder* streaming) override; private: - uint8_t section_id_; + const uint8_t section_id_; // The start offset of this section in the module. - uint32_t module_offset_; + const uint32_t module_offset_; }; class StreamingDecoder::DecodeSectionPayload : public DecodingState { @@ -173,16 +237,12 @@ class StreamingDecoder::DecodeSectionPayload : public DecodingState { explicit DecodeSectionPayload(SectionBuffer* section_buffer) : section_buffer_(section_buffer) {} - size_t size() const override { return section_buffer_->payload_length(); } - - uint8_t* buffer() override { - return section_buffer_->bytes() + section_buffer_->payload_offset(); - } + Vector<uint8_t> buffer() override { return section_buffer_->payload(); } std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override; private: - SectionBuffer* section_buffer_; + SectionBuffer* const section_buffer_; }; class StreamingDecoder::DecodeNumberOfFunctions : public DecodeVarInt32 { @@ -195,7 +255,7 @@ class StreamingDecoder::DecodeNumberOfFunctions : public DecodeVarInt32 { StreamingDecoder* streaming) override; private: - SectionBuffer* section_buffer_; + SectionBuffer* const section_buffer_; }; class StreamingDecoder::DecodeFunctionLength : public DecodeVarInt32 { @@ -215,73 +275,76 @@ class StreamingDecoder::DecodeFunctionLength : public DecodeVarInt32 { StreamingDecoder* streaming) override; private: - SectionBuffer* section_buffer_; - size_t buffer_offset_; - size_t num_remaining_functions_; + SectionBuffer* const section_buffer_; + const size_t buffer_offset_; + const size_t num_remaining_functions_; }; class StreamingDecoder::DecodeFunctionBody : public DecodingState { public: explicit DecodeFunctionBody(SectionBuffer* section_buffer, - size_t buffer_offset, size_t function_length, + size_t buffer_offset, size_t function_body_length, size_t num_remaining_functions, uint32_t module_offset) : section_buffer_(section_buffer), buffer_offset_(buffer_offset), - size_(function_length), + function_body_length_(function_body_length), num_remaining_functions_(num_remaining_functions), module_offset_(module_offset) {} - size_t size() const override { return size_; } - - uint8_t* buffer() override { - return section_buffer_->bytes() + buffer_offset_; + Vector<uint8_t> buffer() override { + Vector<uint8_t> remaining_buffer = + section_buffer_->bytes() + buffer_offset_; + return remaining_buffer.SubVector(0, function_body_length_); } std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override; private: - SectionBuffer* section_buffer_; - size_t buffer_offset_; - size_t size_; - size_t num_remaining_functions_; - uint32_t module_offset_; + SectionBuffer* const section_buffer_; + const size_t buffer_offset_; + const size_t function_body_length_; + const size_t num_remaining_functions_; + const uint32_t module_offset_; }; size_t StreamingDecoder::DecodeVarInt32::ReadBytes( StreamingDecoder* streaming, Vector<const uint8_t> bytes) { - size_t bytes_read = std::min(bytes.size(), remaining()); + Vector<uint8_t> buf = buffer(); + Vector<uint8_t> remaining_buf = buf + offset(); + size_t new_bytes = std::min(bytes.size(), remaining_buf.size()); TRACE_STREAMING("ReadBytes of a VarInt\n"); - memcpy(buffer() + offset(), &bytes.first(), bytes_read); - Decoder decoder(buffer(), buffer() + offset() + bytes_read, - streaming->module_offset()); + memcpy(remaining_buf.start(), &bytes.first(), new_bytes); + buf.Truncate(offset() + new_bytes); + Decoder decoder(buf, streaming->module_offset()); value_ = decoder.consume_u32v(field_name_); // The number of bytes we actually needed to read. - DCHECK_GT(decoder.pc(), buffer()); - bytes_consumed_ = static_cast<size_t>(decoder.pc() - buffer()); + DCHECK_GT(decoder.pc(), buffer().start()); + bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.start()); TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_); if (decoder.failed()) { - if (offset() + bytes_read == size()) { + if (new_bytes == remaining_buf.size()) { // We only report an error if we read all bytes. - streaming->Error(decoder.toResult(nullptr)); + streaming->Error(decoder.error()); } - set_offset(offset() + bytes_read); - return bytes_read; - } else { - DCHECK_GT(bytes_consumed_, offset()); - size_t result = bytes_consumed_ - offset(); - // We read all the bytes we needed. - set_offset(size()); - return result; + set_offset(offset() + new_bytes); + return new_bytes; } + + // We read all the bytes we needed. + DCHECK_GT(bytes_consumed_, offset()); + new_bytes = bytes_consumed_ - offset(); + // Set the offset to the buffer size to signal that we are at the end of this + // section. + set_offset(buffer().size()); + return new_bytes; } std::unique_ptr<StreamingDecoder::DecodingState> StreamingDecoder::DecodeVarInt32::Next(StreamingDecoder* streaming) { - if (!streaming->ok()) { - return nullptr; - } + if (!streaming->ok()) return nullptr; + if (value_ > max_value_) { std::ostringstream oss; oss << "function size > maximum function size: " << value_ << " < " @@ -296,10 +359,8 @@ std::unique_ptr<StreamingDecoder::DecodingState> StreamingDecoder::DecodeModuleHeader::Next(StreamingDecoder* streaming) { TRACE_STREAMING("DecodeModuleHeader\n"); streaming->ProcessModuleHeader(); - if (streaming->ok()) { - return base::make_unique<DecodeSectionID>(streaming->module_offset()); - } - return nullptr; + if (!streaming->ok()) return nullptr; + return base::make_unique<DecodeSectionID>(streaming->module_offset()); } std::unique_ptr<StreamingDecoder::DecodingState> @@ -313,30 +374,25 @@ std::unique_ptr<StreamingDecoder::DecodingState> StreamingDecoder::DecodeSectionLength::NextWithValue( StreamingDecoder* streaming) { TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_); - SectionBuffer* buf = streaming->CreateNewBuffer( - module_offset_, section_id_, value_, - Vector<const uint8_t>(buffer(), static_cast<int>(bytes_consumed_))); + SectionBuffer* buf = + streaming->CreateNewBuffer(module_offset_, section_id_, value_, + buffer().SubVector(0, bytes_consumed_)); if (!buf) return nullptr; if (value_ == 0) { if (section_id_ == SectionCode::kCodeSectionCode) { return streaming->Error("Code section cannot have size 0"); - } else { - streaming->ProcessSection(buf); - if (streaming->ok()) { - // There is no payload, we go to the next section immediately. - return base::make_unique<DecodeSectionID>(streaming->module_offset_); - } else { - return nullptr; - } } + streaming->ProcessSection(buf); + if (!streaming->ok()) return nullptr; + // There is no payload, we go to the next section immediately. + return base::make_unique<DecodeSectionID>(streaming->module_offset_); } else { if (section_id_ == SectionCode::kCodeSectionCode) { // We reached the code section. All functions of the code section are put // into the same SectionBuffer. return base::make_unique<DecodeNumberOfFunctions>(buf); - } else { - return base::make_unique<DecodeSectionPayload>(buf); } + return base::make_unique<DecodeSectionPayload>(buf); } } @@ -344,10 +400,8 @@ std::unique_ptr<StreamingDecoder::DecodingState> StreamingDecoder::DecodeSectionPayload::Next(StreamingDecoder* streaming) { TRACE_STREAMING("DecodeSectionPayload\n"); streaming->ProcessSection(section_buffer_); - if (streaming->ok()) { - return base::make_unique<DecodeSectionID>(streaming->module_offset()); - } - return nullptr; + if (!streaming->ok()) return nullptr; + return base::make_unique<DecodeSectionID>(streaming->module_offset()); } std::unique_ptr<StreamingDecoder::DecodingState> @@ -355,26 +409,25 @@ StreamingDecoder::DecodeNumberOfFunctions::NextWithValue( StreamingDecoder* streaming) { TRACE_STREAMING("DecodeNumberOfFunctions(%zu)\n", value_); // Copy the bytes we read into the section buffer. - if (section_buffer_->payload_length() >= bytes_consumed_) { - memcpy(section_buffer_->bytes() + section_buffer_->payload_offset(), - buffer(), bytes_consumed_); - } else { + Vector<uint8_t> payload_buf = section_buffer_->payload(); + if (payload_buf.size() < bytes_consumed_) { return streaming->Error("Invalid code section length"); } + memcpy(payload_buf.start(), buffer().start(), bytes_consumed_); // {value} is the number of functions. - if (value_ > 0) { - streaming->StartCodeSection(value_); - if (!streaming->ok()) return nullptr; - return base::make_unique<DecodeFunctionLength>( - section_buffer_, section_buffer_->payload_offset() + bytes_consumed_, - value_); - } else { - if (section_buffer_->payload_length() != bytes_consumed_) { + if (value_ == 0) { + if (payload_buf.size() != bytes_consumed_) { return streaming->Error("not all code section bytes were consumed"); } return base::make_unique<DecodeSectionID>(streaming->module_offset()); } + + streaming->StartCodeSection(value_, streaming->section_buffers_.back()); + if (!streaming->ok()) return nullptr; + return base::make_unique<DecodeFunctionLength>( + section_buffer_, section_buffer_->payload_offset() + bytes_consumed_, + value_); } std::unique_ptr<StreamingDecoder::DecodingState> @@ -382,20 +435,17 @@ StreamingDecoder::DecodeFunctionLength::NextWithValue( StreamingDecoder* streaming) { TRACE_STREAMING("DecodeFunctionLength(%zu)\n", value_); // Copy the bytes we consumed into the section buffer. - if (section_buffer_->length() >= buffer_offset_ + bytes_consumed_) { - memcpy(section_buffer_->bytes() + buffer_offset_, buffer(), - bytes_consumed_); - } else { + Vector<uint8_t> fun_length_buffer = section_buffer_->bytes() + buffer_offset_; + if (fun_length_buffer.size() < bytes_consumed_) { return streaming->Error("Invalid code section length"); } + memcpy(fun_length_buffer.start(), buffer().start(), bytes_consumed_); // {value} is the length of the function. - if (value_ == 0) { - return streaming->Error("Invalid function length (0)"); - } else if (buffer_offset_ + bytes_consumed_ + value_ > - section_buffer_->length()) { - streaming->Error("not enough code section bytes"); - return nullptr; + if (value_ == 0) return streaming->Error("Invalid function length (0)"); + + if (buffer_offset_ + bytes_consumed_ + value_ > section_buffer_->length()) { + return streaming->Error("not enough code section bytes"); } return base::make_unique<DecodeFunctionBody>( @@ -406,21 +456,19 @@ StreamingDecoder::DecodeFunctionLength::NextWithValue( std::unique_ptr<StreamingDecoder::DecodingState> StreamingDecoder::DecodeFunctionBody::Next(StreamingDecoder* streaming) { TRACE_STREAMING("DecodeFunctionBody\n"); - streaming->ProcessFunctionBody( - Vector<const uint8_t>(buffer(), static_cast<int>(size())), - module_offset_); - if (!streaming->ok()) { - return nullptr; + streaming->ProcessFunctionBody(buffer(), module_offset_); + if (!streaming->ok()) return nullptr; + + size_t end_offset = buffer_offset_ + function_body_length_; + if (num_remaining_functions_ > 0) { + return base::make_unique<DecodeFunctionLength>(section_buffer_, end_offset, + num_remaining_functions_); } - if (num_remaining_functions_ != 0) { - return base::make_unique<DecodeFunctionLength>( - section_buffer_, buffer_offset_ + size(), num_remaining_functions_); - } else { - if (buffer_offset_ + size() != section_buffer_->length()) { - return streaming->Error("not all code section bytes were used"); - } - return base::make_unique<DecodeSectionID>(streaming->module_offset()); + // We just read the last function body. Continue with the next section. + if (end_offset != section_buffer_->length()) { + return streaming->Error("not all code section bytes were used"); } + return base::make_unique<DecodeSectionID>(streaming->module_offset()); } StreamingDecoder::StreamingDecoder( @@ -428,6 +476,23 @@ StreamingDecoder::StreamingDecoder( : processor_(std::move(processor)), // A module always starts with a module header. state_(new DecodeModuleHeader()) {} + +StreamingDecoder::SectionBuffer* StreamingDecoder::CreateNewBuffer( + uint32_t module_offset, uint8_t section_id, size_t length, + Vector<const uint8_t> length_bytes) { + // Check the order of sections. Unknown sections can appear at any position. + if (section_id != kUnknownSectionCode) { + if (section_id < next_section_id_) { + Error("Unexpected section"); + return nullptr; + } + next_section_id_ = section_id + 1; + } + section_buffers_.emplace_back(std::make_shared<SectionBuffer>( + module_offset, section_id, length, length_bytes)); + return section_buffers_.back().get(); +} + } // namespace wasm } // namespace internal } // namespace v8 |