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 2797 : void StreamingDecoder::OnBytesReceived(Vector<const uint8_t> bytes) {
30 2797 : if (deserializing()) {
31 : wire_bytes_for_deserializing_.insert(wire_bytes_for_deserializing_.end(),
32 8 : bytes.begin(), bytes.end());
33 2797 : return;
34 : }
35 :
36 : TRACE_STREAMING("OnBytesReceived(%zu bytes)\n", bytes.size());
37 :
38 : size_t current = 0;
39 11565 : while (ok() && current < bytes.size()) {
40 : size_t num_bytes =
41 8776 : state_->ReadBytes(this, bytes.SubVector(current, bytes.size()));
42 8776 : current += num_bytes;
43 8776 : module_offset_ += num_bytes;
44 8776 : if (state_->offset() == state_->buffer().size()) {
45 15824 : state_ = state_->Next(this);
46 : }
47 : }
48 2789 : total_size_ += bytes.size();
49 2789 : if (ok()) {
50 1699 : processor_->OnFinishedChunk();
51 : }
52 : }
53 :
54 5675 : size_t StreamingDecoder::DecodingState::ReadBytes(StreamingDecoder* streaming,
55 11350 : Vector<const uint8_t> bytes) {
56 11350 : Vector<uint8_t> remaining_buf = buffer() + offset();
57 11350 : size_t num_bytes = std::min(bytes.size(), remaining_buf.size());
58 : TRACE_STREAMING("ReadBytes(%zu bytes)\n", num_bytes);
59 5675 : memcpy(remaining_buf.start(), &bytes.first(), num_bytes);
60 5675 : set_offset(offset() + num_bytes);
61 5675 : return num_bytes;
62 : }
63 :
64 1428 : void StreamingDecoder::Finish() {
65 : TRACE_STREAMING("Finish\n");
66 1428 : if (!ok()) return;
67 :
68 491 : 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 487 : 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 392 : 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 392 : uint8_t module_header[]{BYTES(kWasmMagic), BYTES(kWasmVersion)};
91 : #undef BYTES
92 : memcpy(cursor, module_header, arraysize(module_header));
93 392 : cursor += arraysize(module_header);
94 : }
95 1658 : for (const auto& buffer : section_buffers_) {
96 : DCHECK_LE(cursor - bytes.start() + buffer->length(), total_size_);
97 1748 : memcpy(cursor, buffer->bytes().start(), buffer->length());
98 874 : cursor += buffer->length();
99 : }
100 1176 : processor_->OnFinishedStream(std::move(bytes));
101 : }
102 :
103 56 : void StreamingDecoder::Abort() {
104 : TRACE_STREAMING("Abort\n");
105 112 : if (!ok()) return; // Failed already.
106 52 : 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 4 : TopTierCompiledCallback(std::weak_ptr<NativeModule> native_module,
127 : StreamingDecoder::ModuleCompiledCallback callback)
128 : : native_module_(std::move(native_module)),
129 4 : callback_(std::move(callback)) {}
130 :
131 8 : void operator()(CompilationEvent event) const {
132 16 : 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 4 : 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 212 : void StreamingDecoder::NotifyNativeModuleCreated(
155 : const std::shared_ptr<NativeModule>& native_module) {
156 424 : if (!module_compiled_callback_) return;
157 4 : auto* comp_state = native_module->compilation_state();
158 : comp_state->AddCallback(TopTierCompiledCallback{
159 24 : 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 3122 : class StreamingDecoder::DecodeVarInt32 : public DecodingState {
167 : public:
168 : explicit DecodeVarInt32(size_t max_value, const char* field_name)
169 3122 : : max_value_(max_value), field_name_(field_name) {}
170 :
171 12176 : 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 4476 : class StreamingDecoder::DecodeModuleHeader : public DecodingState {
192 : public:
193 5705 : 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 4168 : class StreamingDecoder::DecodeSectionID : public DecodingState {
207 : public:
208 : explicit DecodeSectionID(uint32_t module_offset)
209 2084 : : module_offset_(module_offset) {}
210 :
211 3344 : Vector<uint8_t> buffer() override { return {&id_, 1}; }
212 392 : 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 3344 : 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 1672 : 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 1992 : class StreamingDecoder::DecodeSectionPayload : public DecodingState {
239 : public:
240 : explicit DecodeSectionPayload(SectionBuffer* section_buffer)
241 996 : : section_buffer_(section_buffer) {}
242 :
243 4184 : 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 1068 : class StreamingDecoder::DecodeNumberOfFunctions : public DecodeVarInt32 {
252 : public:
253 : explicit DecodeNumberOfFunctions(SectionBuffer* section_buffer)
254 : : DecodeVarInt32(kV8MaxWasmFunctions, "functions count"),
255 534 : 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 1832 : 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 916 : 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 1554 : 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 777 : module_offset_(module_offset) {}
297 :
298 2413 : Vector<uint8_t> buffer() override {
299 : Vector<uint8_t> remaining_buffer =
300 2413 : section_buffer_->bytes() + buffer_offset_;
301 2413 : 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 3101 : size_t StreamingDecoder::DecodeVarInt32::ReadBytes(
315 3101 : StreamingDecoder* streaming, Vector<const uint8_t> bytes) {
316 3101 : Vector<uint8_t> buf = buffer();
317 9303 : Vector<uint8_t> remaining_buf = buf + offset();
318 6202 : size_t new_bytes = std::min(bytes.size(), remaining_buf.size());
319 : TRACE_STREAMING("ReadBytes of a VarInt\n");
320 3101 : memcpy(remaining_buf.start(), &bytes.first(), new_bytes);
321 3101 : buf.Truncate(offset() + new_bytes);
322 : Decoder decoder(buf, streaming->module_offset());
323 6202 : value_ = decoder.consume_u32v(field_name_);
324 : // The number of bytes we actually needed to read.
325 : DCHECK_GT(decoder.pc(), buffer().start());
326 3101 : bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.start());
327 : TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_);
328 :
329 3101 : if (decoder.failed()) {
330 60 : if (new_bytes == remaining_buf.size()) {
331 : // We only report an error if we read all bytes.
332 78 : streaming->Error(decoder.error());
333 : }
334 60 : set_offset(offset() + new_bytes);
335 60 : return new_bytes;
336 : }
337 :
338 : // We read all the bytes we needed.
339 : DCHECK_GT(bytes_consumed_, offset());
340 3041 : new_bytes = bytes_consumed_ - offset();
341 : // Set the offset to the buffer size to signal that we are at the end of this
342 : // section.
343 6082 : set_offset(buffer().size());
344 3041 : return new_bytes;
345 : }
346 :
347 : std::unique_ptr<StreamingDecoder::DecodingState>
348 3080 : StreamingDecoder::DecodeVarInt32::Next(StreamingDecoder* streaming) {
349 3080 : if (!streaming->ok()) return nullptr;
350 :
351 3041 : if (value_ > max_value_) {
352 36 : std::ostringstream oss;
353 72 : oss << "function size > maximum function size: " << value_ << " < "
354 36 : << max_value_;
355 72 : return streaming->Error(oss.str());
356 : }
357 :
358 3005 : return NextWithValue(streaming);
359 : }
360 :
361 : std::unique_ptr<StreamingDecoder::DecodingState>
362 2262 : StreamingDecoder::DecodeModuleHeader::Next(StreamingDecoder* streaming) {
363 : TRACE_STREAMING("DecodeModuleHeader\n");
364 1427 : streaming->ProcessModuleHeader();
365 1427 : if (!streaming->ok()) return nullptr;
366 1670 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
367 : }
368 :
369 : std::unique_ptr<StreamingDecoder::DecodingState>
370 1672 : StreamingDecoder::DecodeSectionID::Next(StreamingDecoder* streaming) {
371 : TRACE_STREAMING("DecodeSectionID: %s section\n",
372 : SectionName(static_cast<SectionCode>(id_)));
373 3344 : return base::make_unique<DecodeSectionLength>(id_, module_offset_);
374 : }
375 :
376 : std::unique_ptr<StreamingDecoder::DecodingState>
377 1629 : StreamingDecoder::DecodeSectionLength::NextWithValue(
378 : StreamingDecoder* streaming) {
379 : TRACE_STREAMING("DecodeSectionLength(%zu)\n", value_);
380 : SectionBuffer* buf =
381 : streaming->CreateNewBuffer(module_offset_, section_id_, value_,
382 3258 : buffer().SubVector(0, bytes_consumed_));
383 1629 : if (!buf) return nullptr;
384 1586 : if (value_ == 0) {
385 56 : if (section_id_ == SectionCode::kCodeSectionCode) {
386 38 : return streaming->Error("code section cannot have size 0");
387 : }
388 37 : streaming->ProcessSection(buf);
389 37 : if (!streaming->ok()) return nullptr;
390 : // There is no payload, we go to the next section immediately.
391 74 : return base::make_unique<DecodeSectionID>(streaming->module_offset_);
392 : } else {
393 1530 : if (section_id_ == SectionCode::kCodeSectionCode) {
394 : // We reached the code section. All functions of the code section are put
395 : // into the same SectionBuffer.
396 1068 : return base::make_unique<DecodeNumberOfFunctions>(buf);
397 : }
398 : return base::make_unique<DecodeSectionPayload>(buf);
399 : }
400 : }
401 :
402 : std::unique_ptr<StreamingDecoder::DecodingState>
403 1892 : StreamingDecoder::DecodeSectionPayload::Next(StreamingDecoder* streaming) {
404 : TRACE_STREAMING("DecodeSectionPayload\n");
405 956 : streaming->ProcessSection(section_buffer_);
406 956 : if (!streaming->ok()) return nullptr;
407 1872 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
408 : }
409 :
410 : std::unique_ptr<StreamingDecoder::DecodingState>
411 518 : StreamingDecoder::DecodeNumberOfFunctions::NextWithValue(
412 4 : StreamingDecoder* streaming) {
413 : TRACE_STREAMING("DecodeNumberOfFunctions(%zu)\n", value_);
414 : // Copy the bytes we read into the section buffer.
415 984 : Vector<uint8_t> payload_buf = section_buffer_->payload();
416 518 : if (payload_buf.size() < bytes_consumed_) {
417 48 : return streaming->Error("invalid code section length");
418 : }
419 988 : memcpy(payload_buf.start(), buffer().start(), bytes_consumed_);
420 :
421 : // {value} is the number of functions.
422 494 : if (value_ == 0) {
423 16 : if (payload_buf.size() != bytes_consumed_) {
424 24 : return streaming->Error("not all code section bytes were used");
425 : }
426 8 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
427 : }
428 :
429 956 : streaming->StartCodeSection(value_, streaming->section_buffers_.back());
430 478 : if (!streaming->ok()) return nullptr;
431 : return base::make_unique<DecodeFunctionLength>(
432 932 : section_buffer_, section_buffer_->payload_offset() + bytes_consumed_,
433 1398 : value_);
434 : }
435 :
436 : std::unique_ptr<StreamingDecoder::DecodingState>
437 858 : StreamingDecoder::DecodeFunctionLength::NextWithValue(
438 777 : StreamingDecoder* streaming) {
439 : TRACE_STREAMING("DecodeFunctionLength(%zu)\n", value_);
440 : // Copy the bytes we consumed into the section buffer.
441 858 : Vector<uint8_t> fun_length_buffer = section_buffer_->bytes() + buffer_offset_;
442 858 : if (fun_length_buffer.size() < bytes_consumed_) {
443 96 : return streaming->Error("read past code section end");
444 : }
445 1620 : memcpy(fun_length_buffer.start(), buffer().start(), bytes_consumed_);
446 :
447 : // {value} is the length of the function.
448 831 : if (value_ == 0) return streaming->Error("invalid function length (0)");
449 :
450 1578 : if (buffer_offset_ + bytes_consumed_ + value_ > section_buffer_->length()) {
451 24 : return streaming->Error("not enough code section bytes");
452 : }
453 :
454 : return base::make_unique<DecodeFunctionBody>(
455 : section_buffer_, buffer_offset_ + bytes_consumed_, value_,
456 1554 : num_remaining_functions_, streaming->module_offset());
457 : }
458 :
459 : std::unique_ptr<StreamingDecoder::DecodingState>
460 1049 : StreamingDecoder::DecodeFunctionBody::Next(StreamingDecoder* streaming) {
461 : TRACE_STREAMING("DecodeFunctionBody\n");
462 1554 : streaming->ProcessFunctionBody(buffer(), module_offset_);
463 777 : if (!streaming->ok()) return nullptr;
464 :
465 777 : size_t end_offset = buffer_offset_ + function_body_length_;
466 777 : if (num_remaining_functions_ > 0) {
467 : return base::make_unique<DecodeFunctionLength>(section_buffer_, end_offset,
468 900 : num_remaining_functions_);
469 : }
470 : // We just read the last function body. Continue with the next section.
471 654 : if (end_offset != section_buffer_->length()) {
472 110 : return streaming->Error("not all code section bytes were used");
473 : }
474 544 : return base::make_unique<DecodeSectionID>(streaming->module_offset());
475 : }
476 :
477 1492 : StreamingDecoder::StreamingDecoder(
478 : std::unique_ptr<StreamingProcessor> processor)
479 : : processor_(std::move(processor)),
480 : // A module always starts with a module header.
481 4476 : state_(new DecodeModuleHeader()) {}
482 :
483 1629 : StreamingDecoder::SectionBuffer* StreamingDecoder::CreateNewBuffer(
484 : uint32_t module_offset, uint8_t section_id, size_t length,
485 : Vector<const uint8_t> length_bytes) {
486 : // Check the order of sections. Unknown sections can appear at any position.
487 1629 : if (section_id != kUnknownSectionCode) {
488 1526 : if (section_id < next_section_id_) {
489 129 : Error("section out of order");
490 43 : return nullptr;
491 : }
492 1483 : next_section_id_ = section_id + 1;
493 : }
494 : section_buffers_.emplace_back(std::make_shared<SectionBuffer>(
495 3172 : module_offset, section_id, length, length_bytes));
496 1586 : return section_buffers_.back().get();
497 : }
498 :
499 : } // namespace wasm
500 : } // namespace internal
501 178779 : } // namespace v8
502 :
503 : #undef TRACE_STREAMING
|