Line data Source code
1 : // Copyright 2017 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/wasm/streaming-decoder.h"
6 :
7 : #include "src/base/template-utils.h"
8 : #include "src/handles.h"
9 : #include "src/objects-inl.h"
10 : #include "src/objects/descriptor-array.h"
11 : #include "src/objects/dictionary.h"
12 : #include "src/wasm/decoder.h"
13 : #include "src/wasm/leb-helper.h"
14 : #include "src/wasm/module-decoder.h"
15 : #include "src/wasm/wasm-code-manager.h"
16 : #include "src/wasm/wasm-limits.h"
17 : #include "src/wasm/wasm-objects.h"
18 : #include "src/wasm/wasm-result.h"
19 :
20 : #define TRACE_STREAMING(...) \
21 : do { \
22 : if (FLAG_trace_wasm_streaming) PrintF(__VA_ARGS__); \
23 : } while (false)
24 :
25 : namespace v8 {
26 : namespace internal {
27 : namespace wasm {
28 :
29 2908 : void StreamingDecoder::OnBytesReceived(Vector<const uint8_t> bytes) {
30 2908 : if (deserializing()) {
31 : wire_bytes_for_deserializing_.insert(wire_bytes_for_deserializing_.end(),
32 10 : bytes.begin(), bytes.end());
33 2908 : return;
34 : }
35 :
36 : TRACE_STREAMING("OnBytesReceived(%zu bytes)\n", bytes.size());
37 :
38 : size_t current = 0;
39 12459 : while (ok() && current < bytes.size()) {
40 : size_t num_bytes =
41 9561 : state_->ReadBytes(this, bytes.SubVector(current, bytes.size()));
42 9561 : current += num_bytes;
43 9561 : module_offset_ += num_bytes;
44 9561 : if (state_->offset() == state_->buffer().size()) {
45 17376 : state_ = state_->Next(this);
46 : }
47 : }
48 2898 : total_size_ += bytes.size();
49 2898 : if (ok()) {
50 1774 : processor_->OnFinishedChunk();
51 : }
52 : }
53 :
54 6145 : size_t StreamingDecoder::DecodingState::ReadBytes(StreamingDecoder* streaming,
55 12290 : Vector<const uint8_t> bytes) {
56 12290 : Vector<uint8_t> remaining_buf = buffer() + offset();
57 12290 : size_t num_bytes = std::min(bytes.size(), remaining_buf.size());
58 : TRACE_STREAMING("ReadBytes(%zu bytes)\n", num_bytes);
59 6145 : memcpy(remaining_buf.start(), &bytes.first(), num_bytes);
60 6145 : set_offset(offset() + num_bytes);
61 6145 : return num_bytes;
62 : }
63 :
64 1480 : void StreamingDecoder::Finish() {
65 : TRACE_STREAMING("Finish\n");
66 1480 : if (!ok()) return;
67 :
68 520 : if (deserializing()) {
69 10 : Vector<const uint8_t> wire_bytes = VectorOf(wire_bytes_for_deserializing_);
70 : // Try to deserialize the module from wire bytes and module bytes.
71 15 : if (processor_->Deserialize(compiled_module_bytes_, wire_bytes)) return;
72 :
73 : // Deserialization failed. Restart decoding using |wire_bytes|.
74 5 : compiled_module_bytes_ = {};
75 : DCHECK(!deserializing());
76 5 : OnBytesReceived(wire_bytes);
77 : // The decoder has received all wire bytes; fall through and finish.
78 : }
79 :
80 515 : if (!state_->is_finishing_allowed()) {
81 : // The byte stream ended too early, we report an error.
82 291 : Error("unexpected end of stream");
83 97 : return;
84 : }
85 :
86 418 : OwnedVector<uint8_t> bytes = OwnedVector<uint8_t>::New(total_size_);
87 : uint8_t* cursor = bytes.start();
88 : {
89 : #define BYTES(x) (x & 0xFF), (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF
90 418 : uint8_t module_header[]{BYTES(kWasmMagic), BYTES(kWasmVersion)};
91 : #undef BYTES
92 : memcpy(cursor, module_header, arraysize(module_header));
93 418 : cursor += arraysize(module_header);
94 : }
95 1810 : for (const auto& buffer : section_buffers_) {
96 : DCHECK_LE(cursor - bytes.start() + buffer->length(), total_size_);
97 1948 : memcpy(cursor, buffer->bytes().start(), buffer->length());
98 974 : cursor += buffer->length();
99 : }
100 1254 : processor_->OnFinishedStream(std::move(bytes));
101 : }
102 :
103 70 : void StreamingDecoder::Abort() {
104 : TRACE_STREAMING("Abort\n");
105 140 : if (!ok()) return; // Failed already.
106 65 : processor_->OnAbort();
107 : Fail();
108 : }
109 :
110 5 : void StreamingDecoder::SetModuleCompiledCallback(
111 : ModuleCompiledCallback callback) {
112 : DCHECK_NULL(module_compiled_callback_);
113 5 : module_compiled_callback_ = callback;
114 5 : }
115 :
116 10 : bool StreamingDecoder::SetCompiledModuleBytes(
117 : Vector<const uint8_t> compiled_module_bytes) {
118 10 : compiled_module_bytes_ = compiled_module_bytes;
119 10 : return true;
120 : }
121 :
122 : namespace {
123 :
124 50 : class TopTierCompiledCallback {
125 : public:
126 : TopTierCompiledCallback(std::shared_ptr<NativeModule> native_module,
127 : StreamingDecoder::ModuleCompiledCallback callback)
128 : : native_module_(std::move(native_module)),
129 5 : callback_(std::move(callback)) {}
130 :
131 : void operator()(CompilationEvent event, const WasmError* error) const {
132 10 : if (event != CompilationEvent::kFinishedTopTierCompilation) return;
133 : DCHECK_NULL(error);
134 5 : callback_(native_module_);
135 : #ifdef DEBUG
136 : DCHECK(!called_);
137 : called_ = true;
138 : #endif
139 : }
140 :
141 : private:
142 : const std::shared_ptr<NativeModule> native_module_;
143 : const StreamingDecoder::ModuleCompiledCallback callback_;
144 : #ifdef DEBUG
145 : mutable bool called_ = false;
146 : #endif
147 : };
148 :
149 : } // namespace
150 :
151 253 : void StreamingDecoder::NotifyNativeModuleCreated(
152 : const std::shared_ptr<NativeModule>& native_module) {
153 506 : if (!module_compiled_callback_) return;
154 5 : auto* comp_state = native_module->compilation_state();
155 : comp_state->AddCallback(TopTierCompiledCallback{
156 20 : std::move(native_module), std::move(module_compiled_callback_)});
157 : module_compiled_callback_ = {};
158 : }
159 :
160 : // An abstract class to share code among the states which decode VarInts. This
161 : // class takes over the decoding of the VarInt and then calls the actual decode
162 : // code with the decoded value.
163 3440 : class StreamingDecoder::DecodeVarInt32 : public DecodingState {
164 : public:
165 : explicit DecodeVarInt32(size_t max_value, const char* field_name)
166 3440 : : max_value_(max_value), field_name_(field_name) {}
167 :
168 13420 : Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); }
169 :
170 : size_t ReadBytes(StreamingDecoder* streaming,
171 : Vector<const uint8_t> bytes) override;
172 :
173 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
174 :
175 : virtual std::unique_ptr<DecodingState> NextWithValue(
176 : StreamingDecoder* streaming) = 0;
177 :
178 : protected:
179 : uint8_t byte_buffer_[kMaxVarInt32Size];
180 : // The maximum valid value decoded in this state. {Next} returns an error if
181 : // this value is exceeded.
182 : const size_t max_value_;
183 : const char* const field_name_;
184 : size_t value_ = 0;
185 : size_t bytes_consumed_ = 0;
186 : };
187 :
188 4680 : class StreamingDecoder::DecodeModuleHeader : public DecodingState {
189 : public:
190 5890 : Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); }
191 :
192 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
193 :
194 : private:
195 : // Checks if the magic bytes of the module header are correct.
196 : void CheckHeader(Decoder* decoder);
197 :
198 : // The size of the module header.
199 : static constexpr size_t kModuleHeaderSize = 8;
200 : uint8_t byte_buffer_[kModuleHeaderSize];
201 : };
202 :
203 4604 : class StreamingDecoder::DecodeSectionID : public DecodingState {
204 : public:
205 : explicit DecodeSectionID(uint32_t module_offset)
206 2302 : : module_offset_(module_offset) {}
207 :
208 3718 : Vector<uint8_t> buffer() override { return {&id_, 1}; }
209 418 : bool is_finishing_allowed() const override { return true; }
210 :
211 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
212 :
213 : private:
214 : uint8_t id_ = 0;
215 : // The start offset of this section in the module.
216 : const uint32_t module_offset_;
217 : };
218 :
219 3718 : class StreamingDecoder::DecodeSectionLength : public DecodeVarInt32 {
220 : public:
221 : explicit DecodeSectionLength(uint8_t id, uint32_t module_offset)
222 : : DecodeVarInt32(kV8MaxWasmModuleSize, "section length"),
223 : section_id_(id),
224 1859 : module_offset_(module_offset) {}
225 :
226 : std::unique_ptr<DecodingState> NextWithValue(
227 : StreamingDecoder* streaming) override;
228 :
229 : private:
230 : const uint8_t section_id_;
231 : // The start offset of this section in the module.
232 : const uint32_t module_offset_;
233 : };
234 :
235 2270 : class StreamingDecoder::DecodeSectionPayload : public DecodingState {
236 : public:
237 : explicit DecodeSectionPayload(SectionBuffer* section_buffer)
238 1135 : : section_buffer_(section_buffer) {}
239 :
240 4752 : Vector<uint8_t> buffer() override { return section_buffer_->payload(); }
241 :
242 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
243 :
244 : private:
245 : SectionBuffer* const section_buffer_;
246 : };
247 :
248 1152 : class StreamingDecoder::DecodeNumberOfFunctions : public DecodeVarInt32 {
249 : public:
250 : explicit DecodeNumberOfFunctions(SectionBuffer* section_buffer)
251 : : DecodeVarInt32(kV8MaxWasmFunctions, "functions count"),
252 576 : section_buffer_(section_buffer) {}
253 :
254 : std::unique_ptr<DecodingState> NextWithValue(
255 : StreamingDecoder* streaming) override;
256 :
257 : private:
258 : SectionBuffer* const section_buffer_;
259 : };
260 :
261 2010 : class StreamingDecoder::DecodeFunctionLength : public DecodeVarInt32 {
262 : public:
263 : explicit DecodeFunctionLength(SectionBuffer* section_buffer,
264 : size_t buffer_offset,
265 : size_t num_remaining_functions)
266 : : DecodeVarInt32(kV8MaxWasmFunctionSize, "body size"),
267 : section_buffer_(section_buffer),
268 : buffer_offset_(buffer_offset),
269 : // We are reading a new function, so one function less is remaining.
270 1005 : num_remaining_functions_(num_remaining_functions - 1) {
271 : DCHECK_GT(num_remaining_functions, 0);
272 : }
273 :
274 : std::unique_ptr<DecodingState> NextWithValue(
275 : StreamingDecoder* streaming) override;
276 :
277 : private:
278 : SectionBuffer* const section_buffer_;
279 : const size_t buffer_offset_;
280 : const size_t num_remaining_functions_;
281 : };
282 :
283 1712 : class StreamingDecoder::DecodeFunctionBody : public DecodingState {
284 : public:
285 : explicit DecodeFunctionBody(SectionBuffer* section_buffer,
286 : size_t buffer_offset, size_t function_body_length,
287 : size_t num_remaining_functions,
288 : uint32_t module_offset)
289 : : section_buffer_(section_buffer),
290 : buffer_offset_(buffer_offset),
291 : function_body_length_(function_body_length),
292 : num_remaining_functions_(num_remaining_functions),
293 856 : module_offset_(module_offset) {}
294 :
295 2650 : Vector<uint8_t> buffer() override {
296 : Vector<uint8_t> remaining_buffer =
297 2650 : section_buffer_->bytes() + buffer_offset_;
298 2650 : return remaining_buffer.SubVector(0, function_body_length_);
299 : }
300 :
301 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
302 :
303 : private:
304 : SectionBuffer* const section_buffer_;
305 : const size_t buffer_offset_;
306 : const size_t function_body_length_;
307 : const size_t num_remaining_functions_;
308 : const uint32_t module_offset_;
309 : };
310 :
311 3416 : size_t StreamingDecoder::DecodeVarInt32::ReadBytes(
312 3416 : StreamingDecoder* streaming, Vector<const uint8_t> bytes) {
313 3416 : Vector<uint8_t> buf = buffer();
314 10248 : Vector<uint8_t> remaining_buf = buf + offset();
315 6832 : size_t new_bytes = std::min(bytes.size(), remaining_buf.size());
316 : TRACE_STREAMING("ReadBytes of a VarInt\n");
317 3416 : memcpy(remaining_buf.start(), &bytes.first(), new_bytes);
318 3416 : buf.Truncate(offset() + new_bytes);
319 : Decoder decoder(buf, streaming->module_offset());
320 6832 : value_ = decoder.consume_u32v(field_name_);
321 : // The number of bytes we actually needed to read.
322 : DCHECK_GT(decoder.pc(), buffer().start());
323 3416 : bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.start());
324 : TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_);
325 :
326 3416 : if (decoder.failed()) {
327 65 : if (new_bytes == remaining_buf.size()) {
328 : // We only report an error if we read all bytes.
329 84 : streaming->Error(decoder.error());
330 : }
331 65 : set_offset(offset() + new_bytes);
332 65 : return new_bytes;
333 : }
334 :
335 : // We read all the bytes we needed.
336 : DCHECK_GT(bytes_consumed_, offset());
337 3351 : new_bytes = bytes_consumed_ - offset();
338 : // Set the offset to the buffer size to signal that we are at the end of this
339 : // section.
340 6702 : set_offset(buffer().size());
341 3351 : return new_bytes;
342 : }
343 :
344 : std::unique_ptr<StreamingDecoder::DecodingState>
345 3393 : StreamingDecoder::DecodeVarInt32::Next(StreamingDecoder* streaming) {
346 3393 : if (!streaming->ok()) return nullptr;
347 :
348 3351 : if (value_ > max_value_) {
349 42 : std::ostringstream oss;
350 84 : oss << "function size > maximum function size: " << value_ << " < "
351 42 : << max_value_;
352 84 : return streaming->Error(oss.str());
353 : }
354 :
355 3309 : return NextWithValue(streaming);
356 : }
357 :
358 : std::unique_ptr<StreamingDecoder::DecodingState>
359 2382 : StreamingDecoder::DecodeModuleHeader::Next(StreamingDecoder* streaming) {
360 : TRACE_STREAMING("DecodeModuleHeader\n");
361 1488 : streaming->ProcessModuleHeader();
362 1488 : if (!streaming->ok()) return nullptr;
363 1788 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
364 : }
365 :
366 : std::unique_ptr<StreamingDecoder::DecodingState>
367 1859 : StreamingDecoder::DecodeSectionID::Next(StreamingDecoder* streaming) {
368 : TRACE_STREAMING("DecodeSectionID: %s section\n",
369 : SectionName(static_cast<SectionCode>(id_)));
370 3718 : return base::make_unique<DecodeSectionLength>(id_, module_offset_);
371 : }
372 :
373 : std::unique_ptr<StreamingDecoder::DecodingState>
374 1811 : StreamingDecoder::DecodeSectionLength::NextWithValue(
375 : StreamingDecoder* streaming) {
376 : TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_);
377 : SectionBuffer* buf =
378 : streaming->CreateNewBuffer(module_offset_, section_id_, value_,
379 3622 : buffer().SubVector(0, bytes_consumed_));
380 1811 : if (!buf) return nullptr;
381 1768 : if (value_ == 0) {
382 57 : if (section_id_ == SectionCode::kCodeSectionCode) {
383 40 : return streaming->Error("Code section cannot have size 0");
384 : }
385 37 : streaming->ProcessSection(buf);
386 37 : if (!streaming->ok()) return nullptr;
387 : // There is no payload, we go to the next section immediately.
388 74 : return base::make_unique<DecodeSectionID>(streaming->module_offset_);
389 : } else {
390 1711 : if (section_id_ == SectionCode::kCodeSectionCode) {
391 : // We reached the code section. All functions of the code section are put
392 : // into the same SectionBuffer.
393 1152 : return base::make_unique<DecodeNumberOfFunctions>(buf);
394 : }
395 : return base::make_unique<DecodeSectionPayload>(buf);
396 : }
397 : }
398 :
399 : std::unique_ptr<StreamingDecoder::DecodingState>
400 2160 : StreamingDecoder::DecodeSectionPayload::Next(StreamingDecoder* streaming) {
401 : TRACE_STREAMING("DecodeSectionPayload\n");
402 1092 : streaming->ProcessSection(section_buffer_);
403 1092 : if (!streaming->ok()) return nullptr;
404 2136 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
405 : }
406 :
407 : std::unique_ptr<StreamingDecoder::DecodingState>
408 558 : StreamingDecoder::DecodeNumberOfFunctions::NextWithValue(
409 5 : StreamingDecoder* streaming) {
410 : TRACE_STREAMING("DecodeNumberOfFunctions(%zu)\n", value_);
411 : // Copy the bytes we read into the section buffer.
412 1061 : Vector<uint8_t> payload_buf = section_buffer_->payload();
413 558 : if (payload_buf.size() < bytes_consumed_) {
414 48 : return streaming->Error("Invalid code section length");
415 : }
416 1068 : memcpy(payload_buf.start(), buffer().start(), bytes_consumed_);
417 :
418 : // {value} is the number of functions.
419 534 : if (value_ == 0) {
420 17 : if (payload_buf.size() != bytes_consumed_) {
421 24 : return streaming->Error("not all code section bytes were consumed");
422 : }
423 10 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
424 : }
425 :
426 1034 : streaming->StartCodeSection(value_, streaming->section_buffers_.back());
427 517 : if (!streaming->ok()) return nullptr;
428 : return base::make_unique<DecodeFunctionLength>(
429 1006 : section_buffer_, section_buffer_->payload_offset() + bytes_consumed_,
430 1509 : value_);
431 : }
432 :
433 : std::unique_ptr<StreamingDecoder::DecodingState>
434 940 : StreamingDecoder::DecodeFunctionLength::NextWithValue(
435 856 : StreamingDecoder* streaming) {
436 : TRACE_STREAMING("DecodeFunctionLength(%zu)\n", value_);
437 : // Copy the bytes we consumed into the section buffer.
438 940 : Vector<uint8_t> fun_length_buffer = section_buffer_->bytes() + buffer_offset_;
439 940 : if (fun_length_buffer.size() < bytes_consumed_) {
440 96 : return streaming->Error("Invalid code section length");
441 : }
442 1784 : memcpy(fun_length_buffer.start(), buffer().start(), bytes_consumed_);
443 :
444 : // {value} is the length of the function.
445 914 : if (value_ == 0) return streaming->Error("Invalid function length (0)");
446 :
447 1740 : if (buffer_offset_ + bytes_consumed_ + value_ > section_buffer_->length()) {
448 28 : return streaming->Error("not enough code section bytes");
449 : }
450 :
451 : return base::make_unique<DecodeFunctionBody>(
452 : section_buffer_, buffer_offset_ + bytes_consumed_, value_,
453 1712 : num_remaining_functions_, streaming->module_offset());
454 : }
455 :
456 : std::unique_ptr<StreamingDecoder::DecodingState>
457 1154 : StreamingDecoder::DecodeFunctionBody::Next(StreamingDecoder* streaming) {
458 : TRACE_STREAMING("DecodeFunctionBody\n");
459 1712 : streaming->ProcessFunctionBody(buffer(), module_offset_);
460 856 : if (!streaming->ok()) return nullptr;
461 :
462 856 : size_t end_offset = buffer_offset_ + function_body_length_;
463 856 : if (num_remaining_functions_ > 0) {
464 : return base::make_unique<DecodeFunctionLength>(section_buffer_, end_offset,
465 1004 : num_remaining_functions_);
466 : }
467 : // We just read the last function body. Continue with the next section.
468 708 : if (end_offset != section_buffer_->length()) {
469 112 : return streaming->Error("not all code section bytes were used");
470 : }
471 596 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
472 : }
473 :
474 1560 : StreamingDecoder::StreamingDecoder(
475 : std::unique_ptr<StreamingProcessor> processor)
476 : : processor_(std::move(processor)),
477 : // A module always starts with a module header.
478 4680 : state_(new DecodeModuleHeader()) {}
479 :
480 1811 : StreamingDecoder::SectionBuffer* StreamingDecoder::CreateNewBuffer(
481 : uint32_t module_offset, uint8_t section_id, size_t length,
482 : Vector<const uint8_t> length_bytes) {
483 : // Check the order of sections. Unknown sections can appear at any position.
484 1811 : if (section_id != kUnknownSectionCode) {
485 1698 : if (section_id < next_section_id_) {
486 129 : Error("Unexpected section");
487 43 : return nullptr;
488 : }
489 1655 : next_section_id_ = section_id + 1;
490 : }
491 : section_buffers_.emplace_back(std::make_shared<SectionBuffer>(
492 3536 : module_offset, section_id, length, length_bytes));
493 1768 : return section_buffers_.back().get();
494 : }
495 :
496 : } // namespace wasm
497 : } // namespace internal
498 183867 : } // namespace v8
499 :
500 : #undef TRACE_STREAMING
|