LCOV - code coverage report
Current view: top level - test/common/wasm - wasm-module-runner.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 62 87 71.3 %
Date: 2017-10-20 Functions: 8 10 80.0 %

          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 "test/common/wasm/wasm-module-runner.h"
       6             : 
       7             : #include "src/handles.h"
       8             : #include "src/isolate.h"
       9             : #include "src/objects-inl.h"
      10             : #include "src/objects.h"
      11             : #include "src/property-descriptor.h"
      12             : #include "src/wasm/module-compiler.h"
      13             : #include "src/wasm/module-decoder.h"
      14             : #include "src/wasm/wasm-interpreter.h"
      15             : #include "src/wasm/wasm-js.h"
      16             : #include "src/wasm/wasm-module.h"
      17             : #include "src/wasm/wasm-objects.h"
      18             : #include "src/wasm/wasm-result.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : namespace testing {
      24             : 
      25           0 : uint32_t GetInitialMemSize(const WasmModule* module) {
      26           0 :   return WasmModule::kPageSize * module->initial_pages;
      27             : }
      28             : 
      29           7 : std::unique_ptr<WasmModule> DecodeWasmModuleForTesting(
      30             :     Isolate* isolate, ErrorThrower* thrower, const byte* module_start,
      31             :     const byte* module_end, ModuleOrigin origin, bool verify_functions) {
      32             :   // Decode the module, but don't verify function bodies, since we'll
      33             :   // be compiling them anyway.
      34             :   ModuleResult decoding_result = SyncDecodeWasmModule(
      35          14 :       isolate, module_start, module_end, verify_functions, origin);
      36             : 
      37           7 :   if (decoding_result.failed()) {
      38             :     // Module verification failed. throw.
      39             :     thrower->CompileError("DecodeWasmModule failed: %s",
      40           0 :                           decoding_result.error_msg().c_str());
      41             :   }
      42             : 
      43           7 :   return std::move(decoding_result.val);
      44             : }
      45             : 
      46           2 : bool InterpretWasmModuleForTesting(Isolate* isolate,
      47             :                                    Handle<WasmInstanceObject> instance,
      48             :                                    const char* name, size_t argc,
      49             :                                    WasmValue* args) {
      50             :   MaybeHandle<WasmExportedFunction> maybe_function =
      51           1 :       GetExportedFunction(isolate, instance, "main");
      52             :   Handle<WasmExportedFunction> function;
      53           1 :   if (!maybe_function.ToHandle(&function)) {
      54             :     return false;
      55             :   }
      56             :   int function_index = function->function_index();
      57           3 :   FunctionSig* signature = instance->module()->functions[function_index].sig;
      58           1 :   size_t param_count = signature->parameter_count();
      59           1 :   std::unique_ptr<WasmValue[]> arguments(new WasmValue[param_count]);
      60             : 
      61           1 :   memcpy(arguments.get(), args, std::min(param_count, argc));
      62             : 
      63             :   // Fill the parameters up with default values.
      64           1 :   for (size_t i = argc; i < param_count; ++i) {
      65           0 :     switch (signature->GetParam(i)) {
      66             :       case MachineRepresentation::kWord32:
      67           0 :         arguments[i] = WasmValue(int32_t{0});
      68           0 :         break;
      69             :       case MachineRepresentation::kWord64:
      70           0 :         arguments[i] = WasmValue(int64_t{0});
      71           0 :         break;
      72             :       case MachineRepresentation::kFloat32:
      73           0 :         arguments[i] = WasmValue(0.0f);
      74           0 :         break;
      75             :       case MachineRepresentation::kFloat64:
      76           0 :         arguments[i] = WasmValue(0.0);
      77           0 :         break;
      78             :       default:
      79           0 :         UNREACHABLE();
      80             :     }
      81             :   }
      82             : 
      83             :   // Don't execute more than 16k steps.
      84             :   constexpr int kMaxNumSteps = 16 * 1024;
      85             : 
      86           1 :   Zone zone(isolate->allocator(), ZONE_NAME);
      87             : 
      88           1 :   WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
      89           2 :   WasmInterpreter::HeapObjectsScope heap_objects_scope(interpreter, instance);
      90           1 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
      91           1 :   thread->Reset();
      92           1 :   thread->InitFrame(&instance->module()->functions[function_index],
      93           1 :                     arguments.get());
      94           1 :   WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
      95             : 
      96           2 :   return interpreter_result != WasmInterpreter::PAUSED;
      97             : }
      98             : 
      99         348 : int32_t RunWasmModuleForTesting(Isolate* isolate,
     100             :                                 Handle<WasmInstanceObject> instance, int argc,
     101             :                                 Handle<Object> argv[]) {
     102             :   ErrorThrower thrower(isolate, "RunWasmModule");
     103             :   return CallWasmFunctionForTesting(isolate, instance, &thrower, "main", argc,
     104         348 :                                     argv);
     105             : }
     106             : 
     107         252 : int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
     108             :                                 const byte* module_end) {
     109             :   HandleScope scope(isolate);
     110         252 :   ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
     111             :   MaybeHandle<WasmInstanceObject> instance = SyncCompileAndInstantiate(
     112         252 :       isolate, &thrower, ModuleWireBytes(module_start, module_end), {}, {});
     113         252 :   if (instance.is_null()) {
     114             :     return -1;
     115             :   }
     116             :   return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
     117         252 :                                  nullptr);
     118             : }
     119             : 
     120           0 : int32_t CompileAndRunAsmWasmModule(Isolate* isolate, const byte* module_start,
     121             :                                    const byte* module_end) {
     122             :   HandleScope scope(isolate);
     123           0 :   ErrorThrower thrower(isolate, "CompileAndRunAsmWasmModule");
     124             :   MaybeHandle<WasmModuleObject> module = wasm::SyncCompileTranslatedAsmJs(
     125             :       isolate, &thrower, ModuleWireBytes(module_start, module_end),
     126           0 :       Handle<Script>::null(), Vector<const byte>());
     127             :   DCHECK_EQ(thrower.error(), module.is_null());
     128           0 :   if (module.is_null()) return -1;
     129             : 
     130             :   MaybeHandle<WasmInstanceObject> instance = wasm::SyncInstantiate(
     131             :       isolate, &thrower, module.ToHandleChecked(), Handle<JSReceiver>::null(),
     132           0 :       Handle<JSArrayBuffer>::null());
     133             :   DCHECK_EQ(thrower.error(), instance.is_null());
     134           0 :   if (instance.is_null()) return -1;
     135             : 
     136             :   return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
     137           0 :                                  nullptr);
     138             : }
     139           1 : int32_t InterpretWasmModule(Isolate* isolate,
     140             :                             Handle<WasmInstanceObject> instance,
     141             :                             ErrorThrower* thrower, int32_t function_index,
     142             :                             WasmValue* args, bool* possible_nondeterminism) {
     143             :   // Don't execute more than 16k steps.
     144             :   constexpr int kMaxNumSteps = 16 * 1024;
     145             : 
     146           1 :   Zone zone(isolate->allocator(), ZONE_NAME);
     147             :   v8::internal::HandleScope scope(isolate);
     148             : 
     149           1 :   WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
     150           2 :   WasmInterpreter::HeapObjectsScope heap_objects_scope(interpreter, instance);
     151           1 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     152           1 :   thread->Reset();
     153           3 :   thread->InitFrame(&(instance->module()->functions[function_index]), args);
     154           1 :   WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
     155             : 
     156           1 :   *possible_nondeterminism = thread->PossibleNondeterminism();
     157           1 :   if (interpreter_result == WasmInterpreter::FINISHED) {
     158           1 :     WasmValue val = thread->GetReturnValue();
     159             :     return val.to<int32_t>();
     160           0 :   } else if (thread->state() == WasmInterpreter::TRAPPED) {
     161             :     return 0xdeadbeef;
     162             :   } else {
     163             :     thrower->RangeError(
     164           0 :         "Interpreter did not finish execution within its step bound");
     165           0 :     return -1;
     166           1 :   }
     167             : }
     168             : 
     169         374 : MaybeHandle<WasmExportedFunction> GetExportedFunction(
     170             :     Isolate* isolate, Handle<WasmInstanceObject> instance, const char* name) {
     171             :   Handle<JSObject> exports_object;
     172         374 :   Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
     173             :   exports_object = Handle<JSObject>::cast(
     174         748 :       JSObject::GetProperty(instance, exports).ToHandleChecked());
     175             : 
     176         374 :   Handle<Name> main_name = isolate->factory()->NewStringFromAsciiChecked(name);
     177             :   PropertyDescriptor desc;
     178             :   Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
     179         374 :       isolate, exports_object, main_name, &desc);
     180         374 :   if (!property_found.FromMaybe(false)) return {};
     181         374 :   if (!desc.value()->IsJSFunction()) return {};
     182             : 
     183         374 :   return Handle<WasmExportedFunction>::cast(desc.value());
     184             : }
     185             : 
     186         373 : int32_t CallWasmFunctionForTesting(Isolate* isolate,
     187             :                                    Handle<WasmInstanceObject> instance,
     188             :                                    ErrorThrower* thrower, const char* name,
     189             :                                    int argc, Handle<Object> argv[]) {
     190             :   MaybeHandle<WasmExportedFunction> maybe_export =
     191         373 :       GetExportedFunction(isolate, instance, name);
     192             :   Handle<WasmExportedFunction> main_export;
     193         373 :   if (!maybe_export.ToHandle(&main_export)) {
     194             :     return -1;
     195             :   }
     196             : 
     197             :   // Call the JS function.
     198             :   Handle<Object> undefined = isolate->factory()->undefined_value();
     199             :   MaybeHandle<Object> retval =
     200         373 :       Execution::Call(isolate, main_export, undefined, argc, argv);
     201             : 
     202             :   // The result should be a number.
     203         373 :   if (retval.is_null()) {
     204             :     DCHECK(isolate->has_pending_exception());
     205             :     isolate->clear_pending_exception();
     206          60 :     thrower->RuntimeError("Calling exported wasm function failed.");
     207          60 :     return -1;
     208             :   }
     209             :   Handle<Object> result = retval.ToHandleChecked();
     210         313 :   if (result->IsSmi()) {
     211         193 :     return Smi::ToInt(*result);
     212             :   }
     213         120 :   if (result->IsHeapNumber()) {
     214         120 :     return static_cast<int32_t>(HeapNumber::cast(*result)->value());
     215             :   }
     216             :   thrower->RuntimeError(
     217           0 :       "Calling exported wasm function failed: Return value should be number");
     218           0 :   return -1;
     219             : }
     220             : 
     221         390 : void SetupIsolateForWasmModule(Isolate* isolate) {
     222         390 :   WasmJs::Install(isolate, true);
     223         390 : }
     224             : 
     225             : }  // namespace testing
     226             : }  // namespace wasm
     227             : }  // namespace internal
     228             : }  // namespace v8

Generated by: LCOV version 1.10