LCOV - code coverage report
Current view: top level - src/wasm - wasm-module-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 247 257 96.1 %
Date: 2019-04-19 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/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       17633 : size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
      30             :   // Emit the section code.
      31       17633 :   buffer.write_u8(code);
      32             : 
      33             :   // Emit a placeholder for the length.
      34       17634 :   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       22642 :   buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
      40             :                                                  kPaddedVarInt32Size));
      41             : }
      42             : 
      43             : }  // namespace
      44             : 
      45       15590 : 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       62359 :       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       14557 : void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
      63             :   DCHECK(!locals_.has_sig());
      64             :   locals_.set_sig(sig);
      65       14980 :   signature_index_ = builder_->AddSignature(sig);
      66       14559 : }
      67             : 
      68      545535 : uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
      69             :   DCHECK(locals_.has_sig());
      70      545535 :   return locals_.AddLocals(1, type);
      71             : }
      72             : 
      73      501684 : void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
      74      501684 :   EmitWithU32V(kExprGetLocal, local_index);
      75      501684 : }
      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         423 : void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
      86       33695 :   body_.write(code, code_size);
      87         423 : }
      88             : 
      89    12778174 : void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
      90             : 
      91      151417 : void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
      92      151417 :   body_.write_u8(opcode);
      93             :   body_.write_u8(immediate);
      94      151417 : }
      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     1510123 : void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
     104     1510123 :   body_.write_u8(opcode);
     105             :   body_.write_i32v(immediate);
     106     1510123 : }
     107             : 
     108     1281259 : void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
     109     1281259 :   body_.write_u8(opcode);
     110     1281258 :   body_.write_u32v(immediate);
     111     1281258 : }
     112             : 
     113     1468758 : void WasmFunctionBuilder::EmitI32Const(int32_t value) {
     114     1468758 :   EmitWithI32V(kExprI32Const, value);
     115     1468758 : }
     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       12639 : void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
     142             : 
     143       59286 : 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       59286 :   uint32_t byte_offset = static_cast<uint32_t>(body_.size());
     150       59286 :   asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_);
     151       59286 :   last_asm_byte_offset_ = byte_offset;
     152             : 
     153             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
     154       59286 :   uint32_t call_position_u32 = static_cast<uint32_t>(call_position);
     155       59286 :   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       59286 :   uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position);
     159       59286 :   asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32);
     160       59286 :   last_asm_source_position_ = to_number_position_u32;
     161       59286 : }
     162             : 
     163       12639 : 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       12639 :   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       12639 :   asm_func_start_source_position_ = function_position_u32;
     171       12639 :   last_asm_source_position_ = function_position_u32;
     172       12639 : }
     173             : 
     174           9 : void WasmFunctionBuilder::SetCompilationHint(
     175             :     WasmCompilationHintStrategy strategy, WasmCompilationHintTier baseline,
     176             :     WasmCompilationHintTier top_tier) {
     177             :   uint8_t hint_byte = static_cast<uint8_t>(strategy) |
     178           9 :                       static_cast<uint8_t>(baseline) << 2 |
     179           9 :                       static_cast<uint8_t>(top_tier) << 4;
     180             :   DCHECK_NE(hint_byte, kNoCompilationHint);
     181           9 :   hint_ = hint_byte;
     182           9 : }
     183             : 
     184      392907 : void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
     185             :   DCHECK_LE(position, body_.size());
     186             :   body_.Truncate(position);
     187      392907 : }
     188             : 
     189           0 : void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
     190       14802 :   buffer.write_u32v(signature_index_);
     191           0 : }
     192             : 
     193       14800 : void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
     194       14800 :   size_t locals_size = locals_.Size();
     195       14800 :   buffer.write_size(locals_size + body_.size());
     196       14800 :   buffer.EnsureSpace(locals_size);
     197             :   byte** ptr = buffer.pos_ptr();
     198       14800 :   locals_.Emit(*ptr);
     199       14800 :   (*ptr) += locals_size;  // UGLY: manual bump of position pointer
     200       14800 :   if (body_.size() > 0) {
     201             :     size_t base = buffer.offset();
     202       14800 :     buffer.write(body_.begin(), body_.size());
     203       48028 :     for (DirectCallIndex call : direct_calls_) {
     204       33228 :       buffer.patch_u32v(
     205             :           base + call.offset,
     206             :           call.direct_index +
     207       33228 :               static_cast<uint32_t>(builder_->function_imports_.size()));
     208             :     }
     209             :   }
     210       14800 : }
     211             : 
     212       14377 : void WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const {
     213       16872 :   if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) {
     214        2495 :     buffer.write_size(0);
     215        2495 :     return;
     216             :   }
     217       11882 :   size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size());
     218             :   size_t func_start_size =
     219       11882 :       LEBHelper::sizeof_u32v(asm_func_start_source_position_);
     220       11882 :   buffer.write_size(asm_offsets_.size() + locals_enc_size + func_start_size);
     221             :   // Offset of the recorded byte offsets.
     222             :   DCHECK_GE(kMaxUInt32, locals_.Size());
     223       11882 :   buffer.write_u32v(static_cast<uint32_t>(locals_.Size()));
     224             :   // Start position of the function.
     225       11881 :   buffer.write_u32v(asm_func_start_source_position_);
     226       11880 :   buffer.write(asm_offsets_.begin(), asm_offsets_.size());
     227             : }
     228             : 
     229        4078 : WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
     230             :     : zone_(zone),
     231             :       signatures_(zone),
     232             :       function_imports_(zone),
     233             :       function_exports_(zone),
     234             :       global_imports_(zone),
     235             :       functions_(zone),
     236             :       data_segments_(zone),
     237             :       indirect_functions_(zone),
     238             :       globals_(zone),
     239             :       signature_map_(zone),
     240             :       start_function_index_(-1),
     241             :       min_memory_size_(16),
     242             :       max_memory_size_(0),
     243             :       has_max_memory_size_(false),
     244        8157 :       has_shared_memory_(false) {}
     245             : 
     246       15590 : WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) {
     247       46771 :   functions_.push_back(new (zone_) WasmFunctionBuilder(this));
     248             :   // Add the signature if one was provided here.
     249       16013 :   if (sig) functions_.back()->SetSignature(sig);
     250       15590 :   return functions_.back();
     251             : }
     252             : 
     253           4 : void WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size,
     254             :                                        uint32_t dest) {
     255           8 :   data_segments_.push_back({ZoneVector<byte>(zone()), dest});
     256             :   ZoneVector<byte>& vec = data_segments_.back().data;
     257          36 :   for (uint32_t i = 0; i < size; i++) {
     258          16 :     vec.push_back(data[i]);
     259             :   }
     260           4 : }
     261             : 
     262       64418 : uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
     263       64418 :   auto sig_entry = signature_map_.find(*sig);
     264       64420 :   if (sig_entry != signature_map_.end()) return sig_entry->second;
     265        6669 :   uint32_t index = static_cast<uint32_t>(signatures_.size());
     266        6669 :   signature_map_.emplace(*sig, index);
     267        6670 :   signatures_.push_back(sig);
     268        6669 :   return index;
     269             : }
     270             : 
     271         219 : uint32_t WasmModuleBuilder::AllocateIndirectFunctions(uint32_t count) {
     272         219 :   uint32_t index = static_cast<uint32_t>(indirect_functions_.size());
     273             :   DCHECK_GE(FLAG_wasm_max_table_size, index);
     274         219 :   if (count > FLAG_wasm_max_table_size - index) {
     275             :     return std::numeric_limits<uint32_t>::max();
     276             :   }
     277         209 :   indirect_functions_.resize(indirect_functions_.size() + count);
     278         209 :   return index;
     279             : }
     280             : 
     281        4189 : void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
     282             :                                             uint32_t direct) {
     283        8378 :   indirect_functions_[indirect] = direct;
     284        4189 : }
     285             : 
     286        2076 : uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
     287             :                                       FunctionSig* sig) {
     288        4152 :   function_imports_.push_back({name, AddSignature(sig)});
     289        2076 :   return static_cast<uint32_t>(function_imports_.size() - 1);
     290             : }
     291             : 
     292         469 : uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
     293             :                                             ValueType type) {
     294         938 :   global_imports_.push_back({name, ValueTypes::ValueTypeCodeFor(type)});
     295         469 :   return static_cast<uint32_t>(global_imports_.size() - 1);
     296             : }
     297             : 
     298        2494 : void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
     299        2494 :   start_function_index_ = function->func_index();
     300        2494 : }
     301             : 
     302        4655 : void WasmModuleBuilder::AddExport(Vector<const char> name,
     303             :                                   WasmFunctionBuilder* function) {
     304        9309 :   function_exports_.push_back({name, function->func_index()});
     305        4654 : }
     306             : 
     307        2956 : uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
     308             :                                       bool mutability,
     309             :                                       const WasmInitExpr& init) {
     310        5912 :   globals_.push_back({type, exported, mutability, init});
     311        2956 :   return static_cast<uint32_t>(globals_.size() - 1);
     312             : }
     313             : 
     314        3755 : void WasmModuleBuilder::SetMinMemorySize(uint32_t value) {
     315        3755 :   min_memory_size_ = value;
     316        3755 : }
     317             : 
     318           6 : void WasmModuleBuilder::SetMaxMemorySize(uint32_t value) {
     319           6 :   has_max_memory_size_ = true;
     320           6 :   max_memory_size_ = value;
     321           6 : }
     322             : 
     323           4 : void WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; }
     324             : 
     325        2817 : void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
     326             :   // == Emit magic =============================================================
     327        2817 :   buffer.write_u32(kWasmMagic);
     328        2818 :   buffer.write_u32(kWasmVersion);
     329             : 
     330             :   // == Emit signatures ========================================================
     331        2818 :   if (signatures_.size() > 0) {
     332        2813 :     size_t start = EmitSection(kTypeSectionCode, buffer);
     333        2814 :     buffer.write_size(signatures_.size());
     334             : 
     335        9228 :     for (FunctionSig* sig : signatures_) {
     336             :       buffer.write_u8(kWasmFunctionTypeCode);
     337        6415 :       buffer.write_size(sig->parameter_count());
     338       18249 :       for (auto param : sig->parameters()) {
     339        5918 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(param));
     340             :       }
     341        6414 :       buffer.write_size(sig->return_count());
     342       13391 :       for (auto ret : sig->returns()) {
     343        3489 :         buffer.write_u8(ValueTypes::ValueTypeCodeFor(ret));
     344             :       }
     345             :     }
     346             :     FixupSection(buffer, start);
     347             :   }
     348             : 
     349             :   // == Emit imports ===========================================================
     350        2819 :   if (global_imports_.size() + function_imports_.size() > 0) {
     351         234 :     size_t start = EmitSection(kImportSectionCode, buffer);
     352         234 :     buffer.write_size(global_imports_.size() + function_imports_.size());
     353         703 :     for (auto import : global_imports_) {
     354         469 :       buffer.write_u32v(0);              // module name (length)
     355             :       buffer.write_string(import.name);  // field name
     356             :       buffer.write_u8(kExternalGlobal);
     357             :       buffer.write_u8(import.type_code);
     358             :       buffer.write_u8(0);  // immutable
     359             :     }
     360        2274 :     for (auto import : function_imports_) {
     361        2040 :       buffer.write_u32v(0);              // module name (length)
     362             :       buffer.write_string(import.name);  // field name
     363             :       buffer.write_u8(kExternalFunction);
     364        2040 :       buffer.write_u32v(import.sig_index);
     365             :     }
     366             :     FixupSection(buffer, start);
     367             :   }
     368             : 
     369             :   // == Emit function signatures ===============================================
     370             :   uint32_t num_function_names = 0;
     371        2819 :   if (functions_.size() > 0) {
     372        2813 :     size_t start = EmitSection(kFunctionSectionCode, buffer);
     373        2814 :     buffer.write_size(functions_.size());
     374       17616 :     for (auto* function : functions_) {
     375             :       function->WriteSignature(buffer);
     376       14802 :       if (!function->name_.empty()) ++num_function_names;
     377             :     }
     378             :     FixupSection(buffer, start);
     379             :   }
     380             : 
     381             :   // == emit function table ====================================================
     382        2820 :   if (indirect_functions_.size() > 0) {
     383          45 :     size_t start = EmitSection(kTableSectionCode, buffer);
     384             :     buffer.write_u8(1);  // table count
     385             :     buffer.write_u8(kLocalAnyFunc);
     386             :     buffer.write_u8(kHasMaximumFlag);
     387          45 :     buffer.write_size(indirect_functions_.size());
     388          45 :     buffer.write_size(indirect_functions_.size());
     389             :     FixupSection(buffer, start);
     390             :   }
     391             : 
     392             :   // == emit memory declaration ================================================
     393             :   {
     394        2820 :     size_t start = EmitSection(kMemorySectionCode, buffer);
     395             :     buffer.write_u8(1);  // memory count
     396        2817 :     if (has_shared_memory_) {
     397           4 :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kSharedAndMaximum
     398             :                                            : MemoryFlags::kSharedNoMaximum);
     399             :     } else {
     400        2813 :       buffer.write_u8(has_max_memory_size_ ? MemoryFlags::kMaximum
     401             :                                            : MemoryFlags::kNoMaximum);
     402             :     }
     403        2817 :     buffer.write_u32v(min_memory_size_);
     404        2818 :     if (has_max_memory_size_) {
     405           6 :       buffer.write_u32v(max_memory_size_);
     406             :     }
     407             :     FixupSection(buffer, start);
     408             :   }
     409             : 
     410             :   // == Emit globals ===========================================================
     411        2818 :   if (globals_.size() > 0) {
     412         791 :     size_t start = EmitSection(kGlobalSectionCode, buffer);
     413         791 :     buffer.write_size(globals_.size());
     414             : 
     415        3561 :     for (auto global : globals_) {
     416        2770 :       buffer.write_u8(ValueTypes::ValueTypeCodeFor(global.type));
     417        2770 :       buffer.write_u8(global.mutability ? 1 : 0);
     418        2770 :       switch (global.init.kind) {
     419             :         case WasmInitExpr::kI32Const:
     420             :           DCHECK_EQ(kWasmI32, global.type);
     421             :           buffer.write_u8(kExprI32Const);
     422        1947 :           buffer.write_i32v(global.init.val.i32_const);
     423             :           break;
     424             :         case WasmInitExpr::kI64Const:
     425             :           DCHECK_EQ(kWasmI64, global.type);
     426             :           buffer.write_u8(kExprI64Const);
     427           0 :           buffer.write_i64v(global.init.val.i64_const);
     428             :           break;
     429             :         case WasmInitExpr::kF32Const:
     430             :           DCHECK_EQ(kWasmF32, global.type);
     431             :           buffer.write_u8(kExprF32Const);
     432          60 :           buffer.write_f32(global.init.val.f32_const);
     433             :           break;
     434             :         case WasmInitExpr::kF64Const:
     435             :           DCHECK_EQ(kWasmF64, global.type);
     436             :           buffer.write_u8(kExprF64Const);
     437         274 :           buffer.write_f64(global.init.val.f64_const);
     438             :           break;
     439             :         case WasmInitExpr::kGlobalIndex:
     440             :           buffer.write_u8(kExprGetGlobal);
     441          12 :           buffer.write_u32v(global.init.val.global_index);
     442          12 :           break;
     443             :         default: {
     444             :           // No initializer, emit a default value.
     445         477 :           switch (global.type) {
     446             :             case kWasmI32:
     447             :               buffer.write_u8(kExprI32Const);
     448             :               // LEB encoding of 0.
     449             :               buffer.write_u8(0);
     450             :               break;
     451             :             case kWasmI64:
     452             :               buffer.write_u8(kExprI64Const);
     453             :               // LEB encoding of 0.
     454             :               buffer.write_u8(0);
     455             :               break;
     456             :             case kWasmF32:
     457             :               buffer.write_u8(kExprF32Const);
     458             :               buffer.write_f32(0.f);
     459             :               break;
     460             :             case kWasmF64:
     461             :               buffer.write_u8(kExprF64Const);
     462             :               buffer.write_f64(0.);
     463             :               break;
     464             :             default:
     465           0 :               UNREACHABLE();
     466             :           }
     467             :         }
     468             :       }
     469             :       buffer.write_u8(kExprEnd);
     470             :     }
     471             :     FixupSection(buffer, start);
     472             :   }
     473             : 
     474             :   // == emit exports ===========================================================
     475        2818 :   if (!function_exports_.empty()) {
     476        2762 :     size_t start = EmitSection(kExportSectionCode, buffer);
     477        2762 :     buffer.write_size(function_exports_.size());
     478        7353 :     for (auto function_export : function_exports_) {
     479             :       buffer.write_string(function_export.name);
     480             :       buffer.write_u8(kExternalFunction);
     481        9182 :       buffer.write_size(function_export.function_index +
     482        4591 :                         function_imports_.size());
     483             :     }
     484             :     FixupSection(buffer, start);
     485             :   }
     486             : 
     487             :   // == emit start function index ==============================================
     488        2818 :   if (start_function_index_ >= 0) {
     489        2495 :     size_t start = EmitSection(kStartSectionCode, buffer);
     490        4988 :     buffer.write_size(start_function_index_ + function_imports_.size());
     491             :     FixupSection(buffer, start);
     492             :   }
     493             : 
     494             :   // == emit function table elements ===========================================
     495        2817 :   if (indirect_functions_.size() > 0) {
     496          45 :     size_t start = EmitSection(kElementSectionCode, buffer);
     497             :     buffer.write_u8(1);              // count of entries
     498             :     buffer.write_u8(0);              // table index
     499             :     buffer.write_u8(kExprI32Const);  // offset
     500          45 :     buffer.write_u32v(0);
     501             :     buffer.write_u8(kExprEnd);
     502          45 :     buffer.write_size(indirect_functions_.size());  // element count
     503             : 
     504        4230 :     for (auto index : indirect_functions_) {
     505        8370 :       buffer.write_size(index + function_imports_.size());
     506             :     }
     507             : 
     508             :     FixupSection(buffer, start);
     509             :   }
     510             : 
     511             :   // == emit compilation hints section =========================================
     512             :   bool emit_compilation_hints = false;
     513       17608 :   for (auto* fn : functions_) {
     514       14801 :     if (fn->hint_ != kNoCompilationHint) {
     515             :       emit_compilation_hints = true;
     516             :       break;
     517             :     }
     518             :   }
     519        2817 :   if (emit_compilation_hints) {
     520             :     // Emit the section code.
     521             :     buffer.write_u8(kUnknownSectionCode);
     522             :     // Emit a placeholder for section length.
     523             :     size_t start = buffer.reserve_u32v();
     524             :     // Emit custom section name.
     525             :     buffer.write_string(CStrVector("compilationHints"));
     526             :     // Emit hint count.
     527           9 :     buffer.write_size(functions_.size());
     528             :     // Emit hint bytes.
     529          18 :     for (auto* fn : functions_) {
     530             :       uint8_t hint_byte =
     531           9 :           fn->hint_ != kNoCompilationHint ? fn->hint_ : kDefaultCompilationHint;
     532             :       buffer.write_u8(hint_byte);
     533             :     }
     534             :     FixupSection(buffer, start);
     535             :   }
     536             : 
     537             :   // == emit code ==============================================================
     538        2817 :   if (functions_.size() > 0) {
     539        2813 :     size_t start = EmitSection(kCodeSectionCode, buffer);
     540        2814 :     buffer.write_size(functions_.size());
     541       17614 :     for (auto* function : functions_) {
     542       14800 :       function->WriteBody(buffer);
     543             :     }
     544             :     FixupSection(buffer, start);
     545             :   }
     546             : 
     547             :   // == emit data segments =====================================================
     548        2818 :   if (data_segments_.size() > 0) {
     549           4 :     size_t start = EmitSection(kDataSectionCode, buffer);
     550           4 :     buffer.write_size(data_segments_.size());
     551             : 
     552           8 :     for (auto segment : data_segments_) {
     553             :       buffer.write_u8(0);              // linear memory segment
     554             :       buffer.write_u8(kExprI32Const);  // initializer expression for dest
     555           4 :       buffer.write_u32v(segment.dest);
     556             :       buffer.write_u8(kExprEnd);
     557           4 :       buffer.write_u32v(static_cast<uint32_t>(segment.data.size()));
     558           4 :       buffer.write(&segment.data[0], segment.data.size());
     559             :     }
     560             :     FixupSection(buffer, start);
     561             :   }
     562             : 
     563             :   // == Emit names =============================================================
     564        2818 :   if (num_function_names > 0 || !function_imports_.empty()) {
     565             :     // Emit the section code.
     566             :     buffer.write_u8(kUnknownSectionCode);
     567             :     // Emit a placeholder for the length.
     568             :     size_t start = buffer.reserve_u32v();
     569             :     // Emit the section string.
     570             :     buffer.write_string(CStrVector("name"));
     571             :     // Emit a subsection for the function names.
     572             :     buffer.write_u8(NameSectionKindCode::kFunction);
     573             :     // Emit a placeholder for the subsection length.
     574             :     size_t functions_start = buffer.reserve_u32v();
     575             :     // Emit the function names.
     576             :     // Imports are always named.
     577        2499 :     uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
     578        2499 :     buffer.write_size(num_imports + num_function_names);
     579             :     uint32_t function_index = 0;
     580        6579 :     for (; function_index < num_imports; ++function_index) {
     581        2040 :       const WasmFunctionImport* import = &function_imports_[function_index];
     582             :       DCHECK(!import->name.empty());
     583        2040 :       buffer.write_u32v(function_index);
     584             :       buffer.write_string(import->name);
     585             :     }
     586        2499 :     if (num_function_names > 0) {
     587       16869 :       for (auto* function : functions_) {
     588             :         DCHECK_EQ(function_index,
     589             :                   function->func_index() + function_imports_.size());
     590       14375 :         if (!function->name_.empty()) {
     591       11881 :           buffer.write_u32v(function_index);
     592             :           buffer.write_string(function->name_);
     593             :         }
     594       14375 :         ++function_index;
     595             :       }
     596             :     }
     597             :     FixupSection(buffer, functions_start);
     598             :     FixupSection(buffer, start);
     599             :   }
     600        2818 : }
     601             : 
     602        2494 : void WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer& buffer) const {
     603             :   // == Emit asm.js offset table ===============================================
     604        2494 :   buffer.write_size(functions_.size());
     605             :   // Emit the offset table per function.
     606       16870 :   for (auto* function : functions_) {
     607       14375 :     function->WriteAsmWasmOffsetTable(buffer);
     608             :   }
     609             :   // Append a 0 to indicate that this is an encoded table.
     610             :   buffer.write_u8(0);
     611        2495 : }
     612             : }  // namespace wasm
     613             : }  // namespace internal
     614      122036 : }  // namespace v8

Generated by: LCOV version 1.10