11cb0ef41Sopenharmony_ci// Copyright 2015 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-objects.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/base/iterator.h" 81cb0ef41Sopenharmony_ci#include "src/base/vector.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/wasm-compiler.h" 121cb0ef41Sopenharmony_ci#include "src/debug/debug-interface.h" 131cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 141cb0ef41Sopenharmony_ci#include "src/objects/debug-objects-inl.h" 151cb0ef41Sopenharmony_ci#include "src/objects/managed-inl.h" 161cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 171cb0ef41Sopenharmony_ci#include "src/objects/shared-function-info.h" 181cb0ef41Sopenharmony_ci#include "src/objects/struct-inl.h" 191cb0ef41Sopenharmony_ci#include "src/trap-handler/trap-handler.h" 201cb0ef41Sopenharmony_ci#include "src/utils/utils.h" 211cb0ef41Sopenharmony_ci#include "src/wasm/code-space-access.h" 221cb0ef41Sopenharmony_ci#include "src/wasm/jump-table-assembler.h" 231cb0ef41Sopenharmony_ci#include "src/wasm/module-compiler.h" 241cb0ef41Sopenharmony_ci#include "src/wasm/module-decoder.h" 251cb0ef41Sopenharmony_ci#include "src/wasm/module-instantiate.h" 261cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h" 271cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h" 281cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h" 291cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h" 301cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h" 311cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h" 321cb0ef41Sopenharmony_ci#include "src/wasm/wasm-subtyping.h" 331cb0ef41Sopenharmony_ci#include "src/wasm/wasm-value.h" 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#define TRACE_IFT(...) \ 361cb0ef41Sopenharmony_ci do { \ 371cb0ef41Sopenharmony_ci if (false) PrintF(__VA_ARGS__); \ 381cb0ef41Sopenharmony_ci } while (false) 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cinamespace v8 { 411cb0ef41Sopenharmony_cinamespace internal { 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci// Import a few often used types from the wasm namespace. 441cb0ef41Sopenharmony_ciusing WasmFunction = wasm::WasmFunction; 451cb0ef41Sopenharmony_ciusing WasmModule = wasm::WasmModule; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_cinamespace { 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci// Manages the natively-allocated memory for a WasmInstanceObject. Since 501cb0ef41Sopenharmony_ci// an instance finalizer is not guaranteed to run upon isolate shutdown, 511cb0ef41Sopenharmony_ci// we must use a Managed<WasmInstanceNativeAllocations> to guarantee 521cb0ef41Sopenharmony_ci// it is freed. 531cb0ef41Sopenharmony_ciclass WasmInstanceNativeAllocations { 541cb0ef41Sopenharmony_ci public: 551cb0ef41Sopenharmony_ci WasmInstanceNativeAllocations(Handle<WasmInstanceObject> instance, 561cb0ef41Sopenharmony_ci size_t num_imported_functions, 571cb0ef41Sopenharmony_ci size_t num_imported_mutable_globals, 581cb0ef41Sopenharmony_ci size_t num_data_segments, 591cb0ef41Sopenharmony_ci size_t num_elem_segments) 601cb0ef41Sopenharmony_ci : imported_function_targets_(new Address[num_imported_functions]), 611cb0ef41Sopenharmony_ci imported_mutable_globals_(new Address[num_imported_mutable_globals]), 621cb0ef41Sopenharmony_ci data_segment_starts_(new Address[num_data_segments]), 631cb0ef41Sopenharmony_ci data_segment_sizes_(new uint32_t[num_data_segments]), 641cb0ef41Sopenharmony_ci dropped_elem_segments_(new uint8_t[num_elem_segments]) { 651cb0ef41Sopenharmony_ci instance->set_imported_function_targets(imported_function_targets_.get()); 661cb0ef41Sopenharmony_ci instance->set_imported_mutable_globals(imported_mutable_globals_.get()); 671cb0ef41Sopenharmony_ci instance->set_data_segment_starts(data_segment_starts_.get()); 681cb0ef41Sopenharmony_ci instance->set_data_segment_sizes(data_segment_sizes_.get()); 691cb0ef41Sopenharmony_ci instance->set_dropped_elem_segments(dropped_elem_segments_.get()); 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci private: 731cb0ef41Sopenharmony_ci const std::unique_ptr<Address[]> imported_function_targets_; 741cb0ef41Sopenharmony_ci const std::unique_ptr<Address[]> imported_mutable_globals_; 751cb0ef41Sopenharmony_ci const std::unique_ptr<Address[]> data_segment_starts_; 761cb0ef41Sopenharmony_ci const std::unique_ptr<uint32_t[]> data_segment_sizes_; 771cb0ef41Sopenharmony_ci const std::unique_ptr<uint8_t[]> dropped_elem_segments_; 781cb0ef41Sopenharmony_ci}; 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_cisize_t EstimateNativeAllocationsSize(const WasmModule* module) { 811cb0ef41Sopenharmony_ci size_t estimate = 821cb0ef41Sopenharmony_ci sizeof(WasmInstanceNativeAllocations) + 831cb0ef41Sopenharmony_ci (1 * kSystemPointerSize * module->num_imported_mutable_globals) + 841cb0ef41Sopenharmony_ci (2 * kSystemPointerSize * module->num_imported_functions) + 851cb0ef41Sopenharmony_ci ((kSystemPointerSize + sizeof(uint32_t) + sizeof(uint8_t)) * 861cb0ef41Sopenharmony_ci module->num_declared_data_segments); 871cb0ef41Sopenharmony_ci return estimate; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_cienum DispatchTableElements : int { 911cb0ef41Sopenharmony_ci kDispatchTableInstanceOffset, 921cb0ef41Sopenharmony_ci kDispatchTableIndexOffset, 931cb0ef41Sopenharmony_ci // Marker: 941cb0ef41Sopenharmony_ci kDispatchTableNumElements 951cb0ef41Sopenharmony_ci}; 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci} // namespace 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci// static 1001cb0ef41Sopenharmony_ciHandle<WasmModuleObject> WasmModuleObject::New( 1011cb0ef41Sopenharmony_ci Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module, 1021cb0ef41Sopenharmony_ci Handle<Script> script) { 1031cb0ef41Sopenharmony_ci Handle<FixedArray> export_wrappers = isolate->factory()->NewFixedArray(0); 1041cb0ef41Sopenharmony_ci return New(isolate, std::move(native_module), script, export_wrappers); 1051cb0ef41Sopenharmony_ci} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci// static 1081cb0ef41Sopenharmony_ciHandle<WasmModuleObject> WasmModuleObject::New( 1091cb0ef41Sopenharmony_ci Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module, 1101cb0ef41Sopenharmony_ci Handle<Script> script, Handle<FixedArray> export_wrappers) { 1111cb0ef41Sopenharmony_ci Handle<Managed<wasm::NativeModule>> managed_native_module; 1121cb0ef41Sopenharmony_ci if (script->type() == Script::TYPE_WASM) { 1131cb0ef41Sopenharmony_ci managed_native_module = handle( 1141cb0ef41Sopenharmony_ci Managed<wasm::NativeModule>::cast(script->wasm_managed_native_module()), 1151cb0ef41Sopenharmony_ci isolate); 1161cb0ef41Sopenharmony_ci } else { 1171cb0ef41Sopenharmony_ci const WasmModule* module = native_module->module(); 1181cb0ef41Sopenharmony_ci size_t memory_estimate = 1191cb0ef41Sopenharmony_ci native_module->committed_code_space() + 1201cb0ef41Sopenharmony_ci wasm::WasmCodeManager::EstimateNativeModuleMetaDataSize(module); 1211cb0ef41Sopenharmony_ci managed_native_module = Managed<wasm::NativeModule>::FromSharedPtr( 1221cb0ef41Sopenharmony_ci isolate, memory_estimate, std::move(native_module)); 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast( 1251cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(isolate->wasm_module_constructor())); 1261cb0ef41Sopenharmony_ci module_object->set_export_wrappers(*export_wrappers); 1271cb0ef41Sopenharmony_ci module_object->set_managed_native_module(*managed_native_module); 1281cb0ef41Sopenharmony_ci module_object->set_script(*script); 1291cb0ef41Sopenharmony_ci return module_object; 1301cb0ef41Sopenharmony_ci} 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ciHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes( 1331cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmModuleObject> module_object, 1341cb0ef41Sopenharmony_ci wasm::WireBytesRef ref, InternalizeString internalize) { 1351cb0ef41Sopenharmony_ci base::Vector<const uint8_t> wire_bytes = 1361cb0ef41Sopenharmony_ci module_object->native_module()->wire_bytes(); 1371cb0ef41Sopenharmony_ci return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref, 1381cb0ef41Sopenharmony_ci internalize); 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ciHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes( 1421cb0ef41Sopenharmony_ci Isolate* isolate, base::Vector<const uint8_t> wire_bytes, 1431cb0ef41Sopenharmony_ci wasm::WireBytesRef ref, InternalizeString internalize) { 1441cb0ef41Sopenharmony_ci base::Vector<const uint8_t> name_vec = 1451cb0ef41Sopenharmony_ci wire_bytes.SubVector(ref.offset(), ref.end_offset()); 1461cb0ef41Sopenharmony_ci // UTF8 validation happens at decode time. 1471cb0ef41Sopenharmony_ci DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.begin(), name_vec.length())); 1481cb0ef41Sopenharmony_ci auto* factory = isolate->factory(); 1491cb0ef41Sopenharmony_ci return internalize 1501cb0ef41Sopenharmony_ci ? factory->InternalizeUtf8String( 1511cb0ef41Sopenharmony_ci base::Vector<const char>::cast(name_vec)) 1521cb0ef41Sopenharmony_ci : factory 1531cb0ef41Sopenharmony_ci ->NewStringFromUtf8(base::Vector<const char>::cast(name_vec)) 1541cb0ef41Sopenharmony_ci .ToHandleChecked(); 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ciMaybeHandle<String> WasmModuleObject::GetModuleNameOrNull( 1581cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmModuleObject> module_object) { 1591cb0ef41Sopenharmony_ci const WasmModule* module = module_object->module(); 1601cb0ef41Sopenharmony_ci if (!module->name.is_set()) return {}; 1611cb0ef41Sopenharmony_ci return ExtractUtf8StringFromModuleBytes(isolate, module_object, module->name, 1621cb0ef41Sopenharmony_ci kNoInternalize); 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ciMaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull( 1661cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmModuleObject> module_object, 1671cb0ef41Sopenharmony_ci uint32_t func_index) { 1681cb0ef41Sopenharmony_ci DCHECK_LT(func_index, module_object->module()->functions.size()); 1691cb0ef41Sopenharmony_ci wasm::WireBytesRef name = 1701cb0ef41Sopenharmony_ci module_object->module()->lazily_generated_names.LookupFunctionName( 1711cb0ef41Sopenharmony_ci wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()), 1721cb0ef41Sopenharmony_ci func_index); 1731cb0ef41Sopenharmony_ci if (!name.is_set()) return {}; 1741cb0ef41Sopenharmony_ci return ExtractUtf8StringFromModuleBytes(isolate, module_object, name, 1751cb0ef41Sopenharmony_ci kNoInternalize); 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_cibase::Vector<const uint8_t> WasmModuleObject::GetRawFunctionName( 1791cb0ef41Sopenharmony_ci int func_index) { 1801cb0ef41Sopenharmony_ci if (func_index == wasm::kAnonymousFuncIndex) { 1811cb0ef41Sopenharmony_ci return base::Vector<const uint8_t>({nullptr, 0}); 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci DCHECK_GT(module()->functions.size(), func_index); 1841cb0ef41Sopenharmony_ci wasm::ModuleWireBytes wire_bytes(native_module()->wire_bytes()); 1851cb0ef41Sopenharmony_ci wasm::WireBytesRef name_ref = 1861cb0ef41Sopenharmony_ci module()->lazily_generated_names.LookupFunctionName(wire_bytes, 1871cb0ef41Sopenharmony_ci func_index); 1881cb0ef41Sopenharmony_ci wasm::WasmName name = wire_bytes.GetNameOrNull(name_ref); 1891cb0ef41Sopenharmony_ci return base::Vector<const uint8_t>::cast(name); 1901cb0ef41Sopenharmony_ci} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ciHandle<WasmTableObject> WasmTableObject::New( 1931cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, wasm::ValueType type, 1941cb0ef41Sopenharmony_ci uint32_t initial, bool has_maximum, uint32_t maximum, 1951cb0ef41Sopenharmony_ci Handle<FixedArray>* entries, Handle<Object> initial_value) { 1961cb0ef41Sopenharmony_ci // TODO(7748): Make this work with other types when spec clears up. 1971cb0ef41Sopenharmony_ci { 1981cb0ef41Sopenharmony_ci const WasmModule* module = 1991cb0ef41Sopenharmony_ci instance.is_null() ? nullptr : instance->module(); 2001cb0ef41Sopenharmony_ci CHECK(wasm::WasmTable::IsValidTableType(type, module)); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(initial); 2041cb0ef41Sopenharmony_ci for (int i = 0; i < static_cast<int>(initial); ++i) { 2051cb0ef41Sopenharmony_ci backing_store->set(i, *initial_value); 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci Handle<Object> max; 2091cb0ef41Sopenharmony_ci if (has_maximum) { 2101cb0ef41Sopenharmony_ci max = isolate->factory()->NewNumberFromUint(maximum); 2111cb0ef41Sopenharmony_ci } else { 2121cb0ef41Sopenharmony_ci max = isolate->factory()->undefined_value(); 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci Handle<JSFunction> table_ctor( 2161cb0ef41Sopenharmony_ci isolate->native_context()->wasm_table_constructor(), isolate); 2171cb0ef41Sopenharmony_ci auto table_obj = Handle<WasmTableObject>::cast( 2181cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(table_ctor)); 2191cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci if (!instance.is_null()) table_obj->set_instance(*instance); 2221cb0ef41Sopenharmony_ci table_obj->set_entries(*backing_store); 2231cb0ef41Sopenharmony_ci table_obj->set_current_length(initial); 2241cb0ef41Sopenharmony_ci table_obj->set_maximum_length(*max); 2251cb0ef41Sopenharmony_ci table_obj->set_raw_type(static_cast<int>(type.raw_bit_field())); 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array()); 2281cb0ef41Sopenharmony_ci if (entries != nullptr) { 2291cb0ef41Sopenharmony_ci *entries = backing_store; 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci return Handle<WasmTableObject>::cast(table_obj); 2321cb0ef41Sopenharmony_ci} 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_civoid WasmTableObject::AddDispatchTable(Isolate* isolate, 2351cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_obj, 2361cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 2371cb0ef41Sopenharmony_ci int table_index) { 2381cb0ef41Sopenharmony_ci Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables(), isolate); 2391cb0ef41Sopenharmony_ci int old_length = dispatch_tables->length(); 2401cb0ef41Sopenharmony_ci DCHECK_EQ(0, old_length % kDispatchTableNumElements); 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci if (instance.is_null()) return; 2431cb0ef41Sopenharmony_ci // TODO(titzer): use weak cells here to avoid leaking instances. 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci // Grow the dispatch table and add a new entry at the end. 2461cb0ef41Sopenharmony_ci Handle<FixedArray> new_dispatch_tables = 2471cb0ef41Sopenharmony_ci isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 2481cb0ef41Sopenharmony_ci kDispatchTableNumElements); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci new_dispatch_tables->set(old_length + kDispatchTableInstanceOffset, 2511cb0ef41Sopenharmony_ci *instance); 2521cb0ef41Sopenharmony_ci new_dispatch_tables->set(old_length + kDispatchTableIndexOffset, 2531cb0ef41Sopenharmony_ci Smi::FromInt(table_index)); 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci table_obj->set_dispatch_tables(*new_dispatch_tables); 2561cb0ef41Sopenharmony_ci} 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ciint WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table, 2591cb0ef41Sopenharmony_ci uint32_t count, Handle<Object> init_value) { 2601cb0ef41Sopenharmony_ci uint32_t old_size = table->current_length(); 2611cb0ef41Sopenharmony_ci if (count == 0) return old_size; // Degenerate case: nothing to do. 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci // Check if growing by {count} is valid. 2641cb0ef41Sopenharmony_ci uint32_t max_size; 2651cb0ef41Sopenharmony_ci if (!table->maximum_length().ToUint32(&max_size)) { 2661cb0ef41Sopenharmony_ci max_size = FLAG_wasm_max_table_size; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci max_size = std::min(max_size, FLAG_wasm_max_table_size); 2691cb0ef41Sopenharmony_ci DCHECK_LE(old_size, max_size); 2701cb0ef41Sopenharmony_ci if (max_size - old_size < count) return -1; 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci uint32_t new_size = old_size + count; 2731cb0ef41Sopenharmony_ci // Even with 2x over-allocation, there should not be an integer overflow. 2741cb0ef41Sopenharmony_ci STATIC_ASSERT(wasm::kV8MaxWasmTableSize <= kMaxInt / 2); 2751cb0ef41Sopenharmony_ci DCHECK_GE(kMaxInt, new_size); 2761cb0ef41Sopenharmony_ci int old_capacity = table->entries().length(); 2771cb0ef41Sopenharmony_ci if (new_size > static_cast<uint32_t>(old_capacity)) { 2781cb0ef41Sopenharmony_ci int grow = static_cast<int>(new_size) - old_capacity; 2791cb0ef41Sopenharmony_ci // Grow at least by the old capacity, to implement exponential growing. 2801cb0ef41Sopenharmony_ci grow = std::max(grow, old_capacity); 2811cb0ef41Sopenharmony_ci // Never grow larger than the max size. 2821cb0ef41Sopenharmony_ci grow = std::min(grow, static_cast<int>(max_size - old_capacity)); 2831cb0ef41Sopenharmony_ci auto new_store = isolate->factory()->CopyFixedArrayAndGrow( 2841cb0ef41Sopenharmony_ci handle(table->entries(), isolate), grow); 2851cb0ef41Sopenharmony_ci table->set_entries(*new_store, WriteBarrierMode::UPDATE_WRITE_BARRIER); 2861cb0ef41Sopenharmony_ci } 2871cb0ef41Sopenharmony_ci table->set_current_length(new_size); 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); 2901cb0ef41Sopenharmony_ci DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); 2911cb0ef41Sopenharmony_ci // Tables are stored in the instance object, no code patching is 2921cb0ef41Sopenharmony_ci // necessary. We simply have to grow the raw tables in each instance 2931cb0ef41Sopenharmony_ci // that has imported this table. 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci // TODO(titzer): replace the dispatch table with a weak list of all 2961cb0ef41Sopenharmony_ci // the instances that import a given table. 2971cb0ef41Sopenharmony_ci for (int i = 0; i < dispatch_tables->length(); 2981cb0ef41Sopenharmony_ci i += kDispatchTableNumElements) { 2991cb0ef41Sopenharmony_ci int table_index = 3001cb0ef41Sopenharmony_ci Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value(); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance( 3031cb0ef41Sopenharmony_ci WasmInstanceObject::cast(dispatch_tables->get(i)), isolate); 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci DCHECK_EQ(old_size, 3061cb0ef41Sopenharmony_ci instance->GetIndirectFunctionTable(isolate, table_index)->size()); 3071cb0ef41Sopenharmony_ci WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( 3081cb0ef41Sopenharmony_ci instance, table_index, new_size); 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci for (uint32_t entry = old_size; entry < new_size; ++entry) { 3121cb0ef41Sopenharmony_ci WasmTableObject::Set(isolate, table, entry, init_value); 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci return old_size; 3151cb0ef41Sopenharmony_ci} 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_cibool WasmTableObject::IsInBounds(Isolate* isolate, 3181cb0ef41Sopenharmony_ci Handle<WasmTableObject> table, 3191cb0ef41Sopenharmony_ci uint32_t entry_index) { 3201cb0ef41Sopenharmony_ci return entry_index < static_cast<uint32_t>(table->current_length()); 3211cb0ef41Sopenharmony_ci} 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_cibool WasmTableObject::IsValidElement(Isolate* isolate, 3241cb0ef41Sopenharmony_ci Handle<WasmTableObject> table, 3251cb0ef41Sopenharmony_ci Handle<Object> entry) { 3261cb0ef41Sopenharmony_ci const char* error_message; 3271cb0ef41Sopenharmony_ci const WasmModule* module = 3281cb0ef41Sopenharmony_ci !table->instance().IsUndefined() 3291cb0ef41Sopenharmony_ci ? WasmInstanceObject::cast(table->instance()).module() 3301cb0ef41Sopenharmony_ci : nullptr; 3311cb0ef41Sopenharmony_ci if (entry->IsWasmInternalFunction()) { 3321cb0ef41Sopenharmony_ci entry = 3331cb0ef41Sopenharmony_ci handle(Handle<WasmInternalFunction>::cast(entry)->external(), isolate); 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci return wasm::TypecheckJSObject(isolate, module, entry, table->type(), 3361cb0ef41Sopenharmony_ci &error_message); 3371cb0ef41Sopenharmony_ci} 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_civoid WasmTableObject::SetFunctionTableEntry(Isolate* isolate, 3401cb0ef41Sopenharmony_ci Handle<WasmTableObject> table, 3411cb0ef41Sopenharmony_ci Handle<FixedArray> entries, 3421cb0ef41Sopenharmony_ci int entry_index, 3431cb0ef41Sopenharmony_ci Handle<Object> entry) { 3441cb0ef41Sopenharmony_ci if (entry->IsNull(isolate)) { 3451cb0ef41Sopenharmony_ci ClearDispatchTables(isolate, table, entry_index); // Degenerate case. 3461cb0ef41Sopenharmony_ci entries->set(entry_index, ReadOnlyRoots(isolate).null_value()); 3471cb0ef41Sopenharmony_ci return; 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci Handle<Object> external = 3511cb0ef41Sopenharmony_ci handle(Handle<WasmInternalFunction>::cast(entry)->external(), isolate); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci if (WasmExportedFunction::IsWasmExportedFunction(*external)) { 3541cb0ef41Sopenharmony_ci auto exported_function = Handle<WasmExportedFunction>::cast(external); 3551cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> target_instance(exported_function->instance(), 3561cb0ef41Sopenharmony_ci isolate); 3571cb0ef41Sopenharmony_ci int func_index = exported_function->function_index(); 3581cb0ef41Sopenharmony_ci auto* wasm_function = &target_instance->module()->functions[func_index]; 3591cb0ef41Sopenharmony_ci UpdateDispatchTables(isolate, *table, entry_index, wasm_function, 3601cb0ef41Sopenharmony_ci *target_instance); 3611cb0ef41Sopenharmony_ci } else if (WasmJSFunction::IsWasmJSFunction(*external)) { 3621cb0ef41Sopenharmony_ci UpdateDispatchTables(isolate, table, entry_index, 3631cb0ef41Sopenharmony_ci Handle<WasmJSFunction>::cast(external)); 3641cb0ef41Sopenharmony_ci } else { 3651cb0ef41Sopenharmony_ci DCHECK(WasmCapiFunction::IsWasmCapiFunction(*external)); 3661cb0ef41Sopenharmony_ci UpdateDispatchTables(isolate, table, entry_index, 3671cb0ef41Sopenharmony_ci Handle<WasmCapiFunction>::cast(external)); 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci entries->set(entry_index, *entry); 3701cb0ef41Sopenharmony_ci} 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_civoid WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table, 3731cb0ef41Sopenharmony_ci uint32_t index, Handle<Object> entry) { 3741cb0ef41Sopenharmony_ci // Callers need to perform bounds checks, type check, and error handling. 3751cb0ef41Sopenharmony_ci DCHECK(IsInBounds(isolate, table, index)); 3761cb0ef41Sopenharmony_ci DCHECK(IsValidElement(isolate, table, entry)); 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci Handle<FixedArray> entries(table->entries(), isolate); 3791cb0ef41Sopenharmony_ci // The FixedArray is addressed with int's. 3801cb0ef41Sopenharmony_ci int entry_index = static_cast<int>(index); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci switch (table->type().heap_representation()) { 3831cb0ef41Sopenharmony_ci case wasm::HeapType::kAny: 3841cb0ef41Sopenharmony_ci entries->set(entry_index, *entry); 3851cb0ef41Sopenharmony_ci return; 3861cb0ef41Sopenharmony_ci case wasm::HeapType::kFunc: 3871cb0ef41Sopenharmony_ci SetFunctionTableEntry(isolate, table, entries, entry_index, entry); 3881cb0ef41Sopenharmony_ci return; 3891cb0ef41Sopenharmony_ci case wasm::HeapType::kEq: 3901cb0ef41Sopenharmony_ci case wasm::HeapType::kData: 3911cb0ef41Sopenharmony_ci case wasm::HeapType::kArray: 3921cb0ef41Sopenharmony_ci case wasm::HeapType::kI31: 3931cb0ef41Sopenharmony_ci // TODO(7748): Implement once we have struct/arrays/i31ref tables. 3941cb0ef41Sopenharmony_ci UNREACHABLE(); 3951cb0ef41Sopenharmony_ci case wasm::HeapType::kBottom: 3961cb0ef41Sopenharmony_ci UNREACHABLE(); 3971cb0ef41Sopenharmony_ci default: 3981cb0ef41Sopenharmony_ci DCHECK(!table->instance().IsUndefined()); 3991cb0ef41Sopenharmony_ci // TODO(7748): Relax this once we have struct/array/i31ref tables. 4001cb0ef41Sopenharmony_ci DCHECK(WasmInstanceObject::cast(table->instance()) 4011cb0ef41Sopenharmony_ci .module() 4021cb0ef41Sopenharmony_ci ->has_signature(table->type().ref_index())); 4031cb0ef41Sopenharmony_ci SetFunctionTableEntry(isolate, table, entries, entry_index, entry); 4041cb0ef41Sopenharmony_ci return; 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci} 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ciHandle<Object> WasmTableObject::Get(Isolate* isolate, 4091cb0ef41Sopenharmony_ci Handle<WasmTableObject> table, 4101cb0ef41Sopenharmony_ci uint32_t index) { 4111cb0ef41Sopenharmony_ci Handle<FixedArray> entries(table->entries(), isolate); 4121cb0ef41Sopenharmony_ci // Callers need to perform bounds checks and error handling. 4131cb0ef41Sopenharmony_ci DCHECK(IsInBounds(isolate, table, index)); 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci // The FixedArray is addressed with int's. 4161cb0ef41Sopenharmony_ci int entry_index = static_cast<int>(index); 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci Handle<Object> entry(entries->get(entry_index), isolate); 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci if (entry->IsNull(isolate)) { 4211cb0ef41Sopenharmony_ci return entry; 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci switch (table->type().heap_representation()) { 4251cb0ef41Sopenharmony_ci case wasm::HeapType::kAny: 4261cb0ef41Sopenharmony_ci return entry; 4271cb0ef41Sopenharmony_ci case wasm::HeapType::kFunc: 4281cb0ef41Sopenharmony_ci if (entry->IsWasmInternalFunction()) return entry; 4291cb0ef41Sopenharmony_ci break; 4301cb0ef41Sopenharmony_ci case wasm::HeapType::kEq: 4311cb0ef41Sopenharmony_ci case wasm::HeapType::kI31: 4321cb0ef41Sopenharmony_ci case wasm::HeapType::kData: 4331cb0ef41Sopenharmony_ci case wasm::HeapType::kArray: 4341cb0ef41Sopenharmony_ci // TODO(7748): Implement once we have a story for struct/arrays/i31ref in 4351cb0ef41Sopenharmony_ci // JS. 4361cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 4371cb0ef41Sopenharmony_ci case wasm::HeapType::kBottom: 4381cb0ef41Sopenharmony_ci UNREACHABLE(); 4391cb0ef41Sopenharmony_ci default: 4401cb0ef41Sopenharmony_ci DCHECK(!table->instance().IsUndefined()); 4411cb0ef41Sopenharmony_ci // TODO(7748): Relax this once we have struct/array/i31ref tables. 4421cb0ef41Sopenharmony_ci DCHECK(WasmInstanceObject::cast(table->instance()) 4431cb0ef41Sopenharmony_ci .module() 4441cb0ef41Sopenharmony_ci ->has_signature(table->type().ref_index())); 4451cb0ef41Sopenharmony_ci if (entry->IsWasmInternalFunction()) return entry; 4461cb0ef41Sopenharmony_ci break; 4471cb0ef41Sopenharmony_ci } 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ci // {entry} is not a valid entry in the table. It has to be a placeholder 4501cb0ef41Sopenharmony_ci // for lazy initialization. 4511cb0ef41Sopenharmony_ci Handle<Tuple2> tuple = Handle<Tuple2>::cast(entry); 4521cb0ef41Sopenharmony_ci auto instance = handle(WasmInstanceObject::cast(tuple->value1()), isolate); 4531cb0ef41Sopenharmony_ci int function_index = Smi::cast(tuple->value2()).value(); 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci // Check if we already compiled a wrapper for the function but did not store 4561cb0ef41Sopenharmony_ci // it in the table slot yet. 4571cb0ef41Sopenharmony_ci Handle<WasmInternalFunction> internal = 4581cb0ef41Sopenharmony_ci WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate, instance, 4591cb0ef41Sopenharmony_ci function_index); 4601cb0ef41Sopenharmony_ci entries->set(entry_index, *internal); 4611cb0ef41Sopenharmony_ci return internal; 4621cb0ef41Sopenharmony_ci} 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_civoid WasmTableObject::Fill(Isolate* isolate, Handle<WasmTableObject> table, 4651cb0ef41Sopenharmony_ci uint32_t start, Handle<Object> entry, 4661cb0ef41Sopenharmony_ci uint32_t count) { 4671cb0ef41Sopenharmony_ci // Bounds checks must be done by the caller. 4681cb0ef41Sopenharmony_ci DCHECK_LE(start, table->current_length()); 4691cb0ef41Sopenharmony_ci DCHECK_LE(count, table->current_length()); 4701cb0ef41Sopenharmony_ci DCHECK_LE(start + count, table->current_length()); 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 4731cb0ef41Sopenharmony_ci WasmTableObject::Set(isolate, table, start + i, entry); 4741cb0ef41Sopenharmony_ci } 4751cb0ef41Sopenharmony_ci} 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_civoid WasmTableObject::UpdateDispatchTables(Isolate* isolate, 4781cb0ef41Sopenharmony_ci WasmTableObject table, 4791cb0ef41Sopenharmony_ci int entry_index, 4801cb0ef41Sopenharmony_ci const wasm::WasmFunction* func, 4811cb0ef41Sopenharmony_ci WasmInstanceObject target_instance) { 4821cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci // We simply need to update the IFTs for each instance that imports 4851cb0ef41Sopenharmony_ci // this table. 4861cb0ef41Sopenharmony_ci FixedArray dispatch_tables = table.dispatch_tables(); 4871cb0ef41Sopenharmony_ci DCHECK_EQ(0, dispatch_tables.length() % kDispatchTableNumElements); 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci Object call_ref = 4901cb0ef41Sopenharmony_ci func->imported 4911cb0ef41Sopenharmony_ci // The function in the target instance was imported. Use its imports 4921cb0ef41Sopenharmony_ci // table, which contains a tuple needed by the import wrapper. 4931cb0ef41Sopenharmony_ci ? target_instance.imported_function_refs().get(func->func_index) 4941cb0ef41Sopenharmony_ci // For wasm functions, just pass the target instance. 4951cb0ef41Sopenharmony_ci : target_instance; 4961cb0ef41Sopenharmony_ci Address call_target = target_instance.GetCallTarget(func->func_index); 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci int original_sig_id = func->sig_index; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci for (int i = 0, len = dispatch_tables.length(); i < len; 5011cb0ef41Sopenharmony_ci i += kDispatchTableNumElements) { 5021cb0ef41Sopenharmony_ci int table_index = 5031cb0ef41Sopenharmony_ci Smi::cast(dispatch_tables.get(i + kDispatchTableIndexOffset)).value(); 5041cb0ef41Sopenharmony_ci WasmInstanceObject instance = WasmInstanceObject::cast( 5051cb0ef41Sopenharmony_ci dispatch_tables.get(i + kDispatchTableInstanceOffset)); 5061cb0ef41Sopenharmony_ci const WasmModule* module = instance.module(); 5071cb0ef41Sopenharmony_ci // Try to avoid the signature map lookup by checking if the signature in 5081cb0ef41Sopenharmony_ci // {module} at {original_sig_id} matches {func->sig}. 5091cb0ef41Sopenharmony_ci int sig_id; 5101cb0ef41Sopenharmony_ci // TODO(7748): wasm-gc signatures cannot be canonicalized this way because 5111cb0ef41Sopenharmony_ci // references could wrongly be detected as identical. 5121cb0ef41Sopenharmony_ci if (module->has_signature(original_sig_id) && 5131cb0ef41Sopenharmony_ci *module->signature(original_sig_id) == *func->sig) { 5141cb0ef41Sopenharmony_ci sig_id = module->canonicalized_type_ids[original_sig_id]; 5151cb0ef41Sopenharmony_ci DCHECK_EQ(sig_id, module->signature_map.Find(*func->sig)); 5161cb0ef41Sopenharmony_ci } else { 5171cb0ef41Sopenharmony_ci // Note that {SignatureMap::Find} may return {-1} if the signature is 5181cb0ef41Sopenharmony_ci // not found; it will simply never match any check. 5191cb0ef41Sopenharmony_ci sig_id = module->signature_map.Find(*func->sig); 5201cb0ef41Sopenharmony_ci } 5211cb0ef41Sopenharmony_ci WasmIndirectFunctionTable ift = WasmIndirectFunctionTable::cast( 5221cb0ef41Sopenharmony_ci instance.indirect_function_tables().get(table_index)); 5231cb0ef41Sopenharmony_ci ift.Set(entry_index, sig_id, call_target, call_ref); 5241cb0ef41Sopenharmony_ci } 5251cb0ef41Sopenharmony_ci} 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_civoid WasmTableObject::UpdateDispatchTables(Isolate* isolate, 5281cb0ef41Sopenharmony_ci Handle<WasmTableObject> table, 5291cb0ef41Sopenharmony_ci int entry_index, 5301cb0ef41Sopenharmony_ci Handle<WasmJSFunction> function) { 5311cb0ef41Sopenharmony_ci // We simply need to update the IFTs for each instance that imports 5321cb0ef41Sopenharmony_ci // this table. 5331cb0ef41Sopenharmony_ci Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); 5341cb0ef41Sopenharmony_ci DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci for (int i = 0; i < dispatch_tables->length(); 5371cb0ef41Sopenharmony_ci i += kDispatchTableNumElements) { 5381cb0ef41Sopenharmony_ci int table_index = 5391cb0ef41Sopenharmony_ci Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value(); 5401cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance( 5411cb0ef41Sopenharmony_ci WasmInstanceObject::cast( 5421cb0ef41Sopenharmony_ci dispatch_tables->get(i + kDispatchTableInstanceOffset)), 5431cb0ef41Sopenharmony_ci isolate); 5441cb0ef41Sopenharmony_ci WasmInstanceObject::ImportWasmJSFunctionIntoTable( 5451cb0ef41Sopenharmony_ci isolate, instance, table_index, entry_index, function); 5461cb0ef41Sopenharmony_ci } 5471cb0ef41Sopenharmony_ci} 5481cb0ef41Sopenharmony_ci 5491cb0ef41Sopenharmony_civoid WasmTableObject::UpdateDispatchTables( 5501cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmTableObject> table, int entry_index, 5511cb0ef41Sopenharmony_ci Handle<WasmCapiFunction> capi_function) { 5521cb0ef41Sopenharmony_ci // We simply need to update the IFTs for each instance that imports 5531cb0ef41Sopenharmony_ci // this table. 5541cb0ef41Sopenharmony_ci Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); 5551cb0ef41Sopenharmony_ci DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci // Reconstruct signature. 5581cb0ef41Sopenharmony_ci // TODO(jkummerow): Unify with "SignatureHelper" in c-api.cc. 5591cb0ef41Sopenharmony_ci PodArray<wasm::ValueType> serialized_sig = 5601cb0ef41Sopenharmony_ci capi_function->GetSerializedSignature(); 5611cb0ef41Sopenharmony_ci int total_count = serialized_sig.length() - 1; 5621cb0ef41Sopenharmony_ci std::unique_ptr<wasm::ValueType[]> reps(new wasm::ValueType[total_count]); 5631cb0ef41Sopenharmony_ci int result_count; 5641cb0ef41Sopenharmony_ci static const wasm::ValueType kMarker = wasm::kWasmVoid; 5651cb0ef41Sopenharmony_ci for (int i = 0, j = 0; i <= total_count; i++) { 5661cb0ef41Sopenharmony_ci if (serialized_sig.get(i) == kMarker) { 5671cb0ef41Sopenharmony_ci result_count = i; 5681cb0ef41Sopenharmony_ci continue; 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci reps[j++] = serialized_sig.get(i); 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci int param_count = total_count - result_count; 5731cb0ef41Sopenharmony_ci wasm::FunctionSig sig(result_count, param_count, reps.get()); 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci for (int i = 0; i < dispatch_tables->length(); 5761cb0ef41Sopenharmony_ci i += kDispatchTableNumElements) { 5771cb0ef41Sopenharmony_ci int table_index = 5781cb0ef41Sopenharmony_ci Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value(); 5791cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance( 5801cb0ef41Sopenharmony_ci WasmInstanceObject::cast( 5811cb0ef41Sopenharmony_ci dispatch_tables->get(i + kDispatchTableInstanceOffset)), 5821cb0ef41Sopenharmony_ci isolate); 5831cb0ef41Sopenharmony_ci wasm::NativeModule* native_module = 5841cb0ef41Sopenharmony_ci instance->module_object().native_module(); 5851cb0ef41Sopenharmony_ci wasm::WasmImportWrapperCache* cache = native_module->import_wrapper_cache(); 5861cb0ef41Sopenharmony_ci auto kind = compiler::WasmImportCallKind::kWasmToCapi; 5871cb0ef41Sopenharmony_ci wasm::WasmCode* wasm_code = 5881cb0ef41Sopenharmony_ci cache->MaybeGet(kind, &sig, param_count, wasm::kNoSuspend); 5891cb0ef41Sopenharmony_ci if (wasm_code == nullptr) { 5901cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 5911cb0ef41Sopenharmony_ci wasm::WasmImportWrapperCache::ModificationScope cache_scope(cache); 5921cb0ef41Sopenharmony_ci wasm_code = compiler::CompileWasmCapiCallWrapper(native_module, &sig); 5931cb0ef41Sopenharmony_ci wasm::WasmImportWrapperCache::CacheKey key(kind, &sig, param_count, 5941cb0ef41Sopenharmony_ci wasm::kNoSuspend); 5951cb0ef41Sopenharmony_ci cache_scope[key] = wasm_code; 5961cb0ef41Sopenharmony_ci wasm_code->IncRef(); 5971cb0ef41Sopenharmony_ci isolate->counters()->wasm_generated_code_size()->Increment( 5981cb0ef41Sopenharmony_ci wasm_code->instructions().length()); 5991cb0ef41Sopenharmony_ci isolate->counters()->wasm_reloc_size()->Increment( 6001cb0ef41Sopenharmony_ci wasm_code->reloc_info().length()); 6011cb0ef41Sopenharmony_ci } 6021cb0ef41Sopenharmony_ci // Note that {SignatureMap::Find} may return {-1} if the signature is 6031cb0ef41Sopenharmony_ci // not found; it will simply never match any check. 6041cb0ef41Sopenharmony_ci auto sig_id = instance->module()->signature_map.Find(sig); 6051cb0ef41Sopenharmony_ci instance->GetIndirectFunctionTable(isolate, table_index) 6061cb0ef41Sopenharmony_ci ->Set(entry_index, sig_id, wasm_code->instruction_start(), 6071cb0ef41Sopenharmony_ci WasmCapiFunctionData::cast( 6081cb0ef41Sopenharmony_ci capi_function->shared().function_data(kAcquireLoad)) 6091cb0ef41Sopenharmony_ci .internal() 6101cb0ef41Sopenharmony_ci .ref()); 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci} 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_civoid WasmTableObject::ClearDispatchTables(Isolate* isolate, 6151cb0ef41Sopenharmony_ci Handle<WasmTableObject> table, 6161cb0ef41Sopenharmony_ci int index) { 6171cb0ef41Sopenharmony_ci Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); 6181cb0ef41Sopenharmony_ci DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); 6191cb0ef41Sopenharmony_ci for (int i = 0; i < dispatch_tables->length(); 6201cb0ef41Sopenharmony_ci i += kDispatchTableNumElements) { 6211cb0ef41Sopenharmony_ci int table_index = 6221cb0ef41Sopenharmony_ci Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value(); 6231cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> target_instance( 6241cb0ef41Sopenharmony_ci WasmInstanceObject::cast( 6251cb0ef41Sopenharmony_ci dispatch_tables->get(i + kDispatchTableInstanceOffset)), 6261cb0ef41Sopenharmony_ci isolate); 6271cb0ef41Sopenharmony_ci Handle<WasmIndirectFunctionTable> function_table = 6281cb0ef41Sopenharmony_ci target_instance->GetIndirectFunctionTable(isolate, table_index); 6291cb0ef41Sopenharmony_ci DCHECK_LT(index, function_table->size()); 6301cb0ef41Sopenharmony_ci function_table->Clear(index); 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci} 6331cb0ef41Sopenharmony_ci 6341cb0ef41Sopenharmony_civoid WasmTableObject::SetFunctionTablePlaceholder( 6351cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmTableObject> table, int entry_index, 6361cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, int func_index) { 6371cb0ef41Sopenharmony_ci // Put (instance, func_index) as a Tuple2 into the entry_index. 6381cb0ef41Sopenharmony_ci // The {WasmExportedFunction} will be created lazily. 6391cb0ef41Sopenharmony_ci // Allocate directly in old space as the tuples are typically long-lived, and 6401cb0ef41Sopenharmony_ci // we create many of them, which would result in lots of GC when initializing 6411cb0ef41Sopenharmony_ci // large tables. 6421cb0ef41Sopenharmony_ci Handle<Tuple2> tuple = isolate->factory()->NewTuple2( 6431cb0ef41Sopenharmony_ci instance, Handle<Smi>(Smi::FromInt(func_index), isolate), 6441cb0ef41Sopenharmony_ci AllocationType::kOld); 6451cb0ef41Sopenharmony_ci table->entries().set(entry_index, *tuple); 6461cb0ef41Sopenharmony_ci} 6471cb0ef41Sopenharmony_ci 6481cb0ef41Sopenharmony_civoid WasmTableObject::GetFunctionTableEntry( 6491cb0ef41Sopenharmony_ci Isolate* isolate, const WasmModule* module, Handle<WasmTableObject> table, 6501cb0ef41Sopenharmony_ci int entry_index, bool* is_valid, bool* is_null, 6511cb0ef41Sopenharmony_ci MaybeHandle<WasmInstanceObject>* instance, int* function_index, 6521cb0ef41Sopenharmony_ci MaybeHandle<WasmJSFunction>* maybe_js_function) { 6531cb0ef41Sopenharmony_ci DCHECK(wasm::IsSubtypeOf(table->type(), wasm::kWasmFuncRef, module)); 6541cb0ef41Sopenharmony_ci DCHECK_LT(entry_index, table->current_length()); 6551cb0ef41Sopenharmony_ci // We initialize {is_valid} with {true}. We may change it later. 6561cb0ef41Sopenharmony_ci *is_valid = true; 6571cb0ef41Sopenharmony_ci Handle<Object> element(table->entries().get(entry_index), isolate); 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci *is_null = element->IsNull(isolate); 6601cb0ef41Sopenharmony_ci if (*is_null) return; 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci if (element->IsWasmInternalFunction()) { 6631cb0ef41Sopenharmony_ci element = handle(Handle<WasmInternalFunction>::cast(element)->external(), 6641cb0ef41Sopenharmony_ci isolate); 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci if (WasmExportedFunction::IsWasmExportedFunction(*element)) { 6671cb0ef41Sopenharmony_ci auto target_func = Handle<WasmExportedFunction>::cast(element); 6681cb0ef41Sopenharmony_ci *instance = handle(target_func->instance(), isolate); 6691cb0ef41Sopenharmony_ci *function_index = target_func->function_index(); 6701cb0ef41Sopenharmony_ci *maybe_js_function = MaybeHandle<WasmJSFunction>(); 6711cb0ef41Sopenharmony_ci return; 6721cb0ef41Sopenharmony_ci } 6731cb0ef41Sopenharmony_ci if (WasmJSFunction::IsWasmJSFunction(*element)) { 6741cb0ef41Sopenharmony_ci *instance = MaybeHandle<WasmInstanceObject>(); 6751cb0ef41Sopenharmony_ci *maybe_js_function = Handle<WasmJSFunction>::cast(element); 6761cb0ef41Sopenharmony_ci return; 6771cb0ef41Sopenharmony_ci } 6781cb0ef41Sopenharmony_ci if (element->IsTuple2()) { 6791cb0ef41Sopenharmony_ci auto tuple = Handle<Tuple2>::cast(element); 6801cb0ef41Sopenharmony_ci *instance = handle(WasmInstanceObject::cast(tuple->value1()), isolate); 6811cb0ef41Sopenharmony_ci *function_index = Smi::cast(tuple->value2()).value(); 6821cb0ef41Sopenharmony_ci *maybe_js_function = MaybeHandle<WasmJSFunction>(); 6831cb0ef41Sopenharmony_ci return; 6841cb0ef41Sopenharmony_ci } 6851cb0ef41Sopenharmony_ci *is_valid = false; 6861cb0ef41Sopenharmony_ci} 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_cinamespace { 6891cb0ef41Sopenharmony_ciclass IftNativeAllocations { 6901cb0ef41Sopenharmony_ci public: 6911cb0ef41Sopenharmony_ci IftNativeAllocations(Handle<WasmIndirectFunctionTable> table, uint32_t size) 6921cb0ef41Sopenharmony_ci : sig_ids_(size), targets_(size) { 6931cb0ef41Sopenharmony_ci table->set_sig_ids(sig_ids_.data()); 6941cb0ef41Sopenharmony_ci table->set_targets(targets_.data()); 6951cb0ef41Sopenharmony_ci } 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci static size_t SizeInMemory(uint32_t size) { 6981cb0ef41Sopenharmony_ci return size * (sizeof(Address) + sizeof(uint32_t)); 6991cb0ef41Sopenharmony_ci } 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_ci void resize(Handle<WasmIndirectFunctionTable> table, uint32_t new_size) { 7021cb0ef41Sopenharmony_ci DCHECK_GE(new_size, sig_ids_.size()); 7031cb0ef41Sopenharmony_ci DCHECK_EQ(this, Managed<IftNativeAllocations>::cast( 7041cb0ef41Sopenharmony_ci table->managed_native_allocations()) 7051cb0ef41Sopenharmony_ci .raw()); 7061cb0ef41Sopenharmony_ci sig_ids_.resize(new_size); 7071cb0ef41Sopenharmony_ci targets_.resize(new_size); 7081cb0ef41Sopenharmony_ci table->set_sig_ids(sig_ids_.data()); 7091cb0ef41Sopenharmony_ci table->set_targets(targets_.data()); 7101cb0ef41Sopenharmony_ci } 7111cb0ef41Sopenharmony_ci 7121cb0ef41Sopenharmony_ci private: 7131cb0ef41Sopenharmony_ci std::vector<uint32_t> sig_ids_; 7141cb0ef41Sopenharmony_ci std::vector<Address> targets_; 7151cb0ef41Sopenharmony_ci}; 7161cb0ef41Sopenharmony_ci} // namespace 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ciHandle<WasmIndirectFunctionTable> WasmIndirectFunctionTable::New( 7191cb0ef41Sopenharmony_ci Isolate* isolate, uint32_t size) { 7201cb0ef41Sopenharmony_ci auto refs = isolate->factory()->NewFixedArray(static_cast<int>(size)); 7211cb0ef41Sopenharmony_ci auto table = Handle<WasmIndirectFunctionTable>::cast( 7221cb0ef41Sopenharmony_ci isolate->factory()->NewStruct(WASM_INDIRECT_FUNCTION_TABLE_TYPE)); 7231cb0ef41Sopenharmony_ci table->set_size(size); 7241cb0ef41Sopenharmony_ci table->set_refs(*refs); 7251cb0ef41Sopenharmony_ci auto native_allocations = Managed<IftNativeAllocations>::Allocate( 7261cb0ef41Sopenharmony_ci isolate, IftNativeAllocations::SizeInMemory(size), table, size); 7271cb0ef41Sopenharmony_ci table->set_managed_native_allocations(*native_allocations); 7281cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < size; ++i) { 7291cb0ef41Sopenharmony_ci table->Clear(i); 7301cb0ef41Sopenharmony_ci } 7311cb0ef41Sopenharmony_ci return table; 7321cb0ef41Sopenharmony_ci} 7331cb0ef41Sopenharmony_civoid WasmIndirectFunctionTable::Set(uint32_t index, int sig_id, 7341cb0ef41Sopenharmony_ci Address call_target, Object ref) { 7351cb0ef41Sopenharmony_ci sig_ids()[index] = sig_id; 7361cb0ef41Sopenharmony_ci targets()[index] = call_target; 7371cb0ef41Sopenharmony_ci refs().set(index, ref); 7381cb0ef41Sopenharmony_ci} 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_civoid WasmIndirectFunctionTable::Clear(uint32_t index) { 7411cb0ef41Sopenharmony_ci sig_ids()[index] = -1; 7421cb0ef41Sopenharmony_ci targets()[index] = 0; 7431cb0ef41Sopenharmony_ci refs().set( 7441cb0ef41Sopenharmony_ci index, 7451cb0ef41Sopenharmony_ci ReadOnlyRoots(GetIsolateFromWritableObject(*this)).undefined_value()); 7461cb0ef41Sopenharmony_ci} 7471cb0ef41Sopenharmony_ci 7481cb0ef41Sopenharmony_civoid WasmIndirectFunctionTable::Resize(Isolate* isolate, 7491cb0ef41Sopenharmony_ci Handle<WasmIndirectFunctionTable> table, 7501cb0ef41Sopenharmony_ci uint32_t new_size) { 7511cb0ef41Sopenharmony_ci uint32_t old_size = table->size(); 7521cb0ef41Sopenharmony_ci if (old_size >= new_size) return; // Nothing to do. 7531cb0ef41Sopenharmony_ci 7541cb0ef41Sopenharmony_ci table->set_size(new_size); 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ci // Grow table exponentially to guarantee amortized constant allocation and gc 7571cb0ef41Sopenharmony_ci // time. 7581cb0ef41Sopenharmony_ci Handle<FixedArray> old_refs(table->refs(), isolate); 7591cb0ef41Sopenharmony_ci // Since we might have overallocated, {old_capacity} might be different than 7601cb0ef41Sopenharmony_ci // {old_size}. 7611cb0ef41Sopenharmony_ci uint32_t old_capacity = old_refs->length(); 7621cb0ef41Sopenharmony_ci // If we have enough capacity, there is no need to reallocate. 7631cb0ef41Sopenharmony_ci if (new_size <= old_capacity) return; 7641cb0ef41Sopenharmony_ci uint32_t new_capacity = std::max(2 * old_capacity, new_size); 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci Managed<IftNativeAllocations>::cast(table->managed_native_allocations()) 7671cb0ef41Sopenharmony_ci .raw() 7681cb0ef41Sopenharmony_ci ->resize(table, new_capacity); 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci Handle<FixedArray> new_refs = isolate->factory()->CopyFixedArrayAndGrow( 7711cb0ef41Sopenharmony_ci old_refs, static_cast<int>(new_capacity - old_capacity)); 7721cb0ef41Sopenharmony_ci table->set_refs(*new_refs); 7731cb0ef41Sopenharmony_ci for (uint32_t i = old_capacity; i < new_capacity; ++i) { 7741cb0ef41Sopenharmony_ci table->Clear(i); 7751cb0ef41Sopenharmony_ci } 7761cb0ef41Sopenharmony_ci} 7771cb0ef41Sopenharmony_ci 7781cb0ef41Sopenharmony_cinamespace { 7791cb0ef41Sopenharmony_ci 7801cb0ef41Sopenharmony_civoid SetInstanceMemory(Handle<WasmInstanceObject> instance, 7811cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer) { 7821cb0ef41Sopenharmony_ci bool is_wasm_module = instance->module()->origin == wasm::kWasmOrigin; 7831cb0ef41Sopenharmony_ci bool use_trap_handler = 7841cb0ef41Sopenharmony_ci instance->module_object().native_module()->bounds_checks() == 7851cb0ef41Sopenharmony_ci wasm::kTrapHandler; 7861cb0ef41Sopenharmony_ci // Wasm modules compiled to use the trap handler don't have bounds checks, 7871cb0ef41Sopenharmony_ci // so they must have a memory that has guard regions. 7881cb0ef41Sopenharmony_ci CHECK_IMPLIES(is_wasm_module && use_trap_handler, 7891cb0ef41Sopenharmony_ci buffer->GetBackingStore()->has_guard_regions()); 7901cb0ef41Sopenharmony_ci 7911cb0ef41Sopenharmony_ci instance->SetRawMemory(reinterpret_cast<byte*>(buffer->backing_store()), 7921cb0ef41Sopenharmony_ci buffer->byte_length()); 7931cb0ef41Sopenharmony_ci#if DEBUG 7941cb0ef41Sopenharmony_ci if (!FLAG_mock_arraybuffer_allocator) { 7951cb0ef41Sopenharmony_ci // To flush out bugs earlier, in DEBUG mode, check that all pages of the 7961cb0ef41Sopenharmony_ci // memory are accessible by reading and writing one byte on each page. 7971cb0ef41Sopenharmony_ci // Don't do this if the mock ArrayBuffer allocator is enabled. 7981cb0ef41Sopenharmony_ci byte* mem_start = instance->memory_start(); 7991cb0ef41Sopenharmony_ci size_t mem_size = instance->memory_size(); 8001cb0ef41Sopenharmony_ci for (size_t offset = 0; offset < mem_size; offset += wasm::kWasmPageSize) { 8011cb0ef41Sopenharmony_ci byte val = mem_start[offset]; 8021cb0ef41Sopenharmony_ci USE(val); 8031cb0ef41Sopenharmony_ci mem_start[offset] = val; 8041cb0ef41Sopenharmony_ci } 8051cb0ef41Sopenharmony_ci } 8061cb0ef41Sopenharmony_ci#endif 8071cb0ef41Sopenharmony_ci} 8081cb0ef41Sopenharmony_ci} // namespace 8091cb0ef41Sopenharmony_ci 8101cb0ef41Sopenharmony_ciMaybeHandle<WasmMemoryObject> WasmMemoryObject::New( 8111cb0ef41Sopenharmony_ci Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer, int maximum) { 8121cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer; 8131cb0ef41Sopenharmony_ci if (!maybe_buffer.ToHandle(&buffer)) { 8141cb0ef41Sopenharmony_ci // If no buffer was provided, create a zero-length one. 8151cb0ef41Sopenharmony_ci auto backing_store = 8161cb0ef41Sopenharmony_ci BackingStore::AllocateWasmMemory(isolate, 0, 0, SharedFlag::kNotShared); 8171cb0ef41Sopenharmony_ci if (!backing_store) return {}; 8181cb0ef41Sopenharmony_ci buffer = isolate->factory()->NewJSArrayBuffer(std::move(backing_store)); 8191cb0ef41Sopenharmony_ci } 8201cb0ef41Sopenharmony_ci 8211cb0ef41Sopenharmony_ci Handle<JSFunction> memory_ctor( 8221cb0ef41Sopenharmony_ci isolate->native_context()->wasm_memory_constructor(), isolate); 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_ci auto memory_object = Handle<WasmMemoryObject>::cast( 8251cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(memory_ctor, AllocationType::kOld)); 8261cb0ef41Sopenharmony_ci memory_object->set_array_buffer(*buffer); 8271cb0ef41Sopenharmony_ci memory_object->set_maximum_pages(maximum); 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci if (buffer->is_shared()) { 8301cb0ef41Sopenharmony_ci auto backing_store = buffer->GetBackingStore(); 8311cb0ef41Sopenharmony_ci backing_store->AttachSharedWasmMemoryObject(isolate, memory_object); 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci // For debugging purposes we memorize a link from the JSArrayBuffer 8351cb0ef41Sopenharmony_ci // to it's owning WasmMemoryObject instance. 8361cb0ef41Sopenharmony_ci Handle<Symbol> symbol = isolate->factory()->array_buffer_wasm_memory_symbol(); 8371cb0ef41Sopenharmony_ci JSObject::SetProperty(isolate, buffer, symbol, memory_object).Check(); 8381cb0ef41Sopenharmony_ci 8391cb0ef41Sopenharmony_ci return memory_object; 8401cb0ef41Sopenharmony_ci} 8411cb0ef41Sopenharmony_ci 8421cb0ef41Sopenharmony_ciMaybeHandle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate, 8431cb0ef41Sopenharmony_ci int initial, int maximum, 8441cb0ef41Sopenharmony_ci SharedFlag shared) { 8451cb0ef41Sopenharmony_ci bool has_maximum = maximum != kNoMaximum; 8461cb0ef41Sopenharmony_ci int heuristic_maximum = maximum; 8471cb0ef41Sopenharmony_ci if (!has_maximum) { 8481cb0ef41Sopenharmony_ci heuristic_maximum = static_cast<int>(wasm::max_mem_pages()); 8491cb0ef41Sopenharmony_ci } 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci#ifdef V8_TARGET_ARCH_32_BIT 8521cb0ef41Sopenharmony_ci // On 32-bit platforms we need an heuristic here to balance overall memory 8531cb0ef41Sopenharmony_ci // and address space consumption. 8541cb0ef41Sopenharmony_ci constexpr int kGBPages = 1024 * 1024 * 1024 / wasm::kWasmPageSize; 8551cb0ef41Sopenharmony_ci if (initial > kGBPages) { 8561cb0ef41Sopenharmony_ci // We always allocate at least the initial size. 8571cb0ef41Sopenharmony_ci heuristic_maximum = initial; 8581cb0ef41Sopenharmony_ci } else if (has_maximum) { 8591cb0ef41Sopenharmony_ci // We try to reserve the maximum, but at most 1GB to avoid OOMs. 8601cb0ef41Sopenharmony_ci heuristic_maximum = std::min(maximum, kGBPages); 8611cb0ef41Sopenharmony_ci } else if (shared == SharedFlag::kShared) { 8621cb0ef41Sopenharmony_ci // If shared memory has no maximum, we use an implicit maximum of 1GB. 8631cb0ef41Sopenharmony_ci heuristic_maximum = kGBPages; 8641cb0ef41Sopenharmony_ci } else { 8651cb0ef41Sopenharmony_ci // If non-shared memory has no maximum, we only allocate the initial size 8661cb0ef41Sopenharmony_ci // and then grow with realloc. 8671cb0ef41Sopenharmony_ci heuristic_maximum = initial; 8681cb0ef41Sopenharmony_ci } 8691cb0ef41Sopenharmony_ci#endif 8701cb0ef41Sopenharmony_ci 8711cb0ef41Sopenharmony_ci auto backing_store = BackingStore::AllocateWasmMemory( 8721cb0ef41Sopenharmony_ci isolate, initial, heuristic_maximum, shared); 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_ci if (!backing_store) return {}; 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer = 8771cb0ef41Sopenharmony_ci (shared == SharedFlag::kShared) 8781cb0ef41Sopenharmony_ci ? isolate->factory()->NewJSSharedArrayBuffer(std::move(backing_store)) 8791cb0ef41Sopenharmony_ci : isolate->factory()->NewJSArrayBuffer(std::move(backing_store)); 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_ci return New(isolate, buffer, maximum); 8821cb0ef41Sopenharmony_ci} 8831cb0ef41Sopenharmony_ci 8841cb0ef41Sopenharmony_civoid WasmMemoryObject::AddInstance(Isolate* isolate, 8851cb0ef41Sopenharmony_ci Handle<WasmMemoryObject> memory, 8861cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance) { 8871cb0ef41Sopenharmony_ci Handle<WeakArrayList> old_instances = 8881cb0ef41Sopenharmony_ci memory->has_instances() 8891cb0ef41Sopenharmony_ci ? Handle<WeakArrayList>(memory->instances(), isolate) 8901cb0ef41Sopenharmony_ci : handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(), 8911cb0ef41Sopenharmony_ci isolate); 8921cb0ef41Sopenharmony_ci Handle<WeakArrayList> new_instances = WeakArrayList::Append( 8931cb0ef41Sopenharmony_ci isolate, old_instances, MaybeObjectHandle::Weak(instance)); 8941cb0ef41Sopenharmony_ci memory->set_instances(*new_instances); 8951cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate); 8961cb0ef41Sopenharmony_ci SetInstanceMemory(instance, buffer); 8971cb0ef41Sopenharmony_ci} 8981cb0ef41Sopenharmony_ci 8991cb0ef41Sopenharmony_civoid WasmMemoryObject::update_instances(Isolate* isolate, 9001cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer) { 9011cb0ef41Sopenharmony_ci if (has_instances()) { 9021cb0ef41Sopenharmony_ci Handle<WeakArrayList> instances(this->instances(), isolate); 9031cb0ef41Sopenharmony_ci for (int i = 0; i < instances->length(); i++) { 9041cb0ef41Sopenharmony_ci MaybeObject elem = instances->Get(i); 9051cb0ef41Sopenharmony_ci HeapObject heap_object; 9061cb0ef41Sopenharmony_ci if (elem->GetHeapObjectIfWeak(&heap_object)) { 9071cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance( 9081cb0ef41Sopenharmony_ci WasmInstanceObject::cast(heap_object), isolate); 9091cb0ef41Sopenharmony_ci SetInstanceMemory(instance, buffer); 9101cb0ef41Sopenharmony_ci } else { 9111cb0ef41Sopenharmony_ci DCHECK(elem->IsCleared()); 9121cb0ef41Sopenharmony_ci } 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci } 9151cb0ef41Sopenharmony_ci set_array_buffer(*buffer); 9161cb0ef41Sopenharmony_ci} 9171cb0ef41Sopenharmony_ci 9181cb0ef41Sopenharmony_ci// static 9191cb0ef41Sopenharmony_ciint32_t WasmMemoryObject::Grow(Isolate* isolate, 9201cb0ef41Sopenharmony_ci Handle<WasmMemoryObject> memory_object, 9211cb0ef41Sopenharmony_ci uint32_t pages) { 9221cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.GrowMemory"); 9231cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer(), isolate); 9241cb0ef41Sopenharmony_ci // Any buffer used as an asmjs memory cannot be detached, and 9251cb0ef41Sopenharmony_ci // therefore this memory cannot be grown. 9261cb0ef41Sopenharmony_ci if (old_buffer->is_asmjs_memory()) return -1; 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci std::shared_ptr<BackingStore> backing_store = old_buffer->GetBackingStore(); 9291cb0ef41Sopenharmony_ci if (!backing_store) return -1; 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ci // Check for maximum memory size. 9321cb0ef41Sopenharmony_ci // Note: The {wasm::max_mem_pages()} limit is already checked in 9331cb0ef41Sopenharmony_ci // {BackingStore::CopyWasmMemory}, and is irrelevant for 9341cb0ef41Sopenharmony_ci // {GrowWasmMemoryInPlace} because memory is never allocated with more 9351cb0ef41Sopenharmony_ci // capacity than that limit. 9361cb0ef41Sopenharmony_ci size_t old_size = old_buffer->byte_length(); 9371cb0ef41Sopenharmony_ci DCHECK_EQ(0, old_size % wasm::kWasmPageSize); 9381cb0ef41Sopenharmony_ci size_t old_pages = old_size / wasm::kWasmPageSize; 9391cb0ef41Sopenharmony_ci uint32_t max_pages = wasm::kSpecMaxMemoryPages; 9401cb0ef41Sopenharmony_ci if (memory_object->has_maximum_pages()) { 9411cb0ef41Sopenharmony_ci DCHECK_GE(max_pages, memory_object->maximum_pages()); 9421cb0ef41Sopenharmony_ci max_pages = static_cast<uint32_t>(memory_object->maximum_pages()); 9431cb0ef41Sopenharmony_ci } 9441cb0ef41Sopenharmony_ci DCHECK_GE(max_pages, old_pages); 9451cb0ef41Sopenharmony_ci if (pages > max_pages - old_pages) return -1; 9461cb0ef41Sopenharmony_ci 9471cb0ef41Sopenharmony_ci base::Optional<size_t> result_inplace = 9481cb0ef41Sopenharmony_ci backing_store->GrowWasmMemoryInPlace(isolate, pages, max_pages); 9491cb0ef41Sopenharmony_ci // Handle shared memory first. 9501cb0ef41Sopenharmony_ci if (old_buffer->is_shared()) { 9511cb0ef41Sopenharmony_ci // Shared memories can only be grown in place; no copying. 9521cb0ef41Sopenharmony_ci if (!result_inplace.has_value()) { 9531cb0ef41Sopenharmony_ci // There are different limits per platform, thus crash if the correctness 9541cb0ef41Sopenharmony_ci // fuzzer is running. 9551cb0ef41Sopenharmony_ci if (FLAG_correctness_fuzzer_suppressions) { 9561cb0ef41Sopenharmony_ci FATAL("could not grow wasm memory"); 9571cb0ef41Sopenharmony_ci } 9581cb0ef41Sopenharmony_ci return -1; 9591cb0ef41Sopenharmony_ci } 9601cb0ef41Sopenharmony_ci 9611cb0ef41Sopenharmony_ci BackingStore::BroadcastSharedWasmMemoryGrow(isolate, backing_store); 9621cb0ef41Sopenharmony_ci // Broadcasting the update should update this memory object too. 9631cb0ef41Sopenharmony_ci CHECK_NE(*old_buffer, memory_object->array_buffer()); 9641cb0ef41Sopenharmony_ci size_t new_pages = result_inplace.value() + pages; 9651cb0ef41Sopenharmony_ci // If the allocation succeeded, then this can't possibly overflow: 9661cb0ef41Sopenharmony_ci size_t new_byte_length = new_pages * wasm::kWasmPageSize; 9671cb0ef41Sopenharmony_ci // This is a less than check, as it is not guaranteed that the SAB 9681cb0ef41Sopenharmony_ci // length here will be equal to the stashed length above as calls to 9691cb0ef41Sopenharmony_ci // grow the same memory object can come in from different workers. 9701cb0ef41Sopenharmony_ci // It is also possible that a call to Grow was in progress when 9711cb0ef41Sopenharmony_ci // handling this call. 9721cb0ef41Sopenharmony_ci CHECK_LE(new_byte_length, memory_object->array_buffer().byte_length()); 9731cb0ef41Sopenharmony_ci // As {old_pages} was read racefully, we return here the synchronized 9741cb0ef41Sopenharmony_ci // value provided by {GrowWasmMemoryInPlace}, to provide the atomic 9751cb0ef41Sopenharmony_ci // read-modify-write behavior required by the spec. 9761cb0ef41Sopenharmony_ci return static_cast<int32_t>(result_inplace.value()); // success 9771cb0ef41Sopenharmony_ci } 9781cb0ef41Sopenharmony_ci 9791cb0ef41Sopenharmony_ci // Check if the non-shared memory could grow in-place. 9801cb0ef41Sopenharmony_ci if (result_inplace.has_value()) { 9811cb0ef41Sopenharmony_ci // Detach old and create a new one with the grown backing store. 9821cb0ef41Sopenharmony_ci old_buffer->Detach(true); 9831cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> new_buffer = 9841cb0ef41Sopenharmony_ci isolate->factory()->NewJSArrayBuffer(std::move(backing_store)); 9851cb0ef41Sopenharmony_ci memory_object->update_instances(isolate, new_buffer); 9861cb0ef41Sopenharmony_ci // For debugging purposes we memorize a link from the JSArrayBuffer 9871cb0ef41Sopenharmony_ci // to it's owning WasmMemoryObject instance. 9881cb0ef41Sopenharmony_ci Handle<Symbol> symbol = 9891cb0ef41Sopenharmony_ci isolate->factory()->array_buffer_wasm_memory_symbol(); 9901cb0ef41Sopenharmony_ci JSObject::SetProperty(isolate, new_buffer, symbol, memory_object).Check(); 9911cb0ef41Sopenharmony_ci DCHECK_EQ(result_inplace.value(), old_pages); 9921cb0ef41Sopenharmony_ci return static_cast<int32_t>(result_inplace.value()); // success 9931cb0ef41Sopenharmony_ci } 9941cb0ef41Sopenharmony_ci 9951cb0ef41Sopenharmony_ci size_t new_pages = old_pages + pages; 9961cb0ef41Sopenharmony_ci DCHECK_LT(old_pages, new_pages); 9971cb0ef41Sopenharmony_ci // Try allocating a new backing store and copying. 9981cb0ef41Sopenharmony_ci // To avoid overall quadratic complexity of many small grow operations, we 9991cb0ef41Sopenharmony_ci // grow by at least 0.5 MB + 12.5% of the existing memory size. 10001cb0ef41Sopenharmony_ci // These numbers are kept small because we must be careful about address 10011cb0ef41Sopenharmony_ci // space consumption on 32-bit platforms. 10021cb0ef41Sopenharmony_ci size_t min_growth = old_pages + 8 + (old_pages >> 3); 10031cb0ef41Sopenharmony_ci size_t new_capacity = std::max(new_pages, min_growth); 10041cb0ef41Sopenharmony_ci std::unique_ptr<BackingStore> new_backing_store = 10051cb0ef41Sopenharmony_ci backing_store->CopyWasmMemory(isolate, new_pages, new_capacity); 10061cb0ef41Sopenharmony_ci if (!new_backing_store) { 10071cb0ef41Sopenharmony_ci // Crash on out-of-memory if the correctness fuzzer is running. 10081cb0ef41Sopenharmony_ci if (FLAG_correctness_fuzzer_suppressions) { 10091cb0ef41Sopenharmony_ci FATAL("could not grow wasm memory"); 10101cb0ef41Sopenharmony_ci } 10111cb0ef41Sopenharmony_ci return -1; 10121cb0ef41Sopenharmony_ci } 10131cb0ef41Sopenharmony_ci 10141cb0ef41Sopenharmony_ci // Detach old and create a new one with the new backing store. 10151cb0ef41Sopenharmony_ci old_buffer->Detach(true); 10161cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> new_buffer = 10171cb0ef41Sopenharmony_ci isolate->factory()->NewJSArrayBuffer(std::move(new_backing_store)); 10181cb0ef41Sopenharmony_ci memory_object->update_instances(isolate, new_buffer); 10191cb0ef41Sopenharmony_ci // For debugging purposes we memorize a link from the JSArrayBuffer 10201cb0ef41Sopenharmony_ci // to it's owning WasmMemoryObject instance. 10211cb0ef41Sopenharmony_ci Handle<Symbol> symbol = isolate->factory()->array_buffer_wasm_memory_symbol(); 10221cb0ef41Sopenharmony_ci JSObject::SetProperty(isolate, new_buffer, symbol, memory_object).Check(); 10231cb0ef41Sopenharmony_ci return static_cast<int32_t>(old_pages); // success 10241cb0ef41Sopenharmony_ci} 10251cb0ef41Sopenharmony_ci 10261cb0ef41Sopenharmony_ci// static 10271cb0ef41Sopenharmony_ciMaybeHandle<WasmGlobalObject> WasmGlobalObject::New( 10281cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, 10291cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> maybe_untagged_buffer, 10301cb0ef41Sopenharmony_ci MaybeHandle<FixedArray> maybe_tagged_buffer, wasm::ValueType type, 10311cb0ef41Sopenharmony_ci int32_t offset, bool is_mutable) { 10321cb0ef41Sopenharmony_ci Handle<JSFunction> global_ctor( 10331cb0ef41Sopenharmony_ci isolate->native_context()->wasm_global_constructor(), isolate); 10341cb0ef41Sopenharmony_ci auto global_obj = Handle<WasmGlobalObject>::cast( 10351cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(global_ctor)); 10361cb0ef41Sopenharmony_ci { 10371cb0ef41Sopenharmony_ci // Disallow GC until all fields have acceptable types. 10381cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 10391cb0ef41Sopenharmony_ci if (!instance.is_null()) global_obj->set_instance(*instance); 10401cb0ef41Sopenharmony_ci global_obj->set_type(type); 10411cb0ef41Sopenharmony_ci global_obj->set_offset(offset); 10421cb0ef41Sopenharmony_ci global_obj->set_is_mutable(is_mutable); 10431cb0ef41Sopenharmony_ci } 10441cb0ef41Sopenharmony_ci 10451cb0ef41Sopenharmony_ci if (type.is_reference()) { 10461cb0ef41Sopenharmony_ci DCHECK(maybe_untagged_buffer.is_null()); 10471cb0ef41Sopenharmony_ci Handle<FixedArray> tagged_buffer; 10481cb0ef41Sopenharmony_ci if (!maybe_tagged_buffer.ToHandle(&tagged_buffer)) { 10491cb0ef41Sopenharmony_ci // If no buffer was provided, create one. 10501cb0ef41Sopenharmony_ci tagged_buffer = 10511cb0ef41Sopenharmony_ci isolate->factory()->NewFixedArray(1, AllocationType::kOld); 10521cb0ef41Sopenharmony_ci CHECK_EQ(offset, 0); 10531cb0ef41Sopenharmony_ci } 10541cb0ef41Sopenharmony_ci global_obj->set_tagged_buffer(*tagged_buffer); 10551cb0ef41Sopenharmony_ci } else { 10561cb0ef41Sopenharmony_ci DCHECK(maybe_tagged_buffer.is_null()); 10571cb0ef41Sopenharmony_ci uint32_t type_size = type.value_kind_size(); 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> untagged_buffer; 10601cb0ef41Sopenharmony_ci if (!maybe_untagged_buffer.ToHandle(&untagged_buffer)) { 10611cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> result = 10621cb0ef41Sopenharmony_ci isolate->factory()->NewJSArrayBufferAndBackingStore( 10631cb0ef41Sopenharmony_ci offset + type_size, InitializedFlag::kZeroInitialized); 10641cb0ef41Sopenharmony_ci 10651cb0ef41Sopenharmony_ci if (!result.ToHandle(&untagged_buffer)) return {}; 10661cb0ef41Sopenharmony_ci } 10671cb0ef41Sopenharmony_ci 10681cb0ef41Sopenharmony_ci // Check that the offset is in bounds. 10691cb0ef41Sopenharmony_ci CHECK_LE(offset + type_size, untagged_buffer->byte_length()); 10701cb0ef41Sopenharmony_ci 10711cb0ef41Sopenharmony_ci global_obj->set_untagged_buffer(*untagged_buffer); 10721cb0ef41Sopenharmony_ci } 10731cb0ef41Sopenharmony_ci 10741cb0ef41Sopenharmony_ci return global_obj; 10751cb0ef41Sopenharmony_ci} 10761cb0ef41Sopenharmony_ci 10771cb0ef41Sopenharmony_ciFunctionTargetAndRef::FunctionTargetAndRef( 10781cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> target_instance, int target_func_index) { 10791cb0ef41Sopenharmony_ci Isolate* isolate = target_instance->native_context().GetIsolate(); 10801cb0ef41Sopenharmony_ci if (target_func_index < 10811cb0ef41Sopenharmony_ci static_cast<int>(target_instance->module()->num_imported_functions)) { 10821cb0ef41Sopenharmony_ci // The function in the target instance was imported. Use its imports table, 10831cb0ef41Sopenharmony_ci // which contains a tuple needed by the import wrapper. 10841cb0ef41Sopenharmony_ci ImportedFunctionEntry entry(target_instance, target_func_index); 10851cb0ef41Sopenharmony_ci ref_ = handle(entry.object_ref(), isolate); 10861cb0ef41Sopenharmony_ci call_target_ = entry.target(); 10871cb0ef41Sopenharmony_ci } else { 10881cb0ef41Sopenharmony_ci // The function in the target instance was not imported. 10891cb0ef41Sopenharmony_ci ref_ = target_instance; 10901cb0ef41Sopenharmony_ci call_target_ = target_instance->GetCallTarget(target_func_index); 10911cb0ef41Sopenharmony_ci } 10921cb0ef41Sopenharmony_ci} 10931cb0ef41Sopenharmony_ci 10941cb0ef41Sopenharmony_civoid ImportedFunctionEntry::SetWasmToJs( 10951cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSReceiver> callable, 10961cb0ef41Sopenharmony_ci const wasm::WasmCode* wasm_to_js_wrapper, Handle<HeapObject> suspender) { 10971cb0ef41Sopenharmony_ci TRACE_IFT("Import callable 0x%" PRIxPTR "[%d] = {callable=0x%" PRIxPTR 10981cb0ef41Sopenharmony_ci ", target=%p}\n", 10991cb0ef41Sopenharmony_ci instance_->ptr(), index_, callable->ptr(), 11001cb0ef41Sopenharmony_ci wasm_to_js_wrapper->instructions().begin()); 11011cb0ef41Sopenharmony_ci DCHECK(wasm_to_js_wrapper->kind() == wasm::WasmCode::kWasmToJsWrapper || 11021cb0ef41Sopenharmony_ci wasm_to_js_wrapper->kind() == wasm::WasmCode::kWasmToCapiWrapper); 11031cb0ef41Sopenharmony_ci Handle<WasmApiFunctionRef> ref = 11041cb0ef41Sopenharmony_ci isolate->factory()->NewWasmApiFunctionRef(callable, suspender); 11051cb0ef41Sopenharmony_ci instance_->imported_function_refs().set(index_, *ref); 11061cb0ef41Sopenharmony_ci instance_->imported_function_targets()[index_] = 11071cb0ef41Sopenharmony_ci wasm_to_js_wrapper->instruction_start(); 11081cb0ef41Sopenharmony_ci} 11091cb0ef41Sopenharmony_ci 11101cb0ef41Sopenharmony_civoid ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject instance, 11111cb0ef41Sopenharmony_ci Address call_target) { 11121cb0ef41Sopenharmony_ci TRACE_IFT("Import Wasm 0x%" PRIxPTR "[%d] = {instance=0x%" PRIxPTR 11131cb0ef41Sopenharmony_ci ", target=0x%" PRIxPTR "}\n", 11141cb0ef41Sopenharmony_ci instance_->ptr(), index_, instance.ptr(), call_target); 11151cb0ef41Sopenharmony_ci instance_->imported_function_refs().set(index_, instance); 11161cb0ef41Sopenharmony_ci instance_->imported_function_targets()[index_] = call_target; 11171cb0ef41Sopenharmony_ci} 11181cb0ef41Sopenharmony_ci 11191cb0ef41Sopenharmony_ci// Returns an empty Object() if no callable is available, a JSReceiver 11201cb0ef41Sopenharmony_ci// otherwise. 11211cb0ef41Sopenharmony_ciObject ImportedFunctionEntry::maybe_callable() { 11221cb0ef41Sopenharmony_ci Object value = object_ref(); 11231cb0ef41Sopenharmony_ci if (!value.IsWasmApiFunctionRef()) return Object(); 11241cb0ef41Sopenharmony_ci return JSReceiver::cast(WasmApiFunctionRef::cast(value).callable()); 11251cb0ef41Sopenharmony_ci} 11261cb0ef41Sopenharmony_ci 11271cb0ef41Sopenharmony_ciJSReceiver ImportedFunctionEntry::callable() { 11281cb0ef41Sopenharmony_ci return JSReceiver::cast(WasmApiFunctionRef::cast(object_ref()).callable()); 11291cb0ef41Sopenharmony_ci} 11301cb0ef41Sopenharmony_ci 11311cb0ef41Sopenharmony_ciObject ImportedFunctionEntry::object_ref() { 11321cb0ef41Sopenharmony_ci return instance_->imported_function_refs().get(index_); 11331cb0ef41Sopenharmony_ci} 11341cb0ef41Sopenharmony_ci 11351cb0ef41Sopenharmony_ciAddress ImportedFunctionEntry::target() { 11361cb0ef41Sopenharmony_ci return instance_->imported_function_targets()[index_]; 11371cb0ef41Sopenharmony_ci} 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_ci// static 11401cb0ef41Sopenharmony_ciconstexpr uint16_t WasmInstanceObject::kTaggedFieldOffsets[]; 11411cb0ef41Sopenharmony_ci 11421cb0ef41Sopenharmony_ci// static 11431cb0ef41Sopenharmony_cibool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( 11441cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, int table_index, 11451cb0ef41Sopenharmony_ci uint32_t minimum_size) { 11461cb0ef41Sopenharmony_ci Isolate* isolate = instance->GetIsolate(); 11471cb0ef41Sopenharmony_ci DCHECK_LT(table_index, instance->indirect_function_tables().length()); 11481cb0ef41Sopenharmony_ci Handle<WasmIndirectFunctionTable> table = 11491cb0ef41Sopenharmony_ci instance->GetIndirectFunctionTable(isolate, table_index); 11501cb0ef41Sopenharmony_ci WasmIndirectFunctionTable::Resize(isolate, table, minimum_size); 11511cb0ef41Sopenharmony_ci if (table_index == 0) { 11521cb0ef41Sopenharmony_ci instance->SetIndirectFunctionTableShortcuts(isolate); 11531cb0ef41Sopenharmony_ci } 11541cb0ef41Sopenharmony_ci return true; 11551cb0ef41Sopenharmony_ci} 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_civoid WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) { 11581cb0ef41Sopenharmony_ci CHECK_LE(mem_size, wasm::max_mem_bytes()); 11591cb0ef41Sopenharmony_ci#if V8_HOST_ARCH_64_BIT 11601cb0ef41Sopenharmony_ci set_memory_start(mem_start); 11611cb0ef41Sopenharmony_ci set_memory_size(mem_size); 11621cb0ef41Sopenharmony_ci#else 11631cb0ef41Sopenharmony_ci // Must handle memory > 2GiB specially. 11641cb0ef41Sopenharmony_ci CHECK_LE(mem_size, size_t{kMaxUInt32}); 11651cb0ef41Sopenharmony_ci set_memory_start(mem_start); 11661cb0ef41Sopenharmony_ci set_memory_size(mem_size); 11671cb0ef41Sopenharmony_ci#endif 11681cb0ef41Sopenharmony_ci} 11691cb0ef41Sopenharmony_ci 11701cb0ef41Sopenharmony_ciconst WasmModule* WasmInstanceObject::module() { 11711cb0ef41Sopenharmony_ci return module_object().module(); 11721cb0ef41Sopenharmony_ci} 11731cb0ef41Sopenharmony_ci 11741cb0ef41Sopenharmony_ciHandle<WasmInstanceObject> WasmInstanceObject::New( 11751cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmModuleObject> module_object) { 11761cb0ef41Sopenharmony_ci Handle<JSFunction> instance_cons( 11771cb0ef41Sopenharmony_ci isolate->native_context()->wasm_instance_constructor(), isolate); 11781cb0ef41Sopenharmony_ci Handle<JSObject> instance_object = 11791cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(instance_cons, AllocationType::kOld); 11801cb0ef41Sopenharmony_ci 11811cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance( 11821cb0ef41Sopenharmony_ci WasmInstanceObject::cast(*instance_object), isolate); 11831cb0ef41Sopenharmony_ci instance->clear_padding(); 11841cb0ef41Sopenharmony_ci 11851cb0ef41Sopenharmony_ci // Initialize the imported function arrays. 11861cb0ef41Sopenharmony_ci auto module = module_object->module(); 11871cb0ef41Sopenharmony_ci auto num_imported_functions = module->num_imported_functions; 11881cb0ef41Sopenharmony_ci auto num_imported_mutable_globals = module->num_imported_mutable_globals; 11891cb0ef41Sopenharmony_ci auto num_data_segments = module->num_declared_data_segments; 11901cb0ef41Sopenharmony_ci size_t native_allocations_size = EstimateNativeAllocationsSize(module); 11911cb0ef41Sopenharmony_ci auto native_allocations = Managed<WasmInstanceNativeAllocations>::Allocate( 11921cb0ef41Sopenharmony_ci isolate, native_allocations_size, instance, num_imported_functions, 11931cb0ef41Sopenharmony_ci num_imported_mutable_globals, num_data_segments, 11941cb0ef41Sopenharmony_ci module->elem_segments.size()); 11951cb0ef41Sopenharmony_ci instance->set_managed_native_allocations(*native_allocations); 11961cb0ef41Sopenharmony_ci 11971cb0ef41Sopenharmony_ci Handle<FixedArray> imported_function_refs = 11981cb0ef41Sopenharmony_ci isolate->factory()->NewFixedArray(num_imported_functions); 11991cb0ef41Sopenharmony_ci instance->set_imported_function_refs(*imported_function_refs); 12001cb0ef41Sopenharmony_ci 12011cb0ef41Sopenharmony_ci instance->SetRawMemory(reinterpret_cast<byte*>(EmptyBackingStoreBuffer()), 0); 12021cb0ef41Sopenharmony_ci instance->set_isolate_root(isolate->isolate_root()); 12031cb0ef41Sopenharmony_ci instance->set_stack_limit_address( 12041cb0ef41Sopenharmony_ci isolate->stack_guard()->address_of_jslimit()); 12051cb0ef41Sopenharmony_ci instance->set_real_stack_limit_address( 12061cb0ef41Sopenharmony_ci isolate->stack_guard()->address_of_real_jslimit()); 12071cb0ef41Sopenharmony_ci instance->set_new_allocation_limit_address( 12081cb0ef41Sopenharmony_ci isolate->heap()->NewSpaceAllocationLimitAddress()); 12091cb0ef41Sopenharmony_ci instance->set_new_allocation_top_address( 12101cb0ef41Sopenharmony_ci isolate->heap()->NewSpaceAllocationTopAddress()); 12111cb0ef41Sopenharmony_ci instance->set_old_allocation_limit_address( 12121cb0ef41Sopenharmony_ci isolate->heap()->OldSpaceAllocationLimitAddress()); 12131cb0ef41Sopenharmony_ci instance->set_old_allocation_top_address( 12141cb0ef41Sopenharmony_ci isolate->heap()->OldSpaceAllocationTopAddress()); 12151cb0ef41Sopenharmony_ci instance->set_globals_start(nullptr); 12161cb0ef41Sopenharmony_ci instance->set_indirect_function_table_size(0); 12171cb0ef41Sopenharmony_ci instance->set_indirect_function_table_refs( 12181cb0ef41Sopenharmony_ci ReadOnlyRoots(isolate).empty_fixed_array()); 12191cb0ef41Sopenharmony_ci instance->set_indirect_function_table_sig_ids(nullptr); 12201cb0ef41Sopenharmony_ci instance->set_indirect_function_table_targets(nullptr); 12211cb0ef41Sopenharmony_ci instance->set_native_context(*isolate->native_context()); 12221cb0ef41Sopenharmony_ci instance->set_module_object(*module_object); 12231cb0ef41Sopenharmony_ci instance->set_jump_table_start( 12241cb0ef41Sopenharmony_ci module_object->native_module()->jump_table_start()); 12251cb0ef41Sopenharmony_ci instance->set_hook_on_function_call_address( 12261cb0ef41Sopenharmony_ci isolate->debug()->hook_on_function_call_address()); 12271cb0ef41Sopenharmony_ci instance->set_managed_object_maps(*isolate->factory()->empty_fixed_array()); 12281cb0ef41Sopenharmony_ci instance->set_feedback_vectors(*isolate->factory()->empty_fixed_array()); 12291cb0ef41Sopenharmony_ci instance->set_tiering_budget_array( 12301cb0ef41Sopenharmony_ci module_object->native_module()->tiering_budget_array()); 12311cb0ef41Sopenharmony_ci instance->set_break_on_entry(module_object->script().break_on_entry()); 12321cb0ef41Sopenharmony_ci 12331cb0ef41Sopenharmony_ci // Insert the new instance into the scripts weak list of instances. This list 12341cb0ef41Sopenharmony_ci // is used for breakpoints affecting all instances belonging to the script. 12351cb0ef41Sopenharmony_ci if (module_object->script().type() == Script::TYPE_WASM) { 12361cb0ef41Sopenharmony_ci Handle<WeakArrayList> weak_instance_list( 12371cb0ef41Sopenharmony_ci module_object->script().wasm_weak_instance_list(), isolate); 12381cb0ef41Sopenharmony_ci weak_instance_list = WeakArrayList::Append( 12391cb0ef41Sopenharmony_ci isolate, weak_instance_list, MaybeObjectHandle::Weak(instance)); 12401cb0ef41Sopenharmony_ci module_object->script().set_wasm_weak_instance_list(*weak_instance_list); 12411cb0ef41Sopenharmony_ci } 12421cb0ef41Sopenharmony_ci 12431cb0ef41Sopenharmony_ci InitDataSegmentArrays(instance, module_object); 12441cb0ef41Sopenharmony_ci InitElemSegmentArrays(instance, module_object); 12451cb0ef41Sopenharmony_ci 12461cb0ef41Sopenharmony_ci return instance; 12471cb0ef41Sopenharmony_ci} 12481cb0ef41Sopenharmony_ci 12491cb0ef41Sopenharmony_ci// static 12501cb0ef41Sopenharmony_civoid WasmInstanceObject::InitDataSegmentArrays( 12511cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 12521cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object) { 12531cb0ef41Sopenharmony_ci auto module = module_object->module(); 12541cb0ef41Sopenharmony_ci auto wire_bytes = module_object->native_module()->wire_bytes(); 12551cb0ef41Sopenharmony_ci auto num_data_segments = module->num_declared_data_segments; 12561cb0ef41Sopenharmony_ci // The number of declared data segments will be zero if there is no DataCount 12571cb0ef41Sopenharmony_ci // section. These arrays will not be allocated nor initialized in that case, 12581cb0ef41Sopenharmony_ci // since they cannot be used (since the validator checks that number of 12591cb0ef41Sopenharmony_ci // declared data segments when validating the memory.init and memory.drop 12601cb0ef41Sopenharmony_ci // instructions). 12611cb0ef41Sopenharmony_ci DCHECK(num_data_segments == 0 || 12621cb0ef41Sopenharmony_ci num_data_segments == module->data_segments.size()); 12631cb0ef41Sopenharmony_ci for (size_t i = 0; i < num_data_segments; ++i) { 12641cb0ef41Sopenharmony_ci const wasm::WasmDataSegment& segment = module->data_segments[i]; 12651cb0ef41Sopenharmony_ci // Initialize the pointer and size of passive segments. 12661cb0ef41Sopenharmony_ci auto source_bytes = wire_bytes.SubVector(segment.source.offset(), 12671cb0ef41Sopenharmony_ci segment.source.end_offset()); 12681cb0ef41Sopenharmony_ci instance->data_segment_starts()[i] = 12691cb0ef41Sopenharmony_ci reinterpret_cast<Address>(source_bytes.begin()); 12701cb0ef41Sopenharmony_ci // Set the active segments to being already dropped, since memory.init on 12711cb0ef41Sopenharmony_ci // a dropped passive segment and an active segment have the same 12721cb0ef41Sopenharmony_ci // behavior. 12731cb0ef41Sopenharmony_ci instance->data_segment_sizes()[i] = 12741cb0ef41Sopenharmony_ci segment.active ? 0 : source_bytes.length(); 12751cb0ef41Sopenharmony_ci } 12761cb0ef41Sopenharmony_ci} 12771cb0ef41Sopenharmony_ci 12781cb0ef41Sopenharmony_civoid WasmInstanceObject::InitElemSegmentArrays( 12791cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 12801cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object) { 12811cb0ef41Sopenharmony_ci auto module = module_object->module(); 12821cb0ef41Sopenharmony_ci auto num_elem_segments = module->elem_segments.size(); 12831cb0ef41Sopenharmony_ci for (size_t i = 0; i < num_elem_segments; ++i) { 12841cb0ef41Sopenharmony_ci instance->dropped_elem_segments()[i] = 12851cb0ef41Sopenharmony_ci module->elem_segments[i].status == 12861cb0ef41Sopenharmony_ci wasm::WasmElemSegment::kStatusDeclarative 12871cb0ef41Sopenharmony_ci ? 1 12881cb0ef41Sopenharmony_ci : 0; 12891cb0ef41Sopenharmony_ci } 12901cb0ef41Sopenharmony_ci} 12911cb0ef41Sopenharmony_ci 12921cb0ef41Sopenharmony_ciAddress WasmInstanceObject::GetCallTarget(uint32_t func_index) { 12931cb0ef41Sopenharmony_ci wasm::NativeModule* native_module = module_object().native_module(); 12941cb0ef41Sopenharmony_ci if (func_index < native_module->num_imported_functions()) { 12951cb0ef41Sopenharmony_ci return imported_function_targets()[func_index]; 12961cb0ef41Sopenharmony_ci } 12971cb0ef41Sopenharmony_ci return native_module->GetCallTargetForFunction(func_index); 12981cb0ef41Sopenharmony_ci} 12991cb0ef41Sopenharmony_ci 13001cb0ef41Sopenharmony_ciHandle<WasmIndirectFunctionTable> WasmInstanceObject::GetIndirectFunctionTable( 13011cb0ef41Sopenharmony_ci Isolate* isolate, uint32_t table_index) { 13021cb0ef41Sopenharmony_ci DCHECK_LT(table_index, indirect_function_tables().length()); 13031cb0ef41Sopenharmony_ci return handle(WasmIndirectFunctionTable::cast( 13041cb0ef41Sopenharmony_ci indirect_function_tables().get(table_index)), 13051cb0ef41Sopenharmony_ci isolate); 13061cb0ef41Sopenharmony_ci} 13071cb0ef41Sopenharmony_ci 13081cb0ef41Sopenharmony_civoid WasmInstanceObject::SetIndirectFunctionTableShortcuts(Isolate* isolate) { 13091cb0ef41Sopenharmony_ci if (indirect_function_tables().length() > 0 && 13101cb0ef41Sopenharmony_ci indirect_function_tables().get(0).IsWasmIndirectFunctionTable()) { 13111cb0ef41Sopenharmony_ci HandleScope scope(isolate); 13121cb0ef41Sopenharmony_ci Handle<WasmIndirectFunctionTable> table0 = 13131cb0ef41Sopenharmony_ci GetIndirectFunctionTable(isolate, 0); 13141cb0ef41Sopenharmony_ci set_indirect_function_table_size(table0->size()); 13151cb0ef41Sopenharmony_ci set_indirect_function_table_refs(table0->refs()); 13161cb0ef41Sopenharmony_ci set_indirect_function_table_sig_ids(table0->sig_ids()); 13171cb0ef41Sopenharmony_ci set_indirect_function_table_targets(table0->targets()); 13181cb0ef41Sopenharmony_ci } 13191cb0ef41Sopenharmony_ci} 13201cb0ef41Sopenharmony_ci 13211cb0ef41Sopenharmony_ci// static 13221cb0ef41Sopenharmony_cibool WasmInstanceObject::CopyTableEntries(Isolate* isolate, 13231cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 13241cb0ef41Sopenharmony_ci uint32_t table_dst_index, 13251cb0ef41Sopenharmony_ci uint32_t table_src_index, 13261cb0ef41Sopenharmony_ci uint32_t dst, uint32_t src, 13271cb0ef41Sopenharmony_ci uint32_t count) { 13281cb0ef41Sopenharmony_ci CHECK_LT(table_dst_index, instance->tables().length()); 13291cb0ef41Sopenharmony_ci CHECK_LT(table_src_index, instance->tables().length()); 13301cb0ef41Sopenharmony_ci auto table_dst = handle( 13311cb0ef41Sopenharmony_ci WasmTableObject::cast(instance->tables().get(table_dst_index)), isolate); 13321cb0ef41Sopenharmony_ci auto table_src = handle( 13331cb0ef41Sopenharmony_ci WasmTableObject::cast(instance->tables().get(table_src_index)), isolate); 13341cb0ef41Sopenharmony_ci uint32_t max_dst = table_dst->current_length(); 13351cb0ef41Sopenharmony_ci uint32_t max_src = table_src->current_length(); 13361cb0ef41Sopenharmony_ci bool copy_backward = src < dst; 13371cb0ef41Sopenharmony_ci if (!base::IsInBounds(dst, count, max_dst) || 13381cb0ef41Sopenharmony_ci !base::IsInBounds(src, count, max_src)) { 13391cb0ef41Sopenharmony_ci return false; 13401cb0ef41Sopenharmony_ci } 13411cb0ef41Sopenharmony_ci 13421cb0ef41Sopenharmony_ci // no-op 13431cb0ef41Sopenharmony_ci if ((dst == src && table_dst_index == table_src_index) || count == 0) { 13441cb0ef41Sopenharmony_ci return true; 13451cb0ef41Sopenharmony_ci } 13461cb0ef41Sopenharmony_ci 13471cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < count; ++i) { 13481cb0ef41Sopenharmony_ci uint32_t src_index = copy_backward ? (src + count - i - 1) : src + i; 13491cb0ef41Sopenharmony_ci uint32_t dst_index = copy_backward ? (dst + count - i - 1) : dst + i; 13501cb0ef41Sopenharmony_ci auto value = WasmTableObject::Get(isolate, table_src, src_index); 13511cb0ef41Sopenharmony_ci WasmTableObject::Set(isolate, table_dst, dst_index, value); 13521cb0ef41Sopenharmony_ci } 13531cb0ef41Sopenharmony_ci return true; 13541cb0ef41Sopenharmony_ci} 13551cb0ef41Sopenharmony_ci 13561cb0ef41Sopenharmony_ci// static 13571cb0ef41Sopenharmony_cibool WasmInstanceObject::InitTableEntries(Isolate* isolate, 13581cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 13591cb0ef41Sopenharmony_ci uint32_t table_index, 13601cb0ef41Sopenharmony_ci uint32_t segment_index, uint32_t dst, 13611cb0ef41Sopenharmony_ci uint32_t src, uint32_t count) { 13621cb0ef41Sopenharmony_ci // Note that this implementation just calls through to module instantiation. 13631cb0ef41Sopenharmony_ci // This is intentional, so that the runtime only depends on the object 13641cb0ef41Sopenharmony_ci // methods, and not the module instantiation logic. 13651cb0ef41Sopenharmony_ci return wasm::LoadElemSegment(isolate, instance, table_index, segment_index, 13661cb0ef41Sopenharmony_ci dst, src, count); 13671cb0ef41Sopenharmony_ci} 13681cb0ef41Sopenharmony_ci 13691cb0ef41Sopenharmony_ciMaybeHandle<WasmInternalFunction> WasmInstanceObject::GetWasmInternalFunction( 13701cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, int index) { 13711cb0ef41Sopenharmony_ci MaybeHandle<WasmInternalFunction> result; 13721cb0ef41Sopenharmony_ci if (instance->has_wasm_internal_functions()) { 13731cb0ef41Sopenharmony_ci Object val = instance->wasm_internal_functions().get(index); 13741cb0ef41Sopenharmony_ci if (!val.IsUndefined(isolate)) { 13751cb0ef41Sopenharmony_ci result = Handle<WasmInternalFunction>(WasmInternalFunction::cast(val), 13761cb0ef41Sopenharmony_ci isolate); 13771cb0ef41Sopenharmony_ci } 13781cb0ef41Sopenharmony_ci } 13791cb0ef41Sopenharmony_ci return result; 13801cb0ef41Sopenharmony_ci} 13811cb0ef41Sopenharmony_ci 13821cb0ef41Sopenharmony_ciHandle<WasmInternalFunction> 13831cb0ef41Sopenharmony_ciWasmInstanceObject::GetOrCreateWasmInternalFunction( 13841cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, int function_index) { 13851cb0ef41Sopenharmony_ci MaybeHandle<WasmInternalFunction> maybe_result = 13861cb0ef41Sopenharmony_ci WasmInstanceObject::GetWasmInternalFunction(isolate, instance, 13871cb0ef41Sopenharmony_ci function_index); 13881cb0ef41Sopenharmony_ci 13891cb0ef41Sopenharmony_ci Handle<WasmInternalFunction> result; 13901cb0ef41Sopenharmony_ci if (maybe_result.ToHandle(&result)) { 13911cb0ef41Sopenharmony_ci return result; 13921cb0ef41Sopenharmony_ci } 13931cb0ef41Sopenharmony_ci 13941cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object(instance->module_object(), isolate); 13951cb0ef41Sopenharmony_ci const WasmModule* module = module_object->module(); 13961cb0ef41Sopenharmony_ci const WasmFunction& function = module->functions[function_index]; 13971cb0ef41Sopenharmony_ci int wrapper_index = 13981cb0ef41Sopenharmony_ci GetExportWrapperIndex(module, function.sig_index, function.imported); 13991cb0ef41Sopenharmony_ci DCHECK_EQ(wrapper_index, 14001cb0ef41Sopenharmony_ci GetExportWrapperIndex(module, function.sig, function.imported)); 14011cb0ef41Sopenharmony_ci 14021cb0ef41Sopenharmony_ci Handle<Object> entry = 14031cb0ef41Sopenharmony_ci FixedArray::get(module_object->export_wrappers(), wrapper_index, isolate); 14041cb0ef41Sopenharmony_ci 14051cb0ef41Sopenharmony_ci Handle<CodeT> wrapper; 14061cb0ef41Sopenharmony_ci if (entry->IsCodeT()) { 14071cb0ef41Sopenharmony_ci wrapper = Handle<CodeT>::cast(entry); 14081cb0ef41Sopenharmony_ci } else { 14091cb0ef41Sopenharmony_ci // The wrapper may not exist yet if no function in the exports section has 14101cb0ef41Sopenharmony_ci // this signature. We compile it and store the wrapper in the module for 14111cb0ef41Sopenharmony_ci // later use. 14121cb0ef41Sopenharmony_ci wrapper = ToCodeT( 14131cb0ef41Sopenharmony_ci wasm::JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper( 14141cb0ef41Sopenharmony_ci isolate, function.sig, instance->module(), function.imported), 14151cb0ef41Sopenharmony_ci isolate); 14161cb0ef41Sopenharmony_ci module_object->export_wrappers().set(wrapper_index, *wrapper); 14171cb0ef41Sopenharmony_ci } 14181cb0ef41Sopenharmony_ci auto external = Handle<WasmExternalFunction>::cast(WasmExportedFunction::New( 14191cb0ef41Sopenharmony_ci isolate, instance, function_index, 14201cb0ef41Sopenharmony_ci static_cast<int>(function.sig->parameter_count()), wrapper)); 14211cb0ef41Sopenharmony_ci result = 14221cb0ef41Sopenharmony_ci WasmInternalFunction::FromExternal(external, isolate).ToHandleChecked(); 14231cb0ef41Sopenharmony_ci 14241cb0ef41Sopenharmony_ci WasmInstanceObject::SetWasmInternalFunction(isolate, instance, function_index, 14251cb0ef41Sopenharmony_ci result); 14261cb0ef41Sopenharmony_ci return result; 14271cb0ef41Sopenharmony_ci} 14281cb0ef41Sopenharmony_ci 14291cb0ef41Sopenharmony_civoid WasmInstanceObject::SetWasmInternalFunction( 14301cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, int index, 14311cb0ef41Sopenharmony_ci Handle<WasmInternalFunction> val) { 14321cb0ef41Sopenharmony_ci Handle<FixedArray> functions; 14331cb0ef41Sopenharmony_ci if (!instance->has_wasm_internal_functions()) { 14341cb0ef41Sopenharmony_ci // Lazily allocate the wasm external functions array. 14351cb0ef41Sopenharmony_ci functions = isolate->factory()->NewFixedArray( 14361cb0ef41Sopenharmony_ci static_cast<int>(instance->module()->functions.size())); 14371cb0ef41Sopenharmony_ci instance->set_wasm_internal_functions(*functions); 14381cb0ef41Sopenharmony_ci } else { 14391cb0ef41Sopenharmony_ci functions = 14401cb0ef41Sopenharmony_ci Handle<FixedArray>(instance->wasm_internal_functions(), isolate); 14411cb0ef41Sopenharmony_ci } 14421cb0ef41Sopenharmony_ci functions->set(index, *val); 14431cb0ef41Sopenharmony_ci} 14441cb0ef41Sopenharmony_ci 14451cb0ef41Sopenharmony_ci// static 14461cb0ef41Sopenharmony_civoid WasmInstanceObject::ImportWasmJSFunctionIntoTable( 14471cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, int table_index, 14481cb0ef41Sopenharmony_ci int entry_index, Handle<WasmJSFunction> js_function) { 14491cb0ef41Sopenharmony_ci // Deserialize the signature encapsulated with the {WasmJSFunction}. 14501cb0ef41Sopenharmony_ci // Note that {SignatureMap::Find} may return {-1} if the signature is 14511cb0ef41Sopenharmony_ci // not found; it will simply never match any check. 14521cb0ef41Sopenharmony_ci Zone zone(isolate->allocator(), ZONE_NAME); 14531cb0ef41Sopenharmony_ci const wasm::FunctionSig* sig = js_function->GetSignature(&zone); 14541cb0ef41Sopenharmony_ci auto sig_id = instance->module()->signature_map.Find(*sig); 14551cb0ef41Sopenharmony_ci 14561cb0ef41Sopenharmony_ci // Compile a wrapper for the target callable. 14571cb0ef41Sopenharmony_ci Handle<JSReceiver> callable(js_function->GetCallable(), isolate); 14581cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 14591cb0ef41Sopenharmony_ci Address call_target = kNullAddress; 14601cb0ef41Sopenharmony_ci if (sig_id >= 0) { 14611cb0ef41Sopenharmony_ci wasm::NativeModule* native_module = 14621cb0ef41Sopenharmony_ci instance->module_object().native_module(); 14631cb0ef41Sopenharmony_ci // TODO(wasm): Cache and reuse wrapper code, to avoid repeated compilation 14641cb0ef41Sopenharmony_ci // and permissions switching. 14651cb0ef41Sopenharmony_ci const wasm::WasmFeatures enabled = native_module->enabled_features(); 14661cb0ef41Sopenharmony_ci auto resolved = compiler::ResolveWasmImportCall( 14671cb0ef41Sopenharmony_ci callable, sig, instance->module(), enabled); 14681cb0ef41Sopenharmony_ci compiler::WasmImportCallKind kind = resolved.kind; 14691cb0ef41Sopenharmony_ci callable = resolved.callable; // Update to ultimate target. 14701cb0ef41Sopenharmony_ci DCHECK_NE(compiler::WasmImportCallKind::kLinkError, kind); 14711cb0ef41Sopenharmony_ci wasm::CompilationEnv env = native_module->CreateCompilationEnv(); 14721cb0ef41Sopenharmony_ci // {expected_arity} should only be used if kind != kJSFunctionArityMismatch. 14731cb0ef41Sopenharmony_ci int expected_arity = -1; 14741cb0ef41Sopenharmony_ci if (kind == compiler::WasmImportCallKind ::kJSFunctionArityMismatch) { 14751cb0ef41Sopenharmony_ci expected_arity = Handle<JSFunction>::cast(callable) 14761cb0ef41Sopenharmony_ci ->shared() 14771cb0ef41Sopenharmony_ci .internal_formal_parameter_count_without_receiver(); 14781cb0ef41Sopenharmony_ci } 14791cb0ef41Sopenharmony_ci wasm::Suspend suspend = 14801cb0ef41Sopenharmony_ci resolved.suspender.is_null() || resolved.suspender->IsUndefined() 14811cb0ef41Sopenharmony_ci ? wasm::kNoSuspend 14821cb0ef41Sopenharmony_ci : wasm::kSuspend; 14831cb0ef41Sopenharmony_ci // TODO(manoskouk): Reuse js_function->wasm_to_js_wrapper_code(). 14841cb0ef41Sopenharmony_ci wasm::WasmCompilationResult result = compiler::CompileWasmImportCallWrapper( 14851cb0ef41Sopenharmony_ci &env, kind, sig, false, expected_arity, suspend); 14861cb0ef41Sopenharmony_ci wasm::CodeSpaceWriteScope write_scope(native_module); 14871cb0ef41Sopenharmony_ci std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( 14881cb0ef41Sopenharmony_ci result.func_index, result.code_desc, result.frame_slot_count, 14891cb0ef41Sopenharmony_ci result.tagged_parameter_slots, 14901cb0ef41Sopenharmony_ci result.protected_instructions_data.as_vector(), 14911cb0ef41Sopenharmony_ci result.source_positions.as_vector(), GetCodeKind(result), 14921cb0ef41Sopenharmony_ci wasm::ExecutionTier::kNone, wasm::kNoDebugging); 14931cb0ef41Sopenharmony_ci wasm::WasmCode* published_code = 14941cb0ef41Sopenharmony_ci native_module->PublishCode(std::move(wasm_code)); 14951cb0ef41Sopenharmony_ci isolate->counters()->wasm_generated_code_size()->Increment( 14961cb0ef41Sopenharmony_ci published_code->instructions().length()); 14971cb0ef41Sopenharmony_ci isolate->counters()->wasm_reloc_size()->Increment( 14981cb0ef41Sopenharmony_ci published_code->reloc_info().length()); 14991cb0ef41Sopenharmony_ci call_target = published_code->instruction_start(); 15001cb0ef41Sopenharmony_ci } 15011cb0ef41Sopenharmony_ci 15021cb0ef41Sopenharmony_ci // Update the dispatch table. 15031cb0ef41Sopenharmony_ci Handle<HeapObject> suspender = handle(js_function->GetSuspender(), isolate); 15041cb0ef41Sopenharmony_ci Handle<WasmApiFunctionRef> ref = 15051cb0ef41Sopenharmony_ci isolate->factory()->NewWasmApiFunctionRef(callable, suspender); 15061cb0ef41Sopenharmony_ci WasmIndirectFunctionTable::cast( 15071cb0ef41Sopenharmony_ci instance->indirect_function_tables().get(table_index)) 15081cb0ef41Sopenharmony_ci .Set(entry_index, sig_id, call_target, *ref); 15091cb0ef41Sopenharmony_ci} 15101cb0ef41Sopenharmony_ci 15111cb0ef41Sopenharmony_ci// static 15121cb0ef41Sopenharmony_ciuint8_t* WasmInstanceObject::GetGlobalStorage( 15131cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, const wasm::WasmGlobal& global) { 15141cb0ef41Sopenharmony_ci DCHECK(!global.type.is_reference()); 15151cb0ef41Sopenharmony_ci if (global.mutability && global.imported) { 15161cb0ef41Sopenharmony_ci return reinterpret_cast<byte*>( 15171cb0ef41Sopenharmony_ci instance->imported_mutable_globals()[global.index]); 15181cb0ef41Sopenharmony_ci } else { 15191cb0ef41Sopenharmony_ci return instance->globals_start() + global.offset; 15201cb0ef41Sopenharmony_ci } 15211cb0ef41Sopenharmony_ci} 15221cb0ef41Sopenharmony_ci 15231cb0ef41Sopenharmony_ci// static 15241cb0ef41Sopenharmony_cistd::pair<Handle<FixedArray>, uint32_t> 15251cb0ef41Sopenharmony_ciWasmInstanceObject::GetGlobalBufferAndIndex(Handle<WasmInstanceObject> instance, 15261cb0ef41Sopenharmony_ci const wasm::WasmGlobal& global) { 15271cb0ef41Sopenharmony_ci DCHECK(global.type.is_reference()); 15281cb0ef41Sopenharmony_ci Isolate* isolate = instance->GetIsolate(); 15291cb0ef41Sopenharmony_ci if (global.mutability && global.imported) { 15301cb0ef41Sopenharmony_ci Handle<FixedArray> buffer( 15311cb0ef41Sopenharmony_ci FixedArray::cast( 15321cb0ef41Sopenharmony_ci instance->imported_mutable_globals_buffers().get(global.index)), 15331cb0ef41Sopenharmony_ci isolate); 15341cb0ef41Sopenharmony_ci Address idx = instance->imported_mutable_globals()[global.index]; 15351cb0ef41Sopenharmony_ci DCHECK_LE(idx, std::numeric_limits<uint32_t>::max()); 15361cb0ef41Sopenharmony_ci return {buffer, static_cast<uint32_t>(idx)}; 15371cb0ef41Sopenharmony_ci } 15381cb0ef41Sopenharmony_ci return {handle(instance->tagged_globals_buffer(), isolate), global.offset}; 15391cb0ef41Sopenharmony_ci} 15401cb0ef41Sopenharmony_ci 15411cb0ef41Sopenharmony_ci// static 15421cb0ef41Sopenharmony_ciwasm::WasmValue WasmInstanceObject::GetGlobalValue( 15431cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, const wasm::WasmGlobal& global) { 15441cb0ef41Sopenharmony_ci Isolate* isolate = instance->GetIsolate(); 15451cb0ef41Sopenharmony_ci if (global.type.is_reference()) { 15461cb0ef41Sopenharmony_ci Handle<FixedArray> global_buffer; // The buffer of the global. 15471cb0ef41Sopenharmony_ci uint32_t global_index = 0; // The index into the buffer. 15481cb0ef41Sopenharmony_ci std::tie(global_buffer, global_index) = 15491cb0ef41Sopenharmony_ci GetGlobalBufferAndIndex(instance, global); 15501cb0ef41Sopenharmony_ci return wasm::WasmValue(handle(global_buffer->get(global_index), isolate), 15511cb0ef41Sopenharmony_ci global.type); 15521cb0ef41Sopenharmony_ci } 15531cb0ef41Sopenharmony_ci Address ptr = reinterpret_cast<Address>(GetGlobalStorage(instance, global)); 15541cb0ef41Sopenharmony_ci using wasm::Simd128; 15551cb0ef41Sopenharmony_ci switch (global.type.kind()) { 15561cb0ef41Sopenharmony_ci#define CASE_TYPE(valuetype, ctype) \ 15571cb0ef41Sopenharmony_ci case wasm::valuetype: \ 15581cb0ef41Sopenharmony_ci return wasm::WasmValue(base::ReadUnalignedValue<ctype>(ptr)); 15591cb0ef41Sopenharmony_ci FOREACH_WASMVALUE_CTYPES(CASE_TYPE) 15601cb0ef41Sopenharmony_ci#undef CASE_TYPE 15611cb0ef41Sopenharmony_ci default: 15621cb0ef41Sopenharmony_ci UNREACHABLE(); 15631cb0ef41Sopenharmony_ci } 15641cb0ef41Sopenharmony_ci} 15651cb0ef41Sopenharmony_ci 15661cb0ef41Sopenharmony_ciwasm::WasmValue WasmStruct::GetFieldValue(uint32_t index) { 15671cb0ef41Sopenharmony_ci wasm::ValueType field_type = type()->field(index); 15681cb0ef41Sopenharmony_ci int field_offset = WasmStruct::kHeaderSize + type()->field_offset(index); 15691cb0ef41Sopenharmony_ci Address field_address = GetFieldAddress(field_offset); 15701cb0ef41Sopenharmony_ci using wasm::Simd128; 15711cb0ef41Sopenharmony_ci switch (field_type.kind()) { 15721cb0ef41Sopenharmony_ci#define CASE_TYPE(valuetype, ctype) \ 15731cb0ef41Sopenharmony_ci case wasm::valuetype: \ 15741cb0ef41Sopenharmony_ci return wasm::WasmValue(base::ReadUnalignedValue<ctype>(field_address)); 15751cb0ef41Sopenharmony_ci CASE_TYPE(kI8, int8_t) 15761cb0ef41Sopenharmony_ci CASE_TYPE(kI16, int16_t) 15771cb0ef41Sopenharmony_ci FOREACH_WASMVALUE_CTYPES(CASE_TYPE) 15781cb0ef41Sopenharmony_ci#undef CASE_TYPE 15791cb0ef41Sopenharmony_ci case wasm::kRef: 15801cb0ef41Sopenharmony_ci case wasm::kOptRef: { 15811cb0ef41Sopenharmony_ci Handle<Object> ref(TaggedField<Object>::load(*this, field_offset), 15821cb0ef41Sopenharmony_ci GetIsolateFromWritableObject(*this)); 15831cb0ef41Sopenharmony_ci return wasm::WasmValue(ref, field_type); 15841cb0ef41Sopenharmony_ci } 15851cb0ef41Sopenharmony_ci case wasm::kRtt: 15861cb0ef41Sopenharmony_ci // TODO(7748): Expose RTTs to DevTools. 15871cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 15881cb0ef41Sopenharmony_ci case wasm::kVoid: 15891cb0ef41Sopenharmony_ci case wasm::kBottom: 15901cb0ef41Sopenharmony_ci UNREACHABLE(); 15911cb0ef41Sopenharmony_ci } 15921cb0ef41Sopenharmony_ci} 15931cb0ef41Sopenharmony_ci 15941cb0ef41Sopenharmony_ciwasm::WasmValue WasmArray::GetElement(uint32_t index) { 15951cb0ef41Sopenharmony_ci wasm::ValueType element_type = type()->element_type(); 15961cb0ef41Sopenharmony_ci int element_offset = 15971cb0ef41Sopenharmony_ci WasmArray::kHeaderSize + index * element_type.value_kind_size(); 15981cb0ef41Sopenharmony_ci Address element_address = GetFieldAddress(element_offset); 15991cb0ef41Sopenharmony_ci using wasm::Simd128; 16001cb0ef41Sopenharmony_ci switch (element_type.kind()) { 16011cb0ef41Sopenharmony_ci#define CASE_TYPE(value_type, ctype) \ 16021cb0ef41Sopenharmony_ci case wasm::value_type: \ 16031cb0ef41Sopenharmony_ci return wasm::WasmValue(base::ReadUnalignedValue<ctype>(element_address)); 16041cb0ef41Sopenharmony_ci CASE_TYPE(kI8, int8_t) 16051cb0ef41Sopenharmony_ci CASE_TYPE(kI16, int16_t) 16061cb0ef41Sopenharmony_ci FOREACH_WASMVALUE_CTYPES(CASE_TYPE) 16071cb0ef41Sopenharmony_ci#undef CASE_TYPE 16081cb0ef41Sopenharmony_ci case wasm::kRef: 16091cb0ef41Sopenharmony_ci case wasm::kOptRef: { 16101cb0ef41Sopenharmony_ci Handle<Object> ref(TaggedField<Object>::load(*this, element_offset), 16111cb0ef41Sopenharmony_ci GetIsolateFromWritableObject(*this)); 16121cb0ef41Sopenharmony_ci return wasm::WasmValue(ref, element_type); 16131cb0ef41Sopenharmony_ci } 16141cb0ef41Sopenharmony_ci case wasm::kRtt: 16151cb0ef41Sopenharmony_ci // TODO(7748): Expose RTTs to DevTools. 16161cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 16171cb0ef41Sopenharmony_ci case wasm::kVoid: 16181cb0ef41Sopenharmony_ci case wasm::kBottom: 16191cb0ef41Sopenharmony_ci UNREACHABLE(); 16201cb0ef41Sopenharmony_ci } 16211cb0ef41Sopenharmony_ci} 16221cb0ef41Sopenharmony_ci 16231cb0ef41Sopenharmony_ci// static 16241cb0ef41Sopenharmony_ciHandle<WasmTagObject> WasmTagObject::New(Isolate* isolate, 16251cb0ef41Sopenharmony_ci const wasm::FunctionSig* sig, 16261cb0ef41Sopenharmony_ci Handle<HeapObject> tag) { 16271cb0ef41Sopenharmony_ci Handle<JSFunction> tag_cons(isolate->native_context()->wasm_tag_constructor(), 16281cb0ef41Sopenharmony_ci isolate); 16291cb0ef41Sopenharmony_ci 16301cb0ef41Sopenharmony_ci // Serialize the signature. 16311cb0ef41Sopenharmony_ci DCHECK_EQ(0, sig->return_count()); 16321cb0ef41Sopenharmony_ci DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max()); 16331cb0ef41Sopenharmony_ci int sig_size = static_cast<int>(sig->parameter_count()); 16341cb0ef41Sopenharmony_ci Handle<PodArray<wasm::ValueType>> serialized_sig = 16351cb0ef41Sopenharmony_ci PodArray<wasm::ValueType>::New(isolate, sig_size, AllocationType::kOld); 16361cb0ef41Sopenharmony_ci int index = 0; // Index into the {PodArray} above. 16371cb0ef41Sopenharmony_ci for (wasm::ValueType param : sig->parameters()) { 16381cb0ef41Sopenharmony_ci serialized_sig->set(index++, param); 16391cb0ef41Sopenharmony_ci } 16401cb0ef41Sopenharmony_ci 16411cb0ef41Sopenharmony_ci Handle<JSObject> tag_object = 16421cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(tag_cons, AllocationType::kOld); 16431cb0ef41Sopenharmony_ci Handle<WasmTagObject> tag_wrapper = Handle<WasmTagObject>::cast(tag_object); 16441cb0ef41Sopenharmony_ci tag_wrapper->set_serialized_signature(*serialized_sig); 16451cb0ef41Sopenharmony_ci tag_wrapper->set_tag(*tag); 16461cb0ef41Sopenharmony_ci 16471cb0ef41Sopenharmony_ci return tag_wrapper; 16481cb0ef41Sopenharmony_ci} 16491cb0ef41Sopenharmony_ci 16501cb0ef41Sopenharmony_ci// TODO(9495): Update this if function type variance is introduced. 16511cb0ef41Sopenharmony_cibool WasmTagObject::MatchesSignature(const wasm::FunctionSig* sig) { 16521cb0ef41Sopenharmony_ci DCHECK_EQ(0, sig->return_count()); 16531cb0ef41Sopenharmony_ci DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max()); 16541cb0ef41Sopenharmony_ci int sig_size = static_cast<int>(sig->parameter_count()); 16551cb0ef41Sopenharmony_ci if (sig_size != serialized_signature().length()) return false; 16561cb0ef41Sopenharmony_ci for (int index = 0; index < sig_size; ++index) { 16571cb0ef41Sopenharmony_ci if (sig->GetParam(index) != serialized_signature().get(index)) { 16581cb0ef41Sopenharmony_ci return false; 16591cb0ef41Sopenharmony_ci } 16601cb0ef41Sopenharmony_ci } 16611cb0ef41Sopenharmony_ci return true; 16621cb0ef41Sopenharmony_ci} 16631cb0ef41Sopenharmony_ci 16641cb0ef41Sopenharmony_ci// TODO(9495): Update this if function type variance is introduced. 16651cb0ef41Sopenharmony_cibool WasmCapiFunction::MatchesSignature(const wasm::FunctionSig* sig) const { 16661cb0ef41Sopenharmony_ci // TODO(jkummerow): Unify with "SignatureHelper" in c-api.cc. 16671cb0ef41Sopenharmony_ci int param_count = static_cast<int>(sig->parameter_count()); 16681cb0ef41Sopenharmony_ci int result_count = static_cast<int>(sig->return_count()); 16691cb0ef41Sopenharmony_ci PodArray<wasm::ValueType> serialized_sig = 16701cb0ef41Sopenharmony_ci shared().wasm_capi_function_data().serialized_signature(); 16711cb0ef41Sopenharmony_ci if (param_count + result_count + 1 != serialized_sig.length()) return false; 16721cb0ef41Sopenharmony_ci int serialized_index = 0; 16731cb0ef41Sopenharmony_ci for (int i = 0; i < result_count; i++, serialized_index++) { 16741cb0ef41Sopenharmony_ci if (sig->GetReturn(i) != serialized_sig.get(serialized_index)) { 16751cb0ef41Sopenharmony_ci return false; 16761cb0ef41Sopenharmony_ci } 16771cb0ef41Sopenharmony_ci } 16781cb0ef41Sopenharmony_ci if (serialized_sig.get(serialized_index) != wasm::kWasmVoid) return false; 16791cb0ef41Sopenharmony_ci serialized_index++; 16801cb0ef41Sopenharmony_ci for (int i = 0; i < param_count; i++, serialized_index++) { 16811cb0ef41Sopenharmony_ci if (sig->GetParam(i) != serialized_sig.get(serialized_index)) return false; 16821cb0ef41Sopenharmony_ci } 16831cb0ef41Sopenharmony_ci return true; 16841cb0ef41Sopenharmony_ci} 16851cb0ef41Sopenharmony_ci 16861cb0ef41Sopenharmony_ci// static 16871cb0ef41Sopenharmony_ciHandle<WasmExceptionPackage> WasmExceptionPackage::New( 16881cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmExceptionTag> exception_tag, int size) { 16891cb0ef41Sopenharmony_ci Handle<FixedArray> values = isolate->factory()->NewFixedArray(size); 16901cb0ef41Sopenharmony_ci return New(isolate, exception_tag, values); 16911cb0ef41Sopenharmony_ci} 16921cb0ef41Sopenharmony_ci 16931cb0ef41Sopenharmony_ciHandle<WasmExceptionPackage> WasmExceptionPackage::New( 16941cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmExceptionTag> exception_tag, 16951cb0ef41Sopenharmony_ci Handle<FixedArray> values) { 16961cb0ef41Sopenharmony_ci Handle<JSObject> exception = isolate->factory()->NewWasmExceptionError( 16971cb0ef41Sopenharmony_ci MessageTemplate::kWasmExceptionError); 16981cb0ef41Sopenharmony_ci CHECK(!Object::SetProperty(isolate, exception, 16991cb0ef41Sopenharmony_ci isolate->factory()->wasm_exception_tag_symbol(), 17001cb0ef41Sopenharmony_ci exception_tag, StoreOrigin::kMaybeKeyed, 17011cb0ef41Sopenharmony_ci Just(ShouldThrow::kThrowOnError)) 17021cb0ef41Sopenharmony_ci .is_null()); 17031cb0ef41Sopenharmony_ci CHECK(!Object::SetProperty(isolate, exception, 17041cb0ef41Sopenharmony_ci isolate->factory()->wasm_exception_values_symbol(), 17051cb0ef41Sopenharmony_ci values, StoreOrigin::kMaybeKeyed, 17061cb0ef41Sopenharmony_ci Just(ShouldThrow::kThrowOnError)) 17071cb0ef41Sopenharmony_ci .is_null()); 17081cb0ef41Sopenharmony_ci return Handle<WasmExceptionPackage>::cast(exception); 17091cb0ef41Sopenharmony_ci} 17101cb0ef41Sopenharmony_ci 17111cb0ef41Sopenharmony_ci// static 17121cb0ef41Sopenharmony_ciHandle<Object> WasmExceptionPackage::GetExceptionTag( 17131cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmExceptionPackage> exception_package) { 17141cb0ef41Sopenharmony_ci Handle<Object> tag; 17151cb0ef41Sopenharmony_ci if (JSReceiver::GetProperty(isolate, exception_package, 17161cb0ef41Sopenharmony_ci isolate->factory()->wasm_exception_tag_symbol()) 17171cb0ef41Sopenharmony_ci .ToHandle(&tag)) { 17181cb0ef41Sopenharmony_ci return tag; 17191cb0ef41Sopenharmony_ci } 17201cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).undefined_value_handle(); 17211cb0ef41Sopenharmony_ci} 17221cb0ef41Sopenharmony_ci 17231cb0ef41Sopenharmony_ci// static 17241cb0ef41Sopenharmony_ciHandle<Object> WasmExceptionPackage::GetExceptionValues( 17251cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmExceptionPackage> exception_package) { 17261cb0ef41Sopenharmony_ci Handle<Object> values; 17271cb0ef41Sopenharmony_ci if (JSReceiver::GetProperty( 17281cb0ef41Sopenharmony_ci isolate, exception_package, 17291cb0ef41Sopenharmony_ci isolate->factory()->wasm_exception_values_symbol()) 17301cb0ef41Sopenharmony_ci .ToHandle(&values)) { 17311cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!values->IsUndefined(), values->IsFixedArray()); 17321cb0ef41Sopenharmony_ci return values; 17331cb0ef41Sopenharmony_ci } 17341cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate).undefined_value_handle(); 17351cb0ef41Sopenharmony_ci} 17361cb0ef41Sopenharmony_ci 17371cb0ef41Sopenharmony_civoid EncodeI32ExceptionValue(Handle<FixedArray> encoded_values, 17381cb0ef41Sopenharmony_ci uint32_t* encoded_index, uint32_t value) { 17391cb0ef41Sopenharmony_ci encoded_values->set((*encoded_index)++, Smi::FromInt(value >> 16)); 17401cb0ef41Sopenharmony_ci encoded_values->set((*encoded_index)++, Smi::FromInt(value & 0xffff)); 17411cb0ef41Sopenharmony_ci} 17421cb0ef41Sopenharmony_ci 17431cb0ef41Sopenharmony_civoid EncodeI64ExceptionValue(Handle<FixedArray> encoded_values, 17441cb0ef41Sopenharmony_ci uint32_t* encoded_index, uint64_t value) { 17451cb0ef41Sopenharmony_ci EncodeI32ExceptionValue(encoded_values, encoded_index, 17461cb0ef41Sopenharmony_ci static_cast<uint32_t>(value >> 32)); 17471cb0ef41Sopenharmony_ci EncodeI32ExceptionValue(encoded_values, encoded_index, 17481cb0ef41Sopenharmony_ci static_cast<uint32_t>(value)); 17491cb0ef41Sopenharmony_ci} 17501cb0ef41Sopenharmony_ci 17511cb0ef41Sopenharmony_civoid DecodeI32ExceptionValue(Handle<FixedArray> encoded_values, 17521cb0ef41Sopenharmony_ci uint32_t* encoded_index, uint32_t* value) { 17531cb0ef41Sopenharmony_ci uint32_t msb = Smi::cast(encoded_values->get((*encoded_index)++)).value(); 17541cb0ef41Sopenharmony_ci uint32_t lsb = Smi::cast(encoded_values->get((*encoded_index)++)).value(); 17551cb0ef41Sopenharmony_ci *value = (msb << 16) | (lsb & 0xffff); 17561cb0ef41Sopenharmony_ci} 17571cb0ef41Sopenharmony_ci 17581cb0ef41Sopenharmony_civoid DecodeI64ExceptionValue(Handle<FixedArray> encoded_values, 17591cb0ef41Sopenharmony_ci uint32_t* encoded_index, uint64_t* value) { 17601cb0ef41Sopenharmony_ci uint32_t lsb = 0, msb = 0; 17611cb0ef41Sopenharmony_ci DecodeI32ExceptionValue(encoded_values, encoded_index, &msb); 17621cb0ef41Sopenharmony_ci DecodeI32ExceptionValue(encoded_values, encoded_index, &lsb); 17631cb0ef41Sopenharmony_ci *value = (static_cast<uint64_t>(msb) << 32) | static_cast<uint64_t>(lsb); 17641cb0ef41Sopenharmony_ci} 17651cb0ef41Sopenharmony_ci 17661cb0ef41Sopenharmony_ci// static 17671cb0ef41Sopenharmony_ciHandle<WasmContinuationObject> WasmContinuationObject::New( 17681cb0ef41Sopenharmony_ci Isolate* isolate, std::unique_ptr<wasm::StackMemory> stack, 17691cb0ef41Sopenharmony_ci Handle<HeapObject> parent) { 17701cb0ef41Sopenharmony_ci stack->jmpbuf()->stack_limit = stack->jslimit(); 17711cb0ef41Sopenharmony_ci stack->jmpbuf()->sp = stack->base(); 17721cb0ef41Sopenharmony_ci stack->jmpbuf()->fp = kNullAddress; 17731cb0ef41Sopenharmony_ci wasm::JumpBuffer* jmpbuf = stack->jmpbuf(); 17741cb0ef41Sopenharmony_ci size_t external_size = stack->owned_size(); 17751cb0ef41Sopenharmony_ci Handle<Foreign> managed_stack = Managed<wasm::StackMemory>::FromUniquePtr( 17761cb0ef41Sopenharmony_ci isolate, external_size, std::move(stack)); 17771cb0ef41Sopenharmony_ci Handle<Foreign> foreign_jmpbuf = 17781cb0ef41Sopenharmony_ci isolate->factory()->NewForeign(reinterpret_cast<Address>(jmpbuf)); 17791cb0ef41Sopenharmony_ci Handle<WasmContinuationObject> result = Handle<WasmContinuationObject>::cast( 17801cb0ef41Sopenharmony_ci isolate->factory()->NewStruct(WASM_CONTINUATION_OBJECT_TYPE)); 17811cb0ef41Sopenharmony_ci result->set_jmpbuf(*foreign_jmpbuf); 17821cb0ef41Sopenharmony_ci result->set_stack(*managed_stack); 17831cb0ef41Sopenharmony_ci result->set_parent(*parent); 17841cb0ef41Sopenharmony_ci return result; 17851cb0ef41Sopenharmony_ci} 17861cb0ef41Sopenharmony_ci 17871cb0ef41Sopenharmony_ci// static 17881cb0ef41Sopenharmony_ciHandle<WasmContinuationObject> WasmContinuationObject::New( 17891cb0ef41Sopenharmony_ci Isolate* isolate, std::unique_ptr<wasm::StackMemory> stack) { 17901cb0ef41Sopenharmony_ci auto parent = ReadOnlyRoots(isolate).undefined_value(); 17911cb0ef41Sopenharmony_ci return New(isolate, std::move(stack), handle(parent, isolate)); 17921cb0ef41Sopenharmony_ci} 17931cb0ef41Sopenharmony_ci 17941cb0ef41Sopenharmony_ci// static 17951cb0ef41Sopenharmony_ciHandle<WasmContinuationObject> WasmContinuationObject::New( 17961cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmContinuationObject> parent) { 17971cb0ef41Sopenharmony_ci auto stack = 17981cb0ef41Sopenharmony_ci std::unique_ptr<wasm::StackMemory>(wasm::StackMemory::New(isolate)); 17991cb0ef41Sopenharmony_ci return New(isolate, std::move(stack), parent); 18001cb0ef41Sopenharmony_ci} 18011cb0ef41Sopenharmony_ci 18021cb0ef41Sopenharmony_ci// static 18031cb0ef41Sopenharmony_ciHandle<WasmSuspenderObject> WasmSuspenderObject::New(Isolate* isolate) { 18041cb0ef41Sopenharmony_ci Handle<JSFunction> suspender_cons( 18051cb0ef41Sopenharmony_ci isolate->native_context()->wasm_suspender_constructor(), isolate); 18061cb0ef41Sopenharmony_ci // Suspender objects should be at least as long-lived as the instances of 18071cb0ef41Sopenharmony_ci // which it will wrap the imports/exports, allocate in old space too. 18081cb0ef41Sopenharmony_ci auto suspender = Handle<WasmSuspenderObject>::cast( 18091cb0ef41Sopenharmony_ci isolate->factory()->NewJSObject(suspender_cons, AllocationType::kOld)); 18101cb0ef41Sopenharmony_ci suspender->set_continuation(ReadOnlyRoots(isolate).undefined_value()); 18111cb0ef41Sopenharmony_ci suspender->set_parent(ReadOnlyRoots(isolate).undefined_value()); 18121cb0ef41Sopenharmony_ci suspender->set_state(Inactive); 18131cb0ef41Sopenharmony_ci // Instantiate the callable object which resumes this Suspender. This will be 18141cb0ef41Sopenharmony_ci // used implicitly as the onFulfilled callback of the returned JS promise. 18151cb0ef41Sopenharmony_ci Handle<WasmOnFulfilledData> function_data = 18161cb0ef41Sopenharmony_ci isolate->factory()->NewWasmOnFulfilledData(suspender); 18171cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared = 18181cb0ef41Sopenharmony_ci isolate->factory()->NewSharedFunctionInfoForWasmOnFulfilled( 18191cb0ef41Sopenharmony_ci function_data); 18201cb0ef41Sopenharmony_ci Handle<Context> context(isolate->native_context()); 18211cb0ef41Sopenharmony_ci Handle<JSObject> resume = 18221cb0ef41Sopenharmony_ci Factory::JSFunctionBuilder{isolate, shared, context}.Build(); 18231cb0ef41Sopenharmony_ci suspender->set_resume(*resume); 18241cb0ef41Sopenharmony_ci return suspender; 18251cb0ef41Sopenharmony_ci} 18261cb0ef41Sopenharmony_ci 18271cb0ef41Sopenharmony_ci#ifdef DEBUG 18281cb0ef41Sopenharmony_ci 18291cb0ef41Sopenharmony_cinamespace { 18301cb0ef41Sopenharmony_ci 18311cb0ef41Sopenharmony_ciconstexpr uint32_t kBytesPerExceptionValuesArrayElement = 2; 18321cb0ef41Sopenharmony_ci 18331cb0ef41Sopenharmony_cisize_t ComputeEncodedElementSize(wasm::ValueType type) { 18341cb0ef41Sopenharmony_ci size_t byte_size = type.value_kind_size(); 18351cb0ef41Sopenharmony_ci DCHECK_EQ(byte_size % kBytesPerExceptionValuesArrayElement, 0); 18361cb0ef41Sopenharmony_ci DCHECK_LE(1, byte_size / kBytesPerExceptionValuesArrayElement); 18371cb0ef41Sopenharmony_ci return byte_size / kBytesPerExceptionValuesArrayElement; 18381cb0ef41Sopenharmony_ci} 18391cb0ef41Sopenharmony_ci 18401cb0ef41Sopenharmony_ci} // namespace 18411cb0ef41Sopenharmony_ci 18421cb0ef41Sopenharmony_ci#endif // DEBUG 18431cb0ef41Sopenharmony_ci 18441cb0ef41Sopenharmony_ci// static 18451cb0ef41Sopenharmony_ciuint32_t WasmExceptionPackage::GetEncodedSize(const wasm::WasmTag* tag) { 18461cb0ef41Sopenharmony_ci const wasm::WasmTagSig* sig = tag->sig; 18471cb0ef41Sopenharmony_ci uint32_t encoded_size = 0; 18481cb0ef41Sopenharmony_ci for (size_t i = 0; i < sig->parameter_count(); ++i) { 18491cb0ef41Sopenharmony_ci switch (sig->GetParam(i).kind()) { 18501cb0ef41Sopenharmony_ci case wasm::kI32: 18511cb0ef41Sopenharmony_ci case wasm::kF32: 18521cb0ef41Sopenharmony_ci DCHECK_EQ(2, ComputeEncodedElementSize(sig->GetParam(i))); 18531cb0ef41Sopenharmony_ci encoded_size += 2; 18541cb0ef41Sopenharmony_ci break; 18551cb0ef41Sopenharmony_ci case wasm::kI64: 18561cb0ef41Sopenharmony_ci case wasm::kF64: 18571cb0ef41Sopenharmony_ci DCHECK_EQ(4, ComputeEncodedElementSize(sig->GetParam(i))); 18581cb0ef41Sopenharmony_ci encoded_size += 4; 18591cb0ef41Sopenharmony_ci break; 18601cb0ef41Sopenharmony_ci case wasm::kS128: 18611cb0ef41Sopenharmony_ci DCHECK_EQ(8, ComputeEncodedElementSize(sig->GetParam(i))); 18621cb0ef41Sopenharmony_ci encoded_size += 8; 18631cb0ef41Sopenharmony_ci break; 18641cb0ef41Sopenharmony_ci case wasm::kRef: 18651cb0ef41Sopenharmony_ci case wasm::kOptRef: 18661cb0ef41Sopenharmony_ci encoded_size += 1; 18671cb0ef41Sopenharmony_ci break; 18681cb0ef41Sopenharmony_ci case wasm::kRtt: 18691cb0ef41Sopenharmony_ci case wasm::kVoid: 18701cb0ef41Sopenharmony_ci case wasm::kBottom: 18711cb0ef41Sopenharmony_ci case wasm::kI8: 18721cb0ef41Sopenharmony_ci case wasm::kI16: 18731cb0ef41Sopenharmony_ci UNREACHABLE(); 18741cb0ef41Sopenharmony_ci } 18751cb0ef41Sopenharmony_ci } 18761cb0ef41Sopenharmony_ci return encoded_size; 18771cb0ef41Sopenharmony_ci} 18781cb0ef41Sopenharmony_ci 18791cb0ef41Sopenharmony_cibool WasmExportedFunction::IsWasmExportedFunction(Object object) { 18801cb0ef41Sopenharmony_ci if (!object.IsJSFunction()) return false; 18811cb0ef41Sopenharmony_ci JSFunction js_function = JSFunction::cast(object); 18821cb0ef41Sopenharmony_ci CodeT code = js_function.code(); 18831cb0ef41Sopenharmony_ci if (CodeKind::JS_TO_WASM_FUNCTION != code.kind() && 18841cb0ef41Sopenharmony_ci code.builtin_id() != Builtin::kGenericJSToWasmWrapper && 18851cb0ef41Sopenharmony_ci code.builtin_id() != Builtin::kWasmReturnPromiseOnSuspend) { 18861cb0ef41Sopenharmony_ci return false; 18871cb0ef41Sopenharmony_ci } 18881cb0ef41Sopenharmony_ci DCHECK(js_function.shared().HasWasmExportedFunctionData()); 18891cb0ef41Sopenharmony_ci return true; 18901cb0ef41Sopenharmony_ci} 18911cb0ef41Sopenharmony_ci 18921cb0ef41Sopenharmony_cibool WasmCapiFunction::IsWasmCapiFunction(Object object) { 18931cb0ef41Sopenharmony_ci if (!object.IsJSFunction()) return false; 18941cb0ef41Sopenharmony_ci JSFunction js_function = JSFunction::cast(object); 18951cb0ef41Sopenharmony_ci // TODO(jkummerow): Enable this when there is a JavaScript wrapper 18961cb0ef41Sopenharmony_ci // able to call this function. 18971cb0ef41Sopenharmony_ci // if (js_function->code()->kind() != CodeKind::WASM_TO_CAPI_FUNCTION) { 18981cb0ef41Sopenharmony_ci // return false; 18991cb0ef41Sopenharmony_ci // } 19001cb0ef41Sopenharmony_ci // DCHECK(js_function->shared()->HasWasmCapiFunctionData()); 19011cb0ef41Sopenharmony_ci // return true; 19021cb0ef41Sopenharmony_ci return js_function.shared().HasWasmCapiFunctionData(); 19031cb0ef41Sopenharmony_ci} 19041cb0ef41Sopenharmony_ci 19051cb0ef41Sopenharmony_ciHandle<WasmCapiFunction> WasmCapiFunction::New( 19061cb0ef41Sopenharmony_ci Isolate* isolate, Address call_target, Handle<Foreign> embedder_data, 19071cb0ef41Sopenharmony_ci Handle<PodArray<wasm::ValueType>> serialized_signature) { 19081cb0ef41Sopenharmony_ci // TODO(jkummerow): Install a JavaScript wrapper. For now, calling 19091cb0ef41Sopenharmony_ci // these functions directly is unsupported; they can only be called 19101cb0ef41Sopenharmony_ci // from Wasm code. 19111cb0ef41Sopenharmony_ci 19121cb0ef41Sopenharmony_ci // To support simulator builds, we potentially have to redirect the 19131cb0ef41Sopenharmony_ci // call target (which is an address pointing into the C++ binary). 19141cb0ef41Sopenharmony_ci call_target = ExternalReference::Create(call_target).address(); 19151cb0ef41Sopenharmony_ci 19161cb0ef41Sopenharmony_ci // TODO(7748): Support proper typing for external functions. That requires 19171cb0ef41Sopenharmony_ci // global (cross-module) canonicalization of signatures/RTTs. 19181cb0ef41Sopenharmony_ci Handle<Map> rtt = isolate->factory()->wasm_internal_function_map(); 19191cb0ef41Sopenharmony_ci Handle<WasmCapiFunctionData> fun_data = 19201cb0ef41Sopenharmony_ci isolate->factory()->NewWasmCapiFunctionData( 19211cb0ef41Sopenharmony_ci call_target, embedder_data, BUILTIN_CODE(isolate, Illegal), rtt, 19221cb0ef41Sopenharmony_ci serialized_signature); 19231cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared = 19241cb0ef41Sopenharmony_ci isolate->factory()->NewSharedFunctionInfoForWasmCapiFunction(fun_data); 19251cb0ef41Sopenharmony_ci Handle<JSFunction> result = 19261cb0ef41Sopenharmony_ci Factory::JSFunctionBuilder{isolate, shared, isolate->native_context()} 19271cb0ef41Sopenharmony_ci .Build(); 19281cb0ef41Sopenharmony_ci fun_data->internal().set_external(*result); 19291cb0ef41Sopenharmony_ci return Handle<WasmCapiFunction>::cast(result); 19301cb0ef41Sopenharmony_ci} 19311cb0ef41Sopenharmony_ci 19321cb0ef41Sopenharmony_ciWasmInstanceObject WasmExportedFunction::instance() { 19331cb0ef41Sopenharmony_ci return shared().wasm_exported_function_data().instance(); 19341cb0ef41Sopenharmony_ci} 19351cb0ef41Sopenharmony_ci 19361cb0ef41Sopenharmony_ciint WasmExportedFunction::function_index() { 19371cb0ef41Sopenharmony_ci return shared().wasm_exported_function_data().function_index(); 19381cb0ef41Sopenharmony_ci} 19391cb0ef41Sopenharmony_ci 19401cb0ef41Sopenharmony_ciHandle<WasmExportedFunction> WasmExportedFunction::New( 19411cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index, 19421cb0ef41Sopenharmony_ci int arity, Handle<CodeT> export_wrapper) { 19431cb0ef41Sopenharmony_ci DCHECK( 19441cb0ef41Sopenharmony_ci CodeKind::JS_TO_WASM_FUNCTION == export_wrapper->kind() || 19451cb0ef41Sopenharmony_ci (export_wrapper->is_builtin() && 19461cb0ef41Sopenharmony_ci (export_wrapper->builtin_id() == Builtin::kGenericJSToWasmWrapper || 19471cb0ef41Sopenharmony_ci export_wrapper->builtin_id() == Builtin::kWasmReturnPromiseOnSuspend))); 19481cb0ef41Sopenharmony_ci int num_imported_functions = instance->module()->num_imported_functions; 19491cb0ef41Sopenharmony_ci Handle<Object> ref = 19501cb0ef41Sopenharmony_ci func_index >= num_imported_functions 19511cb0ef41Sopenharmony_ci ? instance 19521cb0ef41Sopenharmony_ci : handle(instance->imported_function_refs().get(func_index), isolate); 19531cb0ef41Sopenharmony_ci 19541cb0ef41Sopenharmony_ci Factory* factory = isolate->factory(); 19551cb0ef41Sopenharmony_ci const wasm::FunctionSig* sig = instance->module()->functions[func_index].sig; 19561cb0ef41Sopenharmony_ci Address call_target = instance->GetCallTarget(func_index); 19571cb0ef41Sopenharmony_ci Handle<Map> rtt; 19581cb0ef41Sopenharmony_ci bool has_gc = 19591cb0ef41Sopenharmony_ci instance->module_object().native_module()->enabled_features().has_gc(); 19601cb0ef41Sopenharmony_ci if (has_gc) { 19611cb0ef41Sopenharmony_ci int sig_index = instance->module()->functions[func_index].sig_index; 19621cb0ef41Sopenharmony_ci // TODO(7748): Create funcref RTTs lazily? 19631cb0ef41Sopenharmony_ci rtt = handle(Map::cast(instance->managed_object_maps().get(sig_index)), 19641cb0ef41Sopenharmony_ci isolate); 19651cb0ef41Sopenharmony_ci } else { 19661cb0ef41Sopenharmony_ci rtt = factory->wasm_internal_function_map(); 19671cb0ef41Sopenharmony_ci } 19681cb0ef41Sopenharmony_ci Handle<WasmExportedFunctionData> function_data = 19691cb0ef41Sopenharmony_ci factory->NewWasmExportedFunctionData( 19701cb0ef41Sopenharmony_ci export_wrapper, instance, call_target, ref, func_index, 19711cb0ef41Sopenharmony_ci reinterpret_cast<Address>(sig), wasm::kGenericWrapperBudget, rtt); 19721cb0ef41Sopenharmony_ci 19731cb0ef41Sopenharmony_ci MaybeHandle<String> maybe_name; 19741cb0ef41Sopenharmony_ci bool is_asm_js_module = instance->module_object().is_asm_js(); 19751cb0ef41Sopenharmony_ci if (is_asm_js_module) { 19761cb0ef41Sopenharmony_ci // We can use the function name only for asm.js. For WebAssembly, the 19771cb0ef41Sopenharmony_ci // function name is specified as the function_index.toString(). 19781cb0ef41Sopenharmony_ci maybe_name = WasmModuleObject::GetFunctionNameOrNull( 19791cb0ef41Sopenharmony_ci isolate, handle(instance->module_object(), isolate), func_index); 19801cb0ef41Sopenharmony_ci } 19811cb0ef41Sopenharmony_ci Handle<String> name; 19821cb0ef41Sopenharmony_ci if (!maybe_name.ToHandle(&name)) { 19831cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 16> buffer; 19841cb0ef41Sopenharmony_ci int length = SNPrintF(buffer, "%d", func_index); 19851cb0ef41Sopenharmony_ci name = factory 19861cb0ef41Sopenharmony_ci ->NewStringFromOneByte( 19871cb0ef41Sopenharmony_ci base::Vector<uint8_t>::cast(buffer.SubVector(0, length))) 19881cb0ef41Sopenharmony_ci .ToHandleChecked(); 19891cb0ef41Sopenharmony_ci } 19901cb0ef41Sopenharmony_ci Handle<Map> function_map; 19911cb0ef41Sopenharmony_ci switch (instance->module()->origin) { 19921cb0ef41Sopenharmony_ci case wasm::kWasmOrigin: 19931cb0ef41Sopenharmony_ci function_map = isolate->wasm_exported_function_map(); 19941cb0ef41Sopenharmony_ci break; 19951cb0ef41Sopenharmony_ci case wasm::kAsmJsSloppyOrigin: 19961cb0ef41Sopenharmony_ci function_map = isolate->sloppy_function_map(); 19971cb0ef41Sopenharmony_ci break; 19981cb0ef41Sopenharmony_ci case wasm::kAsmJsStrictOrigin: 19991cb0ef41Sopenharmony_ci function_map = isolate->strict_function_map(); 20001cb0ef41Sopenharmony_ci break; 20011cb0ef41Sopenharmony_ci } 20021cb0ef41Sopenharmony_ci 20031cb0ef41Sopenharmony_ci Handle<NativeContext> context(isolate->native_context()); 20041cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared = 20051cb0ef41Sopenharmony_ci factory->NewSharedFunctionInfoForWasmExportedFunction(name, 20061cb0ef41Sopenharmony_ci function_data); 20071cb0ef41Sopenharmony_ci Handle<JSFunction> js_function = 20081cb0ef41Sopenharmony_ci Factory::JSFunctionBuilder{isolate, shared, context} 20091cb0ef41Sopenharmony_ci .set_map(function_map) 20101cb0ef41Sopenharmony_ci .Build(); 20111cb0ef41Sopenharmony_ci 20121cb0ef41Sopenharmony_ci // According to the spec, exported functions should not have a [[Construct]] 20131cb0ef41Sopenharmony_ci // method. This does not apply to functions exported from asm.js however. 20141cb0ef41Sopenharmony_ci DCHECK_EQ(is_asm_js_module, js_function->IsConstructor()); 20151cb0ef41Sopenharmony_ci shared->set_length(arity); 20161cb0ef41Sopenharmony_ci shared->set_internal_formal_parameter_count(JSParameterCount(arity)); 20171cb0ef41Sopenharmony_ci shared->set_script(instance->module_object().script()); 20181cb0ef41Sopenharmony_ci function_data->internal().set_external(*js_function); 20191cb0ef41Sopenharmony_ci return Handle<WasmExportedFunction>::cast(js_function); 20201cb0ef41Sopenharmony_ci} 20211cb0ef41Sopenharmony_ci 20221cb0ef41Sopenharmony_ciAddress WasmExportedFunction::GetWasmCallTarget() { 20231cb0ef41Sopenharmony_ci return instance().GetCallTarget(function_index()); 20241cb0ef41Sopenharmony_ci} 20251cb0ef41Sopenharmony_ci 20261cb0ef41Sopenharmony_ciconst wasm::FunctionSig* WasmExportedFunction::sig() { 20271cb0ef41Sopenharmony_ci return instance().module()->functions[function_index()].sig; 20281cb0ef41Sopenharmony_ci} 20291cb0ef41Sopenharmony_ci 20301cb0ef41Sopenharmony_cibool WasmExportedFunction::MatchesSignature( 20311cb0ef41Sopenharmony_ci const WasmModule* other_module, const wasm::FunctionSig* other_sig) { 20321cb0ef41Sopenharmony_ci const wasm::FunctionSig* sig = this->sig(); 20331cb0ef41Sopenharmony_ci if (sig->parameter_count() != other_sig->parameter_count() || 20341cb0ef41Sopenharmony_ci sig->return_count() != other_sig->return_count()) { 20351cb0ef41Sopenharmony_ci return false; 20361cb0ef41Sopenharmony_ci } 20371cb0ef41Sopenharmony_ci 20381cb0ef41Sopenharmony_ci for (int i = 0; i < sig->all().size(); i++) { 20391cb0ef41Sopenharmony_ci if (!wasm::EquivalentTypes(sig->all()[i], other_sig->all()[i], 20401cb0ef41Sopenharmony_ci this->instance().module(), other_module)) { 20411cb0ef41Sopenharmony_ci return false; 20421cb0ef41Sopenharmony_ci } 20431cb0ef41Sopenharmony_ci } 20441cb0ef41Sopenharmony_ci return true; 20451cb0ef41Sopenharmony_ci} 20461cb0ef41Sopenharmony_ci 20471cb0ef41Sopenharmony_ci// static 20481cb0ef41Sopenharmony_cistd::unique_ptr<char[]> WasmExportedFunction::GetDebugName( 20491cb0ef41Sopenharmony_ci const wasm::FunctionSig* sig) { 20501cb0ef41Sopenharmony_ci constexpr const char kPrefix[] = "js-to-wasm:"; 20511cb0ef41Sopenharmony_ci // prefix + parameters + delimiter + returns + zero byte 20521cb0ef41Sopenharmony_ci size_t len = strlen(kPrefix) + sig->all().size() + 2; 20531cb0ef41Sopenharmony_ci auto buffer = base::OwnedVector<char>::New(len); 20541cb0ef41Sopenharmony_ci memcpy(buffer.start(), kPrefix, strlen(kPrefix)); 20551cb0ef41Sopenharmony_ci PrintSignature(buffer.as_vector() + strlen(kPrefix), sig); 20561cb0ef41Sopenharmony_ci return buffer.ReleaseData(); 20571cb0ef41Sopenharmony_ci} 20581cb0ef41Sopenharmony_ci 20591cb0ef41Sopenharmony_ci// static 20601cb0ef41Sopenharmony_cibool WasmJSFunction::IsWasmJSFunction(Object object) { 20611cb0ef41Sopenharmony_ci if (!object.IsJSFunction()) return false; 20621cb0ef41Sopenharmony_ci JSFunction js_function = JSFunction::cast(object); 20631cb0ef41Sopenharmony_ci return js_function.shared().HasWasmJSFunctionData(); 20641cb0ef41Sopenharmony_ci} 20651cb0ef41Sopenharmony_ci 20661cb0ef41Sopenharmony_ciHandle<WasmJSFunction> WasmJSFunction::New(Isolate* isolate, 20671cb0ef41Sopenharmony_ci const wasm::FunctionSig* sig, 20681cb0ef41Sopenharmony_ci Handle<JSReceiver> callable, 20691cb0ef41Sopenharmony_ci Handle<HeapObject> suspender) { 20701cb0ef41Sopenharmony_ci DCHECK_LE(sig->all().size(), kMaxInt); 20711cb0ef41Sopenharmony_ci int sig_size = static_cast<int>(sig->all().size()); 20721cb0ef41Sopenharmony_ci int return_count = static_cast<int>(sig->return_count()); 20731cb0ef41Sopenharmony_ci int parameter_count = static_cast<int>(sig->parameter_count()); 20741cb0ef41Sopenharmony_ci Handle<PodArray<wasm::ValueType>> serialized_sig = 20751cb0ef41Sopenharmony_ci PodArray<wasm::ValueType>::New(isolate, sig_size, AllocationType::kOld); 20761cb0ef41Sopenharmony_ci if (sig_size > 0) { 20771cb0ef41Sopenharmony_ci serialized_sig->copy_in(0, sig->all().begin(), sig_size); 20781cb0ef41Sopenharmony_ci } 20791cb0ef41Sopenharmony_ci // TODO(wasm): Think about caching and sharing the JS-to-JS wrappers per 20801cb0ef41Sopenharmony_ci // signature instead of compiling a new one for every instantiation. 20811cb0ef41Sopenharmony_ci Handle<CodeT> wrapper_code = ToCodeT( 20821cb0ef41Sopenharmony_ci compiler::CompileJSToJSWrapper(isolate, sig, nullptr).ToHandleChecked(), 20831cb0ef41Sopenharmony_ci isolate); 20841cb0ef41Sopenharmony_ci 20851cb0ef41Sopenharmony_ci // WasmJSFunctions use on-heap Code objects as call targets, so we can't 20861cb0ef41Sopenharmony_ci // cache the target address, unless the WasmJSFunction wraps a 20871cb0ef41Sopenharmony_ci // WasmExportedFunction. 20881cb0ef41Sopenharmony_ci Address call_target = kNullAddress; 20891cb0ef41Sopenharmony_ci if (WasmExportedFunction::IsWasmExportedFunction(*callable)) { 20901cb0ef41Sopenharmony_ci call_target = WasmExportedFunction::cast(*callable).GetWasmCallTarget(); 20911cb0ef41Sopenharmony_ci } 20921cb0ef41Sopenharmony_ci 20931cb0ef41Sopenharmony_ci Factory* factory = isolate->factory(); 20941cb0ef41Sopenharmony_ci // TODO(7748): Support proper typing for external functions. That requires 20951cb0ef41Sopenharmony_ci // global (cross-module) canonicalization of signatures/RTTs. 20961cb0ef41Sopenharmony_ci Handle<Map> rtt = factory->wasm_internal_function_map(); 20971cb0ef41Sopenharmony_ci Handle<WasmJSFunctionData> function_data = factory->NewWasmJSFunctionData( 20981cb0ef41Sopenharmony_ci call_target, callable, return_count, parameter_count, serialized_sig, 20991cb0ef41Sopenharmony_ci wrapper_code, rtt, suspender); 21001cb0ef41Sopenharmony_ci 21011cb0ef41Sopenharmony_ci if (wasm::WasmFeatures::FromIsolate(isolate).has_typed_funcref()) { 21021cb0ef41Sopenharmony_ci using CK = compiler::WasmImportCallKind; 21031cb0ef41Sopenharmony_ci int expected_arity = parameter_count; 21041cb0ef41Sopenharmony_ci CK kind = compiler::kDefaultImportCallKind; 21051cb0ef41Sopenharmony_ci if (callable->IsJSFunction()) { 21061cb0ef41Sopenharmony_ci SharedFunctionInfo shared = Handle<JSFunction>::cast(callable)->shared(); 21071cb0ef41Sopenharmony_ci expected_arity = 21081cb0ef41Sopenharmony_ci shared.internal_formal_parameter_count_without_receiver(); 21091cb0ef41Sopenharmony_ci if (expected_arity != parameter_count) { 21101cb0ef41Sopenharmony_ci kind = CK::kJSFunctionArityMismatch; 21111cb0ef41Sopenharmony_ci } 21121cb0ef41Sopenharmony_ci } 21131cb0ef41Sopenharmony_ci // TODO(wasm): Think about caching and sharing the wasm-to-JS wrappers per 21141cb0ef41Sopenharmony_ci // signature instead of compiling a new one for every instantiation. 21151cb0ef41Sopenharmony_ci wasm::Suspend suspend = 21161cb0ef41Sopenharmony_ci suspender.is_null() ? wasm::kNoSuspend : wasm::kSuspend; 21171cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!suspender.is_null(), !suspender->IsUndefined()); 21181cb0ef41Sopenharmony_ci Handle<CodeT> wasm_to_js_wrapper_code = 21191cb0ef41Sopenharmony_ci ToCodeT(compiler::CompileWasmToJSWrapper(isolate, sig, kind, 21201cb0ef41Sopenharmony_ci expected_arity, suspend) 21211cb0ef41Sopenharmony_ci .ToHandleChecked(), 21221cb0ef41Sopenharmony_ci isolate); 21231cb0ef41Sopenharmony_ci function_data->internal().set_code(*wasm_to_js_wrapper_code); 21241cb0ef41Sopenharmony_ci } 21251cb0ef41Sopenharmony_ci 21261cb0ef41Sopenharmony_ci Handle<String> name = factory->Function_string(); 21271cb0ef41Sopenharmony_ci if (callable->IsJSFunction()) { 21281cb0ef41Sopenharmony_ci name = JSFunction::GetDebugName(Handle<JSFunction>::cast(callable)); 21291cb0ef41Sopenharmony_ci name = String::Flatten(isolate, name); 21301cb0ef41Sopenharmony_ci } 21311cb0ef41Sopenharmony_ci Handle<NativeContext> context(isolate->native_context()); 21321cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared = 21331cb0ef41Sopenharmony_ci factory->NewSharedFunctionInfoForWasmJSFunction(name, function_data); 21341cb0ef41Sopenharmony_ci Handle<JSFunction> js_function = 21351cb0ef41Sopenharmony_ci Factory::JSFunctionBuilder{isolate, shared, context} 21361cb0ef41Sopenharmony_ci .set_map(isolate->wasm_exported_function_map()) 21371cb0ef41Sopenharmony_ci .Build(); 21381cb0ef41Sopenharmony_ci js_function->shared().set_internal_formal_parameter_count( 21391cb0ef41Sopenharmony_ci JSParameterCount(parameter_count)); 21401cb0ef41Sopenharmony_ci function_data->internal().set_external(*js_function); 21411cb0ef41Sopenharmony_ci return Handle<WasmJSFunction>::cast(js_function); 21421cb0ef41Sopenharmony_ci} 21431cb0ef41Sopenharmony_ci 21441cb0ef41Sopenharmony_ciJSReceiver WasmJSFunction::GetCallable() const { 21451cb0ef41Sopenharmony_ci return JSReceiver::cast(WasmApiFunctionRef::cast( 21461cb0ef41Sopenharmony_ci shared().wasm_js_function_data().internal().ref()) 21471cb0ef41Sopenharmony_ci .callable()); 21481cb0ef41Sopenharmony_ci} 21491cb0ef41Sopenharmony_ci 21501cb0ef41Sopenharmony_ciHeapObject WasmJSFunction::GetSuspender() const { 21511cb0ef41Sopenharmony_ci return WasmApiFunctionRef::cast( 21521cb0ef41Sopenharmony_ci shared().wasm_js_function_data().internal().ref()) 21531cb0ef41Sopenharmony_ci .suspender(); 21541cb0ef41Sopenharmony_ci} 21551cb0ef41Sopenharmony_ci 21561cb0ef41Sopenharmony_ciconst wasm::FunctionSig* WasmJSFunction::GetSignature(Zone* zone) { 21571cb0ef41Sopenharmony_ci WasmJSFunctionData function_data = shared().wasm_js_function_data(); 21581cb0ef41Sopenharmony_ci int sig_size = function_data.serialized_signature().length(); 21591cb0ef41Sopenharmony_ci wasm::ValueType* types = zone->NewArray<wasm::ValueType>(sig_size); 21601cb0ef41Sopenharmony_ci if (sig_size > 0) { 21611cb0ef41Sopenharmony_ci function_data.serialized_signature().copy_out(0, types, sig_size); 21621cb0ef41Sopenharmony_ci } 21631cb0ef41Sopenharmony_ci int return_count = function_data.serialized_return_count(); 21641cb0ef41Sopenharmony_ci int parameter_count = function_data.serialized_parameter_count(); 21651cb0ef41Sopenharmony_ci return zone->New<wasm::FunctionSig>(return_count, parameter_count, types); 21661cb0ef41Sopenharmony_ci} 21671cb0ef41Sopenharmony_ci 21681cb0ef41Sopenharmony_cibool WasmJSFunction::MatchesSignatureForSuspend(const wasm::FunctionSig* sig) { 21691cb0ef41Sopenharmony_ci DCHECK_LE(sig->all().size(), kMaxInt); 21701cb0ef41Sopenharmony_ci int sig_size = static_cast<int>(sig->all().size()); 21711cb0ef41Sopenharmony_ci int parameter_count = static_cast<int>(sig->parameter_count()); 21721cb0ef41Sopenharmony_ci int return_count = static_cast<int>(sig->return_count()); 21731cb0ef41Sopenharmony_ci DisallowHeapAllocation no_alloc; 21741cb0ef41Sopenharmony_ci WasmJSFunctionData function_data = shared().wasm_js_function_data(); 21751cb0ef41Sopenharmony_ci if (parameter_count != function_data.serialized_parameter_count()) { 21761cb0ef41Sopenharmony_ci return false; 21771cb0ef41Sopenharmony_ci } 21781cb0ef41Sopenharmony_ci if (sig_size == 0) return true; // Prevent undefined behavior. 21791cb0ef41Sopenharmony_ci // This function is only called for functions wrapped by a 21801cb0ef41Sopenharmony_ci // WebAssembly.Suspender object, so the return type has to be externref. 21811cb0ef41Sopenharmony_ci CHECK_EQ(function_data.serialized_return_count(), 1); 21821cb0ef41Sopenharmony_ci CHECK_EQ(function_data.serialized_signature().get(0), wasm::kWasmAnyRef); 21831cb0ef41Sopenharmony_ci const wasm::ValueType* expected = sig->all().begin(); 21841cb0ef41Sopenharmony_ci return function_data.serialized_signature().matches( 21851cb0ef41Sopenharmony_ci 1, expected + return_count, parameter_count); 21861cb0ef41Sopenharmony_ci} 21871cb0ef41Sopenharmony_ci 21881cb0ef41Sopenharmony_ci// TODO(9495): Update this if function type variance is introduced. 21891cb0ef41Sopenharmony_cibool WasmJSFunction::MatchesSignature(const wasm::FunctionSig* sig) { 21901cb0ef41Sopenharmony_ci DCHECK_LE(sig->all().size(), kMaxInt); 21911cb0ef41Sopenharmony_ci int sig_size = static_cast<int>(sig->all().size()); 21921cb0ef41Sopenharmony_ci int return_count = static_cast<int>(sig->return_count()); 21931cb0ef41Sopenharmony_ci int parameter_count = static_cast<int>(sig->parameter_count()); 21941cb0ef41Sopenharmony_ci DisallowHeapAllocation no_alloc; 21951cb0ef41Sopenharmony_ci WasmJSFunctionData function_data = shared().wasm_js_function_data(); 21961cb0ef41Sopenharmony_ci if (return_count != function_data.serialized_return_count() || 21971cb0ef41Sopenharmony_ci parameter_count != function_data.serialized_parameter_count()) { 21981cb0ef41Sopenharmony_ci return false; 21991cb0ef41Sopenharmony_ci } 22001cb0ef41Sopenharmony_ci if (sig_size == 0) return true; // Prevent undefined behavior. 22011cb0ef41Sopenharmony_ci const wasm::ValueType* expected = sig->all().begin(); 22021cb0ef41Sopenharmony_ci return function_data.serialized_signature().matches(expected, sig_size); 22031cb0ef41Sopenharmony_ci} 22041cb0ef41Sopenharmony_ci 22051cb0ef41Sopenharmony_ciPodArray<wasm::ValueType> WasmCapiFunction::GetSerializedSignature() const { 22061cb0ef41Sopenharmony_ci return shared().wasm_capi_function_data().serialized_signature(); 22071cb0ef41Sopenharmony_ci} 22081cb0ef41Sopenharmony_ci 22091cb0ef41Sopenharmony_cibool WasmExternalFunction::IsWasmExternalFunction(Object object) { 22101cb0ef41Sopenharmony_ci return WasmExportedFunction::IsWasmExportedFunction(object) || 22111cb0ef41Sopenharmony_ci WasmJSFunction::IsWasmJSFunction(object); 22121cb0ef41Sopenharmony_ci} 22131cb0ef41Sopenharmony_ci 22141cb0ef41Sopenharmony_ci// static 22151cb0ef41Sopenharmony_ciMaybeHandle<WasmInternalFunction> WasmInternalFunction::FromExternal( 22161cb0ef41Sopenharmony_ci Handle<Object> external, Isolate* isolate) { 22171cb0ef41Sopenharmony_ci if (WasmExportedFunction::IsWasmExportedFunction(*external) || 22181cb0ef41Sopenharmony_ci WasmJSFunction::IsWasmJSFunction(*external) || 22191cb0ef41Sopenharmony_ci WasmCapiFunction::IsWasmCapiFunction(*external)) { 22201cb0ef41Sopenharmony_ci WasmFunctionData data = WasmFunctionData::cast( 22211cb0ef41Sopenharmony_ci Handle<JSFunction>::cast(external)->shared().function_data( 22221cb0ef41Sopenharmony_ci kAcquireLoad)); 22231cb0ef41Sopenharmony_ci return handle(data.internal(), isolate); 22241cb0ef41Sopenharmony_ci } 22251cb0ef41Sopenharmony_ci return MaybeHandle<WasmInternalFunction>(); 22261cb0ef41Sopenharmony_ci} 22271cb0ef41Sopenharmony_ci 22281cb0ef41Sopenharmony_ciHandle<WasmExceptionTag> WasmExceptionTag::New(Isolate* isolate, int index) { 22291cb0ef41Sopenharmony_ci Handle<WasmExceptionTag> result = 22301cb0ef41Sopenharmony_ci Handle<WasmExceptionTag>::cast(isolate->factory()->NewStruct( 22311cb0ef41Sopenharmony_ci WASM_EXCEPTION_TAG_TYPE, AllocationType::kOld)); 22321cb0ef41Sopenharmony_ci result->set_index(index); 22331cb0ef41Sopenharmony_ci return result; 22341cb0ef41Sopenharmony_ci} 22351cb0ef41Sopenharmony_ci 22361cb0ef41Sopenharmony_ciHandle<AsmWasmData> AsmWasmData::New( 22371cb0ef41Sopenharmony_ci Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module, 22381cb0ef41Sopenharmony_ci Handle<FixedArray> export_wrappers, Handle<HeapNumber> uses_bitset) { 22391cb0ef41Sopenharmony_ci const WasmModule* module = native_module->module(); 22401cb0ef41Sopenharmony_ci const bool kUsesLiftoff = false; 22411cb0ef41Sopenharmony_ci size_t memory_estimate = 22421cb0ef41Sopenharmony_ci wasm::WasmCodeManager::EstimateNativeModuleCodeSize( 22431cb0ef41Sopenharmony_ci module, kUsesLiftoff, wasm::DynamicTiering::kDisabled) + 22441cb0ef41Sopenharmony_ci wasm::WasmCodeManager::EstimateNativeModuleMetaDataSize(module); 22451cb0ef41Sopenharmony_ci Handle<Managed<wasm::NativeModule>> managed_native_module = 22461cb0ef41Sopenharmony_ci Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate, 22471cb0ef41Sopenharmony_ci std::move(native_module)); 22481cb0ef41Sopenharmony_ci Handle<AsmWasmData> result = Handle<AsmWasmData>::cast( 22491cb0ef41Sopenharmony_ci isolate->factory()->NewStruct(ASM_WASM_DATA_TYPE, AllocationType::kOld)); 22501cb0ef41Sopenharmony_ci result->set_managed_native_module(*managed_native_module); 22511cb0ef41Sopenharmony_ci result->set_export_wrappers(*export_wrappers); 22521cb0ef41Sopenharmony_ci result->set_uses_bitset(*uses_bitset); 22531cb0ef41Sopenharmony_ci return result; 22541cb0ef41Sopenharmony_ci} 22551cb0ef41Sopenharmony_ci 22561cb0ef41Sopenharmony_cinamespace wasm { 22571cb0ef41Sopenharmony_ci 22581cb0ef41Sopenharmony_cibool TypecheckJSObject(Isolate* isolate, const WasmModule* module, 22591cb0ef41Sopenharmony_ci Handle<Object> value, ValueType expected, 22601cb0ef41Sopenharmony_ci const char** error_message) { 22611cb0ef41Sopenharmony_ci DCHECK(expected.is_reference()); 22621cb0ef41Sopenharmony_ci switch (expected.kind()) { 22631cb0ef41Sopenharmony_ci case kOptRef: 22641cb0ef41Sopenharmony_ci if (value->IsNull(isolate)) return true; 22651cb0ef41Sopenharmony_ci V8_FALLTHROUGH; 22661cb0ef41Sopenharmony_ci case kRef: { 22671cb0ef41Sopenharmony_ci HeapType::Representation repr = expected.heap_representation(); 22681cb0ef41Sopenharmony_ci switch (repr) { 22691cb0ef41Sopenharmony_ci case HeapType::kFunc: { 22701cb0ef41Sopenharmony_ci if (!(WasmExternalFunction::IsWasmExternalFunction(*value) || 22711cb0ef41Sopenharmony_ci WasmCapiFunction::IsWasmCapiFunction(*value))) { 22721cb0ef41Sopenharmony_ci *error_message = 22731cb0ef41Sopenharmony_ci "function-typed object must be null (if nullable) or a Wasm " 22741cb0ef41Sopenharmony_ci "function object"; 22751cb0ef41Sopenharmony_ci return false; 22761cb0ef41Sopenharmony_ci } 22771cb0ef41Sopenharmony_ci return true; 22781cb0ef41Sopenharmony_ci } 22791cb0ef41Sopenharmony_ci case HeapType::kAny: 22801cb0ef41Sopenharmony_ci return true; 22811cb0ef41Sopenharmony_ci case HeapType::kData: 22821cb0ef41Sopenharmony_ci case HeapType::kArray: 22831cb0ef41Sopenharmony_ci case HeapType::kEq: 22841cb0ef41Sopenharmony_ci case HeapType::kI31: { 22851cb0ef41Sopenharmony_ci // TODO(7748): Change this when we have a decision on the JS API for 22861cb0ef41Sopenharmony_ci // structs/arrays. 22871cb0ef41Sopenharmony_ci if (!FLAG_wasm_gc_js_interop) { 22881cb0ef41Sopenharmony_ci Handle<Name> key = isolate->factory()->wasm_wrapped_object_symbol(); 22891cb0ef41Sopenharmony_ci LookupIterator it(isolate, value, key, 22901cb0ef41Sopenharmony_ci LookupIterator::OWN_SKIP_INTERCEPTOR); 22911cb0ef41Sopenharmony_ci if (it.state() != LookupIterator::DATA) { 22921cb0ef41Sopenharmony_ci *error_message = 22931cb0ef41Sopenharmony_ci "eqref/dataref/i31ref object must be null (if nullable) or " 22941cb0ef41Sopenharmony_ci "wrapped with the wasm object wrapper"; 22951cb0ef41Sopenharmony_ci return false; 22961cb0ef41Sopenharmony_ci } 22971cb0ef41Sopenharmony_ci value = it.GetDataValue(); 22981cb0ef41Sopenharmony_ci } 22991cb0ef41Sopenharmony_ci 23001cb0ef41Sopenharmony_ci if (repr == HeapType::kI31) { 23011cb0ef41Sopenharmony_ci if (!value->IsSmi()) { 23021cb0ef41Sopenharmony_ci *error_message = "i31ref-typed object cannot be a heap object"; 23031cb0ef41Sopenharmony_ci return false; 23041cb0ef41Sopenharmony_ci } 23051cb0ef41Sopenharmony_ci return true; 23061cb0ef41Sopenharmony_ci } 23071cb0ef41Sopenharmony_ci 23081cb0ef41Sopenharmony_ci if (!((repr == HeapType::kEq && value->IsSmi()) || 23091cb0ef41Sopenharmony_ci (repr != HeapType::kArray && value->IsWasmStruct()) || 23101cb0ef41Sopenharmony_ci value->IsWasmArray())) { 23111cb0ef41Sopenharmony_ci *error_message = "object incompatible with wasm type"; 23121cb0ef41Sopenharmony_ci return false; 23131cb0ef41Sopenharmony_ci } 23141cb0ef41Sopenharmony_ci return true; 23151cb0ef41Sopenharmony_ci } 23161cb0ef41Sopenharmony_ci default: 23171cb0ef41Sopenharmony_ci if (module == nullptr) { 23181cb0ef41Sopenharmony_ci *error_message = 23191cb0ef41Sopenharmony_ci "an object defined in JavaScript cannot be compatible with a " 23201cb0ef41Sopenharmony_ci "type defined in a Webassembly module"; 23211cb0ef41Sopenharmony_ci return false; 23221cb0ef41Sopenharmony_ci } 23231cb0ef41Sopenharmony_ci DCHECK(module->has_type(expected.ref_index())); 23241cb0ef41Sopenharmony_ci if (module->has_signature(expected.ref_index())) { 23251cb0ef41Sopenharmony_ci if (WasmExportedFunction::IsWasmExportedFunction(*value)) { 23261cb0ef41Sopenharmony_ci WasmExportedFunction function = 23271cb0ef41Sopenharmony_ci WasmExportedFunction::cast(*value); 23281cb0ef41Sopenharmony_ci const WasmModule* exporting_module = function.instance().module(); 23291cb0ef41Sopenharmony_ci ValueType real_type = ValueType::Ref( 23301cb0ef41Sopenharmony_ci exporting_module->functions[function.function_index()] 23311cb0ef41Sopenharmony_ci .sig_index, 23321cb0ef41Sopenharmony_ci kNonNullable); 23331cb0ef41Sopenharmony_ci if (!IsSubtypeOf(real_type, expected, exporting_module, module)) { 23341cb0ef41Sopenharmony_ci *error_message = 23351cb0ef41Sopenharmony_ci "assigned exported function has to be a subtype of the " 23361cb0ef41Sopenharmony_ci "expected type"; 23371cb0ef41Sopenharmony_ci return false; 23381cb0ef41Sopenharmony_ci } 23391cb0ef41Sopenharmony_ci return true; 23401cb0ef41Sopenharmony_ci } 23411cb0ef41Sopenharmony_ci 23421cb0ef41Sopenharmony_ci if (WasmJSFunction::IsWasmJSFunction(*value)) { 23431cb0ef41Sopenharmony_ci // Since a WasmJSFunction cannot refer to indexed types (definable 23441cb0ef41Sopenharmony_ci // only in a module), we do not need full function subtyping. 23451cb0ef41Sopenharmony_ci // TODO(manoskouk): Change this if wasm types can be exported. 23461cb0ef41Sopenharmony_ci if (!WasmJSFunction::cast(*value).MatchesSignature( 23471cb0ef41Sopenharmony_ci module->signature(expected.ref_index()))) { 23481cb0ef41Sopenharmony_ci *error_message = 23491cb0ef41Sopenharmony_ci "assigned WasmJSFunction has to be a subtype of the " 23501cb0ef41Sopenharmony_ci "expected type"; 23511cb0ef41Sopenharmony_ci return false; 23521cb0ef41Sopenharmony_ci } 23531cb0ef41Sopenharmony_ci return true; 23541cb0ef41Sopenharmony_ci } 23551cb0ef41Sopenharmony_ci 23561cb0ef41Sopenharmony_ci if (WasmCapiFunction::IsWasmCapiFunction(*value)) { 23571cb0ef41Sopenharmony_ci // Since a WasmCapiFunction cannot refer to indexed types 23581cb0ef41Sopenharmony_ci // (definable only in a module), we do not need full function 23591cb0ef41Sopenharmony_ci // subtyping. 23601cb0ef41Sopenharmony_ci // TODO(manoskouk): Change this if wasm types can be exported. 23611cb0ef41Sopenharmony_ci if (!WasmCapiFunction::cast(*value).MatchesSignature( 23621cb0ef41Sopenharmony_ci module->signature(expected.ref_index()))) { 23631cb0ef41Sopenharmony_ci *error_message = 23641cb0ef41Sopenharmony_ci "assigned WasmCapiFunction has to be a subtype of the " 23651cb0ef41Sopenharmony_ci "expected type"; 23661cb0ef41Sopenharmony_ci return false; 23671cb0ef41Sopenharmony_ci } 23681cb0ef41Sopenharmony_ci return true; 23691cb0ef41Sopenharmony_ci } 23701cb0ef41Sopenharmony_ci 23711cb0ef41Sopenharmony_ci *error_message = 23721cb0ef41Sopenharmony_ci "function-typed object must be null (if nullable) or a Wasm " 23731cb0ef41Sopenharmony_ci "function object"; 23741cb0ef41Sopenharmony_ci 23751cb0ef41Sopenharmony_ci return false; 23761cb0ef41Sopenharmony_ci } 23771cb0ef41Sopenharmony_ci // TODO(7748): Implement when the JS API for structs/arrays is decided 23781cb0ef41Sopenharmony_ci // on. 23791cb0ef41Sopenharmony_ci *error_message = 23801cb0ef41Sopenharmony_ci "passing struct/array-typed objects between Webassembly and " 23811cb0ef41Sopenharmony_ci "Javascript is not supported yet."; 23821cb0ef41Sopenharmony_ci return false; 23831cb0ef41Sopenharmony_ci } 23841cb0ef41Sopenharmony_ci } 23851cb0ef41Sopenharmony_ci case kRtt: 23861cb0ef41Sopenharmony_ci // TODO(7748): Implement when the JS API for rtts is decided on. 23871cb0ef41Sopenharmony_ci *error_message = 23881cb0ef41Sopenharmony_ci "passing rtts between Webassembly and Javascript is not supported " 23891cb0ef41Sopenharmony_ci "yet."; 23901cb0ef41Sopenharmony_ci return false; 23911cb0ef41Sopenharmony_ci case kI8: 23921cb0ef41Sopenharmony_ci case kI16: 23931cb0ef41Sopenharmony_ci case kI32: 23941cb0ef41Sopenharmony_ci case kI64: 23951cb0ef41Sopenharmony_ci case kF32: 23961cb0ef41Sopenharmony_ci case kF64: 23971cb0ef41Sopenharmony_ci case kS128: 23981cb0ef41Sopenharmony_ci case kVoid: 23991cb0ef41Sopenharmony_ci case kBottom: 24001cb0ef41Sopenharmony_ci UNREACHABLE(); 24011cb0ef41Sopenharmony_ci } 24021cb0ef41Sopenharmony_ci} 24031cb0ef41Sopenharmony_ci 24041cb0ef41Sopenharmony_ci} // namespace wasm 24051cb0ef41Sopenharmony_ci 24061cb0ef41Sopenharmony_ci} // namespace internal 24071cb0ef41Sopenharmony_ci} // namespace v8 24081cb0ef41Sopenharmony_ci 24091cb0ef41Sopenharmony_ci#undef TRACE_IFT 2410