11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/wasm/wasm-serialization.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h"
81cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h"
91cb0ef41Sopenharmony_ci#include "src/codegen/external-reference-table.h"
101cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
111cb0ef41Sopenharmony_ci#include "src/objects/objects.h"
121cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h"
131cb0ef41Sopenharmony_ci#include "src/snapshot/code-serializer.h"
141cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
151cb0ef41Sopenharmony_ci#include "src/utils/utils.h"
161cb0ef41Sopenharmony_ci#include "src/utils/version.h"
171cb0ef41Sopenharmony_ci#include "src/wasm/code-space-access.h"
181cb0ef41Sopenharmony_ci#include "src/wasm/function-compiler.h"
191cb0ef41Sopenharmony_ci#include "src/wasm/module-compiler.h"
201cb0ef41Sopenharmony_ci#include "src/wasm/module-decoder.h"
211cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h"
221cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h"
231cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h"
241cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h"
251cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects.h"
261cb0ef41Sopenharmony_ci#include "src/wasm/wasm-result.h"
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cinamespace v8 {
291cb0ef41Sopenharmony_cinamespace internal {
301cb0ef41Sopenharmony_cinamespace wasm {
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_cinamespace {
331cb0ef41Sopenharmony_ciconstexpr uint8_t kLazyFunction = 2;
341cb0ef41Sopenharmony_ciconstexpr uint8_t kLiftoffFunction = 3;
351cb0ef41Sopenharmony_ciconstexpr uint8_t kTurboFanFunction = 4;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci// TODO(bbudge) Try to unify the various implementations of readers and writers
381cb0ef41Sopenharmony_ci// in Wasm, e.g. StreamProcessor and ZoneBuffer, with these.
391cb0ef41Sopenharmony_ciclass Writer {
401cb0ef41Sopenharmony_ci public:
411cb0ef41Sopenharmony_ci  explicit Writer(base::Vector<byte> buffer)
421cb0ef41Sopenharmony_ci      : start_(buffer.begin()), end_(buffer.end()), pos_(buffer.begin()) {}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  size_t bytes_written() const { return pos_ - start_; }
451cb0ef41Sopenharmony_ci  byte* current_location() const { return pos_; }
461cb0ef41Sopenharmony_ci  size_t current_size() const { return end_ - pos_; }
471cb0ef41Sopenharmony_ci  base::Vector<byte> current_buffer() const {
481cb0ef41Sopenharmony_ci    return {current_location(), current_size()};
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  template <typename T>
521cb0ef41Sopenharmony_ci  void Write(const T& value) {
531cb0ef41Sopenharmony_ci    DCHECK_GE(current_size(), sizeof(T));
541cb0ef41Sopenharmony_ci    WriteUnalignedValue(reinterpret_cast<Address>(current_location()), value);
551cb0ef41Sopenharmony_ci    pos_ += sizeof(T);
561cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_serialization) {
571cb0ef41Sopenharmony_ci      StdoutStream{} << "wrote: " << static_cast<size_t>(value)
581cb0ef41Sopenharmony_ci                     << " sized: " << sizeof(T) << std::endl;
591cb0ef41Sopenharmony_ci    }
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  void WriteVector(const base::Vector<const byte> v) {
631cb0ef41Sopenharmony_ci    DCHECK_GE(current_size(), v.size());
641cb0ef41Sopenharmony_ci    if (v.size() > 0) {
651cb0ef41Sopenharmony_ci      memcpy(current_location(), v.begin(), v.size());
661cb0ef41Sopenharmony_ci      pos_ += v.size();
671cb0ef41Sopenharmony_ci    }
681cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_serialization) {
691cb0ef41Sopenharmony_ci      StdoutStream{} << "wrote vector of " << v.size() << " elements"
701cb0ef41Sopenharmony_ci                     << std::endl;
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  void Skip(size_t size) { pos_ += size; }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci private:
771cb0ef41Sopenharmony_ci  byte* const start_;
781cb0ef41Sopenharmony_ci  byte* const end_;
791cb0ef41Sopenharmony_ci  byte* pos_;
801cb0ef41Sopenharmony_ci};
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ciclass Reader {
831cb0ef41Sopenharmony_ci public:
841cb0ef41Sopenharmony_ci  explicit Reader(base::Vector<const byte> buffer)
851cb0ef41Sopenharmony_ci      : start_(buffer.begin()), end_(buffer.end()), pos_(buffer.begin()) {}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  size_t bytes_read() const { return pos_ - start_; }
881cb0ef41Sopenharmony_ci  const byte* current_location() const { return pos_; }
891cb0ef41Sopenharmony_ci  size_t current_size() const { return end_ - pos_; }
901cb0ef41Sopenharmony_ci  base::Vector<const byte> current_buffer() const {
911cb0ef41Sopenharmony_ci    return {current_location(), current_size()};
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  template <typename T>
951cb0ef41Sopenharmony_ci  T Read() {
961cb0ef41Sopenharmony_ci    DCHECK_GE(current_size(), sizeof(T));
971cb0ef41Sopenharmony_ci    T value =
981cb0ef41Sopenharmony_ci        ReadUnalignedValue<T>(reinterpret_cast<Address>(current_location()));
991cb0ef41Sopenharmony_ci    pos_ += sizeof(T);
1001cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_serialization) {
1011cb0ef41Sopenharmony_ci      StdoutStream{} << "read: " << static_cast<size_t>(value)
1021cb0ef41Sopenharmony_ci                     << " sized: " << sizeof(T) << std::endl;
1031cb0ef41Sopenharmony_ci    }
1041cb0ef41Sopenharmony_ci    return value;
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  template <typename T>
1081cb0ef41Sopenharmony_ci  base::Vector<const T> ReadVector(size_t size) {
1091cb0ef41Sopenharmony_ci    DCHECK_GE(current_size(), size);
1101cb0ef41Sopenharmony_ci    base::Vector<const byte> bytes{pos_, size * sizeof(T)};
1111cb0ef41Sopenharmony_ci    pos_ += size * sizeof(T);
1121cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_serialization) {
1131cb0ef41Sopenharmony_ci      StdoutStream{} << "read vector of " << size << " elements of size "
1141cb0ef41Sopenharmony_ci                     << sizeof(T) << " (total size " << size * sizeof(T) << ")"
1151cb0ef41Sopenharmony_ci                     << std::endl;
1161cb0ef41Sopenharmony_ci    }
1171cb0ef41Sopenharmony_ci    return base::Vector<const T>::cast(bytes);
1181cb0ef41Sopenharmony_ci  }
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  void Skip(size_t size) { pos_ += size; }
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci private:
1231cb0ef41Sopenharmony_ci  const byte* const start_;
1241cb0ef41Sopenharmony_ci  const byte* const end_;
1251cb0ef41Sopenharmony_ci  const byte* pos_;
1261cb0ef41Sopenharmony_ci};
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_civoid WriteHeader(Writer* writer) {
1291cb0ef41Sopenharmony_ci  writer->Write(SerializedData::kMagicNumber);
1301cb0ef41Sopenharmony_ci  writer->Write(Version::Hash());
1311cb0ef41Sopenharmony_ci  writer->Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
1321cb0ef41Sopenharmony_ci  writer->Write(FlagList::Hash());
1331cb0ef41Sopenharmony_ci  DCHECK_EQ(WasmSerializer::kHeaderSize, writer->bytes_written());
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci// On Intel, call sites are encoded as a displacement. For linking and for
1371cb0ef41Sopenharmony_ci// serialization/deserialization, we want to store/retrieve a tag (the function
1381cb0ef41Sopenharmony_ci// index). On Intel, that means accessing the raw displacement.
1391cb0ef41Sopenharmony_ci// On ARM64, call sites are encoded as either a literal load or a direct branch.
1401cb0ef41Sopenharmony_ci// Other platforms simply require accessing the target address.
1411cb0ef41Sopenharmony_civoid SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
1421cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
1431cb0ef41Sopenharmony_ci  DCHECK(rinfo->HasTargetAddressAddress());
1441cb0ef41Sopenharmony_ci  DCHECK(!RelocInfo::IsCompressedEmbeddedObject(rinfo->rmode()));
1451cb0ef41Sopenharmony_ci  WriteUnalignedValue(rinfo->target_address_address(), tag);
1461cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM64
1471cb0ef41Sopenharmony_ci  Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
1481cb0ef41Sopenharmony_ci  if (instr->IsLdrLiteralX()) {
1491cb0ef41Sopenharmony_ci    WriteUnalignedValue(rinfo->constant_pool_entry_address(),
1501cb0ef41Sopenharmony_ci                        static_cast<Address>(tag));
1511cb0ef41Sopenharmony_ci  } else {
1521cb0ef41Sopenharmony_ci    DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
1531cb0ef41Sopenharmony_ci    instr->SetBranchImmTarget(
1541cb0ef41Sopenharmony_ci        reinterpret_cast<Instruction*>(rinfo->pc() + tag * kInstrSize));
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci#else
1571cb0ef41Sopenharmony_ci  Address addr = static_cast<Address>(tag);
1581cb0ef41Sopenharmony_ci  if (rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE) {
1591cb0ef41Sopenharmony_ci    rinfo->set_target_external_reference(addr, SKIP_ICACHE_FLUSH);
1601cb0ef41Sopenharmony_ci  } else if (rinfo->rmode() == RelocInfo::WASM_STUB_CALL) {
1611cb0ef41Sopenharmony_ci    rinfo->set_wasm_stub_call_address(addr, SKIP_ICACHE_FLUSH);
1621cb0ef41Sopenharmony_ci  } else {
1631cb0ef41Sopenharmony_ci    rinfo->set_target_address(addr, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
1641cb0ef41Sopenharmony_ci  }
1651cb0ef41Sopenharmony_ci#endif
1661cb0ef41Sopenharmony_ci}
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ciuint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
1691cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
1701cb0ef41Sopenharmony_ci  DCHECK(!RelocInfo::IsCompressedEmbeddedObject(rinfo->rmode()));
1711cb0ef41Sopenharmony_ci  return ReadUnalignedValue<uint32_t>(rinfo->target_address_address());
1721cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM64
1731cb0ef41Sopenharmony_ci  Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
1741cb0ef41Sopenharmony_ci  if (instr->IsLdrLiteralX()) {
1751cb0ef41Sopenharmony_ci    return ReadUnalignedValue<uint32_t>(rinfo->constant_pool_entry_address());
1761cb0ef41Sopenharmony_ci  } else {
1771cb0ef41Sopenharmony_ci    DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
1781cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(instr->ImmPCOffset() / kInstrSize);
1791cb0ef41Sopenharmony_ci  }
1801cb0ef41Sopenharmony_ci#else
1811cb0ef41Sopenharmony_ci  Address addr;
1821cb0ef41Sopenharmony_ci  if (rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE) {
1831cb0ef41Sopenharmony_ci    addr = rinfo->target_external_reference();
1841cb0ef41Sopenharmony_ci  } else if (rinfo->rmode() == RelocInfo::WASM_STUB_CALL) {
1851cb0ef41Sopenharmony_ci    addr = rinfo->wasm_stub_call_address();
1861cb0ef41Sopenharmony_ci  } else {
1871cb0ef41Sopenharmony_ci    addr = rinfo->target_address();
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci  return static_cast<uint32_t>(addr);
1901cb0ef41Sopenharmony_ci#endif
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ciconstexpr size_t kHeaderSize = sizeof(size_t);  // total code size
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ciconstexpr size_t kCodeHeaderSize = sizeof(uint8_t) +  // code kind
1961cb0ef41Sopenharmony_ci                                   sizeof(int) +      // offset of constant pool
1971cb0ef41Sopenharmony_ci                                   sizeof(int) +  // offset of safepoint table
1981cb0ef41Sopenharmony_ci                                   sizeof(int) +  // offset of handler table
1991cb0ef41Sopenharmony_ci                                   sizeof(int) +  // offset of code comments
2001cb0ef41Sopenharmony_ci                                   sizeof(int) +  // unpadded binary size
2011cb0ef41Sopenharmony_ci                                   sizeof(int) +  // stack slots
2021cb0ef41Sopenharmony_ci                                   sizeof(int) +  // tagged parameter slots
2031cb0ef41Sopenharmony_ci                                   sizeof(int) +  // code size
2041cb0ef41Sopenharmony_ci                                   sizeof(int) +  // reloc size
2051cb0ef41Sopenharmony_ci                                   sizeof(int) +  // source positions size
2061cb0ef41Sopenharmony_ci                                   sizeof(int) +  // protected instructions size
2071cb0ef41Sopenharmony_ci                                   sizeof(WasmCode::Kind) +  // code kind
2081cb0ef41Sopenharmony_ci                                   sizeof(ExecutionTier);    // tier
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci// A List of all isolate-independent external references. This is used to create
2111cb0ef41Sopenharmony_ci// a tag from the Address of an external reference and vice versa.
2121cb0ef41Sopenharmony_ciclass ExternalReferenceList {
2131cb0ef41Sopenharmony_ci public:
2141cb0ef41Sopenharmony_ci  ExternalReferenceList(const ExternalReferenceList&) = delete;
2151cb0ef41Sopenharmony_ci  ExternalReferenceList& operator=(const ExternalReferenceList&) = delete;
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  uint32_t tag_from_address(Address ext_ref_address) const {
2181cb0ef41Sopenharmony_ci    auto tag_addr_less_than = [this](uint32_t tag, Address searched_addr) {
2191cb0ef41Sopenharmony_ci      return external_reference_by_tag_[tag] < searched_addr;
2201cb0ef41Sopenharmony_ci    };
2211cb0ef41Sopenharmony_ci    auto it = std::lower_bound(std::begin(tags_ordered_by_address_),
2221cb0ef41Sopenharmony_ci                               std::end(tags_ordered_by_address_),
2231cb0ef41Sopenharmony_ci                               ext_ref_address, tag_addr_less_than);
2241cb0ef41Sopenharmony_ci    DCHECK_NE(std::end(tags_ordered_by_address_), it);
2251cb0ef41Sopenharmony_ci    uint32_t tag = *it;
2261cb0ef41Sopenharmony_ci    DCHECK_EQ(address_from_tag(tag), ext_ref_address);
2271cb0ef41Sopenharmony_ci    return tag;
2281cb0ef41Sopenharmony_ci  }
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  Address address_from_tag(uint32_t tag) const {
2311cb0ef41Sopenharmony_ci    DCHECK_GT(kNumExternalReferences, tag);
2321cb0ef41Sopenharmony_ci    return external_reference_by_tag_[tag];
2331cb0ef41Sopenharmony_ci  }
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  static const ExternalReferenceList& Get() {
2361cb0ef41Sopenharmony_ci    static ExternalReferenceList list;  // Lazily initialized.
2371cb0ef41Sopenharmony_ci    return list;
2381cb0ef41Sopenharmony_ci  }
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci private:
2411cb0ef41Sopenharmony_ci  // Private constructor. There will only be a single instance of this object.
2421cb0ef41Sopenharmony_ci  ExternalReferenceList() {
2431cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < kNumExternalReferences; ++i) {
2441cb0ef41Sopenharmony_ci      tags_ordered_by_address_[i] = i;
2451cb0ef41Sopenharmony_ci    }
2461cb0ef41Sopenharmony_ci    auto addr_by_tag_less_than = [this](uint32_t a, uint32_t b) {
2471cb0ef41Sopenharmony_ci      return external_reference_by_tag_[a] < external_reference_by_tag_[b];
2481cb0ef41Sopenharmony_ci    };
2491cb0ef41Sopenharmony_ci    std::sort(std::begin(tags_ordered_by_address_),
2501cb0ef41Sopenharmony_ci              std::end(tags_ordered_by_address_), addr_by_tag_less_than);
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci#define COUNT_EXTERNAL_REFERENCE(name, ...) +1
2541cb0ef41Sopenharmony_ci  static constexpr uint32_t kNumExternalReferencesList =
2551cb0ef41Sopenharmony_ci      EXTERNAL_REFERENCE_LIST(COUNT_EXTERNAL_REFERENCE);
2561cb0ef41Sopenharmony_ci  static constexpr uint32_t kNumExternalReferencesIntrinsics =
2571cb0ef41Sopenharmony_ci      FOR_EACH_INTRINSIC(COUNT_EXTERNAL_REFERENCE);
2581cb0ef41Sopenharmony_ci  static constexpr uint32_t kNumExternalReferences =
2591cb0ef41Sopenharmony_ci      kNumExternalReferencesList + kNumExternalReferencesIntrinsics;
2601cb0ef41Sopenharmony_ci#undef COUNT_EXTERNAL_REFERENCE
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  Address external_reference_by_tag_[kNumExternalReferences] = {
2631cb0ef41Sopenharmony_ci#define EXT_REF_ADDR(name, desc) ExternalReference::name().address(),
2641cb0ef41Sopenharmony_ci      EXTERNAL_REFERENCE_LIST(EXT_REF_ADDR)
2651cb0ef41Sopenharmony_ci#undef EXT_REF_ADDR
2661cb0ef41Sopenharmony_ci#define RUNTIME_ADDR(name, ...) \
2671cb0ef41Sopenharmony_ci  ExternalReference::Create(Runtime::k##name).address(),
2681cb0ef41Sopenharmony_ci          FOR_EACH_INTRINSIC(RUNTIME_ADDR)
2691cb0ef41Sopenharmony_ci#undef RUNTIME_ADDR
2701cb0ef41Sopenharmony_ci  };
2711cb0ef41Sopenharmony_ci  uint32_t tags_ordered_by_address_[kNumExternalReferences];
2721cb0ef41Sopenharmony_ci};
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_cistatic_assert(std::is_trivially_destructible<ExternalReferenceList>::value,
2751cb0ef41Sopenharmony_ci              "static destructors not allowed");
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci}  // namespace
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE NativeModuleSerializer {
2801cb0ef41Sopenharmony_ci public:
2811cb0ef41Sopenharmony_ci  NativeModuleSerializer(const NativeModule*, base::Vector<WasmCode* const>);
2821cb0ef41Sopenharmony_ci  NativeModuleSerializer(const NativeModuleSerializer&) = delete;
2831cb0ef41Sopenharmony_ci  NativeModuleSerializer& operator=(const NativeModuleSerializer&) = delete;
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  size_t Measure() const;
2861cb0ef41Sopenharmony_ci  bool Write(Writer* writer);
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci private:
2891cb0ef41Sopenharmony_ci  size_t MeasureCode(const WasmCode*) const;
2901cb0ef41Sopenharmony_ci  void WriteHeader(Writer*, size_t total_code_size);
2911cb0ef41Sopenharmony_ci  void WriteCode(const WasmCode*, Writer*);
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci  const NativeModule* const native_module_;
2941cb0ef41Sopenharmony_ci  const base::Vector<WasmCode* const> code_table_;
2951cb0ef41Sopenharmony_ci  bool write_called_ = false;
2961cb0ef41Sopenharmony_ci  size_t total_written_code_ = 0;
2971cb0ef41Sopenharmony_ci  int num_turbofan_functions_ = 0;
2981cb0ef41Sopenharmony_ci};
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ciNativeModuleSerializer::NativeModuleSerializer(
3011cb0ef41Sopenharmony_ci    const NativeModule* module, base::Vector<WasmCode* const> code_table)
3021cb0ef41Sopenharmony_ci    : native_module_(module), code_table_(code_table) {
3031cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(native_module_);
3041cb0ef41Sopenharmony_ci  // TODO(mtrofin): persist the export wrappers. Ideally, we'd only persist
3051cb0ef41Sopenharmony_ci  // the unique ones, i.e. the cache.
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_cisize_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
3091cb0ef41Sopenharmony_ci  if (code == nullptr) return sizeof(uint8_t);
3101cb0ef41Sopenharmony_ci  DCHECK_EQ(WasmCode::kWasmFunction, code->kind());
3111cb0ef41Sopenharmony_ci  if (code->tier() != ExecutionTier::kTurbofan) {
3121cb0ef41Sopenharmony_ci    return sizeof(uint8_t);
3131cb0ef41Sopenharmony_ci  }
3141cb0ef41Sopenharmony_ci  return kCodeHeaderSize + code->instructions().size() +
3151cb0ef41Sopenharmony_ci         code->reloc_info().size() + code->source_positions().size() +
3161cb0ef41Sopenharmony_ci         code->protected_instructions_data().size();
3171cb0ef41Sopenharmony_ci}
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_cisize_t NativeModuleSerializer::Measure() const {
3201cb0ef41Sopenharmony_ci  size_t size = kHeaderSize;
3211cb0ef41Sopenharmony_ci  for (WasmCode* code : code_table_) {
3221cb0ef41Sopenharmony_ci    size += MeasureCode(code);
3231cb0ef41Sopenharmony_ci  }
3241cb0ef41Sopenharmony_ci  return size;
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_civoid NativeModuleSerializer::WriteHeader(Writer* writer,
3281cb0ef41Sopenharmony_ci                                         size_t total_code_size) {
3291cb0ef41Sopenharmony_ci  // TODO(eholk): We need to properly preserve the flag whether the trap
3301cb0ef41Sopenharmony_ci  // handler was used or not when serializing.
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci  writer->Write(total_code_size);
3331cb0ef41Sopenharmony_ci}
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_civoid NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
3361cb0ef41Sopenharmony_ci  if (code == nullptr) {
3371cb0ef41Sopenharmony_ci    writer->Write(kLazyFunction);
3381cb0ef41Sopenharmony_ci    return;
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  DCHECK_EQ(WasmCode::kWasmFunction, code->kind());
3421cb0ef41Sopenharmony_ci  // Only serialize TurboFan code, as Liftoff code can contain breakpoints or
3431cb0ef41Sopenharmony_ci  // non-relocatable constants.
3441cb0ef41Sopenharmony_ci  if (code->tier() != ExecutionTier::kTurbofan) {
3451cb0ef41Sopenharmony_ci    // We check if the function has been executed already. If so, we serialize
3461cb0ef41Sopenharmony_ci    // it as {kLiftoffFunction} so that upon deserialization the function will
3471cb0ef41Sopenharmony_ci    // get compiled with Liftoff eagerly. If the function has not been executed
3481cb0ef41Sopenharmony_ci    // yet, we serialize it as {kLazyFunction}, and the function will not get
3491cb0ef41Sopenharmony_ci    // compiled upon deserialization.
3501cb0ef41Sopenharmony_ci    NativeModule* native_module = code->native_module();
3511cb0ef41Sopenharmony_ci    uint32_t budget =
3521cb0ef41Sopenharmony_ci        native_module->tiering_budget_array()[declared_function_index(
3531cb0ef41Sopenharmony_ci            native_module->module(), code->index())];
3541cb0ef41Sopenharmony_ci    writer->Write(budget == static_cast<uint32_t>(FLAG_wasm_tiering_budget)
3551cb0ef41Sopenharmony_ci                      ? kLazyFunction
3561cb0ef41Sopenharmony_ci                      : kLiftoffFunction);
3571cb0ef41Sopenharmony_ci    return;
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  ++num_turbofan_functions_;
3611cb0ef41Sopenharmony_ci  writer->Write(kTurboFanFunction);
3621cb0ef41Sopenharmony_ci  // Write the size of the entire code section, followed by the code header.
3631cb0ef41Sopenharmony_ci  writer->Write(code->constant_pool_offset());
3641cb0ef41Sopenharmony_ci  writer->Write(code->safepoint_table_offset());
3651cb0ef41Sopenharmony_ci  writer->Write(code->handler_table_offset());
3661cb0ef41Sopenharmony_ci  writer->Write(code->code_comments_offset());
3671cb0ef41Sopenharmony_ci  writer->Write(code->unpadded_binary_size());
3681cb0ef41Sopenharmony_ci  writer->Write(code->stack_slots());
3691cb0ef41Sopenharmony_ci  writer->Write(code->raw_tagged_parameter_slots_for_serialization());
3701cb0ef41Sopenharmony_ci  writer->Write(code->instructions().length());
3711cb0ef41Sopenharmony_ci  writer->Write(code->reloc_info().length());
3721cb0ef41Sopenharmony_ci  writer->Write(code->source_positions().length());
3731cb0ef41Sopenharmony_ci  writer->Write(code->protected_instructions_data().length());
3741cb0ef41Sopenharmony_ci  writer->Write(code->kind());
3751cb0ef41Sopenharmony_ci  writer->Write(code->tier());
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  // Get a pointer to the destination buffer, to hold relocated code.
3781cb0ef41Sopenharmony_ci  byte* serialized_code_start = writer->current_buffer().begin();
3791cb0ef41Sopenharmony_ci  byte* code_start = serialized_code_start;
3801cb0ef41Sopenharmony_ci  size_t code_size = code->instructions().size();
3811cb0ef41Sopenharmony_ci  writer->Skip(code_size);
3821cb0ef41Sopenharmony_ci  // Write the reloc info, source positions, and protected code.
3831cb0ef41Sopenharmony_ci  writer->WriteVector(code->reloc_info());
3841cb0ef41Sopenharmony_ci  writer->WriteVector(code->source_positions());
3851cb0ef41Sopenharmony_ci  writer->WriteVector(code->protected_instructions_data());
3861cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM || \
3871cb0ef41Sopenharmony_ci    V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X || \
3881cb0ef41Sopenharmony_ci    V8_TARGET_ARCH_RISCV64
3891cb0ef41Sopenharmony_ci  // On platforms that don't support misaligned word stores, copy to an aligned
3901cb0ef41Sopenharmony_ci  // buffer if necessary so we can relocate the serialized code.
3911cb0ef41Sopenharmony_ci  std::unique_ptr<byte[]> aligned_buffer;
3921cb0ef41Sopenharmony_ci  if (!IsAligned(reinterpret_cast<Address>(serialized_code_start),
3931cb0ef41Sopenharmony_ci                 kSystemPointerSize)) {
3941cb0ef41Sopenharmony_ci    // 'byte' does not guarantee an alignment but seems to work well enough in
3951cb0ef41Sopenharmony_ci    // practice.
3961cb0ef41Sopenharmony_ci    aligned_buffer.reset(new byte[code_size]);
3971cb0ef41Sopenharmony_ci    code_start = aligned_buffer.get();
3981cb0ef41Sopenharmony_ci  }
3991cb0ef41Sopenharmony_ci#endif
4001cb0ef41Sopenharmony_ci  memcpy(code_start, code->instructions().begin(), code_size);
4011cb0ef41Sopenharmony_ci  // Relocate the code.
4021cb0ef41Sopenharmony_ci  int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
4031cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL) |
4041cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
4051cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
4061cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
4071cb0ef41Sopenharmony_ci  RelocIterator orig_iter(code->instructions(), code->reloc_info(),
4081cb0ef41Sopenharmony_ci                          code->constant_pool(), mask);
4091cb0ef41Sopenharmony_ci  for (RelocIterator iter(
4101cb0ef41Sopenharmony_ci           {code_start, code->instructions().size()}, code->reloc_info(),
4111cb0ef41Sopenharmony_ci           reinterpret_cast<Address>(code_start) + code->constant_pool_offset(),
4121cb0ef41Sopenharmony_ci           mask);
4131cb0ef41Sopenharmony_ci       !iter.done(); iter.next(), orig_iter.next()) {
4141cb0ef41Sopenharmony_ci    RelocInfo::Mode mode = orig_iter.rinfo()->rmode();
4151cb0ef41Sopenharmony_ci    switch (mode) {
4161cb0ef41Sopenharmony_ci      case RelocInfo::WASM_CALL: {
4171cb0ef41Sopenharmony_ci        Address orig_target = orig_iter.rinfo()->wasm_call_address();
4181cb0ef41Sopenharmony_ci        uint32_t tag =
4191cb0ef41Sopenharmony_ci            native_module_->GetFunctionIndexFromJumpTableSlot(orig_target);
4201cb0ef41Sopenharmony_ci        SetWasmCalleeTag(iter.rinfo(), tag);
4211cb0ef41Sopenharmony_ci      } break;
4221cb0ef41Sopenharmony_ci      case RelocInfo::WASM_STUB_CALL: {
4231cb0ef41Sopenharmony_ci        Address target = orig_iter.rinfo()->wasm_stub_call_address();
4241cb0ef41Sopenharmony_ci        uint32_t tag = native_module_->GetRuntimeStubId(target);
4251cb0ef41Sopenharmony_ci        DCHECK_GT(WasmCode::kRuntimeStubCount, tag);
4261cb0ef41Sopenharmony_ci        SetWasmCalleeTag(iter.rinfo(), tag);
4271cb0ef41Sopenharmony_ci      } break;
4281cb0ef41Sopenharmony_ci      case RelocInfo::EXTERNAL_REFERENCE: {
4291cb0ef41Sopenharmony_ci        Address orig_target = orig_iter.rinfo()->target_external_reference();
4301cb0ef41Sopenharmony_ci        uint32_t ext_ref_tag =
4311cb0ef41Sopenharmony_ci            ExternalReferenceList::Get().tag_from_address(orig_target);
4321cb0ef41Sopenharmony_ci        SetWasmCalleeTag(iter.rinfo(), ext_ref_tag);
4331cb0ef41Sopenharmony_ci      } break;
4341cb0ef41Sopenharmony_ci      case RelocInfo::INTERNAL_REFERENCE:
4351cb0ef41Sopenharmony_ci      case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
4361cb0ef41Sopenharmony_ci        Address orig_target = orig_iter.rinfo()->target_internal_reference();
4371cb0ef41Sopenharmony_ci        Address offset = orig_target - code->instruction_start();
4381cb0ef41Sopenharmony_ci        Assembler::deserialization_set_target_internal_reference_at(
4391cb0ef41Sopenharmony_ci            iter.rinfo()->pc(), offset, mode);
4401cb0ef41Sopenharmony_ci      } break;
4411cb0ef41Sopenharmony_ci      default:
4421cb0ef41Sopenharmony_ci        UNREACHABLE();
4431cb0ef41Sopenharmony_ci    }
4441cb0ef41Sopenharmony_ci  }
4451cb0ef41Sopenharmony_ci  // If we copied to an aligned buffer, copy code into serialized buffer.
4461cb0ef41Sopenharmony_ci  if (code_start != serialized_code_start) {
4471cb0ef41Sopenharmony_ci    memcpy(serialized_code_start, code_start, code_size);
4481cb0ef41Sopenharmony_ci  }
4491cb0ef41Sopenharmony_ci  total_written_code_ += code_size;
4501cb0ef41Sopenharmony_ci}
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_cibool NativeModuleSerializer::Write(Writer* writer) {
4531cb0ef41Sopenharmony_ci  DCHECK(!write_called_);
4541cb0ef41Sopenharmony_ci  write_called_ = true;
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  size_t total_code_size = 0;
4571cb0ef41Sopenharmony_ci  for (WasmCode* code : code_table_) {
4581cb0ef41Sopenharmony_ci    if (code && code->tier() == ExecutionTier::kTurbofan) {
4591cb0ef41Sopenharmony_ci      DCHECK(IsAligned(code->instructions().size(), kCodeAlignment));
4601cb0ef41Sopenharmony_ci      total_code_size += code->instructions().size();
4611cb0ef41Sopenharmony_ci    }
4621cb0ef41Sopenharmony_ci  }
4631cb0ef41Sopenharmony_ci  WriteHeader(writer, total_code_size);
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  for (WasmCode* code : code_table_) {
4661cb0ef41Sopenharmony_ci    WriteCode(code, writer);
4671cb0ef41Sopenharmony_ci  }
4681cb0ef41Sopenharmony_ci  // If not a single function was written, serialization was not successful.
4691cb0ef41Sopenharmony_ci  if (num_turbofan_functions_ == 0) return false;
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  // Make sure that the serialized total code size was correct.
4721cb0ef41Sopenharmony_ci  CHECK_EQ(total_written_code_, total_code_size);
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci  return true;
4751cb0ef41Sopenharmony_ci}
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ciWasmSerializer::WasmSerializer(NativeModule* native_module)
4781cb0ef41Sopenharmony_ci    : native_module_(native_module),
4791cb0ef41Sopenharmony_ci      code_table_(native_module->SnapshotCodeTable()) {}
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_cisize_t WasmSerializer::GetSerializedNativeModuleSize() const {
4821cb0ef41Sopenharmony_ci  NativeModuleSerializer serializer(native_module_,
4831cb0ef41Sopenharmony_ci                                    base::VectorOf(code_table_));
4841cb0ef41Sopenharmony_ci  return kHeaderSize + serializer.Measure();
4851cb0ef41Sopenharmony_ci}
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_cibool WasmSerializer::SerializeNativeModule(base::Vector<byte> buffer) const {
4881cb0ef41Sopenharmony_ci  NativeModuleSerializer serializer(native_module_,
4891cb0ef41Sopenharmony_ci                                    base::VectorOf(code_table_));
4901cb0ef41Sopenharmony_ci  size_t measured_size = kHeaderSize + serializer.Measure();
4911cb0ef41Sopenharmony_ci  if (buffer.size() < measured_size) return false;
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  Writer writer(buffer);
4941cb0ef41Sopenharmony_ci  WriteHeader(&writer);
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci  if (!serializer.Write(&writer)) return false;
4971cb0ef41Sopenharmony_ci  DCHECK_EQ(measured_size, writer.bytes_written());
4981cb0ef41Sopenharmony_ci  return true;
4991cb0ef41Sopenharmony_ci}
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_cistruct DeserializationUnit {
5021cb0ef41Sopenharmony_ci  base::Vector<const byte> src_code_buffer;
5031cb0ef41Sopenharmony_ci  std::unique_ptr<WasmCode> code;
5041cb0ef41Sopenharmony_ci  NativeModule::JumpTablesRef jump_tables;
5051cb0ef41Sopenharmony_ci};
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ciclass DeserializationQueue {
5081cb0ef41Sopenharmony_ci public:
5091cb0ef41Sopenharmony_ci  void Add(std::vector<DeserializationUnit> batch) {
5101cb0ef41Sopenharmony_ci    DCHECK(!batch.empty());
5111cb0ef41Sopenharmony_ci    base::MutexGuard guard(&mutex_);
5121cb0ef41Sopenharmony_ci    queue_.emplace(std::move(batch));
5131cb0ef41Sopenharmony_ci  }
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  std::vector<DeserializationUnit> Pop() {
5161cb0ef41Sopenharmony_ci    base::MutexGuard guard(&mutex_);
5171cb0ef41Sopenharmony_ci    if (queue_.empty()) return {};
5181cb0ef41Sopenharmony_ci    auto batch = std::move(queue_.front());
5191cb0ef41Sopenharmony_ci    queue_.pop();
5201cb0ef41Sopenharmony_ci    return batch;
5211cb0ef41Sopenharmony_ci  }
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ci  std::vector<DeserializationUnit> PopAll() {
5241cb0ef41Sopenharmony_ci    base::MutexGuard guard(&mutex_);
5251cb0ef41Sopenharmony_ci    if (queue_.empty()) return {};
5261cb0ef41Sopenharmony_ci    auto units = std::move(queue_.front());
5271cb0ef41Sopenharmony_ci    queue_.pop();
5281cb0ef41Sopenharmony_ci    while (!queue_.empty()) {
5291cb0ef41Sopenharmony_ci      units.insert(units.end(), std::make_move_iterator(queue_.front().begin()),
5301cb0ef41Sopenharmony_ci                   std::make_move_iterator(queue_.front().end()));
5311cb0ef41Sopenharmony_ci      queue_.pop();
5321cb0ef41Sopenharmony_ci    }
5331cb0ef41Sopenharmony_ci    return units;
5341cb0ef41Sopenharmony_ci  }
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci  size_t NumBatches() const {
5371cb0ef41Sopenharmony_ci    base::MutexGuard guard(&mutex_);
5381cb0ef41Sopenharmony_ci    return queue_.size();
5391cb0ef41Sopenharmony_ci  }
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci private:
5421cb0ef41Sopenharmony_ci  mutable base::Mutex mutex_;
5431cb0ef41Sopenharmony_ci  std::queue<std::vector<DeserializationUnit>> queue_;
5441cb0ef41Sopenharmony_ci};
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE NativeModuleDeserializer {
5471cb0ef41Sopenharmony_ci public:
5481cb0ef41Sopenharmony_ci  explicit NativeModuleDeserializer(NativeModule*);
5491cb0ef41Sopenharmony_ci  NativeModuleDeserializer(const NativeModuleDeserializer&) = delete;
5501cb0ef41Sopenharmony_ci  NativeModuleDeserializer& operator=(const NativeModuleDeserializer&) = delete;
5511cb0ef41Sopenharmony_ci
5521cb0ef41Sopenharmony_ci  bool Read(Reader* reader);
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  base::Vector<const int> lazy_functions() {
5551cb0ef41Sopenharmony_ci    return base::VectorOf(lazy_functions_);
5561cb0ef41Sopenharmony_ci  }
5571cb0ef41Sopenharmony_ci
5581cb0ef41Sopenharmony_ci  base::Vector<const int> liftoff_functions() {
5591cb0ef41Sopenharmony_ci    return base::VectorOf(liftoff_functions_);
5601cb0ef41Sopenharmony_ci  }
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ci private:
5631cb0ef41Sopenharmony_ci  friend class DeserializeCodeTask;
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  void ReadHeader(Reader* reader);
5661cb0ef41Sopenharmony_ci  DeserializationUnit ReadCode(int fn_index, Reader* reader);
5671cb0ef41Sopenharmony_ci  void CopyAndRelocate(const DeserializationUnit& unit);
5681cb0ef41Sopenharmony_ci  void Publish(std::vector<DeserializationUnit> batch);
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  NativeModule* const native_module_;
5711cb0ef41Sopenharmony_ci#ifdef DEBUG
5721cb0ef41Sopenharmony_ci  bool read_called_ = false;
5731cb0ef41Sopenharmony_ci#endif
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci  // Updated in {ReadCode}.
5761cb0ef41Sopenharmony_ci  size_t remaining_code_size_ = 0;
5771cb0ef41Sopenharmony_ci  base::Vector<byte> current_code_space_;
5781cb0ef41Sopenharmony_ci  NativeModule::JumpTablesRef current_jump_tables_;
5791cb0ef41Sopenharmony_ci  std::vector<int> lazy_functions_;
5801cb0ef41Sopenharmony_ci  std::vector<int> liftoff_functions_;
5811cb0ef41Sopenharmony_ci};
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ciclass DeserializeCodeTask : public JobTask {
5841cb0ef41Sopenharmony_ci public:
5851cb0ef41Sopenharmony_ci  DeserializeCodeTask(NativeModuleDeserializer* deserializer,
5861cb0ef41Sopenharmony_ci                      DeserializationQueue* reloc_queue)
5871cb0ef41Sopenharmony_ci      : deserializer_(deserializer), reloc_queue_(reloc_queue) {}
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ci  void Run(JobDelegate* delegate) override {
5901cb0ef41Sopenharmony_ci    CodeSpaceWriteScope code_space_write_scope(deserializer_->native_module_);
5911cb0ef41Sopenharmony_ci    do {
5921cb0ef41Sopenharmony_ci      // Repeatedly publish everything that was copied already.
5931cb0ef41Sopenharmony_ci      TryPublishing(delegate);
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci      auto batch = reloc_queue_->Pop();
5961cb0ef41Sopenharmony_ci      if (batch.empty()) break;
5971cb0ef41Sopenharmony_ci      for (const auto& unit : batch) {
5981cb0ef41Sopenharmony_ci        deserializer_->CopyAndRelocate(unit);
5991cb0ef41Sopenharmony_ci      }
6001cb0ef41Sopenharmony_ci      publish_queue_.Add(std::move(batch));
6011cb0ef41Sopenharmony_ci      delegate->NotifyConcurrencyIncrease();
6021cb0ef41Sopenharmony_ci    } while (!delegate->ShouldYield());
6031cb0ef41Sopenharmony_ci  }
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  size_t GetMaxConcurrency(size_t /* worker_count */) const override {
6061cb0ef41Sopenharmony_ci    // Number of copy&reloc batches, plus 1 if there is also something to
6071cb0ef41Sopenharmony_ci    // publish.
6081cb0ef41Sopenharmony_ci    bool publish = publishing_.load(std::memory_order_relaxed) == false &&
6091cb0ef41Sopenharmony_ci                   publish_queue_.NumBatches() > 0;
6101cb0ef41Sopenharmony_ci    return reloc_queue_->NumBatches() + (publish ? 1 : 0);
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci private:
6141cb0ef41Sopenharmony_ci  void TryPublishing(JobDelegate* delegate) {
6151cb0ef41Sopenharmony_ci    // Publishing is sequential, so only start publishing if no one else is.
6161cb0ef41Sopenharmony_ci    if (publishing_.exchange(true, std::memory_order_relaxed)) return;
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci    WasmCodeRefScope code_scope;
6191cb0ef41Sopenharmony_ci    while (true) {
6201cb0ef41Sopenharmony_ci      bool yield = false;
6211cb0ef41Sopenharmony_ci      while (!yield) {
6221cb0ef41Sopenharmony_ci        auto to_publish = publish_queue_.PopAll();
6231cb0ef41Sopenharmony_ci        if (to_publish.empty()) break;
6241cb0ef41Sopenharmony_ci        deserializer_->Publish(std::move(to_publish));
6251cb0ef41Sopenharmony_ci        yield = delegate->ShouldYield();
6261cb0ef41Sopenharmony_ci      }
6271cb0ef41Sopenharmony_ci      publishing_.store(false, std::memory_order_relaxed);
6281cb0ef41Sopenharmony_ci      if (yield) break;
6291cb0ef41Sopenharmony_ci      // After finishing publishing, check again if new work arrived in the mean
6301cb0ef41Sopenharmony_ci      // time. If so, continue publishing.
6311cb0ef41Sopenharmony_ci      if (publish_queue_.NumBatches() == 0) break;
6321cb0ef41Sopenharmony_ci      if (publishing_.exchange(true, std::memory_order_relaxed)) break;
6331cb0ef41Sopenharmony_ci      // We successfully reset {publishing_} from {false} to {true}.
6341cb0ef41Sopenharmony_ci    }
6351cb0ef41Sopenharmony_ci  }
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  NativeModuleDeserializer* const deserializer_;
6381cb0ef41Sopenharmony_ci  DeserializationQueue* const reloc_queue_;
6391cb0ef41Sopenharmony_ci  DeserializationQueue publish_queue_;
6401cb0ef41Sopenharmony_ci  std::atomic<bool> publishing_{false};
6411cb0ef41Sopenharmony_ci};
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ciNativeModuleDeserializer::NativeModuleDeserializer(NativeModule* native_module)
6441cb0ef41Sopenharmony_ci    : native_module_(native_module) {}
6451cb0ef41Sopenharmony_ci
6461cb0ef41Sopenharmony_cibool NativeModuleDeserializer::Read(Reader* reader) {
6471cb0ef41Sopenharmony_ci  DCHECK(!read_called_);
6481cb0ef41Sopenharmony_ci#ifdef DEBUG
6491cb0ef41Sopenharmony_ci  read_called_ = true;
6501cb0ef41Sopenharmony_ci#endif
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci  ReadHeader(reader);
6531cb0ef41Sopenharmony_ci  uint32_t total_fns = native_module_->num_functions();
6541cb0ef41Sopenharmony_ci  uint32_t first_wasm_fn = native_module_->num_imported_functions();
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  WasmCodeRefScope wasm_code_ref_scope;
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci  DeserializationQueue reloc_queue;
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_ci  std::unique_ptr<JobHandle> job_handle = V8::GetCurrentPlatform()->PostJob(
6611cb0ef41Sopenharmony_ci      TaskPriority::kUserVisible,
6621cb0ef41Sopenharmony_ci      std::make_unique<DeserializeCodeTask>(this, &reloc_queue));
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_ci  // Choose a batch size such that we do not create too small batches (>=100k
6651cb0ef41Sopenharmony_ci  // code bytes), but also not too many (<=100 batches).
6661cb0ef41Sopenharmony_ci  constexpr size_t kMinBatchSizeInBytes = 100000;
6671cb0ef41Sopenharmony_ci  size_t batch_limit =
6681cb0ef41Sopenharmony_ci      std::max(kMinBatchSizeInBytes, remaining_code_size_ / 100);
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci  std::vector<DeserializationUnit> batch;
6711cb0ef41Sopenharmony_ci  size_t batch_size = 0;
6721cb0ef41Sopenharmony_ci  CodeSpaceWriteScope code_space_write_scope(native_module_);
6731cb0ef41Sopenharmony_ci  for (uint32_t i = first_wasm_fn; i < total_fns; ++i) {
6741cb0ef41Sopenharmony_ci    DeserializationUnit unit = ReadCode(i, reader);
6751cb0ef41Sopenharmony_ci    if (!unit.code) continue;
6761cb0ef41Sopenharmony_ci    batch_size += unit.code->instructions().size();
6771cb0ef41Sopenharmony_ci    batch.emplace_back(std::move(unit));
6781cb0ef41Sopenharmony_ci    if (batch_size >= batch_limit) {
6791cb0ef41Sopenharmony_ci      reloc_queue.Add(std::move(batch));
6801cb0ef41Sopenharmony_ci      DCHECK(batch.empty());
6811cb0ef41Sopenharmony_ci      batch_size = 0;
6821cb0ef41Sopenharmony_ci      job_handle->NotifyConcurrencyIncrease();
6831cb0ef41Sopenharmony_ci    }
6841cb0ef41Sopenharmony_ci  }
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci  // We should have read the expected amount of code now, and should have fully
6871cb0ef41Sopenharmony_ci  // utilized the allocated code space.
6881cb0ef41Sopenharmony_ci  DCHECK_EQ(0, remaining_code_size_);
6891cb0ef41Sopenharmony_ci  DCHECK_EQ(0, current_code_space_.size());
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ci  if (!batch.empty()) {
6921cb0ef41Sopenharmony_ci    reloc_queue.Add(std::move(batch));
6931cb0ef41Sopenharmony_ci    job_handle->NotifyConcurrencyIncrease();
6941cb0ef41Sopenharmony_ci  }
6951cb0ef41Sopenharmony_ci
6961cb0ef41Sopenharmony_ci  // Wait for all tasks to finish, while participating in their work.
6971cb0ef41Sopenharmony_ci  job_handle->Join();
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ci  return reader->current_size() == 0;
7001cb0ef41Sopenharmony_ci}
7011cb0ef41Sopenharmony_ci
7021cb0ef41Sopenharmony_civoid NativeModuleDeserializer::ReadHeader(Reader* reader) {
7031cb0ef41Sopenharmony_ci  remaining_code_size_ = reader->Read<size_t>();
7041cb0ef41Sopenharmony_ci}
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ciDeserializationUnit NativeModuleDeserializer::ReadCode(int fn_index,
7071cb0ef41Sopenharmony_ci                                                       Reader* reader) {
7081cb0ef41Sopenharmony_ci  uint8_t code_kind = reader->Read<uint8_t>();
7091cb0ef41Sopenharmony_ci  if (code_kind == kLazyFunction) {
7101cb0ef41Sopenharmony_ci    lazy_functions_.push_back(fn_index);
7111cb0ef41Sopenharmony_ci    return {};
7121cb0ef41Sopenharmony_ci  }
7131cb0ef41Sopenharmony_ci  if (code_kind == kLiftoffFunction) {
7141cb0ef41Sopenharmony_ci    liftoff_functions_.push_back(fn_index);
7151cb0ef41Sopenharmony_ci    return {};
7161cb0ef41Sopenharmony_ci  }
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci  int constant_pool_offset = reader->Read<int>();
7191cb0ef41Sopenharmony_ci  int safepoint_table_offset = reader->Read<int>();
7201cb0ef41Sopenharmony_ci  int handler_table_offset = reader->Read<int>();
7211cb0ef41Sopenharmony_ci  int code_comment_offset = reader->Read<int>();
7221cb0ef41Sopenharmony_ci  int unpadded_binary_size = reader->Read<int>();
7231cb0ef41Sopenharmony_ci  int stack_slot_count = reader->Read<int>();
7241cb0ef41Sopenharmony_ci  uint32_t tagged_parameter_slots = reader->Read<uint32_t>();
7251cb0ef41Sopenharmony_ci  int code_size = reader->Read<int>();
7261cb0ef41Sopenharmony_ci  int reloc_size = reader->Read<int>();
7271cb0ef41Sopenharmony_ci  int source_position_size = reader->Read<int>();
7281cb0ef41Sopenharmony_ci  int protected_instructions_size = reader->Read<int>();
7291cb0ef41Sopenharmony_ci  WasmCode::Kind kind = reader->Read<WasmCode::Kind>();
7301cb0ef41Sopenharmony_ci  ExecutionTier tier = reader->Read<ExecutionTier>();
7311cb0ef41Sopenharmony_ci
7321cb0ef41Sopenharmony_ci  DCHECK(IsAligned(code_size, kCodeAlignment));
7331cb0ef41Sopenharmony_ci  DCHECK_GE(remaining_code_size_, code_size);
7341cb0ef41Sopenharmony_ci  if (current_code_space_.size() < static_cast<size_t>(code_size)) {
7351cb0ef41Sopenharmony_ci    // Allocate the next code space. Don't allocate more than 90% of
7361cb0ef41Sopenharmony_ci    // {kMaxCodeSpaceSize}, to leave some space for jump tables.
7371cb0ef41Sopenharmony_ci    constexpr size_t kMaxReservation =
7381cb0ef41Sopenharmony_ci        RoundUp<kCodeAlignment>(WasmCodeAllocator::kMaxCodeSpaceSize * 9 / 10);
7391cb0ef41Sopenharmony_ci    size_t code_space_size = std::min(kMaxReservation, remaining_code_size_);
7401cb0ef41Sopenharmony_ci    std::tie(current_code_space_, current_jump_tables_) =
7411cb0ef41Sopenharmony_ci        native_module_->AllocateForDeserializedCode(code_space_size);
7421cb0ef41Sopenharmony_ci    DCHECK_EQ(current_code_space_.size(), code_space_size);
7431cb0ef41Sopenharmony_ci    DCHECK(current_jump_tables_.is_valid());
7441cb0ef41Sopenharmony_ci  }
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_ci  DeserializationUnit unit;
7471cb0ef41Sopenharmony_ci  unit.src_code_buffer = reader->ReadVector<byte>(code_size);
7481cb0ef41Sopenharmony_ci  auto reloc_info = reader->ReadVector<byte>(reloc_size);
7491cb0ef41Sopenharmony_ci  auto source_pos = reader->ReadVector<byte>(source_position_size);
7501cb0ef41Sopenharmony_ci  auto protected_instructions =
7511cb0ef41Sopenharmony_ci      reader->ReadVector<byte>(protected_instructions_size);
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci  base::Vector<uint8_t> instructions =
7541cb0ef41Sopenharmony_ci      current_code_space_.SubVector(0, code_size);
7551cb0ef41Sopenharmony_ci  current_code_space_ += code_size;
7561cb0ef41Sopenharmony_ci  remaining_code_size_ -= code_size;
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci  unit.code = native_module_->AddDeserializedCode(
7591cb0ef41Sopenharmony_ci      fn_index, instructions, stack_slot_count, tagged_parameter_slots,
7601cb0ef41Sopenharmony_ci      safepoint_table_offset, handler_table_offset, constant_pool_offset,
7611cb0ef41Sopenharmony_ci      code_comment_offset, unpadded_binary_size, protected_instructions,
7621cb0ef41Sopenharmony_ci      reloc_info, source_pos, kind, tier);
7631cb0ef41Sopenharmony_ci  unit.jump_tables = current_jump_tables_;
7641cb0ef41Sopenharmony_ci  return unit;
7651cb0ef41Sopenharmony_ci}
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_civoid NativeModuleDeserializer::CopyAndRelocate(
7681cb0ef41Sopenharmony_ci    const DeserializationUnit& unit) {
7691cb0ef41Sopenharmony_ci  memcpy(unit.code->instructions().begin(), unit.src_code_buffer.begin(),
7701cb0ef41Sopenharmony_ci         unit.src_code_buffer.size());
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci  // Relocate the code.
7731cb0ef41Sopenharmony_ci  int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
7741cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL) |
7751cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
7761cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
7771cb0ef41Sopenharmony_ci             RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
7781cb0ef41Sopenharmony_ci  for (RelocIterator iter(unit.code->instructions(), unit.code->reloc_info(),
7791cb0ef41Sopenharmony_ci                          unit.code->constant_pool(), mask);
7801cb0ef41Sopenharmony_ci       !iter.done(); iter.next()) {
7811cb0ef41Sopenharmony_ci    RelocInfo::Mode mode = iter.rinfo()->rmode();
7821cb0ef41Sopenharmony_ci    switch (mode) {
7831cb0ef41Sopenharmony_ci      case RelocInfo::WASM_CALL: {
7841cb0ef41Sopenharmony_ci        uint32_t tag = GetWasmCalleeTag(iter.rinfo());
7851cb0ef41Sopenharmony_ci        Address target =
7861cb0ef41Sopenharmony_ci            native_module_->GetNearCallTargetForFunction(tag, unit.jump_tables);
7871cb0ef41Sopenharmony_ci        iter.rinfo()->set_wasm_call_address(target, SKIP_ICACHE_FLUSH);
7881cb0ef41Sopenharmony_ci        break;
7891cb0ef41Sopenharmony_ci      }
7901cb0ef41Sopenharmony_ci      case RelocInfo::WASM_STUB_CALL: {
7911cb0ef41Sopenharmony_ci        uint32_t tag = GetWasmCalleeTag(iter.rinfo());
7921cb0ef41Sopenharmony_ci        DCHECK_LT(tag, WasmCode::kRuntimeStubCount);
7931cb0ef41Sopenharmony_ci        Address target = native_module_->GetNearRuntimeStubEntry(
7941cb0ef41Sopenharmony_ci            static_cast<WasmCode::RuntimeStubId>(tag), unit.jump_tables);
7951cb0ef41Sopenharmony_ci        iter.rinfo()->set_wasm_stub_call_address(target, SKIP_ICACHE_FLUSH);
7961cb0ef41Sopenharmony_ci        break;
7971cb0ef41Sopenharmony_ci      }
7981cb0ef41Sopenharmony_ci      case RelocInfo::EXTERNAL_REFERENCE: {
7991cb0ef41Sopenharmony_ci        uint32_t tag = GetWasmCalleeTag(iter.rinfo());
8001cb0ef41Sopenharmony_ci        Address address = ExternalReferenceList::Get().address_from_tag(tag);
8011cb0ef41Sopenharmony_ci        iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH);
8021cb0ef41Sopenharmony_ci        break;
8031cb0ef41Sopenharmony_ci      }
8041cb0ef41Sopenharmony_ci      case RelocInfo::INTERNAL_REFERENCE:
8051cb0ef41Sopenharmony_ci      case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
8061cb0ef41Sopenharmony_ci        Address offset = iter.rinfo()->target_internal_reference();
8071cb0ef41Sopenharmony_ci        Address target = unit.code->instruction_start() + offset;
8081cb0ef41Sopenharmony_ci        Assembler::deserialization_set_target_internal_reference_at(
8091cb0ef41Sopenharmony_ci            iter.rinfo()->pc(), target, mode);
8101cb0ef41Sopenharmony_ci        break;
8111cb0ef41Sopenharmony_ci      }
8121cb0ef41Sopenharmony_ci      default:
8131cb0ef41Sopenharmony_ci        UNREACHABLE();
8141cb0ef41Sopenharmony_ci    }
8151cb0ef41Sopenharmony_ci  }
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ci  // Finally, flush the icache for that code.
8181cb0ef41Sopenharmony_ci  FlushInstructionCache(unit.code->instructions().begin(),
8191cb0ef41Sopenharmony_ci                        unit.code->instructions().size());
8201cb0ef41Sopenharmony_ci}
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_civoid NativeModuleDeserializer::Publish(std::vector<DeserializationUnit> batch) {
8231cb0ef41Sopenharmony_ci  DCHECK(!batch.empty());
8241cb0ef41Sopenharmony_ci  std::vector<std::unique_ptr<WasmCode>> codes;
8251cb0ef41Sopenharmony_ci  codes.reserve(batch.size());
8261cb0ef41Sopenharmony_ci  for (auto& unit : batch) {
8271cb0ef41Sopenharmony_ci    codes.emplace_back(std::move(unit).code);
8281cb0ef41Sopenharmony_ci  }
8291cb0ef41Sopenharmony_ci  auto published_codes = native_module_->PublishCode(base::VectorOf(codes));
8301cb0ef41Sopenharmony_ci  for (auto* wasm_code : published_codes) {
8311cb0ef41Sopenharmony_ci    wasm_code->MaybePrint();
8321cb0ef41Sopenharmony_ci    wasm_code->Validate();
8331cb0ef41Sopenharmony_ci  }
8341cb0ef41Sopenharmony_ci}
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_cibool IsSupportedVersion(base::Vector<const byte> header) {
8371cb0ef41Sopenharmony_ci  if (header.size() < WasmSerializer::kHeaderSize) return false;
8381cb0ef41Sopenharmony_ci  byte current_version[WasmSerializer::kHeaderSize];
8391cb0ef41Sopenharmony_ci  Writer writer({current_version, WasmSerializer::kHeaderSize});
8401cb0ef41Sopenharmony_ci  WriteHeader(&writer);
8411cb0ef41Sopenharmony_ci  return memcmp(header.begin(), current_version, WasmSerializer::kHeaderSize) ==
8421cb0ef41Sopenharmony_ci         0;
8431cb0ef41Sopenharmony_ci}
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_ciMaybeHandle<WasmModuleObject> DeserializeNativeModule(
8461cb0ef41Sopenharmony_ci    Isolate* isolate, base::Vector<const byte> data,
8471cb0ef41Sopenharmony_ci    base::Vector<const byte> wire_bytes_vec,
8481cb0ef41Sopenharmony_ci    base::Vector<const char> source_url) {
8491cb0ef41Sopenharmony_ci  if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) return {};
8501cb0ef41Sopenharmony_ci  if (!IsSupportedVersion(data)) return {};
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_ci  // Make the copy of the wire bytes early, so we use the same memory for
8531cb0ef41Sopenharmony_ci  // decoding, lookup in the native module cache, and insertion into the cache.
8541cb0ef41Sopenharmony_ci  auto owned_wire_bytes = base::OwnedVector<uint8_t>::Of(wire_bytes_vec);
8551cb0ef41Sopenharmony_ci
8561cb0ef41Sopenharmony_ci  // TODO(titzer): module features should be part of the serialization format.
8571cb0ef41Sopenharmony_ci  WasmEngine* wasm_engine = GetWasmEngine();
8581cb0ef41Sopenharmony_ci  WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
8591cb0ef41Sopenharmony_ci  ModuleResult decode_result = DecodeWasmModule(
8601cb0ef41Sopenharmony_ci      enabled_features, owned_wire_bytes.start(), owned_wire_bytes.end(), false,
8611cb0ef41Sopenharmony_ci      i::wasm::kWasmOrigin, isolate->counters(), isolate->metrics_recorder(),
8621cb0ef41Sopenharmony_ci      isolate->GetOrRegisterRecorderContextId(isolate->native_context()),
8631cb0ef41Sopenharmony_ci      DecodingMethod::kDeserialize, wasm_engine->allocator());
8641cb0ef41Sopenharmony_ci  if (decode_result.failed()) return {};
8651cb0ef41Sopenharmony_ci  std::shared_ptr<WasmModule> module = std::move(decode_result).value();
8661cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(module);
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci  auto shared_native_module = wasm_engine->MaybeGetNativeModule(
8691cb0ef41Sopenharmony_ci      module->origin, owned_wire_bytes.as_vector(), isolate);
8701cb0ef41Sopenharmony_ci  if (shared_native_module == nullptr) {
8711cb0ef41Sopenharmony_ci    DynamicTiering dynamic_tiering = isolate->IsWasmDynamicTieringEnabled()
8721cb0ef41Sopenharmony_ci                                         ? DynamicTiering::kEnabled
8731cb0ef41Sopenharmony_ci                                         : DynamicTiering::kDisabled;
8741cb0ef41Sopenharmony_ci    const bool kIncludeLiftoff = dynamic_tiering == DynamicTiering::kDisabled;
8751cb0ef41Sopenharmony_ci    size_t code_size_estimate =
8761cb0ef41Sopenharmony_ci        wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
8771cb0ef41Sopenharmony_ci            module.get(), kIncludeLiftoff, dynamic_tiering);
8781cb0ef41Sopenharmony_ci    shared_native_module = wasm_engine->NewNativeModule(
8791cb0ef41Sopenharmony_ci        isolate, enabled_features, std::move(module), code_size_estimate);
8801cb0ef41Sopenharmony_ci    // We have to assign a compilation ID here, as it is required for a
8811cb0ef41Sopenharmony_ci    // potential re-compilation, e.g. triggered by
8821cb0ef41Sopenharmony_ci    // {TierDownAllModulesPerIsolate}. The value is -2 so that it is different
8831cb0ef41Sopenharmony_ci    // than the compilation ID of actual compilations, and also different than
8841cb0ef41Sopenharmony_ci    // the sentinel value of the CompilationState.
8851cb0ef41Sopenharmony_ci    shared_native_module->compilation_state()->set_compilation_id(-2);
8861cb0ef41Sopenharmony_ci    shared_native_module->SetWireBytes(std::move(owned_wire_bytes));
8871cb0ef41Sopenharmony_ci
8881cb0ef41Sopenharmony_ci    NativeModuleDeserializer deserializer(shared_native_module.get());
8891cb0ef41Sopenharmony_ci    Reader reader(data + WasmSerializer::kHeaderSize);
8901cb0ef41Sopenharmony_ci    bool error = !deserializer.Read(&reader);
8911cb0ef41Sopenharmony_ci    if (error) {
8921cb0ef41Sopenharmony_ci      wasm_engine->UpdateNativeModuleCache(error, &shared_native_module,
8931cb0ef41Sopenharmony_ci                                           isolate);
8941cb0ef41Sopenharmony_ci      return {};
8951cb0ef41Sopenharmony_ci    }
8961cb0ef41Sopenharmony_ci    shared_native_module->compilation_state()->InitializeAfterDeserialization(
8971cb0ef41Sopenharmony_ci        deserializer.lazy_functions(), deserializer.liftoff_functions());
8981cb0ef41Sopenharmony_ci    wasm_engine->UpdateNativeModuleCache(error, &shared_native_module, isolate);
8991cb0ef41Sopenharmony_ci  }
9001cb0ef41Sopenharmony_ci
9011cb0ef41Sopenharmony_ci  Handle<FixedArray> export_wrappers;
9021cb0ef41Sopenharmony_ci  CompileJsToWasmWrappers(isolate, shared_native_module->module(),
9031cb0ef41Sopenharmony_ci                          &export_wrappers);
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci  Handle<Script> script =
9061cb0ef41Sopenharmony_ci      wasm_engine->GetOrCreateScript(isolate, shared_native_module, source_url);
9071cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module_object = WasmModuleObject::New(
9081cb0ef41Sopenharmony_ci      isolate, shared_native_module, script, export_wrappers);
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci  // Finish the Wasm script now and make it public to the debugger.
9111cb0ef41Sopenharmony_ci  isolate->debug()->OnAfterCompile(script);
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_ci  // Log the code within the generated module for profiling.
9141cb0ef41Sopenharmony_ci  shared_native_module->LogWasmCodes(isolate, *script);
9151cb0ef41Sopenharmony_ci
9161cb0ef41Sopenharmony_ci  return module_object;
9171cb0ef41Sopenharmony_ci}
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci}  // namespace wasm
9201cb0ef41Sopenharmony_ci}  // namespace internal
9211cb0ef41Sopenharmony_ci}  // namespace v8
922