LCOV - code coverage report
Current view: top level - test/common/wasm - wasm-module-runner.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 101 70.3 %
Date: 2019-01-20 Functions: 10 13 76.9 %

          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         285 : MaybeHandle<WasmInstanceObject> CompileAndInstantiateForTesting(
      30             :     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes) {
      31         285 :   auto enabled_features = WasmFeaturesFromIsolate(isolate);
      32             :   MaybeHandle<WasmModuleObject> module = isolate->wasm_engine()->SyncCompile(
      33         285 :       isolate, enabled_features, thrower, bytes);
      34             :   DCHECK_EQ(thrower->error(), module.is_null());
      35         285 :   if (module.is_null()) return {};
      36             : 
      37             :   return isolate->wasm_engine()->SyncInstantiate(
      38         570 :       isolate, thrower, module.ToHandleChecked(), {}, {});
      39             : }
      40             : 
      41           0 : std::shared_ptr<WasmModule> DecodeWasmModuleForTesting(
      42           0 :     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             :   ModuleResult decoding_result = DecodeWasmModule(
      48             :       enabled_features, module_start, module_end, verify_functions, origin,
      49           0 :       isolate->counters(), isolate->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           2 : 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 :   memcpy(arguments.get(), args, std::min(param_count, argc));
      76             : 
      77             :   // Fill the parameters up with default values.
      78           1 :   for (size_t i = argc; i < param_count; ++i) {
      79           0 :     switch (signature->GetParam(i)) {
      80             :       case kWasmI32:
      81           0 :         arguments[i] = WasmValue(int32_t{0});
      82           0 :         break;
      83             :       case kWasmI64:
      84           0 :         arguments[i] = WasmValue(int64_t{0});
      85           0 :         break;
      86             :       case kWasmF32:
      87           0 :         arguments[i] = WasmValue(0.0f);
      88           0 :         break;
      89             :       case kWasmF64:
      90           0 :         arguments[i] = WasmValue(0.0);
      91           0 :         break;
      92             :       default:
      93           0 :         UNREACHABLE();
      94             :     }
      95             :   }
      96             : 
      97             :   // Don't execute more than 16k steps.
      98             :   constexpr int kMaxNumSteps = 16 * 1024;
      99             : 
     100           1 :   Zone zone(isolate->allocator(), ZONE_NAME);
     101             : 
     102           1 :   WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
     103           1 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     104           1 :   thread->Reset();
     105             : 
     106             :   // Start an activation so that we can deal with stack overflows. We do not
     107             :   // finish the activation. An activation is just part of the state of the
     108             :   // interpreter, and we do not reuse the interpreter anyways. In addition,
     109             :   // finishing the activation is not correct in all cases, e.g. when the
     110             :   // execution of the interpreter did not finish after kMaxNumSteps.
     111           1 :   thread->StartActivation();
     112           2 :   thread->InitFrame(&instance->module()->functions[function_index],
     113           1 :                     arguments.get());
     114           1 :   WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
     115             : 
     116           1 :   isolate->clear_pending_exception();
     117             : 
     118           1 :   return interpreter_result != WasmInterpreter::PAUSED;
     119             : }
     120             : 
     121        2845 : int32_t RunWasmModuleForTesting(Isolate* isolate,
     122             :                                 Handle<WasmInstanceObject> instance, int argc,
     123             :                                 Handle<Object> argv[]) {
     124             :   ErrorThrower thrower(isolate, "RunWasmModule");
     125             :   return CallWasmFunctionForTesting(isolate, instance, &thrower, "main", argc,
     126        2845 :                                     argv);
     127             : }
     128             : 
     129         210 : int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
     130             :                                 const byte* module_end) {
     131             :   HandleScope scope(isolate);
     132         210 :   ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
     133             :   MaybeHandle<WasmInstanceObject> instance = CompileAndInstantiateForTesting(
     134         210 :       isolate, &thrower, ModuleWireBytes(module_start, module_end));
     135         210 :   if (instance.is_null()) {
     136             :     return -1;
     137             :   }
     138             :   return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
     139         210 :                                  nullptr);
     140             : }
     141             : 
     142           0 : int32_t CompileAndRunAsmWasmModule(Isolate* isolate, const byte* module_start,
     143             :                                    const byte* module_end) {
     144             :   HandleScope scope(isolate);
     145           0 :   ErrorThrower thrower(isolate, "CompileAndRunAsmWasmModule");
     146             :   MaybeHandle<AsmWasmData> data =
     147             :       isolate->wasm_engine()->SyncCompileTranslatedAsmJs(
     148             :           isolate, &thrower, ModuleWireBytes(module_start, module_end),
     149           0 :           Vector<const byte>(), Handle<HeapNumber>());
     150             :   DCHECK_EQ(thrower.error(), data.is_null());
     151           0 :   if (data.is_null()) return -1;
     152             : 
     153             :   MaybeHandle<WasmModuleObject> module =
     154             :       isolate->wasm_engine()->FinalizeTranslatedAsmJs(
     155           0 :           isolate, data.ToHandleChecked(), Handle<Script>::null());
     156             : 
     157             :   MaybeHandle<WasmInstanceObject> instance =
     158             :       isolate->wasm_engine()->SyncInstantiate(
     159             :           isolate, &thrower, module.ToHandleChecked(),
     160           0 :           Handle<JSReceiver>::null(), Handle<JSArrayBuffer>::null());
     161             :   DCHECK_EQ(thrower.error(), instance.is_null());
     162           0 :   if (instance.is_null()) return -1;
     163             : 
     164             :   return RunWasmModuleForTesting(isolate, instance.ToHandleChecked(), 0,
     165           0 :                                  nullptr);
     166             : }
     167           1 : WasmInterpretationResult InterpretWasmModule(
     168           1 :     Isolate* isolate, Handle<WasmInstanceObject> instance,
     169             :     int32_t function_index, WasmValue* args) {
     170             :   // Don't execute more than 16k steps.
     171             :   constexpr int kMaxNumSteps = 16 * 1024;
     172             : 
     173           1 :   Zone zone(isolate->allocator(), ZONE_NAME);
     174             :   v8::internal::HandleScope scope(isolate);
     175             : 
     176           1 :   WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
     177           1 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     178           1 :   thread->Reset();
     179             : 
     180             :   // Start an activation so that we can deal with stack overflows. We do not
     181             :   // finish the activation. An activation is just part of the state of the
     182             :   // interpreter, and we do not reuse the interpreter anyways. In addition,
     183             :   // finishing the activation is not correct in all cases, e.g. when the
     184             :   // execution of the interpreter did not finish after kMaxNumSteps.
     185           1 :   thread->StartActivation();
     186           3 :   thread->InitFrame(&(instance->module()->functions[function_index]), args);
     187           1 :   WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
     188             : 
     189           1 :   bool stack_overflow = isolate->has_pending_exception();
     190           1 :   isolate->clear_pending_exception();
     191             : 
     192           1 :   if (stack_overflow) return WasmInterpretationResult::Stopped();
     193             : 
     194           1 :   if (thread->state() == WasmInterpreter::TRAPPED) {
     195           0 :     return WasmInterpretationResult::Trapped(thread->PossibleNondeterminism());
     196             :   }
     197             : 
     198           1 :   if (interpreter_result == WasmInterpreter::FINISHED) {
     199             :     return WasmInterpretationResult::Finished(
     200             :         thread->GetReturnValue().to<int32_t>(),
     201           2 :         thread->PossibleNondeterminism());
     202             :   }
     203             : 
     204           1 :   return WasmInterpretationResult::Stopped();
     205             : }
     206             : 
     207        2867 : MaybeHandle<WasmExportedFunction> GetExportedFunction(
     208             :     Isolate* isolate, Handle<WasmInstanceObject> instance, const char* name) {
     209             :   Handle<JSObject> exports_object;
     210        2867 :   Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
     211             :   exports_object = Handle<JSObject>::cast(
     212        5734 :       JSObject::GetProperty(isolate, instance, exports).ToHandleChecked());
     213             : 
     214        2867 :   Handle<Name> main_name = isolate->factory()->NewStringFromAsciiChecked(name);
     215             :   PropertyDescriptor desc;
     216             :   Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
     217        2867 :       isolate, exports_object, main_name, &desc);
     218        2867 :   if (!property_found.FromMaybe(false)) return {};
     219        5734 :   if (!desc.value()->IsJSFunction()) return {};
     220             : 
     221        2867 :   return Handle<WasmExportedFunction>::cast(desc.value());
     222             : }
     223             : 
     224        2866 : int32_t CallWasmFunctionForTesting(Isolate* isolate,
     225             :                                    Handle<WasmInstanceObject> instance,
     226             :                                    ErrorThrower* thrower, const char* name,
     227             :                                    int argc, Handle<Object> argv[]) {
     228             :   MaybeHandle<WasmExportedFunction> maybe_export =
     229        2866 :       GetExportedFunction(isolate, instance, name);
     230             :   Handle<WasmExportedFunction> main_export;
     231        2866 :   if (!maybe_export.ToHandle(&main_export)) {
     232             :     return -1;
     233             :   }
     234             : 
     235             :   // Call the JS function.
     236             :   Handle<Object> undefined = isolate->factory()->undefined_value();
     237             :   MaybeHandle<Object> retval =
     238        2866 :       Execution::Call(isolate, main_export, undefined, argc, argv);
     239             : 
     240             :   // The result should be a number.
     241        2866 :   if (retval.is_null()) {
     242             :     DCHECK(isolate->has_pending_exception());
     243          50 :     isolate->clear_pending_exception();
     244          50 :     thrower->RuntimeError("Calling exported wasm function failed.");
     245          50 :     return -1;
     246             :   }
     247             :   Handle<Object> result = retval.ToHandleChecked();
     248        5632 :   if (result->IsSmi()) {
     249        2716 :     return Smi::ToInt(*result);
     250             :   }
     251         200 :   if (result->IsHeapNumber()) {
     252         100 :     return static_cast<int32_t>(HeapNumber::cast(*result)->value());
     253             :   }
     254             :   thrower->RuntimeError(
     255           0 :       "Calling exported wasm function failed: Return value should be number");
     256           0 :   return -1;
     257             : }
     258             : 
     259         441 : void SetupIsolateForWasmModule(Isolate* isolate) {
     260         441 :   WasmJs::Install(isolate, true);
     261         441 : }
     262             : 
     263             : }  // namespace testing
     264             : }  // namespace wasm
     265             : }  // namespace internal
     266       85029 : }  // namespace v8

Generated by: LCOV version 1.10