LCOV - code coverage report
Current view: top level - src/wasm - wasm-module-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 261 271 96.3 %
Date: 2017-10-20 Functions: 42 45 93.3 %

          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/module-decoder.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       24819 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
      30             :   // Emit the section code.
      31       24819 :   buffer.write_u8(code);
      32             : 
      33             :   // Emit a placeholder for the length.
      34       24819 :   return buffer.reserve_u32v();
      35             : }
      36             : 
      37             : // Patch the size of a section after it's finished.
      38       31913 : void FixupSection(ZoneBuffer& buffer, size_t start) {
      39             :   buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
      40       31913 :                                                  kPaddedVarInt32Size));
      41       31913 : }
      42             : 
      43             : }  // namespace
      44             : 
      45      187731 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
      46             :     : builder_(builder),
      47             :       locals_(builder->zone()),
      48             :       signature_index_(0),
      49       20859 :       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      104295 :       asm_offsets_(builder->zone(), 8) {}
      57             : 
      58       60308 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
      59             : 
      60        9004 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
      61             : 
      62       19505 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
      63             :   DCHECK(!locals_.has_sig());
      64             :   locals_.set_sig(sig);
      65       20036 :   signature_index_ = builder_->AddSignature(sig);
      66       19505 : }
      67             : 
      68       56116 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
      69             :   DCHECK(locals_.has_sig());
      70       56116 :   return locals_.AddLocals(1, type);
      71             : }
      72             : 
      73      630558 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
      74      630558 :   EmitWithU32V(kExprGetLocal, local_index);
      75      630558 : }
      76             : 
      77       59877 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
      78       59877 :   EmitWithU32V(kExprSetLocal, local_index);
      79       59877 : }
      80             : 
      81      223075 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
      82      223075 :   EmitWithU32V(kExprTeeLocal, local_index);
      83      223075 : }
      84             : 
      85         533 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
      86       41445 :   body_.write(code, code_size);
      87         533 : }
      88             : 
      89     3480860 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
      90             : 
      91      188831 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
      92      188831 :   body_.write_u8(opcode);
      93             :   body_.write_u8(immediate);
      94      188831 : }
      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     1260464 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
     104     1260464 :   body_.write_u8(opcode);
     105             :   body_.write_i32v(immediate);
     106     1260464 : }
     107             : 
     108      976025 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
     109      976025 :   body_.write_u8(opcode);
     110      976025 :   body_.write_u32v(immediate);
     111      976025 : }
     112             : 
     113     1208026 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
     114     1208026 :   EmitWithI32V(kExprI32Const, value);
     115     1208026 : }
     116             : 
     117           0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
     118           0 :   body_.write_u8(kExprI64Const);
     119             :   body_.write_i64v(value);
     120           0 : }
     121             : 
     122          48 : void WasmFunctionBuilder::EmitF32Const(float value) {
     123          48 :   body_.write_u8(kExprF32Const);
     124             :   body_.write_f32(value);
     125          48 : }
     126             : 
     127       12212 : void WasmFunctionBuilder::EmitF64Const(double value) {
     128       12212 :   body_.write_u8(kExprF64Const);
     129             :   body_.write_f64(value);
     130       12212 : }
     131             : 
     132       40912 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
     133             :   DirectCallIndex call;
     134       81824 :   call.offset = body_.size();
     135       40912 :   call.direct_index = index;
     136       40912 :   direct_calls_.push_back(call);
     137       40912 :   byte placeholder_bytes[kMaxVarInt32Size] = {0};
     138             :   EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
     139       40912 : }
     140             : 
     141       16733 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
     142             : 
     143       55615 : void WasmFunctionBuilder::AddAsmWasmOffset(int call_position,
     144             :                                            int 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      111230 :   uint32_t byte_offset = static_cast<uint32_t>(body_.size());
     150       55615 :   asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
     151       55615 :   last_asm_byte_offset_ = byte_offset;
     152             : 
     153             :   DCHECK_GE(call_position, 0);
     154       55615 :   asm_offsets_.write_i32v(call_position - last_asm_source_position_);
     155             : 
     156             :   DCHECK_GE(to_number_position, 0);
     157       55615 :   asm_offsets_.write_i32v(to_number_position - call_position);
     158       55615 :   last_asm_source_position_ = to_number_position;
     159       55615 : }
     160             : 
     161       16733 : void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) {
     162             :   DCHECK_EQ(0, asm_func_start_source_position_);
     163             :   DCHECK_LE(0, position);
     164             :   // Must be called before emitting any asm.js source position.
     165             :   DCHECK_EQ(0, asm_offsets_.size());
     166       16733 :   asm_func_start_source_position_ = position;
     167       16733 :   last_asm_source_position_ = position;
     168       16733 : }
     169             : 
     170      487869 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
     171             :   DCHECK_LE(position, body_.size());
     172      487869 :   body_.Truncate(position);
     173      487869 : }
     174             : 
     175           0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
     176       19790 :   buffer.write_u32v(signature_index_);
     177           0 : }
     178             : 
     179       80426 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
     180       19790 :   size_t locals_size = locals_.Size();
     181       59370 :   buffer.write_size(locals_size + body_.size());
     182       19790 :   buffer.EnsureSpace(locals_size);
     183             :   byte** ptr = buffer.pos_ptr();
     184       19790 :   locals_.Emit(*ptr);
     185       19790 :   (*ptr) += locals_size;  // UGLY: manual bump of position pointer
     186       19790 :   if (body_.size() > 0) {
     187             :     size_t base = buffer.offset();
     188       19790 :     buffer.write(body_.begin(), body_.size());
     189       80426 :     for (DirectCallIndex call : direct_calls_) {
     190             :       buffer.patch_u32v(
     191             :           base + call.offset,
     192             :           call.direct_index +
     193       81692 :               static_cast<uint32_t>(builder_->function_imports_.size()));
     194             :     }
     195             :   }
     196       19790 : }
     197             : 
     198       19259 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
     199       54230 :   if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
     200        3547 :     buffer.write_size(0);
     201       22806 :     return;
     202             :   }
     203       15712 :   size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
     204             :   size_t func_start_size =
     205       15712 :       LEBHelper::sizeof_u32v(asm_func_start_source_position_);
     206       15712 :   buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
     207             :   // Offset of the recorded byte offsets.
     208             :   DCHECK_GE(kMaxUInt32, locals_.Size());
     209       15712 :   buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
     210             :   // Start position of the function.
     211       15712 :   buffer.write_u32v(asm_func_start_source_position_);
     212       15712 :   buffer.write(asm_offsets_.begin(), asm_offsets_.size());
     213             : }
     214             : 
     215      346446 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
     216             :     : zone_(zone),
     217             :       signatures_(zone),
     218             :       function_imports_(zone),
     219             :       function_exports_(zone),
     220             :       global_imports_(zone),
     221             :       functions_(zone),
     222             :       data_segments_(zone),
     223             :       indirect_functions_(zone),
     224             :       globals_(zone),
     225             :       signature_map_(zone),
     226             :       start_function_index_(-1),
     227             :       min_memory_size_(16),
     228             :       max_memory_size_(0),
     229             :       has_max_memory_size_(false),
     230      692892 :       has_shared_memory_(false) {}
     231             : 
     232       20859 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
     233       62577 :   functions_.push_back(new (zone_) WasmFunctionBuilder(this));
     234             :   // Add the signature if one was provided here.
     235       21390 :   if (sig) functions_.back()->SetSignature(sig);
     236       20859 :   return functions_.back();
     237             : }
     238             : 
     239           6 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
     240           6 :                                        uint32_t dest) {
     241          12 :   data_segments_.push_back({ZoneVector<byte>(zone()), dest});
     242             :   ZoneVector<byte>& vec = data_segments_.back().data;
     243          30 :   for (uint32_t i = 0; i < size; i++) {
     244          24 :     vec.push_back(data[i]);
     245             :   }
     246           6 : }
     247             : 
     248     1263550 : bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
     249     1263550 :                                                         FunctionSig* b) const {
     250      445157 :   if (a->return_count() < b->return_count()) return true;
     251      420353 :   if (a->return_count() > b->return_count()) return false;
     252      389121 :   if (a->parameter_count() < b->parameter_count()) return true;
     253      265015 :   if (a->parameter_count() > b->parameter_count()) return false;
     254       79266 :   for (size_t r = 0; r < a->return_count(); r++) {
     255       93575 :     if (a->GetReturn(r) < b->GetReturn(r)) return true;
     256       90974 :     if (a->GetReturn(r) > b->GetReturn(r)) return false;
     257             :   }
     258      320191 :   for (size_t p = 0; p < a->parameter_count(); p++) {
     259      335697 :     if (a->GetParam(p) < b->GetParam(p)) return true;
     260      333319 :     if (a->GetParam(p) > b->GetParam(p)) return false;
     261             :   }
     262             :   return false;
     263             : }
     264             : 
     265       80987 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
     266             :   SignatureMap::iterator pos = signature_map_.find(sig);
     267       80987 :   if (pos != signature_map_.end()) {
     268       71520 :     return pos->second;
     269             :   } else {
     270       18934 :     uint32_t index = static_cast<uint32_t>(signatures_.size());
     271        9467 :     signature_map_[sig] = index;
     272        9467 :     signatures_.push_back(sig);
     273        9467 :     return index;
     274             :   }
     275             : }
     276             : 
     277         299 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
     278         598 :   uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
     279             :   DCHECK_GE(FLAG_wasm_max_table_size, index);
     280         299 :   if (count > FLAG_wasm_max_table_size - index) {
     281             :     return std::numeric_limits<uint32_t>::max();
     282             :   }
     283         285 :   indirect_functions_.resize(indirect_functions_.size() + count);
     284         285 :   return index;
     285             : }
     286             : 
     287        5045 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
     288             :                                             uint32_t direct) {
     289       10090 :   indirect_functions_[indirect] = direct;
     290        5045 : }
     291             : 
     292        2836 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
     293             :                                       FunctionSig* sig) {
     294        5672 :   function_imports_.push_back({name, AddSignature(sig)});
     295        2836 :   return static_cast<uint32_t>(function_imports_.size() - 1);
     296             : }
     297             : 
     298         661 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
     299             :                                             ValueType type) {
     300        1322 :   global_imports_.push_back({name, WasmOpcodes::ValueTypeCodeFor(type)});
     301         661 :   return static_cast<uint32_t>(global_imports_.size() - 1);
     302             : }
     303             : 
     304        3547 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
     305        3547 :   start_function_index_ = function->func_index();
     306        3547 : }
     307             : 
     308        6514 : void WasmModuleBuilder::AddExport(Vector<const char> name,
     309        6514 :                                   WasmFunctionBuilder* function) {
     310       19542 :   function_exports_.push_back({name, function->func_index()});
     311        6514 : }
     312             : 
     313        4217 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
     314             :                                       bool mutability,
     315             :                                       const WasmInitExpr& init) {
     316        8434 :   globals_.push_back({type, exported, mutability, init});
     317        4217 :   return static_cast<uint32_t>(globals_.size() - 1);
     318             : }
     319             : 
     320      346047 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
     321      346047 :   min_memory_size_ = value;
     322      346047 : }
     323             : 
     324           9 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
     325           9 :   has_max_memory_size_ = true;
     326           9 :   max_memory_size_ = value;
     327           9 : }
     328             : 
     329           6 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
     330             : 
     331        3946 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
     332             :   // == Emit magic =============================================================
     333             :   buffer.write_u32(kWasmMagic);
     334             :   buffer.write_u32(kWasmVersion);
     335             : 
     336             :   // == Emit signatures ========================================================
     337       11838 :   if (signatures_.size() > 0) {
     338        3946 :     size_t start = EmitSection(kTypeSectionCode, buffer);
     339        3946 :     buffer.write_size(signatures_.size());
     340             : 
     341       44348 :     for (FunctionSig* sig : signatures_) {
     342             :       buffer.write_u8(kWasmFunctionTypeForm);
     343        9114 :       buffer.write_size(sig->parameter_count());
     344       17451 :       for (auto param : sig->parameters()) {
     345        8337 :         buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(param));
     346             :       }
     347        9114 :       buffer.write_size(sig->return_count());
     348       14071 :       for (auto ret : sig->returns()) {
     349        4957 :         buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret));
     350             :       }
     351             :     }
     352        3946 :     FixupSection(buffer, start);
     353             :   }
     354             : 
     355             :   // == Emit imports ===========================================================
     356       33821 :   if (global_imports_.size() + function_imports_.size() > 0) {
     357         322 :     size_t start = EmitSection(kImportSectionCode, buffer);
     358         322 :     buffer.write_size(global_imports_.size() + function_imports_.size());
     359        1305 :     for (auto import : global_imports_) {
     360         661 :       buffer.write_u32v(0);              // module name (length)
     361             :       buffer.write_string(import.name);  // field name
     362             :       buffer.write_u8(kExternalGlobal);
     363             :       buffer.write_u8(import.type_code);
     364             :       buffer.write_u8(0);  // immutable
     365             :     }
     366        3426 :     for (auto import : function_imports_) {
     367        2782 :       buffer.write_u32v(0);              // module name (length)
     368             :       buffer.write_string(import.name);  // field name
     369             :       buffer.write_u8(kExternalFunction);
     370        2782 :       buffer.write_u32v(import.sig_index);
     371             :     }
     372         322 :     FixupSection(buffer, start);
     373             :   }
     374             : 
     375             :   // == Emit function signatures ===============================================
     376             :   uint32_t num_function_names = 0;
     377       19730 :   if (functions_.size() > 0) {
     378        3946 :     size_t start = EmitSection(kFunctionSectionCode, buffer);
     379        3946 :     buffer.write_size(functions_.size());
     380       27682 :     for (auto function : functions_) {
     381             :       function->WriteSignature(buffer);
     382       19790 :       if (!function->name_.is_empty()) ++num_function_names;
     383             :     }
     384        3946 :     FixupSection(buffer, start);
     385             :   }
     386             : 
     387             :   // == emit function table ====================================================
     388       12033 :   if (indirect_functions_.size() > 0) {
     389          65 :     size_t start = EmitSection(kTableSectionCode, buffer);
     390             :     buffer.write_u8(1);  // table count
     391             :     buffer.write_u8(kWasmAnyFunctionTypeForm);
     392             :     buffer.write_u8(kHasMaximumFlag);
     393          65 :     buffer.write_size(indirect_functions_.size());
     394          65 :     buffer.write_size(indirect_functions_.size());
     395          65 :     FixupSection(buffer, start);
     396             :   }
     397             : 
     398             :   // == emit memory declaration ================================================
     399             :   {
     400        3946 :     size_t start = EmitSection(kMemorySectionCode, buffer);
     401             :     buffer.write_u8(1);  // memory count
     402        3946 :     if (has_shared_memory_) {
     403             :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
     404           6 :                                            : MemoryFlags::kSharedNoMaximum);
     405             :     } else {
     406             :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
     407        3940 :                                            : MemoryFlags::kNoMaximum);
     408             :     }
     409        3946 :     buffer.write_u32v(min_memory_size_);
     410        3946 :     if (has_max_memory_size_) {
     411           9 :       buffer.write_u32v(max_memory_size_);
     412             :     }
     413        3946 :     FixupSection(buffer, start);
     414             :   }
     415             : 
     416             :   // == Emit globals ===========================================================
     417        9036 :   if (globals_.size() > 0) {
     418        1144 :     size_t start = EmitSection(kGlobalSectionCode, buffer);
     419        1144 :     buffer.write_size(globals_.size());
     420             : 
     421        6247 :     for (auto global : globals_) {
     422        3959 :       buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(global.type));
     423        3959 :       buffer.write_u8(global.mutability ? 1 : 0);
     424        3959 :       switch (global.init.kind) {
     425             :         case WasmInitExpr::kI32Const:
     426             :           DCHECK_EQ(kWasmI32, global.type);
     427             :           buffer.write_u8(kExprI32Const);
     428        2784 :           buffer.write_i32v(global.init.val.i32_const);
     429             :           break;
     430             :         case WasmInitExpr::kI64Const:
     431             :           DCHECK_EQ(kWasmI64, global.type);
     432             :           buffer.write_u8(kExprI64Const);
     433           0 :           buffer.write_i64v(global.init.val.i64_const);
     434             :           break;
     435             :         case WasmInitExpr::kF32Const:
     436             :           DCHECK_EQ(kWasmF32, global.type);
     437             :           buffer.write_u8(kExprF32Const);
     438          84 :           buffer.write_f32(global.init.val.f32_const);
     439             :           break;
     440             :         case WasmInitExpr::kF64Const:
     441             :           DCHECK_EQ(kWasmF64, global.type);
     442             :           buffer.write_u8(kExprF64Const);
     443         400 :           buffer.write_f64(global.init.val.f64_const);
     444             :           break;
     445             :         case WasmInitExpr::kGlobalIndex:
     446             :           buffer.write_u8(kExprGetGlobal);
     447          18 :           buffer.write_u32v(global.init.val.global_index);
     448          18 :           break;
     449             :         default: {
     450             :           // No initializer, emit a default value.
     451         673 :           switch (global.type) {
     452             :             case kWasmI32:
     453             :               buffer.write_u8(kExprI32Const);
     454             :               // LEB encoding of 0.
     455             :               buffer.write_u8(0);
     456             :               break;
     457             :             case kWasmI64:
     458             :               buffer.write_u8(kExprI64Const);
     459             :               // LEB encoding of 0.
     460             :               buffer.write_u8(0);
     461             :               break;
     462             :             case kWasmF32:
     463             :               buffer.write_u8(kExprF32Const);
     464             :               buffer.write_f32(0.f);
     465             :               break;
     466             :             case kWasmF64:
     467             :               buffer.write_u8(kExprF64Const);
     468             :               buffer.write_f64(0.);
     469             :               break;
     470             :             default:
     471           0 :               UNREACHABLE();
     472             :           }
     473             :         }
     474             :       }
     475             :       buffer.write_u8(kExprEnd);
     476             :     }
     477        1144 :     FixupSection(buffer, start);
     478             :   }
     479             : 
     480             :   // == emit exports ===========================================================
     481        7832 :   if (!function_exports_.empty()) {
     482        3886 :     size_t start = EmitSection(kExportSectionCode, buffer);
     483        3886 :     buffer.write_size(function_exports_.size());
     484       14196 :     for (auto function_export : function_exports_) {
     485             :       buffer.write_string(function_export.name);
     486             :       buffer.write_u8(kExternalFunction);
     487             :       buffer.write_size(function_export.function_index +
     488       12848 :                         function_imports_.size());
     489             :     }
     490        3886 :     FixupSection(buffer, start);
     491             :   }
     492             : 
     493             :   // == emit start function index ==============================================
     494        3946 :   if (start_function_index_ >= 0) {
     495        3547 :     size_t start = EmitSection(kStartSectionCode, buffer);
     496        7094 :     buffer.write_size(start_function_index_ + function_imports_.size());
     497        3547 :     FixupSection(buffer, start);
     498             :   }
     499             : 
     500             :   // == emit function table elements ===========================================
     501        3946 :   if (indirect_functions_.size() > 0) {
     502          65 :     size_t start = EmitSection(kElementSectionCode, buffer);
     503             :     buffer.write_u8(1);              // count of entries
     504             :     buffer.write_u8(0);              // table index
     505             :     buffer.write_u8(kExprI32Const);  // offset
     506          65 :     buffer.write_u32v(0);
     507             :     buffer.write_u8(kExprEnd);
     508          65 :     buffer.write_size(indirect_functions_.size());  // element count
     509             : 
     510        5169 :     for (auto index : indirect_functions_) {
     511       10078 :       buffer.write_size(index + function_imports_.size());
     512             :     }
     513             : 
     514          65 :     FixupSection(buffer, start);
     515             :   }
     516             : 
     517             :   // == emit code ==============================================================
     518        3946 :   if (functions_.size() > 0) {
     519        3946 :     size_t start = EmitSection(kCodeSectionCode, buffer);
     520        3946 :     buffer.write_size(functions_.size());
     521       27682 :     for (auto function : functions_) {
     522       19790 :       function->WriteBody(buffer);
     523             :     }
     524        3946 :     FixupSection(buffer, start);
     525             :   }
     526             : 
     527             :   // == emit data segments =====================================================
     528        7898 :   if (data_segments_.size() > 0) {
     529           6 :     size_t start = EmitSection(kDataSectionCode, buffer);
     530           6 :     buffer.write_size(data_segments_.size());
     531             : 
     532          18 :     for (auto segment : data_segments_) {
     533             :       buffer.write_u8(0);              // linear memory segment
     534             :       buffer.write_u8(kExprI32Const);  // initializer expression for dest
     535           6 :       buffer.write_u32v(segment.dest);
     536             :       buffer.write_u8(kExprEnd);
     537          12 :       buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
     538          12 :       buffer.write(&segment.data[0], segment.data.size());
     539             :     }
     540           6 :     FixupSection(buffer, start);
     541             :   }
     542             : 
     543             :   // == Emit names =============================================================
     544        4345 :   if (num_function_names > 0 || !function_imports_.empty()) {
     545             :     // Emit the section code.
     546             :     buffer.write_u8(kUnknownSectionCode);
     547             :     // Emit a placeholder for the length.
     548             :     size_t start = buffer.reserve_u32v();
     549             :     // Emit the section string.
     550        3547 :     buffer.write_size(4);
     551        3547 :     buffer.write(reinterpret_cast<const byte*>("name"), 4);
     552             :     // Emit a subsection for the function names.
     553             :     buffer.write_u8(NameSectionType::kFunction);
     554             :     // Emit a placeholder for the subsection length.
     555             :     size_t functions_start = buffer.reserve_u32v();
     556             :     // Emit the function names.
     557             :     // Imports are always named.
     558        3547 :     uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
     559        3547 :     buffer.write_size(num_imports + num_function_names);
     560             :     uint32_t function_index = 0;
     561        6329 :     for (; function_index < num_imports; ++function_index) {
     562        2782 :       const WasmFunctionImport* import = &function_imports_[function_index];
     563             :       DCHECK(!import->name.is_empty());
     564        2782 :       buffer.write_u32v(function_index);
     565             :       buffer.write_string(import->name);
     566             :     }
     567        3547 :     if (num_function_names > 0) {
     568       26353 :       for (auto function : functions_) {
     569             :         DCHECK_EQ(function_index,
     570             :                   function->func_index() + function_imports_.size());
     571       19259 :         if (!function->name_.is_empty()) {
     572       15712 :           buffer.write_u32v(function_index);
     573             :           buffer.write_string(function->name_);
     574             :         }
     575       19259 :         ++function_index;
     576             :       }
     577             :     }
     578        3547 :     FixupSection(buffer, functions_start);
     579        3547 :     FixupSection(buffer, start);
     580             :   }
     581        3946 : }
     582             : 
     583        3547 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
     584             :   // == Emit asm.js offset table ===============================================
     585        7094 :   buffer.write_size(functions_.size());
     586             :   // Emit the offset table per function.
     587       26353 :   for (auto function : functions_) {
     588       19259 :     function->WriteAsmWasmOffsetTable(buffer);
     589             :   }
     590             :   // Append a 0 to indicate that this is an encoded table.
     591             :   buffer.write_u8(0);
     592        3547 : }
     593             : }  // namespace wasm
     594             : }  // namespace internal
     595             : }  // namespace v8

Generated by: LCOV version 1.10