LCOV - code coverage report
Current view: top level - test/unittests/interpreter - interpreter-assembler-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 185 266 69.5 %
Date: 2019-04-18 Functions: 30 40 75.0 %

          Line data    Source code
       1             : // Copyright 2015 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/interpreter/interpreter-assembler-unittest.h"
       6             : 
       7             : #include "src/code-factory.h"
       8             : #include "src/compiler/node-properties.h"
       9             : #include "src/compiler/node.h"
      10             : #include "src/interface-descriptors.h"
      11             : #include "src/isolate.h"
      12             : #include "src/objects-inl.h"
      13             : #include "test/unittests/compiler/compiler-test-utils.h"
      14             : #include "test/unittests/compiler/node-test-utils.h"
      15             : 
      16             : using ::testing::_;
      17             : using v8::internal::compiler::Node;
      18             : 
      19             : namespace c = v8::internal::compiler;
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace interpreter {
      24             : namespace interpreter_assembler_unittest {
      25             : 
      26        1446 : InterpreterAssemblerTestState::InterpreterAssemblerTestState(
      27             :     InterpreterAssemblerTest* test, Bytecode bytecode)
      28             :     : compiler::CodeAssemblerState(
      29             :           test->isolate(), test->zone(), InterpreterDispatchDescriptor{},
      30             :           Code::BYTECODE_HANDLER, Bytecodes::ToString(bytecode),
      31        4338 :           PoisoningMitigationLevel::kPoisonCriticalOnly) {}
      32             : 
      33             : const interpreter::Bytecode kBytecodes[] = {
      34             : #define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
      35             :     BYTECODE_LIST(DEFINE_BYTECODE)
      36             : #undef DEFINE_BYTECODE
      37             : };
      38             : 
      39             : 
      40        1446 : InterpreterAssemblerTest::InterpreterAssemblerForTest::
      41        1446 :     ~InterpreterAssemblerForTest() {
      42             :   // Tests don't necessarily read and write accumulator but
      43             :   // InterpreterAssembler checks accumulator uses.
      44        1446 :   if (Bytecodes::ReadsAccumulator(bytecode())) {
      45         856 :     GetAccumulator();
      46             :   }
      47        1446 :   if (Bytecodes::WritesAccumulator(bytecode())) {
      48        1028 :     SetAccumulator(nullptr);
      49             :   }
      50        1446 : }
      51             : 
      52        2871 : Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
      53             :     const Matcher<c::LoadRepresentation>& rep_matcher,
      54             :     const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
      55             :     LoadSensitivity needs_poisoning) {
      56        2871 :   CHECK_NE(LoadSensitivity::kUnsafe, needs_poisoning);
      57        2871 :   CHECK_NE(PoisoningMitigationLevel::kPoisonAll, poisoning_level());
      58        2871 :   if (poisoning_level() == PoisoningMitigationLevel::kPoisonCriticalOnly &&
      59             :       needs_poisoning == LoadSensitivity::kCritical) {
      60             :     return ::i::compiler::IsPoisonedLoad(rep_matcher, base_matcher,
      61        3807 :                                          index_matcher, _, _);
      62             :   }
      63        4806 :   return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
      64             : }
      65             : 
      66           0 : Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
      67             :     const Matcher<c::StoreRepresentation>& rep_matcher,
      68             :     const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
      69             :     const Matcher<Node*>& value_matcher) {
      70             :   return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
      71           0 :                                 value_matcher, _, _);
      72             : }
      73             : 
      74           0 : Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsWordNot(
      75             :     const Matcher<Node*>& value_matcher) {
      76             :   return kSystemPointerSize == 8
      77           0 :              ? IsWord64Xor(value_matcher, c::IsInt64Constant(-1))
      78           0 :              : IsWord32Xor(value_matcher, c::IsInt32Constant(-1));
      79             : }
      80             : 
      81             : Matcher<Node*>
      82         189 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedByteOperand(
      83             :     int offset, LoadSensitivity needs_poisoning) {
      84             :   return IsLoad(
      85             :       MachineType::Uint8(),
      86         567 :       c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
      87         189 :       c::IsIntPtrAdd(
      88         567 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
      89         378 :           c::IsIntPtrConstant(offset)),
      90         567 :       needs_poisoning);
      91             : }
      92             : 
      93             : Matcher<Node*>
      94         130 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedByteOperand(
      95             :     int offset, LoadSensitivity needs_poisoning) {
      96             :   return IsLoad(
      97             :       MachineType::Int8(),
      98         390 :       c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
      99         130 :       c::IsIntPtrAdd(
     100         390 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     101         260 :           c::IsIntPtrConstant(offset)),
     102         390 :       needs_poisoning);
     103             : }
     104             : 
     105             : Matcher<Node*>
     106         171 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedShortOperand(
     107             :     int offset, LoadSensitivity needs_poisoning) {
     108         171 :   if (TargetSupportsUnalignedAccess()) {
     109             :     return IsLoad(
     110             :         MachineType::Uint16(),
     111         513 :         c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     112         171 :         c::IsIntPtrAdd(
     113         513 :             c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     114         342 :             c::IsIntPtrConstant(offset)),
     115         342 :         needs_poisoning);
     116             :   } else {
     117             : #if V8_TARGET_LITTLE_ENDIAN
     118             :     const int kStep = -1;
     119             :     const int kMsbOffset = 1;
     120             : #elif V8_TARGET_BIG_ENDIAN
     121             :     const int kStep = 1;
     122             :     const int kMsbOffset = 0;
     123             : #else
     124             : #error "Unknown Architecture"
     125             : #endif
     126           0 :     Matcher<Node*> bytes[2];
     127           0 :     for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
     128           0 :       bytes[i] = IsLoad(
     129             :           MachineType::Uint8(),
     130           0 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     131           0 :           c::IsIntPtrAdd(
     132           0 :               c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     133           0 :               c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
     134             :           needs_poisoning);
     135             :     }
     136             :     return c::IsWord32Or(
     137           0 :         c::IsWord32Shl(bytes[0], c::IsInt32Constant(kBitsPerByte)), bytes[1]);
     138             :   }
     139             : }
     140             : 
     141             : Matcher<Node*>
     142         130 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedShortOperand(
     143             :     int offset, LoadSensitivity needs_poisoning) {
     144         130 :   if (TargetSupportsUnalignedAccess()) {
     145             :     return IsLoad(
     146             :         MachineType::Int16(),
     147         390 :         c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     148         130 :         c::IsIntPtrAdd(
     149         390 :             c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     150         260 :             c::IsIntPtrConstant(offset)),
     151         260 :         needs_poisoning);
     152             :   } else {
     153             : #if V8_TARGET_LITTLE_ENDIAN
     154             :     const int kStep = -1;
     155             :     const int kMsbOffset = 1;
     156             : #elif V8_TARGET_BIG_ENDIAN
     157             :     const int kStep = 1;
     158             :     const int kMsbOffset = 0;
     159             : #else
     160             : #error "Unknown Architecture"
     161             : #endif
     162           0 :     Matcher<Node*> bytes[2];
     163           0 :     for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
     164           0 :       bytes[i] = IsLoad(
     165             :           (i == 0) ? MachineType::Int8() : MachineType::Uint8(),
     166           0 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     167           0 :           c::IsIntPtrAdd(
     168           0 :               c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     169           0 :               c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
     170             :           needs_poisoning);
     171             :     }
     172             :     return c::IsWord32Or(
     173           0 :         c::IsWord32Shl(bytes[0], c::IsInt32Constant(kBitsPerByte)), bytes[1]);
     174             :   }
     175             : }
     176             : 
     177             : Matcher<Node*>
     178         159 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedQuadOperand(
     179             :     int offset, LoadSensitivity needs_poisoning) {
     180         159 :   if (TargetSupportsUnalignedAccess()) {
     181             :     return IsLoad(
     182             :         MachineType::Uint32(),
     183         477 :         c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     184         159 :         c::IsIntPtrAdd(
     185         477 :             c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     186         318 :             c::IsIntPtrConstant(offset)),
     187         318 :         needs_poisoning);
     188             :   } else {
     189             : #if V8_TARGET_LITTLE_ENDIAN
     190             :     const int kStep = -1;
     191             :     const int kMsbOffset = 3;
     192             : #elif V8_TARGET_BIG_ENDIAN
     193             :     const int kStep = 1;
     194             :     const int kMsbOffset = 0;
     195             : #else
     196             : #error "Unknown Architecture"
     197             : #endif
     198           0 :     Matcher<Node*> bytes[4];
     199           0 :     for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
     200           0 :       bytes[i] = IsLoad(
     201             :           MachineType::Uint8(),
     202           0 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     203           0 :           c::IsIntPtrAdd(
     204           0 :               c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     205           0 :               c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
     206             :           needs_poisoning);
     207             :     }
     208             :     return c::IsWord32Or(
     209           0 :         c::IsWord32Shl(bytes[0], c::IsInt32Constant(3 * kBitsPerByte)),
     210           0 :         c::IsWord32Or(
     211           0 :             c::IsWord32Shl(bytes[1], c::IsInt32Constant(2 * kBitsPerByte)),
     212           0 :             c::IsWord32Or(
     213           0 :                 c::IsWord32Shl(bytes[2], c::IsInt32Constant(1 * kBitsPerByte)),
     214           0 :                 bytes[3])));
     215             :   }
     216             : }
     217             : 
     218             : Matcher<Node*>
     219         130 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedQuadOperand(
     220             :     int offset, LoadSensitivity needs_poisoning) {
     221         130 :   if (TargetSupportsUnalignedAccess()) {
     222             :     return IsLoad(
     223             :         MachineType::Int32(),
     224         390 :         c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     225         130 :         c::IsIntPtrAdd(
     226         390 :             c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     227         260 :             c::IsIntPtrConstant(offset)),
     228         260 :         needs_poisoning);
     229             :   } else {
     230             : #if V8_TARGET_LITTLE_ENDIAN
     231             :     const int kStep = -1;
     232             :     int kMsbOffset = 3;
     233             : #elif V8_TARGET_BIG_ENDIAN
     234             :     const int kStep = 1;
     235             :     int kMsbOffset = 0;
     236             : #else
     237             : #error "Unknown Architecture"
     238             : #endif
     239           0 :     Matcher<Node*> bytes[4];
     240           0 :     for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
     241           0 :       bytes[i] = IsLoad(
     242             :           (i == 0) ? MachineType::Int8() : MachineType::Uint8(),
     243           0 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     244           0 :           c::IsIntPtrAdd(
     245           0 :               c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     246           0 :               c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
     247             :           needs_poisoning);
     248             :     }
     249             :     return c::IsWord32Or(
     250           0 :         c::IsWord32Shl(bytes[0], c::IsInt32Constant(3 * kBitsPerByte)),
     251           0 :         c::IsWord32Or(
     252           0 :             c::IsWord32Shl(bytes[1], c::IsInt32Constant(2 * kBitsPerByte)),
     253           0 :             c::IsWord32Or(
     254           0 :                 c::IsWord32Shl(bytes[2], c::IsInt32Constant(1 * kBitsPerByte)),
     255           0 :                 bytes[3])));
     256             :   }
     257             : }
     258             : 
     259             : Matcher<Node*>
     260         390 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedOperand(
     261             :     int offset, OperandSize operand_size, LoadSensitivity needs_poisoning) {
     262         390 :   switch (operand_size) {
     263             :     case OperandSize::kByte:
     264         130 :       return IsSignedByteOperand(offset, needs_poisoning);
     265             :     case OperandSize::kShort:
     266         130 :       return IsSignedShortOperand(offset, needs_poisoning);
     267             :     case OperandSize::kQuad:
     268         130 :       return IsSignedQuadOperand(offset, needs_poisoning);
     269             :     case OperandSize::kNone:
     270           0 :       UNREACHABLE();
     271             :   }
     272           0 :   return nullptr;
     273             : }
     274             : 
     275             : Matcher<Node*>
     276         519 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedOperand(
     277             :     int offset, OperandSize operand_size, LoadSensitivity needs_poisoning) {
     278         519 :   switch (operand_size) {
     279             :     case OperandSize::kByte:
     280         189 :       return IsUnsignedByteOperand(offset, needs_poisoning);
     281             :     case OperandSize::kShort:
     282         171 :       return IsUnsignedShortOperand(offset, needs_poisoning);
     283             :     case OperandSize::kQuad:
     284         159 :       return IsUnsignedQuadOperand(offset, needs_poisoning);
     285             :     case OperandSize::kNone:
     286           0 :       UNREACHABLE();
     287             :   }
     288           0 :   return nullptr;
     289             : }
     290             : 
     291             : Matcher<compiler::Node*>
     292         336 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoadRegisterOperand(
     293             :     int offset, OperandSize operand_size) {
     294             :   Matcher<compiler::Node*> reg_operand = IsChangeInt32ToIntPtr(
     295         672 :       IsSignedOperand(offset, operand_size, LoadSensitivity::kSafe));
     296        1008 :   return IsBitcastWordToTagged(IsLoad(
     297         672 :       MachineType::Pointer(), c::IsLoadParentFramePointer(),
     298        1008 :       c::IsWordShl(reg_operand, c::IsIntPtrConstant(kSystemPointerSizeLog2)),
     299         672 :       LoadSensitivity::kCritical));
     300             : }
     301             : 
     302       15419 : TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
     303             :   // If debug code is enabled we emit extra code in Jump.
     304           2 :   if (FLAG_debug_code) return;
     305             : 
     306           1 :   int jump_offsets[] = {-9710, -77, 0, +3, +97109};
     307           3 :   TRACED_FOREACH(int, jump_offset, jump_offsets) {
     308           3 :     TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     309           3 :       if (!interpreter::Bytecodes::IsJump(bytecode)) return;
     310             : 
     311           0 :       InterpreterAssemblerTestState state(this, bytecode);
     312           0 :       InterpreterAssemblerForTest m(&state, bytecode);
     313           0 :       Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
     314             : 
     315             :       Matcher<Node*> next_bytecode_offset_matcher = c::IsIntPtrAdd(
     316           0 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
     317           0 :           c::IsIntPtrConstant(jump_offset));
     318             :       Matcher<Node*> target_bytecode_matcher =
     319           0 :           m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
     320             :       target_bytecode_matcher =
     321           0 :           c::IsChangeUint32ToWord(target_bytecode_matcher);
     322             :       Matcher<Node*> code_target_matcher = m.IsLoad(
     323             :           MachineType::Pointer(),
     324           0 :           c::IsParameter(InterpreterDispatchDescriptor::kDispatchTable),
     325           0 :           c::IsWordShl(target_bytecode_matcher,
     326           0 :                        c::IsIntPtrConstant(kSystemPointerSizeLog2)));
     327             : 
     328           0 :       EXPECT_THAT(
     329             :           tail_call_node,
     330             :           c::IsTailCall(
     331             :               _, code_target_matcher,
     332             :               c::IsParameter(InterpreterDispatchDescriptor::kAccumulator),
     333             :               next_bytecode_offset_matcher, _,
     334             :               c::IsParameter(InterpreterDispatchDescriptor::kDispatchTable), _,
     335           0 :               _));
     336             :     }
     337             :   }
     338             : }
     339             : 
     340       15419 : TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
     341             :   static const OperandScale kOperandScales[] = {
     342             :       OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
     343         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     344        2340 :     TRACED_FOREACH(interpreter::OperandScale, operand_scale, kOperandScales) {
     345         540 :       InterpreterAssemblerTestState state(this, bytecode);
     346        1080 :       InterpreterAssemblerForTest m(&state, bytecode, operand_scale);
     347             :       int number_of_operands =
     348         540 :           interpreter::Bytecodes::NumberOfOperands(bytecode);
     349        2358 :       for (int i = 0; i < number_of_operands; i++) {
     350         909 :         int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i,
     351         909 :                                                               operand_scale);
     352             :         OperandType operand_type =
     353         909 :             interpreter::Bytecodes::GetOperandType(bytecode, i);
     354             :         OperandSize operand_size =
     355         909 :             Bytecodes::SizeOfOperand(operand_type, operand_scale);
     356         909 :         switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
     357             :           case interpreter::OperandType::kRegCount:
     358         156 :             EXPECT_THAT(m.BytecodeOperandCount(i),
     359             :                         m.IsUnsignedOperand(offset, operand_size,
     360           0 :                                             LoadSensitivity::kCritical));
     361          39 :             break;
     362             :           case interpreter::OperandType::kFlag8:
     363         108 :             EXPECT_THAT(m.BytecodeOperandFlag(i),
     364             :                         m.IsUnsignedOperand(offset, operand_size,
     365           0 :                                             LoadSensitivity::kCritical));
     366          27 :             break;
     367             :           case interpreter::OperandType::kIdx:
     368        1800 :             EXPECT_THAT(m.BytecodeOperandIdx(i),
     369             :                         c::IsChangeUint32ToWord(m.IsUnsignedOperand(
     370           0 :                             offset, operand_size, LoadSensitivity::kCritical)));
     371         360 :             break;
     372             :           case interpreter::OperandType::kNativeContextIndex:
     373          15 :             EXPECT_THAT(m.BytecodeOperandNativeContextIndex(i),
     374             :                         c::IsChangeUint32ToWord(m.IsUnsignedOperand(
     375           0 :                             offset, operand_size, LoadSensitivity::kCritical)));
     376           3 :             break;
     377             :           case interpreter::OperandType::kUImm:
     378         300 :             EXPECT_THAT(m.BytecodeOperandUImm(i),
     379             :                         m.IsUnsignedOperand(offset, operand_size,
     380           0 :                                             LoadSensitivity::kCritical));
     381          75 :             break;
     382             :           case interpreter::OperandType::kImm: {
     383         216 :             EXPECT_THAT(m.BytecodeOperandImm(i),
     384             :                         m.IsSignedOperand(offset, operand_size,
     385           0 :                                           LoadSensitivity::kCritical));
     386          54 :             break;
     387             :           }
     388             :           case interpreter::OperandType::kRuntimeId:
     389          48 :             EXPECT_THAT(m.BytecodeOperandRuntimeId(i),
     390             :                         m.IsUnsignedOperand(offset, operand_size,
     391           0 :                                             LoadSensitivity::kCritical));
     392          12 :             break;
     393             :           case interpreter::OperandType::kIntrinsicId:
     394          12 :             EXPECT_THAT(m.BytecodeOperandIntrinsicId(i),
     395             :                         m.IsUnsignedOperand(offset, operand_size,
     396           0 :                                             LoadSensitivity::kCritical));
     397           3 :             break;
     398             :           case interpreter::OperandType::kRegList:
     399             :           case interpreter::OperandType::kReg:
     400             :           case interpreter::OperandType::kRegPair:
     401             :           case interpreter::OperandType::kRegOut:
     402             :           case interpreter::OperandType::kRegOutList:
     403             :           case interpreter::OperandType::kRegOutPair:
     404             :           case interpreter::OperandType::kRegOutTriple:
     405        1344 :             EXPECT_THAT(m.LoadRegisterAtOperandIndex(i),
     406           0 :                         m.IsLoadRegisterOperand(offset, operand_size));
     407         336 :             break;
     408             :           case interpreter::OperandType::kNone:
     409           0 :             UNREACHABLE();
     410             :             break;
     411             :         }
     412             :       }
     413             :     }
     414             :   }
     415           1 : }
     416             : 
     417       15419 : TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
     418         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     419         180 :     InterpreterAssemblerTestState state(this, bytecode);
     420         360 :     InterpreterAssemblerForTest m(&state, bytecode);
     421        1620 :     EXPECT_THAT(
     422             :         m.GetContext(),
     423             :         IsBitcastWordToTagged(m.IsLoad(
     424             :             MachineType::Pointer(), c::IsLoadParentFramePointer(),
     425             :             c::IsIntPtrConstant(Register::current_context().ToOperand() *
     426           0 :                                 kSystemPointerSize))));
     427             :   }
     428           1 : }
     429             : 
     430       15419 : TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
     431         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     432         180 :     InterpreterAssemblerTestState state(this, bytecode);
     433         360 :     InterpreterAssemblerForTest m(&state, bytecode);
     434             :     {
     435         360 :       Node* index = m.IntPtrConstant(2);
     436         180 :       Node* load_constant = m.LoadConstantPoolEntry(index);
     437             : #ifdef V8_COMPRESS_POINTERS
     438             :       Matcher<Node*> constant_pool_matcher =
     439             :           IsChangeCompressedToTagged(m.IsLoad(
     440             :               MachineType::AnyCompressed(),
     441             :               c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     442             :               c::IsIntPtrConstant(BytecodeArray::kConstantPoolOffset -
     443             :                                   kHeapObjectTag)));
     444             :       EXPECT_THAT(load_constant,
     445             :                   IsChangeCompressedToTagged(m.IsLoad(
     446             :                       MachineType::AnyCompressed(), constant_pool_matcher,
     447             :                       c::IsIntPtrConstant(FixedArray::OffsetOfElementAt(2) -
     448             :                                           kHeapObjectTag),
     449             :                       LoadSensitivity::kCritical)));
     450             : #else
     451             :       Matcher<Node*> constant_pool_matcher = m.IsLoad(
     452             :           MachineType::AnyTagged(),
     453         540 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     454         360 :           c::IsIntPtrConstant(BytecodeArray::kConstantPoolOffset -
     455         360 :                               kHeapObjectTag));
     456        1080 :       EXPECT_THAT(
     457             :           load_constant,
     458             :           m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
     459             :                    c::IsIntPtrConstant(FixedArray::OffsetOfElementAt(2) -
     460             :                                        kHeapObjectTag),
     461           0 :                    LoadSensitivity::kCritical));
     462             : #endif
     463             :     }
     464             :     {
     465         180 :       Node* index = m.Parameter(2);
     466         180 :       Node* load_constant = m.LoadConstantPoolEntry(index);
     467             : #if V8_COMPRESS_POINTERS
     468             :       Matcher<Node*> constant_pool_matcher =
     469             :           IsChangeCompressedToTagged(m.IsLoad(
     470             :               MachineType::AnyCompressed(),
     471             :               c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     472             :               c::IsIntPtrConstant(BytecodeArray::kConstantPoolOffset -
     473             :                                   kHeapObjectTag)));
     474             :       EXPECT_THAT(
     475             :           load_constant,
     476             :           IsChangeCompressedToTagged(m.IsLoad(
     477             :               MachineType::AnyCompressed(), constant_pool_matcher,
     478             :               c::IsIntPtrAdd(
     479             :                   c::IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
     480             :                   c::IsWordShl(index, c::IsIntPtrConstant(kTaggedSizeLog2))),
     481             :               LoadSensitivity::kCritical)));
     482             : #else
     483             :       Matcher<Node*> constant_pool_matcher = m.IsLoad(
     484             :           MachineType::AnyTagged(),
     485         540 :           c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
     486         360 :           c::IsIntPtrConstant(BytecodeArray::kConstantPoolOffset -
     487         360 :                               kHeapObjectTag));
     488        2160 :       EXPECT_THAT(
     489             :           load_constant,
     490             :           m.IsLoad(
     491             :               MachineType::AnyTagged(), constant_pool_matcher,
     492             :               c::IsIntPtrAdd(
     493             :                   c::IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
     494             :                   c::IsWordShl(index, c::IsIntPtrConstant(kTaggedSizeLog2))),
     495           0 :               LoadSensitivity::kCritical));
     496             : #endif
     497             :     }
     498             :   }
     499           1 : }
     500             : 
     501       15419 : TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
     502         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     503         180 :     InterpreterAssemblerTestState state(this, bytecode);
     504         360 :     InterpreterAssemblerForTest m(&state, bytecode);
     505         360 :     Node* object = m.IntPtrConstant(0xDEADBEEF);
     506             :     int offset = 16;
     507         180 :     Node* load_field = m.LoadObjectField(object, offset);
     508             : #ifdef V8_COMPRESS_POINTERS
     509             :     EXPECT_THAT(load_field, IsChangeCompressedToTagged(m.IsLoad(
     510             :                                 MachineType::AnyCompressed(), object,
     511             :                                 c::IsIntPtrConstant(offset - kHeapObjectTag))));
     512             : #else
     513        1260 :     EXPECT_THAT(load_field,
     514             :                 m.IsLoad(MachineType::AnyTagged(), object,
     515           0 :                          c::IsIntPtrConstant(offset - kHeapObjectTag)));
     516             : #endif
     517             :   }
     518           1 : }
     519             : 
     520       15419 : TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
     521         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     522         180 :     InterpreterAssemblerTestState state(this, bytecode);
     523         360 :     InterpreterAssemblerForTest m(&state, bytecode);
     524         360 :     Node* arg1 = m.Int32Constant(2);
     525         360 :     Node* arg2 = m.Int32Constant(3);
     526         360 :     Node* context = m.Int32Constant(4);
     527         180 :     Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
     528        2880 :     EXPECT_THAT(call_runtime, c::IsCall(_, _, arg1, arg2, _,
     529           0 :                                         c::IsInt32Constant(2), context, _, _));
     530             :   }
     531           1 : }
     532             : 
     533       15419 : TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
     534           1 :   const int kResultSizes[] = {1, 2};
     535         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     536        1620 :     TRACED_FOREACH(int, result_size, kResultSizes) {
     537         720 :       if (Bytecodes::IsCallRuntime(bytecode)) {
     538           6 :         InterpreterAssemblerTestState state(this, bytecode);
     539          12 :         InterpreterAssemblerForTest m(&state, bytecode);
     540             :         Callable builtin =
     541           6 :             CodeFactory::InterpreterCEntry(isolate(), result_size);
     542             : 
     543          12 :         Node* function_id = m.Int32Constant(0);
     544          12 :         InterpreterAssembler::RegListNodePair registers(m.IntPtrConstant(1),
     545          12 :                                                         m.Int32Constant(2));
     546          12 :         Node* context = m.IntPtrConstant(4);
     547             : 
     548             :         Matcher<Node*> function_table = c::IsExternalConstant(
     549             :             ExternalReference::runtime_function_table_address_for_unittests(
     550          12 :                 isolate()));
     551             :         Matcher<Node*> function = c::IsIntPtrAdd(
     552             :             function_table,
     553          24 :             c::IsChangeUint32ToWord(c::IsInt32Mul(
     554          18 :                 function_id, c::IsInt32Constant(sizeof(Runtime::Function)))));
     555             :         Matcher<Node*> function_entry =
     556             :             m.IsLoad(MachineType::Pointer(), function,
     557          18 :                      c::IsIntPtrConstant(offsetof(Runtime::Function, entry)));
     558             : 
     559             :         Node* call_runtime =
     560           6 :             m.CallRuntimeN(function_id, context, registers, result_size);
     561          78 :         EXPECT_THAT(
     562             :             call_runtime,
     563             :             c::IsCall(_, c::IsHeapConstant(builtin.code()),
     564             :                       registers.reg_count(), registers.base_reg_location(),
     565           0 :                       function_entry, context, _, _));
     566             :       }
     567             :     }
     568             :   }
     569           1 : }
     570             : 
     571       15419 : TARGET_TEST_F(InterpreterAssemblerTest, LoadFeedbackVector) {
     572         721 :   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     573         180 :     InterpreterAssemblerTestState state(this, bytecode);
     574         360 :     InterpreterAssemblerForTest m(&state, bytecode);
     575         360 :     Node* feedback_vector = m.LoadFeedbackVector();
     576             : 
     577             :     // Feedback vector is a phi node with two inputs. One of them is loading the
     578             :     // feedback vector and the other is undefined constant (when feedback
     579             :     // vectors aren't allocated). Find the input that loads feedback vector.
     580         180 :     CHECK(feedback_vector->opcode() == i::compiler::IrOpcode::kPhi);
     581             :     Node* value0 =
     582         180 :         i::compiler::NodeProperties::GetValueInput(feedback_vector, 0);
     583             :     Node* value1 =
     584         180 :         i::compiler::NodeProperties::GetValueInput(feedback_vector, 1);
     585         180 :     Node* load_feedback_vector = value0;
     586         180 :     if (value0->opcode() == i::compiler::IrOpcode::kHeapConstant) {
     587           0 :       load_feedback_vector = value1;
     588             :     }
     589             : 
     590             :     Matcher<Node*> load_function_matcher = IsBitcastWordToTagged(
     591         720 :         m.IsLoad(MachineType::Pointer(), c::IsLoadParentFramePointer(),
     592         540 :                  c::IsIntPtrConstant(Register::function_closure().ToOperand() *
     593         180 :                                      kSystemPointerSize)));
     594             : #ifdef V8_COMPRESS_POINTERS
     595             :     Matcher<Node*> load_vector_cell_matcher = IsChangeCompressedToTagged(
     596             :         m.IsLoad(MachineType::AnyCompressed(), load_function_matcher,
     597             :                  c::IsIntPtrConstant(JSFunction::kFeedbackCellOffset -
     598             :                                      kHeapObjectTag)));
     599             :     EXPECT_THAT(load_feedback_vector,
     600             :                 IsChangeCompressedToTagged(m.IsLoad(
     601             :                     MachineType::AnyCompressed(), load_vector_cell_matcher,
     602             :                     c::IsIntPtrConstant(Cell::kValueOffset - kHeapObjectTag))));
     603             : #else
     604             :     Matcher<Node*> load_vector_cell_matcher = m.IsLoad(
     605             :         MachineType::AnyTagged(), load_function_matcher,
     606         540 :         c::IsIntPtrConstant(JSFunction::kFeedbackCellOffset - kHeapObjectTag));
     607        1080 :     EXPECT_THAT(
     608             :         load_feedback_vector,
     609             :         m.IsLoad(MachineType::AnyTagged(), load_vector_cell_matcher,
     610           0 :                  c::IsIntPtrConstant(Cell::kValueOffset - kHeapObjectTag)));
     611             : #endif
     612             :   }
     613           1 : }
     614             : 
     615             : }  // namespace interpreter_assembler_unittest
     616             : }  // namespace interpreter
     617             : }  // namespace internal
     618        9249 : }  // namespace v8

Generated by: LCOV version 1.10