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