LCOV - code coverage report
Current view: top level - test/unittests/wasm - control-transfer-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 146 152 96.1 %
Date: 2019-04-17 Functions: 75 107 70.1 %

          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/unittests/test-utils.h"
       6             : #include "testing/gmock/include/gmock/gmock.h"
       7             : 
       8             : #include "src/v8.h"
       9             : #include "src/wasm/wasm-interpreter.h"
      10             : 
      11             : #include "test/common/wasm/wasm-macro-gen.h"
      12             : 
      13             : using testing::MakeMatcher;
      14             : using testing::Matcher;
      15             : using testing::MatcherInterface;
      16             : using testing::MatchResultListener;
      17             : using testing::StringMatchResultListener;
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : namespace wasm {
      22             : 
      23             : struct ExpectedControlTransfer {
      24             :   pc_t pc;
      25             :   pcdiff_t pc_diff;
      26             :   uint32_t sp_diff;
      27             :   uint32_t target_arity;
      28             : };
      29             : 
      30             : // For nicer error messages.
      31          82 : class ControlTransferMatcher
      32             :     : public MatcherInterface<const ControlTransferEntry&> {
      33             :  public:
      34             :   explicit ControlTransferMatcher(pc_t pc,
      35             :                                   const ExpectedControlTransfer& expected)
      36          41 :       : pc_(pc), expected_(expected) {}
      37             : 
      38           0 :   void DescribeTo(std::ostream* os) const override {
      39           0 :     *os << "@" << pc_ << ": pcdiff = " << expected_.pc_diff
      40           0 :         << ", spdiff = " << expected_.sp_diff
      41           0 :         << ", target arity = " << expected_.target_arity;
      42           0 :   }
      43             : 
      44          41 :   bool MatchAndExplain(const ControlTransferEntry& input,
      45             :                        MatchResultListener* listener) const override {
      46          82 :     if (input.pc_diff == expected_.pc_diff &&
      47          82 :         input.sp_diff == expected_.sp_diff &&
      48          41 :         input.target_arity == expected_.target_arity) {
      49             :       return true;
      50             :     }
      51             :     *listener << "@" << pc_ << ": pcdiff = " << input.pc_diff
      52             :               << ", spdiff = " << input.sp_diff
      53             :               << ", target arity = " << input.target_arity;
      54           0 :     return false;
      55             :   }
      56             : 
      57             :  private:
      58             :   pc_t pc_;
      59             :   const ExpectedControlTransfer& expected_;
      60             : };
      61             : 
      62          60 : class ControlTransferTest : public TestWithZone {
      63             :  public:
      64             :   template <int code_len>
      65          30 :   void CheckTransfers(
      66             :       const byte (&code)[code_len],
      67             :       std::initializer_list<ExpectedControlTransfer> expected_transfers) {
      68             :     byte code_with_end[code_len + 1];  // NOLINT: code_len is a constant here
      69             :     memcpy(code_with_end, code, code_len);
      70          30 :     code_with_end[code_len] = kExprEnd;
      71             : 
      72             :     ControlTransferMap map = WasmInterpreter::ComputeControlTransfersForTesting(
      73          30 :         zone(), nullptr, code_with_end, code_with_end + code_len + 1);
      74             :     // Check all control targets in the map.
      75         112 :     for (auto& expected_transfer : expected_transfers) {
      76          41 :       pc_t pc = expected_transfer.pc;
      77          82 :       EXPECT_TRUE(map.count(pc) > 0) << "expected control target @" << pc;
      78          41 :       if (!map.count(pc)) continue;
      79          41 :       auto& entry = map[pc];
      80         164 :       EXPECT_THAT(entry, MakeMatcher(new ControlTransferMatcher(
      81             :                              pc, expected_transfer)));
      82             :     }
      83             : 
      84             :     // Check there are no other control targets.
      85          30 :     CheckNoOtherTargets(code_with_end, code_with_end + code_len + 1, map,
      86             :                         expected_transfers);
      87          30 :   }
      88             : 
      89          30 :   void CheckNoOtherTargets(
      90             :       const byte* start, const byte* end, ControlTransferMap& map,
      91             :       std::initializer_list<ExpectedControlTransfer> targets) {
      92             :     // Check there are no other control targets.
      93         560 :     for (pc_t pc = 0; start + pc < end; pc++) {
      94             :       bool found = false;
      95         929 :       for (auto& target : targets) {
      96         373 :         if (target.pc == pc) {
      97             :           found = true;
      98             :           break;
      99             :         }
     100             :       }
     101         265 :       if (found) continue;
     102         448 :       EXPECT_TRUE(map.count(pc) == 0) << "expected no control @ +" << pc;
     103             :     }
     104          30 :   }
     105             : };
     106             : 
     107       15444 : TEST_F(ControlTransferTest, SimpleIf) {
     108             :   byte code[] = {
     109             :       kExprI32Const,  // @0
     110             :       0,              // @1
     111             :       kExprIf,        // @2
     112             :       kLocalVoid,     // @3
     113             :       kExprEnd        // @4
     114           1 :   };
     115           1 :   CheckTransfers(code, {{2, 2, 0, 0}});
     116           1 : }
     117             : 
     118       15444 : TEST_F(ControlTransferTest, SimpleIf1) {
     119             :   byte code[] = {
     120             :       kExprI32Const,  // @0
     121             :       0,              // @1
     122             :       kExprIf,        // @2
     123             :       kLocalVoid,     // @3
     124             :       kExprNop,       // @4
     125             :       kExprEnd        // @5
     126           1 :   };
     127           1 :   CheckTransfers(code, {{2, 3, 0, 0}});
     128           1 : }
     129             : 
     130       15444 : TEST_F(ControlTransferTest, SimpleIf2) {
     131             :   byte code[] = {
     132             :       kExprI32Const,  // @0
     133             :       0,              // @1
     134             :       kExprIf,        // @2
     135             :       kLocalVoid,     // @3
     136             :       kExprNop,       // @4
     137             :       kExprNop,       // @5
     138             :       kExprEnd        // @6
     139           1 :   };
     140           1 :   CheckTransfers(code, {{2, 4, 0, 0}});
     141           1 : }
     142             : 
     143       15444 : TEST_F(ControlTransferTest, SimpleIfElse) {
     144             :   byte code[] = {
     145             :       kExprI32Const,  // @0
     146             :       0,              // @1
     147             :       kExprIf,        // @2
     148             :       kLocalVoid,     // @3
     149             :       kExprElse,      // @4
     150             :       kExprEnd        // @5
     151           1 :   };
     152           1 :   CheckTransfers(code, {{2, 3, 0, 0}, {4, 2, 0, 0}});
     153           1 : }
     154             : 
     155       15444 : TEST_F(ControlTransferTest, SimpleIfElse_v1) {
     156             :   byte code[] = {
     157             :       kExprI32Const,  // @0
     158             :       0,              // @1
     159             :       kExprIf,        // @2
     160             :       kLocalVoid,     // @3
     161             :       kExprI32Const,  // @4
     162             :       0,              // @5
     163             :       kExprElse,      // @6
     164             :       kExprI32Const,  // @7
     165             :       0,              // @8
     166             :       kExprEnd        // @9
     167           1 :   };
     168           1 :   CheckTransfers(code, {{2, 5, 0, 0}, {6, 4, 1, 0}});
     169           1 : }
     170             : 
     171       15444 : TEST_F(ControlTransferTest, SimpleIfElse1) {
     172             :   byte code[] = {
     173             :       kExprI32Const,  // @0
     174             :       0,              // @1
     175             :       kExprIf,        // @2
     176             :       kLocalVoid,     // @3
     177             :       kExprElse,      // @4
     178             :       kExprNop,       // @5
     179             :       kExprEnd        // @6
     180           1 :   };
     181           1 :   CheckTransfers(code, {{2, 3, 0, 0}, {4, 3, 0, 0}});
     182           1 : }
     183             : 
     184       15444 : TEST_F(ControlTransferTest, IfBr) {
     185             :   byte code[] = {
     186             :       kExprI32Const,  // @0
     187             :       0,              // @1
     188             :       kExprIf,        // @2
     189             :       kLocalVoid,     // @3
     190             :       kExprBr,        // @4
     191             :       0,              // @5
     192             :       kExprEnd        // @6
     193           1 :   };
     194           1 :   CheckTransfers(code, {{2, 4, 0, 0}, {4, 3, 0, 0}});
     195           1 : }
     196             : 
     197       15444 : TEST_F(ControlTransferTest, IfBrElse) {
     198             :   byte code[] = {
     199             :       kExprI32Const,  // @0
     200             :       0,              // @1
     201             :       kExprIf,        // @2
     202             :       kLocalVoid,     // @3
     203             :       kExprBr,        // @4
     204             :       0,              // @5
     205             :       kExprElse,      // @6
     206             :       kExprEnd        // @7
     207           1 :   };
     208           1 :   CheckTransfers(code, {{2, 5, 0, 0}, {4, 4, 0, 0}, {6, 2, 0, 0}});
     209           1 : }
     210             : 
     211       15444 : TEST_F(ControlTransferTest, IfElseBr) {
     212             :   byte code[] = {
     213             :       kExprI32Const,  // @0
     214             :       0,              // @1
     215             :       kExprIf,        // @2
     216             :       kLocalVoid,     // @3
     217             :       kExprElse,      // @4
     218             :       kExprBr,        // @5
     219             :       0,              // @6
     220             :       kExprEnd        // @7
     221           1 :   };
     222           1 :   CheckTransfers(code, {{2, 3, 0, 0}, {4, 4, 0, 0}, {5, 3, 0, 0}});
     223           1 : }
     224             : 
     225       15444 : TEST_F(ControlTransferTest, BlockEmpty) {
     226             :   byte code[] = {
     227             :       kExprBlock,  // @0
     228             :       kLocalVoid,  // @1
     229             :       kExprEnd     // @2
     230           1 :   };
     231           1 :   CheckTransfers(code, {});
     232           1 : }
     233             : 
     234       15444 : TEST_F(ControlTransferTest, Br0) {
     235             :   byte code[] = {
     236             :       kExprBlock,  // @0
     237             :       kLocalVoid,  // @1
     238             :       kExprBr,     // @2
     239             :       0,           // @3
     240             :       kExprEnd     // @4
     241           1 :   };
     242           1 :   CheckTransfers(code, {{2, 3, 0, 0}});
     243           1 : }
     244             : 
     245       15444 : TEST_F(ControlTransferTest, Br1) {
     246             :   byte code[] = {
     247             :       kExprBlock,  // @0
     248             :       kLocalVoid,  // @1
     249             :       kExprNop,    // @2
     250             :       kExprBr,     // @3
     251             :       0,           // @4
     252             :       kExprEnd     // @5
     253           1 :   };
     254           1 :   CheckTransfers(code, {{3, 3, 0, 0}});
     255           1 : }
     256             : 
     257       15444 : TEST_F(ControlTransferTest, Br_v1a) {
     258             :   byte code[] = {
     259             :       kExprBlock,     // @0
     260             :       kLocalVoid,     // @1
     261             :       kExprI32Const,  // @2
     262             :       0,              // @3
     263             :       kExprBr,        // @4
     264             :       0,              // @5
     265             :       kExprEnd        // @6
     266           1 :   };
     267           1 :   CheckTransfers(code, {{4, 3, 1, 0}});
     268           1 : }
     269             : 
     270       15444 : TEST_F(ControlTransferTest, Br_v1b) {
     271             :   byte code[] = {
     272             :       kExprBlock,     // @0
     273             :       kLocalVoid,     // @1
     274             :       kExprI32Const,  // @2
     275             :       0,              // @3
     276             :       kExprBr,        // @4
     277             :       0,              // @5
     278             :       kExprEnd        // @6
     279           1 :   };
     280           1 :   CheckTransfers(code, {{4, 3, 1, 0}});
     281           1 : }
     282             : 
     283       15444 : TEST_F(ControlTransferTest, Br_v1c) {
     284             :   byte code[] = {
     285             :       kExprI32Const,  // @0
     286             :       0,              // @1
     287             :       kExprBlock,     // @2
     288             :       kLocalVoid,     // @3
     289             :       kExprBr,        // @4
     290             :       0,              // @5
     291             :       kExprEnd        // @6
     292           1 :   };
     293           1 :   CheckTransfers(code, {{4, 3, 0, 0}});
     294           1 : }
     295             : 
     296       15444 : TEST_F(ControlTransferTest, Br_v1d) {
     297             :   byte code[] = {
     298             :       kExprBlock,     // @0
     299             :       kLocalI32,      // @1
     300             :       kExprI32Const,  // @2
     301             :       0,              // @3
     302             :       kExprBr,        // @4
     303             :       0,              // @5
     304             :       kExprEnd        // @6
     305           1 :   };
     306           1 :   CheckTransfers(code, {{4, 3, 1, 1}});
     307           1 : }
     308             : 
     309       15444 : TEST_F(ControlTransferTest, Br2) {
     310             :   byte code[] = {
     311             :       kExprBlock,  // @0
     312             :       kLocalVoid,  // @1
     313             :       kExprNop,    // @2
     314             :       kExprNop,    // @3
     315             :       kExprBr,     // @4
     316             :       0,           // @5
     317             :       kExprEnd     // @6
     318           1 :   };
     319           1 :   CheckTransfers(code, {{4, 3, 0, 0}});
     320           1 : }
     321             : 
     322       15444 : TEST_F(ControlTransferTest, Br0b) {
     323             :   byte code[] = {
     324             :       kExprBlock,  // @0
     325             :       kLocalVoid,  // @1
     326             :       kExprBr,     // @2
     327             :       0,           // @3
     328             :       kExprNop,    // @4
     329             :       kExprEnd     // @5
     330           1 :   };
     331           1 :   CheckTransfers(code, {{2, 4, 0, 0}});
     332           1 : }
     333             : 
     334       15444 : TEST_F(ControlTransferTest, Br0c) {
     335             :   byte code[] = {
     336             :       kExprBlock,  // @0
     337             :       kLocalVoid,  // @1
     338             :       kExprBr,     // @2
     339             :       0,           // @3
     340             :       kExprNop,    // @4
     341             :       kExprNop,    // @5
     342             :       kExprEnd     // @6
     343           1 :   };
     344           1 :   CheckTransfers(code, {{2, 5, 0, 0}});
     345           1 : }
     346             : 
     347       15444 : TEST_F(ControlTransferTest, SimpleLoop1) {
     348             :   byte code[] = {
     349             :       kExprLoop,   // @0
     350             :       kLocalVoid,  // @1
     351             :       kExprBr,     // @2
     352             :       0,           // @3
     353             :       kExprEnd     // @4
     354           1 :   };
     355           1 :   CheckTransfers(code, {{2, -2, 0, 0}});
     356           1 : }
     357             : 
     358       15444 : TEST_F(ControlTransferTest, SimpleLoop2) {
     359             :   byte code[] = {
     360             :       kExprLoop,   // @0
     361             :       kLocalVoid,  // @1
     362             :       kExprNop,    // @2
     363             :       kExprBr,     // @3
     364             :       0,           // @4
     365             :       kExprEnd     // @5
     366           1 :   };
     367           1 :   CheckTransfers(code, {{3, -3, 0, 0}});
     368           1 : }
     369             : 
     370       15444 : TEST_F(ControlTransferTest, SimpleLoopExit1) {
     371             :   byte code[] = {
     372             :       kExprLoop,   // @0
     373             :       kLocalVoid,  // @1
     374             :       kExprBr,     // @2
     375             :       1,           // @3
     376             :       kExprEnd     // @4
     377           1 :   };
     378           1 :   CheckTransfers(code, {{2, 4, 0, 0}});
     379           1 : }
     380             : 
     381       15444 : TEST_F(ControlTransferTest, SimpleLoopExit2) {
     382             :   byte code[] = {
     383             :       kExprLoop,   // @0
     384             :       kLocalVoid,  // @1
     385             :       kExprNop,    // @2
     386             :       kExprBr,     // @3
     387             :       1,           // @4
     388             :       kExprEnd     // @5
     389           1 :   };
     390           1 :   CheckTransfers(code, {{3, 4, 0, 0}});
     391           1 : }
     392             : 
     393       15444 : TEST_F(ControlTransferTest, BrTable0) {
     394             :   byte code[] = {
     395             :       kExprBlock,     // @0
     396             :       kLocalVoid,     // @1
     397             :       kExprI32Const,  // @2
     398             :       0,              // @3
     399             :       kExprBrTable,   // @4
     400             :       0,              // @5
     401             :       U32V_1(0),      // @6
     402             :       kExprEnd        // @7
     403           1 :   };
     404           1 :   CheckTransfers(code, {{4, 4, 0, 0}});
     405           1 : }
     406             : 
     407       15444 : TEST_F(ControlTransferTest, BrTable0_v1a) {
     408             :   byte code[] = {
     409             :       kExprBlock,     // @0
     410             :       kLocalVoid,     // @1
     411             :       kExprI32Const,  // @2
     412             :       0,              // @3
     413             :       kExprI32Const,  // @4
     414             :       0,              // @5
     415             :       kExprBrTable,   // @6
     416             :       0,              // @7
     417             :       U32V_1(0),      // @8
     418             :       kExprEnd        // @9
     419           1 :   };
     420           1 :   CheckTransfers(code, {{6, 4, 1, 0}});
     421           1 : }
     422             : 
     423       15444 : TEST_F(ControlTransferTest, BrTable0_v1b) {
     424             :   byte code[] = {
     425             :       kExprBlock,     // @0
     426             :       kLocalVoid,     // @1
     427             :       kExprI32Const,  // @2
     428             :       0,              // @3
     429             :       kExprI32Const,  // @4
     430             :       0,              // @5
     431             :       kExprBrTable,   // @6
     432             :       0,              // @7
     433             :       U32V_1(0),      // @8
     434             :       kExprEnd        // @9
     435           1 :   };
     436           1 :   CheckTransfers(code, {{6, 4, 1, 0}});
     437           1 : }
     438             : 
     439       15444 : TEST_F(ControlTransferTest, BrTable1) {
     440             :   byte code[] = {
     441             :       kExprBlock,     // @0
     442             :       kLocalVoid,     // @1
     443             :       kExprI32Const,  // @2
     444             :       0,              // @3
     445             :       kExprBrTable,   // @4
     446             :       1,              // @5
     447             :       U32V_1(0),      // @6
     448             :       U32V_1(0),      // @7
     449             :       kExprEnd        // @8
     450           1 :   };
     451           1 :   CheckTransfers(code, {{4, 5, 0, 0}, {5, 4, 0, 0}});
     452           1 : }
     453             : 
     454       15444 : TEST_F(ControlTransferTest, BrTable2) {
     455             :   byte code[] = {
     456             :       kExprBlock,     // @0
     457             :       kLocalVoid,     // @1
     458             :       kExprBlock,     // @2
     459             :       kLocalVoid,     // @3
     460             :       kExprI32Const,  // @4
     461             :       0,              // @5
     462             :       kExprBrTable,   // @6
     463             :       2,              // @7
     464             :       U32V_1(0),      // @8
     465             :       U32V_1(0),      // @9
     466             :       U32V_1(1),      // @10
     467             :       kExprEnd,       // @11
     468             :       kExprEnd        // @12
     469           1 :   };
     470           1 :   CheckTransfers(code, {{6, 6, 0, 0}, {7, 5, 0, 0}, {8, 5, 0, 0}});
     471           1 : }
     472             : 
     473       15444 : TEST_F(ControlTransferTest, BiggerSpDiffs) {
     474             :   byte code[] = {
     475             :       kExprBlock,     // @0
     476             :       kLocalI32,      // @1
     477             :       kExprI32Const,  // @2
     478             :       0,              // @3
     479             :       kExprBlock,     // @4
     480             :       kLocalVoid,     // @5
     481             :       kExprI32Const,  // @6
     482             :       0,              // @7
     483             :       kExprI32Const,  // @8
     484             :       0,              // @9
     485             :       kExprI32Const,  // @10
     486             :       0,              // @11
     487             :       kExprBrIf,      // @12
     488             :       0,              // @13
     489             :       kExprBr,        // @14
     490             :       1,              // @15
     491             :       kExprEnd,       // @16
     492             :       kExprEnd        // @17
     493           1 :   };
     494           1 :   CheckTransfers(code, {{12, 5, 2, 0}, {14, 4, 3, 1}});
     495           1 : }
     496             : 
     497       15444 : TEST_F(ControlTransferTest, NoInfoForUnreachableCode) {
     498             :   byte code[] = {
     499             :       kExprBlock,        // @0
     500             :       kLocalVoid,        // @1
     501             :       kExprBr,           // @2
     502             :       0,                 // @3
     503             :       kExprBr,           // @4 -- no control transfer entry!
     504             :       1,                 // @5
     505             :       kExprEnd,          // @6
     506             :       kExprBlock,        // @7
     507             :       kLocalVoid,        // @8
     508             :       kExprUnreachable,  // @9
     509             :       kExprI32Const,     // @10
     510             :       0,                 // @11
     511             :       kExprIf,           // @12 -- no control transfer entry!
     512             :       kLocalVoid,        // @13
     513             :       kExprBr,           // @14 -- no control transfer entry!
     514             :       0,                 // @15
     515             :       kExprElse,         // @16 -- no control transfer entry!
     516             :       kExprEnd,          // @17
     517             :       kExprEnd           // @18
     518           1 :   };
     519           1 :   CheckTransfers(code, {{2, 5, 0, 0}});
     520           1 : }
     521             : 
     522             : }  // namespace wasm
     523             : }  // namespace internal
     524        9264 : }  // namespace v8

Generated by: LCOV version 1.10