LCOV - code coverage report
Current view: top level - test/cctest/wasm - test-wasm-interpreter-entry.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 85 85 100.0 %
Date: 2017-10-20 Functions: 21 21 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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 <cstdint>
       6             : 
       7             : #include "src/assembler-inl.h"
       8             : #include "src/objects-inl.h"
       9             : #include "src/wasm/wasm-objects.h"
      10             : #include "test/cctest/cctest.h"
      11             : #include "test/cctest/compiler/value-helper.h"
      12             : #include "test/cctest/wasm/wasm-run-utils.h"
      13             : #include "test/common/wasm/wasm-macro-gen.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace wasm {
      18             : 
      19             : /**
      20             :  * We test the interface from Wasm compiled code to the Wasm interpreter by
      21             :  * building a module with two functions. The external function is called from
      22             :  * this test, and will be compiled code. It takes its arguments and passes them
      23             :  * on to the internal function, which will be redirected to the interpreter.
      24             :  * If the internal function has an i64 parameter, is has to be replaced by two
      25             :  * i32 parameters on the external function.
      26             :  * The internal function just converts all its arguments to f64, sums them up
      27             :  * and returns the sum.
      28             :  */
      29             : namespace {
      30             : 
      31             : template <typename T>
      32             : class ArgPassingHelper {
      33             :  public:
      34          72 :   ArgPassingHelper(WasmRunnerBase& runner, WasmFunctionCompiler& inner_compiler,
      35             :                    std::initializer_list<uint8_t> bytes_inner_function,
      36             :                    std::initializer_list<uint8_t> bytes_outer_function,
      37             :                    const T& expected_lambda)
      38          36 :       : isolate_(runner.main_isolate()),
      39             :         expected_lambda_(expected_lambda),
      40             :         debug_info_(WasmInstanceObject::GetOrCreateDebugInfo(
      41          36 :             runner.builder().instance_object())) {
      42             :     std::vector<uint8_t> inner_code{bytes_inner_function};
      43          36 :     inner_compiler.Build(inner_code.data(),
      44          72 :                          inner_code.data() + inner_code.size());
      45             : 
      46             :     std::vector<uint8_t> outer_code{bytes_outer_function};
      47          72 :     runner.Build(outer_code.data(), outer_code.data() + outer_code.size());
      48             : 
      49          36 :     int funcs_to_redict[] = {static_cast<int>(inner_compiler.function_index())};
      50          36 :     WasmDebugInfo::RedirectToInterpreter(debug_info_,
      51             :                                          ArrayVector(funcs_to_redict));
      52          36 :     main_fun_wrapper_ = runner.builder().WrapCode(runner.function_index());
      53          36 :   }
      54             : 
      55             :   template <typename... Args>
      56       38466 :   void CheckCall(Args... args) {
      57       76932 :     Handle<Object> arg_objs[] = {isolate_->factory()->NewNumber(args)...};
      58             : 
      59       38466 :     uint64_t num_interpreted_before = debug_info_->NumInterpretedCalls();
      60       76932 :     Handle<Object> global(isolate_->context()->global_object(), isolate_);
      61             :     MaybeHandle<Object> retval = Execution::Call(
      62       38466 :         isolate_, main_fun_wrapper_, global, arraysize(arg_objs), arg_objs);
      63       38466 :     uint64_t num_interpreted_after = debug_info_->NumInterpretedCalls();
      64             :     // Check that we really went through the interpreter.
      65       38466 :     CHECK_EQ(num_interpreted_before + 1, num_interpreted_after);
      66             :     // Check the result.
      67             :     double result = retval.ToHandleChecked()->Number();
      68         348 :     double expected = expected_lambda_(args...);
      69       38466 :     CHECK_DOUBLE_EQ(expected, result);
      70       38466 :   }
      71             : 
      72             :  private:
      73             :   Isolate* isolate_;
      74             :   T expected_lambda_;
      75             :   Handle<WasmDebugInfo> debug_info_;
      76             :   Handle<JSFunction> main_fun_wrapper_;
      77             : };
      78             : 
      79             : template <typename T>
      80             : static ArgPassingHelper<T> GetHelper(
      81             :     WasmRunnerBase& runner, WasmFunctionCompiler& inner_compiler,
      82             :     std::initializer_list<uint8_t> bytes_inner_function,
      83             :     std::initializer_list<uint8_t> bytes_outer_function,
      84             :     const T& expected_lambda) {
      85             :   return ArgPassingHelper<T>(runner, inner_compiler, bytes_inner_function,
      86          36 :                              bytes_outer_function, expected_lambda);
      87             : }
      88             : 
      89             : }  // namespace
      90             : 
      91             : // Pass int32_t, return int32_t.
      92       23724 : TEST(TestArgumentPassing_int32) {
      93           6 :   WasmRunner<int32_t, int32_t> runner(kExecuteCompiled);
      94          12 :   WasmFunctionCompiler& f2 = runner.NewFunction<int32_t, int32_t>();
      95             : 
      96             :   auto helper = GetHelper(
      97             :       runner, f2,
      98             :       {// Return 2*<0> + 1.
      99             :        WASM_I32_ADD(WASM_I32_MUL(WASM_I32V_1(2), WASM_GET_LOCAL(0)), WASM_ONE)},
     100             :       {// Call f2 with param <0>.
     101             :        WASM_GET_LOCAL(0), WASM_CALL_FUNCTION0(f2.function_index())},
     102         366 :       [](int32_t a) { return 2 * a + 1; });
     103             : 
     104           6 :   FOR_INT32_INPUTS(v) { helper.CheckCall(*v); }
     105           6 : }
     106             : 
     107             : // Pass int64_t, return double.
     108       23724 : TEST(TestArgumentPassing_double_int64) {
     109           6 :   WasmRunner<double, int32_t, int32_t> runner(kExecuteCompiled);
     110          12 :   WasmFunctionCompiler& f2 = runner.NewFunction<double, int64_t>();
     111             : 
     112             :   auto helper = GetHelper(
     113             :       runner, f2,
     114             :       {// Return (double)<0>.
     115             :        WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0))},
     116             :       {// Call f2 with param (<0> | (<1> << 32)).
     117             :        WASM_I64_IOR(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(0)),
     118             :                     WASM_I64_SHL(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(1)),
     119             :                                  WASM_I64V_1(32))),
     120             :        WASM_CALL_FUNCTION0(f2.function_index())},
     121             :       [](int32_t a, int32_t b) {
     122       21156 :         int64_t a64 = static_cast<int64_t>(a) & 0xffffffff;
     123       21156 :         int64_t b64 = static_cast<int64_t>(b) << 32;
     124       21156 :         return static_cast<double>(a64 | b64);
     125          18 :       });
     126             : 
     127         354 :   FOR_INT32_INPUTS(v1) {
     128       20184 :     FOR_INT32_INPUTS(v2) { helper.CheckCall(*v1, *v2); }
     129             :   }
     130             : 
     131         486 :   FOR_INT64_INPUTS(v) {
     132         486 :     int32_t v1 = static_cast<int32_t>(*v);
     133         486 :     int32_t v2 = static_cast<int32_t>(*v >> 32);
     134         486 :     helper.CheckCall(v1, v2);
     135         486 :     helper.CheckCall(v2, v1);
     136             :   }
     137           6 : }
     138             : 
     139             : // Pass double, return int64_t.
     140       23724 : TEST(TestArgumentPassing_int64_double) {
     141             :   // Outer function still returns double.
     142           6 :   WasmRunner<double, double> runner(kExecuteCompiled);
     143          12 :   WasmFunctionCompiler& f2 = runner.NewFunction<int64_t, double>();
     144             : 
     145             :   auto helper = GetHelper(
     146             :       runner, f2,
     147             :       {// Return (int64_t)<0>.
     148             :        WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))},
     149             :       {// Call f2 with param <0>, convert returned value back to double.
     150             :        WASM_F64_SCONVERT_I64(WASM_SEQ(
     151             :            WASM_GET_LOCAL(0), WASM_CALL_FUNCTION0(f2.function_index())))},
     152          18 :       [](double d) { return d; });
     153             : 
     154         492 :   for (int64_t i : compiler::ValueHelper::int64_vector()) {
     155         486 :     helper.CheckCall(i);
     156             :   }
     157           6 : }
     158             : 
     159             : // Pass float, return double.
     160       23724 : TEST(TestArgumentPassing_float_double) {
     161           6 :   WasmRunner<double, float> runner(kExecuteCompiled);
     162          12 :   WasmFunctionCompiler& f2 = runner.NewFunction<double, float>();
     163             : 
     164             :   auto helper = GetHelper(
     165             :       runner, f2,
     166             :       {// Return 2*(double)<0> + 1.
     167             :        WASM_F64_ADD(
     168             :            WASM_F64_MUL(WASM_F64(2), WASM_F64_CONVERT_F32(WASM_GET_LOCAL(0))),
     169             :            WASM_F64(1))},
     170             :       {// Call f2 with param <0>.
     171             :        WASM_GET_LOCAL(0), WASM_CALL_FUNCTION0(f2.function_index())},
     172         708 :       [](float f) { return 2. * static_cast<double>(f) + 1.; });
     173             : 
     174           6 :   FOR_FLOAT32_INPUTS(f) { helper.CheckCall(*f); }
     175           6 : }
     176             : 
     177             : // Pass two doubles, return double.
     178       23724 : TEST(TestArgumentPassing_double_double) {
     179           6 :   WasmRunner<double, double, double> runner(kExecuteCompiled);
     180          12 :   WasmFunctionCompiler& f2 = runner.NewFunction<double, double, double>();
     181             : 
     182             :   auto helper = GetHelper(runner, f2,
     183             :                           {// Return <0> + <1>.
     184             :                            WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))},
     185             :                           {// Call f2 with params <0>, <1>.
     186             :                            WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
     187             :                            WASM_CALL_FUNCTION0(f2.function_index())},
     188       14424 :                           [](double a, double b) { return a + b; });
     189             : 
     190         300 :   FOR_FLOAT64_INPUTS(d1) {
     191       14406 :     FOR_FLOAT64_INPUTS(d2) { helper.CheckCall(*d1, *d2); }
     192             :   }
     193           6 : }
     194             : 
     195             : // Pass int32_t, int64_t, float and double, return double.
     196       23724 : TEST(TestArgumentPassing_AllTypes) {
     197             :   // The second and third argument will be combined to an i64.
     198             :   WasmRunner<double, int32_t, int32_t, int32_t, float, double> runner(
     199           6 :       kExecuteCompiled);
     200           6 :   WasmFunctionCompiler& f2 =
     201           6 :       runner.NewFunction<double, int32_t, int64_t, float, double>();
     202             : 
     203             :   auto helper = GetHelper(
     204             :       runner, f2,
     205             :       {
     206             :           // Convert all arguments to double, add them and return the sum.
     207             :           WASM_F64_ADD(          // <0+1+2> + <3>
     208             :               WASM_F64_ADD(      // <0+1> + <2>
     209             :                   WASM_F64_ADD(  // <0> + <1>
     210             :                       WASM_F64_SCONVERT_I32(
     211             :                           WASM_GET_LOCAL(0)),  // <0> to double
     212             :                       WASM_F64_SCONVERT_I64(
     213             :                           WASM_GET_LOCAL(1))),               // <1> to double
     214             :                   WASM_F64_CONVERT_F32(WASM_GET_LOCAL(2))),  // <2> to double
     215             :               WASM_GET_LOCAL(3))                             // <3>
     216             :       },
     217             :       {WASM_GET_LOCAL(0),                                      // first arg
     218             :        WASM_I64_IOR(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(1)),  // second arg
     219             :                     WASM_I64_SHL(WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(2)),
     220             :                                  WASM_I64V_1(32))),
     221             :        WASM_GET_LOCAL(3),  // third arg
     222             :        WASM_GET_LOCAL(4),  // fourth arg
     223             :        WASM_CALL_FUNCTION0(f2.function_index())},
     224             :       [](int32_t a, int32_t b, int32_t c, float d, double e) {
     225        2760 :         return 0. + a + (static_cast<int64_t>(b) & 0xffffffff) +
     226        2760 :                ((static_cast<int64_t>(c) & 0xffffffff) << 32) + d + e;
     227        1398 :       });
     228             : 
     229         690 :   auto CheckCall = [&](int32_t a, int64_t b, float c, double d) {
     230         690 :     int32_t b0 = static_cast<int32_t>(b);
     231         690 :     int32_t b1 = static_cast<int32_t>(b >> 32);
     232         690 :     helper.CheckCall(a, b0, b1, c, d);
     233         690 :     helper.CheckCall(a, b1, b0, c, d);
     234         696 :   };
     235             : 
     236             :   Vector<const int32_t> test_values_i32 = compiler::ValueHelper::int32_vector();
     237             :   Vector<const int64_t> test_values_i64 = compiler::ValueHelper::int64_vector();
     238             :   Vector<const float> test_values_f32 = compiler::ValueHelper::float32_vector();
     239             :   Vector<const double> test_values_f64 =
     240             :       compiler::ValueHelper::float64_vector();
     241             :   size_t max_len =
     242          12 :       std::max(std::max(test_values_i32.size(), test_values_i64.size()),
     243          18 :                std::max(test_values_f32.size(), test_values_f64.size()));
     244         696 :   for (size_t i = 0; i < max_len; ++i) {
     245        1380 :     int32_t i32 = test_values_i32[i % test_values_i32.size()];
     246        1380 :     int64_t i64 = test_values_i64[i % test_values_i64.size()];
     247        1380 :     float f32 = test_values_f32[i % test_values_f32.size()];
     248        1380 :     double f64 = test_values_f64[i % test_values_f64.size()];
     249         690 :     CheckCall(i32, i64, f32, f64);
     250             :   }
     251           6 : }
     252             : 
     253             : }  // namespace wasm
     254             : }  // namespace internal
     255       71154 : }  // namespace v8

Generated by: LCOV version 1.10