11cb0ef41Sopenharmony_ci// Copyright 2019 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/module-instantiate.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/api/api-inl.h" 81cb0ef41Sopenharmony_ci#include "src/asmjs/asm-js.h" 91cb0ef41Sopenharmony_ci#include "src/base/atomicops.h" 101cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 111cb0ef41Sopenharmony_ci#include "src/logging/counters-scopes.h" 121cb0ef41Sopenharmony_ci#include "src/logging/metrics.h" 131cb0ef41Sopenharmony_ci#include "src/numbers/conversions-inl.h" 141cb0ef41Sopenharmony_ci#include "src/objects/descriptor-array-inl.h" 151cb0ef41Sopenharmony_ci#include "src/objects/property-descriptor.h" 161cb0ef41Sopenharmony_ci#include "src/tracing/trace-event.h" 171cb0ef41Sopenharmony_ci#include "src/utils/utils.h" 181cb0ef41Sopenharmony_ci#include "src/wasm/code-space-access.h" 191cb0ef41Sopenharmony_ci#include "src/wasm/init-expr-interface.h" 201cb0ef41Sopenharmony_ci#include "src/wasm/module-compiler.h" 211cb0ef41Sopenharmony_ci#include "src/wasm/wasm-constants.h" 221cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h" 231cb0ef41Sopenharmony_ci#include "src/wasm/wasm-external-refs.h" 241cb0ef41Sopenharmony_ci#include "src/wasm/wasm-import-wrapper-cache.h" 251cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h" 261cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h" 271cb0ef41Sopenharmony_ci#include "src/wasm/wasm-opcodes-inl.h" 281cb0ef41Sopenharmony_ci#include "src/wasm/wasm-subtyping.h" 291cb0ef41Sopenharmony_ci#include "src/wasm/wasm-value.h" 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#define TRACE(...) \ 321cb0ef41Sopenharmony_ci do { \ 331cb0ef41Sopenharmony_ci if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ 341cb0ef41Sopenharmony_ci } while (false) 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_cinamespace v8 { 371cb0ef41Sopenharmony_cinamespace internal { 381cb0ef41Sopenharmony_cinamespace wasm { 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cinamespace { 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_cibyte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { 431cb0ef41Sopenharmony_ci return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; 441cb0ef41Sopenharmony_ci} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ciusing ImportWrapperQueue = WrapperQueue<WasmImportWrapperCache::CacheKey, 471cb0ef41Sopenharmony_ci WasmImportWrapperCache::CacheKeyHash>; 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciclass CompileImportWrapperJob final : public JobTask { 501cb0ef41Sopenharmony_ci public: 511cb0ef41Sopenharmony_ci CompileImportWrapperJob( 521cb0ef41Sopenharmony_ci Counters* counters, NativeModule* native_module, 531cb0ef41Sopenharmony_ci ImportWrapperQueue* queue, 541cb0ef41Sopenharmony_ci WasmImportWrapperCache::ModificationScope* cache_scope) 551cb0ef41Sopenharmony_ci : counters_(counters), 561cb0ef41Sopenharmony_ci native_module_(native_module), 571cb0ef41Sopenharmony_ci queue_(queue), 581cb0ef41Sopenharmony_ci cache_scope_(cache_scope) {} 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci size_t GetMaxConcurrency(size_t worker_count) const override { 611cb0ef41Sopenharmony_ci size_t flag_limit = 621cb0ef41Sopenharmony_ci static_cast<size_t>(std::max(1, FLAG_wasm_num_compilation_tasks)); 631cb0ef41Sopenharmony_ci // Add {worker_count} to the queue size because workers might still be 641cb0ef41Sopenharmony_ci // processing units that have already been popped from the queue. 651cb0ef41Sopenharmony_ci return std::min(flag_limit, worker_count + queue_->size()); 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci void Run(JobDelegate* delegate) override { 691cb0ef41Sopenharmony_ci TRACE_EVENT0("v8.wasm", "wasm.CompileImportWrapperJob.Run"); 701cb0ef41Sopenharmony_ci while (base::Optional<WasmImportWrapperCache::CacheKey> key = 711cb0ef41Sopenharmony_ci queue_->pop()) { 721cb0ef41Sopenharmony_ci // TODO(wasm): Batch code publishing, to avoid repeated locking and 731cb0ef41Sopenharmony_ci // permission switching. 741cb0ef41Sopenharmony_ci CompileImportWrapper(native_module_, counters_, key->kind, key->signature, 751cb0ef41Sopenharmony_ci key->expected_arity, key->suspend, cache_scope_); 761cb0ef41Sopenharmony_ci if (delegate->ShouldYield()) return; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci private: 811cb0ef41Sopenharmony_ci Counters* const counters_; 821cb0ef41Sopenharmony_ci NativeModule* const native_module_; 831cb0ef41Sopenharmony_ci ImportWrapperQueue* const queue_; 841cb0ef41Sopenharmony_ci WasmImportWrapperCache::ModificationScope* const cache_scope_; 851cb0ef41Sopenharmony_ci}; 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ciHandle<DescriptorArray> CreateStructDescriptorArray( 881cb0ef41Sopenharmony_ci Isolate* isolate, const wasm::StructType* type) { 891cb0ef41Sopenharmony_ci if (type->field_count() == 0) { 901cb0ef41Sopenharmony_ci return isolate->factory()->empty_descriptor_array(); 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci uint32_t field_count = type->field_count(); 931cb0ef41Sopenharmony_ci static_assert(kV8MaxWasmStructFields <= kMaxNumberOfDescriptors, 941cb0ef41Sopenharmony_ci "Bigger numbers of struct fields require different approach"); 951cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors = 961cb0ef41Sopenharmony_ci isolate->factory()->NewDescriptorArray(field_count); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci // TODO(ishell): cache Wasm field type in FieldType value. 991cb0ef41Sopenharmony_ci MaybeObject any_type = MaybeObject::FromObject(FieldType::Any()); 1001cb0ef41Sopenharmony_ci DCHECK(any_type->IsSmi()); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 128> name_buffer; 1031cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < field_count; i++) { 1041cb0ef41Sopenharmony_ci // TODO(ishell): consider introducing a cache of first N internalized field 1051cb0ef41Sopenharmony_ci // names similar to LookupSingleCharacterStringFromCode(). 1061cb0ef41Sopenharmony_ci SNPrintF(name_buffer, "$field%d", i); 1071cb0ef41Sopenharmony_ci Handle<String> name = 1081cb0ef41Sopenharmony_ci isolate->factory()->InternalizeUtf8String(name_buffer.begin()); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci PropertyAttributes attributes = type->mutability(i) ? SEALED : FROZEN; 1111cb0ef41Sopenharmony_ci PropertyDetails details( 1121cb0ef41Sopenharmony_ci PropertyKind::kData, attributes, PropertyLocation::kField, 1131cb0ef41Sopenharmony_ci PropertyConstness::kMutable, // Don't track constness 1141cb0ef41Sopenharmony_ci Representation::WasmValue(), static_cast<int>(i)); 1151cb0ef41Sopenharmony_ci descriptors->Set(InternalIndex(i), *name, any_type, details); 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci descriptors->Sort(); 1181cb0ef41Sopenharmony_ci return descriptors; 1191cb0ef41Sopenharmony_ci} 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ciHandle<DescriptorArray> CreateArrayDescriptorArray( 1221cb0ef41Sopenharmony_ci Isolate* isolate, const wasm::ArrayType* type) { 1231cb0ef41Sopenharmony_ci uint32_t kDescriptorsCount = 1; 1241cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors = 1251cb0ef41Sopenharmony_ci isolate->factory()->NewDescriptorArray(kDescriptorsCount); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci // TODO(ishell): cache Wasm field type in FieldType value. 1281cb0ef41Sopenharmony_ci MaybeObject any_type = MaybeObject::FromObject(FieldType::Any()); 1291cb0ef41Sopenharmony_ci DCHECK(any_type->IsSmi()); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci // Add descriptor for length property. 1321cb0ef41Sopenharmony_ci PropertyDetails details(PropertyKind::kData, FROZEN, PropertyLocation::kField, 1331cb0ef41Sopenharmony_ci PropertyConstness::kConst, 1341cb0ef41Sopenharmony_ci Representation::WasmValue(), static_cast<int>(0)); 1351cb0ef41Sopenharmony_ci descriptors->Set(InternalIndex(0), *isolate->factory()->length_string(), 1361cb0ef41Sopenharmony_ci any_type, details); 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci descriptors->Sort(); 1391cb0ef41Sopenharmony_ci return descriptors; 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ciHandle<Map> CreateStructMap(Isolate* isolate, const WasmModule* module, 1431cb0ef41Sopenharmony_ci int struct_index, Handle<Map> opt_rtt_parent, 1441cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance) { 1451cb0ef41Sopenharmony_ci const wasm::StructType* type = module->struct_type(struct_index); 1461cb0ef41Sopenharmony_ci const int inobject_properties = 0; 1471cb0ef41Sopenharmony_ci // We have to use the variable size sentinel because the instance size 1481cb0ef41Sopenharmony_ci // stored directly in a Map is capped at 255 pointer sizes. 1491cb0ef41Sopenharmony_ci const int map_instance_size = kVariableSizeSentinel; 1501cb0ef41Sopenharmony_ci const int real_instance_size = WasmStruct::Size(type); 1511cb0ef41Sopenharmony_ci const InstanceType instance_type = WASM_STRUCT_TYPE; 1521cb0ef41Sopenharmony_ci // TODO(jkummerow): If NO_ELEMENTS were supported, we could use that here. 1531cb0ef41Sopenharmony_ci const ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND; 1541cb0ef41Sopenharmony_ci Handle<WasmTypeInfo> type_info = isolate->factory()->NewWasmTypeInfo( 1551cb0ef41Sopenharmony_ci reinterpret_cast<Address>(type), opt_rtt_parent, real_instance_size, 1561cb0ef41Sopenharmony_ci instance); 1571cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors = 1581cb0ef41Sopenharmony_ci CreateStructDescriptorArray(isolate, type); 1591cb0ef41Sopenharmony_ci Handle<Map> map = isolate->factory()->NewMap( 1601cb0ef41Sopenharmony_ci instance_type, map_instance_size, elements_kind, inobject_properties); 1611cb0ef41Sopenharmony_ci map->set_wasm_type_info(*type_info); 1621cb0ef41Sopenharmony_ci map->SetInstanceDescriptors(isolate, *descriptors, 1631cb0ef41Sopenharmony_ci descriptors->number_of_descriptors()); 1641cb0ef41Sopenharmony_ci map->set_is_extensible(false); 1651cb0ef41Sopenharmony_ci WasmStruct::EncodeInstanceSizeInMap(real_instance_size, *map); 1661cb0ef41Sopenharmony_ci return map; 1671cb0ef41Sopenharmony_ci} 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ciHandle<Map> CreateArrayMap(Isolate* isolate, const WasmModule* module, 1701cb0ef41Sopenharmony_ci int array_index, Handle<Map> opt_rtt_parent, 1711cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance) { 1721cb0ef41Sopenharmony_ci const wasm::ArrayType* type = module->array_type(array_index); 1731cb0ef41Sopenharmony_ci const int inobject_properties = 0; 1741cb0ef41Sopenharmony_ci const int instance_size = kVariableSizeSentinel; 1751cb0ef41Sopenharmony_ci // Wasm Arrays don't have a static instance size. 1761cb0ef41Sopenharmony_ci const int cached_instance_size = 0; 1771cb0ef41Sopenharmony_ci const InstanceType instance_type = WASM_ARRAY_TYPE; 1781cb0ef41Sopenharmony_ci const ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND; 1791cb0ef41Sopenharmony_ci Handle<WasmTypeInfo> type_info = isolate->factory()->NewWasmTypeInfo( 1801cb0ef41Sopenharmony_ci reinterpret_cast<Address>(type), opt_rtt_parent, cached_instance_size, 1811cb0ef41Sopenharmony_ci instance); 1821cb0ef41Sopenharmony_ci // TODO(ishell): get canonical descriptor array for WasmArrays from roots. 1831cb0ef41Sopenharmony_ci Handle<DescriptorArray> descriptors = 1841cb0ef41Sopenharmony_ci CreateArrayDescriptorArray(isolate, type); 1851cb0ef41Sopenharmony_ci Handle<Map> map = isolate->factory()->NewMap( 1861cb0ef41Sopenharmony_ci instance_type, instance_size, elements_kind, inobject_properties); 1871cb0ef41Sopenharmony_ci map->set_wasm_type_info(*type_info); 1881cb0ef41Sopenharmony_ci map->SetInstanceDescriptors(isolate, *descriptors, 1891cb0ef41Sopenharmony_ci descriptors->number_of_descriptors()); 1901cb0ef41Sopenharmony_ci map->set_is_extensible(false); 1911cb0ef41Sopenharmony_ci WasmArray::EncodeElementSizeInMap(type->element_type().value_kind_size(), 1921cb0ef41Sopenharmony_ci *map); 1931cb0ef41Sopenharmony_ci return map; 1941cb0ef41Sopenharmony_ci} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ciHandle<Map> CreateFuncRefMap(Isolate* isolate, const WasmModule* module, 1971cb0ef41Sopenharmony_ci Handle<Map> opt_rtt_parent, 1981cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance) { 1991cb0ef41Sopenharmony_ci const int inobject_properties = 0; 2001cb0ef41Sopenharmony_ci const int instance_size = 2011cb0ef41Sopenharmony_ci Map::cast(isolate->root(RootIndex::kWasmInternalFunctionMap)) 2021cb0ef41Sopenharmony_ci .instance_size(); 2031cb0ef41Sopenharmony_ci const InstanceType instance_type = WASM_INTERNAL_FUNCTION_TYPE; 2041cb0ef41Sopenharmony_ci const ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND; 2051cb0ef41Sopenharmony_ci Handle<WasmTypeInfo> type_info = isolate->factory()->NewWasmTypeInfo( 2061cb0ef41Sopenharmony_ci kNullAddress, opt_rtt_parent, instance_size, instance); 2071cb0ef41Sopenharmony_ci Handle<Map> map = isolate->factory()->NewMap( 2081cb0ef41Sopenharmony_ci instance_type, instance_size, elements_kind, inobject_properties); 2091cb0ef41Sopenharmony_ci map->set_wasm_type_info(*type_info); 2101cb0ef41Sopenharmony_ci return map; 2111cb0ef41Sopenharmony_ci} 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_civoid CreateMapForType(Isolate* isolate, const WasmModule* module, 2141cb0ef41Sopenharmony_ci int type_index, Handle<WasmInstanceObject> instance, 2151cb0ef41Sopenharmony_ci Handle<FixedArray> maps) { 2161cb0ef41Sopenharmony_ci // Recursive calls for supertypes may already have created this map. 2171cb0ef41Sopenharmony_ci if (maps->get(type_index).IsMap()) return; 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci Handle<WeakArrayList> canonical_rtts; 2201cb0ef41Sopenharmony_ci uint32_t canonical_type_index = 2211cb0ef41Sopenharmony_ci module->isorecursive_canonical_type_ids[type_index]; 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci if (FLAG_wasm_type_canonicalization) { 2241cb0ef41Sopenharmony_ci // Try to find the canonical map for this type in the isolate store. 2251cb0ef41Sopenharmony_ci canonical_rtts = handle(isolate->heap()->wasm_canonical_rtts(), isolate); 2261cb0ef41Sopenharmony_ci DCHECK_GT(static_cast<uint32_t>(canonical_rtts->length()), 2271cb0ef41Sopenharmony_ci canonical_type_index); 2281cb0ef41Sopenharmony_ci MaybeObject maybe_canonical_map = canonical_rtts->Get(canonical_type_index); 2291cb0ef41Sopenharmony_ci if (maybe_canonical_map.IsStrongOrWeak() && 2301cb0ef41Sopenharmony_ci maybe_canonical_map.GetHeapObject().IsMap()) { 2311cb0ef41Sopenharmony_ci maps->set(type_index, maybe_canonical_map.GetHeapObject()); 2321cb0ef41Sopenharmony_ci return; 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci Handle<Map> rtt_parent; 2371cb0ef41Sopenharmony_ci // If the type with {type_index} has an explicit supertype, make sure the 2381cb0ef41Sopenharmony_ci // map for that supertype is created first, so that the supertypes list 2391cb0ef41Sopenharmony_ci // that's cached on every RTT can be set up correctly. 2401cb0ef41Sopenharmony_ci uint32_t supertype = module->supertype(type_index); 2411cb0ef41Sopenharmony_ci if (supertype != kNoSuperType) { 2421cb0ef41Sopenharmony_ci // This recursion is safe, because kV8MaxRttSubtypingDepth limits the 2431cb0ef41Sopenharmony_ci // number of recursive steps, so we won't overflow the stack. 2441cb0ef41Sopenharmony_ci CreateMapForType(isolate, module, supertype, instance, maps); 2451cb0ef41Sopenharmony_ci rtt_parent = handle(Map::cast(maps->get(supertype)), isolate); 2461cb0ef41Sopenharmony_ci } 2471cb0ef41Sopenharmony_ci Handle<Map> map; 2481cb0ef41Sopenharmony_ci switch (module->types[type_index].kind) { 2491cb0ef41Sopenharmony_ci case TypeDefinition::kStruct: 2501cb0ef41Sopenharmony_ci map = CreateStructMap(isolate, module, type_index, rtt_parent, instance); 2511cb0ef41Sopenharmony_ci break; 2521cb0ef41Sopenharmony_ci case TypeDefinition::kArray: 2531cb0ef41Sopenharmony_ci map = CreateArrayMap(isolate, module, type_index, rtt_parent, instance); 2541cb0ef41Sopenharmony_ci break; 2551cb0ef41Sopenharmony_ci case TypeDefinition::kFunction: 2561cb0ef41Sopenharmony_ci map = CreateFuncRefMap(isolate, module, rtt_parent, instance); 2571cb0ef41Sopenharmony_ci break; 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci if (FLAG_wasm_type_canonicalization) { 2601cb0ef41Sopenharmony_ci canonical_rtts->Set(canonical_type_index, HeapObjectReference::Weak(*map)); 2611cb0ef41Sopenharmony_ci } 2621cb0ef41Sopenharmony_ci maps->set(type_index, *map); 2631cb0ef41Sopenharmony_ci} 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci} // namespace 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci// A helper class to simplify instantiating a module from a module object. 2681cb0ef41Sopenharmony_ci// It closes over the {Isolate}, the {ErrorThrower}, etc. 2691cb0ef41Sopenharmony_ciclass InstanceBuilder { 2701cb0ef41Sopenharmony_ci public: 2711cb0ef41Sopenharmony_ci InstanceBuilder(Isolate* isolate, v8::metrics::Recorder::ContextId context_id, 2721cb0ef41Sopenharmony_ci ErrorThrower* thrower, Handle<WasmModuleObject> module_object, 2731cb0ef41Sopenharmony_ci MaybeHandle<JSReceiver> ffi, 2741cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> memory_buffer); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci // Build an instance, in all of its glory. 2771cb0ef41Sopenharmony_ci MaybeHandle<WasmInstanceObject> Build(); 2781cb0ef41Sopenharmony_ci // Run the start function, if any. 2791cb0ef41Sopenharmony_ci bool ExecuteStartFunction(); 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci private: 2821cb0ef41Sopenharmony_ci // A pre-evaluated value to use in import binding. 2831cb0ef41Sopenharmony_ci struct SanitizedImport { 2841cb0ef41Sopenharmony_ci Handle<String> module_name; 2851cb0ef41Sopenharmony_ci Handle<String> import_name; 2861cb0ef41Sopenharmony_ci Handle<Object> value; 2871cb0ef41Sopenharmony_ci }; 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci Isolate* isolate_; 2901cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId context_id_; 2911cb0ef41Sopenharmony_ci const WasmFeatures enabled_; 2921cb0ef41Sopenharmony_ci const WasmModule* const module_; 2931cb0ef41Sopenharmony_ci ErrorThrower* thrower_; 2941cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object_; 2951cb0ef41Sopenharmony_ci MaybeHandle<JSReceiver> ffi_; 2961cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> memory_buffer_; 2971cb0ef41Sopenharmony_ci Handle<WasmMemoryObject> memory_object_; 2981cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> untagged_globals_; 2991cb0ef41Sopenharmony_ci Handle<FixedArray> tagged_globals_; 3001cb0ef41Sopenharmony_ci std::vector<Handle<WasmTagObject>> tags_wrappers_; 3011cb0ef41Sopenharmony_ci Handle<WasmExportedFunction> start_function_; 3021cb0ef41Sopenharmony_ci std::vector<SanitizedImport> sanitized_imports_; 3031cb0ef41Sopenharmony_ci // We pass this {Zone} to the temporary {WasmFullDecoder} we allocate during 3041cb0ef41Sopenharmony_ci // each call to {EvaluateInitExpression}. This has been found to improve 3051cb0ef41Sopenharmony_ci // performance a bit over allocating a new {Zone} each time. 3061cb0ef41Sopenharmony_ci Zone init_expr_zone_; 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci// Helper routines to print out errors with imports. 3091cb0ef41Sopenharmony_ci#define ERROR_THROWER_WITH_MESSAGE(TYPE) \ 3101cb0ef41Sopenharmony_ci void Report##TYPE(const char* error, uint32_t index, \ 3111cb0ef41Sopenharmony_ci Handle<String> module_name, Handle<String> import_name) { \ 3121cb0ef41Sopenharmony_ci thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s", \ 3131cb0ef41Sopenharmony_ci index, module_name->ToCString().get(), \ 3141cb0ef41Sopenharmony_ci import_name->ToCString().get(), error); \ 3151cb0ef41Sopenharmony_ci } \ 3161cb0ef41Sopenharmony_ci \ 3171cb0ef41Sopenharmony_ci MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index, \ 3181cb0ef41Sopenharmony_ci Handle<String> module_name) { \ 3191cb0ef41Sopenharmony_ci thrower_->TYPE("Import #%d module=\"%s\" error: %s", index, \ 3201cb0ef41Sopenharmony_ci module_name->ToCString().get(), error); \ 3211cb0ef41Sopenharmony_ci return MaybeHandle<Object>(); \ 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci ERROR_THROWER_WITH_MESSAGE(LinkError) 3251cb0ef41Sopenharmony_ci ERROR_THROWER_WITH_MESSAGE(TypeError) 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_ci#undef ERROR_THROWER_WITH_MESSAGE 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci // Look up an import value in the {ffi_} object. 3301cb0ef41Sopenharmony_ci MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name, 3311cb0ef41Sopenharmony_ci Handle<String> import_name); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci // Look up an import value in the {ffi_} object specifically for linking an 3341cb0ef41Sopenharmony_ci // asm.js module. This only performs non-observable lookups, which allows 3351cb0ef41Sopenharmony_ci // falling back to JavaScript proper (and hence re-executing all lookups) if 3361cb0ef41Sopenharmony_ci // module instantiation fails. 3371cb0ef41Sopenharmony_ci MaybeHandle<Object> LookupImportAsm(uint32_t index, 3381cb0ef41Sopenharmony_ci Handle<String> import_name); 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci // Load data segments into the memory. 3411cb0ef41Sopenharmony_ci void LoadDataSegments(Handle<WasmInstanceObject> instance); 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci void WriteGlobalValue(const WasmGlobal& global, const WasmValue& value); 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci void SanitizeImports(); 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci // Find the imported memory if there is one. 3481cb0ef41Sopenharmony_ci bool FindImportedMemory(); 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci // Allocate the memory. 3511cb0ef41Sopenharmony_ci bool AllocateMemory(); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci // Processes a single imported function. 3541cb0ef41Sopenharmony_ci bool ProcessImportedFunction(Handle<WasmInstanceObject> instance, 3551cb0ef41Sopenharmony_ci int import_index, int func_index, 3561cb0ef41Sopenharmony_ci Handle<String> module_name, 3571cb0ef41Sopenharmony_ci Handle<String> import_name, 3581cb0ef41Sopenharmony_ci Handle<Object> value); 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci // Initialize imported tables of type funcref. 3611cb0ef41Sopenharmony_ci bool InitializeImportedIndirectFunctionTable( 3621cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, int table_index, int import_index, 3631cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_object); 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci // Process a single imported table. 3661cb0ef41Sopenharmony_ci bool ProcessImportedTable(Handle<WasmInstanceObject> instance, 3671cb0ef41Sopenharmony_ci int import_index, int table_index, 3681cb0ef41Sopenharmony_ci Handle<String> module_name, 3691cb0ef41Sopenharmony_ci Handle<String> import_name, Handle<Object> value); 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci // Process a single imported memory. 3721cb0ef41Sopenharmony_ci bool ProcessImportedMemory(Handle<WasmInstanceObject> instance, 3731cb0ef41Sopenharmony_ci int import_index, Handle<String> module_name, 3741cb0ef41Sopenharmony_ci Handle<String> import_name, Handle<Object> value); 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci // Process a single imported global. 3771cb0ef41Sopenharmony_ci bool ProcessImportedGlobal(Handle<WasmInstanceObject> instance, 3781cb0ef41Sopenharmony_ci int import_index, int global_index, 3791cb0ef41Sopenharmony_ci Handle<String> module_name, 3801cb0ef41Sopenharmony_ci Handle<String> import_name, Handle<Object> value); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci // Process a single imported WasmGlobalObject. 3831cb0ef41Sopenharmony_ci bool ProcessImportedWasmGlobalObject(Handle<WasmInstanceObject> instance, 3841cb0ef41Sopenharmony_ci int import_index, 3851cb0ef41Sopenharmony_ci Handle<String> module_name, 3861cb0ef41Sopenharmony_ci Handle<String> import_name, 3871cb0ef41Sopenharmony_ci const WasmGlobal& global, 3881cb0ef41Sopenharmony_ci Handle<WasmGlobalObject> global_object); 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci // Compile import wrappers in parallel. The result goes into the native 3911cb0ef41Sopenharmony_ci // module's import_wrapper_cache. 3921cb0ef41Sopenharmony_ci void CompileImportWrappers(Handle<WasmInstanceObject> instance); 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci // Process the imports, including functions, tables, globals, and memory, in 3951cb0ef41Sopenharmony_ci // order, loading them from the {ffi_} object. Returns the number of imported 3961cb0ef41Sopenharmony_ci // functions, or {-1} on error. 3971cb0ef41Sopenharmony_ci int ProcessImports(Handle<WasmInstanceObject> instance); 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci template <typename T> 4001cb0ef41Sopenharmony_ci T* GetRawUntaggedGlobalPtr(const WasmGlobal& global); 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci // Process initialization of globals. 4031cb0ef41Sopenharmony_ci void InitGlobals(Handle<WasmInstanceObject> instance); 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci // Process the exports, creating wrappers for functions, tables, memories, 4061cb0ef41Sopenharmony_ci // and globals. 4071cb0ef41Sopenharmony_ci void ProcessExports(Handle<WasmInstanceObject> instance); 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci void InitializeNonDefaultableTables(Handle<WasmInstanceObject> instance); 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci void LoadTableSegments(Handle<WasmInstanceObject> instance); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci // Creates new tags. Note that some tags might already exist if they were 4141cb0ef41Sopenharmony_ci // imported, those tags will be re-used. 4151cb0ef41Sopenharmony_ci void InitializeTags(Handle<WasmInstanceObject> instance); 4161cb0ef41Sopenharmony_ci}; 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ciMaybeHandle<WasmInstanceObject> InstantiateToInstanceObject( 4191cb0ef41Sopenharmony_ci Isolate* isolate, ErrorThrower* thrower, 4201cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports, 4211cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> memory_buffer) { 4221cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId context_id = 4231cb0ef41Sopenharmony_ci isolate->GetOrRegisterRecorderContextId(isolate->native_context()); 4241cb0ef41Sopenharmony_ci InstanceBuilder builder(isolate, context_id, thrower, module_object, imports, 4251cb0ef41Sopenharmony_ci memory_buffer); 4261cb0ef41Sopenharmony_ci auto instance = builder.Build(); 4271cb0ef41Sopenharmony_ci if (!instance.is_null() && builder.ExecuteStartFunction()) { 4281cb0ef41Sopenharmony_ci return instance; 4291cb0ef41Sopenharmony_ci } 4301cb0ef41Sopenharmony_ci DCHECK(isolate->has_pending_exception() || thrower->error()); 4311cb0ef41Sopenharmony_ci return {}; 4321cb0ef41Sopenharmony_ci} 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ciInstanceBuilder::InstanceBuilder(Isolate* isolate, 4351cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId context_id, 4361cb0ef41Sopenharmony_ci ErrorThrower* thrower, 4371cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object, 4381cb0ef41Sopenharmony_ci MaybeHandle<JSReceiver> ffi, 4391cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> memory_buffer) 4401cb0ef41Sopenharmony_ci : isolate_(isolate), 4411cb0ef41Sopenharmony_ci context_id_(context_id), 4421cb0ef41Sopenharmony_ci enabled_(module_object->native_module()->enabled_features()), 4431cb0ef41Sopenharmony_ci module_(module_object->module()), 4441cb0ef41Sopenharmony_ci thrower_(thrower), 4451cb0ef41Sopenharmony_ci module_object_(module_object), 4461cb0ef41Sopenharmony_ci ffi_(ffi), 4471cb0ef41Sopenharmony_ci memory_buffer_(memory_buffer), 4481cb0ef41Sopenharmony_ci init_expr_zone_(isolate_->allocator(), "init. expression zone") { 4491cb0ef41Sopenharmony_ci sanitized_imports_.reserve(module_->import_table.size()); 4501cb0ef41Sopenharmony_ci} 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci// Build an instance, in all of its glory. 4531cb0ef41Sopenharmony_ciMaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { 4541cb0ef41Sopenharmony_ci TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"), 4551cb0ef41Sopenharmony_ci "wasm.InstanceBuilder.Build"); 4561cb0ef41Sopenharmony_ci // Check that an imports argument was provided, if the module requires it. 4571cb0ef41Sopenharmony_ci // No point in continuing otherwise. 4581cb0ef41Sopenharmony_ci if (!module_->import_table.empty() && ffi_.is_null()) { 4591cb0ef41Sopenharmony_ci thrower_->TypeError( 4601cb0ef41Sopenharmony_ci "Imports argument must be present and must be an object"); 4611cb0ef41Sopenharmony_ci return {}; 4621cb0ef41Sopenharmony_ci } 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci SanitizeImports(); 4651cb0ef41Sopenharmony_ci if (thrower_->error()) return {}; 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci // From here on, we expect the build pipeline to run without exiting to JS. 4681cb0ef41Sopenharmony_ci DisallowJavascriptExecution no_js(isolate_); 4691cb0ef41Sopenharmony_ci // Record build time into correct bucket, then build instance. 4701cb0ef41Sopenharmony_ci TimedHistogramScope wasm_instantiate_module_time_scope(SELECT_WASM_COUNTER( 4711cb0ef41Sopenharmony_ci isolate_->counters(), module_->origin, wasm_instantiate, module_time)); 4721cb0ef41Sopenharmony_ci v8::metrics::WasmModuleInstantiated wasm_module_instantiated; 4731cb0ef41Sopenharmony_ci base::ElapsedTimer timer; 4741cb0ef41Sopenharmony_ci timer.Start(); 4751cb0ef41Sopenharmony_ci NativeModule* native_module = module_object_->native_module(); 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 4781cb0ef41Sopenharmony_ci // Set up the memory buffer and memory objects. 4791cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 4801cb0ef41Sopenharmony_ci uint32_t initial_pages = module_->initial_pages; 4811cb0ef41Sopenharmony_ci auto initial_pages_counter = SELECT_WASM_COUNTER( 4821cb0ef41Sopenharmony_ci isolate_->counters(), module_->origin, wasm, min_mem_pages_count); 4831cb0ef41Sopenharmony_ci initial_pages_counter->AddSample(initial_pages); 4841cb0ef41Sopenharmony_ci if (module_->has_maximum_pages) { 4851cb0ef41Sopenharmony_ci DCHECK_EQ(kWasmOrigin, module_->origin); 4861cb0ef41Sopenharmony_ci auto max_pages_counter = 4871cb0ef41Sopenharmony_ci isolate_->counters()->wasm_wasm_max_mem_pages_count(); 4881cb0ef41Sopenharmony_ci max_pages_counter->AddSample(module_->maximum_pages); 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci if (is_asmjs_module(module_)) { 4921cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer; 4931cb0ef41Sopenharmony_ci if (memory_buffer_.ToHandle(&buffer)) { 4941cb0ef41Sopenharmony_ci // asm.js instantiation should have changed the state of the buffer. 4951cb0ef41Sopenharmony_ci CHECK(!buffer->is_detachable()); 4961cb0ef41Sopenharmony_ci CHECK(buffer->is_asmjs_memory()); 4971cb0ef41Sopenharmony_ci } else { 4981cb0ef41Sopenharmony_ci // Use an empty JSArrayBuffer for degenerate asm.js modules. 4991cb0ef41Sopenharmony_ci memory_buffer_ = isolate_->factory()->NewJSArrayBufferAndBackingStore( 5001cb0ef41Sopenharmony_ci 0, InitializedFlag::kUninitialized); 5011cb0ef41Sopenharmony_ci if (!memory_buffer_.ToHandle(&buffer)) { 5021cb0ef41Sopenharmony_ci thrower_->RangeError("Out of memory: asm.js memory"); 5031cb0ef41Sopenharmony_ci return {}; 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci buffer->set_is_asmjs_memory(true); 5061cb0ef41Sopenharmony_ci buffer->set_is_detachable(false); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci // The maximum number of pages isn't strictly necessary for memory 5101cb0ef41Sopenharmony_ci // objects used for asm.js, as they are never visible, but we might 5111cb0ef41Sopenharmony_ci // as well make it accurate. 5121cb0ef41Sopenharmony_ci auto maximum_pages = 5131cb0ef41Sopenharmony_ci static_cast<int>(RoundUp(buffer->byte_length(), wasm::kWasmPageSize) / 5141cb0ef41Sopenharmony_ci wasm::kWasmPageSize); 5151cb0ef41Sopenharmony_ci memory_object_ = 5161cb0ef41Sopenharmony_ci WasmMemoryObject::New(isolate_, memory_buffer_, maximum_pages) 5171cb0ef41Sopenharmony_ci .ToHandleChecked(); 5181cb0ef41Sopenharmony_ci } else { 5191cb0ef41Sopenharmony_ci // Actual wasm module must have either imported or created memory. 5201cb0ef41Sopenharmony_ci CHECK(memory_buffer_.is_null()); 5211cb0ef41Sopenharmony_ci if (!FindImportedMemory()) { 5221cb0ef41Sopenharmony_ci if (module_->has_memory && !AllocateMemory()) { 5231cb0ef41Sopenharmony_ci DCHECK(isolate_->has_pending_exception() || thrower_->error()); 5241cb0ef41Sopenharmony_ci return {}; 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci } 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5301cb0ef41Sopenharmony_ci // Create the WebAssembly.Instance object. 5311cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5321cb0ef41Sopenharmony_ci TRACE("New module instantiation for %p\n", native_module); 5331cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance = 5341cb0ef41Sopenharmony_ci WasmInstanceObject::New(isolate_, module_object_); 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5371cb0ef41Sopenharmony_ci // Attach the memory to the instance. 5381cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5391cb0ef41Sopenharmony_ci if (module_->has_memory) { 5401cb0ef41Sopenharmony_ci DCHECK(!memory_object_.is_null()); 5411cb0ef41Sopenharmony_ci if (!instance->has_memory_object()) { 5421cb0ef41Sopenharmony_ci instance->set_memory_object(*memory_object_); 5431cb0ef41Sopenharmony_ci } 5441cb0ef41Sopenharmony_ci // Add the instance object to the list of instances for this memory. 5451cb0ef41Sopenharmony_ci WasmMemoryObject::AddInstance(isolate_, memory_object_, instance); 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci // Double-check the {memory} array buffer matches the instance. 5481cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> memory = memory_buffer_.ToHandleChecked(); 5491cb0ef41Sopenharmony_ci CHECK_EQ(instance->memory_size(), memory->byte_length()); 5501cb0ef41Sopenharmony_ci CHECK_EQ(instance->memory_start(), memory->backing_store()); 5511cb0ef41Sopenharmony_ci } 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5541cb0ef41Sopenharmony_ci // Set up the globals for the new instance. 5551cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5561cb0ef41Sopenharmony_ci uint32_t untagged_globals_buffer_size = module_->untagged_globals_buffer_size; 5571cb0ef41Sopenharmony_ci if (untagged_globals_buffer_size > 0) { 5581cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> result = 5591cb0ef41Sopenharmony_ci isolate_->factory()->NewJSArrayBufferAndBackingStore( 5601cb0ef41Sopenharmony_ci untagged_globals_buffer_size, InitializedFlag::kZeroInitialized, 5611cb0ef41Sopenharmony_ci AllocationType::kOld); 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci if (!result.ToHandle(&untagged_globals_)) { 5641cb0ef41Sopenharmony_ci thrower_->RangeError("Out of memory: wasm globals"); 5651cb0ef41Sopenharmony_ci return {}; 5661cb0ef41Sopenharmony_ci } 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci instance->set_untagged_globals_buffer(*untagged_globals_); 5691cb0ef41Sopenharmony_ci instance->set_globals_start( 5701cb0ef41Sopenharmony_ci reinterpret_cast<byte*>(untagged_globals_->backing_store())); 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci uint32_t tagged_globals_buffer_size = module_->tagged_globals_buffer_size; 5741cb0ef41Sopenharmony_ci if (tagged_globals_buffer_size > 0) { 5751cb0ef41Sopenharmony_ci tagged_globals_ = isolate_->factory()->NewFixedArray( 5761cb0ef41Sopenharmony_ci static_cast<int>(tagged_globals_buffer_size)); 5771cb0ef41Sopenharmony_ci instance->set_tagged_globals_buffer(*tagged_globals_); 5781cb0ef41Sopenharmony_ci } 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5811cb0ef41Sopenharmony_ci // Set up the array of references to imported globals' array buffers. 5821cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5831cb0ef41Sopenharmony_ci if (module_->num_imported_mutable_globals > 0) { 5841cb0ef41Sopenharmony_ci // TODO(binji): This allocates one slot for each mutable global, which is 5851cb0ef41Sopenharmony_ci // more than required if multiple globals are imported from the same 5861cb0ef41Sopenharmony_ci // module. 5871cb0ef41Sopenharmony_ci Handle<FixedArray> buffers_array = isolate_->factory()->NewFixedArray( 5881cb0ef41Sopenharmony_ci module_->num_imported_mutable_globals, AllocationType::kOld); 5891cb0ef41Sopenharmony_ci instance->set_imported_mutable_globals_buffers(*buffers_array); 5901cb0ef41Sopenharmony_ci } 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5931cb0ef41Sopenharmony_ci // Set up the tag table used for exception tag checks. 5941cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 5951cb0ef41Sopenharmony_ci int tags_count = static_cast<int>(module_->tags.size()); 5961cb0ef41Sopenharmony_ci if (tags_count > 0) { 5971cb0ef41Sopenharmony_ci Handle<FixedArray> tag_table = 5981cb0ef41Sopenharmony_ci isolate_->factory()->NewFixedArray(tags_count, AllocationType::kOld); 5991cb0ef41Sopenharmony_ci instance->set_tags_table(*tag_table); 6001cb0ef41Sopenharmony_ci tags_wrappers_.resize(tags_count); 6011cb0ef41Sopenharmony_ci } 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6041cb0ef41Sopenharmony_ci // Set up table storage space. 6051cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6061cb0ef41Sopenharmony_ci int table_count = static_cast<int>(module_->tables.size()); 6071cb0ef41Sopenharmony_ci { 6081cb0ef41Sopenharmony_ci for (int i = 0; i < table_count; i++) { 6091cb0ef41Sopenharmony_ci const WasmTable& table = module_->tables[i]; 6101cb0ef41Sopenharmony_ci if (table.initial_size > FLAG_wasm_max_table_size) { 6111cb0ef41Sopenharmony_ci thrower_->RangeError( 6121cb0ef41Sopenharmony_ci "initial table size (%u elements) is larger than implementation " 6131cb0ef41Sopenharmony_ci "limit (%u elements)", 6141cb0ef41Sopenharmony_ci table.initial_size, FLAG_wasm_max_table_size); 6151cb0ef41Sopenharmony_ci return {}; 6161cb0ef41Sopenharmony_ci } 6171cb0ef41Sopenharmony_ci } 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_ci Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count); 6201cb0ef41Sopenharmony_ci for (int i = module_->num_imported_tables; i < table_count; i++) { 6211cb0ef41Sopenharmony_ci const WasmTable& table = module_->tables[i]; 6221cb0ef41Sopenharmony_ci // Initialize tables with null for now. We will initialize non-defaultable 6231cb0ef41Sopenharmony_ci // tables later, in {InitializeNonDefaultableTables}. 6241cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_obj = WasmTableObject::New( 6251cb0ef41Sopenharmony_ci isolate_, instance, table.type, table.initial_size, 6261cb0ef41Sopenharmony_ci table.has_maximum_size, table.maximum_size, nullptr, 6271cb0ef41Sopenharmony_ci isolate_->factory()->null_value()); 6281cb0ef41Sopenharmony_ci tables->set(i, *table_obj); 6291cb0ef41Sopenharmony_ci } 6301cb0ef41Sopenharmony_ci instance->set_tables(*tables); 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci { 6341cb0ef41Sopenharmony_ci Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count); 6351cb0ef41Sopenharmony_ci for (int i = 0; i < table_count; ++i) { 6361cb0ef41Sopenharmony_ci const WasmTable& table = module_->tables[i]; 6371cb0ef41Sopenharmony_ci if (IsSubtypeOf(table.type, kWasmFuncRef, module_)) { 6381cb0ef41Sopenharmony_ci Handle<WasmIndirectFunctionTable> table_obj = 6391cb0ef41Sopenharmony_ci WasmIndirectFunctionTable::New(isolate_, table.initial_size); 6401cb0ef41Sopenharmony_ci tables->set(i, *table_obj); 6411cb0ef41Sopenharmony_ci } 6421cb0ef41Sopenharmony_ci } 6431cb0ef41Sopenharmony_ci instance->set_indirect_function_tables(*tables); 6441cb0ef41Sopenharmony_ci } 6451cb0ef41Sopenharmony_ci 6461cb0ef41Sopenharmony_ci instance->SetIndirectFunctionTableShortcuts(isolate_); 6471cb0ef41Sopenharmony_ci 6481cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6491cb0ef41Sopenharmony_ci // Process the imports for the module. 6501cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6511cb0ef41Sopenharmony_ci if (!module_->import_table.empty()) { 6521cb0ef41Sopenharmony_ci int num_imported_functions = ProcessImports(instance); 6531cb0ef41Sopenharmony_ci if (num_imported_functions < 0) return {}; 6541cb0ef41Sopenharmony_ci wasm_module_instantiated.imported_function_count = num_imported_functions; 6551cb0ef41Sopenharmony_ci } 6561cb0ef41Sopenharmony_ci 6571cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6581cb0ef41Sopenharmony_ci // Create maps for managed objects (GC proposal). 6591cb0ef41Sopenharmony_ci // Must happen before {InitGlobals} because globals can refer to these maps. 6601cb0ef41Sopenharmony_ci // We do not need to cache the canonical rtts to (rtt.canon any)'s subtype 6611cb0ef41Sopenharmony_ci // list. 6621cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6631cb0ef41Sopenharmony_ci if (enabled_.has_gc()) { 6641cb0ef41Sopenharmony_ci if (FLAG_wasm_type_canonicalization) { 6651cb0ef41Sopenharmony_ci uint32_t maximum_canonical_type_index = 6661cb0ef41Sopenharmony_ci *std::max_element(module_->isorecursive_canonical_type_ids.begin(), 6671cb0ef41Sopenharmony_ci module_->isorecursive_canonical_type_ids.end()); 6681cb0ef41Sopenharmony_ci // Make sure all canonical indices have been set. 6691cb0ef41Sopenharmony_ci DCHECK_NE(maximum_canonical_type_index, kNoSuperType); 6701cb0ef41Sopenharmony_ci isolate_->heap()->EnsureWasmCanonicalRttsSize( 6711cb0ef41Sopenharmony_ci maximum_canonical_type_index + 1); 6721cb0ef41Sopenharmony_ci } 6731cb0ef41Sopenharmony_ci Handle<FixedArray> maps = isolate_->factory()->NewFixedArray( 6741cb0ef41Sopenharmony_ci static_cast<int>(module_->types.size())); 6751cb0ef41Sopenharmony_ci for (uint32_t index = 0; index < module_->types.size(); index++) { 6761cb0ef41Sopenharmony_ci CreateMapForType(isolate_, module_, index, instance, maps); 6771cb0ef41Sopenharmony_ci } 6781cb0ef41Sopenharmony_ci instance->set_managed_object_maps(*maps); 6791cb0ef41Sopenharmony_ci } 6801cb0ef41Sopenharmony_ci 6811cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6821cb0ef41Sopenharmony_ci // Allocate type feedback vectors for functions. 6831cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 6841cb0ef41Sopenharmony_ci if (FLAG_wasm_speculative_inlining) { 6851cb0ef41Sopenharmony_ci int num_functions = static_cast<int>(module_->num_declared_functions); 6861cb0ef41Sopenharmony_ci Handle<FixedArray> vectors = 6871cb0ef41Sopenharmony_ci isolate_->factory()->NewFixedArray(num_functions, AllocationType::kOld); 6881cb0ef41Sopenharmony_ci instance->set_feedback_vectors(*vectors); 6891cb0ef41Sopenharmony_ci for (int i = 0; i < num_functions; i++) { 6901cb0ef41Sopenharmony_ci int func_index = module_->num_imported_functions + i; 6911cb0ef41Sopenharmony_ci int slots = 6921cb0ef41Sopenharmony_ci base::Relaxed_Load(&module_->functions[func_index].feedback_slots); 6931cb0ef41Sopenharmony_ci if (slots == 0) continue; 6941cb0ef41Sopenharmony_ci if (FLAG_trace_wasm_speculative_inlining) { 6951cb0ef41Sopenharmony_ci PrintF("[Function %d (declared %d): allocating %d feedback slots]\n", 6961cb0ef41Sopenharmony_ci func_index, i, slots); 6971cb0ef41Sopenharmony_ci } 6981cb0ef41Sopenharmony_ci Handle<FixedArray> feedback = 6991cb0ef41Sopenharmony_ci isolate_->factory()->NewFixedArrayWithZeroes(slots); 7001cb0ef41Sopenharmony_ci vectors->set(i, *feedback); 7011cb0ef41Sopenharmony_ci } 7021cb0ef41Sopenharmony_ci } 7031cb0ef41Sopenharmony_ci 7041cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7051cb0ef41Sopenharmony_ci // Process the initialization for the module's globals. 7061cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7071cb0ef41Sopenharmony_ci InitGlobals(instance); 7081cb0ef41Sopenharmony_ci 7091cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7101cb0ef41Sopenharmony_ci // Initialize the indirect function tables and dispatch tables. We do this 7111cb0ef41Sopenharmony_ci // before initializing non-defaultable tables and loading element segments, so 7121cb0ef41Sopenharmony_ci // that indirect function tables in this module are included in the updates 7131cb0ef41Sopenharmony_ci // when we do so. 7141cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7151cb0ef41Sopenharmony_ci for (int table_index = 0; 7161cb0ef41Sopenharmony_ci table_index < static_cast<int>(module_->tables.size()); ++table_index) { 7171cb0ef41Sopenharmony_ci const WasmTable& table = module_->tables[table_index]; 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci if (IsSubtypeOf(table.type, kWasmFuncRef, module_)) { 7201cb0ef41Sopenharmony_ci WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( 7211cb0ef41Sopenharmony_ci instance, table_index, table.initial_size); 7221cb0ef41Sopenharmony_ci if (thrower_->error()) return {}; 7231cb0ef41Sopenharmony_ci auto table_object = handle( 7241cb0ef41Sopenharmony_ci WasmTableObject::cast(instance->tables().get(table_index)), isolate_); 7251cb0ef41Sopenharmony_ci WasmTableObject::AddDispatchTable(isolate_, table_object, instance, 7261cb0ef41Sopenharmony_ci table_index); 7271cb0ef41Sopenharmony_ci } 7281cb0ef41Sopenharmony_ci } 7291cb0ef41Sopenharmony_ci 7301cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7311cb0ef41Sopenharmony_ci // Initialize non-defaultable tables. 7321cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7331cb0ef41Sopenharmony_ci if (FLAG_experimental_wasm_typed_funcref) { 7341cb0ef41Sopenharmony_ci InitializeNonDefaultableTables(instance); 7351cb0ef41Sopenharmony_ci } 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7381cb0ef41Sopenharmony_ci // Initialize the tags table. 7391cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7401cb0ef41Sopenharmony_ci if (tags_count > 0) { 7411cb0ef41Sopenharmony_ci InitializeTags(instance); 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci 7441cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7451cb0ef41Sopenharmony_ci // Set up the exports object for the new instance. 7461cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7471cb0ef41Sopenharmony_ci ProcessExports(instance); 7481cb0ef41Sopenharmony_ci if (thrower_->error()) return {}; 7491cb0ef41Sopenharmony_ci 7501cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7511cb0ef41Sopenharmony_ci // Load element segments into tables. 7521cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7531cb0ef41Sopenharmony_ci if (table_count > 0) { 7541cb0ef41Sopenharmony_ci LoadTableSegments(instance); 7551cb0ef41Sopenharmony_ci if (thrower_->error()) return {}; 7561cb0ef41Sopenharmony_ci } 7571cb0ef41Sopenharmony_ci 7581cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7591cb0ef41Sopenharmony_ci // Initialize the memory by loading data segments. 7601cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7611cb0ef41Sopenharmony_ci if (module_->data_segments.size() > 0) { 7621cb0ef41Sopenharmony_ci LoadDataSegments(instance); 7631cb0ef41Sopenharmony_ci if (thrower_->error()) return {}; 7641cb0ef41Sopenharmony_ci } 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7671cb0ef41Sopenharmony_ci // Create a wrapper for the start function. 7681cb0ef41Sopenharmony_ci //-------------------------------------------------------------------------- 7691cb0ef41Sopenharmony_ci if (module_->start_function_index >= 0) { 7701cb0ef41Sopenharmony_ci int start_index = module_->start_function_index; 7711cb0ef41Sopenharmony_ci auto& function = module_->functions[start_index]; 7721cb0ef41Sopenharmony_ci Handle<CodeT> wrapper_code = 7731cb0ef41Sopenharmony_ci ToCodeT(JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper( 7741cb0ef41Sopenharmony_ci isolate_, function.sig, module_, function.imported), 7751cb0ef41Sopenharmony_ci isolate_); 7761cb0ef41Sopenharmony_ci // TODO(clemensb): Don't generate an exported function for the start 7771cb0ef41Sopenharmony_ci // function. Use CWasmEntry instead. 7781cb0ef41Sopenharmony_ci start_function_ = WasmExportedFunction::New( 7791cb0ef41Sopenharmony_ci isolate_, instance, start_index, 7801cb0ef41Sopenharmony_ci static_cast<int>(function.sig->parameter_count()), wrapper_code); 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_ci if (function.imported) { 7831cb0ef41Sopenharmony_ci ImportedFunctionEntry entry(instance, module_->start_function_index); 7841cb0ef41Sopenharmony_ci Object callable = entry.maybe_callable(); 7851cb0ef41Sopenharmony_ci if (callable.IsJSFunction()) { 7861cb0ef41Sopenharmony_ci // If the start function was imported and calls into Blink, we have 7871cb0ef41Sopenharmony_ci // to pretend that the V8 API was used to enter its correct context. 7881cb0ef41Sopenharmony_ci // To get that context to {ExecuteStartFunction} below, we install it 7891cb0ef41Sopenharmony_ci // as the context of the wrapper we just compiled. That's a bit of a 7901cb0ef41Sopenharmony_ci // hack because it's not really the wrapper's context, only its wrapped 7911cb0ef41Sopenharmony_ci // target's context, but the end result is the same, and since the 7921cb0ef41Sopenharmony_ci // start function wrapper doesn't leak, neither does this 7931cb0ef41Sopenharmony_ci // implementation detail. 7941cb0ef41Sopenharmony_ci start_function_->set_context(JSFunction::cast(callable).context()); 7951cb0ef41Sopenharmony_ci } 7961cb0ef41Sopenharmony_ci } 7971cb0ef41Sopenharmony_ci } 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci DCHECK(!isolate_->has_pending_exception()); 8001cb0ef41Sopenharmony_ci TRACE("Successfully built instance for module %p\n", 8011cb0ef41Sopenharmony_ci module_object_->native_module()); 8021cb0ef41Sopenharmony_ci wasm_module_instantiated.success = true; 8031cb0ef41Sopenharmony_ci wasm_module_instantiated.wall_clock_duration_in_us = 8041cb0ef41Sopenharmony_ci timer.Elapsed().InMicroseconds(); 8051cb0ef41Sopenharmony_ci timer.Stop(); 8061cb0ef41Sopenharmony_ci isolate_->metrics_recorder()->DelayMainThreadEvent(wasm_module_instantiated, 8071cb0ef41Sopenharmony_ci context_id_); 8081cb0ef41Sopenharmony_ci return instance; 8091cb0ef41Sopenharmony_ci} 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_cibool InstanceBuilder::ExecuteStartFunction() { 8121cb0ef41Sopenharmony_ci TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"), 8131cb0ef41Sopenharmony_ci "wasm.ExecuteStartFunction"); 8141cb0ef41Sopenharmony_ci if (start_function_.is_null()) return true; // No start function. 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ci HandleScope scope(isolate_); 8171cb0ef41Sopenharmony_ci // In case the start function calls out to Blink, we have to make sure that 8181cb0ef41Sopenharmony_ci // the correct "entered context" is available. This is the equivalent of 8191cb0ef41Sopenharmony_ci // v8::Context::Enter() and must happen in addition to the function call 8201cb0ef41Sopenharmony_ci // sequence doing the compiled version of "isolate->set_context(...)". 8211cb0ef41Sopenharmony_ci HandleScopeImplementer* hsi = isolate_->handle_scope_implementer(); 8221cb0ef41Sopenharmony_ci hsi->EnterContext(start_function_->native_context()); 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_ci // Call the JS function. 8251cb0ef41Sopenharmony_ci Handle<Object> undefined = isolate_->factory()->undefined_value(); 8261cb0ef41Sopenharmony_ci MaybeHandle<Object> retval = 8271cb0ef41Sopenharmony_ci Execution::Call(isolate_, start_function_, undefined, 0, nullptr); 8281cb0ef41Sopenharmony_ci hsi->LeaveContext(); 8291cb0ef41Sopenharmony_ci 8301cb0ef41Sopenharmony_ci if (retval.is_null()) { 8311cb0ef41Sopenharmony_ci DCHECK(isolate_->has_pending_exception()); 8321cb0ef41Sopenharmony_ci return false; 8331cb0ef41Sopenharmony_ci } 8341cb0ef41Sopenharmony_ci return true; 8351cb0ef41Sopenharmony_ci} 8361cb0ef41Sopenharmony_ci 8371cb0ef41Sopenharmony_ci// Look up an import value in the {ffi_} object. 8381cb0ef41Sopenharmony_ciMaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index, 8391cb0ef41Sopenharmony_ci Handle<String> module_name, 8401cb0ef41Sopenharmony_ci Handle<String> import_name) { 8411cb0ef41Sopenharmony_ci // We pre-validated in the js-api layer that the ffi object is present, and 8421cb0ef41Sopenharmony_ci // a JSObject, if the module has imports. 8431cb0ef41Sopenharmony_ci DCHECK(!ffi_.is_null()); 8441cb0ef41Sopenharmony_ci // Look up the module first. 8451cb0ef41Sopenharmony_ci MaybeHandle<Object> result = Object::GetPropertyOrElement( 8461cb0ef41Sopenharmony_ci isolate_, ffi_.ToHandleChecked(), module_name); 8471cb0ef41Sopenharmony_ci if (result.is_null()) { 8481cb0ef41Sopenharmony_ci return ReportTypeError("module not found", index, module_name); 8491cb0ef41Sopenharmony_ci } 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci Handle<Object> module = result.ToHandleChecked(); 8521cb0ef41Sopenharmony_ci 8531cb0ef41Sopenharmony_ci // Look up the value in the module. 8541cb0ef41Sopenharmony_ci if (!module->IsJSReceiver()) { 8551cb0ef41Sopenharmony_ci return ReportTypeError("module is not an object or function", index, 8561cb0ef41Sopenharmony_ci module_name); 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ci result = Object::GetPropertyOrElement(isolate_, module, import_name); 8601cb0ef41Sopenharmony_ci if (result.is_null()) { 8611cb0ef41Sopenharmony_ci ReportLinkError("import not found", index, module_name, import_name); 8621cb0ef41Sopenharmony_ci return MaybeHandle<JSFunction>(); 8631cb0ef41Sopenharmony_ci } 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_ci return result; 8661cb0ef41Sopenharmony_ci} 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_cinamespace { 8691cb0ef41Sopenharmony_cibool HasDefaultToNumberBehaviour(Isolate* isolate, 8701cb0ef41Sopenharmony_ci Handle<JSFunction> function) { 8711cb0ef41Sopenharmony_ci // Disallow providing a [Symbol.toPrimitive] member. 8721cb0ef41Sopenharmony_ci LookupIterator to_primitive_it{isolate, function, 8731cb0ef41Sopenharmony_ci isolate->factory()->to_primitive_symbol()}; 8741cb0ef41Sopenharmony_ci if (to_primitive_it.state() != LookupIterator::NOT_FOUND) return false; 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_ci // The {valueOf} member must be the default "ObjectPrototypeValueOf". 8771cb0ef41Sopenharmony_ci LookupIterator value_of_it{isolate, function, 8781cb0ef41Sopenharmony_ci isolate->factory()->valueOf_string()}; 8791cb0ef41Sopenharmony_ci if (value_of_it.state() != LookupIterator::DATA) return false; 8801cb0ef41Sopenharmony_ci Handle<Object> value_of = value_of_it.GetDataValue(); 8811cb0ef41Sopenharmony_ci if (!value_of->IsJSFunction()) return false; 8821cb0ef41Sopenharmony_ci Builtin value_of_builtin_id = 8831cb0ef41Sopenharmony_ci Handle<JSFunction>::cast(value_of)->code().builtin_id(); 8841cb0ef41Sopenharmony_ci if (value_of_builtin_id != Builtin::kObjectPrototypeValueOf) return false; 8851cb0ef41Sopenharmony_ci 8861cb0ef41Sopenharmony_ci // The {toString} member must be the default "FunctionPrototypeToString". 8871cb0ef41Sopenharmony_ci LookupIterator to_string_it{isolate, function, 8881cb0ef41Sopenharmony_ci isolate->factory()->toString_string()}; 8891cb0ef41Sopenharmony_ci if (to_string_it.state() != LookupIterator::DATA) return false; 8901cb0ef41Sopenharmony_ci Handle<Object> to_string = to_string_it.GetDataValue(); 8911cb0ef41Sopenharmony_ci if (!to_string->IsJSFunction()) return false; 8921cb0ef41Sopenharmony_ci Builtin to_string_builtin_id = 8931cb0ef41Sopenharmony_ci Handle<JSFunction>::cast(to_string)->code().builtin_id(); 8941cb0ef41Sopenharmony_ci if (to_string_builtin_id != Builtin::kFunctionPrototypeToString) return false; 8951cb0ef41Sopenharmony_ci 8961cb0ef41Sopenharmony_ci // Just a default function, which will convert to "Nan". Accept this. 8971cb0ef41Sopenharmony_ci return true; 8981cb0ef41Sopenharmony_ci} 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ciV8_INLINE WasmValue EvaluateInitExpression(Zone* zone, ConstantExpression expr, 9011cb0ef41Sopenharmony_ci ValueType expected, Isolate* isolate, 9021cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 9031cb0ef41Sopenharmony_ci ErrorThrower* thrower) { 9041cb0ef41Sopenharmony_ci switch (expr.kind()) { 9051cb0ef41Sopenharmony_ci case ConstantExpression::kEmpty: 9061cb0ef41Sopenharmony_ci UNREACHABLE(); 9071cb0ef41Sopenharmony_ci case ConstantExpression::kI32Const: 9081cb0ef41Sopenharmony_ci return WasmValue(expr.i32_value()); 9091cb0ef41Sopenharmony_ci case ConstantExpression::kRefNull: 9101cb0ef41Sopenharmony_ci return WasmValue(isolate->factory()->null_value(), 9111cb0ef41Sopenharmony_ci ValueType::Ref(expr.repr(), kNullable)); 9121cb0ef41Sopenharmony_ci case ConstantExpression::kRefFunc: { 9131cb0ef41Sopenharmony_ci uint32_t index = expr.index(); 9141cb0ef41Sopenharmony_ci Handle<Object> value = 9151cb0ef41Sopenharmony_ci WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate, instance, 9161cb0ef41Sopenharmony_ci index); 9171cb0ef41Sopenharmony_ci return WasmValue(value, expected); 9181cb0ef41Sopenharmony_ci } 9191cb0ef41Sopenharmony_ci case ConstantExpression::kWireBytesRef: { 9201cb0ef41Sopenharmony_ci WireBytesRef ref = expr.wire_bytes_ref(); 9211cb0ef41Sopenharmony_ci 9221cb0ef41Sopenharmony_ci base::Vector<const byte> module_bytes = 9231cb0ef41Sopenharmony_ci instance->module_object().native_module()->wire_bytes(); 9241cb0ef41Sopenharmony_ci 9251cb0ef41Sopenharmony_ci const byte* start = module_bytes.begin() + ref.offset(); 9261cb0ef41Sopenharmony_ci const byte* end = module_bytes.begin() + ref.end_offset(); 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci auto sig = FixedSizeSignature<ValueType>::Returns(expected); 9291cb0ef41Sopenharmony_ci FunctionBody body(&sig, ref.offset(), start, end); 9301cb0ef41Sopenharmony_ci WasmFeatures detected; 9311cb0ef41Sopenharmony_ci // We use kFullValidation so we do not have to create another template 9321cb0ef41Sopenharmony_ci // instance of WasmFullDecoder, which would cost us >50Kb binary code 9331cb0ef41Sopenharmony_ci // size. 9341cb0ef41Sopenharmony_ci WasmFullDecoder<Decoder::kFullValidation, InitExprInterface, 9351cb0ef41Sopenharmony_ci kInitExpression> 9361cb0ef41Sopenharmony_ci decoder(zone, instance->module(), WasmFeatures::All(), &detected, 9371cb0ef41Sopenharmony_ci body, instance->module(), isolate, instance); 9381cb0ef41Sopenharmony_ci 9391cb0ef41Sopenharmony_ci decoder.DecodeFunctionBody(); 9401cb0ef41Sopenharmony_ci 9411cb0ef41Sopenharmony_ci if (decoder.interface().runtime_error()) { 9421cb0ef41Sopenharmony_ci thrower->RuntimeError("%s", decoder.interface().runtime_error_msg()); 9431cb0ef41Sopenharmony_ci return {}; 9441cb0ef41Sopenharmony_ci } 9451cb0ef41Sopenharmony_ci 9461cb0ef41Sopenharmony_ci return decoder.interface().result(); 9471cb0ef41Sopenharmony_ci } 9481cb0ef41Sopenharmony_ci } 9491cb0ef41Sopenharmony_ci} 9501cb0ef41Sopenharmony_ci} // namespace 9511cb0ef41Sopenharmony_ci 9521cb0ef41Sopenharmony_ci// Look up an import value in the {ffi_} object specifically for linking an 9531cb0ef41Sopenharmony_ci// asm.js module. This only performs non-observable lookups, which allows 9541cb0ef41Sopenharmony_ci// falling back to JavaScript proper (and hence re-executing all lookups) if 9551cb0ef41Sopenharmony_ci// module instantiation fails. 9561cb0ef41Sopenharmony_ciMaybeHandle<Object> InstanceBuilder::LookupImportAsm( 9571cb0ef41Sopenharmony_ci uint32_t index, Handle<String> import_name) { 9581cb0ef41Sopenharmony_ci // Check that a foreign function interface object was provided. 9591cb0ef41Sopenharmony_ci if (ffi_.is_null()) { 9601cb0ef41Sopenharmony_ci return ReportLinkError("missing imports object", index, import_name); 9611cb0ef41Sopenharmony_ci } 9621cb0ef41Sopenharmony_ci 9631cb0ef41Sopenharmony_ci // Perform lookup of the given {import_name} without causing any observable 9641cb0ef41Sopenharmony_ci // side-effect. We only accept accesses that resolve to data properties, 9651cb0ef41Sopenharmony_ci // which is indicated by the asm.js spec in section 7 ("Linking") as well. 9661cb0ef41Sopenharmony_ci PropertyKey key(isolate_, Handle<Name>::cast(import_name)); 9671cb0ef41Sopenharmony_ci LookupIterator it(isolate_, ffi_.ToHandleChecked(), key); 9681cb0ef41Sopenharmony_ci switch (it.state()) { 9691cb0ef41Sopenharmony_ci case LookupIterator::ACCESS_CHECK: 9701cb0ef41Sopenharmony_ci case LookupIterator::INTEGER_INDEXED_EXOTIC: 9711cb0ef41Sopenharmony_ci case LookupIterator::INTERCEPTOR: 9721cb0ef41Sopenharmony_ci case LookupIterator::JSPROXY: 9731cb0ef41Sopenharmony_ci case LookupIterator::ACCESSOR: 9741cb0ef41Sopenharmony_ci case LookupIterator::TRANSITION: 9751cb0ef41Sopenharmony_ci return ReportLinkError("not a data property", index, import_name); 9761cb0ef41Sopenharmony_ci case LookupIterator::NOT_FOUND: 9771cb0ef41Sopenharmony_ci // Accepting missing properties as undefined does not cause any 9781cb0ef41Sopenharmony_ci // observable difference from JavaScript semantics, we are lenient. 9791cb0ef41Sopenharmony_ci return isolate_->factory()->undefined_value(); 9801cb0ef41Sopenharmony_ci case LookupIterator::DATA: { 9811cb0ef41Sopenharmony_ci Handle<Object> value = it.GetDataValue(); 9821cb0ef41Sopenharmony_ci // For legacy reasons, we accept functions for imported globals (see 9831cb0ef41Sopenharmony_ci // {ProcessImportedGlobal}), but only if we can easily determine that 9841cb0ef41Sopenharmony_ci // their Number-conversion is side effect free and returns NaN (which is 9851cb0ef41Sopenharmony_ci // the case as long as "valueOf" (or others) are not overwritten). 9861cb0ef41Sopenharmony_ci if (value->IsJSFunction() && 9871cb0ef41Sopenharmony_ci module_->import_table[index].kind == kExternalGlobal && 9881cb0ef41Sopenharmony_ci !HasDefaultToNumberBehaviour(isolate_, 9891cb0ef41Sopenharmony_ci Handle<JSFunction>::cast(value))) { 9901cb0ef41Sopenharmony_ci return ReportLinkError("function has special ToNumber behaviour", index, 9911cb0ef41Sopenharmony_ci import_name); 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci return value; 9941cb0ef41Sopenharmony_ci } 9951cb0ef41Sopenharmony_ci } 9961cb0ef41Sopenharmony_ci} 9971cb0ef41Sopenharmony_ci 9981cb0ef41Sopenharmony_ci// Load data segments into the memory. 9991cb0ef41Sopenharmony_civoid InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) { 10001cb0ef41Sopenharmony_ci base::Vector<const uint8_t> wire_bytes = 10011cb0ef41Sopenharmony_ci module_object_->native_module()->wire_bytes(); 10021cb0ef41Sopenharmony_ci for (const WasmDataSegment& segment : module_->data_segments) { 10031cb0ef41Sopenharmony_ci uint32_t size = segment.source.length(); 10041cb0ef41Sopenharmony_ci 10051cb0ef41Sopenharmony_ci // Passive segments are not copied during instantiation. 10061cb0ef41Sopenharmony_ci if (!segment.active) continue; 10071cb0ef41Sopenharmony_ci 10081cb0ef41Sopenharmony_ci size_t dest_offset; 10091cb0ef41Sopenharmony_ci if (module_->is_memory64) { 10101cb0ef41Sopenharmony_ci uint64_t dest_offset_64 = 10111cb0ef41Sopenharmony_ci EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, kWasmI64, 10121cb0ef41Sopenharmony_ci isolate_, instance, thrower_) 10131cb0ef41Sopenharmony_ci .to_u64(); 10141cb0ef41Sopenharmony_ci if (thrower_->error()) return; 10151cb0ef41Sopenharmony_ci // Clamp to {std::numeric_limits<size_t>::max()}, which is always an 10161cb0ef41Sopenharmony_ci // invalid offset. 10171cb0ef41Sopenharmony_ci DCHECK_GT(std::numeric_limits<size_t>::max(), instance->memory_size()); 10181cb0ef41Sopenharmony_ci dest_offset = static_cast<size_t>(std::min( 10191cb0ef41Sopenharmony_ci dest_offset_64, uint64_t{std::numeric_limits<size_t>::max()})); 10201cb0ef41Sopenharmony_ci } else { 10211cb0ef41Sopenharmony_ci dest_offset = 10221cb0ef41Sopenharmony_ci EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, kWasmI32, 10231cb0ef41Sopenharmony_ci isolate_, instance, thrower_) 10241cb0ef41Sopenharmony_ci .to_u32(); 10251cb0ef41Sopenharmony_ci if (thrower_->error()) return; 10261cb0ef41Sopenharmony_ci } 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_ci if (!base::IsInBounds<size_t>(dest_offset, size, instance->memory_size())) { 10291cb0ef41Sopenharmony_ci thrower_->RuntimeError("data segment is out of bounds"); 10301cb0ef41Sopenharmony_ci return; 10311cb0ef41Sopenharmony_ci } 10321cb0ef41Sopenharmony_ci 10331cb0ef41Sopenharmony_ci std::memcpy(instance->memory_start() + dest_offset, 10341cb0ef41Sopenharmony_ci wire_bytes.begin() + segment.source.offset(), size); 10351cb0ef41Sopenharmony_ci } 10361cb0ef41Sopenharmony_ci} 10371cb0ef41Sopenharmony_ci 10381cb0ef41Sopenharmony_civoid InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, 10391cb0ef41Sopenharmony_ci const WasmValue& value) { 10401cb0ef41Sopenharmony_ci TRACE("init [globals_start=%p + %u] = %s, type = %s\n", 10411cb0ef41Sopenharmony_ci global.type.is_reference() 10421cb0ef41Sopenharmony_ci ? reinterpret_cast<byte*>(tagged_globals_->address()) 10431cb0ef41Sopenharmony_ci : raw_buffer_ptr(untagged_globals_, 0), 10441cb0ef41Sopenharmony_ci global.offset, value.to_string().c_str(), global.type.name().c_str()); 10451cb0ef41Sopenharmony_ci DCHECK(IsSubtypeOf(value.type(), global.type, module_)); 10461cb0ef41Sopenharmony_ci if (global.type.is_numeric()) { 10471cb0ef41Sopenharmony_ci value.CopyTo(GetRawUntaggedGlobalPtr<byte>(global)); 10481cb0ef41Sopenharmony_ci } else { 10491cb0ef41Sopenharmony_ci tagged_globals_->set(global.offset, *value.to_ref()); 10501cb0ef41Sopenharmony_ci } 10511cb0ef41Sopenharmony_ci} 10521cb0ef41Sopenharmony_ci 10531cb0ef41Sopenharmony_civoid InstanceBuilder::SanitizeImports() { 10541cb0ef41Sopenharmony_ci base::Vector<const uint8_t> wire_bytes = 10551cb0ef41Sopenharmony_ci module_object_->native_module()->wire_bytes(); 10561cb0ef41Sopenharmony_ci for (size_t index = 0; index < module_->import_table.size(); ++index) { 10571cb0ef41Sopenharmony_ci const WasmImport& import = module_->import_table[index]; 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ci Handle<String> module_name = 10601cb0ef41Sopenharmony_ci WasmModuleObject::ExtractUtf8StringFromModuleBytes( 10611cb0ef41Sopenharmony_ci isolate_, wire_bytes, import.module_name, kInternalize); 10621cb0ef41Sopenharmony_ci 10631cb0ef41Sopenharmony_ci Handle<String> import_name = 10641cb0ef41Sopenharmony_ci WasmModuleObject::ExtractUtf8StringFromModuleBytes( 10651cb0ef41Sopenharmony_ci isolate_, wire_bytes, import.field_name, kInternalize); 10661cb0ef41Sopenharmony_ci 10671cb0ef41Sopenharmony_ci int int_index = static_cast<int>(index); 10681cb0ef41Sopenharmony_ci MaybeHandle<Object> result = 10691cb0ef41Sopenharmony_ci is_asmjs_module(module_) 10701cb0ef41Sopenharmony_ci ? LookupImportAsm(int_index, import_name) 10711cb0ef41Sopenharmony_ci : LookupImport(int_index, module_name, import_name); 10721cb0ef41Sopenharmony_ci if (thrower_->error()) { 10731cb0ef41Sopenharmony_ci thrower_->LinkError("Could not find value for import %zu", index); 10741cb0ef41Sopenharmony_ci return; 10751cb0ef41Sopenharmony_ci } 10761cb0ef41Sopenharmony_ci Handle<Object> value = result.ToHandleChecked(); 10771cb0ef41Sopenharmony_ci sanitized_imports_.push_back({module_name, import_name, value}); 10781cb0ef41Sopenharmony_ci } 10791cb0ef41Sopenharmony_ci} 10801cb0ef41Sopenharmony_ci 10811cb0ef41Sopenharmony_cibool InstanceBuilder::FindImportedMemory() { 10821cb0ef41Sopenharmony_ci DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size()); 10831cb0ef41Sopenharmony_ci for (size_t index = 0; index < module_->import_table.size(); index++) { 10841cb0ef41Sopenharmony_ci WasmImport import = module_->import_table[index]; 10851cb0ef41Sopenharmony_ci 10861cb0ef41Sopenharmony_ci if (import.kind == kExternalMemory) { 10871cb0ef41Sopenharmony_ci auto& value = sanitized_imports_[index].value; 10881cb0ef41Sopenharmony_ci if (!value->IsWasmMemoryObject()) return false; 10891cb0ef41Sopenharmony_ci memory_object_ = Handle<WasmMemoryObject>::cast(value); 10901cb0ef41Sopenharmony_ci memory_buffer_ = 10911cb0ef41Sopenharmony_ci Handle<JSArrayBuffer>(memory_object_->array_buffer(), isolate_); 10921cb0ef41Sopenharmony_ci return true; 10931cb0ef41Sopenharmony_ci } 10941cb0ef41Sopenharmony_ci } 10951cb0ef41Sopenharmony_ci return false; 10961cb0ef41Sopenharmony_ci} 10971cb0ef41Sopenharmony_ci 10981cb0ef41Sopenharmony_cibool InstanceBuilder::ProcessImportedFunction( 10991cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, int import_index, int func_index, 11001cb0ef41Sopenharmony_ci Handle<String> module_name, Handle<String> import_name, 11011cb0ef41Sopenharmony_ci Handle<Object> value) { 11021cb0ef41Sopenharmony_ci // Function imports must be callable. 11031cb0ef41Sopenharmony_ci if (!value->IsCallable()) { 11041cb0ef41Sopenharmony_ci ReportLinkError("function import requires a callable", import_index, 11051cb0ef41Sopenharmony_ci module_name, import_name); 11061cb0ef41Sopenharmony_ci return false; 11071cb0ef41Sopenharmony_ci } 11081cb0ef41Sopenharmony_ci // Store any {WasmExternalFunction} callable in the instance before the call 11091cb0ef41Sopenharmony_ci // is resolved to preserve its identity. This handles exported functions as 11101cb0ef41Sopenharmony_ci // well as functions constructed via other means (e.g. WebAssembly.Function). 11111cb0ef41Sopenharmony_ci if (WasmExternalFunction::IsWasmExternalFunction(*value)) { 11121cb0ef41Sopenharmony_ci WasmInstanceObject::SetWasmInternalFunction( 11131cb0ef41Sopenharmony_ci isolate_, instance, func_index, 11141cb0ef41Sopenharmony_ci WasmInternalFunction::FromExternal( 11151cb0ef41Sopenharmony_ci Handle<WasmExternalFunction>::cast(value), isolate_) 11161cb0ef41Sopenharmony_ci .ToHandleChecked()); 11171cb0ef41Sopenharmony_ci } 11181cb0ef41Sopenharmony_ci auto js_receiver = Handle<JSReceiver>::cast(value); 11191cb0ef41Sopenharmony_ci const FunctionSig* expected_sig = module_->functions[func_index].sig; 11201cb0ef41Sopenharmony_ci auto resolved = compiler::ResolveWasmImportCall(js_receiver, expected_sig, 11211cb0ef41Sopenharmony_ci module_, enabled_); 11221cb0ef41Sopenharmony_ci compiler::WasmImportCallKind kind = resolved.kind; 11231cb0ef41Sopenharmony_ci js_receiver = resolved.callable; 11241cb0ef41Sopenharmony_ci switch (kind) { 11251cb0ef41Sopenharmony_ci case compiler::WasmImportCallKind::kLinkError: 11261cb0ef41Sopenharmony_ci ReportLinkError("imported function does not match the expected type", 11271cb0ef41Sopenharmony_ci import_index, module_name, import_name); 11281cb0ef41Sopenharmony_ci return false; 11291cb0ef41Sopenharmony_ci case compiler::WasmImportCallKind::kWasmToWasm: { 11301cb0ef41Sopenharmony_ci // The imported function is a Wasm function from another instance. 11311cb0ef41Sopenharmony_ci auto imported_function = Handle<WasmExportedFunction>::cast(js_receiver); 11321cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> imported_instance( 11331cb0ef41Sopenharmony_ci imported_function->instance(), isolate_); 11341cb0ef41Sopenharmony_ci // The import reference is the instance object itself. 11351cb0ef41Sopenharmony_ci Address imported_target = imported_function->GetWasmCallTarget(); 11361cb0ef41Sopenharmony_ci ImportedFunctionEntry entry(instance, func_index); 11371cb0ef41Sopenharmony_ci entry.SetWasmToWasm(*imported_instance, imported_target); 11381cb0ef41Sopenharmony_ci break; 11391cb0ef41Sopenharmony_ci } 11401cb0ef41Sopenharmony_ci case compiler::WasmImportCallKind::kWasmToCapi: { 11411cb0ef41Sopenharmony_ci NativeModule* native_module = instance->module_object().native_module(); 11421cb0ef41Sopenharmony_ci int expected_arity = static_cast<int>(expected_sig->parameter_count()); 11431cb0ef41Sopenharmony_ci WasmImportWrapperCache* cache = native_module->import_wrapper_cache(); 11441cb0ef41Sopenharmony_ci // TODO(jkummerow): Consider precompiling CapiCallWrappers in parallel, 11451cb0ef41Sopenharmony_ci // just like other import wrappers. 11461cb0ef41Sopenharmony_ci WasmCode* wasm_code = 11471cb0ef41Sopenharmony_ci cache->MaybeGet(kind, expected_sig, expected_arity, kNoSuspend); 11481cb0ef41Sopenharmony_ci if (wasm_code == nullptr) { 11491cb0ef41Sopenharmony_ci WasmCodeRefScope code_ref_scope; 11501cb0ef41Sopenharmony_ci WasmImportWrapperCache::ModificationScope cache_scope(cache); 11511cb0ef41Sopenharmony_ci wasm_code = 11521cb0ef41Sopenharmony_ci compiler::CompileWasmCapiCallWrapper(native_module, expected_sig); 11531cb0ef41Sopenharmony_ci WasmImportWrapperCache::CacheKey key(kind, expected_sig, expected_arity, 11541cb0ef41Sopenharmony_ci kNoSuspend); 11551cb0ef41Sopenharmony_ci cache_scope[key] = wasm_code; 11561cb0ef41Sopenharmony_ci wasm_code->IncRef(); 11571cb0ef41Sopenharmony_ci isolate_->counters()->wasm_generated_code_size()->Increment( 11581cb0ef41Sopenharmony_ci wasm_code->instructions().length()); 11591cb0ef41Sopenharmony_ci isolate_->counters()->wasm_reloc_size()->Increment( 11601cb0ef41Sopenharmony_ci wasm_code->reloc_info().length()); 11611cb0ef41Sopenharmony_ci } 11621cb0ef41Sopenharmony_ci 11631cb0ef41Sopenharmony_ci ImportedFunctionEntry entry(instance, func_index); 11641cb0ef41Sopenharmony_ci // We re-use the SetWasmToJs infrastructure because it passes the 11651cb0ef41Sopenharmony_ci // callable to the wrapper, which we need to get the function data. 11661cb0ef41Sopenharmony_ci entry.SetWasmToJs(isolate_, js_receiver, wasm_code, 11671cb0ef41Sopenharmony_ci isolate_->factory()->undefined_value()); 11681cb0ef41Sopenharmony_ci break; 11691cb0ef41Sopenharmony_ci } 11701cb0ef41Sopenharmony_ci case compiler::WasmImportCallKind::kWasmToJSFastApi: { 11711cb0ef41Sopenharmony_ci NativeModule* native_module = instance->module_object().native_module(); 11721cb0ef41Sopenharmony_ci DCHECK(js_receiver->IsJSFunction()); 11731cb0ef41Sopenharmony_ci Handle<JSFunction> function = Handle<JSFunction>::cast(js_receiver); 11741cb0ef41Sopenharmony_ci 11751cb0ef41Sopenharmony_ci WasmCodeRefScope code_ref_scope; 11761cb0ef41Sopenharmony_ci WasmCode* wasm_code = compiler::CompileWasmJSFastCallWrapper( 11771cb0ef41Sopenharmony_ci native_module, expected_sig, function); 11781cb0ef41Sopenharmony_ci ImportedFunctionEntry entry(instance, func_index); 11791cb0ef41Sopenharmony_ci entry.SetWasmToJs(isolate_, js_receiver, wasm_code, 11801cb0ef41Sopenharmony_ci isolate_->factory()->undefined_value()); 11811cb0ef41Sopenharmony_ci break; 11821cb0ef41Sopenharmony_ci } 11831cb0ef41Sopenharmony_ci default: { 11841cb0ef41Sopenharmony_ci // The imported function is a callable. 11851cb0ef41Sopenharmony_ci 11861cb0ef41Sopenharmony_ci int expected_arity = static_cast<int>(expected_sig->parameter_count()); 11871cb0ef41Sopenharmony_ci if (kind == compiler::WasmImportCallKind::kJSFunctionArityMismatch) { 11881cb0ef41Sopenharmony_ci Handle<JSFunction> function = Handle<JSFunction>::cast(js_receiver); 11891cb0ef41Sopenharmony_ci SharedFunctionInfo shared = function->shared(); 11901cb0ef41Sopenharmony_ci expected_arity = 11911cb0ef41Sopenharmony_ci shared.internal_formal_parameter_count_without_receiver(); 11921cb0ef41Sopenharmony_ci } 11931cb0ef41Sopenharmony_ci 11941cb0ef41Sopenharmony_ci NativeModule* native_module = instance->module_object().native_module(); 11951cb0ef41Sopenharmony_ci Suspend suspend = 11961cb0ef41Sopenharmony_ci resolved.suspender.is_null() || resolved.suspender->IsUndefined() 11971cb0ef41Sopenharmony_ci ? kNoSuspend 11981cb0ef41Sopenharmony_ci : kSuspend; 11991cb0ef41Sopenharmony_ci WasmCode* wasm_code = native_module->import_wrapper_cache()->Get( 12001cb0ef41Sopenharmony_ci kind, expected_sig, expected_arity, suspend); 12011cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(wasm_code); 12021cb0ef41Sopenharmony_ci ImportedFunctionEntry entry(instance, func_index); 12031cb0ef41Sopenharmony_ci if (wasm_code->kind() == WasmCode::kWasmToJsWrapper) { 12041cb0ef41Sopenharmony_ci // Wasm to JS wrappers are treated specially in the import table. 12051cb0ef41Sopenharmony_ci entry.SetWasmToJs(isolate_, js_receiver, wasm_code, resolved.suspender); 12061cb0ef41Sopenharmony_ci } else { 12071cb0ef41Sopenharmony_ci // Wasm math intrinsics are compiled as regular Wasm functions. 12081cb0ef41Sopenharmony_ci DCHECK(kind >= compiler::WasmImportCallKind::kFirstMathIntrinsic && 12091cb0ef41Sopenharmony_ci kind <= compiler::WasmImportCallKind::kLastMathIntrinsic); 12101cb0ef41Sopenharmony_ci entry.SetWasmToWasm(*instance, wasm_code->instruction_start()); 12111cb0ef41Sopenharmony_ci } 12121cb0ef41Sopenharmony_ci break; 12131cb0ef41Sopenharmony_ci } 12141cb0ef41Sopenharmony_ci } 12151cb0ef41Sopenharmony_ci return true; 12161cb0ef41Sopenharmony_ci} 12171cb0ef41Sopenharmony_ci 12181cb0ef41Sopenharmony_cibool InstanceBuilder::InitializeImportedIndirectFunctionTable( 12191cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, int table_index, int import_index, 12201cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_object) { 12211cb0ef41Sopenharmony_ci int imported_table_size = table_object->current_length(); 12221cb0ef41Sopenharmony_ci // Allocate a new dispatch table. 12231cb0ef41Sopenharmony_ci WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( 12241cb0ef41Sopenharmony_ci instance, table_index, imported_table_size); 12251cb0ef41Sopenharmony_ci // Initialize the dispatch table with the (foreign) JS functions 12261cb0ef41Sopenharmony_ci // that are already in the table. 12271cb0ef41Sopenharmony_ci for (int i = 0; i < imported_table_size; ++i) { 12281cb0ef41Sopenharmony_ci bool is_valid; 12291cb0ef41Sopenharmony_ci bool is_null; 12301cb0ef41Sopenharmony_ci MaybeHandle<WasmInstanceObject> maybe_target_instance; 12311cb0ef41Sopenharmony_ci int function_index; 12321cb0ef41Sopenharmony_ci MaybeHandle<WasmJSFunction> maybe_js_function; 12331cb0ef41Sopenharmony_ci WasmTableObject::GetFunctionTableEntry( 12341cb0ef41Sopenharmony_ci isolate_, module_, table_object, i, &is_valid, &is_null, 12351cb0ef41Sopenharmony_ci &maybe_target_instance, &function_index, &maybe_js_function); 12361cb0ef41Sopenharmony_ci if (!is_valid) { 12371cb0ef41Sopenharmony_ci thrower_->LinkError("table import %d[%d] is not a wasm function", 12381cb0ef41Sopenharmony_ci import_index, i); 12391cb0ef41Sopenharmony_ci return false; 12401cb0ef41Sopenharmony_ci } 12411cb0ef41Sopenharmony_ci if (is_null) continue; 12421cb0ef41Sopenharmony_ci Handle<WasmJSFunction> js_function; 12431cb0ef41Sopenharmony_ci if (maybe_js_function.ToHandle(&js_function)) { 12441cb0ef41Sopenharmony_ci WasmInstanceObject::ImportWasmJSFunctionIntoTable( 12451cb0ef41Sopenharmony_ci isolate_, instance, table_index, i, js_function); 12461cb0ef41Sopenharmony_ci continue; 12471cb0ef41Sopenharmony_ci } 12481cb0ef41Sopenharmony_ci 12491cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> target_instance = 12501cb0ef41Sopenharmony_ci maybe_target_instance.ToHandleChecked(); 12511cb0ef41Sopenharmony_ci const FunctionSig* sig = target_instance->module_object() 12521cb0ef41Sopenharmony_ci .module() 12531cb0ef41Sopenharmony_ci ->functions[function_index] 12541cb0ef41Sopenharmony_ci .sig; 12551cb0ef41Sopenharmony_ci 12561cb0ef41Sopenharmony_ci // Look up the signature's canonical id. If there is no canonical 12571cb0ef41Sopenharmony_ci // id, then the signature does not appear at all in this module, 12581cb0ef41Sopenharmony_ci // so putting {-1} in the table will cause checks to always fail. 12591cb0ef41Sopenharmony_ci FunctionTargetAndRef entry(target_instance, function_index); 12601cb0ef41Sopenharmony_ci instance->GetIndirectFunctionTable(isolate_, table_index) 12611cb0ef41Sopenharmony_ci ->Set(i, module_->signature_map.Find(*sig), entry.call_target(), 12621cb0ef41Sopenharmony_ci *entry.ref()); 12631cb0ef41Sopenharmony_ci } 12641cb0ef41Sopenharmony_ci return true; 12651cb0ef41Sopenharmony_ci} 12661cb0ef41Sopenharmony_ci 12671cb0ef41Sopenharmony_cibool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance, 12681cb0ef41Sopenharmony_ci int import_index, int table_index, 12691cb0ef41Sopenharmony_ci Handle<String> module_name, 12701cb0ef41Sopenharmony_ci Handle<String> import_name, 12711cb0ef41Sopenharmony_ci Handle<Object> value) { 12721cb0ef41Sopenharmony_ci if (!value->IsWasmTableObject()) { 12731cb0ef41Sopenharmony_ci ReportLinkError("table import requires a WebAssembly.Table", import_index, 12741cb0ef41Sopenharmony_ci module_name, import_name); 12751cb0ef41Sopenharmony_ci return false; 12761cb0ef41Sopenharmony_ci } 12771cb0ef41Sopenharmony_ci const WasmTable& table = module_->tables[table_index]; 12781cb0ef41Sopenharmony_ci 12791cb0ef41Sopenharmony_ci auto table_object = Handle<WasmTableObject>::cast(value); 12801cb0ef41Sopenharmony_ci 12811cb0ef41Sopenharmony_ci uint32_t imported_table_size = 12821cb0ef41Sopenharmony_ci static_cast<uint32_t>(table_object->current_length()); 12831cb0ef41Sopenharmony_ci if (imported_table_size < table.initial_size) { 12841cb0ef41Sopenharmony_ci thrower_->LinkError("table import %d is smaller than initial %u, got %u", 12851cb0ef41Sopenharmony_ci import_index, table.initial_size, imported_table_size); 12861cb0ef41Sopenharmony_ci return false; 12871cb0ef41Sopenharmony_ci } 12881cb0ef41Sopenharmony_ci 12891cb0ef41Sopenharmony_ci if (table.has_maximum_size) { 12901cb0ef41Sopenharmony_ci if (table_object->maximum_length().IsUndefined(isolate_)) { 12911cb0ef41Sopenharmony_ci thrower_->LinkError("table import %d has no maximum length, expected %u", 12921cb0ef41Sopenharmony_ci import_index, table.maximum_size); 12931cb0ef41Sopenharmony_ci return false; 12941cb0ef41Sopenharmony_ci } 12951cb0ef41Sopenharmony_ci int64_t imported_maximum_size = table_object->maximum_length().Number(); 12961cb0ef41Sopenharmony_ci if (imported_maximum_size < 0) { 12971cb0ef41Sopenharmony_ci thrower_->LinkError("table import %d has no maximum length, expected %u", 12981cb0ef41Sopenharmony_ci import_index, table.maximum_size); 12991cb0ef41Sopenharmony_ci return false; 13001cb0ef41Sopenharmony_ci } 13011cb0ef41Sopenharmony_ci if (imported_maximum_size > table.maximum_size) { 13021cb0ef41Sopenharmony_ci thrower_->LinkError("table import %d has a larger maximum size %" PRIx64 13031cb0ef41Sopenharmony_ci " than the module's declared maximum %u", 13041cb0ef41Sopenharmony_ci import_index, imported_maximum_size, 13051cb0ef41Sopenharmony_ci table.maximum_size); 13061cb0ef41Sopenharmony_ci return false; 13071cb0ef41Sopenharmony_ci } 13081cb0ef41Sopenharmony_ci } 13091cb0ef41Sopenharmony_ci 13101cb0ef41Sopenharmony_ci const WasmModule* table_type_module = 13111cb0ef41Sopenharmony_ci !table_object->instance().IsUndefined() 13121cb0ef41Sopenharmony_ci ? WasmInstanceObject::cast(table_object->instance()).module() 13131cb0ef41Sopenharmony_ci : instance->module(); 13141cb0ef41Sopenharmony_ci 13151cb0ef41Sopenharmony_ci if (!EquivalentTypes(table.type, table_object->type(), module_, 13161cb0ef41Sopenharmony_ci table_type_module)) { 13171cb0ef41Sopenharmony_ci ReportLinkError("imported table does not match the expected type", 13181cb0ef41Sopenharmony_ci import_index, module_name, import_name); 13191cb0ef41Sopenharmony_ci return false; 13201cb0ef41Sopenharmony_ci } 13211cb0ef41Sopenharmony_ci 13221cb0ef41Sopenharmony_ci if (IsSubtypeOf(table.type, kWasmFuncRef, module_) && 13231cb0ef41Sopenharmony_ci !InitializeImportedIndirectFunctionTable(instance, table_index, 13241cb0ef41Sopenharmony_ci import_index, table_object)) { 13251cb0ef41Sopenharmony_ci return false; 13261cb0ef41Sopenharmony_ci } 13271cb0ef41Sopenharmony_ci 13281cb0ef41Sopenharmony_ci instance->tables().set(table_index, *value); 13291cb0ef41Sopenharmony_ci return true; 13301cb0ef41Sopenharmony_ci} 13311cb0ef41Sopenharmony_ci 13321cb0ef41Sopenharmony_cibool InstanceBuilder::ProcessImportedMemory(Handle<WasmInstanceObject> instance, 13331cb0ef41Sopenharmony_ci int import_index, 13341cb0ef41Sopenharmony_ci Handle<String> module_name, 13351cb0ef41Sopenharmony_ci Handle<String> import_name, 13361cb0ef41Sopenharmony_ci Handle<Object> value) { 13371cb0ef41Sopenharmony_ci if (!value->IsWasmMemoryObject()) { 13381cb0ef41Sopenharmony_ci ReportLinkError("memory import must be a WebAssembly.Memory object", 13391cb0ef41Sopenharmony_ci import_index, module_name, import_name); 13401cb0ef41Sopenharmony_ci return false; 13411cb0ef41Sopenharmony_ci } 13421cb0ef41Sopenharmony_ci auto memory_object = Handle<WasmMemoryObject>::cast(value); 13431cb0ef41Sopenharmony_ci 13441cb0ef41Sopenharmony_ci // The imported memory should have been already set up early. 13451cb0ef41Sopenharmony_ci CHECK_EQ(instance->memory_object(), *memory_object); 13461cb0ef41Sopenharmony_ci 13471cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> buffer(memory_object_->array_buffer(), isolate_); 13481cb0ef41Sopenharmony_ci // memory_ should have already been assigned in Build(). 13491cb0ef41Sopenharmony_ci DCHECK_EQ(*memory_buffer_.ToHandleChecked(), *buffer); 13501cb0ef41Sopenharmony_ci uint32_t imported_cur_pages = 13511cb0ef41Sopenharmony_ci static_cast<uint32_t>(buffer->byte_length() / kWasmPageSize); 13521cb0ef41Sopenharmony_ci if (imported_cur_pages < module_->initial_pages) { 13531cb0ef41Sopenharmony_ci thrower_->LinkError("memory import %d is smaller than initial %u, got %u", 13541cb0ef41Sopenharmony_ci import_index, module_->initial_pages, 13551cb0ef41Sopenharmony_ci imported_cur_pages); 13561cb0ef41Sopenharmony_ci return false; 13571cb0ef41Sopenharmony_ci } 13581cb0ef41Sopenharmony_ci int32_t imported_maximum_pages = memory_object_->maximum_pages(); 13591cb0ef41Sopenharmony_ci if (module_->has_maximum_pages) { 13601cb0ef41Sopenharmony_ci if (imported_maximum_pages < 0) { 13611cb0ef41Sopenharmony_ci thrower_->LinkError( 13621cb0ef41Sopenharmony_ci "memory import %d has no maximum limit, expected at most %u", 13631cb0ef41Sopenharmony_ci import_index, imported_maximum_pages); 13641cb0ef41Sopenharmony_ci return false; 13651cb0ef41Sopenharmony_ci } 13661cb0ef41Sopenharmony_ci if (static_cast<uint32_t>(imported_maximum_pages) > 13671cb0ef41Sopenharmony_ci module_->maximum_pages) { 13681cb0ef41Sopenharmony_ci thrower_->LinkError( 13691cb0ef41Sopenharmony_ci "memory import %d has a larger maximum size %u than the " 13701cb0ef41Sopenharmony_ci "module's declared maximum %u", 13711cb0ef41Sopenharmony_ci import_index, imported_maximum_pages, module_->maximum_pages); 13721cb0ef41Sopenharmony_ci return false; 13731cb0ef41Sopenharmony_ci } 13741cb0ef41Sopenharmony_ci } 13751cb0ef41Sopenharmony_ci if (module_->has_shared_memory != buffer->is_shared()) { 13761cb0ef41Sopenharmony_ci thrower_->LinkError( 13771cb0ef41Sopenharmony_ci "mismatch in shared state of memory, declared = %d, imported = %d", 13781cb0ef41Sopenharmony_ci module_->has_shared_memory, buffer->is_shared()); 13791cb0ef41Sopenharmony_ci return false; 13801cb0ef41Sopenharmony_ci } 13811cb0ef41Sopenharmony_ci 13821cb0ef41Sopenharmony_ci return true; 13831cb0ef41Sopenharmony_ci} 13841cb0ef41Sopenharmony_ci 13851cb0ef41Sopenharmony_cibool InstanceBuilder::ProcessImportedWasmGlobalObject( 13861cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, int import_index, 13871cb0ef41Sopenharmony_ci Handle<String> module_name, Handle<String> import_name, 13881cb0ef41Sopenharmony_ci const WasmGlobal& global, Handle<WasmGlobalObject> global_object) { 13891cb0ef41Sopenharmony_ci if (static_cast<bool>(global_object->is_mutable()) != global.mutability) { 13901cb0ef41Sopenharmony_ci ReportLinkError("imported global does not match the expected mutability", 13911cb0ef41Sopenharmony_ci import_index, module_name, import_name); 13921cb0ef41Sopenharmony_ci return false; 13931cb0ef41Sopenharmony_ci } 13941cb0ef41Sopenharmony_ci 13951cb0ef41Sopenharmony_ci const WasmModule* global_type_module = 13961cb0ef41Sopenharmony_ci !global_object->instance().IsUndefined() 13971cb0ef41Sopenharmony_ci ? WasmInstanceObject::cast(global_object->instance()).module() 13981cb0ef41Sopenharmony_ci : instance->module(); 13991cb0ef41Sopenharmony_ci 14001cb0ef41Sopenharmony_ci bool valid_type = 14011cb0ef41Sopenharmony_ci global.mutability 14021cb0ef41Sopenharmony_ci ? EquivalentTypes(global_object->type(), global.type, 14031cb0ef41Sopenharmony_ci global_type_module, instance->module()) 14041cb0ef41Sopenharmony_ci : IsSubtypeOf(global_object->type(), global.type, global_type_module, 14051cb0ef41Sopenharmony_ci instance->module()); 14061cb0ef41Sopenharmony_ci 14071cb0ef41Sopenharmony_ci if (!valid_type) { 14081cb0ef41Sopenharmony_ci ReportLinkError("imported global does not match the expected type", 14091cb0ef41Sopenharmony_ci import_index, module_name, import_name); 14101cb0ef41Sopenharmony_ci return false; 14111cb0ef41Sopenharmony_ci } 14121cb0ef41Sopenharmony_ci if (global.mutability) { 14131cb0ef41Sopenharmony_ci DCHECK_LT(global.index, module_->num_imported_mutable_globals); 14141cb0ef41Sopenharmony_ci Handle<Object> buffer; 14151cb0ef41Sopenharmony_ci Address address_or_offset; 14161cb0ef41Sopenharmony_ci if (global.type.is_reference()) { 14171cb0ef41Sopenharmony_ci static_assert(sizeof(global_object->offset()) <= sizeof(Address), 14181cb0ef41Sopenharmony_ci "The offset into the globals buffer does not fit into " 14191cb0ef41Sopenharmony_ci "the imported_mutable_globals array"); 14201cb0ef41Sopenharmony_ci buffer = handle(global_object->tagged_buffer(), isolate_); 14211cb0ef41Sopenharmony_ci // For externref globals we use a relative offset, not an absolute 14221cb0ef41Sopenharmony_ci // address. 14231cb0ef41Sopenharmony_ci address_or_offset = static_cast<Address>(global_object->offset()); 14241cb0ef41Sopenharmony_ci } else { 14251cb0ef41Sopenharmony_ci buffer = handle(global_object->untagged_buffer(), isolate_); 14261cb0ef41Sopenharmony_ci // It is safe in this case to store the raw pointer to the buffer 14271cb0ef41Sopenharmony_ci // since the backing store of the JSArrayBuffer will not be 14281cb0ef41Sopenharmony_ci // relocated. 14291cb0ef41Sopenharmony_ci address_or_offset = reinterpret_cast<Address>(raw_buffer_ptr( 14301cb0ef41Sopenharmony_ci Handle<JSArrayBuffer>::cast(buffer), global_object->offset())); 14311cb0ef41Sopenharmony_ci } 14321cb0ef41Sopenharmony_ci instance->imported_mutable_globals_buffers().set(global.index, *buffer); 14331cb0ef41Sopenharmony_ci instance->imported_mutable_globals()[global.index] = address_or_offset; 14341cb0ef41Sopenharmony_ci return true; 14351cb0ef41Sopenharmony_ci } 14361cb0ef41Sopenharmony_ci 14371cb0ef41Sopenharmony_ci WasmValue value; 14381cb0ef41Sopenharmony_ci switch (global_object->type().kind()) { 14391cb0ef41Sopenharmony_ci case kI32: 14401cb0ef41Sopenharmony_ci value = WasmValue(global_object->GetI32()); 14411cb0ef41Sopenharmony_ci break; 14421cb0ef41Sopenharmony_ci case kI64: 14431cb0ef41Sopenharmony_ci value = WasmValue(global_object->GetI64()); 14441cb0ef41Sopenharmony_ci break; 14451cb0ef41Sopenharmony_ci case kF32: 14461cb0ef41Sopenharmony_ci value = WasmValue(global_object->GetF32()); 14471cb0ef41Sopenharmony_ci break; 14481cb0ef41Sopenharmony_ci case kF64: 14491cb0ef41Sopenharmony_ci value = WasmValue(global_object->GetF64()); 14501cb0ef41Sopenharmony_ci break; 14511cb0ef41Sopenharmony_ci case kRtt: 14521cb0ef41Sopenharmony_ci case kRef: 14531cb0ef41Sopenharmony_ci case kOptRef: 14541cb0ef41Sopenharmony_ci value = WasmValue(global_object->GetRef(), global_object->type()); 14551cb0ef41Sopenharmony_ci break; 14561cb0ef41Sopenharmony_ci case kVoid: 14571cb0ef41Sopenharmony_ci case kS128: 14581cb0ef41Sopenharmony_ci case kBottom: 14591cb0ef41Sopenharmony_ci case kI8: 14601cb0ef41Sopenharmony_ci case kI16: 14611cb0ef41Sopenharmony_ci UNREACHABLE(); 14621cb0ef41Sopenharmony_ci } 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_ci WriteGlobalValue(global, value); 14651cb0ef41Sopenharmony_ci return true; 14661cb0ef41Sopenharmony_ci} 14671cb0ef41Sopenharmony_ci 14681cb0ef41Sopenharmony_cibool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance, 14691cb0ef41Sopenharmony_ci int import_index, int global_index, 14701cb0ef41Sopenharmony_ci Handle<String> module_name, 14711cb0ef41Sopenharmony_ci Handle<String> import_name, 14721cb0ef41Sopenharmony_ci Handle<Object> value) { 14731cb0ef41Sopenharmony_ci // Immutable global imports are converted to numbers and written into 14741cb0ef41Sopenharmony_ci // the {untagged_globals_} array buffer. 14751cb0ef41Sopenharmony_ci // 14761cb0ef41Sopenharmony_ci // Mutable global imports instead have their backing array buffers 14771cb0ef41Sopenharmony_ci // referenced by this instance, and store the address of the imported 14781cb0ef41Sopenharmony_ci // global in the {imported_mutable_globals_} array. 14791cb0ef41Sopenharmony_ci const WasmGlobal& global = module_->globals[global_index]; 14801cb0ef41Sopenharmony_ci 14811cb0ef41Sopenharmony_ci // SIMD proposal allows modules to define an imported v128 global, and only 14821cb0ef41Sopenharmony_ci // supports importing a WebAssembly.Global object for this global, but also 14831cb0ef41Sopenharmony_ci // defines constructing a WebAssembly.Global of v128 to be a TypeError. 14841cb0ef41Sopenharmony_ci // We *should* never hit this case in the JS API, but the module should should 14851cb0ef41Sopenharmony_ci // be allowed to declare such a global (no validation error). 14861cb0ef41Sopenharmony_ci if (global.type == kWasmS128 && !value->IsWasmGlobalObject()) { 14871cb0ef41Sopenharmony_ci ReportLinkError("global import of type v128 must be a WebAssembly.Global", 14881cb0ef41Sopenharmony_ci import_index, module_name, import_name); 14891cb0ef41Sopenharmony_ci return false; 14901cb0ef41Sopenharmony_ci } 14911cb0ef41Sopenharmony_ci 14921cb0ef41Sopenharmony_ci if (is_asmjs_module(module_)) { 14931cb0ef41Sopenharmony_ci // Accepting {JSFunction} on top of just primitive values here is a 14941cb0ef41Sopenharmony_ci // workaround to support legacy asm.js code with broken binding. Note 14951cb0ef41Sopenharmony_ci // that using {NaN} (or Smi::zero()) here is what using the observable 14961cb0ef41Sopenharmony_ci // conversion via {ToPrimitive} would produce as well. {LookupImportAsm} 14971cb0ef41Sopenharmony_ci // checked via {HasDefaultToNumberBehaviour} that "valueOf" or friends have 14981cb0ef41Sopenharmony_ci // not been patched. 14991cb0ef41Sopenharmony_ci if (value->IsJSFunction()) value = isolate_->factory()->nan_value(); 15001cb0ef41Sopenharmony_ci if (value->IsPrimitive()) { 15011cb0ef41Sopenharmony_ci MaybeHandle<Object> converted = global.type == kWasmI32 15021cb0ef41Sopenharmony_ci ? Object::ToInt32(isolate_, value) 15031cb0ef41Sopenharmony_ci : Object::ToNumber(isolate_, value); 15041cb0ef41Sopenharmony_ci if (!converted.ToHandle(&value)) { 15051cb0ef41Sopenharmony_ci // Conversion is known to fail for Symbols and BigInts. 15061cb0ef41Sopenharmony_ci ReportLinkError("global import must be a number", import_index, 15071cb0ef41Sopenharmony_ci module_name, import_name); 15081cb0ef41Sopenharmony_ci return false; 15091cb0ef41Sopenharmony_ci } 15101cb0ef41Sopenharmony_ci } 15111cb0ef41Sopenharmony_ci } 15121cb0ef41Sopenharmony_ci 15131cb0ef41Sopenharmony_ci if (value->IsWasmGlobalObject()) { 15141cb0ef41Sopenharmony_ci auto global_object = Handle<WasmGlobalObject>::cast(value); 15151cb0ef41Sopenharmony_ci return ProcessImportedWasmGlobalObject(instance, import_index, module_name, 15161cb0ef41Sopenharmony_ci import_name, global, global_object); 15171cb0ef41Sopenharmony_ci } 15181cb0ef41Sopenharmony_ci 15191cb0ef41Sopenharmony_ci if (global.mutability) { 15201cb0ef41Sopenharmony_ci ReportLinkError( 15211cb0ef41Sopenharmony_ci "imported mutable global must be a WebAssembly.Global object", 15221cb0ef41Sopenharmony_ci import_index, module_name, import_name); 15231cb0ef41Sopenharmony_ci return false; 15241cb0ef41Sopenharmony_ci } 15251cb0ef41Sopenharmony_ci 15261cb0ef41Sopenharmony_ci if (global.type.is_reference()) { 15271cb0ef41Sopenharmony_ci const char* error_message; 15281cb0ef41Sopenharmony_ci if (!wasm::TypecheckJSObject(isolate_, module_, value, global.type, 15291cb0ef41Sopenharmony_ci &error_message)) { 15301cb0ef41Sopenharmony_ci ReportLinkError(error_message, global_index, module_name, import_name); 15311cb0ef41Sopenharmony_ci return false; 15321cb0ef41Sopenharmony_ci } 15331cb0ef41Sopenharmony_ci if (IsSubtypeOf(global.type, kWasmFuncRef, module_) && !value->IsNull()) { 15341cb0ef41Sopenharmony_ci value = 15351cb0ef41Sopenharmony_ci WasmInternalFunction::FromExternal(value, isolate_).ToHandleChecked(); 15361cb0ef41Sopenharmony_ci } 15371cb0ef41Sopenharmony_ci WriteGlobalValue(global, WasmValue(value, global.type)); 15381cb0ef41Sopenharmony_ci return true; 15391cb0ef41Sopenharmony_ci } 15401cb0ef41Sopenharmony_ci 15411cb0ef41Sopenharmony_ci if (value->IsNumber() && global.type != kWasmI64) { 15421cb0ef41Sopenharmony_ci double number_value = value->Number(); 15431cb0ef41Sopenharmony_ci // The Wasm-BigInt proposal currently says that i64 globals may 15441cb0ef41Sopenharmony_ci // only be initialized with BigInts. See: 15451cb0ef41Sopenharmony_ci // https://github.com/WebAssembly/JS-BigInt-integration/issues/12 15461cb0ef41Sopenharmony_ci WasmValue wasm_value = global.type == kWasmI32 15471cb0ef41Sopenharmony_ci ? WasmValue(DoubleToInt32(number_value)) 15481cb0ef41Sopenharmony_ci : global.type == kWasmF32 15491cb0ef41Sopenharmony_ci ? WasmValue(DoubleToFloat32(number_value)) 15501cb0ef41Sopenharmony_ci : WasmValue(number_value); 15511cb0ef41Sopenharmony_ci WriteGlobalValue(global, wasm_value); 15521cb0ef41Sopenharmony_ci return true; 15531cb0ef41Sopenharmony_ci } 15541cb0ef41Sopenharmony_ci 15551cb0ef41Sopenharmony_ci if (global.type == kWasmI64 && value->IsBigInt()) { 15561cb0ef41Sopenharmony_ci WriteGlobalValue(global, WasmValue(BigInt::cast(*value).AsInt64())); 15571cb0ef41Sopenharmony_ci return true; 15581cb0ef41Sopenharmony_ci } 15591cb0ef41Sopenharmony_ci 15601cb0ef41Sopenharmony_ci ReportLinkError( 15611cb0ef41Sopenharmony_ci "global import must be a number, valid Wasm reference, or " 15621cb0ef41Sopenharmony_ci "WebAssembly.Global object", 15631cb0ef41Sopenharmony_ci import_index, module_name, import_name); 15641cb0ef41Sopenharmony_ci return false; 15651cb0ef41Sopenharmony_ci} 15661cb0ef41Sopenharmony_ci 15671cb0ef41Sopenharmony_civoid InstanceBuilder::CompileImportWrappers( 15681cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance) { 15691cb0ef41Sopenharmony_ci int num_imports = static_cast<int>(module_->import_table.size()); 15701cb0ef41Sopenharmony_ci TRACE_EVENT1("v8.wasm", "wasm.CompileImportWrappers", "num_imports", 15711cb0ef41Sopenharmony_ci num_imports); 15721cb0ef41Sopenharmony_ci NativeModule* native_module = instance->module_object().native_module(); 15731cb0ef41Sopenharmony_ci WasmImportWrapperCache::ModificationScope cache_scope( 15741cb0ef41Sopenharmony_ci native_module->import_wrapper_cache()); 15751cb0ef41Sopenharmony_ci 15761cb0ef41Sopenharmony_ci // Compilation is done in two steps: 15771cb0ef41Sopenharmony_ci // 1) Insert nullptr entries in the cache for wrappers that need to be 15781cb0ef41Sopenharmony_ci // compiled. 2) Compile wrappers in background tasks using the 15791cb0ef41Sopenharmony_ci // ImportWrapperQueue. This way the cache won't invalidate other iterators 15801cb0ef41Sopenharmony_ci // when inserting a new WasmCode, since the key will already be there. 15811cb0ef41Sopenharmony_ci ImportWrapperQueue import_wrapper_queue; 15821cb0ef41Sopenharmony_ci for (int index = 0; index < num_imports; ++index) { 15831cb0ef41Sopenharmony_ci Handle<Object> value = sanitized_imports_[index].value; 15841cb0ef41Sopenharmony_ci if (module_->import_table[index].kind != kExternalFunction || 15851cb0ef41Sopenharmony_ci !value->IsCallable()) { 15861cb0ef41Sopenharmony_ci continue; 15871cb0ef41Sopenharmony_ci } 15881cb0ef41Sopenharmony_ci auto js_receiver = Handle<JSReceiver>::cast(value); 15891cb0ef41Sopenharmony_ci uint32_t func_index = module_->import_table[index].index; 15901cb0ef41Sopenharmony_ci const FunctionSig* sig = module_->functions[func_index].sig; 15911cb0ef41Sopenharmony_ci auto resolved = 15921cb0ef41Sopenharmony_ci compiler::ResolveWasmImportCall(js_receiver, sig, module_, enabled_); 15931cb0ef41Sopenharmony_ci compiler::WasmImportCallKind kind = resolved.kind; 15941cb0ef41Sopenharmony_ci if (kind == compiler::WasmImportCallKind::kWasmToWasm || 15951cb0ef41Sopenharmony_ci kind == compiler::WasmImportCallKind::kLinkError || 15961cb0ef41Sopenharmony_ci kind == compiler::WasmImportCallKind::kWasmToCapi || 15971cb0ef41Sopenharmony_ci kind == compiler::WasmImportCallKind::kWasmToJSFastApi) { 15981cb0ef41Sopenharmony_ci continue; 15991cb0ef41Sopenharmony_ci } 16001cb0ef41Sopenharmony_ci 16011cb0ef41Sopenharmony_ci int expected_arity = static_cast<int>(sig->parameter_count()); 16021cb0ef41Sopenharmony_ci if (resolved.kind == 16031cb0ef41Sopenharmony_ci compiler::WasmImportCallKind::kJSFunctionArityMismatch) { 16041cb0ef41Sopenharmony_ci Handle<JSFunction> function = Handle<JSFunction>::cast(resolved.callable); 16051cb0ef41Sopenharmony_ci SharedFunctionInfo shared = function->shared(); 16061cb0ef41Sopenharmony_ci expected_arity = 16071cb0ef41Sopenharmony_ci shared.internal_formal_parameter_count_without_receiver(); 16081cb0ef41Sopenharmony_ci } 16091cb0ef41Sopenharmony_ci 16101cb0ef41Sopenharmony_ci Suspend suspend = 16111cb0ef41Sopenharmony_ci resolved.suspender.is_null() || resolved.suspender->IsUndefined() 16121cb0ef41Sopenharmony_ci ? kNoSuspend 16131cb0ef41Sopenharmony_ci : kSuspend; 16141cb0ef41Sopenharmony_ci WasmImportWrapperCache::CacheKey key(kind, sig, expected_arity, suspend); 16151cb0ef41Sopenharmony_ci if (cache_scope[key] != nullptr) { 16161cb0ef41Sopenharmony_ci // Cache entry already exists, no need to compile it again. 16171cb0ef41Sopenharmony_ci continue; 16181cb0ef41Sopenharmony_ci } 16191cb0ef41Sopenharmony_ci import_wrapper_queue.insert(key); 16201cb0ef41Sopenharmony_ci } 16211cb0ef41Sopenharmony_ci 16221cb0ef41Sopenharmony_ci auto compile_job_task = std::make_unique<CompileImportWrapperJob>( 16231cb0ef41Sopenharmony_ci isolate_->counters(), native_module, &import_wrapper_queue, &cache_scope); 16241cb0ef41Sopenharmony_ci auto compile_job = V8::GetCurrentPlatform()->PostJob( 16251cb0ef41Sopenharmony_ci TaskPriority::kUserVisible, std::move(compile_job_task)); 16261cb0ef41Sopenharmony_ci 16271cb0ef41Sopenharmony_ci // Wait for the job to finish, while contributing in this thread. 16281cb0ef41Sopenharmony_ci compile_job->Join(); 16291cb0ef41Sopenharmony_ci} 16301cb0ef41Sopenharmony_ci 16311cb0ef41Sopenharmony_ci// Process the imports, including functions, tables, globals, and memory, in 16321cb0ef41Sopenharmony_ci// order, loading them from the {ffi_} object. Returns the number of imported 16331cb0ef41Sopenharmony_ci// functions. 16341cb0ef41Sopenharmony_ciint InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) { 16351cb0ef41Sopenharmony_ci int num_imported_functions = 0; 16361cb0ef41Sopenharmony_ci int num_imported_tables = 0; 16371cb0ef41Sopenharmony_ci 16381cb0ef41Sopenharmony_ci DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size()); 16391cb0ef41Sopenharmony_ci 16401cb0ef41Sopenharmony_ci CompileImportWrappers(instance); 16411cb0ef41Sopenharmony_ci int num_imports = static_cast<int>(module_->import_table.size()); 16421cb0ef41Sopenharmony_ci for (int index = 0; index < num_imports; ++index) { 16431cb0ef41Sopenharmony_ci const WasmImport& import = module_->import_table[index]; 16441cb0ef41Sopenharmony_ci 16451cb0ef41Sopenharmony_ci Handle<String> module_name = sanitized_imports_[index].module_name; 16461cb0ef41Sopenharmony_ci Handle<String> import_name = sanitized_imports_[index].import_name; 16471cb0ef41Sopenharmony_ci Handle<Object> value = sanitized_imports_[index].value; 16481cb0ef41Sopenharmony_ci 16491cb0ef41Sopenharmony_ci switch (import.kind) { 16501cb0ef41Sopenharmony_ci case kExternalFunction: { 16511cb0ef41Sopenharmony_ci uint32_t func_index = import.index; 16521cb0ef41Sopenharmony_ci DCHECK_EQ(num_imported_functions, func_index); 16531cb0ef41Sopenharmony_ci if (!ProcessImportedFunction(instance, index, func_index, module_name, 16541cb0ef41Sopenharmony_ci import_name, value)) { 16551cb0ef41Sopenharmony_ci return -1; 16561cb0ef41Sopenharmony_ci } 16571cb0ef41Sopenharmony_ci num_imported_functions++; 16581cb0ef41Sopenharmony_ci break; 16591cb0ef41Sopenharmony_ci } 16601cb0ef41Sopenharmony_ci case kExternalTable: { 16611cb0ef41Sopenharmony_ci uint32_t table_index = import.index; 16621cb0ef41Sopenharmony_ci DCHECK_EQ(table_index, num_imported_tables); 16631cb0ef41Sopenharmony_ci if (!ProcessImportedTable(instance, index, table_index, module_name, 16641cb0ef41Sopenharmony_ci import_name, value)) { 16651cb0ef41Sopenharmony_ci return -1; 16661cb0ef41Sopenharmony_ci } 16671cb0ef41Sopenharmony_ci num_imported_tables++; 16681cb0ef41Sopenharmony_ci USE(num_imported_tables); 16691cb0ef41Sopenharmony_ci break; 16701cb0ef41Sopenharmony_ci } 16711cb0ef41Sopenharmony_ci case kExternalMemory: { 16721cb0ef41Sopenharmony_ci if (!ProcessImportedMemory(instance, index, module_name, import_name, 16731cb0ef41Sopenharmony_ci value)) { 16741cb0ef41Sopenharmony_ci return -1; 16751cb0ef41Sopenharmony_ci } 16761cb0ef41Sopenharmony_ci break; 16771cb0ef41Sopenharmony_ci } 16781cb0ef41Sopenharmony_ci case kExternalGlobal: { 16791cb0ef41Sopenharmony_ci if (!ProcessImportedGlobal(instance, index, import.index, module_name, 16801cb0ef41Sopenharmony_ci import_name, value)) { 16811cb0ef41Sopenharmony_ci return -1; 16821cb0ef41Sopenharmony_ci } 16831cb0ef41Sopenharmony_ci break; 16841cb0ef41Sopenharmony_ci } 16851cb0ef41Sopenharmony_ci case kExternalTag: { 16861cb0ef41Sopenharmony_ci if (!value->IsWasmTagObject()) { 16871cb0ef41Sopenharmony_ci ReportLinkError("tag import requires a WebAssembly.Tag", index, 16881cb0ef41Sopenharmony_ci module_name, import_name); 16891cb0ef41Sopenharmony_ci return -1; 16901cb0ef41Sopenharmony_ci } 16911cb0ef41Sopenharmony_ci Handle<WasmTagObject> imported_tag = Handle<WasmTagObject>::cast(value); 16921cb0ef41Sopenharmony_ci if (!imported_tag->MatchesSignature(module_->tags[import.index].sig)) { 16931cb0ef41Sopenharmony_ci ReportLinkError("imported tag does not match the expected type", 16941cb0ef41Sopenharmony_ci index, module_name, import_name); 16951cb0ef41Sopenharmony_ci return -1; 16961cb0ef41Sopenharmony_ci } 16971cb0ef41Sopenharmony_ci Object tag = imported_tag->tag(); 16981cb0ef41Sopenharmony_ci DCHECK(instance->tags_table().get(import.index).IsUndefined()); 16991cb0ef41Sopenharmony_ci instance->tags_table().set(import.index, tag); 17001cb0ef41Sopenharmony_ci tags_wrappers_[import.index] = imported_tag; 17011cb0ef41Sopenharmony_ci break; 17021cb0ef41Sopenharmony_ci } 17031cb0ef41Sopenharmony_ci default: 17041cb0ef41Sopenharmony_ci UNREACHABLE(); 17051cb0ef41Sopenharmony_ci } 17061cb0ef41Sopenharmony_ci } 17071cb0ef41Sopenharmony_ci return num_imported_functions; 17081cb0ef41Sopenharmony_ci} 17091cb0ef41Sopenharmony_ci 17101cb0ef41Sopenharmony_citemplate <typename T> 17111cb0ef41Sopenharmony_ciT* InstanceBuilder::GetRawUntaggedGlobalPtr(const WasmGlobal& global) { 17121cb0ef41Sopenharmony_ci return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset)); 17131cb0ef41Sopenharmony_ci} 17141cb0ef41Sopenharmony_ci 17151cb0ef41Sopenharmony_ci// Process initialization of globals. 17161cb0ef41Sopenharmony_civoid InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { 17171cb0ef41Sopenharmony_ci for (const WasmGlobal& global : module_->globals) { 17181cb0ef41Sopenharmony_ci if (global.mutability && global.imported) continue; 17191cb0ef41Sopenharmony_ci // Happens with imported globals. 17201cb0ef41Sopenharmony_ci if (!global.init.is_set()) continue; 17211cb0ef41Sopenharmony_ci 17221cb0ef41Sopenharmony_ci WasmValue value = 17231cb0ef41Sopenharmony_ci EvaluateInitExpression(&init_expr_zone_, global.init, global.type, 17241cb0ef41Sopenharmony_ci isolate_, instance, thrower_); 17251cb0ef41Sopenharmony_ci if (thrower_->error()) return; 17261cb0ef41Sopenharmony_ci 17271cb0ef41Sopenharmony_ci if (global.type.is_reference()) { 17281cb0ef41Sopenharmony_ci tagged_globals_->set(global.offset, *value.to_ref()); 17291cb0ef41Sopenharmony_ci } else { 17301cb0ef41Sopenharmony_ci value.CopyTo(GetRawUntaggedGlobalPtr<byte>(global)); 17311cb0ef41Sopenharmony_ci } 17321cb0ef41Sopenharmony_ci } 17331cb0ef41Sopenharmony_ci} 17341cb0ef41Sopenharmony_ci 17351cb0ef41Sopenharmony_ci// Allocate memory for a module instance as a new JSArrayBuffer. 17361cb0ef41Sopenharmony_cibool InstanceBuilder::AllocateMemory() { 17371cb0ef41Sopenharmony_ci int initial_pages = static_cast<int>(module_->initial_pages); 17381cb0ef41Sopenharmony_ci int maximum_pages = module_->has_maximum_pages 17391cb0ef41Sopenharmony_ci ? static_cast<int>(module_->maximum_pages) 17401cb0ef41Sopenharmony_ci : WasmMemoryObject::kNoMaximum; 17411cb0ef41Sopenharmony_ci auto shared = (module_->has_shared_memory && enabled_.has_threads()) 17421cb0ef41Sopenharmony_ci ? SharedFlag::kShared 17431cb0ef41Sopenharmony_ci : SharedFlag::kNotShared; 17441cb0ef41Sopenharmony_ci 17451cb0ef41Sopenharmony_ci if (!WasmMemoryObject::New(isolate_, initial_pages, maximum_pages, shared) 17461cb0ef41Sopenharmony_ci .ToHandle(&memory_object_)) { 17471cb0ef41Sopenharmony_ci thrower_->RangeError("Out of memory: wasm memory"); 17481cb0ef41Sopenharmony_ci return false; 17491cb0ef41Sopenharmony_ci } 17501cb0ef41Sopenharmony_ci memory_buffer_ = 17511cb0ef41Sopenharmony_ci Handle<JSArrayBuffer>(memory_object_->array_buffer(), isolate_); 17521cb0ef41Sopenharmony_ci return true; 17531cb0ef41Sopenharmony_ci} 17541cb0ef41Sopenharmony_ci 17551cb0ef41Sopenharmony_ci// Process the exports, creating wrappers for functions, tables, memories, 17561cb0ef41Sopenharmony_ci// globals, and exceptions. 17571cb0ef41Sopenharmony_civoid InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) { 17581cb0ef41Sopenharmony_ci std::unordered_map<int, Handle<Object>> imported_globals; 17591cb0ef41Sopenharmony_ci 17601cb0ef41Sopenharmony_ci // If an imported WebAssembly function or global gets exported, the export 17611cb0ef41Sopenharmony_ci // has to be identical to to import. Therefore we cache all imported 17621cb0ef41Sopenharmony_ci // WebAssembly functions in the instance, and all imported globals in a map 17631cb0ef41Sopenharmony_ci // here. 17641cb0ef41Sopenharmony_ci for (int index = 0, end = static_cast<int>(module_->import_table.size()); 17651cb0ef41Sopenharmony_ci index < end; ++index) { 17661cb0ef41Sopenharmony_ci const WasmImport& import = module_->import_table[index]; 17671cb0ef41Sopenharmony_ci if (import.kind == kExternalFunction) { 17681cb0ef41Sopenharmony_ci Handle<Object> value = sanitized_imports_[index].value; 17691cb0ef41Sopenharmony_ci if (WasmExternalFunction::IsWasmExternalFunction(*value)) { 17701cb0ef41Sopenharmony_ci WasmInstanceObject::SetWasmInternalFunction( 17711cb0ef41Sopenharmony_ci isolate_, instance, import.index, 17721cb0ef41Sopenharmony_ci WasmInternalFunction::FromExternal( 17731cb0ef41Sopenharmony_ci Handle<WasmExternalFunction>::cast(value), isolate_) 17741cb0ef41Sopenharmony_ci .ToHandleChecked()); 17751cb0ef41Sopenharmony_ci } 17761cb0ef41Sopenharmony_ci } else if (import.kind == kExternalGlobal) { 17771cb0ef41Sopenharmony_ci Handle<Object> value = sanitized_imports_[index].value; 17781cb0ef41Sopenharmony_ci if (value->IsWasmGlobalObject()) { 17791cb0ef41Sopenharmony_ci imported_globals[import.index] = value; 17801cb0ef41Sopenharmony_ci } 17811cb0ef41Sopenharmony_ci } 17821cb0ef41Sopenharmony_ci } 17831cb0ef41Sopenharmony_ci 17841cb0ef41Sopenharmony_ci Handle<JSObject> exports_object; 17851cb0ef41Sopenharmony_ci MaybeHandle<String> single_function_name; 17861cb0ef41Sopenharmony_ci bool is_asm_js = is_asmjs_module(module_); 17871cb0ef41Sopenharmony_ci if (is_asm_js) { 17881cb0ef41Sopenharmony_ci Handle<JSFunction> object_function = Handle<JSFunction>( 17891cb0ef41Sopenharmony_ci isolate_->native_context()->object_function(), isolate_); 17901cb0ef41Sopenharmony_ci exports_object = isolate_->factory()->NewJSObject(object_function); 17911cb0ef41Sopenharmony_ci single_function_name = 17921cb0ef41Sopenharmony_ci isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName); 17931cb0ef41Sopenharmony_ci } else { 17941cb0ef41Sopenharmony_ci exports_object = isolate_->factory()->NewJSObjectWithNullProto(); 17951cb0ef41Sopenharmony_ci } 17961cb0ef41Sopenharmony_ci instance->set_exports_object(*exports_object); 17971cb0ef41Sopenharmony_ci 17981cb0ef41Sopenharmony_ci PropertyDescriptor desc; 17991cb0ef41Sopenharmony_ci desc.set_writable(is_asm_js); 18001cb0ef41Sopenharmony_ci desc.set_enumerable(true); 18011cb0ef41Sopenharmony_ci desc.set_configurable(is_asm_js); 18021cb0ef41Sopenharmony_ci 18031cb0ef41Sopenharmony_ci // Process each export in the export table. 18041cb0ef41Sopenharmony_ci for (const WasmExport& exp : module_->export_table) { 18051cb0ef41Sopenharmony_ci Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes( 18061cb0ef41Sopenharmony_ci isolate_, module_object_, exp.name, kInternalize); 18071cb0ef41Sopenharmony_ci Handle<JSObject> export_to = exports_object; 18081cb0ef41Sopenharmony_ci switch (exp.kind) { 18091cb0ef41Sopenharmony_ci case kExternalFunction: { 18101cb0ef41Sopenharmony_ci // Wrap and export the code as a JSFunction. 18111cb0ef41Sopenharmony_ci // TODO(wasm): reduce duplication with LoadElemSegment() further below 18121cb0ef41Sopenharmony_ci Handle<WasmInternalFunction> internal = 18131cb0ef41Sopenharmony_ci WasmInstanceObject::GetOrCreateWasmInternalFunction( 18141cb0ef41Sopenharmony_ci isolate_, instance, exp.index); 18151cb0ef41Sopenharmony_ci Handle<WasmExternalFunction> wasm_external_function = 18161cb0ef41Sopenharmony_ci handle(WasmExternalFunction::cast(internal->external()), isolate_); 18171cb0ef41Sopenharmony_ci desc.set_value(wasm_external_function); 18181cb0ef41Sopenharmony_ci 18191cb0ef41Sopenharmony_ci if (is_asm_js && 18201cb0ef41Sopenharmony_ci String::Equals(isolate_, name, 18211cb0ef41Sopenharmony_ci single_function_name.ToHandleChecked())) { 18221cb0ef41Sopenharmony_ci export_to = instance; 18231cb0ef41Sopenharmony_ci } 18241cb0ef41Sopenharmony_ci break; 18251cb0ef41Sopenharmony_ci } 18261cb0ef41Sopenharmony_ci case kExternalTable: { 18271cb0ef41Sopenharmony_ci desc.set_value(handle(instance->tables().get(exp.index), isolate_)); 18281cb0ef41Sopenharmony_ci break; 18291cb0ef41Sopenharmony_ci } 18301cb0ef41Sopenharmony_ci case kExternalMemory: { 18311cb0ef41Sopenharmony_ci // Export the memory as a WebAssembly.Memory object. A WasmMemoryObject 18321cb0ef41Sopenharmony_ci // should already be available if the module has memory, since we always 18331cb0ef41Sopenharmony_ci // create or import it when building an WasmInstanceObject. 18341cb0ef41Sopenharmony_ci DCHECK(instance->has_memory_object()); 18351cb0ef41Sopenharmony_ci desc.set_value( 18361cb0ef41Sopenharmony_ci Handle<WasmMemoryObject>(instance->memory_object(), isolate_)); 18371cb0ef41Sopenharmony_ci break; 18381cb0ef41Sopenharmony_ci } 18391cb0ef41Sopenharmony_ci case kExternalGlobal: { 18401cb0ef41Sopenharmony_ci const WasmGlobal& global = module_->globals[exp.index]; 18411cb0ef41Sopenharmony_ci if (global.imported) { 18421cb0ef41Sopenharmony_ci auto cached_global = imported_globals.find(exp.index); 18431cb0ef41Sopenharmony_ci if (cached_global != imported_globals.end()) { 18441cb0ef41Sopenharmony_ci desc.set_value(cached_global->second); 18451cb0ef41Sopenharmony_ci break; 18461cb0ef41Sopenharmony_ci } 18471cb0ef41Sopenharmony_ci } 18481cb0ef41Sopenharmony_ci Handle<JSArrayBuffer> untagged_buffer; 18491cb0ef41Sopenharmony_ci Handle<FixedArray> tagged_buffer; 18501cb0ef41Sopenharmony_ci uint32_t offset; 18511cb0ef41Sopenharmony_ci 18521cb0ef41Sopenharmony_ci if (global.mutability && global.imported) { 18531cb0ef41Sopenharmony_ci Handle<FixedArray> buffers_array( 18541cb0ef41Sopenharmony_ci instance->imported_mutable_globals_buffers(), isolate_); 18551cb0ef41Sopenharmony_ci if (global.type.is_reference()) { 18561cb0ef41Sopenharmony_ci tagged_buffer = handle( 18571cb0ef41Sopenharmony_ci FixedArray::cast(buffers_array->get(global.index)), isolate_); 18581cb0ef41Sopenharmony_ci // For externref globals we store the relative offset in the 18591cb0ef41Sopenharmony_ci // imported_mutable_globals array instead of an absolute address. 18601cb0ef41Sopenharmony_ci Address addr = instance->imported_mutable_globals()[global.index]; 18611cb0ef41Sopenharmony_ci DCHECK_LE(addr, static_cast<Address>( 18621cb0ef41Sopenharmony_ci std::numeric_limits<uint32_t>::max())); 18631cb0ef41Sopenharmony_ci offset = static_cast<uint32_t>(addr); 18641cb0ef41Sopenharmony_ci } else { 18651cb0ef41Sopenharmony_ci untagged_buffer = 18661cb0ef41Sopenharmony_ci handle(JSArrayBuffer::cast(buffers_array->get(global.index)), 18671cb0ef41Sopenharmony_ci isolate_); 18681cb0ef41Sopenharmony_ci Address global_addr = 18691cb0ef41Sopenharmony_ci instance->imported_mutable_globals()[global.index]; 18701cb0ef41Sopenharmony_ci 18711cb0ef41Sopenharmony_ci size_t buffer_size = untagged_buffer->byte_length(); 18721cb0ef41Sopenharmony_ci Address backing_store = 18731cb0ef41Sopenharmony_ci reinterpret_cast<Address>(untagged_buffer->backing_store()); 18741cb0ef41Sopenharmony_ci CHECK(global_addr >= backing_store && 18751cb0ef41Sopenharmony_ci global_addr < backing_store + buffer_size); 18761cb0ef41Sopenharmony_ci offset = static_cast<uint32_t>(global_addr - backing_store); 18771cb0ef41Sopenharmony_ci } 18781cb0ef41Sopenharmony_ci } else { 18791cb0ef41Sopenharmony_ci if (global.type.is_reference()) { 18801cb0ef41Sopenharmony_ci tagged_buffer = handle(instance->tagged_globals_buffer(), isolate_); 18811cb0ef41Sopenharmony_ci } else { 18821cb0ef41Sopenharmony_ci untagged_buffer = 18831cb0ef41Sopenharmony_ci handle(instance->untagged_globals_buffer(), isolate_); 18841cb0ef41Sopenharmony_ci } 18851cb0ef41Sopenharmony_ci offset = global.offset; 18861cb0ef41Sopenharmony_ci } 18871cb0ef41Sopenharmony_ci 18881cb0ef41Sopenharmony_ci // Since the global's array untagged_buffer is always provided, 18891cb0ef41Sopenharmony_ci // allocation should never fail. 18901cb0ef41Sopenharmony_ci Handle<WasmGlobalObject> global_obj = 18911cb0ef41Sopenharmony_ci WasmGlobalObject::New(isolate_, instance, untagged_buffer, 18921cb0ef41Sopenharmony_ci tagged_buffer, global.type, offset, 18931cb0ef41Sopenharmony_ci global.mutability) 18941cb0ef41Sopenharmony_ci .ToHandleChecked(); 18951cb0ef41Sopenharmony_ci desc.set_value(global_obj); 18961cb0ef41Sopenharmony_ci break; 18971cb0ef41Sopenharmony_ci } 18981cb0ef41Sopenharmony_ci case kExternalTag: { 18991cb0ef41Sopenharmony_ci const WasmTag& tag = module_->tags[exp.index]; 19001cb0ef41Sopenharmony_ci Handle<WasmTagObject> wrapper = tags_wrappers_[exp.index]; 19011cb0ef41Sopenharmony_ci if (wrapper.is_null()) { 19021cb0ef41Sopenharmony_ci Handle<HeapObject> tag_object( 19031cb0ef41Sopenharmony_ci HeapObject::cast(instance->tags_table().get(exp.index)), 19041cb0ef41Sopenharmony_ci isolate_); 19051cb0ef41Sopenharmony_ci wrapper = WasmTagObject::New(isolate_, tag.sig, tag_object); 19061cb0ef41Sopenharmony_ci tags_wrappers_[exp.index] = wrapper; 19071cb0ef41Sopenharmony_ci } 19081cb0ef41Sopenharmony_ci desc.set_value(wrapper); 19091cb0ef41Sopenharmony_ci break; 19101cb0ef41Sopenharmony_ci } 19111cb0ef41Sopenharmony_ci default: 19121cb0ef41Sopenharmony_ci UNREACHABLE(); 19131cb0ef41Sopenharmony_ci } 19141cb0ef41Sopenharmony_ci 19151cb0ef41Sopenharmony_ci v8::Maybe<bool> status = JSReceiver::DefineOwnProperty( 19161cb0ef41Sopenharmony_ci isolate_, export_to, name, &desc, Just(kThrowOnError)); 19171cb0ef41Sopenharmony_ci if (!status.IsJust()) { 19181cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 19191cb0ef41Sopenharmony_ci TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>(no_gc)); 19201cb0ef41Sopenharmony_ci thrower_->LinkError("export of %.*s failed.", trunc_name.length(), 19211cb0ef41Sopenharmony_ci trunc_name.start()); 19221cb0ef41Sopenharmony_ci return; 19231cb0ef41Sopenharmony_ci } 19241cb0ef41Sopenharmony_ci } 19251cb0ef41Sopenharmony_ci 19261cb0ef41Sopenharmony_ci if (module_->origin == kWasmOrigin) { 19271cb0ef41Sopenharmony_ci v8::Maybe<bool> success = 19281cb0ef41Sopenharmony_ci JSReceiver::SetIntegrityLevel(exports_object, FROZEN, kDontThrow); 19291cb0ef41Sopenharmony_ci DCHECK(success.FromMaybe(false)); 19301cb0ef41Sopenharmony_ci USE(success); 19311cb0ef41Sopenharmony_ci } 19321cb0ef41Sopenharmony_ci} 19331cb0ef41Sopenharmony_ci 19341cb0ef41Sopenharmony_cinamespace { 19351cb0ef41Sopenharmony_ciV8_INLINE void SetFunctionTablePlaceholder(Isolate* isolate, 19361cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 19371cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_object, 19381cb0ef41Sopenharmony_ci uint32_t entry_index, 19391cb0ef41Sopenharmony_ci uint32_t func_index) { 19401cb0ef41Sopenharmony_ci const WasmModule* module = instance->module(); 19411cb0ef41Sopenharmony_ci const WasmFunction* function = &module->functions[func_index]; 19421cb0ef41Sopenharmony_ci MaybeHandle<WasmInternalFunction> wasm_internal_function = 19431cb0ef41Sopenharmony_ci WasmInstanceObject::GetWasmInternalFunction(isolate, instance, 19441cb0ef41Sopenharmony_ci func_index); 19451cb0ef41Sopenharmony_ci if (wasm_internal_function.is_null()) { 19461cb0ef41Sopenharmony_ci // No JSFunction entry yet exists for this function. Create a {Tuple2} 19471cb0ef41Sopenharmony_ci // holding the information to lazily allocate one. 19481cb0ef41Sopenharmony_ci WasmTableObject::SetFunctionTablePlaceholder( 19491cb0ef41Sopenharmony_ci isolate, table_object, entry_index, instance, func_index); 19501cb0ef41Sopenharmony_ci } else { 19511cb0ef41Sopenharmony_ci table_object->entries().set(entry_index, 19521cb0ef41Sopenharmony_ci *wasm_internal_function.ToHandleChecked()); 19531cb0ef41Sopenharmony_ci } 19541cb0ef41Sopenharmony_ci WasmTableObject::UpdateDispatchTables(isolate, *table_object, entry_index, 19551cb0ef41Sopenharmony_ci function, *instance); 19561cb0ef41Sopenharmony_ci} 19571cb0ef41Sopenharmony_ci 19581cb0ef41Sopenharmony_ciV8_INLINE void SetFunctionTableNullEntry(Isolate* isolate, 19591cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_object, 19601cb0ef41Sopenharmony_ci uint32_t entry_index) { 19611cb0ef41Sopenharmony_ci table_object->entries().set(entry_index, *isolate->factory()->null_value()); 19621cb0ef41Sopenharmony_ci WasmTableObject::ClearDispatchTables(isolate, table_object, entry_index); 19631cb0ef41Sopenharmony_ci} 19641cb0ef41Sopenharmony_ci} // namespace 19651cb0ef41Sopenharmony_ci 19661cb0ef41Sopenharmony_civoid InstanceBuilder::InitializeNonDefaultableTables( 19671cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance) { 19681cb0ef41Sopenharmony_ci for (int table_index = 0; 19691cb0ef41Sopenharmony_ci table_index < static_cast<int>(module_->tables.size()); ++table_index) { 19701cb0ef41Sopenharmony_ci const WasmTable& table = module_->tables[table_index]; 19711cb0ef41Sopenharmony_ci if (!table.type.is_defaultable()) { 19721cb0ef41Sopenharmony_ci auto table_object = handle( 19731cb0ef41Sopenharmony_ci WasmTableObject::cast(instance->tables().get(table_index)), isolate_); 19741cb0ef41Sopenharmony_ci bool is_function_table = IsSubtypeOf(table.type, kWasmFuncRef, module_); 19751cb0ef41Sopenharmony_ci if (is_function_table && 19761cb0ef41Sopenharmony_ci table.initial_value.kind() == ConstantExpression::kRefFunc) { 19771cb0ef41Sopenharmony_ci for (uint32_t entry_index = 0; entry_index < table.initial_size; 19781cb0ef41Sopenharmony_ci entry_index++) { 19791cb0ef41Sopenharmony_ci SetFunctionTablePlaceholder(isolate_, instance, table_object, 19801cb0ef41Sopenharmony_ci entry_index, table.initial_value.index()); 19811cb0ef41Sopenharmony_ci } 19821cb0ef41Sopenharmony_ci } else if (is_function_table && 19831cb0ef41Sopenharmony_ci table.initial_value.kind() == ConstantExpression::kRefNull) { 19841cb0ef41Sopenharmony_ci for (uint32_t entry_index = 0; entry_index < table.initial_size; 19851cb0ef41Sopenharmony_ci entry_index++) { 19861cb0ef41Sopenharmony_ci SetFunctionTableNullEntry(isolate_, table_object, entry_index); 19871cb0ef41Sopenharmony_ci } 19881cb0ef41Sopenharmony_ci } else { 19891cb0ef41Sopenharmony_ci WasmValue value = 19901cb0ef41Sopenharmony_ci EvaluateInitExpression(&init_expr_zone_, table.initial_value, 19911cb0ef41Sopenharmony_ci table.type, isolate_, instance, thrower_); 19921cb0ef41Sopenharmony_ci if (thrower_->error()) return; 19931cb0ef41Sopenharmony_ci for (uint32_t entry_index = 0; entry_index < table.initial_size; 19941cb0ef41Sopenharmony_ci entry_index++) { 19951cb0ef41Sopenharmony_ci WasmTableObject::Set(isolate_, table_object, entry_index, 19961cb0ef41Sopenharmony_ci value.to_ref()); 19971cb0ef41Sopenharmony_ci } 19981cb0ef41Sopenharmony_ci } 19991cb0ef41Sopenharmony_ci } 20001cb0ef41Sopenharmony_ci} 20011cb0ef41Sopenharmony_ci} 20021cb0ef41Sopenharmony_ci 20031cb0ef41Sopenharmony_cinamespace { 20041cb0ef41Sopenharmony_cibool LoadElemSegmentImpl(Zone* zone, Isolate* isolate, 20051cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance, 20061cb0ef41Sopenharmony_ci Handle<WasmTableObject> table_object, 20071cb0ef41Sopenharmony_ci uint32_t table_index, uint32_t segment_index, 20081cb0ef41Sopenharmony_ci uint32_t dst, uint32_t src, size_t count) { 20091cb0ef41Sopenharmony_ci DCHECK_LT(segment_index, instance->module()->elem_segments.size()); 20101cb0ef41Sopenharmony_ci auto& elem_segment = instance->module()->elem_segments[segment_index]; 20111cb0ef41Sopenharmony_ci // TODO(wasm): Move this functionality into wasm-objects, since it is used 20121cb0ef41Sopenharmony_ci // for both instantiation and in the implementation of the table.init 20131cb0ef41Sopenharmony_ci // instruction. 20141cb0ef41Sopenharmony_ci if (!base::IsInBounds<uint64_t>(dst, count, table_object->current_length()) || 20151cb0ef41Sopenharmony_ci !base::IsInBounds<uint64_t>( 20161cb0ef41Sopenharmony_ci src, count, 20171cb0ef41Sopenharmony_ci instance->dropped_elem_segments()[segment_index] == 0 20181cb0ef41Sopenharmony_ci ? elem_segment.entries.size() 20191cb0ef41Sopenharmony_ci : 0)) { 20201cb0ef41Sopenharmony_ci return false; 20211cb0ef41Sopenharmony_ci } 20221cb0ef41Sopenharmony_ci 20231cb0ef41Sopenharmony_ci bool is_function_table = 20241cb0ef41Sopenharmony_ci IsSubtypeOf(table_object->type(), kWasmFuncRef, instance->module()); 20251cb0ef41Sopenharmony_ci 20261cb0ef41Sopenharmony_ci ErrorThrower thrower(isolate, "LoadElemSegment"); 20271cb0ef41Sopenharmony_ci 20281cb0ef41Sopenharmony_ci for (size_t i = 0; i < count; ++i) { 20291cb0ef41Sopenharmony_ci ConstantExpression entry = elem_segment.entries[src + i]; 20301cb0ef41Sopenharmony_ci int entry_index = static_cast<int>(dst + i); 20311cb0ef41Sopenharmony_ci if (is_function_table && entry.kind() == ConstantExpression::kRefFunc) { 20321cb0ef41Sopenharmony_ci SetFunctionTablePlaceholder(isolate, instance, table_object, entry_index, 20331cb0ef41Sopenharmony_ci entry.index()); 20341cb0ef41Sopenharmony_ci } else if (is_function_table && 20351cb0ef41Sopenharmony_ci entry.kind() == ConstantExpression::kRefNull) { 20361cb0ef41Sopenharmony_ci SetFunctionTableNullEntry(isolate, table_object, entry_index); 20371cb0ef41Sopenharmony_ci } else { 20381cb0ef41Sopenharmony_ci WasmValue value = EvaluateInitExpression(zone, entry, elem_segment.type, 20391cb0ef41Sopenharmony_ci isolate, instance, &thrower); 20401cb0ef41Sopenharmony_ci if (thrower.error()) return false; 20411cb0ef41Sopenharmony_ci WasmTableObject::Set(isolate, table_object, entry_index, value.to_ref()); 20421cb0ef41Sopenharmony_ci } 20431cb0ef41Sopenharmony_ci } 20441cb0ef41Sopenharmony_ci return true; 20451cb0ef41Sopenharmony_ci} 20461cb0ef41Sopenharmony_ci} // namespace 20471cb0ef41Sopenharmony_ci 20481cb0ef41Sopenharmony_civoid InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) { 20491cb0ef41Sopenharmony_ci for (uint32_t segment_index = 0; 20501cb0ef41Sopenharmony_ci segment_index < module_->elem_segments.size(); ++segment_index) { 20511cb0ef41Sopenharmony_ci auto& elem_segment = instance->module()->elem_segments[segment_index]; 20521cb0ef41Sopenharmony_ci // Passive segments are not copied during instantiation. 20531cb0ef41Sopenharmony_ci if (elem_segment.status != WasmElemSegment::kStatusActive) continue; 20541cb0ef41Sopenharmony_ci 20551cb0ef41Sopenharmony_ci uint32_t table_index = elem_segment.table_index; 20561cb0ef41Sopenharmony_ci uint32_t dst = 20571cb0ef41Sopenharmony_ci EvaluateInitExpression(&init_expr_zone_, elem_segment.offset, kWasmI32, 20581cb0ef41Sopenharmony_ci isolate_, instance, thrower_) 20591cb0ef41Sopenharmony_ci .to_u32(); 20601cb0ef41Sopenharmony_ci if (thrower_->error()) return; 20611cb0ef41Sopenharmony_ci uint32_t src = 0; 20621cb0ef41Sopenharmony_ci size_t count = elem_segment.entries.size(); 20631cb0ef41Sopenharmony_ci 20641cb0ef41Sopenharmony_ci bool success = LoadElemSegmentImpl( 20651cb0ef41Sopenharmony_ci &init_expr_zone_, isolate_, instance, 20661cb0ef41Sopenharmony_ci handle(WasmTableObject::cast( 20671cb0ef41Sopenharmony_ci instance->tables().get(elem_segment.table_index)), 20681cb0ef41Sopenharmony_ci isolate_), 20691cb0ef41Sopenharmony_ci table_index, segment_index, dst, src, count); 20701cb0ef41Sopenharmony_ci // Set the active segments to being already dropped, since table.init on 20711cb0ef41Sopenharmony_ci // a dropped passive segment and an active segment have the same behavior. 20721cb0ef41Sopenharmony_ci instance->dropped_elem_segments()[segment_index] = 1; 20731cb0ef41Sopenharmony_ci if (!success) { 20741cb0ef41Sopenharmony_ci thrower_->RuntimeError("table initializer is out of bounds"); 20751cb0ef41Sopenharmony_ci return; 20761cb0ef41Sopenharmony_ci } 20771cb0ef41Sopenharmony_ci } 20781cb0ef41Sopenharmony_ci} 20791cb0ef41Sopenharmony_ci 20801cb0ef41Sopenharmony_civoid InstanceBuilder::InitializeTags(Handle<WasmInstanceObject> instance) { 20811cb0ef41Sopenharmony_ci Handle<FixedArray> tags_table(instance->tags_table(), isolate_); 20821cb0ef41Sopenharmony_ci for (int index = 0; index < tags_table->length(); ++index) { 20831cb0ef41Sopenharmony_ci if (!tags_table->get(index).IsUndefined(isolate_)) continue; 20841cb0ef41Sopenharmony_ci Handle<WasmExceptionTag> tag = WasmExceptionTag::New(isolate_, index); 20851cb0ef41Sopenharmony_ci tags_table->set(index, *tag); 20861cb0ef41Sopenharmony_ci } 20871cb0ef41Sopenharmony_ci} 20881cb0ef41Sopenharmony_ci 20891cb0ef41Sopenharmony_cibool LoadElemSegment(Isolate* isolate, Handle<WasmInstanceObject> instance, 20901cb0ef41Sopenharmony_ci uint32_t table_index, uint32_t segment_index, uint32_t dst, 20911cb0ef41Sopenharmony_ci uint32_t src, uint32_t count) { 20921cb0ef41Sopenharmony_ci AccountingAllocator allocator; 20931cb0ef41Sopenharmony_ci // This {Zone} will be used only by the temporary WasmFullDecoder allocated 20941cb0ef41Sopenharmony_ci // down the line from this call. Therefore it is safe to stack-allocate it 20951cb0ef41Sopenharmony_ci // here. 20961cb0ef41Sopenharmony_ci Zone zone(&allocator, "LoadElemSegment"); 20971cb0ef41Sopenharmony_ci return LoadElemSegmentImpl( 20981cb0ef41Sopenharmony_ci &zone, isolate, instance, 20991cb0ef41Sopenharmony_ci handle(WasmTableObject::cast(instance->tables().get(table_index)), 21001cb0ef41Sopenharmony_ci isolate), 21011cb0ef41Sopenharmony_ci table_index, segment_index, dst, src, count); 21021cb0ef41Sopenharmony_ci} 21031cb0ef41Sopenharmony_ci 21041cb0ef41Sopenharmony_ci} // namespace wasm 21051cb0ef41Sopenharmony_ci} // namespace internal 21061cb0ef41Sopenharmony_ci} // namespace v8 21071cb0ef41Sopenharmony_ci 21081cb0ef41Sopenharmony_ci#undef TRACE 2109