Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
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"
23 :
24 : namespace v8 {
25 : namespace internal {
26 :
27 : namespace {
28 :
29 4296 : WasmInstanceObject GetWasmInstanceOnStackTop(Isolate* isolate) {
30 4296 : StackFrameIterator it(isolate, isolate->thread_local_top());
31 : // On top: C entry stub.
32 : DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
33 4296 : it.Advance();
34 : // Next: the wasm compiled frame.
35 : DCHECK(it.frame()->is_wasm_compiled());
36 : WasmCompiledFrame* frame = WasmCompiledFrame::cast(it.frame());
37 8592 : return frame->wasm_instance();
38 : }
39 :
40 2232 : Context GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
41 4464 : return GetWasmInstanceOnStackTop(isolate)->native_context();
42 : }
43 :
44 : class ClearThreadInWasmScope {
45 : public:
46 : ClearThreadInWasmScope() {
47 : DCHECK_EQ(trap_handler::IsTrapHandlerEnabled(),
48 : trap_handler::IsThreadInWasm());
49 : trap_handler::ClearThreadInWasm();
50 : }
51 : ~ClearThreadInWasmScope() {
52 : DCHECK(!trap_handler::IsThreadInWasm());
53 : trap_handler::SetThreadInWasm();
54 : }
55 : };
56 :
57 148735 : Object ThrowWasmError(Isolate* isolate, MessageTemplate message) {
58 : HandleScope scope(isolate);
59 148735 : Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(message);
60 297470 : return isolate->Throw(*error_obj);
61 : }
62 : } // namespace
63 :
64 384 : RUNTIME_FUNCTION(Runtime_WasmIsValidAnyFuncValue) {
65 : HandleScope scope(isolate);
66 : DCHECK_EQ(1, args.length());
67 : CONVERT_ARG_HANDLE_CHECKED(Object, function, 0);
68 :
69 192 : if (function->IsNull(isolate)) {
70 : return Smi::FromInt(true);
71 : }
72 184 : if (WasmExportedFunction::IsWasmExportedFunction(*function)) {
73 : return Smi::FromInt(true);
74 : }
75 : return Smi::FromInt(false);
76 : }
77 :
78 3984 : RUNTIME_FUNCTION(Runtime_WasmMemoryGrow) {
79 : HandleScope scope(isolate);
80 : DCHECK_EQ(2, args.length());
81 1992 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
82 : // {delta_pages} is checked to be a positive smi in the WasmMemoryGrow builtin
83 : // which calls this runtime function.
84 3984 : CONVERT_UINT32_ARG_CHECKED(delta_pages, 1);
85 :
86 : // This runtime function is always being called from wasm code.
87 : ClearThreadInWasmScope flag_scope;
88 :
89 1992 : int ret = WasmMemoryObject::Grow(
90 1992 : isolate, handle(instance->memory_object(), isolate), delta_pages);
91 : // The WasmMemoryGrow builtin which calls this runtime function expects us to
92 : // always return a Smi.
93 : return Smi::FromInt(ret);
94 : }
95 :
96 297342 : RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
97 : ClearThreadInWasmScope clear_wasm_flag;
98 : DCHECK_EQ(1, args.length());
99 148671 : CONVERT_SMI_ARG_CHECKED(message_id, 0);
100 148671 : return ThrowWasmError(isolate, MessageTemplateFromInt(message_id));
101 : }
102 :
103 120 : RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
104 : SealHandleScope shs(isolate);
105 : DCHECK_LE(0, args.length());
106 60 : return isolate->StackOverflow();
107 : }
108 :
109 256 : RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) {
110 : HandleScope scope(isolate);
111 : DCHECK_EQ(0, args.length());
112 256 : THROW_NEW_ERROR_RETURN_FAILURE(
113 : isolate, NewTypeError(MessageTemplate::kWasmTrapTypeError));
114 : }
115 :
116 1408 : RUNTIME_FUNCTION(Runtime_WasmThrowCreate) {
117 : // TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
118 : HandleScope scope(isolate);
119 : DCHECK_EQ(2, args.length());
120 : DCHECK(isolate->context().is_null());
121 704 : isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
122 704 : CONVERT_ARG_CHECKED(WasmExceptionTag, tag_raw, 0);
123 704 : CONVERT_SMI_ARG_CHECKED(size, 1);
124 : // TODO(mstarzinger): Manually box because parameters are not visited yet.
125 : Handle<Object> tag(tag_raw, isolate);
126 : Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
127 704 : MessageTemplate::kWasmExceptionError);
128 2112 : CHECK(!Object::SetProperty(isolate, exception,
129 : isolate->factory()->wasm_exception_tag_symbol(),
130 : tag, StoreOrigin::kMaybeKeyed,
131 : Just(ShouldThrow::kThrowOnError))
132 : .is_null());
133 704 : Handle<FixedArray> values = isolate->factory()->NewFixedArray(size);
134 2112 : CHECK(!Object::SetProperty(isolate, exception,
135 : isolate->factory()->wasm_exception_values_symbol(),
136 : values, StoreOrigin::kMaybeKeyed,
137 : Just(ShouldThrow::kThrowOnError))
138 : .is_null());
139 : return *exception;
140 : }
141 :
142 960 : RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
143 : // TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
144 : HandleScope scope(isolate);
145 : DCHECK_EQ(1, args.length());
146 : DCHECK(isolate->context().is_null());
147 480 : isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
148 : CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
149 : // TODO(mstarzinger): Manually box because parameters are not visited yet.
150 : Handle<Object> except_obj(except_obj_raw, isolate);
151 960 : return *WasmExceptionPackage::GetExceptionTag(isolate, except_obj);
152 : }
153 :
154 2096 : RUNTIME_FUNCTION(Runtime_WasmExceptionGetValues) {
155 : // TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
156 : HandleScope scope(isolate);
157 : DCHECK_EQ(1, args.length());
158 : DCHECK(isolate->context().is_null());
159 1048 : isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
160 : CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
161 : // TODO(mstarzinger): Manually box because parameters are not visited yet.
162 : Handle<Object> except_obj(except_obj_raw, isolate);
163 2096 : return *WasmExceptionPackage::GetExceptionValues(isolate, except_obj);
164 : }
165 :
166 68746 : RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
167 : DCHECK_EQ(2, args.length());
168 : HandleScope scope(isolate);
169 68746 : CONVERT_NUMBER_CHECKED(int32_t, func_index, Int32, args[0]);
170 : CONVERT_ARG_HANDLE_CHECKED(Object, arg_buffer_obj, 1);
171 :
172 : // The arg buffer is the raw pointer to the caller's stack. It looks like a
173 : // Smi (lowest bit not set, as checked by IsSmi), but is no valid Smi. We just
174 : // cast it back to the raw pointer.
175 34373 : CHECK(!arg_buffer_obj->IsHeapObject());
176 34373 : CHECK(arg_buffer_obj->IsSmi());
177 : Address arg_buffer = arg_buffer_obj->ptr();
178 :
179 : ClearThreadInWasmScope wasm_flag;
180 :
181 : // Find the frame pointer and instance of the interpreter frame on the stack.
182 : Handle<WasmInstanceObject> instance;
183 : Address frame_pointer = 0;
184 : {
185 68746 : StackFrameIterator it(isolate, isolate->thread_local_top());
186 : // On top: C entry stub.
187 : DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
188 34373 : it.Advance();
189 : // Next: the wasm interpreter entry.
190 : DCHECK_EQ(StackFrame::WASM_INTERPRETER_ENTRY, it.frame()->type());
191 : instance = handle(
192 34373 : WasmInterpreterEntryFrame::cast(it.frame())->wasm_instance(), isolate);
193 : frame_pointer = it.frame()->fp();
194 : }
195 :
196 : // Set the current isolate's context.
197 : DCHECK(isolate->context().is_null());
198 : isolate->set_context(instance->native_context());
199 :
200 : // Run the function in the interpreter. Note that neither the {WasmDebugInfo}
201 : // nor the {InterpreterHandle} have to exist, because interpretation might
202 : // have been triggered by another Isolate sharing the same WasmEngine.
203 : Handle<WasmDebugInfo> debug_info =
204 34373 : WasmInstanceObject::GetOrCreateDebugInfo(instance);
205 : bool success = WasmDebugInfo::RunInterpreter(
206 34373 : isolate, debug_info, frame_pointer, func_index, arg_buffer);
207 :
208 34373 : if (!success) {
209 : DCHECK(isolate->has_pending_exception());
210 : return ReadOnlyRoots(isolate).exception();
211 : }
212 : return ReadOnlyRoots(isolate).undefined_value();
213 : }
214 :
215 322 : RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
216 : SealHandleScope shs(isolate);
217 : DCHECK_EQ(0, args.length());
218 : DCHECK(!trap_handler::IsTrapHandlerEnabled() ||
219 : trap_handler::IsThreadInWasm());
220 :
221 : ClearThreadInWasmScope wasm_flag;
222 :
223 : // Check if this is a real stack overflow.
224 : StackLimitCheck check(isolate);
225 161 : if (check.JsHasOverflowed()) return isolate->StackOverflow();
226 :
227 53 : return isolate->stack_guard()->HandleInterrupts();
228 : }
229 :
230 16124 : RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
231 : HandleScope scope(isolate);
232 : DCHECK_EQ(2, args.length());
233 8062 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
234 8062 : CONVERT_SMI_ARG_CHECKED(func_index, 1);
235 :
236 : ClearThreadInWasmScope wasm_flag;
237 :
238 : #ifdef DEBUG
239 : StackFrameIterator it(isolate, isolate->thread_local_top());
240 : // On top: C entry stub.
241 : DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
242 : it.Advance();
243 : // Next: the wasm lazy compile frame.
244 : DCHECK_EQ(StackFrame::WASM_COMPILE_LAZY, it.frame()->type());
245 : DCHECK_EQ(*instance, WasmCompileLazyFrame::cast(it.frame())->wasm_instance());
246 : #endif
247 :
248 8062 : auto* native_module = instance->module_object()->native_module();
249 8062 : wasm::CompileLazy(isolate, native_module, func_index);
250 :
251 8062 : Address entrypoint = native_module->GetCallTargetForFunction(func_index);
252 : return Object(entrypoint);
253 : }
254 :
255 : // Should be called from within a handle scope
256 654 : Handle<JSArrayBuffer> getSharedArrayBuffer(Handle<WasmInstanceObject> instance,
257 : Isolate* isolate, uint32_t address) {
258 : DCHECK(instance->has_memory_object());
259 : Handle<JSArrayBuffer> array_buffer(instance->memory_object()->array_buffer(),
260 : isolate);
261 :
262 : // Validation should have failed if the memory was not shared.
263 : DCHECK(array_buffer->is_shared());
264 :
265 : // Should have trapped if address was OOB
266 : DCHECK_LT(address, array_buffer->byte_length());
267 654 : return array_buffer;
268 : }
269 :
270 272 : RUNTIME_FUNCTION(Runtime_WasmAtomicNotify) {
271 : HandleScope scope(isolate);
272 : DCHECK_EQ(3, args.length());
273 136 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
274 272 : CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
275 272 : CONVERT_NUMBER_CHECKED(uint32_t, count, Uint32, args[2]);
276 : Handle<JSArrayBuffer> array_buffer =
277 136 : getSharedArrayBuffer(instance, isolate, address);
278 136 : return FutexEmulation::Wake(array_buffer, address, count);
279 : }
280 :
281 0 : double WaitTimeoutInMs(double timeout_ns) {
282 : return timeout_ns < 0
283 : ? V8_INFINITY
284 : : timeout_ns / (base::Time::kNanosecondsPerMicrosecond *
285 519 : base::Time::kMicrosecondsPerMillisecond);
286 : }
287 :
288 520 : RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) {
289 : HandleScope scope(isolate);
290 : DCHECK_EQ(4, args.length());
291 260 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
292 520 : CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
293 520 : CONVERT_NUMBER_CHECKED(int32_t, expected_value, Int32, args[2]);
294 260 : CONVERT_DOUBLE_ARG_CHECKED(timeout_ns, 3);
295 : double timeout_ms = WaitTimeoutInMs(timeout_ns);
296 : Handle<JSArrayBuffer> array_buffer =
297 260 : getSharedArrayBuffer(instance, isolate, address);
298 : return FutexEmulation::Wait32(isolate, array_buffer, address, expected_value,
299 259 : timeout_ms);
300 : }
301 :
302 520 : RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) {
303 : HandleScope scope(isolate);
304 : DCHECK_EQ(5, args.length());
305 260 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
306 520 : CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
307 520 : CONVERT_NUMBER_CHECKED(uint32_t, expected_value_high, Uint32, args[2]);
308 516 : CONVERT_NUMBER_CHECKED(uint32_t, expected_value_low, Uint32, args[3]);
309 259 : CONVERT_DOUBLE_ARG_CHECKED(timeout_ns, 4);
310 259 : int64_t expected_value = (static_cast<uint64_t>(expected_value_high) << 32) |
311 259 : static_cast<uint64_t>(expected_value_low);
312 : double timeout_ms = WaitTimeoutInMs(timeout_ns);
313 : Handle<JSArrayBuffer> array_buffer =
314 259 : getSharedArrayBuffer(instance, isolate, address);
315 : return FutexEmulation::Wait64(isolate, array_buffer, address, expected_value,
316 259 : timeout_ms);
317 : }
318 :
319 : namespace {
320 1464 : Object ThrowTableOutOfBounds(Isolate* isolate,
321 : Handle<WasmInstanceObject> instance) {
322 : // Handle out-of-bounds access here in the runtime call, rather
323 : // than having the lower-level layers deal with JS exceptions.
324 1464 : if (isolate->context().is_null()) {
325 : isolate->set_context(instance->native_context());
326 : }
327 : Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
328 1464 : MessageTemplate::kWasmTrapTableOutOfBounds);
329 1464 : return isolate->Throw(*error_obj);
330 : }
331 : } // namespace
332 :
333 240 : RUNTIME_FUNCTION(Runtime_WasmFunctionTableGet) {
334 : // This runtime function is always being called from wasm code.
335 : ClearThreadInWasmScope flag_scope;
336 :
337 : HandleScope scope(isolate);
338 : DCHECK_EQ(3, args.length());
339 120 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
340 240 : CONVERT_UINT32_ARG_CHECKED(table_index, 1);
341 240 : CONVERT_UINT32_ARG_CHECKED(entry_index, 2);
342 : DCHECK_LT(table_index, instance->tables()->length());
343 : auto table = handle(
344 240 : WasmTableObject::cast(instance->tables()->get(table_index)), isolate);
345 :
346 120 : if (!WasmTableObject::IsInBounds(isolate, table, entry_index)) {
347 16 : return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
348 : }
349 :
350 208 : return *WasmTableObject::Get(isolate, table, entry_index);
351 : }
352 :
353 80 : RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) {
354 : // This runtime function is always being called from wasm code.
355 : ClearThreadInWasmScope flag_scope;
356 :
357 : HandleScope scope(isolate);
358 : DCHECK_EQ(4, args.length());
359 40 : CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
360 80 : CONVERT_UINT32_ARG_CHECKED(table_index, 1);
361 80 : CONVERT_UINT32_ARG_CHECKED(entry_index, 2);
362 : CONVERT_ARG_CHECKED(Object, element_raw, 3);
363 : // TODO(mstarzinger): Manually box because parameters are not visited yet.
364 : Handle<Object> element(element_raw, isolate);
365 : DCHECK_LT(table_index, instance->tables()->length());
366 : auto table = handle(
367 80 : WasmTableObject::cast(instance->tables()->get(table_index)), isolate);
368 :
369 40 : if (!WasmTableObject::IsInBounds(isolate, table, entry_index)) {
370 16 : return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
371 : }
372 24 : WasmTableObject::Set(isolate, table, entry_index, element);
373 : return ReadOnlyRoots(isolate).undefined_value();
374 : }
375 :
376 304 : RUNTIME_FUNCTION(Runtime_WasmIndirectCallCheckSignatureAndGetTargetInstance) {
377 : HandleScope scope(isolate);
378 : DCHECK_EQ(3, args.length());
379 : auto instance =
380 152 : Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
381 304 : CONVERT_UINT32_ARG_CHECKED(table_index, 0);
382 304 : CONVERT_UINT32_ARG_CHECKED(entry_index, 1);
383 304 : CONVERT_UINT32_ARG_CHECKED(sig_index, 2);
384 : DCHECK(isolate->context().is_null());
385 : isolate->set_context(instance->native_context());
386 :
387 : DCHECK_LT(table_index, instance->tables()->length());
388 : auto table_obj = handle(
389 304 : WasmTableObject::cast(instance->tables()->get(table_index)), isolate);
390 :
391 : // This check is already done in generated code.
392 : DCHECK(WasmTableObject::IsInBounds(isolate, table_obj, entry_index));
393 :
394 : bool is_valid;
395 : bool is_null;
396 152 : MaybeHandle<WasmInstanceObject> maybe_target_instance;
397 : int function_index;
398 152 : WasmTableObject::GetFunctionTableEntry(
399 : isolate, table_obj, entry_index, &is_valid, &is_null,
400 152 : &maybe_target_instance, &function_index);
401 :
402 152 : CHECK(is_valid);
403 152 : if (is_null) {
404 : // We throw a signature mismatch trap to be in sync with the generated
405 : // code. There we do a signature check instead of a null-check. Trap
406 : // reasons are not defined in the spec. Otherwise, a null-check is
407 : // performed before a signature, according to the spec.
408 16 : return ThrowWasmError(isolate, MessageTemplate::kWasmTrapFuncSigMismatch);
409 : }
410 :
411 : // Now we do the signature check.
412 : Handle<WasmInstanceObject> target_instance =
413 : maybe_target_instance.ToHandleChecked();
414 :
415 : const wasm::WasmModule* target_module =
416 136 : target_instance->module_object()->native_module()->module();
417 :
418 272 : wasm::FunctionSig* target_sig = target_module->functions[function_index].sig;
419 :
420 136 : auto target_sig_id = instance->module()->signature_map.Find(*target_sig);
421 408 : uint32_t expected_sig_id = instance->module()->signature_ids[sig_index];
422 :
423 136 : if (expected_sig_id != static_cast<uint32_t>(target_sig_id)) {
424 16 : return ThrowWasmError(isolate, MessageTemplate::kWasmTrapFuncSigMismatch);
425 : }
426 :
427 240 : if (function_index <
428 240 : static_cast<int>(target_instance->module()->num_imported_functions)) {
429 : // The function in the target instance was imported. Use its imports table,
430 : // which contains a tuple needed by the import wrapper.
431 : ImportedFunctionEntry entry(target_instance, function_index);
432 8 : return entry.object_ref();
433 : }
434 : return *target_instance;
435 : }
436 :
437 240 : RUNTIME_FUNCTION(Runtime_WasmIndirectCallGetTargetAddress) {
438 : HandleScope scope(isolate);
439 : DCHECK_EQ(2, args.length());
440 : auto instance =
441 120 : Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
442 240 : CONVERT_UINT32_ARG_CHECKED(table_index, 0);
443 240 : CONVERT_UINT32_ARG_CHECKED(entry_index, 1);
444 :
445 : DCHECK_LT(table_index, instance->tables()->length());
446 : auto table_obj = handle(
447 240 : WasmTableObject::cast(instance->tables()->get(table_index)), isolate);
448 :
449 : DCHECK(WasmTableObject::IsInBounds(isolate, table_obj, entry_index));
450 :
451 : bool is_valid;
452 : bool is_null;
453 120 : MaybeHandle<WasmInstanceObject> maybe_target_instance;
454 : int function_index;
455 120 : WasmTableObject::GetFunctionTableEntry(
456 : isolate, table_obj, entry_index, &is_valid, &is_null,
457 120 : &maybe_target_instance, &function_index);
458 :
459 120 : CHECK(is_valid);
460 : // The null-check should already have been done in
461 : // Runtime_WasmIndirectCallCheckSignatureAndGetTargetInstance. That runtime
462 : // function should always be called first.
463 120 : CHECK(!is_null);
464 :
465 : Handle<WasmInstanceObject> target_instance =
466 : maybe_target_instance.ToHandleChecked();
467 :
468 : Address call_target = 0;
469 240 : if (function_index <
470 240 : static_cast<int>(target_instance->module()->num_imported_functions)) {
471 : // The function in the target instance was imported. Use its imports table,
472 : // which contains a tuple needed by the import wrapper.
473 : ImportedFunctionEntry entry(target_instance, function_index);
474 8 : call_target = entry.target();
475 : } else {
476 : // The function in the target instance was not imported.
477 224 : call_target = target_instance->GetCallTarget(function_index);
478 : }
479 :
480 : // The return value is an address and not a SMI. However, the address is
481 : // always aligned, and a SMI uses the same space as {Address}.
482 120 : CHECK(HAS_SMI_TAG(call_target));
483 : return Smi(call_target);
484 : }
485 :
486 464 : RUNTIME_FUNCTION(Runtime_WasmTableInit) {
487 : HandleScope scope(isolate);
488 : DCHECK_EQ(5, args.length());
489 : auto instance =
490 232 : Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
491 464 : CONVERT_UINT32_ARG_CHECKED(table_index, 0);
492 464 : CONVERT_UINT32_ARG_CHECKED(elem_segment_index, 1);
493 464 : CONVERT_UINT32_ARG_CHECKED(dst, 2);
494 464 : CONVERT_UINT32_ARG_CHECKED(src, 3);
495 464 : CONVERT_UINT32_ARG_CHECKED(count, 4);
496 :
497 : DCHECK(isolate->context().is_null());
498 : isolate->set_context(instance->native_context());
499 :
500 232 : bool oob = !WasmInstanceObject::InitTableEntries(
501 : isolate, instance, table_index, elem_segment_index, dst, src, count);
502 232 : if (oob) return ThrowTableOutOfBounds(isolate, instance);
503 : return ReadOnlyRoots(isolate).undefined_value();
504 : }
505 :
506 3120 : RUNTIME_FUNCTION(Runtime_WasmTableCopy) {
507 : HandleScope scope(isolate);
508 : DCHECK_EQ(5, args.length());
509 : auto instance =
510 1560 : Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
511 3120 : CONVERT_UINT32_ARG_CHECKED(table_src_index, 0);
512 3120 : CONVERT_UINT32_ARG_CHECKED(table_dst_index, 1);
513 3120 : CONVERT_UINT32_ARG_CHECKED(dst, 2);
514 3120 : CONVERT_UINT32_ARG_CHECKED(src, 3);
515 3120 : CONVERT_UINT32_ARG_CHECKED(count, 4);
516 :
517 1560 : bool oob = !WasmInstanceObject::CopyTableEntries(
518 : isolate, instance, table_src_index, table_dst_index, dst, src, count);
519 1560 : if (oob) return ThrowTableOutOfBounds(isolate, instance);
520 : return ReadOnlyRoots(isolate).undefined_value();
521 : }
522 : } // namespace internal
523 120216 : } // namespace v8
|