LCOV - code coverage report
Current view: top level - test/cctest/wasm - test-run-wasm-interpreter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 324 324 100.0 %
Date: 2019-04-17 Functions: 24 24 100.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 <stdint.h>
       6             : #include <stdlib.h>
       7             : #include <string.h>
       8             : 
       9             : #include <memory>
      10             : 
      11             : #include "src/assembler-inl.h"
      12             : #include "src/wasm/wasm-interpreter.h"
      13             : #include "test/cctest/cctest.h"
      14             : #include "test/cctest/compiler/value-helper.h"
      15             : #include "test/cctest/wasm/wasm-run-utils.h"
      16             : #include "test/common/wasm/test-signatures.h"
      17             : #include "test/common/wasm/wasm-macro-gen.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : namespace wasm {
      22             : namespace test_run_wasm_interpreter {
      23             : 
      24       26643 : TEST(Run_WasmInt8Const_i) {
      25           8 :   WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
      26             :   const byte kExpectedValue = 109;
      27             :   // return(kExpectedValue)
      28           4 :   BUILD(r, WASM_I32V_2(kExpectedValue));
      29           8 :   CHECK_EQ(kExpectedValue, r.Call());
      30           4 : }
      31             : 
      32       26643 : TEST(Run_WasmIfElse) {
      33           8 :   WasmRunner<int32_t, int32_t> r(ExecutionTier::kInterpreter);
      34           4 :   BUILD(r, WASM_IF_ELSE_I(WASM_GET_LOCAL(0), WASM_I32V_1(9), WASM_I32V_1(10)));
      35           4 :   CHECK_EQ(10, r.Call(0));
      36           4 :   CHECK_EQ(9, r.Call(1));
      37           4 : }
      38             : 
      39       26643 : TEST(Run_WasmIfReturn) {
      40           8 :   WasmRunner<int32_t, int32_t> r(ExecutionTier::kInterpreter);
      41           4 :   BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_RETURN1(WASM_I32V_2(77))),
      42             :         WASM_I32V_2(65));
      43           4 :   CHECK_EQ(65, r.Call(0));
      44           4 :   CHECK_EQ(77, r.Call(1));
      45           4 : }
      46             : 
      47       26643 : TEST(Run_WasmNopsN) {
      48             :   const int kMaxNops = 10;
      49             :   byte code[kMaxNops + 2];
      50          84 :   for (int nops = 0; nops < kMaxNops; nops++) {
      51          40 :     byte expected = static_cast<byte>(20 + nops);
      52             :     memset(code, kExprNop, sizeof(code));
      53          40 :     code[nops] = kExprI32Const;
      54          40 :     code[nops + 1] = expected;
      55             : 
      56          80 :     WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
      57          40 :     r.Build(code, code + nops + 2);
      58          80 :     CHECK_EQ(expected, r.Call());
      59             :   }
      60           4 : }
      61             : 
      62       26643 : TEST(Run_WasmConstsN) {
      63             :   const int kMaxConsts = 5;
      64             :   byte code[kMaxConsts * 3];
      65             :   int32_t expected = 0;
      66          36 :   for (int count = 1; count < kMaxConsts; count++) {
      67          96 :     for (int i = 0; i < count; i++) {
      68          40 :       byte val = static_cast<byte>(count * 10 + i);
      69          40 :       code[i * 3] = kExprI32Const;
      70          40 :       code[i * 3 + 1] = val;
      71          40 :       if (i == (count - 1)) {
      72          16 :         code[i * 3 + 2] = kExprNop;
      73          16 :         expected = val;
      74             :       } else {
      75          24 :         code[i * 3 + 2] = kExprDrop;
      76             :       }
      77             :     }
      78             : 
      79          32 :     WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
      80          16 :     r.Build(code, code + (count * 3));
      81          16 :     CHECK_EQ(expected, r.Call());
      82             :   }
      83           4 : }
      84             : 
      85       26643 : TEST(Run_WasmBlocksN) {
      86             :   const int kMaxNops = 10;
      87             :   const int kExtra = 5;
      88             :   byte code[kMaxNops + kExtra];
      89          84 :   for (int nops = 0; nops < kMaxNops; nops++) {
      90          40 :     byte expected = static_cast<byte>(30 + nops);
      91             :     memset(code, kExprNop, sizeof(code));
      92          40 :     code[0] = kExprBlock;
      93          40 :     code[1] = kLocalI32;
      94          40 :     code[2 + nops] = kExprI32Const;
      95          40 :     code[2 + nops + 1] = expected;
      96          40 :     code[2 + nops + 2] = kExprEnd;
      97             : 
      98          80 :     WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
      99          40 :     r.Build(code, code + nops + kExtra);
     100          80 :     CHECK_EQ(expected, r.Call());
     101             :   }
     102           4 : }
     103             : 
     104       26643 : TEST(Run_WasmBlockBreakN) {
     105             :   const int kMaxNops = 10;
     106             :   const int kExtra = 6;
     107             :   int run = 0;
     108             :   byte code[kMaxNops + kExtra];
     109          84 :   for (int nops = 0; nops < kMaxNops; nops++) {
     110             :     // Place the break anywhere within the block.
     111         400 :     for (int index = 0; index < nops; index++) {
     112             :       memset(code, kExprNop, sizeof(code));
     113         180 :       code[0] = kExprBlock;
     114         180 :       code[1] = kLocalI32;
     115         180 :       code[sizeof(code) - 1] = kExprEnd;
     116             : 
     117         180 :       int expected = run++;
     118         180 :       code[2 + index + 0] = kExprI32Const;
     119         180 :       code[2 + index + 1] = static_cast<byte>(expected);
     120         180 :       code[2 + index + 2] = kExprBr;
     121         180 :       code[2 + index + 3] = 0;
     122             : 
     123         360 :       WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
     124         180 :       r.Build(code, code + kMaxNops + kExtra);
     125         180 :       CHECK_EQ(expected, r.Call());
     126             :     }
     127             :   }
     128           4 : }
     129             : 
     130       26643 : TEST(Run_Wasm_nested_ifs_i) {
     131           8 :   WasmRunner<int32_t, int32_t, int32_t> r(ExecutionTier::kInterpreter);
     132             : 
     133           4 :   BUILD(
     134             :       r,
     135             :       WASM_IF_ELSE_I(
     136             :           WASM_GET_LOCAL(0),
     137             :           WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I32V_1(11), WASM_I32V_1(12)),
     138             :           WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I32V_1(13), WASM_I32V_1(14))));
     139             : 
     140           4 :   CHECK_EQ(11, r.Call(1, 1));
     141           4 :   CHECK_EQ(12, r.Call(1, 0));
     142           4 :   CHECK_EQ(13, r.Call(0, 1));
     143           4 :   CHECK_EQ(14, r.Call(0, 0));
     144           4 : }
     145             : 
     146             : // Repeated from test-run-wasm.cc to avoid poluting header files.
     147             : template <typename T>
     148             : static T factorial(T v) {
     149             :   T expected = 1;
     150      160848 :   for (T i = v; i > 1; i--) {
     151       80392 :     expected *= i;
     152             :   }
     153             :   return expected;
     154             : }
     155             : 
     156             : // Basic test of return call in interpreter. Good old factorial.
     157       26643 : TEST(Run_Wasm_returnCallFactorial) {
     158             :   EXPERIMENTAL_FLAG_SCOPE(return_call);
     159             :   // Run in bounded amount of stack - 8kb.
     160             :   FlagScope<int32_t> stack_size(&v8::internal::FLAG_stack_size, 8);
     161             : 
     162           8 :   WasmRunner<uint32_t, int32_t> r(ExecutionTier::kInterpreter);
     163             : 
     164             :   WasmFunctionCompiler& fact_aux_fn =
     165             :       r.NewFunction<int32_t, int32_t, int32_t>("fact_aux");
     166             : 
     167           8 :   BUILD(r, WASM_RETURN_CALL_FUNCTION(fact_aux_fn.function_index(),
     168             :                                      WASM_GET_LOCAL(0), WASM_I32V(1)));
     169             : 
     170           8 :   BUILD(fact_aux_fn,
     171             :         WASM_IF_ELSE_I(
     172             :             WASM_I32_EQ(WASM_I32V(1), WASM_GET_LOCAL(0)), WASM_GET_LOCAL(1),
     173             :             WASM_RETURN_CALL_FUNCTION(
     174             :                 fact_aux_fn.function_index(),
     175             :                 WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V(1)),
     176             :                 WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))));
     177             : 
     178             :   // Runs out of stack space without using return call.
     179           4 :   uint32_t test_values[] = {1, 2, 5, 10, 20, 20000};
     180             : 
     181          52 :   for (uint32_t v : test_values) {
     182          24 :     uint32_t found = r.Call(v);
     183          24 :     CHECK_EQ(factorial(v), found);
     184             :   }
     185           4 : }
     186             : 
     187       26643 : TEST(Run_Wasm_returnCallFactorial64) {
     188             :   EXPERIMENTAL_FLAG_SCOPE(return_call);
     189             : 
     190           4 :   int32_t test_values[] = {1, 2, 5, 10, 20};
     191           8 :   WasmRunner<int64_t, int32_t> r(ExecutionTier::kInterpreter);
     192             : 
     193             :   WasmFunctionCompiler& fact_aux_fn =
     194             :       r.NewFunction<int64_t, int32_t, int64_t>("fact_aux");
     195             : 
     196           8 :   BUILD(r, WASM_RETURN_CALL_FUNCTION(fact_aux_fn.function_index(),
     197             :                                      WASM_GET_LOCAL(0), WASM_I64V(1)));
     198             : 
     199           8 :   BUILD(fact_aux_fn,
     200             :         WASM_IF_ELSE_L(
     201             :             WASM_I32_EQ(WASM_I32V(1), WASM_GET_LOCAL(0)), WASM_GET_LOCAL(1),
     202             :             WASM_RETURN_CALL_FUNCTION(
     203             :                 fact_aux_fn.function_index(),
     204             :                 WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V(1)),
     205             :                 WASM_I64_MUL(WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)),
     206             :                              WASM_GET_LOCAL(1)))));
     207             : 
     208          44 :   for (int32_t v : test_values) {
     209          40 :     CHECK_EQ(factorial<int64_t>(v), r.Call(v));
     210             :   }
     211           4 : }
     212             : 
     213       26643 : TEST(Run_Wasm_returnCallIndirectFactorial) {
     214             :   EXPERIMENTAL_FLAG_SCOPE(return_call);
     215             : 
     216           4 :   TestSignatures sigs;
     217             : 
     218           8 :   WasmRunner<uint32_t, uint32_t> r(ExecutionTier::kInterpreter);
     219             : 
     220           4 :   WasmFunctionCompiler& fact_aux_fn = r.NewFunction(sigs.i_ii(), "fact_aux");
     221             :   fact_aux_fn.SetSigIndex(0);
     222             : 
     223           4 :   r.builder().AddSignature(sigs.i_ii());
     224             : 
     225             :   // Function table.
     226             :   uint16_t indirect_function_table[] = {
     227           4 :       static_cast<uint16_t>(fact_aux_fn.function_index())};
     228             : 
     229             :   r.builder().AddIndirectFunctionTable(indirect_function_table,
     230           4 :                                        arraysize(indirect_function_table));
     231             : 
     232           4 :   BUILD(r, WASM_RETURN_CALL_INDIRECT(0, WASM_I32V(0), WASM_GET_LOCAL(0),
     233             :                                      WASM_I32V(1)));
     234             : 
     235           4 :   BUILD(fact_aux_fn,
     236             :         WASM_IF_ELSE_I(
     237             :             WASM_I32_EQ(WASM_I32V(1), WASM_GET_LOCAL(0)), WASM_GET_LOCAL(1),
     238             :             WASM_RETURN_CALL_INDIRECT(
     239             :                 0, WASM_I32V(0), WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V(1)),
     240             :                 WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))));
     241             : 
     242           4 :   uint32_t test_values[] = {1, 2, 5, 10, 20};
     243             : 
     244          44 :   for (uint32_t v : test_values) {
     245          40 :     CHECK_EQ(factorial(v), r.Call(v));
     246             :   }
     247           4 : }
     248             : // Make tests more robust by not hard-coding offsets of various operations.
     249             : // The {Find} method finds the offsets for the given bytecodes, returning
     250             : // the offsets in an array.
     251           8 : std::unique_ptr<int[]> Find(byte* code, size_t code_size, int n, ...) {
     252             :   va_list vl;
     253           8 :   va_start(vl, n);
     254             : 
     255           8 :   std::unique_ptr<int[]> offsets(new int[n]);
     256             : 
     257          40 :   for (int i = 0; i < n; i++) {
     258          32 :     offsets[i] = -1;
     259             :   }
     260             : 
     261             :   int pos = 0;
     262           8 :   WasmOpcode current = static_cast<WasmOpcode>(va_arg(vl, int));
     263          72 :   for (size_t i = 0; i < code_size; i++) {
     264          40 :     if (code[i] == current) {
     265          32 :       offsets[pos++] = static_cast<int>(i);
     266          16 :       if (pos == n) break;
     267           8 :       current = static_cast<WasmOpcode>(va_arg(vl, int));
     268             :     }
     269             :   }
     270           8 :   va_end(vl);
     271             : 
     272           8 :   return offsets;
     273             : }
     274             : 
     275       26643 : TEST(Breakpoint_I32Add) {
     276             :   static const int kLocalsDeclSize = 1;
     277             :   static const int kNumBreakpoints = 3;
     278           4 :   byte code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
     279             :   std::unique_ptr<int[]> offsets =
     280             :       Find(code, sizeof(code), kNumBreakpoints, kExprGetLocal, kExprGetLocal,
     281           4 :            kExprI32Add);
     282             : 
     283           8 :   WasmRunner<int32_t, uint32_t, uint32_t> r(ExecutionTier::kInterpreter);
     284             : 
     285           4 :   r.Build(code, code + arraysize(code));
     286             : 
     287             :   WasmInterpreter* interpreter = r.interpreter();
     288           4 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     289          28 :   for (int i = 0; i < kNumBreakpoints; i++) {
     290          24 :     interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[i],
     291          12 :                                true);
     292             :   }
     293             : 
     294         468 :   FOR_UINT32_INPUTS(a) {
     295        1624 :     for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
     296         696 :       thread->Reset();
     297             :       WasmValue args[] = {WasmValue(a), WasmValue(b)};
     298         696 :       thread->InitFrame(r.function(), args);
     299             : 
     300        4872 :       for (int i = 0; i < kNumBreakpoints; i++) {
     301        2088 :         thread->Run();  // run to next breakpoint
     302             :         // Check the thread stopped at the right pc.
     303        2088 :         CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
     304        4176 :         CHECK_EQ(static_cast<size_t>(kLocalsDeclSize + offsets[i]),
     305             :                  thread->GetBreakpointPc());
     306             :       }
     307             : 
     308         696 :       thread->Run();  // run to completion
     309             : 
     310             :       // Check the thread finished with the right value.
     311         696 :       CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
     312         696 :       uint32_t expected = (a) + (b);
     313         696 :       CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
     314             :     }
     315             :   }
     316           4 : }
     317             : 
     318       26643 : TEST(Step_I32Mul) {
     319             :   static const int kTraceLength = 4;
     320           4 :   byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
     321             : 
     322           8 :   WasmRunner<int32_t, uint32_t, uint32_t> r(ExecutionTier::kInterpreter);
     323             : 
     324           4 :   r.Build(code, code + arraysize(code));
     325             : 
     326             :   WasmInterpreter* interpreter = r.interpreter();
     327           4 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     328             : 
     329         468 :   FOR_UINT32_INPUTS(a) {
     330        1624 :     for (uint32_t b = 33; b < 3000000000u; b += 1000000000u) {
     331         696 :       thread->Reset();
     332             :       WasmValue args[] = {WasmValue(a), WasmValue(b)};
     333         696 :       thread->InitFrame(r.function(), args);
     334             : 
     335             :       // Run instructions one by one.
     336        4872 :       for (int i = 0; i < kTraceLength - 1; i++) {
     337             :         thread->Step();
     338             :         // Check the thread stopped.
     339        2088 :         CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
     340             :       }
     341             : 
     342             :       // Run last instruction.
     343             :       thread->Step();
     344             : 
     345             :       // Check the thread finished with the right value.
     346         696 :       CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
     347         696 :       uint32_t expected = (a) * (b);
     348         696 :       CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
     349             :     }
     350             :   }
     351           4 : }
     352             : 
     353       26643 : TEST(Breakpoint_I32And_disable) {
     354             :   static const int kLocalsDeclSize = 1;
     355             :   static const int kNumBreakpoints = 1;
     356           4 :   byte code[] = {WASM_I32_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
     357             :   std::unique_ptr<int[]> offsets =
     358           4 :       Find(code, sizeof(code), kNumBreakpoints, kExprI32And);
     359             : 
     360           8 :   WasmRunner<int32_t, uint32_t, uint32_t> r(ExecutionTier::kInterpreter);
     361             : 
     362           4 :   r.Build(code, code + arraysize(code));
     363             : 
     364             :   WasmInterpreter* interpreter = r.interpreter();
     365           4 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     366             : 
     367         468 :   FOR_UINT32_INPUTS(a) {
     368        1624 :     for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
     369             :       // Run with and without breakpoints.
     370        3480 :       for (int do_break = 0; do_break < 2; do_break++) {
     371        2784 :         interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[0],
     372        1392 :                                    do_break);
     373        1392 :         thread->Reset();
     374             :         WasmValue args[] = {WasmValue(a), WasmValue(b)};
     375        1392 :         thread->InitFrame(r.function(), args);
     376             : 
     377        1392 :         if (do_break) {
     378         696 :           thread->Run();  // run to next breakpoint
     379             :           // Check the thread stopped at the right pc.
     380         696 :           CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
     381        1392 :           CHECK_EQ(static_cast<size_t>(kLocalsDeclSize + offsets[0]),
     382             :                    thread->GetBreakpointPc());
     383             :         }
     384             : 
     385        1392 :         thread->Run();  // run to completion
     386             : 
     387             :         // Check the thread finished with the right value.
     388        1392 :         CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
     389        1392 :         uint32_t expected = (a) & (b);
     390        1392 :         CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
     391             :       }
     392             :     }
     393             :   }
     394           4 : }
     395             : 
     396       26643 : TEST(MemoryGrow) {
     397             :   {
     398           8 :     WasmRunner<int32_t, uint32_t> r(ExecutionTier::kInterpreter);
     399           4 :     r.builder().AddMemory(kWasmPageSize);
     400           4 :     r.builder().SetMaxMemPages(10);
     401           4 :     BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0)));
     402           4 :     CHECK_EQ(1, r.Call(1));
     403             :   }
     404             :   {
     405           8 :     WasmRunner<int32_t, uint32_t> r(ExecutionTier::kInterpreter);
     406           4 :     r.builder().AddMemory(kWasmPageSize);
     407           4 :     r.builder().SetMaxMemPages(10);
     408           4 :     BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0)));
     409           4 :     CHECK_EQ(-1, r.Call(11));
     410             :   }
     411           4 : }
     412             : 
     413       26643 : TEST(MemoryGrowPreservesData) {
     414             :   int32_t index = 16;
     415             :   int32_t value = 2335;
     416           8 :   WasmRunner<int32_t, uint32_t> r(ExecutionTier::kInterpreter);
     417           4 :   r.builder().AddMemory(kWasmPageSize);
     418           4 :   BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index),
     419             :                           WASM_I32V(value)),
     420             :         WASM_GROW_MEMORY(WASM_GET_LOCAL(0)), WASM_DROP,
     421             :         WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V(index)));
     422           4 :   CHECK_EQ(value, r.Call(1));
     423           4 : }
     424             : 
     425       26643 : TEST(MemoryGrowInvalidSize) {
     426             :   // Grow memory by an invalid amount without initial memory.
     427           8 :   WasmRunner<int32_t, uint32_t> r(ExecutionTier::kInterpreter);
     428           4 :   r.builder().AddMemory(kWasmPageSize);
     429           4 :   BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0)));
     430           4 :   CHECK_EQ(-1, r.Call(1048575));
     431           4 : }
     432             : 
     433       26643 : TEST(ReferenceTypeLocals) {
     434             :   {
     435           8 :     WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
     436           4 :     BUILD(r, WASM_REF_IS_NULL(WASM_REF_NULL));
     437           4 :     CHECK_EQ(1, r.Call());
     438             :   }
     439             :   {
     440           8 :     WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
     441             :     r.AllocateLocal(kWasmAnyRef);
     442           4 :     BUILD(r, WASM_REF_IS_NULL(WASM_GET_LOCAL(0)));
     443           4 :     CHECK_EQ(1, r.Call());
     444             :   }
     445             :   {
     446           8 :     WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
     447             :     r.AllocateLocal(kWasmAnyRef);
     448           4 :     BUILD(r, WASM_REF_IS_NULL(WASM_TEE_LOCAL(0, WASM_REF_NULL)));
     449           4 :     CHECK_EQ(1, r.Call());
     450             :   }
     451             :   // TODO(mstarzinger): Test and support global anyref variables.
     452           4 : }
     453             : 
     454       26643 : TEST(TestPossibleNondeterminism) {
     455             :   {
     456           8 :     WasmRunner<int32_t, float> r(ExecutionTier::kInterpreter);
     457           4 :     BUILD(r, WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(0)));
     458           4 :     r.Call(1048575.5f);
     459           4 :     CHECK(!r.possible_nondeterminism());
     460           4 :     r.Call(std::numeric_limits<float>::quiet_NaN());
     461           4 :     CHECK(!r.possible_nondeterminism());
     462             :   }
     463             :   {
     464           8 :     WasmRunner<int64_t, double> r(ExecutionTier::kInterpreter);
     465           4 :     BUILD(r, WASM_I64_REINTERPRET_F64(WASM_GET_LOCAL(0)));
     466           4 :     r.Call(16.0);
     467           4 :     CHECK(!r.possible_nondeterminism());
     468           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     469           4 :     CHECK(!r.possible_nondeterminism());
     470             :   }
     471             :   {
     472           8 :     WasmRunner<float, float> r(ExecutionTier::kInterpreter);
     473           4 :     BUILD(r, WASM_F32_COPYSIGN(WASM_F32(42.0f), WASM_GET_LOCAL(0)));
     474           4 :     r.Call(16.0f);
     475           4 :     CHECK(!r.possible_nondeterminism());
     476           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     477           4 :     CHECK(!r.possible_nondeterminism());
     478             :   }
     479             :   {
     480           8 :     WasmRunner<double, double> r(ExecutionTier::kInterpreter);
     481           4 :     BUILD(r, WASM_F64_COPYSIGN(WASM_F64(42.0), WASM_GET_LOCAL(0)));
     482           4 :     r.Call(16.0);
     483           4 :     CHECK(!r.possible_nondeterminism());
     484           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     485           4 :     CHECK(!r.possible_nondeterminism());
     486             :   }
     487             :   {
     488             :     int32_t index = 16;
     489           8 :     WasmRunner<int32_t, float> r(ExecutionTier::kInterpreter);
     490           4 :     r.builder().AddMemory(kWasmPageSize);
     491           4 :     BUILD(r, WASM_STORE_MEM(MachineType::Float32(), WASM_I32V(index),
     492             :                             WASM_GET_LOCAL(0)),
     493             :           WASM_I32V(index));
     494           4 :     r.Call(1345.3456f);
     495           4 :     CHECK(!r.possible_nondeterminism());
     496           4 :     r.Call(std::numeric_limits<float>::quiet_NaN());
     497           4 :     CHECK(!r.possible_nondeterminism());
     498             :   }
     499             :   {
     500             :     int32_t index = 16;
     501           8 :     WasmRunner<int32_t, double> r(ExecutionTier::kInterpreter);
     502           4 :     r.builder().AddMemory(kWasmPageSize);
     503           4 :     BUILD(r, WASM_STORE_MEM(MachineType::Float64(), WASM_I32V(index),
     504             :                             WASM_GET_LOCAL(0)),
     505             :           WASM_I32V(index));
     506           4 :     r.Call(1345.3456);
     507           4 :     CHECK(!r.possible_nondeterminism());
     508           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     509           4 :     CHECK(!r.possible_nondeterminism());
     510             :   }
     511             :   {
     512           8 :     WasmRunner<float, float> r(ExecutionTier::kInterpreter);
     513           4 :     BUILD(r, WASM_F32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
     514           4 :     r.Call(1048575.5f);
     515           4 :     CHECK(!r.possible_nondeterminism());
     516           4 :     r.Call(std::numeric_limits<float>::quiet_NaN());
     517           4 :     CHECK(r.possible_nondeterminism());
     518             :   }
     519             :   {
     520           8 :     WasmRunner<double, double> r(ExecutionTier::kInterpreter);
     521           4 :     BUILD(r, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
     522           4 :     r.Call(16.0);
     523           4 :     CHECK(!r.possible_nondeterminism());
     524           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     525           4 :     CHECK(r.possible_nondeterminism());
     526             :   }
     527             :   {
     528           8 :     WasmRunner<int32_t, float> r(ExecutionTier::kInterpreter);
     529           4 :     BUILD(r, WASM_F32_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
     530           4 :     r.Call(16.0);
     531           4 :     CHECK(!r.possible_nondeterminism());
     532           4 :     r.Call(std::numeric_limits<float>::quiet_NaN());
     533           4 :     CHECK(!r.possible_nondeterminism());
     534             :   }
     535             :   {
     536           8 :     WasmRunner<int32_t, double> r(ExecutionTier::kInterpreter);
     537           4 :     BUILD(r, WASM_F64_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
     538           4 :     r.Call(16.0);
     539           4 :     CHECK(!r.possible_nondeterminism());
     540           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     541           4 :     CHECK(!r.possible_nondeterminism());
     542             :   }
     543             :   {
     544           8 :     WasmRunner<float, float> r(ExecutionTier::kInterpreter);
     545           4 :     BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
     546           4 :     r.Call(1048575.5f);
     547           4 :     CHECK(!r.possible_nondeterminism());
     548           4 :     r.Call(std::numeric_limits<float>::quiet_NaN());
     549           4 :     CHECK(r.possible_nondeterminism());
     550             :   }
     551             :   {
     552           8 :     WasmRunner<double, double> r(ExecutionTier::kInterpreter);
     553           4 :     BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
     554           4 :     r.Call(16.0);
     555           4 :     CHECK(!r.possible_nondeterminism());
     556           4 :     r.Call(std::numeric_limits<double>::quiet_NaN());
     557           4 :     CHECK(r.possible_nondeterminism());
     558             :   }
     559           4 : }
     560             : 
     561       26643 : TEST(WasmInterpreterActivations) {
     562           8 :   WasmRunner<void> r(ExecutionTier::kInterpreter);
     563             :   Isolate* isolate = r.main_isolate();
     564           4 :   BUILD(r, WASM_UNREACHABLE);
     565             : 
     566             :   WasmInterpreter* interpreter = r.interpreter();
     567           4 :   WasmInterpreter::Thread* thread = interpreter->GetThread(0);
     568           4 :   CHECK_EQ(0, thread->NumActivations());
     569           4 :   uint32_t act0 = thread->StartActivation();
     570           4 :   CHECK_EQ(0, act0);
     571           4 :   thread->InitFrame(r.function(), nullptr);
     572           4 :   uint32_t act1 = thread->StartActivation();
     573           4 :   CHECK_EQ(1, act1);
     574           4 :   thread->InitFrame(r.function(), nullptr);
     575           4 :   CHECK_EQ(2, thread->NumActivations());
     576           4 :   CHECK_EQ(2, thread->GetFrameCount());
     577           4 :   CHECK_EQ(WasmInterpreter::TRAPPED, thread->Run());
     578           4 :   thread->RaiseException(isolate, handle(Smi::kZero, isolate));
     579           4 :   CHECK_EQ(1, thread->GetFrameCount());
     580           4 :   CHECK_EQ(2, thread->NumActivations());
     581           4 :   thread->FinishActivation(act1);
     582             :   isolate->clear_pending_exception();
     583           4 :   CHECK_EQ(1, thread->GetFrameCount());
     584           4 :   CHECK_EQ(1, thread->NumActivations());
     585           4 :   CHECK_EQ(WasmInterpreter::TRAPPED, thread->Run());
     586           4 :   thread->RaiseException(isolate, handle(Smi::kZero, isolate));
     587           4 :   CHECK_EQ(0, thread->GetFrameCount());
     588           4 :   CHECK_EQ(1, thread->NumActivations());
     589           4 :   thread->FinishActivation(act0);
     590             :   isolate->clear_pending_exception();
     591           4 :   CHECK_EQ(0, thread->NumActivations());
     592           4 : }
     593             : 
     594       26643 : TEST(InterpreterLoadWithoutMemory) {
     595           8 :   WasmRunner<int32_t, int32_t> r(ExecutionTier::kInterpreter);
     596           4 :   r.builder().AddMemory(0);
     597           4 :   BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
     598           4 :   CHECK_TRAP32(r.Call(0));
     599           4 : }
     600             : 
     601             : }  // namespace test_run_wasm_interpreter
     602             : }  // namespace wasm
     603             : }  // namespace internal
     604       79917 : }  // namespace v8

Generated by: LCOV version 1.10