LCOV - code coverage report
Current view: top level - src/wasm - streaming-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 170 170 100.0 %
Date: 2019-02-19 Functions: 38 47 80.9 %

          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

Generated by: LCOV version 1.10