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