LCOV - code coverage report
Current view: top level - src/wasm - wasm-module-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 255 265 96.2 %
Date: 2019-02-19 Functions: 43 46 93.5 %

          Line data    Source code
       1             : // Copyright 2015 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/signature.h"
       6             : 
       7             : #include "src/handles.h"
       8             : #include "src/objects-inl.h"
       9             : #include "src/v8.h"
      10             : #include "src/zone/zone-containers.h"
      11             : 
      12             : #include "src/wasm/function-body-decoder.h"
      13             : #include "src/wasm/leb-helper.h"
      14             : #include "src/wasm/wasm-constants.h"
      15             : #include "src/wasm/wasm-module-builder.h"
      16             : #include "src/wasm/wasm-module.h"
      17             : #include "src/wasm/wasm-opcodes.h"
      18             : 
      19             : #include "src/v8memory.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace wasm {
      24             : 
      25             : namespace {
      26             : 
      27             : // Emit a section code and the size as a padded varint that can be patched
      28             : // later.
      29       17421 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
      30             :   // Emit the section code.
      31       17421 :   buffer.write_u8(code);
      32             : 
      33             :   // Emit a placeholder for the length.
      34       17426 :   return buffer.reserve_u32v();
      35             : }
      36             : 
      37             : // Patch the size of a section after it's finished.
      38       22370 : void FixupSection(ZoneBuffer& buffer, size_t start) {
      39             :   buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
      40       22370 :                                                  kPaddedVarInt32Size));
      41       22370 : }
      42             : 
      43             : }  // namespace
      44             : 
      45      139602 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
      46             :     : builder_(builder),
      47             :       locals_(builder->zone()),
      48             :       signature_index_(0),
      49       15512 :       func_index_(static_cast<uint32_t>(builder->functions_.size())),
      50             :       body_(builder->zone(), 256),
      51             :       i32_temps_(builder->zone()),
      52             :       i64_temps_(builder->zone()),
      53             :       f32_temps_(builder->zone()),
      54             :       f64_temps_(builder->zone()),
      55             :       direct_calls_(builder->zone()),
      56       77556 :       asm_offsets_(builder->zone(), 8) {}
      57             : 
      58       49852 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
      59             : 
      60        8196 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
      61             : 
      62       14493 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
      63             :   DCHECK(!locals_.has_sig());
      64             :   locals_.set_sig(sig);
      65       14907 :   signature_index_ = builder_->AddSignature(sig);
      66       14494 : }
      67             : 
      68      545535 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
      69             :   DCHECK(locals_.has_sig());
      70      545535 :   return locals_.AddLocals(1, type);
      71             : }
      72             : 
      73      501671 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
      74      501671 :   EmitWithU32V(kExprGetLocal, local_index);
      75      501673 : }
      76             : 
      77      548954 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
      78      548954 :   EmitWithU32V(kExprSetLocal, local_index);
      79      548954 : }
      80             : 
      81      179464 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
      82      179464 :   EmitWithU32V(kExprTeeLocal, local_index);
      83      179464 : }
      84             : 
      85         414 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
      86       33686 :   body_.write(code, code_size);
      87         414 : }
      88             : 
      89     2777960 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
      90             : 
      91      151393 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
      92      151393 :   body_.write_u8(opcode);
      93             :   body_.write_u8(immediate);
      94      151393 : }
      95             : 
      96           0 : void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
      97             :                                        const byte imm2) {
      98           0 :   body_.write_u8(opcode);
      99             :   body_.write_u8(imm1);
     100             :   body_.write_u8(imm2);
     101           0 : }
     102             : 
     103     1510075 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
     104     1510075 :   body_.write_u8(opcode);
     105             :   body_.write_i32v(immediate);
     106     1510078 : }
     107             : 
     108     1281234 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
     109     1281234 :   body_.write_u8(opcode);
     110     1281233 :   body_.write_u32v(immediate);
     111     1281236 : }
     112             : 
     113     1468711 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
     114     1468711 :   EmitWithI32V(kExprI32Const, value);
     115     1468715 : }
     116             : 
     117           0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
     118           0 :   body_.write_u8(kExprI64Const);
     119             :   body_.write_i64v(value);
     120           0 : }
     121             : 
     122          32 : void WasmFunctionBuilder::EmitF32Const(float value) {
     123          32 :   body_.write_u8(kExprF32Const);
     124             :   body_.write_f32(value);
     125          32 : }
     126             : 
     127        9382 : void WasmFunctionBuilder::EmitF64Const(double value) {
     128        9382 :   body_.write_u8(kExprF64Const);
     129             :   body_.write_f64(value);
     130        9382 : }
     131             : 
     132       33272 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
     133             :   DirectCallIndex call;
     134       66544 :   call.offset = body_.size();
     135       33272 :   call.direct_index = index;
     136       33272 :   direct_calls_.push_back(call);
     137       33272 :   byte placeholder_bytes[kMaxVarInt32Size] = {0};
     138             :   EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
     139       33272 : }
     140             : 
     141       12595 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
     142             : 
     143       59274 : void WasmFunctionBuilder::AddAsmWasmOffset(size_t call_position,
     144             :                                            size_t to_number_position) {
     145             :   // We only want to emit one mapping per byte offset.
     146             :   DCHECK(asm_offsets_.size() == 0 || body_.size() > last_asm_byte_offset_);
     147             : 
     148             :   DCHECK_LE(body_.size(), kMaxUInt32);
     149      118548 :   uint32_t byte_offset = static_cast<uint32_t>(body_.size());
     150       59274 :   asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
     151       59274 :   last_asm_byte_offset_ = byte_offset;
     152             : 
     153             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
     154       59274 :   uint32_t call_position_u32 = static_cast<uint32_t>(call_position);
     155       59274 :   asm_offsets_.write_i32v(call_position_u32 - last_asm_source_position_);
     156             : 
     157             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(), to_number_position);
     158       59274 :   uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position);
     159       59274 :   asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32);
     160       59274 :   last_asm_source_position_ = to_number_position_u32;
     161       59274 : }
     162             : 
     163       12594 : void WasmFunctionBuilder::SetAsmFunctionStartPosition(
     164             :     size_t function_position) {
     165             :   DCHECK_EQ(0, asm_func_start_source_position_);
     166             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(), function_position);
     167       12594 :   uint32_t function_position_u32 = static_cast<uint32_t>(function_position);
     168             :   // Must be called before emitting any asm.js source position.
     169             :   DCHECK_EQ(0, asm_offsets_.size());
     170       12594 :   asm_func_start_source_position_ = function_position_u32;
     171       12594 :   last_asm_source_position_ = function_position_u32;
     172       12594 : }
     173             : 
     174      392902 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
     175             :   DCHECK_LE(position, body_.size());
     176      392902 :   body_.Truncate(position);
     177      392902 : }
     178             : 
     179           0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
     180       14732 :   buffer.write_u32v(signature_index_);
     181           0 : }
     182             : 
     183       62694 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
     184       14732 :   size_t locals_size = locals_.Size();
     185       44201 :   buffer.write_size(locals_size + body_.size());
     186       14734 :   buffer.EnsureSpace(locals_size);
     187             :   byte** ptr = buffer.pos_ptr();
     188       14736 :   locals_.Emit(*ptr);
     189       14735 :   (*ptr) += locals_size;  // UGLY: manual bump of position pointer
     190       14735 :   if (body_.size() > 0) {
     191             :     size_t base = buffer.offset();
     192       14734 :     buffer.write(body_.begin(), body_.size());
     193       62694 :     for (DirectCallIndex call : direct_calls_) {
     194             :       buffer.patch_u32v(
     195             :           base + call.offset,
     196             :           call.direct_index +
     197       66456 :               static_cast<uint32_t>(builder_->function_imports_.size()));
     198             :     }
     199             :   }
     200       14734 : }
     201             : 
     202       14323 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
     203       40498 :   if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
     204        2469 :     buffer.write_size(0);
     205       16790 :     return;
     206             :   }
     207       11854 :   size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
     208             :   size_t func_start_size =
     209       11853 :       LEBHelper::sizeof_u32v(asm_func_start_source_position_);
     210       11853 :   buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
     211             :   // Offset of the recorded byte offsets.
     212             :   DCHECK_GE(kMaxUInt32, locals_.Size());
     213       11852 :   buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
     214             :   // Start position of the function.
     215       11854 :   buffer.write_u32v(asm_func_start_source_position_);
     216       11853 :   buffer.write(asm_offsets_.begin(), asm_offsets_.size());
     217             : }
     218             : 
     219        4033 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
     220             :     : zone_(zone),
     221             :       signatures_(zone),
     222             :       function_imports_(zone),
     223             :       function_exports_(zone),
     224             :       global_imports_(zone),
     225             :       functions_(zone),
     226             :       data_segments_(zone),
     227             :       indirect_functions_(zone),
     228             :       globals_(zone),
     229             :       signature_map_(zone),
     230             :       start_function_index_(-1),
     231             :       min_memory_size_(16),
     232             :       max_memory_size_(0),
     233             :       has_max_memory_size_(false),
     234        8066 :       has_shared_memory_(false) {}
     235             : 
     236       15513 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
     237       46545 :   functions_.push_back(new (zone_) WasmFunctionBuilder(this));
     238             :   // Add the signature if one was provided here.
     239       15930 :   if (sig) functions_.back()->SetSignature(sig);
     240       15516 :   return functions_.back();
     241             : }
     242             : 
     243           4 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
     244           4 :                                        uint32_t dest) {
     245           8 :   data_segments_.push_back({ZoneVector<byte>(zone()), dest});
     246             :   ZoneVector<byte>& vec = data_segments_.back().data;
     247          20 :   for (uint32_t i = 0; i < size; i++) {
     248          16 :     vec.push_back(data[i]);
     249             :   }
     250           4 : }
     251             : 
     252       64330 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
     253       64330 :   auto sig_entry = signature_map_.find(*sig);
     254       64331 :   if (sig_entry != signature_map_.end()) return sig_entry->second;
     255       13218 :   uint32_t index = static_cast<uint32_t>(signatures_.size());
     256        6609 :   signature_map_.emplace(*sig, index);
     257        6609 :   signatures_.push_back(sig);
     258        6608 :   return index;
     259             : }
     260             : 
     261         219 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
     262         438 :   uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
     263             :   DCHECK_GE(FLAG_wasm_max_table_size, index);
     264         219 :   if (count > FLAG_wasm_max_table_size - index) {
     265             :     return std::numeric_limits<uint32_t>::max();
     266             :   }
     267         209 :   indirect_functions_.resize(indirect_functions_.size() + count);
     268         209 :   return index;
     269             : }
     270             : 
     271        4189 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
     272             :                                             uint32_t direct) {
     273        8378 :   indirect_functions_[indirect] = direct;
     274        4189 : }
     275             : 
     276        2072 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
     277             :                                       FunctionSig* sig) {
     278        4144 :   function_imports_.push_back({name, AddSignature(sig)});
     279        2072 :   return static_cast<uint32_t>(function_imports_.size() - 1);
     280             : }
     281             : 
     282         469 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
     283             :                                             ValueType type) {
     284         938 :   global_imports_.push_back({name, ValueTypes::ValueTypeCodeFor(type)});
     285         469 :   return static_cast<uint32_t>(global_imports_.size() - 1);
     286             : }
     287             : 
     288        2468 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
     289        2468 :   start_function_index_ = function->func_index();
     290        2468 : }
     291             : 
     292        4614 : void WasmModuleBuilder::AddExport(Vector<const char> name,
     293        4614 :                                   WasmFunctionBuilder* function) {
     294       13844 :   function_exports_.push_back({name, function->func_index()});
     295        4616 : }
     296             : 
     297        2954 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
     298             :                                       bool mutability,
     299             :                                       const WasmInitExpr& init) {
     300        5908 :   globals_.push_back({type, exported, mutability, init});
     301        2954 :   return static_cast<uint32_t>(globals_.size() - 1);
     302             : }
     303             : 
     304        3719 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
     305        3719 :   min_memory_size_ = value;
     306        3719 : }
     307             : 
     308           6 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
     309           6 :   has_max_memory_size_ = true;
     310           6 :   max_memory_size_ = value;
     311           6 : }
     312             : 
     313           4 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
     314             : 
     315        2784 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
     316             :   // == Emit magic =============================================================
     317        2784 :   buffer.write_u32(kWasmMagic);
     318        2784 :   buffer.write_u32(kWasmVersion);
     319             : 
     320             :   // == Emit signatures ========================================================
     321        8347 :   if (signatures_.size() > 0) {
     322        2778 :     size_t start = EmitSection(kTypeSectionCode, buffer);
     323        2779 :     buffer.write_size(signatures_.size());
     324             : 
     325       31014 :     for (FunctionSig* sig : signatures_) {
     326             :       buffer.write_u8(kWasmFunctionTypeCode);
     327        6363 :       buffer.write_size(sig->parameter_count());
     328       12255 :       for (auto param : sig->parameters()) {
     329        5892 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(param));
     330             :       }
     331        6363 :       buffer.write_size(sig->return_count());
     332        9831 :       for (auto ret : sig->returns()) {
     333        3468 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(ret));
     334             :       }
     335             :     }
     336        2780 :     FixupSection(buffer, start);
     337             :   }
     338             : 
     339             :   // == Emit imports ===========================================================
     340       24522 :   if (global_imports_.size() + function_imports_.size() > 0) {
     341         230 :     size_t start = EmitSection(kImportSectionCode, buffer);
     342         230 :     buffer.write_size(global_imports_.size() + function_imports_.size());
     343         929 :     for (auto import : global_imports_) {
     344         469 :       buffer.write_u32v(0);              // module name (length)
     345             :       buffer.write_string(import.name);  // field name
     346             :       buffer.write_u8(kExternalGlobal);
     347             :       buffer.write_u8(import.type_code);
     348             :       buffer.write_u8(0);  // immutable
     349             :     }
     350        2496 :     for (auto import : function_imports_) {
     351        2036 :       buffer.write_u32v(0);              // module name (length)
     352             :       buffer.write_string(import.name);  // field name
     353             :       buffer.write_u8(kExternalFunction);
     354        2036 :       buffer.write_u32v(import.sig_index);
     355             :     }
     356         230 :     FixupSection(buffer, start);
     357             :   }
     358             : 
     359             :   // == Emit function signatures ===============================================
     360             :   uint32_t num_function_names = 0;
     361       13901 :   if (functions_.size() > 0) {
     362        2777 :     size_t start = EmitSection(kFunctionSectionCode, buffer);
     363        2778 :     buffer.write_size(functions_.size());
     364       20285 :     for (auto function : functions_) {
     365             :       function->WriteSignature(buffer);
     366       14733 :       if (!function->name_.is_empty()) ++num_function_names;
     367             :     }
     368        2777 :     FixupSection(buffer, start);
     369             :   }
     370             : 
     371             :   // == emit function table ====================================================
     372        8481 :   if (indirect_functions_.size() > 0) {
     373          45 :     size_t start = EmitSection(kTableSectionCode, buffer);
     374             :     buffer.write_u8(1);  // table count
     375             :     buffer.write_u8(kLocalAnyFunc);
     376             :     buffer.write_u8(kHasMaximumFlag);
     377          45 :     buffer.write_size(indirect_functions_.size());
     378          45 :     buffer.write_size(indirect_functions_.size());
     379          45 :     FixupSection(buffer, start);
     380             :   }
     381             : 
     382             :   // == emit memory declaration ================================================
     383             :   {
     384        2783 :     size_t start = EmitSection(kMemorySectionCode, buffer);
     385             :     buffer.write_u8(1);  // memory count
     386        2780 :     if (has_shared_memory_) {
     387             :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
     388           4 :                                            : MemoryFlags::kSharedNoMaximum);
     389             :     } else {
     390             :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
     391        2776 :                                            : MemoryFlags::kNoMaximum);
     392             :     }
     393        2781 :     buffer.write_u32v(min_memory_size_);
     394        2780 :     if (has_max_memory_size_) {
     395           6 :       buffer.write_u32v(max_memory_size_);
     396             :     }
     397        2780 :     FixupSection(buffer, start);
     398             :   }
     399             : 
     400             :   // == Emit globals ===========================================================
     401        6355 :   if (globals_.size() > 0) {
     402         789 :     size_t start = EmitSection(kGlobalSectionCode, buffer);
     403         789 :     buffer.write_size(globals_.size());
     404             : 
     405        4346 :     for (auto global : globals_) {
     406        2768 :       buffer.write_u8(ValueTypes::ValueTypeCodeFor(global.type));
     407        2768 :       buffer.write_u8(global.mutability ? 1 : 0);
     408        2768 :       switch (global.init.kind) {
     409             :         case WasmInitExpr::kI32Const:
     410             :           DCHECK_EQ(kWasmI32, global.type);
     411             :           buffer.write_u8(kExprI32Const);
     412        1945 :           buffer.write_i32v(global.init.val.i32_const);
     413             :           break;
     414             :         case WasmInitExpr::kI64Const:
     415             :           DCHECK_EQ(kWasmI64, global.type);
     416             :           buffer.write_u8(kExprI64Const);
     417           0 :           buffer.write_i64v(global.init.val.i64_const);
     418             :           break;
     419             :         case WasmInitExpr::kF32Const:
     420             :           DCHECK_EQ(kWasmF32, global.type);
     421             :           buffer.write_u8(kExprF32Const);
     422          56 :           buffer.write_f32(global.init.val.f32_const);
     423             :           break;
     424             :         case WasmInitExpr::kF64Const:
     425             :           DCHECK_EQ(kWasmF64, global.type);
     426             :           buffer.write_u8(kExprF64Const);
     427         278 :           buffer.write_f64(global.init.val.f64_const);
     428             :           break;
     429             :         case WasmInitExpr::kGlobalIndex:
     430             :           buffer.write_u8(kExprGetGlobal);
     431          12 :           buffer.write_u32v(global.init.val.global_index);
     432          12 :           break;
     433             :         default: {
     434             :           // No initializer, emit a default value.
     435         477 :           switch (global.type) {
     436             :             case kWasmI32:
     437             :               buffer.write_u8(kExprI32Const);
     438             :               // LEB encoding of 0.
     439             :               buffer.write_u8(0);
     440             :               break;
     441             :             case kWasmI64:
     442             :               buffer.write_u8(kExprI64Const);
     443             :               // LEB encoding of 0.
     444             :               buffer.write_u8(0);
     445             :               break;
     446             :             case kWasmF32:
     447             :               buffer.write_u8(kExprF32Const);
     448             :               buffer.write_f32(0.f);
     449             :               break;
     450             :             case kWasmF64:
     451             :               buffer.write_u8(kExprF64Const);
     452             :               buffer.write_f64(0.);
     453             :               break;
     454             :             default:
     455           0 :               UNREACHABLE();
     456             :           }
     457             :         }
     458             :       }
     459             :       buffer.write_u8(kExprEnd);
     460             :     }
     461         789 :     FixupSection(buffer, start);
     462             :   }
     463             : 
     464             :   // == emit exports ===========================================================
     465        5506 :   if (!function_exports_.empty()) {
     466        2725 :     size_t start = EmitSection(kExportSectionCode, buffer);
     467        2727 :     buffer.write_size(function_exports_.size());
     468       10007 :     for (auto function_export : function_exports_) {
     469             :       buffer.write_string(function_export.name);
     470             :       buffer.write_u8(kExternalFunction);
     471             :       buffer.write_size(function_export.function_index +
     472        9110 :                         function_imports_.size());
     473             :     }
     474        2725 :     FixupSection(buffer, start);
     475             :   }
     476             : 
     477             :   // == emit start function index ==============================================
     478        2780 :   if (start_function_index_ >= 0) {
     479        2468 :     size_t start = EmitSection(kStartSectionCode, buffer);
     480        4936 :     buffer.write_size(start_function_index_ + function_imports_.size());
     481        2468 :     FixupSection(buffer, start);
     482             :   }
     483             : 
     484             :   // == emit function table elements ===========================================
     485        2780 :   if (indirect_functions_.size() > 0) {
     486          45 :     size_t start = EmitSection(kElementSectionCode, buffer);
     487             :     buffer.write_u8(1);              // count of entries
     488             :     buffer.write_u8(0);              // table index
     489             :     buffer.write_u8(kExprI32Const);  // offset
     490          45 :     buffer.write_u32v(0);
     491             :     buffer.write_u8(kExprEnd);
     492          45 :     buffer.write_size(indirect_functions_.size());  // element count
     493             : 
     494        4275 :     for (auto index : indirect_functions_) {
     495        8370 :       buffer.write_size(index + function_imports_.size());
     496             :     }
     497             : 
     498          45 :     FixupSection(buffer, start);
     499             :   }
     500             : 
     501             :   // == emit code ==============================================================
     502        2780 :   if (functions_.size() > 0) {
     503        2776 :     size_t start = EmitSection(kCodeSectionCode, buffer);
     504        2779 :     buffer.write_size(functions_.size());
     505       20289 :     for (auto function : functions_) {
     506       14733 :       function->WriteBody(buffer);
     507             :     }
     508        2778 :     FixupSection(buffer, start);
     509             :   }
     510             : 
     511             :   // == emit data segments =====================================================
     512        5568 :   if (data_segments_.size() > 0) {
     513           4 :     size_t start = EmitSection(kDataSectionCode, buffer);
     514           4 :     buffer.write_size(data_segments_.size());
     515             : 
     516          12 :     for (auto segment : data_segments_) {
     517             :       buffer.write_u8(0);              // linear memory segment
     518             :       buffer.write_u8(kExprI32Const);  // initializer expression for dest
     519           4 :       buffer.write_u32v(segment.dest);
     520             :       buffer.write_u8(kExprEnd);
     521           8 :       buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
     522           8 :       buffer.write(&segment.data[0], segment.data.size());
     523             :     }
     524           4 :     FixupSection(buffer, start);
     525             :   }
     526             : 
     527             :   // == Emit names =============================================================
     528        3096 :   if (num_function_names > 0 || !function_imports_.empty()) {
     529             :     // Emit the section code.
     530             :     buffer.write_u8(kUnknownSectionCode);
     531             :     // Emit a placeholder for the length.
     532             :     size_t start = buffer.reserve_u32v();
     533             :     // Emit the section string.
     534        2471 :     buffer.write_size(4);
     535        2471 :     buffer.write(reinterpret_cast<const byte*>("name"), 4);
     536             :     // Emit a subsection for the function names.
     537             :     buffer.write_u8(NameSectionKindCode::kFunction);
     538             :     // Emit a placeholder for the subsection length.
     539             :     size_t functions_start = buffer.reserve_u32v();
     540             :     // Emit the function names.
     541             :     // Imports are always named.
     542        2472 :     uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
     543        2472 :     buffer.write_size(num_imports + num_function_names);
     544             :     uint32_t function_index = 0;
     545        4510 :     for (; function_index < num_imports; ++function_index) {
     546        2036 :       const WasmFunctionImport* import = &function_imports_[function_index];
     547             :       DCHECK(!import->name.is_empty());
     548        2036 :       buffer.write_u32v(function_index);
     549             :       buffer.write_string(import->name);
     550             :     }
     551        2474 :     if (num_function_names > 0) {
     552       19260 :       for (auto function : functions_) {
     553             :         DCHECK_EQ(function_index,
     554             :                   function->func_index() + function_imports_.size());
     555       14322 :         if (!function->name_.is_empty()) {
     556       11855 :           buffer.write_u32v(function_index);
     557             :           buffer.write_string(function->name_);
     558             :         }
     559       14324 :         ++function_index;
     560             :       }
     561             :     }
     562        2476 :     FixupSection(buffer, functions_start);
     563        2473 :     FixupSection(buffer, start);
     564             :   }
     565        2782 : }
     566             : 
     567        2468 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
     568             :   // == Emit asm.js offset table ===============================================
     569        4936 :   buffer.write_size(functions_.size());
     570             :   // Emit the offset table per function.
     571       19257 :   for (auto function : functions_) {
     572       14320 :     function->WriteAsmWasmOffsetTable(buffer);
     573             :   }
     574             :   // Append a 0 to indicate that this is an encoded table.
     575             :   buffer.write_u8(0);
     576        2469 : }
     577             : }  // namespace wasm
     578             : }  // namespace internal
     579      178779 : }  // namespace v8

Generated by: LCOV version 1.10