5 #include "src/arguments-inl.h" 6 #include "src/compiler/wasm-compiler.h" 7 #include "src/conversions.h" 8 #include "src/counters.h" 9 #include "src/debug/debug.h" 10 #include "src/frame-constants.h" 11 #include "src/heap/factory.h" 12 #include "src/message-template.h" 13 #include "src/objects-inl.h" 14 #include "src/objects/frame-array-inl.h" 15 #include "src/runtime/runtime-utils.h" 16 #include "src/trap-handler/trap-handler.h" 17 #include "src/v8memory.h" 18 #include "src/wasm/module-compiler.h" 19 #include "src/wasm/wasm-code-manager.h" 20 #include "src/wasm/wasm-constants.h" 21 #include "src/wasm/wasm-engine.h" 22 #include "src/wasm/wasm-objects.h" 29 WasmInstanceObject* GetWasmInstanceOnStackTop(Isolate* isolate) {
30 StackFrameIterator it(isolate, isolate->thread_local_top());
32 DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
35 DCHECK(it.frame()->is_wasm_compiled());
36 WasmCompiledFrame* frame = WasmCompiledFrame::cast(it.frame());
37 return frame->wasm_instance();
40 Context GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
41 return GetWasmInstanceOnStackTop(isolate)->native_context();
44 class ClearThreadInWasmScope {
46 ClearThreadInWasmScope() {
47 DCHECK_EQ(trap_handler::IsTrapHandlerEnabled(),
48 trap_handler::IsThreadInWasm());
49 trap_handler::ClearThreadInWasm();
51 ~ClearThreadInWasmScope() {
52 DCHECK(!trap_handler::IsThreadInWasm());
53 trap_handler::SetThreadInWasm();
59 RUNTIME_FUNCTION(Runtime_WasmMemoryGrow) {
60 HandleScope scope(isolate);
61 DCHECK_EQ(2, args.length());
62 CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
65 CONVERT_UINT32_ARG_CHECKED(delta_pages, 1);
68 ClearThreadInWasmScope flag_scope;
70 int ret = WasmMemoryObject::Grow(
71 isolate, handle(instance->memory_object(), isolate), delta_pages);
74 return Smi::FromInt(ret);
77 RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
78 DCHECK_EQ(1, args.length());
79 CONVERT_SMI_ARG_CHECKED(message_id, 0);
80 ClearThreadInWasmScope clear_wasm_flag;
82 HandleScope scope(isolate);
83 Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
84 MessageTemplateFromInt(message_id));
85 return isolate->Throw(*error_obj);
88 RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
89 SealHandleScope shs(isolate);
90 DCHECK_LE(0, args.length());
91 DCHECK(isolate->context().is_null());
92 isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
93 return isolate->StackOverflow();
96 RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) {
97 HandleScope scope(isolate);
98 DCHECK_EQ(0, args.length());
99 THROW_NEW_ERROR_RETURN_FAILURE(
100 isolate, NewTypeError(MessageTemplate::kWasmTrapTypeError));
103 RUNTIME_FUNCTION(Runtime_WasmThrowCreate) {
105 HandleScope scope(isolate);
106 DCHECK_EQ(2, args.length());
107 DCHECK(isolate->context().is_null());
108 isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
109 CONVERT_ARG_CHECKED(HeapObject, tag_raw, 0);
110 CONVERT_SMI_ARG_CHECKED(size, 1);
112 Handle<Object> tag(tag_raw, isolate);
113 Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
114 MessageTemplate::kWasmExceptionError);
116 !JSReceiver::SetProperty(isolate, exception,
117 isolate->factory()->wasm_exception_tag_symbol(),
118 tag, LanguageMode::kStrict)
120 Handle<FixedArray> values = isolate->factory()->NewFixedArray(size);
121 CHECK(!JSReceiver::SetProperty(
123 isolate->factory()->wasm_exception_values_symbol(), values,
124 LanguageMode::kStrict)
129 RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
131 HandleScope scope(isolate);
132 DCHECK_EQ(1, args.length());
133 DCHECK(isolate->context().is_null());
134 isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
135 CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
137 Handle<Object> except_obj(except_obj_raw, isolate);
138 if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
139 Handle<JSReceiver> exception(JSReceiver::cast(*except_obj), isolate);
141 if (JSReceiver::GetProperty(isolate, exception,
142 isolate->factory()->wasm_exception_tag_symbol())
147 return ReadOnlyRoots(isolate).undefined_value();
150 RUNTIME_FUNCTION(Runtime_WasmExceptionGetValues) {
152 HandleScope scope(isolate);
153 DCHECK_EQ(1, args.length());
154 DCHECK(isolate->context().is_null());
155 isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
156 CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
158 Handle<Object> except_obj(except_obj_raw, isolate);
159 if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
160 Handle<JSReceiver> exception(JSReceiver::cast(*except_obj), isolate);
161 Handle<Object> values;
162 if (JSReceiver::GetProperty(
164 isolate->factory()->wasm_exception_values_symbol())
165 .ToHandle(&values)) {
166 DCHECK(values->IsFixedArray());
170 return ReadOnlyRoots(isolate).undefined_value();
173 RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
174 DCHECK_EQ(2, args.length());
175 HandleScope scope(isolate);
176 CONVERT_NUMBER_CHECKED(int32_t, func_index, Int32, args[0]);
177 CONVERT_ARG_HANDLE_CHECKED(Object, arg_buffer_obj, 1);
182 CHECK(!arg_buffer_obj->IsHeapObject());
183 CHECK(arg_buffer_obj->IsSmi());
184 Address arg_buffer =
reinterpret_cast<Address
>(*arg_buffer_obj);
186 ClearThreadInWasmScope wasm_flag;
189 Handle<WasmInstanceObject> instance;
190 Address frame_pointer = 0;
192 StackFrameIterator it(isolate, isolate->thread_local_top());
194 DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
197 DCHECK_EQ(StackFrame::WASM_INTERPRETER_ENTRY, it.frame()->type());
199 WasmInterpreterEntryFrame::cast(it.frame())->wasm_instance(), isolate);
200 frame_pointer = it.frame()->fp();
204 DCHECK(isolate->context().is_null());
205 isolate->set_context(instance->native_context());
210 Handle<WasmDebugInfo> debug_info =
211 WasmInstanceObject::GetOrCreateDebugInfo(instance);
212 bool success = WasmDebugInfo::RunInterpreter(
213 isolate, debug_info, frame_pointer, func_index, arg_buffer);
216 DCHECK(isolate->has_pending_exception());
217 return ReadOnlyRoots(isolate).exception();
219 return ReadOnlyRoots(isolate).undefined_value();
222 RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
223 SealHandleScope shs(isolate);
224 DCHECK_EQ(0, args.length());
225 DCHECK(!trap_handler::IsTrapHandlerEnabled() ||
226 trap_handler::IsThreadInWasm());
228 ClearThreadInWasmScope wasm_flag;
231 StackLimitCheck check(isolate);
232 if (check.JsHasOverflowed())
return isolate->StackOverflow();
234 return isolate->stack_guard()->HandleInterrupts();
237 RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
238 HandleScope scope(isolate);
239 DCHECK_EQ(2, args.length());
240 CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
241 CONVERT_SMI_ARG_CHECKED(func_index, 1);
243 ClearThreadInWasmScope wasm_flag;
246 StackFrameIterator it(isolate, isolate->thread_local_top());
248 DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
251 DCHECK_EQ(StackFrame::WASM_COMPILE_LAZY, it.frame()->type());
252 DCHECK_EQ(*instance, WasmCompileLazyFrame::cast(it.frame())->wasm_instance());
255 Address entrypoint = wasm::CompileLazy(
256 isolate, instance->module_object()->native_module(), func_index);
257 return reinterpret_cast<Object*
>(entrypoint);
261 Handle<JSArrayBuffer> getSharedArrayBuffer(Handle<WasmInstanceObject> instance,
262 Isolate* isolate,
uint32_t address) {
263 DCHECK(instance->has_memory_object());
264 Handle<JSArrayBuffer> array_buffer(instance->memory_object()->array_buffer(),
268 DCHECK(array_buffer->is_shared());
271 DCHECK_LT(address, array_buffer->byte_length());
275 RUNTIME_FUNCTION(Runtime_WasmAtomicWake) {
276 HandleScope scope(isolate);
277 DCHECK_EQ(3, args.length());
278 CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
279 CONVERT_NUMBER_CHECKED(
uint32_t, address, Uint32, args[1]);
280 CONVERT_NUMBER_CHECKED(
uint32_t, count, Uint32, args[2]);
281 Handle<JSArrayBuffer> array_buffer =
282 getSharedArrayBuffer(instance, isolate, address);
283 return FutexEmulation::Wake(array_buffer, address, count);
286 RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) {
287 HandleScope scope(isolate);
288 DCHECK_EQ(4, args.length());
289 CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
290 CONVERT_NUMBER_CHECKED(
uint32_t, address, Uint32, args[1]);
291 CONVERT_NUMBER_CHECKED(int32_t, expected_value, Int32, args[2]);
292 CONVERT_DOUBLE_ARG_CHECKED(timeout, 3);
293 timeout = timeout < 0 ? V8_INFINITY
294 : timeout / (base::Time::kNanosecondsPerMicrosecond *
295 base::Time::kMicrosecondsPerMillisecond);
296 Handle<JSArrayBuffer> array_buffer =
297 getSharedArrayBuffer(instance, isolate, address);
298 return FutexEmulation::Wait(isolate, array_buffer, address, expected_value,