LCOV - code coverage report
Current view: top level - src/wasm - wasm-module-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 263 275 95.6 %
Date: 2017-04-26 Functions: 40 43 93.0 %

          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             : #if DEBUG
      22             : #define TRACE(...)                                    \
      23             :   do {                                                \
      24             :     if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \
      25             :   } while (false)
      26             : #else
      27             : #define TRACE(...)
      28             : #endif
      29             : 
      30             : namespace v8 {
      31             : namespace internal {
      32             : namespace wasm {
      33             : 
      34             : namespace {
      35             : 
      36             : // Emit a section code and the size as a padded varint that can be patched
      37             : // later.
      38       24875 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
      39             :   // Emit the section code.
      40             :   buffer.write_u8(code);
      41             : 
      42             :   // Emit a placeholder for the length.
      43       24875 :   return buffer.reserve_u32v();
      44             : }
      45             : 
      46             : // Patch the size of a section after it's finished.
      47       31143 : void FixupSection(ZoneBuffer& buffer, size_t start) {
      48             :   buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
      49       31143 :                                                  kPaddedVarInt32Size));
      50       31143 : }
      51             : 
      52             : }  // namespace
      53             : 
      54      145565 : WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
      55             :     : builder_(builder),
      56             :       locals_(builder->zone()),
      57             :       signature_index_(0),
      58       20795 :       func_index_(static_cast<uint32_t>(builder->functions_.size())),
      59             :       body_(builder->zone()),
      60             :       name_(builder->zone()),
      61             :       exported_names_(builder->zone()),
      62             :       i32_temps_(builder->zone()),
      63             :       i64_temps_(builder->zone()),
      64             :       f32_temps_(builder->zone()),
      65             :       f64_temps_(builder->zone()),
      66             :       direct_calls_(builder->zone()),
      67       83180 :       asm_offsets_(builder->zone(), 8) {}
      68             : 
      69        5236 : void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
      70             : 
      71       41327 : void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
      72             : 
      73        5681 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
      74             :   DCHECK(!locals_.has_sig());
      75             :   locals_.set_sig(sig);
      76       20596 :   signature_index_ = builder_->AddSignature(sig);
      77        5681 : }
      78             : 
      79       37808 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
      80             :   DCHECK(locals_.has_sig());
      81       37808 :   return locals_.AddLocals(1, type);
      82             : }
      83             : 
      84      445830 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
      85      445830 :   EmitWithU32V(kExprGetLocal, local_index);
      86      445830 : }
      87             : 
      88      169519 : void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
      89      169519 :   EmitWithU32V(kExprSetLocal, local_index);
      90      169519 : }
      91             : 
      92       22026 : void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
      93       22026 :   EmitWithU32V(kExprTeeLocal, local_index);
      94       22026 : }
      95             : 
      96         411 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
      97       27160 :   body_.write(code, code_size);
      98         411 : }
      99             : 
     100     2062800 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
     101             : 
     102      209224 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
     103      209224 :   body_.write_u8(opcode);
     104             :   body_.write_u8(immediate);
     105      209224 : }
     106             : 
     107           0 : void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
     108             :                                        const byte imm2) {
     109           0 :   body_.write_u8(opcode);
     110             :   body_.write_u8(imm1);
     111             :   body_.write_u8(imm2);
     112           0 : }
     113             : 
     114      518707 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
     115      518707 :   body_.write_u8(opcode);
     116             :   body_.write_i32v(immediate);
     117      518707 : }
     118             : 
     119      684064 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
     120      684064 :   body_.write_u8(opcode);
     121      684064 :   body_.write_u32v(immediate);
     122      684064 : }
     123             : 
     124      513023 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
     125      513023 :   EmitWithI32V(kExprI32Const, value);
     126      513023 : }
     127             : 
     128           0 : void WasmFunctionBuilder::EmitI64Const(int64_t value) {
     129           0 :   body_.write_u8(kExprI64Const);
     130             :   body_.write_i64v(value);
     131           0 : }
     132             : 
     133         164 : void WasmFunctionBuilder::EmitF32Const(float value) {
     134         164 :   body_.write_u8(kExprF32Const);
     135             :   body_.write_f32(value);
     136         164 : }
     137             : 
     138       10104 : void WasmFunctionBuilder::EmitF64Const(double value) {
     139       10104 :   body_.write_u8(kExprF64Const);
     140             :   body_.write_f64(value);
     141       10104 : }
     142             : 
     143       26749 : void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
     144             :   DirectCallIndex call;
     145       53498 :   call.offset = body_.size();
     146       26749 :   call.direct_index = index;
     147       26749 :   direct_calls_.push_back(call);
     148       26749 :   byte placeholder_bytes[kMaxVarInt32Size] = {0};
     149             :   EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
     150       26749 : }
     151             : 
     152        8884 : void WasmFunctionBuilder::ExportAs(Vector<const char> name) {
     153             :   exported_names_.push_back(ZoneVector<char>(
     154       26652 :       name.start(), name.start() + name.length(), builder_->zone()));
     155        8884 : }
     156             : 
     157       13224 : void WasmFunctionBuilder::SetName(Vector<const char> name) {
     158       13224 :   name_.resize(name.length());
     159       13224 :   memcpy(name_.data(), name.start(), name.length());
     160       13224 : }
     161             : 
     162       36183 : void WasmFunctionBuilder::AddAsmWasmOffset(int call_position,
     163             :                                            int to_number_position) {
     164             :   // We only want to emit one mapping per byte offset.
     165             :   DCHECK(asm_offsets_.size() == 0 || body_.size() > last_asm_byte_offset_);
     166             : 
     167             :   DCHECK_LE(body_.size(), kMaxUInt32);
     168       72366 :   uint32_t byte_offset = static_cast<uint32_t>(body_.size());
     169       36183 :   asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
     170       36183 :   last_asm_byte_offset_ = byte_offset;
     171             : 
     172             :   DCHECK_GE(call_position, 0);
     173       36183 :   asm_offsets_.write_i32v(call_position - last_asm_source_position_);
     174             : 
     175             :   DCHECK_GE(to_number_position, 0);
     176       36183 :   asm_offsets_.write_i32v(to_number_position - call_position);
     177       36183 :   last_asm_source_position_ = to_number_position;
     178       36183 : }
     179             : 
     180       16738 : void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) {
     181             :   DCHECK_EQ(0, asm_func_start_source_position_);
     182             :   DCHECK_LE(0, position);
     183             :   // Must be called before emitting any asm.js source position.
     184             :   DCHECK_EQ(0, asm_offsets_.size());
     185       16738 :   asm_func_start_source_position_ = position;
     186       16738 :   last_asm_source_position_ = position;
     187       16738 : }
     188             : 
     189       29068 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
     190             :   DCHECK_LE(position, body_.size());
     191       29068 :   body_.Truncate(position);
     192       29068 : }
     193             : 
     194           0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
     195       19942 :   buffer.write_u32v(signature_index_);
     196           0 : }
     197             : 
     198       19942 : void WasmFunctionBuilder::WriteExports(ZoneBuffer& buffer) const {
     199       48741 :   for (auto name : exported_names_) {
     200       17714 :     buffer.write_size(name.size());
     201       17714 :     buffer.write(reinterpret_cast<const byte*>(name.data()), name.size());
     202             :     buffer.write_u8(kExternalFunction);
     203       17714 :     buffer.write_size(func_index_ + builder_->function_imports_.size());
     204             :   }
     205       19942 : }
     206             : 
     207       66593 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
     208       19942 :   size_t locals_size = locals_.Size();
     209       59826 :   buffer.write_size(locals_size + body_.size());
     210       19942 :   buffer.EnsureSpace(locals_size);
     211             :   byte** ptr = buffer.pos_ptr();
     212       19942 :   locals_.Emit(*ptr);
     213       19942 :   (*ptr) += locals_size;  // UGLY: manual bump of position pointer
     214       19942 :   if (body_.size() > 0) {
     215             :     size_t base = buffer.offset();
     216       19942 :     buffer.write(body_.begin(), body_.size());
     217       66593 :     for (DirectCallIndex call : direct_calls_) {
     218             :       buffer.patch_u32v(
     219             :           base + call.offset,
     220             :           call.direct_index +
     221       53418 :               static_cast<uint32_t>(builder_->function_imports_.size()));
     222             :     }
     223             :   }
     224       19942 : }
     225             : 
     226       19533 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
     227       54983 :   if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
     228        3616 :     buffer.write_size(0);
     229       23149 :     return;
     230             :   }
     231       15917 :   size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
     232             :   size_t func_start_size =
     233       15917 :       LEBHelper::sizeof_u32v(asm_func_start_source_position_);
     234       15917 :   buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
     235             :   // Offset of the recorded byte offsets.
     236             :   DCHECK_GE(kMaxUInt32, locals_.Size());
     237       15917 :   buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
     238             :   // Start position of the function.
     239       15917 :   buffer.write_u32v(asm_func_start_source_position_);
     240       15917 :   buffer.write(asm_offsets_.begin(), asm_offsets_.size());
     241             : }
     242             : 
     243      355090 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
     244             :     : zone_(zone),
     245             :       signatures_(zone),
     246             :       function_imports_(zone),
     247             :       global_imports_(zone),
     248             :       functions_(zone),
     249             :       data_segments_(zone),
     250             :       indirect_functions_(zone),
     251             :       globals_(zone),
     252             :       signature_map_(zone),
     253      710180 :       start_function_index_(-1) {}
     254             : 
     255       20795 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
     256       62385 :   functions_.push_back(new (zone_) WasmFunctionBuilder(this));
     257             :   // Add the signature if one was provided here.
     258       35710 :   if (sig) functions_.back()->SetSignature(sig);
     259       20795 :   return functions_.back();
     260             : }
     261             : 
     262           7 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
     263           7 :                                        uint32_t dest) {
     264          14 :   data_segments_.push_back({ZoneVector<byte>(zone()), dest});
     265             :   ZoneVector<byte>& vec = data_segments_.back().data;
     266          35 :   for (uint32_t i = 0; i < size; i++) {
     267          28 :     vec.push_back(data[i]);
     268             :   }
     269           7 : }
     270             : 
     271      307431 : bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
     272      307431 :                                                         FunctionSig* b) const {
     273      118289 :   if (a->return_count() < b->return_count()) return true;
     274      105122 :   if (a->return_count() > b->return_count()) return false;
     275       93885 :   if (a->parameter_count() < b->parameter_count()) return true;
     276       67252 :   if (a->parameter_count() > b->parameter_count()) return false;
     277       19044 :   for (size_t r = 0; r < a->return_count(); r++) {
     278       22487 :     if (a->GetReturn(r) < b->GetReturn(r)) return true;
     279       21379 :     if (a->GetReturn(r) > b->GetReturn(r)) return false;
     280             :   }
     281       70026 :   for (size_t p = 0; p < a->parameter_count(); p++) {
     282       72770 :     if (a->GetParam(p) < b->GetParam(p)) return true;
     283       72147 :     if (a->GetParam(p) > b->GetParam(p)) return false;
     284             :   }
     285             :   return false;
     286             : }
     287             : 
     288       27270 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
     289             :   SignatureMap::iterator pos = signature_map_.find(sig);
     290       27270 :   if (pos != signature_map_.end()) {
     291       17943 :     return pos->second;
     292             :   } else {
     293       18654 :     uint32_t index = static_cast<uint32_t>(signatures_.size());
     294        9327 :     signature_map_[sig] = index;
     295        9327 :     signatures_.push_back(sig);
     296        9327 :     return index;
     297             :   }
     298             : }
     299             : 
     300         240 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
     301         480 :   uint32_t ret = static_cast<uint32_t>(indirect_functions_.size());
     302         240 :   indirect_functions_.resize(indirect_functions_.size() + count);
     303         240 :   return ret;
     304             : }
     305             : 
     306        2989 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
     307             :                                             uint32_t direct) {
     308        5978 :   indirect_functions_[indirect] = direct;
     309        2989 : }
     310             : 
     311        1053 : uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length,
     312             :                                       FunctionSig* sig) {
     313        2106 :   function_imports_.push_back({AddSignature(sig), name, name_length});
     314        1053 :   return static_cast<uint32_t>(function_imports_.size() - 1);
     315             : }
     316             : 
     317         136 : uint32_t WasmModuleBuilder::AddGlobalImport(const char* name, int name_length,
     318             :                                             ValueType type) {
     319             :   global_imports_.push_back(
     320         272 :       {WasmOpcodes::ValueTypeCodeFor(type), name, name_length});
     321         136 :   return static_cast<uint32_t>(global_imports_.size() - 1);
     322             : }
     323             : 
     324        4081 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
     325        4081 :   start_function_index_ = function->func_index();
     326        4081 : }
     327             : 
     328        3141 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
     329             :                                       bool mutability,
     330             :                                       const WasmInitExpr& init) {
     331        6282 :   globals_.push_back({type, exported, mutability, init});
     332        3141 :   return static_cast<uint32_t>(globals_.size() - 1);
     333             : }
     334             : 
     335        4011 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
     336             :   uint32_t exports = 0;
     337             : 
     338             :   // == Emit magic =============================================================
     339             :   TRACE("emit magic\n");
     340             :   buffer.write_u32(kWasmMagic);
     341             :   buffer.write_u32(kWasmVersion);
     342             : 
     343             :   // == Emit signatures ========================================================
     344       12033 :   if (signatures_.size() > 0) {
     345        4011 :     size_t start = EmitSection(kTypeSectionCode, buffer);
     346        4011 :     buffer.write_size(signatures_.size());
     347             : 
     348       42798 :     for (FunctionSig* sig : signatures_) {
     349             :       buffer.write_u8(kWasmFunctionTypeForm);
     350        8694 :       buffer.write_size(sig->parameter_count());
     351       16231 :       for (auto param : sig->parameters()) {
     352        7537 :         buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(param));
     353             :       }
     354        8694 :       buffer.write_size(sig->return_count());
     355       13380 :       for (auto ret : sig->returns()) {
     356        4686 :         buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(ret));
     357             :       }
     358             :     }
     359        4011 :     FixupSection(buffer, start);
     360             :   }
     361             : 
     362             :   // == Emit imports ===========================================================
     363       23295 :   if (global_imports_.size() + function_imports_.size() > 0) {
     364         243 :     size_t start = EmitSection(kImportSectionCode, buffer);
     365         243 :     buffer.write_size(global_imports_.size() + function_imports_.size());
     366         622 :     for (auto import : global_imports_) {
     367         136 :       buffer.write_u32v(0);                   // module name length
     368         136 :       buffer.write_u32v(import.name_length);  // field name length
     369             :       buffer.write(reinterpret_cast<const byte*>(import.name),  // field name
     370         136 :                    import.name_length);
     371             :       buffer.write_u8(kExternalGlobal);
     372             :       buffer.write_u8(import.type_code);
     373             :       buffer.write_u8(0);  // immutable
     374             :     }
     375        1530 :     for (auto import : function_imports_) {
     376        1044 :       buffer.write_u32v(0);                   // module name length
     377        1044 :       buffer.write_u32v(import.name_length);  // field name length
     378             :       buffer.write(reinterpret_cast<const byte*>(import.name),  // field name
     379        1044 :                    import.name_length);
     380             :       buffer.write_u8(kExternalFunction);
     381        1044 :       buffer.write_u32v(import.sig_index);
     382             :     }
     383         243 :     FixupSection(buffer, start);
     384             :   }
     385             : 
     386             :   // == Emit function signatures ===============================================
     387             :   uint32_t num_function_names = 0;
     388       20055 :   if (functions_.size() > 0) {
     389        4011 :     size_t start = EmitSection(kFunctionSectionCode, buffer);
     390        4011 :     buffer.write_size(functions_.size());
     391       27964 :     for (auto function : functions_) {
     392             :       function->WriteSignature(buffer);
     393       39884 :       exports += static_cast<uint32_t>(function->exported_names_.size());
     394       19942 :       if (!function->name_.empty()) ++num_function_names;
     395             :     }
     396        4011 :     FixupSection(buffer, start);
     397             :   }
     398             : 
     399             :   // == emit function table ====================================================
     400       12222 :   if (indirect_functions_.size() > 0) {
     401          63 :     size_t start = EmitSection(kTableSectionCode, buffer);
     402             :     buffer.write_u8(1);  // table count
     403             :     buffer.write_u8(kWasmAnyFunctionTypeForm);
     404             :     buffer.write_u8(kResizableMaximumFlag);
     405          63 :     buffer.write_size(indirect_functions_.size());
     406          63 :     buffer.write_size(indirect_functions_.size());
     407          63 :     FixupSection(buffer, start);
     408             :   }
     409             : 
     410             :   // == emit memory declaration ================================================
     411             :   {
     412        4011 :     size_t start = EmitSection(kMemorySectionCode, buffer);
     413             :     buffer.write_u8(1);  // memory count
     414        4011 :     buffer.write_u32v(kResizableMaximumFlag);
     415        4011 :     buffer.write_u32v(16);  // min memory size
     416        4011 :     buffer.write_u32v(32);  // max memory size
     417        4011 :     FixupSection(buffer, start);
     418             :   }
     419             : 
     420             :   // == Emit globals ===========================================================
     421        8850 :   if (globals_.size() > 0) {
     422         828 :     size_t start = EmitSection(kGlobalSectionCode, buffer);
     423         828 :     buffer.write_size(globals_.size());
     424             : 
     425        4686 :     for (auto global : globals_) {
     426        3030 :       buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(global.type));
     427        3030 :       buffer.write_u8(global.mutability ? 1 : 0);
     428        3030 :       switch (global.init.kind) {
     429             :         case WasmInitExpr::kI32Const:
     430             :           DCHECK_EQ(kWasmI32, global.type);
     431             :           buffer.write_u8(kExprI32Const);
     432        1212 :           buffer.write_i32v(global.init.val.i32_const);
     433             :           break;
     434             :         case WasmInitExpr::kI64Const:
     435             :           DCHECK_EQ(kWasmI64, global.type);
     436             :           buffer.write_u8(kExprI64Const);
     437           0 :           buffer.write_i64v(global.init.val.i64_const);
     438             :           break;
     439             :         case WasmInitExpr::kF32Const:
     440             :           DCHECK_EQ(kWasmF32, global.type);
     441             :           buffer.write_u8(kExprF32Const);
     442          74 :           buffer.write_f32(global.init.val.f32_const);
     443             :           break;
     444             :         case WasmInitExpr::kF64Const:
     445             :           DCHECK_EQ(kWasmF64, global.type);
     446             :           buffer.write_u8(kExprF64Const);
     447         116 :           buffer.write_f64(global.init.val.f64_const);
     448             :           break;
     449             :         case WasmInitExpr::kGlobalIndex:
     450             :           buffer.write_u8(kExprGetGlobal);
     451           0 :           buffer.write_u32v(global.init.val.global_index);
     452           0 :           break;
     453             :         default: {
     454             :           // No initializer, emit a default value.
     455        1628 :           switch (global.type) {
     456             :             case kWasmI32:
     457             :               buffer.write_u8(kExprI32Const);
     458             :               // LEB encoding of 0.
     459             :               buffer.write_u8(0);
     460             :               break;
     461             :             case kWasmI64:
     462             :               buffer.write_u8(kExprI64Const);
     463             :               // LEB encoding of 0.
     464             :               buffer.write_u8(0);
     465             :               break;
     466             :             case kWasmF32:
     467             :               buffer.write_u8(kExprF32Const);
     468             :               buffer.write_f32(0.f);
     469             :               break;
     470             :             case kWasmF64:
     471             :               buffer.write_u8(kExprF64Const);
     472             :               buffer.write_f64(0.);
     473             :               break;
     474             :             default:
     475           0 :               UNREACHABLE();
     476             :           }
     477             :         }
     478             :       }
     479             :       buffer.write_u8(kExprEnd);
     480             :     }
     481         828 :     FixupSection(buffer, start);
     482             :   }
     483             : 
     484             :   // == emit exports ===========================================================
     485        4011 :   if (exports > 0) {
     486        4011 :     size_t start = EmitSection(kExportSectionCode, buffer);
     487        4011 :     buffer.write_u32v(exports);
     488       27964 :     for (auto function : functions_) function->WriteExports(buffer);
     489        4011 :     FixupSection(buffer, start);
     490             :   }
     491             : 
     492             :   // == emit start function index ==============================================
     493        4011 :   if (start_function_index_ >= 0) {
     494        3616 :     size_t start = EmitSection(kStartSectionCode, buffer);
     495        7232 :     buffer.write_size(start_function_index_ + function_imports_.size());
     496        3616 :     FixupSection(buffer, start);
     497             :   }
     498             : 
     499             :   // == emit function table elements ===========================================
     500        4011 :   if (indirect_functions_.size() > 0) {
     501          63 :     size_t start = EmitSection(kElementSectionCode, buffer);
     502             :     buffer.write_u8(1);              // count of entries
     503             :     buffer.write_u8(0);              // table index
     504             :     buffer.write_u8(kExprI32Const);  // offset
     505          63 :     buffer.write_u32v(0);
     506             :     buffer.write_u8(kExprEnd);
     507          63 :     buffer.write_size(indirect_functions_.size());  // element count
     508             : 
     509        3108 :     for (auto index : indirect_functions_) {
     510        5964 :       buffer.write_size(index + function_imports_.size());
     511             :     }
     512             : 
     513          63 :     FixupSection(buffer, start);
     514             :   }
     515             : 
     516             :   // == emit code ==============================================================
     517        4011 :   if (functions_.size() > 0) {
     518        4011 :     size_t start = EmitSection(kCodeSectionCode, buffer);
     519        4011 :     buffer.write_size(functions_.size());
     520       27964 :     for (auto function : functions_) {
     521       19942 :       function->WriteBody(buffer);
     522             :     }
     523        4011 :     FixupSection(buffer, start);
     524             :   }
     525             : 
     526             :   // == emit data segments =====================================================
     527        8029 :   if (data_segments_.size() > 0) {
     528           7 :     size_t start = EmitSection(kDataSectionCode, buffer);
     529           7 :     buffer.write_size(data_segments_.size());
     530             : 
     531          21 :     for (auto segment : data_segments_) {
     532             :       buffer.write_u8(0);              // linear memory segment
     533             :       buffer.write_u8(kExprI32Const);  // initializer expression for dest
     534           7 :       buffer.write_u32v(segment.dest);
     535             :       buffer.write_u8(kExprEnd);
     536          14 :       buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
     537          14 :       buffer.write(&segment.data[0], segment.data.size());
     538             :     }
     539           7 :     FixupSection(buffer, start);
     540             :   }
     541             : 
     542             :   // == Emit names =============================================================
     543        4888 :   if (num_function_names > 0 || !function_imports_.empty()) {
     544             :     // Emit the section code.
     545             :     buffer.write_u8(kUnknownSectionCode);
     546             :     // Emit a placeholder for the length.
     547             :     size_t start = buffer.reserve_u32v();
     548             :     // Emit the section string.
     549        3134 :     buffer.write_size(4);
     550        3134 :     buffer.write(reinterpret_cast<const byte*>("name"), 4);
     551             :     // Emit a subsection for the function names.
     552             :     buffer.write_u8(NameSectionType::kFunction);
     553             :     // Emit a placeholder for the subsection length.
     554             :     size_t functions_start = buffer.reserve_u32v();
     555             :     // Emit the function names.
     556             :     // Imports are always named.
     557        3134 :     uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
     558        3134 :     buffer.write_size(num_imports + num_function_names);
     559             :     uint32_t function_index = 0;
     560        4178 :     for (; function_index < num_imports; ++function_index) {
     561        1044 :       const WasmFunctionImport* import = &function_imports_[function_index];
     562             :       DCHECK_NOT_NULL(import->name);
     563        1044 :       buffer.write_u32v(function_index);
     564        1044 :       uint32_t name_len = static_cast<uint32_t>(import->name_length);
     565        1044 :       buffer.write_u32v(name_len);
     566        1044 :       buffer.write(reinterpret_cast<const byte*>(import->name), name_len);
     567             :     }
     568        3134 :     if (num_function_names > 0) {
     569       24837 :       for (auto function : functions_) {
     570             :         DCHECK_EQ(function_index,
     571             :                   function->func_index() + function_imports_.size());
     572       44269 :         if (!function->name_.empty()) {
     573       12850 :           buffer.write_u32v(function_index);
     574       12850 :           buffer.write_size(function->name_.size());
     575             :           buffer.write(reinterpret_cast<const byte*>(function->name_.data()),
     576       12850 :                        function->name_.size());
     577             :         }
     578       18569 :         ++function_index;
     579             :       }
     580             :     }
     581        3134 :     FixupSection(buffer, functions_start);
     582        3134 :     FixupSection(buffer, start);
     583             :   }
     584        4011 : }
     585             : 
     586        3616 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
     587             :   // == Emit asm.js offset table ===============================================
     588        7232 :   buffer.write_size(functions_.size());
     589             :   // Emit the offset table per function.
     590       26765 :   for (auto function : functions_) {
     591       19533 :     function->WriteAsmWasmOffsetTable(buffer);
     592             :   }
     593             :   // Append a 0 to indicate that this is an encoded table.
     594             :   buffer.write_u8(0);
     595        3616 : }
     596             : }  // namespace wasm
     597             : }  // namespace internal
     598             : }  // namespace v8

Generated by: LCOV version 1.10