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 2873 : void StreamingDecoder::OnBytesReceived(Vector<const uint8_t> bytes) {
30 2873 : if (deserializing()) {
31 : wire_bytes_for_deserializing_.insert(wire_bytes_for_deserializing_.end(),
32 8 : bytes.begin(), bytes.end());
33 8 : return;
34 : }
35 :
36 : TRACE_STREAMING("OnBytesReceived(%zu bytes)\n", bytes.size());
37 :
38 : size_t current = 0;
39 13057 : while (ok() && current < bytes.size()) {
40 : size_t num_bytes =
41 10192 : state_->ReadBytes(this, bytes.SubVector(current, bytes.size()));
42 10192 : current += num_bytes;
43 10192 : module_offset_ += num_bytes;
44 10192 : if (state_->offset() == state_->buffer().size()) {
45 18656 : state_ = state_->Next(this);
46 : }
47 : }
48 2865 : total_size_ += bytes.size();
49 2865 : if (ok()) {
50 1767 : processor_->OnFinishedChunk();
51 : }
52 : }
53 :
54 6559 : size_t StreamingDecoder::DecodingState::ReadBytes(StreamingDecoder* streaming,
55 : Vector<const uint8_t> bytes) {
56 13118 : Vector<uint8_t> remaining_buf = buffer() + offset();
57 13118 : size_t num_bytes = std::min(bytes.size(), remaining_buf.size());
58 : TRACE_STREAMING("ReadBytes(%zu bytes)\n", num_bytes);
59 : memcpy(remaining_buf.start(), &bytes.first(), num_bytes);
60 6559 : set_offset(offset() + num_bytes);
61 6559 : return num_bytes;
62 : }
63 :
64 1502 : void StreamingDecoder::Finish() {
65 : TRACE_STREAMING("Finish\n");
66 1502 : if (!ok()) return;
67 :
68 551 : if (deserializing()) {
69 8 : Vector<const uint8_t> wire_bytes = VectorOf(wire_bytes_for_deserializing_);
70 : // Try to deserialize the module from wire bytes and module bytes.
71 12 : if (processor_->Deserialize(compiled_module_bytes_, wire_bytes)) return;
72 :
73 : // Deserialization failed. Restart decoding using |wire_bytes|.
74 4 : compiled_module_bytes_ = {};
75 : DCHECK(!deserializing());
76 4 : OnBytesReceived(wire_bytes);
77 : // The decoder has received all wire bytes; fall through and finish.
78 : }
79 :
80 547 : if (!state_->is_finishing_allowed()) {
81 : // The byte stream ended too early, we report an error.
82 285 : Error("unexpected end of stream");
83 95 : return;
84 : }
85 :
86 452 : 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 452 : uint8_t module_header[]{BYTES(kWasmMagic), BYTES(kWasmVersion)};
91 : #undef BYTES
92 : memcpy(cursor, module_header, arraysize(module_header));
93 452 : cursor += arraysize(module_header);
94 : }
95 1626 : for (const auto& buffer : section_buffers_) {
96 : DCHECK_LE(cursor - bytes.start() + buffer->length(), total_size_);
97 : memcpy(cursor, buffer->bytes().start(), buffer->length());
98 1174 : cursor += buffer->length();
99 : }
100 1356 : processor_->OnFinishedStream(std::move(bytes));
101 : }
102 :
103 72 : void StreamingDecoder::Abort() {
104 : TRACE_STREAMING("Abort\n");
105 72 : if (!ok()) return; // Failed already.
106 72 : processor_->OnAbort();
107 : Fail();
108 : }
109 :
110 4 : void StreamingDecoder::SetModuleCompiledCallback(
111 : ModuleCompiledCallback callback) {
112 : DCHECK_NULL(module_compiled_callback_);
113 4 : module_compiled_callback_ = callback;
114 4 : }
115 :
116 8 : bool StreamingDecoder::SetCompiledModuleBytes(
117 : Vector<const uint8_t> compiled_module_bytes) {
118 8 : compiled_module_bytes_ = compiled_module_bytes;
119 8 : return true;
120 : }
121 :
122 : namespace {
123 :
124 40 : class TopTierCompiledCallback {
125 : public:
126 : TopTierCompiledCallback(std::weak_ptr<NativeModule> native_module,
127 : StreamingDecoder::ModuleCompiledCallback callback)
128 : : native_module_(std::move(native_module)),
129 : callback_(std::move(callback)) {}
130 :
131 8 : void operator()(CompilationEvent event) const {
132 8 : if (event != CompilationEvent::kFinishedTopTierCompilation) return;
133 : // If the native module is still alive, get back a shared ptr and call the
134 : // callback.
135 4 : if (std::shared_ptr<NativeModule> native_module = native_module_.lock()) {
136 : callback_(native_module);
137 : }
138 : #ifdef DEBUG
139 : DCHECK(!called_);
140 : called_ = true;
141 : #endif
142 : }
143 :
144 : private:
145 : const std::weak_ptr<NativeModule> native_module_;
146 : const StreamingDecoder::ModuleCompiledCallback callback_;
147 : #ifdef DEBUG
148 : mutable bool called_ = false;
149 : #endif
150 : };
151 :
152 : } // namespace
153 :
154 284 : void StreamingDecoder::NotifyNativeModuleCreated(
155 : const std::shared_ptr<NativeModule>& native_module) {
156 284 : if (!module_compiled_callback_) return;
157 : auto* comp_state = native_module->compilation_state();
158 16 : comp_state->AddCallback(TopTierCompiledCallback{
159 4 : std::move(native_module), std::move(module_compiled_callback_)});
160 : module_compiled_callback_ = {};
161 : }
162 :
163 : // An abstract class to share code among the states which decode VarInts. This
164 : // class takes over the decoding of the VarInt and then calls the actual decode
165 : // code with the decoded value.
166 3650 : class StreamingDecoder::DecodeVarInt32 : public DecodingState {
167 : public:
168 : explicit DecodeVarInt32(size_t max_value, const char* field_name)
169 3650 : : max_value_(max_value), field_name_(field_name) {}
170 :
171 14304 : Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); }
172 :
173 : size_t ReadBytes(StreamingDecoder* streaming,
174 : Vector<const uint8_t> bytes) override;
175 :
176 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
177 :
178 : virtual std::unique_ptr<DecodingState> NextWithValue(
179 : StreamingDecoder* streaming) = 0;
180 :
181 : protected:
182 : uint8_t byte_buffer_[kMaxVarInt32Size];
183 : // The maximum valid value decoded in this state. {Next} returns an error if
184 : // this value is exceeded.
185 : const size_t max_value_;
186 : const char* const field_name_;
187 : size_t value_ = 0;
188 : size_t bytes_consumed_ = 0;
189 : };
190 :
191 4746 : class StreamingDecoder::DecodeModuleHeader : public DecodingState {
192 : public:
193 5927 : Vector<uint8_t> buffer() override { return ArrayVector(byte_buffer_); }
194 :
195 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
196 :
197 : private:
198 : // Checks if the magic bytes of the module header are correct.
199 : void CheckHeader(Decoder* decoder);
200 :
201 : // The size of the module header.
202 : static constexpr size_t kModuleHeaderSize = 8;
203 : uint8_t byte_buffer_[kModuleHeaderSize];
204 : };
205 :
206 5092 : class StreamingDecoder::DecodeSectionID : public DecodingState {
207 : public:
208 : explicit DecodeSectionID(uint32_t module_offset)
209 2546 : : module_offset_(module_offset) {}
210 :
211 4148 : Vector<uint8_t> buffer() override { return {&id_, 1}; }
212 452 : bool is_finishing_allowed() const override { return true; }
213 :
214 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
215 :
216 : private:
217 : uint8_t id_ = 0;
218 : // The start offset of this section in the module.
219 : const uint32_t module_offset_;
220 : };
221 :
222 4148 : class StreamingDecoder::DecodeSectionLength : public DecodeVarInt32 {
223 : public:
224 : explicit DecodeSectionLength(uint8_t id, uint32_t module_offset)
225 : : DecodeVarInt32(kV8MaxWasmModuleSize, "section length"),
226 : section_id_(id),
227 2074 : module_offset_(module_offset) {}
228 :
229 : std::unique_ptr<DecodingState> NextWithValue(
230 : StreamingDecoder* streaming) override;
231 :
232 : private:
233 : const uint8_t section_id_;
234 : // The start offset of this section in the module.
235 : const uint32_t module_offset_;
236 : };
237 :
238 2664 : class StreamingDecoder::DecodeSectionPayload : public DecodingState {
239 : public:
240 : explicit DecodeSectionPayload(SectionBuffer* section_buffer)
241 1332 : : section_buffer_(section_buffer) {}
242 :
243 5528 : Vector<uint8_t> buffer() override { return section_buffer_->payload(); }
244 :
245 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
246 :
247 : private:
248 : SectionBuffer* const section_buffer_;
249 : };
250 :
251 1184 : class StreamingDecoder::DecodeNumberOfFunctions : public DecodeVarInt32 {
252 : public:
253 : explicit DecodeNumberOfFunctions(SectionBuffer* section_buffer)
254 : : DecodeVarInt32(kV8MaxWasmFunctions, "functions count"),
255 592 : section_buffer_(section_buffer) {}
256 :
257 : std::unique_ptr<DecodingState> NextWithValue(
258 : StreamingDecoder* streaming) override;
259 :
260 : private:
261 : SectionBuffer* const section_buffer_;
262 : };
263 :
264 1968 : class StreamingDecoder::DecodeFunctionLength : public DecodeVarInt32 {
265 : public:
266 : explicit DecodeFunctionLength(SectionBuffer* section_buffer,
267 : size_t buffer_offset,
268 : size_t num_remaining_functions)
269 : : DecodeVarInt32(kV8MaxWasmFunctionSize, "body size"),
270 : section_buffer_(section_buffer),
271 : buffer_offset_(buffer_offset),
272 : // We are reading a new function, so one function less is remaining.
273 984 : num_remaining_functions_(num_remaining_functions - 1) {
274 : DCHECK_GT(num_remaining_functions, 0);
275 : }
276 :
277 : std::unique_ptr<DecodingState> NextWithValue(
278 : StreamingDecoder* streaming) override;
279 :
280 : private:
281 : SectionBuffer* const section_buffer_;
282 : const size_t buffer_offset_;
283 : const size_t num_remaining_functions_;
284 : };
285 :
286 1698 : class StreamingDecoder::DecodeFunctionBody : public DecodingState {
287 : public:
288 : explicit DecodeFunctionBody(SectionBuffer* section_buffer,
289 : size_t buffer_offset, size_t function_body_length,
290 : size_t num_remaining_functions,
291 : uint32_t module_offset)
292 : : section_buffer_(section_buffer),
293 : buffer_offset_(buffer_offset),
294 : function_body_length_(function_body_length),
295 : num_remaining_functions_(num_remaining_functions),
296 849 : module_offset_(module_offset) {}
297 :
298 2629 : Vector<uint8_t> buffer() override {
299 : Vector<uint8_t> remaining_buffer =
300 2629 : section_buffer_->bytes() + buffer_offset_;
301 2629 : return remaining_buffer.SubVector(0, function_body_length_);
302 : }
303 :
304 : std::unique_ptr<DecodingState> Next(StreamingDecoder* streaming) override;
305 :
306 : private:
307 : SectionBuffer* const section_buffer_;
308 : const size_t buffer_offset_;
309 : const size_t function_body_length_;
310 : const size_t num_remaining_functions_;
311 : const uint32_t module_offset_;
312 : };
313 :
314 3633 : size_t StreamingDecoder::DecodeVarInt32::ReadBytes(
315 : StreamingDecoder* streaming, Vector<const uint8_t> bytes) {
316 3633 : Vector<uint8_t> buf = buffer();
317 : Vector<uint8_t> remaining_buf = buf + offset();
318 7266 : size_t new_bytes = std::min(bytes.size(), remaining_buf.size());
319 : TRACE_STREAMING("ReadBytes of a VarInt\n");
320 : memcpy(remaining_buf.start(), &bytes.first(), new_bytes);
321 3633 : buf.Truncate(offset() + new_bytes);
322 : Decoder decoder(buf,
323 3633 : streaming->module_offset() - static_cast<uint32_t>(offset()));
324 7266 : value_ = decoder.consume_u32v(field_name_);
325 : // The number of bytes we actually needed to read.
326 : DCHECK_GT(decoder.pc(), buffer().start());
327 3633 : bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.start());
328 : TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_);
329 :
330 3633 : if (decoder.failed()) {
331 60 : if (new_bytes == remaining_buf.size()) {
332 : // We only report an error if we read all bytes.
333 78 : streaming->Error(decoder.error());
334 : }
335 60 : set_offset(offset() + new_bytes);
336 60 : return new_bytes;
337 : }
338 :
339 : // We read all the bytes we needed.
340 : DCHECK_GT(bytes_consumed_, offset());
341 3573 : new_bytes = bytes_consumed_ - offset();
342 : // Set the offset to the buffer size to signal that we are at the end of this
343 : // section.
344 7146 : set_offset(buffer().size());
345 3573 : return new_bytes;
346 : }
347 :
348 : std::unique_ptr<StreamingDecoder::DecodingState>
349 3612 : StreamingDecoder::DecodeVarInt32::Next(StreamingDecoder* streaming) {
350 3612 : if (!streaming->ok()) return nullptr;
351 :
352 3573 : if (value_ > max_value_) {
353 72 : std::ostringstream oss;
354 36 : oss << "function size > maximum function size: " << value_ << " < "
355 36 : << max_value_;
356 72 : return streaming->Error(oss.str());
357 : }
358 :
359 3537 : return NextWithValue(streaming);
360 : }
361 :
362 : std::unique_ptr<StreamingDecoder::DecodingState>
363 1501 : StreamingDecoder::DecodeModuleHeader::Next(StreamingDecoder* streaming) {
364 : TRACE_STREAMING("DecodeModuleHeader\n");
365 1501 : streaming->ProcessModuleHeader();
366 1501 : if (!streaming->ok()) return nullptr;
367 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
368 : }
369 :
370 : std::unique_ptr<StreamingDecoder::DecodingState>
371 2074 : StreamingDecoder::DecodeSectionID::Next(StreamingDecoder* streaming) {
372 : TRACE_STREAMING("DecodeSectionID: %s section\n",
373 : SectionName(static_cast<SectionCode>(id_)));
374 4148 : return base::make_unique<DecodeSectionLength>(id_, module_offset_);
375 : }
376 :
377 : std::unique_ptr<StreamingDecoder::DecodingState>
378 2031 : StreamingDecoder::DecodeSectionLength::NextWithValue(
379 : StreamingDecoder* streaming) {
380 : TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_);
381 : SectionBuffer* buf =
382 2031 : streaming->CreateNewBuffer(module_offset_, section_id_, value_,
383 4062 : buffer().SubVector(0, bytes_consumed_));
384 : DCHECK_NOT_NULL(buf);
385 2031 : if (value_ == 0) {
386 56 : if (section_id_ == SectionCode::kCodeSectionCode) {
387 38 : return streaming->Error("code section cannot have size 0");
388 : }
389 : // Process section without payload as well, to enforce section order and
390 : // other feature checks specific to each individual section.
391 37 : streaming->ProcessSection(buf);
392 37 : if (!streaming->ok()) return nullptr;
393 : // There is no payload, we go to the next section immediately.
394 : return base::make_unique<DecodeSectionID>(streaming->module_offset_);
395 : } else {
396 1975 : if (section_id_ == SectionCode::kCodeSectionCode) {
397 : // Explicitly check for multiple code sections as module decoder never
398 : // sees the code section and hence cannot track this section.
399 643 : if (streaming->code_section_processed_) {
400 : // TODO(mstarzinger): This error message (and other in this class) is
401 : // different for non-streaming decoding. Bring them in sync and test.
402 102 : return streaming->Error("code section can only appear once");
403 : }
404 592 : streaming->code_section_processed_ = true;
405 : // We reached the code section. All functions of the code section are put
406 : // into the same SectionBuffer.
407 1184 : return base::make_unique<DecodeNumberOfFunctions>(buf);
408 : }
409 : return base::make_unique<DecodeSectionPayload>(buf);
410 : }
411 : }
412 :
413 : std::unique_ptr<StreamingDecoder::DecodingState>
414 1292 : StreamingDecoder::DecodeSectionPayload::Next(StreamingDecoder* streaming) {
415 : TRACE_STREAMING("DecodeSectionPayload\n");
416 1292 : streaming->ProcessSection(section_buffer_);
417 1292 : if (!streaming->ok()) return nullptr;
418 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
419 : }
420 :
421 : std::unique_ptr<StreamingDecoder::DecodingState>
422 576 : StreamingDecoder::DecodeNumberOfFunctions::NextWithValue(
423 : StreamingDecoder* streaming) {
424 : TRACE_STREAMING("DecodeNumberOfFunctions(%zu)\n", value_);
425 : // Copy the bytes we read into the section buffer.
426 576 : Vector<uint8_t> payload_buf = section_buffer_->payload();
427 576 : if (payload_buf.size() < bytes_consumed_) {
428 48 : return streaming->Error("invalid code section length");
429 : }
430 1104 : memcpy(payload_buf.start(), buffer().start(), bytes_consumed_);
431 :
432 : // {value} is the number of functions.
433 552 : if (value_ == 0) {
434 16 : if (payload_buf.size() != bytes_consumed_) {
435 24 : return streaming->Error("not all code section bytes were used");
436 : }
437 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
438 : }
439 :
440 : DCHECK_GE(kMaxInt, value_);
441 1072 : streaming->StartCodeSection(static_cast<int>(value_),
442 536 : streaming->section_buffers_.back());
443 536 : if (!streaming->ok()) return nullptr;
444 1572 : return base::make_unique<DecodeFunctionLength>(
445 524 : section_buffer_, section_buffer_->payload_offset() + bytes_consumed_,
446 : value_);
447 : }
448 :
449 : std::unique_ptr<StreamingDecoder::DecodingState>
450 930 : StreamingDecoder::DecodeFunctionLength::NextWithValue(
451 : StreamingDecoder* streaming) {
452 : TRACE_STREAMING("DecodeFunctionLength(%zu)\n", value_);
453 : // Copy the bytes we consumed into the section buffer.
454 930 : Vector<uint8_t> fun_length_buffer = section_buffer_->bytes() + buffer_offset_;
455 930 : if (fun_length_buffer.size() < bytes_consumed_) {
456 96 : return streaming->Error("read past code section end");
457 : }
458 1764 : memcpy(fun_length_buffer.start(), buffer().start(), bytes_consumed_);
459 :
460 : // {value} is the length of the function.
461 903 : if (value_ == 0) return streaming->Error("invalid function length (0)");
462 :
463 861 : if (buffer_offset_ + bytes_consumed_ + value_ > section_buffer_->length()) {
464 24 : return streaming->Error("not enough code section bytes");
465 : }
466 :
467 : return base::make_unique<DecodeFunctionBody>(
468 : section_buffer_, buffer_offset_ + bytes_consumed_, value_,
469 : num_remaining_functions_, streaming->module_offset());
470 : }
471 :
472 : std::unique_ptr<StreamingDecoder::DecodingState>
473 849 : StreamingDecoder::DecodeFunctionBody::Next(StreamingDecoder* streaming) {
474 : TRACE_STREAMING("DecodeFunctionBody\n");
475 1698 : streaming->ProcessFunctionBody(buffer(), module_offset_);
476 849 : if (!streaming->ok()) return nullptr;
477 :
478 841 : size_t end_offset = buffer_offset_ + function_body_length_;
479 841 : if (num_remaining_functions_ > 0) {
480 920 : return base::make_unique<DecodeFunctionLength>(section_buffer_, end_offset,
481 : num_remaining_functions_);
482 : }
483 : // We just read the last function body. Continue with the next section.
484 381 : if (end_offset != section_buffer_->length()) {
485 98 : return streaming->Error("not all code section bytes were used");
486 : }
487 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
488 : }
489 :
490 1582 : StreamingDecoder::StreamingDecoder(
491 : std::unique_ptr<StreamingProcessor> processor)
492 : : processor_(std::move(processor)),
493 : // A module always starts with a module header.
494 4746 : state_(new DecodeModuleHeader()) {}
495 :
496 2031 : StreamingDecoder::SectionBuffer* StreamingDecoder::CreateNewBuffer(
497 : uint32_t module_offset, uint8_t section_id, size_t length,
498 : Vector<const uint8_t> length_bytes) {
499 : // Section buffers are allocated in the same order they appear in the module,
500 : // they will be processed and later on concatenated in that same order.
501 4062 : section_buffers_.emplace_back(std::make_shared<SectionBuffer>(
502 2031 : module_offset, section_id, length, length_bytes));
503 2031 : return section_buffers_.back().get();
504 : }
505 :
506 : } // namespace wasm
507 : } // namespace internal
508 122004 : } // namespace v8
509 :
510 : #undef TRACE_STREAMING
|