LCOV - code coverage report
Current view: top level - src/wasm - wasm-module-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 238 248 96.0 %
Date: 2019-04-17 Functions: 41 44 93.2 %

          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       17614 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
      30             :   // Emit the section code.
      31       17614 :   buffer.write_u8(code);
      32             : 
      33             :   // Emit a placeholder for the length.
      34       17615 :   return buffer.reserve_u32v();
      35             : }
      36             : 
      37             : // Patch the size of a section after it's finished.
      38             : void FixupSection(ZoneBuffer& buffer, size_t start) {
      39       22623 :   buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
      40             :                                                  kPaddedVarInt32Size));
      41             : }
      42             : 
      43             : }  // namespace
      44             : 
      45       15593 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
      46             :     : builder_(builder),
      47             :       locals_(builder->zone()),
      48             :       signature_index_(0),
      49             :       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       62372 :       asm_offsets_(builder->zone(), 8) {}
      57             : 
      58       49868 : 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       14571 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
      63             :   DCHECK(!locals_.has_sig());
      64             :   locals_.set_sig(sig);
      65       14985 :   signature_index_ = builder_->AddSignature(sig);
      66       14571 : }
      67             : 
      68      545535 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
      69             :   DCHECK(locals_.has_sig());
      70      545535 :   return locals_.AddLocals(1, type);
      71             : }
      72             : 
      73      501689 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
      74      501689 :   EmitWithU32V(kExprGetLocal, local_index);
      75      501689 : }
      76             : 
      77      548954 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
      78      548954 :   EmitWithU32V(kExprSetLocal, local_index);
      79      548954 : }
      80             : 
      81      179465 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
      82      179465 :   EmitWithU32V(kExprTeeLocal, local_index);
      83      179465 : }
      84             : 
      85         414 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
      86       33686 :   body_.write(code, code_size);
      87         414 : }
      88             : 
      89    12778224 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
      90             : 
      91      151419 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
      92      151419 :   body_.write_u8(opcode);
      93             :   body_.write_u8(immediate);
      94      151419 : }
      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     1510135 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
     104     1510135 :   body_.write_u8(opcode);
     105             :   body_.write_i32v(immediate);
     106     1510135 : }
     107             : 
     108     1281265 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
     109     1281265 :   body_.write_u8(opcode);
     110     1281265 :   body_.write_u32v(immediate);
     111     1281265 : }
     112             : 
     113     1468770 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
     114     1468770 :   EmitWithI32V(kExprI32Const, value);
     115     1468770 : }
     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     5009357 : void WasmFunctionBuilder::EmitF64Const(double value) {
     128     5009357 :   body_.write_u8(kExprF64Const);
     129             :   body_.write_f64(value);
     130     5009357 : }
     131             : 
     132       33272 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
     133             :   DirectCallIndex call;
     134       33272 :   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       12648 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
     142             : 
     143       59287 : 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       59287 :   uint32_t byte_offset = static_cast<uint32_t>(body_.size());
     150       59287 :   asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
     151       59287 :   last_asm_byte_offset_ = byte_offset;
     152             : 
     153             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
     154       59287 :   uint32_t call_position_u32 = static_cast<uint32_t>(call_position);
     155       59287 :   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       59287 :   uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position);
     159       59287 :   asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32);
     160       59287 :   last_asm_source_position_ = to_number_position_u32;
     161       59287 : }
     162             : 
     163       12648 : 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       12648 :   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       12648 :   asm_func_start_source_position_ = function_position_u32;
     171       12648 :   last_asm_source_position_ = function_position_u32;
     172       12648 : }
     173             : 
     174      392914 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
     175             :   DCHECK_LE(position, body_.size());
     176             :   body_.Truncate(position);
     177      392914 : }
     178             : 
     179           0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
     180       14805 :   buffer.write_u32v(signature_index_);
     181           0 : }
     182             : 
     183       14805 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
     184       14805 :   size_t locals_size = locals_.Size();
     185       14805 :   buffer.write_size(locals_size + body_.size());
     186       14805 :   buffer.EnsureSpace(locals_size);
     187             :   byte** ptr = buffer.pos_ptr();
     188       14805 :   locals_.Emit(*ptr);
     189       14805 :   (*ptr) += locals_size;  // UGLY: manual bump of position pointer
     190       14805 :   if (body_.size() > 0) {
     191             :     size_t base = buffer.offset();
     192       14805 :     buffer.write(body_.begin(), body_.size());
     193       48033 :     for (DirectCallIndex call : direct_calls_) {
     194       33228 :       buffer.patch_u32v(
     195             :           base + call.offset,
     196             :           call.direct_index +
     197       33228 :               static_cast<uint32_t>(builder_->function_imports_.size()));
     198             :     }
     199             :   }
     200       14805 : }
     201             : 
     202       14391 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
     203       16890 :   if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
     204        2499 :     buffer.write_size(0);
     205        2499 :     return;
     206             :   }
     207       11892 :   size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
     208             :   size_t func_start_size =
     209       11892 :       LEBHelper::sizeof_u32v(asm_func_start_source_position_);
     210       11892 :   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       11892 :   buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
     214             :   // Start position of the function.
     215       11892 :   buffer.write_u32v(asm_func_start_source_position_);
     216       11892 :   buffer.write(asm_offsets_.begin(), asm_offsets_.size());
     217             : }
     218             : 
     219        4073 : 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        8146 :       has_shared_memory_(false) {}
     235             : 
     236       15593 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
     237       46779 :   functions_.push_back(new (zone_) WasmFunctionBuilder(this));
     238             :   // Add the signature if one was provided here.
     239       16007 :   if (sig) functions_.back()->SetSignature(sig);
     240       15593 :   return functions_.back();
     241             : }
     242             : 
     243           4 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
     244             :                                        uint32_t dest) {
     245           8 :   data_segments_.push_back({ZoneVector<byte>(zone()), dest});
     246             :   ZoneVector<byte>& vec = data_segments_.back().data;
     247          36 :   for (uint32_t i = 0; i < size; i++) {
     248          16 :     vec.push_back(data[i]);
     249             :   }
     250           4 : }
     251             : 
     252       64431 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
     253       64431 :   auto sig_entry = signature_map_.find(*sig);
     254       64431 :   if (sig_entry != signature_map_.end()) return sig_entry->second;
     255        6673 :   uint32_t index = static_cast<uint32_t>(signatures_.size());
     256        6673 :   signature_map_.emplace(*sig, index);
     257        6673 :   signatures_.push_back(sig);
     258        6673 :   return index;
     259             : }
     260             : 
     261         219 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
     262         219 :   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        2076 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
     277             :                                       FunctionSig* sig) {
     278        4152 :   function_imports_.push_back({name, AddSignature(sig)});
     279        2076 :   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        2499 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
     289        2499 :   start_function_index_ = function->func_index();
     290        2499 : }
     291             : 
     292        4650 : void WasmModuleBuilder::AddExport(Vector<const char> name,
     293             :                                   WasmFunctionBuilder* function) {
     294        9300 :   function_exports_.push_back({name, function->func_index()});
     295        4650 : }
     296             : 
     297        2958 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
     298             :                                       bool mutability,
     299             :                                       const WasmInitExpr& init) {
     300        5916 :   globals_.push_back({type, exported, mutability, init});
     301        2958 :   return static_cast<uint32_t>(globals_.size() - 1);
     302             : }
     303             : 
     304        3759 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
     305        3759 :   min_memory_size_ = value;
     306        3759 : }
     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        2813 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
     316             :   // == Emit magic =============================================================
     317        2813 :   buffer.write_u32(kWasmMagic);
     318        2813 :   buffer.write_u32(kWasmVersion);
     319             : 
     320             :   // == Emit signatures ========================================================
     321        2813 :   if (signatures_.size() > 0) {
     322        2809 :     size_t start = EmitSection(kTypeSectionCode, buffer);
     323        2809 :     buffer.write_size(signatures_.size());
     324             : 
     325        9228 :     for (FunctionSig* sig : signatures_) {
     326             :       buffer.write_u8(kWasmFunctionTypeCode);
     327        6419 :       buffer.write_size(sig->parameter_count());
     328       18279 :       for (auto param : sig->parameters()) {
     329        5930 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(param));
     330             :       }
     331        6419 :       buffer.write_size(sig->return_count());
     332       13391 :       for (auto ret : sig->returns()) {
     333        3486 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(ret));
     334             :       }
     335             :     }
     336             :     FixupSection(buffer, start);
     337             :   }
     338             : 
     339             :   // == Emit imports ===========================================================
     340        2813 :   if (global_imports_.size() + function_imports_.size() > 0) {
     341         234 :     size_t start = EmitSection(kImportSectionCode, buffer);
     342         234 :     buffer.write_size(global_imports_.size() + function_imports_.size());
     343         703 :     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        2274 :     for (auto import : function_imports_) {
     351        2040 :       buffer.write_u32v(0);              // module name (length)
     352             :       buffer.write_string(import.name);  // field name
     353             :       buffer.write_u8(kExternalFunction);
     354        2040 :       buffer.write_u32v(import.sig_index);
     355             :     }
     356             :     FixupSection(buffer, start);
     357             :   }
     358             : 
     359             :   // == Emit function signatures ===============================================
     360             :   uint32_t num_function_names = 0;
     361        2813 :   if (functions_.size() > 0) {
     362        2809 :     size_t start = EmitSection(kFunctionSectionCode, buffer);
     363        2809 :     buffer.write_size(functions_.size());
     364       17614 :     for (auto function : functions_) {
     365             :       function->WriteSignature(buffer);
     366       14805 :       if (!function->name_.empty()) ++num_function_names;
     367             :     }
     368             :     FixupSection(buffer, start);
     369             :   }
     370             : 
     371             :   // == emit function table ====================================================
     372        2813 :   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             :     FixupSection(buffer, start);
     380             :   }
     381             : 
     382             :   // == emit memory declaration ================================================
     383             :   {
     384        2813 :     size_t start = EmitSection(kMemorySectionCode, buffer);
     385             :     buffer.write_u8(1);  // memory count
     386        2813 :     if (has_shared_memory_) {
     387           4 :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
     388             :                                            : MemoryFlags::kSharedNoMaximum);
     389             :     } else {
     390        2809 :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
     391             :                                            : MemoryFlags::kNoMaximum);
     392             :     }
     393        2813 :     buffer.write_u32v(min_memory_size_);
     394        2813 :     if (has_max_memory_size_) {
     395           6 :       buffer.write_u32v(max_memory_size_);
     396             :     }
     397             :     FixupSection(buffer, start);
     398             :   }
     399             : 
     400             :   // == Emit globals ===========================================================
     401        2813 :   if (globals_.size() > 0) {
     402         793 :     size_t start = EmitSection(kGlobalSectionCode, buffer);
     403         793 :     buffer.write_size(globals_.size());
     404             : 
     405        3565 :     for (auto global : globals_) {
     406        2772 :       buffer.write_u8(ValueTypes::ValueTypeCodeFor(global.type));
     407        2772 :       buffer.write_u8(global.mutability ? 1 : 0);
     408        2772 :       switch (global.init.kind) {
     409             :         case WasmInitExpr::kI32Const:
     410             :           DCHECK_EQ(kWasmI32, global.type);
     411             :           buffer.write_u8(kExprI32Const);
     412        1949 :           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          60 :           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         274 :           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             :     FixupSection(buffer, start);
     462             :   }
     463             : 
     464             :   // == emit exports ===========================================================
     465        2813 :   if (!function_exports_.empty()) {
     466        2757 :     size_t start = EmitSection(kExportSectionCode, buffer);
     467        2757 :     buffer.write_size(function_exports_.size());
     468        7343 :     for (auto function_export : function_exports_) {
     469             :       buffer.write_string(function_export.name);
     470             :       buffer.write_u8(kExternalFunction);
     471        9172 :       buffer.write_size(function_export.function_index +
     472        4586 :                         function_imports_.size());
     473             :     }
     474             :     FixupSection(buffer, start);
     475             :   }
     476             : 
     477             :   // == emit start function index ==============================================
     478        2813 :   if (start_function_index_ >= 0) {
     479        2499 :     size_t start = EmitSection(kStartSectionCode, buffer);
     480        4998 :     buffer.write_size(start_function_index_ + function_imports_.size());
     481             :     FixupSection(buffer, start);
     482             :   }
     483             : 
     484             :   // == emit function table elements ===========================================
     485        2813 :   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        4230 :     for (auto index : indirect_functions_) {
     495        8370 :       buffer.write_size(index + function_imports_.size());
     496             :     }
     497             : 
     498             :     FixupSection(buffer, start);
     499             :   }
     500             : 
     501             :   // == emit code ==============================================================
     502        2813 :   if (functions_.size() > 0) {
     503        2809 :     size_t start = EmitSection(kCodeSectionCode, buffer);
     504        2809 :     buffer.write_size(functions_.size());
     505       17614 :     for (auto function : functions_) {
     506       14805 :       function->WriteBody(buffer);
     507             :     }
     508             :     FixupSection(buffer, start);
     509             :   }
     510             : 
     511             :   // == emit data segments =====================================================
     512        2813 :   if (data_segments_.size() > 0) {
     513           4 :     size_t start = EmitSection(kDataSectionCode, buffer);
     514           4 :     buffer.write_size(data_segments_.size());
     515             : 
     516           8 :     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           4 :       buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
     522           4 :       buffer.write(&segment.data[0], segment.data.size());
     523             :     }
     524             :     FixupSection(buffer, start);
     525             :   }
     526             : 
     527             :   // == Emit names =============================================================
     528        2813 :   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        2503 :     buffer.write_size(4);
     535        2503 :     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        2503 :     uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
     543        2503 :     buffer.write_size(num_imports + num_function_names);
     544             :     uint32_t function_index = 0;
     545        6583 :     for (; function_index < num_imports; ++function_index) {
     546        2040 :       const WasmFunctionImport* import = &function_imports_[function_index];
     547             :       DCHECK(!import->name.empty());
     548        2040 :       buffer.write_u32v(function_index);
     549             :       buffer.write_string(import->name);
     550             :     }
     551        2503 :     if (num_function_names > 0) {
     552       16890 :       for (auto function : functions_) {
     553             :         DCHECK_EQ(function_index,
     554             :                   function->func_index() + function_imports_.size());
     555       14391 :         if (!function->name_.empty()) {
     556       11892 :           buffer.write_u32v(function_index);
     557             :           buffer.write_string(function->name_);
     558             :         }
     559       14391 :         ++function_index;
     560             :       }
     561             :     }
     562             :     FixupSection(buffer, functions_start);
     563             :     FixupSection(buffer, start);
     564             :   }
     565        2813 : }
     566             : 
     567        2499 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
     568             :   // == Emit asm.js offset table ===============================================
     569        2499 :   buffer.write_size(functions_.size());
     570             :   // Emit the offset table per function.
     571       16890 :   for (auto function : functions_) {
     572       14391 :     function->WriteAsmWasmOffsetTable(buffer);
     573             :   }
     574             :   // Append a 0 to indicate that this is an encoded table.
     575             :   buffer.write_u8(0);
     576        2499 : }
     577             : }  // namespace wasm
     578             : }  // namespace internal
     579      122004 : }  // namespace v8

Generated by: LCOV version 1.10