summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/streaming-decoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/wasm/streaming-decoder.h')
-rw-r--r--deps/v8/src/wasm/streaming-decoder.h152
1 files changed, 152 insertions, 0 deletions
diff --git a/deps/v8/src/wasm/streaming-decoder.h b/deps/v8/src/wasm/streaming-decoder.h
new file mode 100644
index 0000000000..349e013e6c
--- /dev/null
+++ b/deps/v8/src/wasm/streaming-decoder.h
@@ -0,0 +1,152 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_WASM_STREAMING_DECODER_H_
+#define V8_WASM_STREAMING_DECODER_H_
+
+#include <vector>
+#include "src/isolate.h"
+#include "src/wasm/decoder.h"
+#include "src/wasm/wasm-objects.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+// The StreamingDecoder takes a sequence of byte arrays, each received by a call
+// of {OnBytesReceived}, and extracts the bytes which belong to section payloads
+// and function bodies.
+class V8_EXPORT_PRIVATE StreamingDecoder {
+ public:
+ explicit StreamingDecoder(Isolate* isolate);
+
+ // The buffer passed into OnBytesReceived is owned by the caller.
+ void OnBytesReceived(Vector<const uint8_t> bytes);
+
+ // Finishes the stream and returns compiled WasmModuleObject.
+ MaybeHandle<WasmModuleObject> Finish();
+
+ // Finishes the streaming and returns true if no error was detected.
+ bool FinishForTesting();
+
+ private:
+ // The SectionBuffer is the data object for the content of a single section.
+ // It stores all bytes of the section (including section id and section
+ // length), and the offset where the actual payload starts.
+ class SectionBuffer {
+ public:
+ // id: The section id.
+ // payload_length: The length of the payload.
+ // length_bytes: The section length, as it is encoded in the module bytes.
+ SectionBuffer(uint8_t id, size_t payload_length,
+ Vector<const uint8_t> length_bytes)
+ : // ID + length + payload
+ length_(1 + length_bytes.length() + payload_length),
+ bytes_(new uint8_t[length_]),
+ payload_offset_(1 + length_bytes.length()) {
+ bytes_[0] = id;
+ memcpy(bytes_.get() + 1, &length_bytes.first(), length_bytes.length());
+ }
+ uint8_t* bytes() const { return bytes_.get(); }
+ size_t length() const { return length_; }
+ size_t payload_offset() const { return payload_offset_; }
+ size_t payload_length() const { return length_ - payload_offset_; }
+
+ private:
+ size_t length_;
+ std::unique_ptr<uint8_t[]> bytes_;
+ size_t payload_offset_;
+ };
+
+ // The decoding of a stream of wasm module bytes is organized in states. Each
+ // state provides a buffer to store the bytes required for the current state,
+ // information on how many bytes have already been received, how many bytes
+ // are needed, and a {Next} function which starts the next state once all
+ // bytes of the current state were received.
+ //
+ // The states change according to the following state diagram:
+ //
+ // Start
+ // |
+ // |
+ // v
+ // DecodeModuleHeader
+ // | _________________________________________
+ // | | |
+ // v v |
+ // DecodeSectionID --> DecodeSectionLength --> DecodeSectionPayload
+ // A |
+ // | | (if the section id == code)
+ // | v
+ // | DecodeNumberOfFunctions -- > DecodeFunctionLength
+ // | A |
+ // | | |
+ // | (after all functions were read) | v
+ // ------------------------------------- DecodeFunctionBody
+ //
+ class DecodingState {
+ public:
+ virtual ~DecodingState() = default;
+
+ // Reads the bytes for the current state and returns the number of read
+ // bytes.
+ virtual size_t ReadBytes(StreamingDecoder* streaming,
+ Vector<const uint8_t> bytes);
+
+ // Returns the next state of the streaming decoding.
+ virtual std::unique_ptr<DecodingState> Next(
+ StreamingDecoder* streaming) = 0;
+ // The number of bytes to be received.
+ virtual size_t size() const = 0;
+ // The buffer to store the received bytes.
+ virtual uint8_t* buffer() = 0;
+ // The number of bytes which were already received.
+ size_t offset() const { return offset_; }
+ void set_offset(size_t value) { offset_ = value; }
+ // The number of bytes which are still needed.
+ size_t remaining() const { return size() - offset(); }
+ bool is_finished() const { return offset() == size(); }
+ // A flag to indicate if finishing the streaming decoder is allowed without
+ // error.
+ virtual bool is_finishing_allowed() const { return false; }
+
+ private:
+ size_t offset_ = 0;
+ };
+
+ // Forward declarations of the concrete states. This is needed so that they
+ // can access private members of the StreamingDecoder.
+ class DecodeVarInt32;
+ class DecodeModuleHeader;
+ class DecodeSectionID;
+ class DecodeSectionLength;
+ class DecodeSectionPayload;
+ class DecodeNumberOfFunctions;
+ class DecodeFunctionLength;
+ class DecodeFunctionBody;
+
+ // Creates a buffer for the next section of the module.
+ SectionBuffer* CreateNewBuffer(uint8_t id, size_t length,
+ Vector<const uint8_t> length_bytes) {
+ section_buffers_.emplace_back(new SectionBuffer(id, length, length_bytes));
+ return section_buffers_.back().get();
+ }
+
+ Decoder* decoder() { return &decoder_; }
+
+ Isolate* isolate_;
+ std::unique_ptr<DecodingState> state_;
+ // The decoder is an instance variable because we use it for error handling.
+ Decoder decoder_;
+ std::vector<std::unique_ptr<SectionBuffer>> section_buffers_;
+ size_t total_size_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamingDecoder);
+};
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8
+
+#endif // V8_WASM_STREAMING_DECODER_H_