LCOV - code coverage report
Current view: top level - test/common/wasm - wasm-module-runner.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 68 98 69.4 %
Date: 2019-04-17 Functions: 9 12 75.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/heap-number-inl.h"
      11             : #include "src/property-descriptor.h"
      12             : #include "src/wasm/module-decoder.h"
      13             : #include "src/wasm/wasm-engine.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 kWasmPageSize * module->initial_pages;
      27             : }
      28             : 
      29         228 : MaybeHandle<WasmInstanceObject> CompileAndInstantiateForTesting(
      30             :     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes) {
      31         228 :   auto enabled_features = WasmFeaturesFromIsolate(isolate);
      32             :   MaybeHandle<WasmModuleObject> module = isolate->wasm_engine()->SyncCompile(
      33         228 :       isolate, enabled_features, thrower, bytes);
      34             :   DCHECK_EQ(thrower->error(), module.is_null());
      35         228 :   if (module.is_null()) return {};
      36             : 
      37             :   return isolate->wasm_engine()->SyncInstantiate(
      38         456 :       isolate, thrower, module.ToHandleChecked(), {}, {});
      39             : }
      40             : 
      41           0 : std::shared_ptr<WasmModule> DecodeWasmModuleForTesting(
      42             :     Isolate* isolate, ErrorThrower* thrower, const byte* module_start,
      43             :     const byte* module_end, ModuleOrigin origin, bool verify_functions) {
      44             :   // Decode the module, but don't verify function bodies, since we'll
      45             :   // be compiling them anyway.
      46           0 :   auto enabled_features = WasmFeaturesFromIsolate(isolate);
      47           0 :   ModuleResult decoding_result = DecodeWasmModule(
      48             :       enabled_features, module_start, module_end, verify_functions, origin,
      49           0 :       isolate->counters(), isolate->wasm_engine()->allocator());
      50             : 
      51           0 :   if (decoding_result.failed()) {
      52             :     // Module verification failed. throw.
      53             :     thrower->CompileError("DecodeWasmModule failed: %s",
      54           0 :                           decoding_result.error().message().c_str());
      55             :   }
      56             : 
      57           0 :   return std::move(decoding_result).value();
      58             : }
      59             : 
      60           1 : bool InterpretWasmModuleForTesting(Isolate* isolate,
      61             :                                    Handle<WasmInstanceObject> instance,
      62             :                                    const char* name, size_t argc,
      63             :                                    WasmValue* args) {
      64             :   MaybeHandle<WasmExportedFunction> maybe_function =
      65           1 :       GetExportedFunction(isolate, instance, "main");
      66             :   Handle<WasmExportedFunction> function;
      67           1 :   if (!maybe_function.ToHandle(&function)) {
      68             :     return false;
      69             :   }
      70           1 :   int function_index = function->function_index();
      71           3 :   FunctionSig* signature = instance->module()->functions[function_index].sig;
      72           1 :   size_t param_count = signature->parameter_count();
      73           1 :   std::unique_ptr<WasmValue[]> arguments(new WasmValue[param_count]);
      74             : 
      75           1 :   size_t arg_count = std::min(param_count, argc);
      76           1 :   if (arg_count > 0) {
      77             :     memcpy(arguments.get(), args, arg_count);
      78             :   }
      79             : 
      80             :   // Fill the parameters up with default values.
      81           1 :   for (size_t i = argc; i < param_count; ++i) {
      82           0 :     switch (signature->GetParam(i)) {
      83             :       case kWasmI32:
      84           0 :         arguments[i] = WasmValue(int32_t{0});
      85           0 :         break;
      86             :       case kWasmI64:
      87           0 :         arguments[i] = WasmValue(int64_t{0});
      88           0 :         break;
      89             :       case kWasmF32:
      90           0 :         arguments[i] = WasmValue(0.0f);
      91           0 :         break;
      92             :       case kWasmF64:
      93           0 :         arguments[i] = WasmValue(0.0);
      94           0 :         break;
      95             :       default:
      96           0 :         UNREACHABLE();
      97             :     }
      98             :   }
      99             : 
     100             :   // Don't execute more than 16k steps.
     101             :   constexpr int kMaxNumSteps = 16 * 1024;
     102             : 
     103           2 :   Zone zone(isolate->allocator(), ZONE_NAME);
     104             : 
     105           1 :   WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
     106           1 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     107           1 :   thread->Reset();
     108             : 
     109             :   // Start an activation so that we can deal with stack overflows. We do not
     110             :   // finish the activation. An activation is just part of the state of the
     111             :   // interpreter, and we do not reuse the interpreter anyways. In addition,
     112             :   // finishing the activation is not correct in all cases, e.g. when the
     113             :   // execution of the interpreter did not finish after kMaxNumSteps.
     114           1 :   thread->StartActivation();
     115           2 :   thread->InitFrame(&instance->module()->functions[function_index],
     116           1 :                     arguments.get());
     117           1 :   WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
     118             : 
     119             :   isolate->clear_pending_exception();
     120             : 
     121           1 :   return interpreter_result != WasmInterpreter::PAUSED;
     122             : }
     123             : 
     124        2275 : int32_t RunWasmModuleForTesting(Isolate* isolate,
     125             :                                 Handle<WasmInstanceObject> instance, int argc,
     126             :                                 Handle<Object> argv[]) {
     127        2276 :   ErrorThrower thrower(isolate, "RunWasmModule");
     128             :   return CallWasmFunctionForTesting(isolate, instance, &thrower, "main", argc,
     129        4551 :                                     argv);
     130             : }
     131             : 
     132         168 : int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
     133             :                                 const byte* module_end) {
     134             :   HandleScope scope(isolate);
     135         168 :   ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
     136             :   MaybeHandle<WasmInstanceObject> instance = CompileAndInstantiateForTesting(
     137         168 :       isolate, &thrower, ModuleWireBytes(module_start, module_end));
     138         168 :   if (instance.is_null()) {
     139             :     return -1;
     140             :   }
     141             :   return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
     142         168 :                                  nullptr);
     143             : }
     144             : 
     145           0 : int32_t CompileAndRunAsmWasmModule(Isolate* isolate, const byte* module_start,
     146             :                                    const byte* module_end) {
     147             :   HandleScope scope(isolate);
     148           0 :   ErrorThrower thrower(isolate, "CompileAndRunAsmWasmModule");
     149             :   MaybeHandle<AsmWasmData> data =
     150             :       isolate->wasm_engine()->SyncCompileTranslatedAsmJs(
     151             :           isolate, &thrower, ModuleWireBytes(module_start, module_end),
     152           0 :           Vector<const byte>(), Handle<HeapNumber>());
     153             :   DCHECK_EQ(thrower.error(), data.is_null());
     154           0 :   if (data.is_null()) return -1;
     155             : 
     156             :   MaybeHandle<WasmModuleObject> module =
     157             :       isolate->wasm_engine()->FinalizeTranslatedAsmJs(
     158           0 :           isolate, data.ToHandleChecked(), Handle<Script>::null());
     159             : 
     160             :   MaybeHandle<WasmInstanceObject> instance =
     161             :       isolate->wasm_engine()->SyncInstantiate(
     162             :           isolate, &thrower, module.ToHandleChecked(),
     163           0 :           Handle<JSReceiver>::null(), Handle<JSArrayBuffer>::null());
     164             :   DCHECK_EQ(thrower.error(), instance.is_null());
     165           0 :   if (instance.is_null()) return -1;
     166             : 
     167             :   return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
     168           0 :                                  nullptr);
     169             : }
     170           1 : WasmInterpretationResult InterpretWasmModule(
     171             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
     172             :     int32_t function_index, WasmValue* args) {
     173             :   // Don't execute more than 16k steps.
     174             :   constexpr int kMaxNumSteps = 16 * 1024;
     175             : 
     176           2 :   Zone zone(isolate->allocator(), ZONE_NAME);
     177             :   v8::internal::HandleScope scope(isolate);
     178             : 
     179           1 :   WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
     180           1 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     181           1 :   thread->Reset();
     182             : 
     183             :   // Start an activation so that we can deal with stack overflows. We do not
     184             :   // finish the activation. An activation is just part of the state of the
     185             :   // interpreter, and we do not reuse the interpreter anyways. In addition,
     186             :   // finishing the activation is not correct in all cases, e.g. when the
     187             :   // execution of the interpreter did not finish after kMaxNumSteps.
     188           1 :   thread->StartActivation();
     189           3 :   thread->InitFrame(&(instance->module()->functions[function_index]), args);
     190           1 :   WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
     191             : 
     192             :   bool stack_overflow = isolate->has_pending_exception();
     193             :   isolate->clear_pending_exception();
     194             : 
     195           1 :   if (stack_overflow) return WasmInterpretationResult::Stopped();
     196             : 
     197           1 :   if (thread->state() == WasmInterpreter::TRAPPED) {
     198           0 :     return WasmInterpretationResult::Trapped(thread->PossibleNondeterminism());
     199             :   }
     200             : 
     201           1 :   if (interpreter_result == WasmInterpreter::FINISHED) {
     202             :     return WasmInterpretationResult::Finished(
     203           2 :         thread->GetReturnValue().to<int32_t>(),
     204           1 :         thread->PossibleNondeterminism());
     205             :   }
     206             : 
     207             :   return WasmInterpretationResult::Stopped();
     208             : }
     209             : 
     210        2293 : MaybeHandle<WasmExportedFunction> GetExportedFunction(
     211             :     Isolate* isolate, Handle<WasmInstanceObject> instance, const char* name) {
     212             :   Handle<JSObject> exports_object;
     213        2293 :   Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
     214             :   exports_object = Handle<JSObject>::cast(
     215        4588 :       JSObject::GetProperty(isolate, instance, exports).ToHandleChecked());
     216             : 
     217        2294 :   Handle<Name> main_name = isolate->factory()->NewStringFromAsciiChecked(name);
     218             :   PropertyDescriptor desc;
     219             :   Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
     220        2294 :       isolate, exports_object, main_name, &desc);
     221        2294 :   if (!property_found.FromMaybe(false)) return {};
     222        2294 :   if (!desc.value()->IsJSFunction()) return {};
     223             : 
     224        2294 :   return Handle<WasmExportedFunction>::cast(desc.value());
     225             : }
     226             : 
     227        2292 : int32_t CallWasmFunctionForTesting(Isolate* isolate,
     228             :                                    Handle<WasmInstanceObject> instance,
     229             :                                    ErrorThrower* thrower, const char* name,
     230             :                                    int argc, Handle<Object> argv[]) {
     231             :   MaybeHandle<WasmExportedFunction> maybe_export =
     232        2292 :       GetExportedFunction(isolate, instance, name);
     233             :   Handle<WasmExportedFunction> main_export;
     234        2292 :   if (!maybe_export.ToHandle(&main_export)) {
     235             :     return -1;
     236             :   }
     237             : 
     238             :   // Call the JS function.
     239             :   Handle<Object> undefined = isolate->factory()->undefined_value();
     240             :   MaybeHandle<Object> retval =
     241        2292 :       Execution::Call(isolate, main_export, undefined, argc, argv);
     242             : 
     243             :   // The result should be a number.
     244        2293 :   if (retval.is_null()) {
     245             :     DCHECK(isolate->has_pending_exception());
     246             :     isolate->clear_pending_exception();
     247          40 :     thrower->RuntimeError("Calling exported wasm function failed.");
     248          40 :     return -1;
     249             :   }
     250             :   Handle<Object> result = retval.ToHandleChecked();
     251        2253 :   if (result->IsSmi()) {
     252        2173 :     return Smi::ToInt(*result);
     253             :   }
     254          80 :   if (result->IsHeapNumber()) {
     255          80 :     return static_cast<int32_t>(HeapNumber::cast(*result)->value());
     256             :   }
     257             :   thrower->RuntimeError(
     258           0 :       "Calling exported wasm function failed: Return value should be number");
     259           0 :   return -1;
     260             : }
     261             : 
     262         354 : void SetupIsolateForWasmModule(Isolate* isolate) {
     263         354 :   WasmJs::Install(isolate, true);
     264         354 : }
     265             : 
     266             : }  // namespace testing
     267             : }  // namespace wasm
     268             : }  // namespace internal
     269       53290 : }  // namespace v8

Generated by: LCOV version 1.10