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