LCOV - code coverage report
Current view: top level - src/wasm - wasm-serialization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 170 203 83.7 %
Date: 2019-02-19 Functions: 24 28 85.7 %

          Line data    Source code
       1             : // Copyright 2017 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/wasm/wasm-serialization.h"
       6             : 
       7             : #include "src/assembler-inl.h"
       8             : #include "src/external-reference-table.h"
       9             : #include "src/objects-inl.h"
      10             : #include "src/objects.h"
      11             : #include "src/ostreams.h"
      12             : #include "src/snapshot/code-serializer.h"
      13             : #include "src/snapshot/serializer-common.h"
      14             : #include "src/utils.h"
      15             : #include "src/version.h"
      16             : #include "src/wasm/function-compiler.h"
      17             : #include "src/wasm/module-compiler.h"
      18             : #include "src/wasm/module-decoder.h"
      19             : #include "src/wasm/wasm-code-manager.h"
      20             : #include "src/wasm/wasm-module.h"
      21             : #include "src/wasm/wasm-objects-inl.h"
      22             : #include "src/wasm/wasm-objects.h"
      23             : #include "src/wasm/wasm-result.h"
      24             : 
      25             : namespace v8 {
      26             : namespace internal {
      27             : namespace wasm {
      28             : 
      29             : namespace {
      30             : 
      31             : // TODO(bbudge) Try to unify the various implementations of readers and writers
      32             : // in WASM, e.g. StreamProcessor and ZoneBuffer, with these.
      33             : class Writer {
      34             :  public:
      35             :   explicit Writer(Vector<byte> buffer)
      36         594 :       : start_(buffer.start()), end_(buffer.end()), pos_(buffer.start()) {}
      37             : 
      38             :   size_t bytes_written() const { return pos_ - start_; }
      39             :   byte* current_location() const { return pos_; }
      40             :   size_t current_size() const { return end_ - pos_; }
      41         257 :   Vector<byte> current_buffer() const {
      42             :     return {current_location(), current_size()};
      43             :   }
      44             : 
      45             :   template <typename T>
      46       11270 :   void Write(const T& value) {
      47             :     DCHECK_GE(current_size(), sizeof(T));
      48        5635 :     WriteUnalignedValue(reinterpret_cast<Address>(current_location()), value);
      49        5635 :     pos_ += sizeof(T);
      50        5635 :     if (FLAG_trace_wasm_serialization) {
      51           0 :       StdoutStream{} << "wrote: " << static_cast<size_t>(value)
      52           0 :                      << " sized: " << sizeof(T) << std::endl;
      53             :     }
      54        5635 :   }
      55             : 
      56        1093 :   void WriteVector(const Vector<const byte> v) {
      57             :     DCHECK_GE(current_size(), v.size());
      58         771 :     if (v.size() > 0) {
      59         322 :       memcpy(current_location(), v.start(), v.size());
      60         322 :       pos_ += v.size();
      61             :     }
      62         771 :     if (FLAG_trace_wasm_serialization) {
      63           0 :       StdoutStream{} << "wrote vector of " << v.size() << " elements"
      64             :                      << std::endl;
      65             :     }
      66         771 :   }
      67             : 
      68         257 :   void Skip(size_t size) { pos_ += size; }
      69             : 
      70             :  private:
      71             :   byte* const start_;
      72             :   byte* const end_;
      73             :   byte* pos_;
      74             : };
      75             : 
      76             : class Reader {
      77             :  public:
      78             :   explicit Reader(Vector<const byte> buffer)
      79         360 :       : start_(buffer.start()), end_(buffer.end()), pos_(buffer.start()) {}
      80             : 
      81             :   size_t bytes_read() const { return pos_ - start_; }
      82             :   const byte* current_location() const { return pos_; }
      83         180 :   size_t current_size() const { return end_ - pos_; }
      84             :   Vector<const byte> current_buffer() const {
      85             :     return {current_location(), current_size()};
      86             :   }
      87             : 
      88             :   template <typename T>
      89        3644 :   T Read() {
      90             :     DCHECK_GE(current_size(), sizeof(T));
      91             :     T value =
      92             :         ReadUnalignedValue<T>(reinterpret_cast<Address>(current_location()));
      93        3644 :     pos_ += sizeof(T);
      94        3644 :     if (FLAG_trace_wasm_serialization) {
      95           0 :       StdoutStream{} << "read: " << static_cast<size_t>(value)
      96           0 :                      << " sized: " << sizeof(T) << std::endl;
      97             :     }
      98        3644 :     return value;
      99             :   }
     100             : 
     101         972 :   void ReadVector(Vector<byte> v) {
     102         684 :     if (v.size() > 0) {
     103             :       DCHECK_GE(current_size(), v.size());
     104         288 :       memcpy(v.start(), current_location(), v.size());
     105         288 :       pos_ += v.size();
     106             :     }
     107         684 :     if (FLAG_trace_wasm_serialization) {
     108           0 :       StdoutStream{} << "read vector of " << v.size() << " elements"
     109             :                      << std::endl;
     110             :     }
     111         684 :   }
     112             : 
     113         228 :   void Skip(size_t size) { pos_ += size; }
     114             : 
     115             :  private:
     116             :   const byte* const start_;
     117             :   const byte* const end_;
     118             :   const byte* pos_;
     119             : };
     120             : 
     121             : constexpr size_t kVersionSize = 4 * sizeof(uint32_t);
     122             : 
     123         393 : void WriteVersion(Writer* writer) {
     124         393 :   writer->Write(SerializedData::kMagicNumber);
     125         393 :   writer->Write(Version::Hash());
     126         393 :   writer->Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
     127         393 :   writer->Write(FlagList::Hash());
     128         393 : }
     129             : 
     130             : // On Intel, call sites are encoded as a displacement. For linking and for
     131             : // serialization/deserialization, we want to store/retrieve a tag (the function
     132             : // index). On Intel, that means accessing the raw displacement.
     133             : // On ARM64, call sites are encoded as either a literal load or a direct branch.
     134             : // Other platforms simply require accessing the target address.
     135         257 : void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
     136             : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
     137             :   DCHECK(rinfo->HasTargetAddressAddress());
     138             :   WriteUnalignedValue(rinfo->target_address_address(), tag);
     139             : #elif V8_TARGET_ARCH_ARM64
     140             :   Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
     141             :   if (instr->IsLdrLiteralX()) {
     142             :     WriteUnalignedValue(rinfo->constant_pool_entry_address(),
     143             :                         static_cast<Address>(tag));
     144             :   } else {
     145             :     DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
     146             :     instr->SetBranchImmTarget(
     147             :         reinterpret_cast<Instruction*>(rinfo->pc() + tag * kInstrSize));
     148             :   }
     149             : #else
     150             :   Address addr = static_cast<Address>(tag);
     151             :   if (rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE) {
     152             :     rinfo->set_target_external_reference(addr, SKIP_ICACHE_FLUSH);
     153             :   } else if (rinfo->rmode() == RelocInfo::WASM_STUB_CALL) {
     154             :     rinfo->set_wasm_stub_call_address(addr, SKIP_ICACHE_FLUSH);
     155             :   } else {
     156             :     rinfo->set_target_address(addr, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     157             :   }
     158             : #endif
     159             : }
     160             : 
     161         240 : uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
     162             : #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
     163             :   return ReadUnalignedValue<uint32_t>(rinfo->target_address_address());
     164             : #elif V8_TARGET_ARCH_ARM64
     165             :   Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
     166             :   if (instr->IsLdrLiteralX()) {
     167             :     return ReadUnalignedValue<uint32_t>(rinfo->constant_pool_entry_address());
     168             :   } else {
     169             :     DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
     170             :     return static_cast<uint32_t>(instr->ImmPCOffset() / kInstrSize);
     171             :   }
     172             : #else
     173             :   Address addr;
     174             :   if (rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE) {
     175             :     addr = rinfo->target_external_reference();
     176             :   } else if (rinfo->rmode() == RelocInfo::WASM_STUB_CALL) {
     177             :     addr = rinfo->wasm_stub_call_address();
     178             :   } else {
     179             :     addr = rinfo->target_address();
     180             :   }
     181             :   return static_cast<uint32_t>(addr);
     182             : #endif
     183             : }
     184             : 
     185             : constexpr size_t kHeaderSize =
     186             :     sizeof(uint32_t) +  // total wasm function count
     187             :     sizeof(uint32_t);   // imported functions (index of first wasm function)
     188             : 
     189             : constexpr size_t kCodeHeaderSize =
     190             :     sizeof(size_t) +         // size of code section
     191             :     sizeof(size_t) +         // offset of constant pool
     192             :     sizeof(size_t) +         // offset of safepoint table
     193             :     sizeof(size_t) +         // offset of handler table
     194             :     sizeof(size_t) +         // offset of code comments
     195             :     sizeof(size_t) +         // unpadded binary size
     196             :     sizeof(uint32_t) +       // stack slots
     197             :     sizeof(uint32_t) +       // tagged parameter slots
     198             :     sizeof(size_t) +         // code size
     199             :     sizeof(size_t) +         // reloc size
     200             :     sizeof(size_t) +         // source positions size
     201             :     sizeof(size_t) +         // protected instructions size
     202             :     sizeof(WasmCode::Tier);  // tier
     203             : 
     204             : // A List of all isolate-independent external references. This is used to create
     205             : // a tag from the Address of an external reference and vice versa.
     206             : class ExternalReferenceList {
     207             :  public:
     208             :   uint32_t tag_from_address(Address ext_ref_address) const {
     209             :     auto tag_addr_less_than = [this](uint32_t tag, Address searched_addr) {
     210           0 :       return external_reference_by_tag_[tag] < searched_addr;
     211             :     };
     212             :     auto it = std::lower_bound(std::begin(tags_ordered_by_address_),
     213             :                                std::end(tags_ordered_by_address_),
     214           0 :                                ext_ref_address, tag_addr_less_than);
     215             :     DCHECK_NE(std::end(tags_ordered_by_address_), it);
     216           0 :     uint32_t tag = *it;
     217             :     DCHECK_EQ(address_from_tag(tag), ext_ref_address);
     218             :     return tag;
     219             :   }
     220             : 
     221             :   Address address_from_tag(uint32_t tag) const {
     222             :     DCHECK_GT(kNumExternalReferences, tag);
     223           0 :     return external_reference_by_tag_[tag];
     224             :   }
     225             : 
     226           0 :   static const ExternalReferenceList& Get() {
     227           0 :     static ExternalReferenceList list;  // Lazily initialized.
     228           0 :     return list;
     229             :   }
     230             : 
     231             :  private:
     232             :   // Private constructor. There will only be a single instance of this object.
     233           0 :   ExternalReferenceList() {
     234           0 :     for (uint32_t i = 0; i < kNumExternalReferences; ++i) {
     235           0 :       tags_ordered_by_address_[i] = i;
     236             :     }
     237             :     auto addr_by_tag_less_than = [this](uint32_t a, uint32_t b) {
     238           0 :       return external_reference_by_tag_[a] < external_reference_by_tag_[b];
     239           0 :     };
     240             :     std::sort(std::begin(tags_ordered_by_address_),
     241           0 :               std::end(tags_ordered_by_address_), addr_by_tag_less_than);
     242           0 :   }
     243             : 
     244             : #define COUNT_EXTERNAL_REFERENCE(name, desc) +1
     245             :   static constexpr uint32_t kNumExternalReferences =
     246             :       EXTERNAL_REFERENCE_LIST(COUNT_EXTERNAL_REFERENCE);
     247             : #undef COUNT_EXTERNAL_REFERENCE
     248             : 
     249             : #define EXT_REF_ADDR(name, desc) ExternalReference::name().address(),
     250             :   Address external_reference_by_tag_[kNumExternalReferences] = {
     251           0 :       EXTERNAL_REFERENCE_LIST(EXT_REF_ADDR)};
     252             : #undef EXT_REF_ADDR
     253             :   uint32_t tags_ordered_by_address_[kNumExternalReferences];
     254             :   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceList);
     255             : };
     256             : 
     257             : static_assert(std::is_trivially_destructible<ExternalReferenceList>::value,
     258             :               "static destructors not allowed");
     259             : 
     260             : }  // namespace
     261             : 
     262             : class V8_EXPORT_PRIVATE NativeModuleSerializer {
     263             :  public:
     264             :   NativeModuleSerializer() = delete;
     265             :   NativeModuleSerializer(const NativeModule*, Vector<WasmCode* const>);
     266             : 
     267             :   size_t Measure() const;
     268             :   bool Write(Writer* writer);
     269             : 
     270             :  private:
     271             :   size_t MeasureCode(const WasmCode*) const;
     272             :   void WriteHeader(Writer* writer);
     273             :   void WriteCode(const WasmCode*, Writer* writer);
     274             : 
     275             :   const NativeModule* const native_module_;
     276             :   Vector<WasmCode* const> code_table_;
     277             :   bool write_called_;
     278             : 
     279             :   // Reverse lookup tables for embedded addresses.
     280             :   std::map<Address, uint32_t> wasm_stub_targets_lookup_;
     281             : 
     282             :   DISALLOW_COPY_AND_ASSIGN(NativeModuleSerializer);
     283             : };
     284             : 
     285         402 : NativeModuleSerializer::NativeModuleSerializer(
     286             :     const NativeModule* module, Vector<WasmCode* const> code_table)
     287         402 :     : native_module_(module), code_table_(code_table), write_called_(false) {
     288             :   DCHECK_NOT_NULL(native_module_);
     289             :   // TODO(mtrofin): persist the export wrappers. Ideally, we'd only persist
     290             :   // the unique ones, i.e. the cache.
     291       10452 :   for (uint32_t i = 0; i < WasmCode::kRuntimeStubCount; ++i) {
     292             :     Address addr = native_module_->runtime_stub_entry(
     293       10050 :         static_cast<WasmCode::RuntimeStubId>(i));
     294       20100 :     wasm_stub_targets_lookup_.insert(std::make_pair(addr, i));
     295             :   }
     296         402 : }
     297             : 
     298           0 : size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
     299        1411 :   if (code == nullptr) return sizeof(size_t);
     300             :   DCHECK_EQ(WasmCode::kFunction, code->kind());
     301             :   return kCodeHeaderSize + code->instructions().size() +
     302        2313 :          code->reloc_info().size() + code->source_positions().size() +
     303         771 :          code->protected_instructions().size() *
     304         771 :              sizeof(trap_handler::ProtectedInstructionData);
     305             : }
     306             : 
     307         402 : size_t NativeModuleSerializer::Measure() const {
     308             :   size_t size = kHeaderSize;
     309        1958 :   for (WasmCode* code : code_table_) {
     310        1154 :     size += MeasureCode(code);
     311             :   }
     312         402 :   return size;
     313             : }
     314             : 
     315         201 : void NativeModuleSerializer::WriteHeader(Writer* writer) {
     316             :   // TODO(eholk): We need to properly preserve the flag whether the trap
     317             :   // handler was used or not when serializing.
     318             : 
     319         402 :   writer->Write(native_module_->num_functions());
     320         402 :   writer->Write(native_module_->num_imported_functions());
     321         201 : }
     322             : 
     323        2890 : void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
     324         577 :   if (code == nullptr) {
     325         320 :     writer->Write(size_t{0});
     326         897 :     return;
     327             :   }
     328             :   DCHECK_EQ(WasmCode::kFunction, code->kind());
     329             :   // Write the size of the entire code section, followed by the code header.
     330         257 :   writer->Write(MeasureCode(code));
     331         257 :   writer->Write(code->constant_pool_offset());
     332         257 :   writer->Write(code->safepoint_table_offset());
     333         257 :   writer->Write(code->handler_table_offset());
     334         257 :   writer->Write(code->code_comments_offset());
     335         257 :   writer->Write(code->unpadded_binary_size());
     336         257 :   writer->Write(code->stack_slots());
     337         257 :   writer->Write(code->tagged_parameter_slots());
     338         257 :   writer->Write(code->instructions().size());
     339         257 :   writer->Write(code->reloc_info().size());
     340         257 :   writer->Write(code->source_positions().size());
     341         257 :   writer->Write(code->protected_instructions().size());
     342         257 :   writer->Write(code->tier());
     343             : 
     344             :   // Get a pointer to the destination buffer, to hold relocated code.
     345             :   byte* serialized_code_start = writer->current_buffer().start();
     346             :   byte* code_start = serialized_code_start;
     347             :   size_t code_size = code->instructions().size();
     348             :   writer->Skip(code_size);
     349             :   // Write the reloc info, source positions, and protected code.
     350         257 :   writer->WriteVector(code->reloc_info());
     351         257 :   writer->WriteVector(code->source_positions());
     352         257 :   writer->WriteVector(Vector<byte>::cast(code->protected_instructions()));
     353             : #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM || \
     354             :     V8_TARGET_ARCH_PPC
     355             :   // On platforms that don't support misaligned word stores, copy to an aligned
     356             :   // buffer if necessary so we can relocate the serialized code.
     357             :   std::unique_ptr<byte[]> aligned_buffer;
     358             :   if (!IsAligned(reinterpret_cast<Address>(serialized_code_start),
     359             :                  kInt32Size)) {
     360             :     aligned_buffer.reset(new byte[code_size]);
     361             :     code_start = aligned_buffer.get();
     362             :   }
     363             : #endif
     364             :   memcpy(code_start, code->instructions().start(), code_size);
     365             :   // Relocate the code.
     366             :   int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
     367             :              RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL) |
     368             :              RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
     369             :              RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
     370             :              RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
     371             :   RelocIterator orig_iter(code->instructions(), code->reloc_info(),
     372         514 :                           code->constant_pool(), mask);
     373         771 :   for (RelocIterator iter(
     374             :            {code_start, code->instructions().size()}, code->reloc_info(),
     375             :            reinterpret_cast<Address>(code_start) + code->constant_pool_offset(),
     376         514 :            mask);
     377         257 :        !iter.done(); iter.next(), orig_iter.next()) {
     378         257 :     RelocInfo::Mode mode = orig_iter.rinfo()->rmode();
     379         257 :     switch (mode) {
     380             :       case RelocInfo::WASM_CALL: {
     381          32 :         Address orig_target = orig_iter.rinfo()->wasm_call_address();
     382             :         uint32_t tag =
     383          32 :             native_module_->GetFunctionIndexFromJumpTableSlot(orig_target);
     384             :         SetWasmCalleeTag(iter.rinfo(), tag);
     385             :       } break;
     386             :       case RelocInfo::WASM_STUB_CALL: {
     387         225 :         Address orig_target = orig_iter.rinfo()->wasm_stub_call_address();
     388             :         auto stub_iter = wasm_stub_targets_lookup_.find(orig_target);
     389             :         DCHECK(stub_iter != wasm_stub_targets_lookup_.end());
     390         225 :         uint32_t tag = stub_iter->second;
     391             :         SetWasmCalleeTag(iter.rinfo(), tag);
     392         225 :       } break;
     393             :       case RelocInfo::EXTERNAL_REFERENCE: {
     394           0 :         Address orig_target = orig_iter.rinfo()->target_external_reference();
     395             :         uint32_t ext_ref_tag =
     396           0 :             ExternalReferenceList::Get().tag_from_address(orig_target);
     397             :         SetWasmCalleeTag(iter.rinfo(), ext_ref_tag);
     398             :       } break;
     399             :       case RelocInfo::INTERNAL_REFERENCE:
     400             :       case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
     401           0 :         Address orig_target = orig_iter.rinfo()->target_internal_reference();
     402           0 :         Address offset = orig_target - code->instruction_start();
     403             :         Assembler::deserialization_set_target_internal_reference_at(
     404           0 :             iter.rinfo()->pc(), offset, mode);
     405             :       } break;
     406             :       default:
     407           0 :         UNREACHABLE();
     408             :     }
     409             :   }
     410             :   // If we copied to an aligned buffer, copy code into serialized buffer.
     411             :   if (code_start != serialized_code_start) {
     412             :     memcpy(serialized_code_start, code_start, code_size);
     413             :   }
     414             : }
     415             : 
     416         201 : bool NativeModuleSerializer::Write(Writer* writer) {
     417             :   DCHECK(!write_called_);
     418         201 :   write_called_ = true;
     419             : 
     420         201 :   WriteHeader(writer);
     421             : 
     422         979 :   for (WasmCode* code : code_table_) {
     423         577 :     WriteCode(code, writer);
     424             :   }
     425         201 :   return true;
     426             : }
     427             : 
     428         201 : WasmSerializer::WasmSerializer(NativeModule* native_module)
     429             :     : native_module_(native_module),
     430         201 :       code_table_(native_module->SnapshotCodeTable()) {}
     431             : 
     432         201 : size_t WasmSerializer::GetSerializedNativeModuleSize() const {
     433         201 :   NativeModuleSerializer serializer(native_module_, VectorOf(code_table_));
     434         402 :   return kVersionSize + serializer.Measure();
     435             : }
     436             : 
     437         201 : bool WasmSerializer::SerializeNativeModule(Vector<byte> buffer) const {
     438         201 :   NativeModuleSerializer serializer(native_module_, VectorOf(code_table_));
     439         201 :   size_t measured_size = kVersionSize + serializer.Measure();
     440         201 :   if (buffer.size() < measured_size) return false;
     441             : 
     442             :   Writer writer(buffer);
     443         201 :   WriteVersion(&writer);
     444             : 
     445         201 :   if (!serializer.Write(&writer)) return false;
     446             :   DCHECK_EQ(measured_size, writer.bytes_written());
     447         201 :   return true;
     448             : }
     449             : 
     450             : class V8_EXPORT_PRIVATE NativeModuleDeserializer {
     451             :  public:
     452             :   NativeModuleDeserializer() = delete;
     453             :   explicit NativeModuleDeserializer(NativeModule*);
     454             : 
     455             :   bool Read(Reader* reader);
     456             : 
     457             :  private:
     458             :   bool ReadHeader(Reader* reader);
     459             :   bool ReadCode(uint32_t fn_index, Reader* reader);
     460             : 
     461             :   NativeModule* const native_module_;
     462             :   bool read_called_;
     463             : 
     464             :   DISALLOW_COPY_AND_ASSIGN(NativeModuleDeserializer);
     465             : };
     466             : 
     467           0 : NativeModuleDeserializer::NativeModuleDeserializer(NativeModule* native_module)
     468         180 :     : native_module_(native_module), read_called_(false) {}
     469             : 
     470         360 : bool NativeModuleDeserializer::Read(Reader* reader) {
     471             :   DCHECK(!read_called_);
     472         180 :   read_called_ = true;
     473             : 
     474         180 :   if (!ReadHeader(reader)) return false;
     475         180 :   uint32_t total_fns = native_module_->num_functions();
     476             :   uint32_t first_wasm_fn = native_module_->num_imported_functions();
     477         728 :   for (uint32_t i = first_wasm_fn; i < total_fns; ++i) {
     478         548 :     if (!ReadCode(i, reader)) return false;
     479             :   }
     480         180 :   return reader->current_size() == 0;
     481             : }
     482             : 
     483         180 : bool NativeModuleDeserializer::ReadHeader(Reader* reader) {
     484         180 :   size_t functions = reader->Read<uint32_t>();
     485         180 :   size_t imports = reader->Read<uint32_t>();
     486         360 :   return functions == native_module_->num_functions() &&
     487         180 :          imports == native_module_->num_imported_functions();
     488             : }
     489             : 
     490         776 : bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
     491         548 :   size_t code_section_size = reader->Read<size_t>();
     492         548 :   if (code_section_size == 0) return true;
     493         228 :   size_t constant_pool_offset = reader->Read<size_t>();
     494         228 :   size_t safepoint_table_offset = reader->Read<size_t>();
     495         228 :   size_t handler_table_offset = reader->Read<size_t>();
     496         228 :   size_t code_comment_offset = reader->Read<size_t>();
     497         228 :   size_t unpadded_binary_size = reader->Read<size_t>();
     498         228 :   uint32_t stack_slot_count = reader->Read<uint32_t>();
     499         228 :   uint32_t tagged_parameter_slots = reader->Read<uint32_t>();
     500         228 :   size_t code_size = reader->Read<size_t>();
     501         228 :   size_t reloc_size = reader->Read<size_t>();
     502         228 :   size_t source_position_size = reader->Read<size_t>();
     503         228 :   size_t protected_instructions_size = reader->Read<size_t>();
     504         228 :   WasmCode::Tier tier = reader->Read<WasmCode::Tier>();
     505             : 
     506             :   Vector<const byte> code_buffer = {reader->current_location(), code_size};
     507             :   reader->Skip(code_size);
     508             : 
     509             :   OwnedVector<byte> reloc_info = OwnedVector<byte>::New(reloc_size);
     510         228 :   reader->ReadVector(reloc_info.as_vector());
     511             :   OwnedVector<byte> source_pos = OwnedVector<byte>::New(source_position_size);
     512         228 :   reader->ReadVector(source_pos.as_vector());
     513             :   auto protected_instructions =
     514             :       OwnedVector<trap_handler::ProtectedInstructionData>::New(
     515         228 :           protected_instructions_size);
     516         228 :   reader->ReadVector(Vector<byte>::cast(protected_instructions.as_vector()));
     517             : 
     518             :   WasmCode* code = native_module_->AddDeserializedCode(
     519             :       fn_index, code_buffer, stack_slot_count, tagged_parameter_slots,
     520             :       safepoint_table_offset, handler_table_offset, constant_pool_offset,
     521             :       code_comment_offset, unpadded_binary_size,
     522             :       std::move(protected_instructions), std::move(reloc_info),
     523        1140 :       std::move(source_pos), tier);
     524             : 
     525             :   // Relocate the code.
     526             :   int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
     527             :              RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL) |
     528             :              RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
     529             :              RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
     530             :              RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
     531         468 :   for (RelocIterator iter(code->instructions(), code->reloc_info(),
     532         456 :                           code->constant_pool(), mask);
     533         240 :        !iter.done(); iter.next()) {
     534         240 :     RelocInfo::Mode mode = iter.rinfo()->rmode();
     535         240 :     switch (mode) {
     536             :       case RelocInfo::WASM_CALL: {
     537             :         uint32_t tag = GetWasmCalleeTag(iter.rinfo());
     538          32 :         Address target = native_module_->GetCallTargetForFunction(tag);
     539          32 :         iter.rinfo()->set_wasm_call_address(target, SKIP_ICACHE_FLUSH);
     540             :         break;
     541             :       }
     542             :       case RelocInfo::WASM_STUB_CALL: {
     543             :         uint32_t tag = GetWasmCalleeTag(iter.rinfo());
     544             :         DCHECK_LT(tag, WasmCode::kRuntimeStubCount);
     545             :         Address target = native_module_->runtime_stub_entry(
     546         208 :             static_cast<WasmCode::RuntimeStubId>(tag));
     547         208 :         iter.rinfo()->set_wasm_stub_call_address(target, SKIP_ICACHE_FLUSH);
     548             :         break;
     549             :       }
     550             :       case RelocInfo::EXTERNAL_REFERENCE: {
     551             :         uint32_t tag = GetWasmCalleeTag(iter.rinfo());
     552           0 :         Address address = ExternalReferenceList::Get().address_from_tag(tag);
     553             :         iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH);
     554             :         break;
     555             :       }
     556             :       case RelocInfo::INTERNAL_REFERENCE:
     557             :       case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
     558           0 :         Address offset = iter.rinfo()->target_internal_reference();
     559           0 :         Address target = code->instruction_start() + offset;
     560             :         Assembler::deserialization_set_target_internal_reference_at(
     561             :             iter.rinfo()->pc(), target, mode);
     562             :         break;
     563             :       }
     564             :       default:
     565           0 :         UNREACHABLE();
     566             :     }
     567             :   }
     568             : 
     569         228 :   code->MaybePrint();
     570         228 :   code->Validate();
     571             : 
     572             :   // Finally, flush the icache for that code.
     573             :   FlushInstructionCache(code->instructions().start(),
     574         228 :                         code->instructions().size());
     575             : 
     576             :   return true;
     577             : }
     578             : 
     579         236 : bool IsSupportedVersion(Vector<const byte> version) {
     580         236 :   if (version.size() < kVersionSize) return false;
     581             :   byte current_version[kVersionSize];
     582             :   Writer writer({current_version, kVersionSize});
     583         192 :   WriteVersion(&writer);
     584         192 :   return memcmp(version.start(), current_version, kVersionSize) == 0;
     585             : }
     586             : 
     587         256 : MaybeHandle<WasmModuleObject> DeserializeNativeModule(
     588         180 :     Isolate* isolate, Vector<const byte> data,
     589             :     Vector<const byte> wire_bytes_vec) {
     590         512 :   if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) return {};
     591         236 :   if (!IsSupportedVersion(data)) return {};
     592             : 
     593             :   ModuleWireBytes wire_bytes(wire_bytes_vec);
     594             :   // TODO(titzer): module features should be part of the serialization format.
     595         180 :   WasmFeatures enabled_features = WasmFeaturesFromIsolate(isolate);
     596             :   ModuleResult decode_result = DecodeWasmModule(
     597             :       enabled_features, wire_bytes.start(), wire_bytes.end(), false,
     598         360 :       i::wasm::kWasmOrigin, isolate->counters(), isolate->allocator());
     599         180 :   if (decode_result.failed()) return {};
     600         180 :   CHECK_NOT_NULL(decode_result.value());
     601             :   WasmModule* module = decode_result.value().get();
     602             :   Handle<Script> script =
     603         180 :       CreateWasmScript(isolate, wire_bytes, module->source_map_url);
     604             : 
     605             :   OwnedVector<uint8_t> wire_bytes_copy =
     606         180 :       OwnedVector<uint8_t>::Of(wire_bytes_vec);
     607             : 
     608             :   Handle<WasmModuleObject> module_object = WasmModuleObject::New(
     609             :       isolate, enabled_features, std::move(decode_result).value(),
     610         540 :       std::move(wire_bytes_copy), script, Handle<ByteArray>::null());
     611         180 :   NativeModule* native_module = module_object->native_module();
     612             : 
     613         180 :   if (FLAG_wasm_lazy_compilation) {
     614          16 :     native_module->SetLazyBuiltin(BUILTIN_CODE(isolate, WasmCompileLazy));
     615             :   }
     616             :   NativeModuleDeserializer deserializer(native_module);
     617             : 
     618             :   Reader reader(data + kVersionSize);
     619         180 :   if (!deserializer.Read(&reader)) return {};
     620             : 
     621             :   CompileJsToWasmWrappers(isolate, native_module->module(),
     622         360 :                           handle(module_object->export_wrappers(), isolate));
     623             : 
     624             :   // Log the code within the generated module for profiling.
     625         180 :   native_module->LogWasmCodes(isolate);
     626             : 
     627         360 :   return module_object;
     628             : }
     629             : 
     630             : }  // namespace wasm
     631             : }  // namespace internal
     632      178779 : }  // namespace v8

Generated by: LCOV version 1.10