LCOV - code coverage report
Current view: top level - test/unittests/compiler/backend - instruction-selector-unittest.h (source / functions) Hit Total Coverage
Test: app.info Lines: 62 63 98.4 %
Date: 2019-04-18 Functions: 19 20 95.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
       6             : #define V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
       7             : 
       8             : #include <deque>
       9             : #include <set>
      10             : 
      11             : #include "src/base/utils/random-number-generator.h"
      12             : #include "src/compiler/backend/instruction-selector.h"
      13             : #include "src/compiler/raw-machine-assembler.h"
      14             : #include "src/macro-assembler.h"
      15             : #include "test/unittests/test-utils.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace compiler {
      20             : 
      21         171 : class InstructionSelectorTest : public TestWithNativeContextAndZone {
      22             :  public:
      23             :   InstructionSelectorTest();
      24             :   ~InstructionSelectorTest() override;
      25             : 
      26             :   base::RandomNumberGenerator* rng() { return &rng_; }
      27             : 
      28             :   class Stream;
      29             : 
      30             :   enum StreamBuilderMode {
      31             :     kAllInstructions,
      32             :     kTargetInstructions,
      33             :     kAllExceptNopInstructions
      34             :   };
      35             : 
      36         249 :   class StreamBuilder final : public RawMachineAssembler {
      37             :    public:
      38           4 :     StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
      39             :         : RawMachineAssembler(test->isolate(),
      40           4 :                               new (test->zone()) Graph(test->zone()),
      41             :                               MakeCallDescriptor(test->zone(), return_type),
      42             :                               MachineType::PointerRepresentation(),
      43             :                               MachineOperatorBuilder::kAllOptionalOps),
      44           8 :           test_(test) {}
      45         103 :     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
      46             :                   MachineType parameter0_type)
      47             :         : RawMachineAssembler(
      48         103 :               test->isolate(), new (test->zone()) Graph(test->zone()),
      49             :               MakeCallDescriptor(test->zone(), return_type, parameter0_type),
      50             :               MachineType::PointerRepresentation(),
      51             :               MachineOperatorBuilder::kAllOptionalOps,
      52             :               InstructionSelector::AlignmentRequirements()),
      53         309 :           test_(test) {}
      54         128 :     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
      55             :                   MachineType parameter0_type, MachineType parameter1_type)
      56             :         : RawMachineAssembler(
      57         128 :               test->isolate(), new (test->zone()) Graph(test->zone()),
      58             :               MakeCallDescriptor(test->zone(), return_type, parameter0_type,
      59             :                                  parameter1_type),
      60             :               MachineType::PointerRepresentation(),
      61             :               MachineOperatorBuilder::kAllOptionalOps),
      62         256 :           test_(test) {}
      63          14 :     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
      64             :                   MachineType parameter0_type, MachineType parameter1_type,
      65             :                   MachineType parameter2_type)
      66             :         : RawMachineAssembler(
      67          14 :               test->isolate(), new (test->zone()) Graph(test->zone()),
      68             :               MakeCallDescriptor(test->zone(), return_type, parameter0_type,
      69             :                                  parameter1_type, parameter2_type),
      70             :               MachineType::PointerRepresentation(),
      71             :               MachineOperatorBuilder::kAllOptionalOps),
      72          28 :           test_(test) {}
      73             : 
      74             :     Stream Build(CpuFeature feature) {
      75           3 :       return Build(InstructionSelector::Features(feature));
      76             :     }
      77             :     Stream Build(CpuFeature feature1, CpuFeature feature2) {
      78             :       return Build(InstructionSelector::Features(feature1, feature2));
      79             :     }
      80             :     Stream Build(StreamBuilderMode mode = kTargetInstructions) {
      81         246 :       return Build(InstructionSelector::Features(), mode);
      82             :     }
      83             :     Stream Build(InstructionSelector::Features features,
      84             :                  StreamBuilderMode mode = kTargetInstructions,
      85             :                  InstructionSelector::SourcePositionMode source_position_mode =
      86             :                      InstructionSelector::kAllSourcePositions);
      87             : 
      88             :     const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count,
      89             :                                                             int local_count);
      90             : 
      91             :    private:
      92           4 :     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
      93             :       MachineSignature::Builder builder(zone, 1, 0);
      94             :       builder.AddReturn(return_type);
      95           4 :       return MakeSimpleCallDescriptor(zone, builder.Build());
      96             :     }
      97             : 
      98         103 :     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
      99             :                                        MachineType parameter0_type) {
     100             :       MachineSignature::Builder builder(zone, 1, 1);
     101             :       builder.AddReturn(return_type);
     102             :       builder.AddParam(parameter0_type);
     103         103 :       return MakeSimpleCallDescriptor(zone, builder.Build());
     104             :     }
     105             : 
     106         128 :     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
     107             :                                        MachineType parameter0_type,
     108             :                                        MachineType parameter1_type) {
     109             :       MachineSignature::Builder builder(zone, 1, 2);
     110             :       builder.AddReturn(return_type);
     111             :       builder.AddParam(parameter0_type);
     112             :       builder.AddParam(parameter1_type);
     113         128 :       return MakeSimpleCallDescriptor(zone, builder.Build());
     114             :     }
     115             : 
     116          14 :     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
     117             :                                        MachineType parameter0_type,
     118             :                                        MachineType parameter1_type,
     119             :                                        MachineType parameter2_type) {
     120             :       MachineSignature::Builder builder(zone, 1, 3);
     121             :       builder.AddReturn(return_type);
     122             :       builder.AddParam(parameter0_type);
     123             :       builder.AddParam(parameter1_type);
     124             :       builder.AddParam(parameter2_type);
     125          14 :       return MakeSimpleCallDescriptor(zone, builder.Build());
     126             :     }
     127             : 
     128             :    private:
     129             :     InstructionSelectorTest* test_;
     130             : 
     131             :     // Create a simple call descriptor for testing.
     132         249 :     CallDescriptor* MakeSimpleCallDescriptor(Zone* zone,
     133             :                                              MachineSignature* msig) {
     134             :       LocationSignature::Builder locations(zone, msig->return_count(),
     135             :                                            msig->parameter_count());
     136             : 
     137             :       // Add return location(s).
     138         249 :       const int return_count = static_cast<int>(msig->return_count());
     139         747 :       for (int i = 0; i < return_count; i++) {
     140         498 :         locations.AddReturn(
     141             :             LinkageLocation::ForCallerFrameSlot(-1 - i, msig->GetReturn(i)));
     142             :       }
     143             : 
     144             :       // Just put all parameters on the stack.
     145         249 :       const int parameter_count = static_cast<int>(msig->parameter_count());
     146        1051 :       for (int i = 0; i < parameter_count; i++) {
     147         802 :         locations.AddParam(
     148             :             LinkageLocation::ForCallerFrameSlot(-1 - i, msig->GetParam(i)));
     149             :       }
     150             : 
     151             :       const RegList kCalleeSaveRegisters = 0;
     152             :       const RegList kCalleeSaveFPRegisters = 0;
     153             : 
     154             :       MachineType target_type = MachineType::Pointer();
     155             :       LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
     156             :       return new (zone) CallDescriptor(  // --
     157             :           CallDescriptor::kCallAddress,  // kind
     158             :           target_type,                   // target MachineType
     159             :           target_loc,                    // target location
     160             :           locations.Build(),             // location_sig
     161             :           0,                             // stack_parameter_count
     162             :           Operator::kNoProperties,       // properties
     163             :           kCalleeSaveRegisters,          // callee-saved registers
     164             :           kCalleeSaveFPRegisters,        // callee-saved fp regs
     165             :           CallDescriptor::kCanUseRoots,  // flags
     166         249 :           "iselect-test-call");
     167             :     }
     168             :   };
     169             : 
     170        1992 :   class Stream final {
     171             :    public:
     172             :     size_t size() const { return instructions_.size(); }
     173        1049 :     const Instruction* operator[](size_t index) const {
     174        1049 :       EXPECT_LT(index, size());
     175        2098 :       return instructions_[index];
     176             :     }
     177             : 
     178             :     bool IsDouble(const InstructionOperand* operand) const {
     179             :       return IsDouble(ToVreg(operand));
     180             :     }
     181             : 
     182          90 :     bool IsDouble(const Node* node) const { return IsDouble(ToVreg(node)); }
     183             : 
     184             :     bool IsInteger(const InstructionOperand* operand) const {
     185             :       return IsInteger(ToVreg(operand));
     186             :     }
     187             : 
     188             :     bool IsInteger(const Node* node) const { return IsInteger(ToVreg(node)); }
     189             : 
     190             :     bool IsReference(const InstructionOperand* operand) const {
     191             :       return IsReference(ToVreg(operand));
     192             :     }
     193             : 
     194          46 :     bool IsReference(const Node* node) const {
     195          92 :       return IsReference(ToVreg(node));
     196             :     }
     197             : 
     198             :     float ToFloat32(const InstructionOperand* operand) const {
     199           1 :       return ToConstant(operand).ToFloat32();
     200             :     }
     201             : 
     202             :     double ToFloat64(const InstructionOperand* operand) const {
     203           2 :       return ToConstant(operand).ToFloat64().value();
     204             :     }
     205             : 
     206             :     int32_t ToInt32(const InstructionOperand* operand) const {
     207         164 :       return ToConstant(operand).ToInt32();
     208             :     }
     209             : 
     210             :     int64_t ToInt64(const InstructionOperand* operand) const {
     211             :       return ToConstant(operand).ToInt64();
     212             :     }
     213             : 
     214             :     Handle<HeapObject> ToHeapObject(const InstructionOperand* operand) const {
     215           1 :       return ToConstant(operand).ToHeapObject();
     216             :     }
     217             : 
     218         272 :     int ToVreg(const InstructionOperand* operand) const {
     219         272 :       if (operand->IsConstant()) {
     220           0 :         return ConstantOperand::cast(operand)->virtual_register();
     221             :       }
     222         544 :       EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
     223         272 :       return UnallocatedOperand::cast(operand)->virtual_register();
     224             :     }
     225             : 
     226             :     int ToVreg(const Node* node) const;
     227             : 
     228             :     bool IsFixed(const InstructionOperand* operand, Register reg) const;
     229             :     bool IsSameAsFirst(const InstructionOperand* operand) const;
     230             :     bool IsUsedAtStart(const InstructionOperand* operand) const;
     231             : 
     232           2 :     FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
     233           2 :       EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
     234           4 :       return deoptimization_entries_[deoptimization_id];
     235             :     }
     236             : 
     237             :     int GetFrameStateDescriptorCount() {
     238           2 :       return static_cast<int>(deoptimization_entries_.size());
     239             :     }
     240             : 
     241             :    private:
     242             :     bool IsDouble(int virtual_register) const {
     243             :       return doubles_.find(virtual_register) != doubles_.end();
     244             :     }
     245             : 
     246             :     bool IsInteger(int virtual_register) const {
     247             :       return !IsDouble(virtual_register) && !IsReference(virtual_register);
     248             :     }
     249             : 
     250             :     bool IsReference(int virtual_register) const {
     251             :       return references_.find(virtual_register) != references_.end();
     252             :     }
     253             : 
     254          86 :     Constant ToConstant(const InstructionOperand* operand) const {
     255             :       ConstantMap::const_iterator i;
     256          86 :       if (operand->IsConstant()) {
     257             :         i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
     258           4 :         EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
     259           4 :         EXPECT_FALSE(constants_.end() == i);
     260             :       } else {
     261         168 :         EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
     262             :         auto imm = ImmediateOperand::cast(operand);
     263          84 :         if (imm->type() == ImmediateOperand::INLINE) {
     264          17 :           return Constant(imm->inline_value());
     265             :         }
     266             :         i = immediates_.find(imm->indexed_value());
     267         134 :         EXPECT_EQ(imm->indexed_value(), i->first);
     268         134 :         EXPECT_FALSE(immediates_.end() == i);
     269             :       }
     270          69 :       return i->second;
     271             :     }
     272             : 
     273             :     friend class StreamBuilder;
     274             : 
     275             :     typedef std::map<int, Constant> ConstantMap;
     276             :     typedef std::map<NodeId, int> VirtualRegisters;
     277             : 
     278             :     ConstantMap constants_;
     279             :     ConstantMap immediates_;
     280             :     std::deque<Instruction*> instructions_;
     281             :     std::set<int> doubles_;
     282             :     std::set<int> references_;
     283             :     VirtualRegisters virtual_registers_;
     284             :     std::deque<FrameStateDescriptor*> deoptimization_entries_;
     285             :   };
     286             : 
     287             :   base::RandomNumberGenerator rng_;
     288             : };
     289             : 
     290             : template <typename T>
     291         348 : class InstructionSelectorTestWithParam
     292             :     : public InstructionSelectorTest,
     293             :       public ::testing::WithParamInterface<T> {};
     294             : 
     295             : }  // namespace compiler
     296             : }  // namespace internal
     297             : }  // namespace v8
     298             : 
     299             : #endif  // V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_

Generated by: LCOV version 1.10