11cb0ef41Sopenharmony_ci// Copyright 2021 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 "include/v8-wasm.h"
61cb0ef41Sopenharmony_ci#include "src/base/memory.h"
71cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h"
81cb0ef41Sopenharmony_ci#include "src/execution/arguments-inl.h"
91cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h"
101cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"
111cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
121cb0ef41Sopenharmony_ci#include "src/objects/smi.h"
131cb0ef41Sopenharmony_ci#include "src/runtime/runtime-utils.h"
141cb0ef41Sopenharmony_ci#include "src/trap-handler/trap-handler.h"
151cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
161cb0ef41Sopenharmony_ci#include "src/wasm/memory-tracing.h"
171cb0ef41Sopenharmony_ci#include "src/wasm/module-compiler.h"
181cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h"
191cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h"
201cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h"
211cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h"
221cb0ef41Sopenharmony_ci#include "src/wasm/wasm-serialization.h"
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cinamespace v8 {
251cb0ef41Sopenharmony_cinamespace internal {
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cinamespace {
281cb0ef41Sopenharmony_cistruct WasmCompileControls {
291cb0ef41Sopenharmony_ci  uint32_t MaxWasmBufferSize = std::numeric_limits<uint32_t>::max();
301cb0ef41Sopenharmony_ci  bool AllowAnySizeForAsync = true;
311cb0ef41Sopenharmony_ci};
321cb0ef41Sopenharmony_ciusing WasmCompileControlsMap = std::map<v8::Isolate*, WasmCompileControls>;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci// We need per-isolate controls, because we sometimes run tests in multiple
351cb0ef41Sopenharmony_ci// isolates concurrently. Methods need to hold the accompanying mutex on access.
361cb0ef41Sopenharmony_ci// To avoid upsetting the static initializer count, we lazy initialize this.
371cb0ef41Sopenharmony_ciDEFINE_LAZY_LEAKY_OBJECT_GETTER(WasmCompileControlsMap,
381cb0ef41Sopenharmony_ci                                GetPerIsolateWasmControls)
391cb0ef41Sopenharmony_cibase::LazyMutex g_PerIsolateWasmControlsMutex = LAZY_MUTEX_INITIALIZER;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_cibool IsWasmCompileAllowed(v8::Isolate* isolate, v8::Local<v8::Value> value,
421cb0ef41Sopenharmony_ci                          bool is_async) {
431cb0ef41Sopenharmony_ci  base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
441cb0ef41Sopenharmony_ci  DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
451cb0ef41Sopenharmony_ci  const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
461cb0ef41Sopenharmony_ci  return (is_async && ctrls.AllowAnySizeForAsync) ||
471cb0ef41Sopenharmony_ci         (value->IsArrayBuffer() && value.As<v8::ArrayBuffer>()->ByteLength() <=
481cb0ef41Sopenharmony_ci                                        ctrls.MaxWasmBufferSize) ||
491cb0ef41Sopenharmony_ci         (value->IsArrayBufferView() &&
501cb0ef41Sopenharmony_ci          value.As<v8::ArrayBufferView>()->ByteLength() <=
511cb0ef41Sopenharmony_ci              ctrls.MaxWasmBufferSize);
521cb0ef41Sopenharmony_ci}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci// Use the compile controls for instantiation, too
551cb0ef41Sopenharmony_cibool IsWasmInstantiateAllowed(v8::Isolate* isolate,
561cb0ef41Sopenharmony_ci                              v8::Local<v8::Value> module_or_bytes,
571cb0ef41Sopenharmony_ci                              bool is_async) {
581cb0ef41Sopenharmony_ci  base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
591cb0ef41Sopenharmony_ci  DCHECK_GT(GetPerIsolateWasmControls()->count(isolate), 0);
601cb0ef41Sopenharmony_ci  const WasmCompileControls& ctrls = GetPerIsolateWasmControls()->at(isolate);
611cb0ef41Sopenharmony_ci  if (is_async && ctrls.AllowAnySizeForAsync) return true;
621cb0ef41Sopenharmony_ci  if (!module_or_bytes->IsWasmModuleObject()) {
631cb0ef41Sopenharmony_ci    return IsWasmCompileAllowed(isolate, module_or_bytes, is_async);
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci  v8::Local<v8::WasmModuleObject> module =
661cb0ef41Sopenharmony_ci      v8::Local<v8::WasmModuleObject>::Cast(module_or_bytes);
671cb0ef41Sopenharmony_ci  return static_cast<uint32_t>(
681cb0ef41Sopenharmony_ci             module->GetCompiledModule().GetWireBytesRef().size()) <=
691cb0ef41Sopenharmony_ci         ctrls.MaxWasmBufferSize;
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_civ8::Local<v8::Value> NewRangeException(v8::Isolate* isolate,
731cb0ef41Sopenharmony_ci                                       const char* message) {
741cb0ef41Sopenharmony_ci  return v8::Exception::RangeError(
751cb0ef41Sopenharmony_ci      v8::String::NewFromOneByte(isolate,
761cb0ef41Sopenharmony_ci                                 reinterpret_cast<const uint8_t*>(message))
771cb0ef41Sopenharmony_ci          .ToLocalChecked());
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_civoid ThrowRangeException(v8::Isolate* isolate, const char* message) {
811cb0ef41Sopenharmony_ci  isolate->ThrowException(NewRangeException(isolate, message));
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_cibool WasmModuleOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
851cb0ef41Sopenharmony_ci  if (IsWasmCompileAllowed(args.GetIsolate(), args[0], false)) return false;
861cb0ef41Sopenharmony_ci  ThrowRangeException(args.GetIsolate(), "Sync compile not allowed");
871cb0ef41Sopenharmony_ci  return true;
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_cibool WasmInstanceOverride(const v8::FunctionCallbackInfo<v8::Value>& args) {
911cb0ef41Sopenharmony_ci  if (IsWasmInstantiateAllowed(args.GetIsolate(), args[0], false)) return false;
921cb0ef41Sopenharmony_ci  ThrowRangeException(args.GetIsolate(), "Sync instantiate not allowed");
931cb0ef41Sopenharmony_ci  return true;
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci}  // namespace
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci// Returns a callable object. The object returns the difference of its two
991cb0ef41Sopenharmony_ci// parameters when it is called.
1001cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_SetWasmCompileControls) {
1011cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1021cb0ef41Sopenharmony_ci  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1031cb0ef41Sopenharmony_ci  CHECK_EQ(args.length(), 2);
1041cb0ef41Sopenharmony_ci  int block_size = args.smi_value_at(0);
1051cb0ef41Sopenharmony_ci  bool allow_async = Oddball::cast(args[1]).ToBool(isolate);
1061cb0ef41Sopenharmony_ci  base::MutexGuard guard(g_PerIsolateWasmControlsMutex.Pointer());
1071cb0ef41Sopenharmony_ci  WasmCompileControls& ctrl = (*GetPerIsolateWasmControls())[v8_isolate];
1081cb0ef41Sopenharmony_ci  ctrl.AllowAnySizeForAsync = allow_async;
1091cb0ef41Sopenharmony_ci  ctrl.MaxWasmBufferSize = static_cast<uint32_t>(block_size);
1101cb0ef41Sopenharmony_ci  v8_isolate->SetWasmModuleCallback(WasmModuleOverride);
1111cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_SetWasmInstantiateControls) {
1151cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1161cb0ef41Sopenharmony_ci  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1171cb0ef41Sopenharmony_ci  CHECK_EQ(args.length(), 0);
1181cb0ef41Sopenharmony_ci  v8_isolate->SetWasmInstanceCallback(WasmInstanceOverride);
1191cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cinamespace {
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_civoid PrintIndentation(int stack_size) {
1251cb0ef41Sopenharmony_ci  const int max_display = 80;
1261cb0ef41Sopenharmony_ci  if (stack_size <= max_display) {
1271cb0ef41Sopenharmony_ci    PrintF("%4d:%*s", stack_size, stack_size, "");
1281cb0ef41Sopenharmony_ci  } else {
1291cb0ef41Sopenharmony_ci    PrintF("%4d:%*s", stack_size, max_display, "...");
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci}
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ciint WasmStackSize(Isolate* isolate) {
1341cb0ef41Sopenharmony_ci  // TODO(wasm): Fix this for mixed JS/Wasm stacks with both --trace and
1351cb0ef41Sopenharmony_ci  // --trace-wasm.
1361cb0ef41Sopenharmony_ci  int n = 0;
1371cb0ef41Sopenharmony_ci  for (StackTraceFrameIterator it(isolate); !it.done(); it.Advance()) {
1381cb0ef41Sopenharmony_ci    if (it.is_wasm()) n++;
1391cb0ef41Sopenharmony_ci  }
1401cb0ef41Sopenharmony_ci  return n;
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci}  // namespace
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmTraceEnter) {
1461cb0ef41Sopenharmony_ci  HandleScope shs(isolate);
1471cb0ef41Sopenharmony_ci  DCHECK_EQ(0, args.length());
1481cb0ef41Sopenharmony_ci  PrintIndentation(WasmStackSize(isolate));
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  // Find the caller wasm frame.
1511cb0ef41Sopenharmony_ci  wasm::WasmCodeRefScope wasm_code_ref_scope;
1521cb0ef41Sopenharmony_ci  StackTraceFrameIterator it(isolate);
1531cb0ef41Sopenharmony_ci  DCHECK(!it.done());
1541cb0ef41Sopenharmony_ci  DCHECK(it.is_wasm());
1551cb0ef41Sopenharmony_ci  WasmFrame* frame = WasmFrame::cast(it.frame());
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  // Find the function name.
1581cb0ef41Sopenharmony_ci  int func_index = frame->function_index();
1591cb0ef41Sopenharmony_ci  const wasm::WasmModule* module = frame->wasm_instance().module();
1601cb0ef41Sopenharmony_ci  wasm::ModuleWireBytes wire_bytes =
1611cb0ef41Sopenharmony_ci      wasm::ModuleWireBytes(frame->native_module()->wire_bytes());
1621cb0ef41Sopenharmony_ci  wasm::WireBytesRef name_ref =
1631cb0ef41Sopenharmony_ci      module->lazily_generated_names.LookupFunctionName(wire_bytes, func_index);
1641cb0ef41Sopenharmony_ci  wasm::WasmName name = wire_bytes.GetNameOrNull(name_ref);
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  wasm::WasmCode* code = frame->wasm_code();
1671cb0ef41Sopenharmony_ci  PrintF(code->is_liftoff() ? "~" : "*");
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  if (name.empty()) {
1701cb0ef41Sopenharmony_ci    PrintF("wasm-function[%d] {\n", func_index);
1711cb0ef41Sopenharmony_ci  } else {
1721cb0ef41Sopenharmony_ci    PrintF("wasm-function[%d] \"%.*s\" {\n", func_index, name.length(),
1731cb0ef41Sopenharmony_ci           name.begin());
1741cb0ef41Sopenharmony_ci  }
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
1771cb0ef41Sopenharmony_ci}
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmTraceExit) {
1801cb0ef41Sopenharmony_ci  HandleScope shs(isolate);
1811cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
1821cb0ef41Sopenharmony_ci  auto value_addr_smi = Smi::cast(args[0]);
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  PrintIndentation(WasmStackSize(isolate));
1851cb0ef41Sopenharmony_ci  PrintF("}");
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  // Find the caller wasm frame.
1881cb0ef41Sopenharmony_ci  wasm::WasmCodeRefScope wasm_code_ref_scope;
1891cb0ef41Sopenharmony_ci  StackTraceFrameIterator it(isolate);
1901cb0ef41Sopenharmony_ci  DCHECK(!it.done());
1911cb0ef41Sopenharmony_ci  DCHECK(it.is_wasm());
1921cb0ef41Sopenharmony_ci  WasmFrame* frame = WasmFrame::cast(it.frame());
1931cb0ef41Sopenharmony_ci  int func_index = frame->function_index();
1941cb0ef41Sopenharmony_ci  const wasm::FunctionSig* sig =
1951cb0ef41Sopenharmony_ci      frame->wasm_instance().module()->functions[func_index].sig;
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  size_t num_returns = sig->return_count();
1981cb0ef41Sopenharmony_ci  if (num_returns == 1) {
1991cb0ef41Sopenharmony_ci    wasm::ValueType return_type = sig->GetReturn(0);
2001cb0ef41Sopenharmony_ci    switch (return_type.kind()) {
2011cb0ef41Sopenharmony_ci      case wasm::kI32: {
2021cb0ef41Sopenharmony_ci        int32_t value = base::ReadUnalignedValue<int32_t>(value_addr_smi.ptr());
2031cb0ef41Sopenharmony_ci        PrintF(" -> %d\n", value);
2041cb0ef41Sopenharmony_ci        break;
2051cb0ef41Sopenharmony_ci      }
2061cb0ef41Sopenharmony_ci      case wasm::kI64: {
2071cb0ef41Sopenharmony_ci        int64_t value = base::ReadUnalignedValue<int64_t>(value_addr_smi.ptr());
2081cb0ef41Sopenharmony_ci        PrintF(" -> %" PRId64 "\n", value);
2091cb0ef41Sopenharmony_ci        break;
2101cb0ef41Sopenharmony_ci      }
2111cb0ef41Sopenharmony_ci      case wasm::kF32: {
2121cb0ef41Sopenharmony_ci        float value = base::ReadUnalignedValue<float>(value_addr_smi.ptr());
2131cb0ef41Sopenharmony_ci        PrintF(" -> %f\n", value);
2141cb0ef41Sopenharmony_ci        break;
2151cb0ef41Sopenharmony_ci      }
2161cb0ef41Sopenharmony_ci      case wasm::kF64: {
2171cb0ef41Sopenharmony_ci        double value = base::ReadUnalignedValue<double>(value_addr_smi.ptr());
2181cb0ef41Sopenharmony_ci        PrintF(" -> %f\n", value);
2191cb0ef41Sopenharmony_ci        break;
2201cb0ef41Sopenharmony_ci      }
2211cb0ef41Sopenharmony_ci      default:
2221cb0ef41Sopenharmony_ci        PrintF(" -> Unsupported type\n");
2231cb0ef41Sopenharmony_ci        break;
2241cb0ef41Sopenharmony_ci    }
2251cb0ef41Sopenharmony_ci  } else {
2261cb0ef41Sopenharmony_ci    // TODO(wasm) Handle multiple return values.
2271cb0ef41Sopenharmony_ci    PrintF("\n");
2281cb0ef41Sopenharmony_ci  }
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
2311cb0ef41Sopenharmony_ci}
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsAsmWasmCode) {
2341cb0ef41Sopenharmony_ci  SealHandleScope shs(isolate);
2351cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
2361cb0ef41Sopenharmony_ci  auto function = JSFunction::cast(args[0]);
2371cb0ef41Sopenharmony_ci  if (!function.shared().HasAsmWasmData()) {
2381cb0ef41Sopenharmony_ci    return ReadOnlyRoots(isolate).false_value();
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci  if (function.shared().HasBuiltinId() &&
2411cb0ef41Sopenharmony_ci      function.shared().builtin_id() == Builtin::kInstantiateAsmJs) {
2421cb0ef41Sopenharmony_ci    // Hasn't been compiled yet.
2431cb0ef41Sopenharmony_ci    return ReadOnlyRoots(isolate).false_value();
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).true_value();
2461cb0ef41Sopenharmony_ci}
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_cinamespace {
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_cibool DisallowWasmCodegenFromStringsCallback(v8::Local<v8::Context> context,
2511cb0ef41Sopenharmony_ci                                            v8::Local<v8::String> source) {
2521cb0ef41Sopenharmony_ci  return false;
2531cb0ef41Sopenharmony_ci}
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci}  // namespace
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_DisallowWasmCodegen) {
2581cb0ef41Sopenharmony_ci  SealHandleScope shs(isolate);
2591cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
2601cb0ef41Sopenharmony_ci  bool flag = Oddball::cast(args[0]).ToBool(isolate);
2611cb0ef41Sopenharmony_ci  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
2621cb0ef41Sopenharmony_ci  v8_isolate->SetAllowWasmCodeGenerationCallback(
2631cb0ef41Sopenharmony_ci      flag ? DisallowWasmCodegenFromStringsCallback : nullptr);
2641cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
2651cb0ef41Sopenharmony_ci}
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsWasmCode) {
2681cb0ef41Sopenharmony_ci  SealHandleScope shs(isolate);
2691cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
2701cb0ef41Sopenharmony_ci  auto function = JSFunction::cast(args[0]);
2711cb0ef41Sopenharmony_ci  CodeT code = function.code();
2721cb0ef41Sopenharmony_ci  bool is_js_to_wasm = code.kind() == CodeKind::JS_TO_WASM_FUNCTION ||
2731cb0ef41Sopenharmony_ci                       (code.builtin_id() == Builtin::kGenericJSToWasmWrapper);
2741cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(is_js_to_wasm);
2751cb0ef41Sopenharmony_ci}
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsWasmTrapHandlerEnabled) {
2781cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
2791cb0ef41Sopenharmony_ci  DCHECK_EQ(0, args.length());
2801cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(trap_handler::IsTrapHandlerEnabled());
2811cb0ef41Sopenharmony_ci}
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsThreadInWasm) {
2841cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
2851cb0ef41Sopenharmony_ci  DCHECK_EQ(0, args.length());
2861cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(trap_handler::IsThreadInWasm());
2871cb0ef41Sopenharmony_ci}
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount) {
2901cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
2911cb0ef41Sopenharmony_ci  DCHECK_EQ(0, args.length());
2921cb0ef41Sopenharmony_ci  size_t trap_count = trap_handler::GetRecoveredTrapCount();
2931cb0ef41Sopenharmony_ci  return *isolate->factory()->NewNumberFromSize(trap_count);
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_GetWasmExceptionTagId) {
2971cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
2981cb0ef41Sopenharmony_ci  DCHECK_EQ(2, args.length());
2991cb0ef41Sopenharmony_ci  Handle<WasmExceptionPackage> exception = args.at<WasmExceptionPackage>(0);
3001cb0ef41Sopenharmony_ci  Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(1);
3011cb0ef41Sopenharmony_ci  Handle<Object> tag =
3021cb0ef41Sopenharmony_ci      WasmExceptionPackage::GetExceptionTag(isolate, exception);
3031cb0ef41Sopenharmony_ci  CHECK(tag->IsWasmExceptionTag());
3041cb0ef41Sopenharmony_ci  Handle<FixedArray> tags_table(instance->tags_table(), isolate);
3051cb0ef41Sopenharmony_ci  for (int index = 0; index < tags_table->length(); ++index) {
3061cb0ef41Sopenharmony_ci    if (tags_table->get(index) == *tag) return Smi::FromInt(index);
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci  UNREACHABLE();
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_GetWasmExceptionValues) {
3121cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3131cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
3141cb0ef41Sopenharmony_ci  Handle<WasmExceptionPackage> exception = args.at<WasmExceptionPackage>(0);
3151cb0ef41Sopenharmony_ci  Handle<Object> values_obj =
3161cb0ef41Sopenharmony_ci      WasmExceptionPackage::GetExceptionValues(isolate, exception);
3171cb0ef41Sopenharmony_ci  CHECK(values_obj->IsFixedArray());  // Only called with correct input.
3181cb0ef41Sopenharmony_ci  Handle<FixedArray> values = Handle<FixedArray>::cast(values_obj);
3191cb0ef41Sopenharmony_ci  return *isolate->factory()->NewJSArrayWithElements(values);
3201cb0ef41Sopenharmony_ci}
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
3231cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3241cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
3251cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module_obj = args.at<WasmModuleObject>(0);
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  wasm::NativeModule* native_module = module_obj->native_module();
3281cb0ef41Sopenharmony_ci  DCHECK(!native_module->compilation_state()->failed());
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  wasm::WasmSerializer wasm_serializer(native_module);
3311cb0ef41Sopenharmony_ci  size_t byte_length = wasm_serializer.GetSerializedNativeModuleSize();
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  Handle<JSArrayBuffer> array_buffer =
3341cb0ef41Sopenharmony_ci      isolate->factory()
3351cb0ef41Sopenharmony_ci          ->NewJSArrayBufferAndBackingStore(byte_length,
3361cb0ef41Sopenharmony_ci                                            InitializedFlag::kUninitialized)
3371cb0ef41Sopenharmony_ci          .ToHandleChecked();
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci  CHECK(wasm_serializer.SerializeNativeModule(
3401cb0ef41Sopenharmony_ci      {static_cast<uint8_t*>(array_buffer->backing_store()), byte_length}));
3411cb0ef41Sopenharmony_ci  return *array_buffer;
3421cb0ef41Sopenharmony_ci}
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci// Take an array buffer and attempt to reconstruct a compiled wasm module.
3451cb0ef41Sopenharmony_ci// Return undefined if unsuccessful.
3461cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
3471cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3481cb0ef41Sopenharmony_ci  DCHECK_EQ(2, args.length());
3491cb0ef41Sopenharmony_ci  Handle<JSArrayBuffer> buffer = args.at<JSArrayBuffer>(0);
3501cb0ef41Sopenharmony_ci  Handle<JSTypedArray> wire_bytes = args.at<JSTypedArray>(1);
3511cb0ef41Sopenharmony_ci  CHECK(!buffer->was_detached());
3521cb0ef41Sopenharmony_ci  CHECK(!wire_bytes->WasDetached());
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  Handle<JSArrayBuffer> wire_bytes_buffer = wire_bytes->GetBuffer();
3551cb0ef41Sopenharmony_ci  base::Vector<const uint8_t> wire_bytes_vec{
3561cb0ef41Sopenharmony_ci      reinterpret_cast<const uint8_t*>(wire_bytes_buffer->backing_store()) +
3571cb0ef41Sopenharmony_ci          wire_bytes->byte_offset(),
3581cb0ef41Sopenharmony_ci      wire_bytes->byte_length()};
3591cb0ef41Sopenharmony_ci  base::Vector<uint8_t> buffer_vec{
3601cb0ef41Sopenharmony_ci      reinterpret_cast<uint8_t*>(buffer->backing_store()),
3611cb0ef41Sopenharmony_ci      buffer->byte_length()};
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  // Note that {wasm::DeserializeNativeModule} will allocate. We assume the
3641cb0ef41Sopenharmony_ci  // JSArrayBuffer backing store doesn't get relocated.
3651cb0ef41Sopenharmony_ci  MaybeHandle<WasmModuleObject> maybe_module_object =
3661cb0ef41Sopenharmony_ci      wasm::DeserializeNativeModule(isolate, buffer_vec, wire_bytes_vec, {});
3671cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module_object;
3681cb0ef41Sopenharmony_ci  if (!maybe_module_object.ToHandle(&module_object)) {
3691cb0ef41Sopenharmony_ci    return ReadOnlyRoots(isolate).undefined_value();
3701cb0ef41Sopenharmony_ci  }
3711cb0ef41Sopenharmony_ci  return *module_object;
3721cb0ef41Sopenharmony_ci}
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmGetNumberOfInstances) {
3751cb0ef41Sopenharmony_ci  SealHandleScope shs(isolate);
3761cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
3771cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module_obj = args.at<WasmModuleObject>(0);
3781cb0ef41Sopenharmony_ci  int instance_count = 0;
3791cb0ef41Sopenharmony_ci  WeakArrayList weak_instance_list =
3801cb0ef41Sopenharmony_ci      module_obj->script().wasm_weak_instance_list();
3811cb0ef41Sopenharmony_ci  for (int i = 0; i < weak_instance_list.length(); ++i) {
3821cb0ef41Sopenharmony_ci    if (weak_instance_list.Get(i)->IsWeak()) instance_count++;
3831cb0ef41Sopenharmony_ci  }
3841cb0ef41Sopenharmony_ci  return Smi::FromInt(instance_count);
3851cb0ef41Sopenharmony_ci}
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmNumCodeSpaces) {
3881cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
3891cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3901cb0ef41Sopenharmony_ci  Handle<JSObject> argument = args.at<JSObject>(0);
3911cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module;
3921cb0ef41Sopenharmony_ci  if (argument->IsWasmInstanceObject()) {
3931cb0ef41Sopenharmony_ci    module = handle(Handle<WasmInstanceObject>::cast(argument)->module_object(),
3941cb0ef41Sopenharmony_ci                    isolate);
3951cb0ef41Sopenharmony_ci  } else if (argument->IsWasmModuleObject()) {
3961cb0ef41Sopenharmony_ci    module = Handle<WasmModuleObject>::cast(argument);
3971cb0ef41Sopenharmony_ci  }
3981cb0ef41Sopenharmony_ci  size_t num_spaces =
3991cb0ef41Sopenharmony_ci      module->native_module()->GetNumberOfCodeSpacesForTesting();
4001cb0ef41Sopenharmony_ci  return *isolate->factory()->NewNumberFromSize(num_spaces);
4011cb0ef41Sopenharmony_ci}
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmTraceMemory) {
4041cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4051cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
4061cb0ef41Sopenharmony_ci  auto info_addr = Smi::cast(args[0]);
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  wasm::MemoryTracingInfo* info =
4091cb0ef41Sopenharmony_ci      reinterpret_cast<wasm::MemoryTracingInfo*>(info_addr.ptr());
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci  // Find the caller wasm frame.
4121cb0ef41Sopenharmony_ci  wasm::WasmCodeRefScope wasm_code_ref_scope;
4131cb0ef41Sopenharmony_ci  StackTraceFrameIterator it(isolate);
4141cb0ef41Sopenharmony_ci  DCHECK(!it.done());
4151cb0ef41Sopenharmony_ci  DCHECK(it.is_wasm());
4161cb0ef41Sopenharmony_ci  WasmFrame* frame = WasmFrame::cast(it.frame());
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  uint8_t* mem_start = reinterpret_cast<uint8_t*>(
4191cb0ef41Sopenharmony_ci      frame->wasm_instance().memory_object().array_buffer().backing_store());
4201cb0ef41Sopenharmony_ci  int func_index = frame->function_index();
4211cb0ef41Sopenharmony_ci  int pos = frame->position();
4221cb0ef41Sopenharmony_ci  wasm::ExecutionTier tier = frame->wasm_code()->is_liftoff()
4231cb0ef41Sopenharmony_ci                                 ? wasm::ExecutionTier::kLiftoff
4241cb0ef41Sopenharmony_ci                                 : wasm::ExecutionTier::kTurbofan;
4251cb0ef41Sopenharmony_ci  wasm::TraceMemoryOperation(tier, info, func_index, pos, mem_start);
4261cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
4271cb0ef41Sopenharmony_ci}
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmTierUpFunction) {
4301cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4311cb0ef41Sopenharmony_ci  DCHECK_EQ(2, args.length());
4321cb0ef41Sopenharmony_ci  Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0);
4331cb0ef41Sopenharmony_ci  int function_index = args.smi_value_at(1);
4341cb0ef41Sopenharmony_ci  auto* native_module = instance->module_object().native_module();
4351cb0ef41Sopenharmony_ci  wasm::GetWasmEngine()->CompileFunction(isolate, native_module, function_index,
4361cb0ef41Sopenharmony_ci                                         wasm::ExecutionTier::kTurbofan);
4371cb0ef41Sopenharmony_ci  CHECK(!native_module->compilation_state()->failed());
4381cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
4391cb0ef41Sopenharmony_ci}
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmTierDown) {
4421cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4431cb0ef41Sopenharmony_ci  DCHECK_EQ(0, args.length());
4441cb0ef41Sopenharmony_ci  wasm::GetWasmEngine()->TierDownAllModulesPerIsolate(isolate);
4451cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
4461cb0ef41Sopenharmony_ci}
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_WasmTierUp) {
4491cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4501cb0ef41Sopenharmony_ci  DCHECK_EQ(0, args.length());
4511cb0ef41Sopenharmony_ci  wasm::GetWasmEngine()->TierUpAllModulesPerIsolate(isolate);
4521cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
4531cb0ef41Sopenharmony_ci}
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsLiftoffFunction) {
4561cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4571cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
4581cb0ef41Sopenharmony_ci  Handle<JSFunction> function = args.at<JSFunction>(0);
4591cb0ef41Sopenharmony_ci  CHECK(WasmExportedFunction::IsWasmExportedFunction(*function));
4601cb0ef41Sopenharmony_ci  Handle<WasmExportedFunction> exp_fun =
4611cb0ef41Sopenharmony_ci      Handle<WasmExportedFunction>::cast(function);
4621cb0ef41Sopenharmony_ci  wasm::NativeModule* native_module =
4631cb0ef41Sopenharmony_ci      exp_fun->instance().module_object().native_module();
4641cb0ef41Sopenharmony_ci  uint32_t func_index = exp_fun->function_index();
4651cb0ef41Sopenharmony_ci  wasm::WasmCodeRefScope code_ref_scope;
4661cb0ef41Sopenharmony_ci  wasm::WasmCode* code = native_module->GetCode(func_index);
4671cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(code && code->is_liftoff());
4681cb0ef41Sopenharmony_ci}
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsTurboFanFunction) {
4711cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4721cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
4731cb0ef41Sopenharmony_ci  Handle<JSFunction> function = args.at<JSFunction>(0);
4741cb0ef41Sopenharmony_ci  CHECK(WasmExportedFunction::IsWasmExportedFunction(*function));
4751cb0ef41Sopenharmony_ci  Handle<WasmExportedFunction> exp_fun =
4761cb0ef41Sopenharmony_ci      Handle<WasmExportedFunction>::cast(function);
4771cb0ef41Sopenharmony_ci  wasm::NativeModule* native_module =
4781cb0ef41Sopenharmony_ci      exp_fun->instance().module_object().native_module();
4791cb0ef41Sopenharmony_ci  uint32_t func_index = exp_fun->function_index();
4801cb0ef41Sopenharmony_ci  wasm::WasmCodeRefScope code_ref_scope;
4811cb0ef41Sopenharmony_ci  wasm::WasmCode* code = native_module->GetCode(func_index);
4821cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(code && code->is_turbofan());
4831cb0ef41Sopenharmony_ci}
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_FreezeWasmLazyCompilation) {
4861cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
4871cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
4881cb0ef41Sopenharmony_ci  auto instance = WasmInstanceObject::cast(args[0]);
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci  instance.module_object().native_module()->set_lazy_compile_frozen(true);
4911cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
4921cb0ef41Sopenharmony_ci}
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci}  // namespace internal
4951cb0ef41Sopenharmony_ci}  // namespace v8
496