LCOV - code coverage report
Current view: top level - src/runtime - runtime-wasm.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 89 92 96.7 %
Date: 2017-04-26 Functions: 17 31 54.8 %

          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/runtime/runtime-utils.h"
       6             : 
       7             : #include "src/arguments.h"
       8             : #include "src/assembler.h"
       9             : #include "src/compiler/wasm-compiler.h"
      10             : #include "src/conversions.h"
      11             : #include "src/debug/debug.h"
      12             : #include "src/factory.h"
      13             : #include "src/frames-inl.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/frame-array-inl.h"
      16             : #include "src/trap-handler/trap-handler.h"
      17             : #include "src/v8memory.h"
      18             : #include "src/wasm/wasm-module.h"
      19             : #include "src/wasm/wasm-objects.h"
      20             : #include "src/wasm/wasm-opcodes.h"
      21             : 
      22             : namespace v8 {
      23             : namespace internal {
      24             : 
      25             : namespace {
      26       85150 : WasmInstanceObject* GetWasmInstanceOnStackTop(Isolate* isolate) {
      27             :   DisallowHeapAllocation no_allocation;
      28       42575 :   const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
      29             :   Address pc =
      30       42575 :       Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset);
      31       42575 :   Code* code = isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
      32             :   DCHECK_EQ(Code::WASM_FUNCTION, code->kind());
      33       42575 :   WasmInstanceObject* owning_instance = wasm::GetOwningWasmInstance(code);
      34       42575 :   CHECK_NOT_NULL(owning_instance);
      35       42575 :   return owning_instance;
      36             : }
      37       36733 : Context* GetWasmContextOnStackTop(Isolate* isolate) {
      38             :   return GetWasmInstanceOnStackTop(isolate)
      39             :       ->compiled_module()
      40       73466 :       ->ptr_to_native_context();
      41             : }
      42             : }  // namespace
      43             : 
      44        9168 : RUNTIME_FUNCTION(Runtime_WasmMemorySize) {
      45        4584 :   HandleScope scope(isolate);
      46             :   DCHECK_EQ(0, args.length());
      47             : 
      48        4584 :   int32_t mem_size = GetWasmInstanceOnStackTop(isolate)->GetMemorySize();
      49        9168 :   return *isolate->factory()->NewNumberFromInt(mem_size);
      50             : }
      51             : 
      52        2516 : RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
      53        1258 :   HandleScope scope(isolate);
      54             :   DCHECK_EQ(1, args.length());
      55        2516 :   CONVERT_UINT32_ARG_CHECKED(delta_pages, 0);
      56             :   Handle<WasmInstanceObject> instance(GetWasmInstanceOnStackTop(isolate),
      57        1258 :                                       isolate);
      58             : 
      59             :   // Set the current isolate's context.
      60             :   DCHECK_NULL(isolate->context());
      61        1258 :   isolate->set_context(instance->compiled_module()->ptr_to_native_context());
      62             : 
      63             :   return *isolate->factory()->NewNumberFromInt(
      64        2516 :       WasmInstanceObject::GrowMemory(isolate, instance, delta_pages));
      65             : }
      66             : 
      67       36123 : Object* ThrowRuntimeError(Isolate* isolate, int message_id, int byte_offset,
      68             :                           bool patch_source_position) {
      69             :   HandleScope scope(isolate);
      70             :   DCHECK_NULL(isolate->context());
      71       36123 :   isolate->set_context(GetWasmContextOnStackTop(isolate));
      72             :   Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
      73       36123 :       static_cast<MessageTemplate::Template>(message_id));
      74             : 
      75       36123 :   if (!patch_source_position) {
      76       33933 :     return isolate->Throw(*error_obj);
      77             :   }
      78             : 
      79             :   // For wasm traps, the byte offset (a.k.a source position) can not be
      80             :   // determined from relocation info, since the explicit checks for traps
      81             :   // converge in one singe block which calls this runtime function.
      82             :   // We hence pass the byte offset explicitely, and patch it into the top-most
      83             :   // frame (a wasm frame) on the collected stack trace.
      84             :   // TODO(wasm): This implementation is temporary, see bug #5007:
      85             :   // https://bugs.chromium.org/p/v8/issues/detail?id=5007
      86             :   Handle<JSObject> error = Handle<JSObject>::cast(error_obj);
      87             :   Handle<Object> stack_trace_obj = JSReceiver::GetDataProperty(
      88        2190 :       error, isolate->factory()->stack_trace_symbol());
      89             :   // Patch the stack trace (array of <receiver, function, code, position>).
      90        2190 :   if (stack_trace_obj->IsJSArray()) {
      91             :     Handle<FrameArray> stack_elements(
      92             :         FrameArray::cast(JSArray::cast(*stack_trace_obj)->elements()));
      93             :     DCHECK(stack_elements->Code(0)->kind() == AbstractCode::WASM_FUNCTION);
      94             :     DCHECK(stack_elements->Offset(0)->value() >= 0);
      95        2190 :     stack_elements->SetOffset(0, Smi::FromInt(-1 - byte_offset));
      96             :   }
      97             : 
      98             :   // Patch the detailed stack trace (array of JSObjects with various
      99             :   // properties).
     100             :   Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty(
     101        2190 :       error, isolate->factory()->detailed_stack_trace_symbol());
     102        2190 :   if (detailed_stack_trace_obj->IsFixedArray()) {
     103             :     Handle<FixedArray> stack_elements(
     104             :         FixedArray::cast(*detailed_stack_trace_obj));
     105             :     DCHECK_GE(stack_elements->length(), 1);
     106             :     Handle<StackFrameInfo> top_frame(
     107             :         StackFrameInfo::cast(stack_elements->get(0)));
     108           1 :     if (top_frame->column_number()) {
     109           1 :       top_frame->set_column_number(byte_offset + 1);
     110             :     }
     111             :   }
     112             : 
     113        2190 :   return isolate->Throw(*error_obj);
     114             : }
     115             : 
     116       67866 : RUNTIME_FUNCTION(Runtime_ThrowWasmErrorFromTrapIf) {
     117             :   DCHECK_EQ(1, args.length());
     118       67866 :   CONVERT_SMI_ARG_CHECKED(message_id, 0);
     119       33933 :   return ThrowRuntimeError(isolate, message_id, 0, false);
     120             : }
     121             : 
     122        4380 : RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
     123             :   DCHECK_EQ(2, args.length());
     124        4380 :   CONVERT_SMI_ARG_CHECKED(message_id, 0);
     125        4380 :   CONVERT_SMI_ARG_CHECKED(byte_offset, 1);
     126        2190 :   return ThrowRuntimeError(isolate, message_id, byte_offset, true);
     127             : }
     128             : 
     129           0 : RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
     130             :   SealHandleScope shs(isolate);
     131             :   DCHECK_LE(0, args.length());
     132             :   DCHECK_NULL(isolate->context());
     133           0 :   isolate->set_context(GetWasmContextOnStackTop(isolate));
     134           0 :   return isolate->StackOverflow();
     135             : }
     136             : 
     137         210 : RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) {
     138         105 :   HandleScope scope(isolate);
     139             :   DCHECK_EQ(0, args.length());
     140         210 :   THROW_NEW_ERROR_RETURN_FAILURE(
     141         105 :       isolate, NewTypeError(MessageTemplate::kWasmTrapTypeError));
     142             : }
     143             : 
     144         720 : RUNTIME_FUNCTION(Runtime_WasmThrow) {
     145         360 :   HandleScope scope(isolate);
     146             :   DCHECK_EQ(2, args.length());
     147         720 :   CONVERT_SMI_ARG_CHECKED(lower, 0);
     148         720 :   CONVERT_SMI_ARG_CHECKED(upper, 1);
     149             : 
     150         360 :   const int32_t thrown_value = (upper << 16) | lower;
     151             : 
     152             :   // Set the current isolate's context.
     153             :   DCHECK_NULL(isolate->context());
     154         360 :   isolate->set_context(GetWasmContextOnStackTop(isolate));
     155             : 
     156         720 :   return isolate->Throw(*isolate->factory()->NewNumberFromInt(thrown_value));
     157             : }
     158             : 
     159         630 : RUNTIME_FUNCTION(Runtime_WasmGetCaughtExceptionValue) {
     160         315 :   HandleScope scope(isolate);
     161             :   DCHECK_EQ(1, args.length());
     162         315 :   Object* exception = args[0];
     163             :   // The unwinder will only deliver exceptions to wasm if the exception is a
     164             :   // Number or a Smi (which we have just converted to a Number.) This logic
     165             :   // lives in Isolate::is_catchable_by_wasm(Object*).
     166         315 :   CHECK(exception->IsNumber());
     167         315 :   return exception;
     168             : }
     169             : 
     170     6694422 : RUNTIME_FUNCTION(Runtime_SetThreadInWasm) {
     171     3347211 :   trap_handler::SetThreadInWasm();
     172     3347211 :   return isolate->heap()->undefined_value();
     173             : }
     174             : 
     175     6689592 : RUNTIME_FUNCTION(Runtime_ClearThreadInWasm) {
     176     3344796 :   trap_handler::ClearThreadInWasm();
     177     3344796 :   return isolate->heap()->undefined_value();
     178             : }
     179             : 
     180      102850 : RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
     181             :   DCHECK_EQ(3, args.length());
     182       51425 :   HandleScope scope(isolate);
     183      102850 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
     184      102850 :   CONVERT_NUMBER_CHECKED(int32_t, func_index, Int32, args[1]);
     185       51425 :   CONVERT_ARG_HANDLE_CHECKED(Object, arg_buffer_obj, 2);
     186       51425 :   CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
     187             :   Handle<WasmInstanceObject> instance =
     188       51425 :       Handle<WasmInstanceObject>::cast(instance_obj);
     189             : 
     190             :   // The arg buffer is the raw pointer to the caller's stack. It looks like a
     191             :   // Smi (lowest bit not set, as checked by IsSmi), but is no valid Smi. We just
     192             :   // cast it back to the raw pointer.
     193       51425 :   CHECK(!arg_buffer_obj->IsHeapObject());
     194       51425 :   CHECK(arg_buffer_obj->IsSmi());
     195             :   uint8_t* arg_buffer = reinterpret_cast<uint8_t*>(*arg_buffer_obj);
     196             : 
     197             :   // Set the current isolate's context.
     198             :   DCHECK_NULL(isolate->context());
     199       51425 :   isolate->set_context(instance->compiled_module()->ptr_to_native_context());
     200             : 
     201             :   // Find the frame pointer of the interpreter entry.
     202             :   Address frame_pointer = 0;
     203             :   {
     204       51425 :     StackFrameIterator it(isolate, isolate->thread_local_top());
     205             :     // On top: C entry stub.
     206             :     DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
     207       51425 :     it.Advance();
     208             :     // Next: the wasm interpreter entry.
     209             :     DCHECK_EQ(StackFrame::WASM_INTERPRETER_ENTRY, it.frame()->type());
     210       51425 :     frame_pointer = it.frame()->fp();
     211             :   }
     212             : 
     213             :   bool success = instance->debug_info()->RunInterpreter(frame_pointer,
     214       51425 :                                                         func_index, arg_buffer);
     215             : 
     216       51425 :   if (!success) {
     217             :     DCHECK(isolate->has_pending_exception());
     218         225 :     return isolate->heap()->exception();
     219             :   }
     220       51200 :   return isolate->heap()->undefined_value();
     221             : }
     222             : 
     223         500 : RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
     224             :   SealHandleScope shs(isolate);
     225             :   DCHECK_EQ(0, args.length());
     226             :   DCHECK(!trap_handler::UseTrapHandler() || trap_handler::IsThreadInWasm());
     227             : 
     228             :   struct ClearAndRestoreThreadInWasm {
     229         500 :     ClearAndRestoreThreadInWasm() { trap_handler::ClearThreadInWasm(); }
     230             : 
     231         500 :     ~ClearAndRestoreThreadInWasm() { trap_handler::SetThreadInWasm(); }
     232         500 :   } restore_thread_in_wasm;
     233             : 
     234             :   // Set the current isolate's context.
     235             :   DCHECK_NULL(isolate->context());
     236         250 :   isolate->set_context(GetWasmContextOnStackTop(isolate));
     237             : 
     238             :   // Check if this is a real stack overflow.
     239         250 :   StackLimitCheck check(isolate);
     240         250 :   if (check.JsHasOverflowed()) return isolate->StackOverflow();
     241             : 
     242         188 :   return isolate->stack_guard()->HandleInterrupts();
     243             : }
     244             : 
     245       25398 : RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
     246             :   DCHECK(args.length() == 0);
     247       12699 :   HandleScope scope(isolate);
     248             : 
     249       25398 :   return *wasm::CompileLazy(isolate);
     250             : }
     251             : 
     252             : }  // namespace internal
     253             : }  // namespace v8

Generated by: LCOV version 1.10