LCOV - code coverage report
Current view: top level - test/cctest/wasm - wasm-run-utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 130 134 97.0 %
Date: 2019-04-17 Functions: 404 496 81.5 %

          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             : #ifndef WASM_RUN_UTILS_H
       6             : #define WASM_RUN_UTILS_H
       7             : 
       8             : #include <setjmp.h>
       9             : #include <stdint.h>
      10             : #include <stdlib.h>
      11             : #include <string.h>
      12             : #include <array>
      13             : #include <memory>
      14             : 
      15             : #include "src/base/utils/random-number-generator.h"
      16             : #include "src/compiler/compiler-source-position-table.h"
      17             : #include "src/compiler/graph-visualizer.h"
      18             : #include "src/compiler/int64-lowering.h"
      19             : #include "src/compiler/js-graph.h"
      20             : #include "src/compiler/node.h"
      21             : #include "src/compiler/pipeline.h"
      22             : #include "src/compiler/wasm-compiler.h"
      23             : #include "src/compiler/zone-stats.h"
      24             : #include "src/trap-handler/trap-handler.h"
      25             : #include "src/wasm/function-body-decoder.h"
      26             : #include "src/wasm/local-decl-encoder.h"
      27             : #include "src/wasm/wasm-code-manager.h"
      28             : #include "src/wasm/wasm-external-refs.h"
      29             : #include "src/wasm/wasm-interpreter.h"
      30             : #include "src/wasm/wasm-js.h"
      31             : #include "src/wasm/wasm-module.h"
      32             : #include "src/wasm/wasm-objects-inl.h"
      33             : #include "src/wasm/wasm-objects.h"
      34             : #include "src/wasm/wasm-opcodes.h"
      35             : #include "src/wasm/wasm-tier.h"
      36             : #include "src/zone/accounting-allocator.h"
      37             : #include "src/zone/zone.h"
      38             : 
      39             : #include "test/cctest/cctest.h"
      40             : #include "test/cctest/compiler/call-tester.h"
      41             : #include "test/cctest/compiler/graph-builder-tester.h"
      42             : #include "test/cctest/compiler/value-helper.h"
      43             : #include "test/common/wasm/flag-utils.h"
      44             : 
      45             : namespace v8 {
      46             : namespace internal {
      47             : namespace wasm {
      48             : 
      49             : constexpr uint32_t kMaxFunctions = 10;
      50             : constexpr uint32_t kMaxGlobalsSize = 128;
      51             : 
      52             : using compiler::CallDescriptor;
      53             : using compiler::MachineTypeForC;
      54             : using compiler::Node;
      55             : 
      56             : // TODO(titzer): check traps more robustly in tests.
      57             : // Currently, in tests, we just return 0xDEADBEEF from the function in which
      58             : // the trap occurs if the runtime context is not available to throw a JavaScript
      59             : // exception.
      60             : #define CHECK_TRAP32(x) \
      61             :   CHECK_EQ(0xDEADBEEF, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
      62             : #define CHECK_TRAP64(x) \
      63             :   CHECK_EQ(0xDEADBEEFDEADBEEF, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
      64             : #define CHECK_TRAP(x) CHECK_TRAP32(x)
      65             : 
      66             : #define WASM_WRAPPER_RETURN_VALUE 8754
      67             : 
      68             : #define BUILD(r, ...)                      \
      69             :   do {                                     \
      70             :     byte code[] = {__VA_ARGS__};           \
      71             :     r.Build(code, code + arraysize(code)); \
      72             :   } while (false)
      73             : 
      74             : // For tests that must manually import a JSFunction with source code.
      75             : struct ManuallyImportedJSFunction {
      76             :   FunctionSig* sig;
      77             :   Handle<JSFunction> js_function;
      78             : };
      79             : 
      80             : // A  Wasm module builder. Globals are pre-set, however, memory and code may be
      81             : // progressively added by a test. In turn, we piecemeal update the runtime
      82             : // objects, i.e. {WasmInstanceObject}, {WasmModuleObject} and, if necessary,
      83             : // the interpreter.
      84     2188448 : class TestingModuleBuilder {
      85             :  public:
      86             :   TestingModuleBuilder(Zone*, ManuallyImportedJSFunction*, ExecutionTier,
      87             :                        RuntimeExceptionSupport, LowerSimd);
      88             : 
      89         384 :   void ChangeOriginToAsmjs() { test_module_->origin = kAsmJsOrigin; }
      90             : 
      91             :   byte* AddMemory(uint32_t size, SharedFlag shared = SharedFlag::kNotShared);
      92             : 
      93             :   size_t CodeTableLength() const { return native_module_->num_functions(); }
      94             : 
      95             :   template <typename T>
      96             :   T* AddMemoryElems(uint32_t count) {
      97       39992 :     AddMemory(count * sizeof(T));
      98             :     return raw_mem_start<T>();
      99             :   }
     100             : 
     101             :   template <typename T>
     102             :   T* AddGlobal(
     103         216 :       ValueType type = ValueTypes::ValueTypeFor(MachineTypeForC<T>())) {
     104       22144 :     const WasmGlobal* global = AddGlobal(type);
     105       22132 :     return reinterpret_cast<T*>(globals_data_ + global->offset);
     106             :   }
     107             : 
     108        3220 :   byte AddSignature(FunctionSig* sig) {
     109             :     DCHECK_EQ(test_module_->signatures.size(),
     110             :               test_module_->signature_ids.size());
     111        3220 :     test_module_->signatures.push_back(sig);
     112        3220 :     auto canonical_sig_num = test_module_->signature_map.FindOrInsert(*sig);
     113        3220 :     test_module_->signature_ids.push_back(canonical_sig_num);
     114             :     size_t size = test_module_->signatures.size();
     115        3220 :     CHECK_GT(127, size);
     116        3220 :     return static_cast<byte>(size - 1);
     117             :   }
     118             : 
     119             :   uint32_t mem_size() { return mem_size_; }
     120             : 
     121             :   template <typename T>
     122             :   T* raw_mem_start() {
     123             :     DCHECK(mem_start_);
     124             :     return reinterpret_cast<T*>(mem_start_);
     125             :   }
     126             : 
     127             :   template <typename T>
     128             :   T* raw_mem_end() {
     129             :     DCHECK(mem_start_);
     130       15924 :     return reinterpret_cast<T*>(mem_start_ + mem_size_);
     131             :   }
     132             : 
     133             :   template <typename T>
     134             :   T raw_mem_at(int i) {
     135             :     DCHECK(mem_start_);
     136       58560 :     return ReadMemory(&(reinterpret_cast<T*>(mem_start_)[i]));
     137             :   }
     138             : 
     139             :   template <typename T>
     140             :   T raw_val_at(int i) {
     141         792 :     return ReadMemory(reinterpret_cast<T*>(mem_start_ + i));
     142             :   }
     143             : 
     144             :   template <typename T>
     145             :   void WriteMemory(T* p, T val) {
     146             :     WriteLittleEndianValue<T>(reinterpret_cast<Address>(p), val);
     147             :   }
     148             : 
     149             :   template <typename T>
     150             :   T ReadMemory(T* p) {
     151             :     return ReadLittleEndianValue<T>(reinterpret_cast<Address>(p));
     152             :   }
     153             : 
     154             :   // Zero-initialize the memory.
     155             :   void BlankMemory() {
     156             :     byte* raw = raw_mem_start<byte>();
     157         624 :     memset(raw, 0, mem_size_);
     158             :   }
     159             : 
     160             :   // Pseudo-randomly intialize the memory.
     161       15564 :   void RandomizeMemory(unsigned int seed = 88) {
     162             :     byte* raw = raw_mem_start<byte>();
     163             :     byte* end = raw_mem_end<byte>();
     164       15564 :     v8::base::RandomNumberGenerator rng;
     165       15564 :     rng.SetSeed(seed);
     166       15564 :     rng.NextBytes(raw, end - raw);
     167       15564 :   }
     168             : 
     169           8 :   void SetMaxMemPages(uint32_t maximum_pages) {
     170           8 :     test_module_->maximum_pages = maximum_pages;
     171           8 :     if (instance_object()->has_memory_object()) {
     172           8 :       instance_object()->memory_object()->set_maximum_pages(maximum_pages);
     173             :     }
     174           8 :   }
     175             : 
     176        1208 :   void SetHasSharedMemory() { test_module_->has_shared_memory = true; }
     177             : 
     178             :   enum FunctionType { kImport, kWasm };
     179             :   uint32_t AddFunction(FunctionSig* sig, const char* name, FunctionType type);
     180             : 
     181             :   // Wrap the code so it can be called as a JS function.
     182             :   Handle<JSFunction> WrapCode(uint32_t index);
     183             : 
     184             :   // If function_indexes is {nullptr}, the contents of the table will be
     185             :   // initialized with null functions.
     186             :   void AddIndirectFunctionTable(const uint16_t* function_indexes,
     187             :                                 uint32_t table_size);
     188             : 
     189             :   uint32_t AddBytes(Vector<const byte> bytes);
     190             : 
     191             :   uint32_t AddException(FunctionSig* sig);
     192             : 
     193             :   uint32_t AddPassiveDataSegment(Vector<const byte> bytes);
     194             :   uint32_t AddPassiveElementSegment(const std::vector<uint32_t>& entries);
     195             : 
     196             :   WasmFunction* GetFunctionAt(int index) {
     197     1103308 :     return &test_module_->functions[index];
     198             :   }
     199             : 
     200             :   WasmInterpreter* interpreter() const { return interpreter_; }
     201             :   bool interpret() const { return interpreter_ != nullptr; }
     202             :   LowerSimd lower_simd() const { return lower_simd_; }
     203             :   Isolate* isolate() const { return isolate_; }
     204             :   Handle<WasmInstanceObject> instance_object() const {
     205             :     return instance_object_;
     206             :   }
     207             :   WasmCode* GetFunctionCode(uint32_t index) const {
     208     9612700 :     return native_module_->GetCode(index);
     209             :   }
     210             :   Address globals_start() const {
     211             :     return reinterpret_cast<Address>(globals_data_);
     212             :   }
     213             : 
     214     9617096 :   void SetExecutable() { native_module_->SetExecutable(true); }
     215             : 
     216             :   CompilationEnv CreateCompilationEnv();
     217             : 
     218             :   ExecutionTier execution_tier() const { return execution_tier_; }
     219             : 
     220             :   RuntimeExceptionSupport runtime_exception_support() const {
     221             :     return runtime_exception_support_;
     222             :   }
     223             : 
     224             :  private:
     225             :   std::shared_ptr<WasmModule> test_module_;
     226             :   WasmModule* test_module_ptr_;
     227             :   Isolate* isolate_;
     228             :   WasmFeatures enabled_features_;
     229             :   uint32_t global_offset = 0;
     230             :   byte* mem_start_ = nullptr;
     231             :   uint32_t mem_size_ = 0;
     232             :   alignas(16) byte globals_data_[kMaxGlobalsSize];
     233             :   WasmInterpreter* interpreter_ = nullptr;
     234             :   ExecutionTier execution_tier_;
     235             :   Handle<WasmInstanceObject> instance_object_;
     236             :   NativeModule* native_module_ = nullptr;
     237             :   RuntimeExceptionSupport runtime_exception_support_;
     238             :   LowerSimd lower_simd_;
     239             : 
     240             :   // Data segment arrays that are normally allocated on the instance.
     241             :   std::vector<byte> data_segment_data_;
     242             :   std::vector<Address> data_segment_starts_;
     243             :   std::vector<uint32_t> data_segment_sizes_;
     244             :   std::vector<byte> dropped_data_segments_;
     245             :   std::vector<byte> dropped_elem_segments_;
     246             : 
     247             :   const WasmGlobal* AddGlobal(ValueType type);
     248             : 
     249             :   Handle<WasmInstanceObject> InitInstanceObject();
     250             : };
     251             : 
     252             : void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
     253             :                        CompilationEnv* module, FunctionSig* sig,
     254             :                        compiler::SourcePositionTable* source_position_table,
     255             :                        const byte* start, const byte* end);
     256             : 
     257             : class WasmFunctionWrapper : private compiler::GraphAndBuilders {
     258             :  public:
     259             :   WasmFunctionWrapper(Zone* zone, int num_params);
     260             : 
     261             :   void Init(CallDescriptor* call_descriptor, MachineType return_type,
     262             :             Vector<MachineType> param_types);
     263             : 
     264             :   template <typename ReturnType, typename... ParamTypes>
     265       16552 :   void Init(CallDescriptor* call_descriptor) {
     266             :     std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
     267       16552 :         {MachineTypeForC<ParamTypes>()...}};
     268             :     Vector<MachineType> param_vec(param_machine_types.data(),
     269             :                                   param_machine_types.size());
     270      729312 :     Init(call_descriptor, MachineTypeForC<ReturnType>(), param_vec);
     271       16552 :   }
     272             : 
     273     9612676 :   void SetInnerCode(WasmCode* code) {
     274             :     intptr_t address = static_cast<intptr_t>(code->instruction_start());
     275     9612676 :     compiler::NodeProperties::ChangeOp(
     276             :         inner_code_node_,
     277    19225352 :         common()->ExternalConstant(ExternalReference::FromRawAddress(address)));
     278     9612676 :   }
     279             : 
     280      729312 :   const compiler::Operator* IntPtrConstant(intptr_t value) {
     281             :     return machine()->Is32()
     282           0 :                ? common()->Int32Constant(static_cast<int32_t>(value))
     283     1458624 :                : common()->Int64Constant(static_cast<int64_t>(value));
     284             :   }
     285             : 
     286     9612676 :   void SetInstance(Handle<WasmInstanceObject> instance) {
     287    19225352 :     compiler::NodeProperties::ChangeOp(context_address_,
     288     9612676 :                                        common()->HeapConstant(instance));
     289     9612676 :   }
     290             : 
     291             :   Handle<Code> GetWrapperCode();
     292             : 
     293             :   Signature<MachineType>* signature() const { return signature_; }
     294             : 
     295             :  private:
     296             :   Node* inner_code_node_;
     297             :   Node* context_address_;
     298             :   MaybeHandle<Code> code_;
     299             :   Signature<MachineType>* signature_;
     300             : };
     301             : 
     302             : // A helper for compiling wasm functions for testing.
     303             : // It contains the internal state for compilation (i.e. TurboFan graph) and
     304             : // interpretation (by adding to the interpreter manually).
     305     2206552 : class WasmFunctionCompiler : public compiler::GraphAndBuilders {
     306             :  public:
     307             :   ~WasmFunctionCompiler();
     308             : 
     309             :   Isolate* isolate() { return builder_->isolate(); }
     310      729312 :   CallDescriptor* descriptor() {
     311      729312 :     if (descriptor_ == nullptr) {
     312      729312 :       descriptor_ = compiler::GetWasmCallDescriptor(zone(), sig);
     313             :     }
     314      729312 :     return descriptor_;
     315             :   }
     316     1102072 :   uint32_t function_index() { return function_->func_index; }
     317             : 
     318             :   void Build(const byte* start, const byte* end);
     319             : 
     320             :   byte AllocateLocal(ValueType type) {
     321      193928 :     uint32_t index = local_decls.AddLocals(1, type);
     322        5572 :     byte result = static_cast<byte>(index);
     323             :     DCHECK_EQ(index, result);
     324             :     return result;
     325             :   }
     326             : 
     327         424 :   void SetSigIndex(int sig_index) { function_->sig_index = sig_index; }
     328             : 
     329             :  private:
     330             :   friend class WasmRunnerBase;
     331             : 
     332             :   WasmFunctionCompiler(Zone* zone, FunctionSig* sig,
     333             :                        TestingModuleBuilder* builder, const char* name);
     334             : 
     335             :   compiler::JSGraph jsgraph;
     336             :   FunctionSig* sig;
     337             :   // The call descriptor is initialized when the function is compiled.
     338             :   CallDescriptor* descriptor_;
     339             :   TestingModuleBuilder* builder_;
     340             :   WasmFunction* function_;
     341             :   LocalDeclEncoder local_decls;
     342             :   compiler::SourcePositionTable source_position_table_;
     343             :   WasmInterpreter* interpreter_;
     344             : };
     345             : 
     346             : // A helper class to build a module around Wasm bytecode, generate machine
     347             : // code, and run that code.
     348     1094224 : class WasmRunnerBase : public HandleAndZoneScope {
     349             :  public:
     350     1094224 :   WasmRunnerBase(ManuallyImportedJSFunction* maybe_import,
     351             :                  ExecutionTier execution_tier, int num_params,
     352             :                  RuntimeExceptionSupport runtime_exception_support,
     353             :                  LowerSimd lower_simd)
     354             :       : zone_(&allocator_, ZONE_NAME),
     355             :         builder_(&zone_, maybe_import, execution_tier,
     356             :                  runtime_exception_support, lower_simd),
     357     3282672 :         wrapper_(&zone_, num_params) {}
     358             : 
     359             :   // Builds a graph from the given Wasm code and generates the machine
     360             :   // code and call wrapper for that graph. This method must not be called
     361             :   // more than once.
     362     1088824 :   void Build(const byte* start, const byte* end) {
     363     1088824 :     CHECK(!compiled_);
     364     1088824 :     compiled_ = true;
     365     1088824 :     functions_[0]->Build(start, end);
     366     1088824 :   }
     367             : 
     368             :   // Resets the state for building the next function.
     369             :   // The main function called will always be the first function.
     370             :   template <typename ReturnType, typename... ParamTypes>
     371     1069420 :   WasmFunctionCompiler& NewFunction(const char* name = nullptr) {
     372     1094440 :     return NewFunction(CreateSig<ReturnType, ParamTypes...>(), name);
     373             :   }
     374             : 
     375             :   // Resets the state for building the next function.
     376             :   // The main function called will be the last generated function.
     377             :   // Returns the index of the previously built function.
     378     1103276 :   WasmFunctionCompiler& NewFunction(FunctionSig* sig,
     379             :                                     const char* name = nullptr) {
     380     3309828 :     functions_.emplace_back(
     381     2206552 :         new WasmFunctionCompiler(&zone_, sig, &builder_, name));
     382     1103276 :     return *functions_.back();
     383             :   }
     384             : 
     385             :   byte AllocateLocal(ValueType type) {
     386             :     return functions_[0]->AllocateLocal(type);
     387             :   }
     388             : 
     389             :   uint32_t function_index() { return functions_[0]->function_index(); }
     390     4707304 :   WasmFunction* function() { return functions_[0]->function_; }
     391             :   WasmInterpreter* interpreter() {
     392             :     DCHECK(interpret());
     393     4700028 :     return functions_[0]->interpreter_;
     394             :   }
     395             :   bool possible_nondeterminism() { return possible_nondeterminism_; }
     396          24 :   TestingModuleBuilder& builder() { return builder_; }
     397             :   Zone* zone() { return &zone_; }
     398             : 
     399             :   bool interpret() { return builder_.interpret(); }
     400             : 
     401             :   template <typename ReturnType, typename... ParamTypes>
     402       25056 :   FunctionSig* CreateSig() {
     403             :     std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
     404       25056 :         {MachineTypeForC<ParamTypes>()...}};
     405             :     Vector<MachineType> param_vec(param_machine_types.data(),
     406             :                                   param_machine_types.size());
     407     1094476 :     return CreateSig(MachineTypeForC<ReturnType>(), param_vec);
     408             :   }
     409             : 
     410             :  private:
     411             :   FunctionSig* CreateSig(MachineType return_type,
     412             :                          Vector<MachineType> param_types);
     413             : 
     414             :  protected:
     415             :   v8::internal::AccountingAllocator allocator_;
     416             :   Zone zone_;
     417             :   TestingModuleBuilder builder_;
     418             :   std::vector<std::unique_ptr<WasmFunctionCompiler>> functions_;
     419             :   WasmFunctionWrapper wrapper_;
     420             :   bool compiled_ = false;
     421             :   bool possible_nondeterminism_ = false;
     422             :   int32_t main_fn_index_ = 0;
     423             : 
     424             :  public:
     425             :   // This field has to be static. Otherwise, gcc complains about the use in
     426             :   // the lambda context below.
     427             :   static bool trap_happened;
     428             : };
     429             : 
     430             : template <typename ReturnType, typename... ParamTypes>
     431     2188448 : class WasmRunner : public WasmRunnerBase {
     432             :  public:
     433     1094224 :   WasmRunner(ExecutionTier execution_tier,
     434             :              ManuallyImportedJSFunction* maybe_import = nullptr,
     435             :              const char* main_fn_name = "main",
     436             :              RuntimeExceptionSupport runtime_exception_support =
     437             :                  kNoRuntimeExceptionSupport,
     438             :              LowerSimd lower_simd = kNoLowerSimd)
     439             :       : WasmRunnerBase(maybe_import, execution_tier, sizeof...(ParamTypes),
     440     1094224 :                        runtime_exception_support, lower_simd) {
     441             :     WasmFunctionCompiler& main_fn =
     442     1069328 :         NewFunction<ReturnType, ParamTypes...>(main_fn_name);
     443             :     // Non-zero if there is an import.
     444     1094224 :     main_fn_index_ = main_fn.function_index();
     445             : 
     446     1094224 :     if (!interpret()) {
     447      729312 :       wrapper_.Init<ReturnType, ParamTypes...>(main_fn.descriptor());
     448             :     }
     449     1094224 :   }
     450             : 
     451             :   WasmRunner(ExecutionTier execution_tier, LowerSimd lower_simd)
     452             :       : WasmRunner(execution_tier, nullptr, "main", kNoRuntimeExceptionSupport,
     453       12772 :                    lower_simd) {}
     454             : 
     455             :   void SetUpTrapCallback() {
     456     9620608 :     WasmRunnerBase::trap_happened = false;
     457      145520 :     auto trap_callback = []() -> void {
     458       72760 :       WasmRunnerBase::trap_happened = true;
     459       72760 :       set_trap_callback_for_testing(nullptr);
     460           0 :     };
     461     9620608 :     set_trap_callback_for_testing(trap_callback);
     462             :   }
     463             : 
     464    14312688 :   ReturnType Call(ParamTypes... p) {
     465             :     DCHECK(compiled_);
     466    14312688 :     if (interpret()) return CallInterpreter(p...);
     467             : 
     468     9612676 :     ReturnType return_value = static_cast<ReturnType>(0xDEADBEEFDEADBEEF);
     469             :     SetUpTrapCallback();
     470             : 
     471    19225352 :     wrapper_.SetInnerCode(builder_.GetFunctionCode(main_fn_index_));
     472     9612676 :     wrapper_.SetInstance(builder_.instance_object());
     473             :     builder_.SetExecutable();
     474     9612676 :     Handle<Code> wrapper_code = wrapper_.GetWrapperCode();
     475             :     compiler::CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
     476             :                                          wrapper_code, wrapper_.signature());
     477             :     int32_t result;
     478             :     {
     479             :       SetThreadInWasmFlag();
     480             : 
     481     9612676 :       result = runner.Call(static_cast<void*>(&p)...,
     482             :                            static_cast<void*>(&return_value));
     483             : 
     484             :       ClearThreadInWasmFlag();
     485             :     }
     486     9612676 :     CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
     487             :     return WasmRunnerBase::trap_happened
     488             :                ? static_cast<ReturnType>(0xDEADBEEFDEADBEEF)
     489     9612676 :                : return_value;
     490             :   }
     491             : 
     492     4700012 :   ReturnType CallInterpreter(ParamTypes... p) {
     493     4700012 :     WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
     494     4700012 :     thread->Reset();
     495             :     std::array<WasmValue, sizeof...(p)> args{{WasmValue(p)...}};
     496     4700012 :     thread->InitFrame(function(), args.data());
     497     4700012 :     thread->Run();
     498     9400024 :     CHECK_GT(thread->NumInterpretedCalls(), 0);
     499     4700012 :     if (thread->state() == WasmInterpreter::FINISHED) {
     500     4663728 :       WasmValue val = thread->GetReturnValue();
     501     4663728 :       possible_nondeterminism_ |= thread->PossibleNondeterminism();
     502             :       return val.to<ReturnType>();
     503       36284 :     } else if (thread->state() == WasmInterpreter::TRAPPED) {
     504             :       // TODO(titzer): return the correct trap code
     505             :       int64_t result = 0xDEADBEEFDEADBEEF;
     506           0 :       return static_cast<ReturnType>(result);
     507             :     } else {
     508             :       // TODO(titzer): falling off end
     509           0 :       return ReturnType{0};
     510             :     }
     511             :   }
     512             : 
     513        7932 :   void CheckCallApplyViaJS(double expected, uint32_t function_index,
     514             :                            Handle<Object>* buffer, int count) {
     515             :     Isolate* isolate = builder_.isolate();
     516             :     SetUpTrapCallback();
     517        7932 :     if (jsfuncs_.size() <= function_index) {
     518        4236 :       jsfuncs_.resize(function_index + 1);
     519             :     }
     520        7932 :     if (jsfuncs_[function_index].is_null()) {
     521        4272 :       jsfuncs_[function_index] = builder_.WrapCode(function_index);
     522             :     }
     523        7932 :     Handle<JSFunction> jsfunc = jsfuncs_[function_index];
     524       15864 :     Handle<Object> global(isolate->context()->global_object(), isolate);
     525             :     MaybeHandle<Object> retval =
     526        7932 :         Execution::TryCall(isolate, jsfunc, global, count, buffer,
     527        7932 :                            Execution::MessageHandling::kReport, nullptr);
     528             : 
     529        7932 :     if (retval.is_null() || WasmRunnerBase::trap_happened) {
     530        2496 :       CHECK_EQ(expected, static_cast<double>(0xDEADBEEF));
     531             :     } else {
     532             :       Handle<Object> result = retval.ToHandleChecked();
     533        5436 :       if (result->IsSmi()) {
     534        3540 :         CHECK_EQ(expected, Smi::ToInt(*result));
     535             :       } else {
     536        1896 :         CHECK(result->IsHeapNumber());
     537        1896 :         CHECK_DOUBLE_EQ(expected, HeapNumber::cast(*result)->value());
     538             :       }
     539             :     }
     540             : 
     541        7932 :     if (builder_.interpret()) {
     542        5288 :       CHECK_GT(builder_.interpreter()->GetThread(0)->NumInterpretedCalls(), 0);
     543             :     }
     544        7932 :   }
     545             : 
     546        3036 :   void CheckCallViaJS(double expected, ParamTypes... p) {
     547             :     Isolate* isolate = builder_.isolate();
     548             :     // MSVC doesn't allow empty arrays, so include a dummy at the end.
     549             :     Handle<Object> buffer[] = {isolate->factory()->NewNumber(p)...,
     550        3000 :                                Handle<Object>()};
     551        3036 :     CheckCallApplyViaJS(expected, function()->func_index, buffer, sizeof...(p));
     552        3036 :   }
     553             : 
     554             :   Handle<Code> GetWrapperCode() { return wrapper_.GetWrapperCode(); }
     555             : 
     556             :  private:
     557             :   wasm::WasmCodeRefScope code_ref_scope_;
     558             :   std::vector<Handle<JSFunction>> jsfuncs_;
     559             : 
     560             :   void SetThreadInWasmFlag() {
     561     9612676 :     *reinterpret_cast<int*>(trap_handler::GetThreadInWasmThreadLocalAddress()) =
     562             :         true;
     563             :   }
     564             : 
     565             :   void ClearThreadInWasmFlag() {
     566     9612676 :     *reinterpret_cast<int*>(trap_handler::GetThreadInWasmThreadLocalAddress()) =
     567             :         false;
     568             :   }
     569             : };
     570             : 
     571             : // A macro to define tests that run in different engine configurations.
     572             : #define WASM_EXEC_TEST(name)                                                 \
     573             :   void RunWasm_##name(ExecutionTier execution_tier);                         \
     574             :   TEST(RunWasmTurbofan_##name) { RunWasm_##name(ExecutionTier::kTurbofan); } \
     575             :   TEST(RunWasmLiftoff_##name) { RunWasm_##name(ExecutionTier::kLiftoff); }   \
     576             :   TEST(RunWasmInterpreter_##name) {                                          \
     577             :     RunWasm_##name(ExecutionTier::kInterpreter);                             \
     578             :   }                                                                          \
     579             :   void RunWasm_##name(ExecutionTier execution_tier)
     580             : 
     581             : #define WASM_COMPILED_EXEC_TEST(name)                                        \
     582             :   void RunWasm_##name(ExecutionTier execution_tier);                         \
     583             :   TEST(RunWasmTurbofan_##name) { RunWasm_##name(ExecutionTier::kTurbofan); } \
     584             :   TEST(RunWasmLiftoff_##name) { RunWasm_##name(ExecutionTier::kLiftoff); }   \
     585             :   void RunWasm_##name(ExecutionTier execution_tier)
     586             : 
     587             : }  // namespace wasm
     588             : }  // namespace internal
     589             : }  // namespace v8
     590             : 
     591             : #endif

Generated by: LCOV version 1.10