LCOV - code coverage report
Current view: top level - src/runtime - runtime-wasm.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 158 159 99.4 %
Date: 2019-03-21 Functions: 26 47 55.3 %

          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

Generated by: LCOV version 1.10