LCOV - code coverage report
Current view: top level - src/wasm - wasm-module-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 253 263 96.2 %
Date: 2019-01-20 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       21323 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
      30             :   // Emit the section code.
      31       21323 :   buffer.write_u8(code);
      32             : 
      33             :   // Emit a placeholder for the length.
      34       21323 :   return buffer.reserve_u32v();
      35             : }
      36             : 
      37             : // Patch the size of a section after it's finished.
      38       27363 : void FixupSection(ZoneBuffer& buffer, size_t start) {
      39             :   buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
      40       27363 :                                                  kPaddedVarInt32Size));
      41       27363 : }
      42             : 
      43             : }  // namespace
      44             : 
      45      164799 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
      46             :     : builder_(builder),
      47             :       locals_(builder->zone()),
      48             :       signature_index_(0),
      49       18313 :       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       91562 :       asm_offsets_(builder->zone(), 8) {}
      57             : 
      58       55088 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
      59             : 
      60        8600 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
      61             : 
      62       17048 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
      63             :   DCHECK(!locals_.has_sig());
      64             :   locals_.set_sig(sig);
      65       17565 :   signature_index_ = builder_->AddSignature(sig);
      66       17049 : }
      67             : 
      68      650821 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
      69             :   DCHECK(locals_.has_sig());
      70      650821 :   return locals_.AddLocals(1, type);
      71             : }
      72             : 
      73      566085 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
      74      566085 :   EmitWithU32V(kExprGetLocal, local_index);
      75      566085 : }
      76             : 
      77      654431 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
      78      654431 :   EmitWithU32V(kExprSetLocal, local_index);
      79      654431 : }
      80             : 
      81      201297 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
      82      201297 :   EmitWithU32V(kExprTeeLocal, local_index);
      83      201297 : }
      84             : 
      85         517 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
      86       37611 :   body_.write(code, code_size);
      87         517 : }
      88             : 
      89     3130029 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
      90             : 
      91      170206 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
      92      170206 :   body_.write_u8(opcode);
      93             :   body_.write_u8(immediate);
      94      170206 : }
      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     1735854 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
     104     1735854 :   body_.write_u8(opcode);
     105             :   body_.write_i32v(immediate);
     106     1735856 : }
     107             : 
     108     1478647 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
     109     1478647 :   body_.write_u8(opcode);
     110     1478647 :   body_.write_u32v(immediate);
     111     1478647 : }
     112             : 
     113     1688937 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
     114     1688937 :   EmitWithI32V(kExprI32Const, value);
     115     1688939 : }
     116             : 
     117           0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
     118           0 :   body_.write_u8(kExprI64Const);
     119             :   body_.write_i64v(value);
     120           0 : }
     121             : 
     122          40 : void WasmFunctionBuilder::EmitF32Const(float value) {
     123          40 :   body_.write_u8(kExprF32Const);
     124             :   body_.write_f32(value);
     125          40 : }
     126             : 
     127       10791 : void WasmFunctionBuilder::EmitF64Const(double value) {
     128       10791 :   body_.write_u8(kExprF64Const);
     129             :   body_.write_f64(value);
     130       10791 : }
     131             : 
     132       37094 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
     133             :   DirectCallIndex call;
     134       74188 :   call.offset = body_.size();
     135       37094 :   call.direct_index = index;
     136       37094 :   direct_calls_.push_back(call);
     137       37094 :   byte placeholder_bytes[kMaxVarInt32Size] = {0};
     138             :   EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
     139       37094 : }
     140             : 
     141       14740 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
     142             : 
     143       65992 : 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      131984 :   uint32_t byte_offset = static_cast<uint32_t>(body_.size());
     150       65992 :   asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
     151       65992 :   last_asm_byte_offset_ = byte_offset;
     152             : 
     153             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
     154       65992 :   uint32_t call_position_u32 = static_cast<uint32_t>(call_position);
     155       65992 :   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       65992 :   uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position);
     159       65992 :   asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32);
     160       65992 :   last_asm_source_position_ = to_number_position_u32;
     161       65992 : }
     162             : 
     163       14738 : 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       14738 :   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       14738 :   asm_func_start_source_position_ = function_position_u32;
     171       14738 :   last_asm_source_position_ = function_position_u32;
     172       14738 : }
     173             : 
     174      440346 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
     175             :   DCHECK_LE(position, body_.size());
     176      440346 :   body_.Truncate(position);
     177      440346 : }
     178             : 
     179           0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
     180       17353 :   buffer.write_u32v(signature_index_);
     181           0 : }
     182             : 
     183       71734 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
     184       17349 :   size_t locals_size = locals_.Size();
     185       52037 :   buffer.write_size(locals_size + body_.size());
     186       17346 :   buffer.EnsureSpace(locals_size);
     187             :   byte** ptr = buffer.pos_ptr();
     188       17346 :   locals_.Emit(*ptr);
     189       17345 :   (*ptr) += locals_size;  // UGLY: manual bump of position pointer
     190       17345 :   if (body_.size() > 0) {
     191             :     size_t base = buffer.offset();
     192       17346 :     buffer.write(body_.begin(), body_.size());
     193       71729 :     for (DirectCallIndex call : direct_calls_) {
     194             :       buffer.patch_u32v(
     195             :           base + call.offset,
     196             :           call.direct_index +
     197       74078 :               static_cast<uint32_t>(builder_->function_imports_.size()));
     198             :     }
     199             :   }
     200       17344 : }
     201             : 
     202       16834 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
     203       47487 :   if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
     204        3015 :     buffer.write_size(0);
     205       19849 :     return;
     206             :   }
     207       13819 :   size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
     208             :   size_t func_start_size =
     209       13819 :       LEBHelper::sizeof_u32v(asm_func_start_source_position_);
     210       13819 :   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       13819 :   buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
     214             :   // Start position of the function.
     215       13819 :   buffer.write_u32v(asm_func_start_source_position_);
     216       13819 :   buffer.write(asm_offsets_.begin(), asm_offsets_.size());
     217             : }
     218             : 
     219        4933 : 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        9866 :       has_shared_memory_(false) {}
     235             : 
     236       18313 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
     237       54942 :   functions_.push_back(new (zone_) WasmFunctionBuilder(this));
     238             :   // Add the signature if one was provided here.
     239       18831 :   if (sig) functions_.back()->SetSignature(sig);
     240       18314 :   return functions_.back();
     241             : }
     242             : 
     243           5 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
     244           5 :                                        uint32_t dest) {
     245          10 :   data_segments_.push_back({ZoneVector<byte>(zone()), dest});
     246             :   ZoneVector<byte>& vec = data_segments_.back().data;
     247          25 :   for (uint32_t i = 0; i < size; i++) {
     248          20 :     vec.push_back(data[i]);
     249             :   }
     250           5 : }
     251             : 
     252       72810 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
     253       72810 :   auto sig_entry = signature_map_.find(*sig);
     254       72810 :   if (sig_entry != signature_map_.end()) return sig_entry->second;
     255       16118 :   uint32_t index = static_cast<uint32_t>(signatures_.size());
     256        8059 :   signature_map_.emplace(*sig, index);
     257        8060 :   signatures_.push_back(sig);
     258        8060 :   return index;
     259             : }
     260             : 
     261         259 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
     262         518 :   uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
     263             :   DCHECK_GE(FLAG_wasm_max_table_size, index);
     264         259 :   if (count > FLAG_wasm_max_table_size - index) {
     265             :     return std::numeric_limits<uint32_t>::max();
     266             :   }
     267         247 :   indirect_functions_.resize(indirect_functions_.size() + count);
     268         247 :   return index;
     269             : }
     270             : 
     271        4617 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
     272             :                                             uint32_t direct) {
     273        9234 :   indirect_functions_[indirect] = direct;
     274        4617 : }
     275             : 
     276        2459 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
     277             :                                       FunctionSig* sig) {
     278        4918 :   function_imports_.push_back({name, AddSignature(sig)});
     279        2459 :   return static_cast<uint32_t>(function_imports_.size() - 1);
     280             : }
     281             : 
     282         565 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
     283             :                                             ValueType type) {
     284        1130 :   global_imports_.push_back({name, ValueTypes::ValueTypeCodeFor(type)});
     285         565 :   return static_cast<uint32_t>(global_imports_.size() - 1);
     286             : }
     287             : 
     288        3015 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
     289        3015 :   start_function_index_ = function->func_index();
     290        3015 : }
     291             : 
     292        5623 : void WasmModuleBuilder::AddExport(Vector<const char> name,
     293        5623 :                                   WasmFunctionBuilder* function) {
     294       16869 :   function_exports_.push_back({name, function->func_index()});
     295        5623 : }
     296             : 
     297        3589 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
     298             :                                       bool mutability,
     299             :                                       const WasmInitExpr& init) {
     300        7178 :   globals_.push_back({type, exported, mutability, init});
     301        3589 :   return static_cast<uint32_t>(globals_.size() - 1);
     302             : }
     303             : 
     304        4541 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
     305        4541 :   min_memory_size_ = value;
     306        4541 : }
     307             : 
     308           7 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
     309           7 :   has_max_memory_size_ = true;
     310           7 :   max_memory_size_ = value;
     311           7 : }
     312             : 
     313           5 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
     314             : 
     315        3407 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
     316             :   // == Emit magic =============================================================
     317             :   buffer.write_u32(kWasmMagic);
     318             :   buffer.write_u32(kWasmVersion);
     319             : 
     320             :   // == Emit signatures ========================================================
     321       10216 :   if (signatures_.size() > 0) {
     322        3402 :     size_t start = EmitSection(kTypeSectionCode, buffer);
     323        3402 :     buffer.write_size(signatures_.size());
     324             : 
     325       37820 :     for (FunctionSig* sig : signatures_) {
     326             :       buffer.write_u8(kWasmFunctionTypeCode);
     327        7754 :       buffer.write_size(sig->parameter_count());
     328       14770 :       for (auto param : sig->parameters()) {
     329        7016 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(param));
     330             :       }
     331        7754 :       buffer.write_size(sig->return_count());
     332       11987 :       for (auto ret : sig->returns()) {
     333        4233 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(ret));
     334             :       }
     335             :     }
     336        3402 :     FixupSection(buffer, start);
     337             :   }
     338             : 
     339             :   // == Emit imports ===========================================================
     340       29392 :   if (global_imports_.size() + function_imports_.size() > 0) {
     341         281 :     size_t start = EmitSection(kImportSectionCode, buffer);
     342         281 :     buffer.write_size(global_imports_.size() + function_imports_.size());
     343        1127 :     for (auto import : global_imports_) {
     344         565 :       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        2976 :     for (auto import : function_imports_) {
     351        2414 :       buffer.write_u32v(0);              // module name (length)
     352             :       buffer.write_string(import.name);  // field name
     353             :       buffer.write_u8(kExternalFunction);
     354        2414 :       buffer.write_u32v(import.sig_index);
     355             :     }
     356         281 :     FixupSection(buffer, start);
     357             :   }
     358             : 
     359             :   // == Emit function signatures ===============================================
     360             :   uint32_t num_function_names = 0;
     361       17025 :   if (functions_.size() > 0) {
     362        3402 :     size_t start = EmitSection(kFunctionSectionCode, buffer);
     363        3402 :     buffer.write_size(functions_.size());
     364       24157 :     for (auto function : functions_) {
     365             :       function->WriteSignature(buffer);
     366       17353 :       if (!function->name_.is_empty()) ++num_function_names;
     367             :     }
     368        3402 :     FixupSection(buffer, start);
     369             :   }
     370             : 
     371             :   // == emit function table ====================================================
     372       10386 :   if (indirect_functions_.size() > 0) {
     373          55 :     size_t start = EmitSection(kTableSectionCode, buffer);
     374             :     buffer.write_u8(1);  // table count
     375             :     buffer.write_u8(kLocalAnyFunc);
     376             :     buffer.write_u8(kHasMaximumFlag);
     377          55 :     buffer.write_size(indirect_functions_.size());
     378          55 :     buffer.write_size(indirect_functions_.size());
     379          55 :     FixupSection(buffer, start);
     380             :   }
     381             : 
     382             :   // == emit memory declaration ================================================
     383             :   {
     384        3407 :     size_t start = EmitSection(kMemorySectionCode, buffer);
     385             :     buffer.write_u8(1);  // memory count
     386        3407 :     if (has_shared_memory_) {
     387             :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
     388           5 :                                            : MemoryFlags::kSharedNoMaximum);
     389             :     } else {
     390             :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
     391        3402 :                                            : MemoryFlags::kNoMaximum);
     392             :     }
     393        3407 :     buffer.write_u32v(min_memory_size_);
     394        3407 :     if (has_max_memory_size_) {
     395           7 :       buffer.write_u32v(max_memory_size_);
     396             :     }
     397        3407 :     FixupSection(buffer, start);
     398             :   }
     399             : 
     400             :   // == Emit globals ===========================================================
     401        7781 :   if (globals_.size() > 0) {
     402         967 :     size_t start = EmitSection(kGlobalSectionCode, buffer);
     403         967 :     buffer.write_size(globals_.size());
     404             : 
     405        5298 :     for (auto global : globals_) {
     406        3364 :       buffer.write_u8(ValueTypes::ValueTypeCodeFor(global.type));
     407        3364 :       buffer.write_u8(global.mutability ? 1 : 0);
     408        3364 :       switch (global.init.kind) {
     409             :         case WasmInitExpr::kI32Const:
     410             :           DCHECK_EQ(kWasmI32, global.type);
     411             :           buffer.write_u8(kExprI32Const);
     412        2365 :           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          70 :           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         339 :           buffer.write_f64(global.init.val.f64_const);
     428             :           break;
     429             :         case WasmInitExpr::kGlobalIndex:
     430             :           buffer.write_u8(kExprGetGlobal);
     431          15 :           buffer.write_u32v(global.init.val.global_index);
     432          15 :           break;
     433             :         default: {
     434             :           // No initializer, emit a default value.
     435         575 :           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         967 :     FixupSection(buffer, start);
     462             :   }
     463             : 
     464             :   // == emit exports ===========================================================
     465        6744 :   if (!function_exports_.empty()) {
     466        3337 :     size_t start = EmitSection(kExportSectionCode, buffer);
     467        3337 :     buffer.write_size(function_exports_.size());
     468       12222 :     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       11096 :                         function_imports_.size());
     473             :     }
     474        3337 :     FixupSection(buffer, start);
     475             :   }
     476             : 
     477             :   // == emit start function index ==============================================
     478        3407 :   if (start_function_index_ >= 0) {
     479        3015 :     size_t start = EmitSection(kStartSectionCode, buffer);
     480        6030 :     buffer.write_size(start_function_index_ + function_imports_.size());
     481        3015 :     FixupSection(buffer, start);
     482             :   }
     483             : 
     484             :   // == emit function table elements ===========================================
     485        3407 :   if (indirect_functions_.size() > 0) {
     486          55 :     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          55 :     buffer.write_u32v(0);
     491             :     buffer.write_u8(kExprEnd);
     492          55 :     buffer.write_size(indirect_functions_.size());  // element count
     493             : 
     494        4722 :     for (auto index : indirect_functions_) {
     495        9224 :       buffer.write_size(index + function_imports_.size());
     496             :     }
     497             : 
     498          55 :     FixupSection(buffer, start);
     499             :   }
     500             : 
     501             :   // == emit code ==============================================================
     502        3407 :   if (functions_.size() > 0) {
     503        3402 :     size_t start = EmitSection(kCodeSectionCode, buffer);
     504        3402 :     buffer.write_size(functions_.size());
     505       24153 :     for (auto function : functions_) {
     506       17349 :       function->WriteBody(buffer);
     507             :     }
     508        3400 :     FixupSection(buffer, start);
     509             :   }
     510             : 
     511             :   // == emit data segments =====================================================
     512        6817 :   if (data_segments_.size() > 0) {
     513           5 :     size_t start = EmitSection(kDataSectionCode, buffer);
     514           5 :     buffer.write_size(data_segments_.size());
     515             : 
     516          15 :     for (auto segment : data_segments_) {
     517             :       buffer.write_u8(0);              // linear memory segment
     518             :       buffer.write_u8(kExprI32Const);  // initializer expression for dest
     519           5 :       buffer.write_u32v(segment.dest);
     520             :       buffer.write_u8(kExprEnd);
     521          10 :       buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
     522          10 :       buffer.write(&segment.data[0], segment.data.size());
     523             :     }
     524           5 :     FixupSection(buffer, start);
     525             :   }
     526             : 
     527             :   // == Emit names =============================================================
     528        3798 :   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        3018 :     buffer.write_size(4);
     535        3018 :     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        3020 :     uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
     543        3020 :     buffer.write_size(num_imports + num_function_names);
     544             :     uint32_t function_index = 0;
     545        5434 :     for (; function_index < num_imports; ++function_index) {
     546        2414 :       const WasmFunctionImport* import = &function_imports_[function_index];
     547             :       DCHECK(!import->name.is_empty());
     548        2414 :       buffer.write_u32v(function_index);
     549             :       buffer.write_string(import->name);
     550             :     }
     551        3020 :     if (num_function_names > 0) {
     552       22862 :       for (auto function : functions_) {
     553             :         DCHECK_EQ(function_index,
     554             :                   function->func_index() + function_imports_.size());
     555       16831 :         if (!function->name_.is_empty()) {
     556       13818 :           buffer.write_u32v(function_index);
     557             :           buffer.write_string(function->name_);
     558             :         }
     559       16832 :         ++function_index;
     560             :       }
     561             :     }
     562        3021 :     FixupSection(buffer, functions_start);
     563        3020 :     FixupSection(buffer, start);
     564             :   }
     565        3407 : }
     566             : 
     567        3015 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
     568             :   // == Emit asm.js offset table ===============================================
     569        6030 :   buffer.write_size(functions_.size());
     570             :   // Emit the offset table per function.
     571       22859 :   for (auto function : functions_) {
     572       16831 :     function->WriteAsmWasmOffsetTable(buffer);
     573             :   }
     574             :   // Append a 0 to indicate that this is an encoded table.
     575             :   buffer.write_u8(0);
     576        3015 : }
     577             : }  // namespace wasm
     578             : }  // namespace internal
     579      183867 : }  // namespace v8

Generated by: LCOV version 1.10