Home | History | Annotate | Download | only in compiler
      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_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
      6 #define V8_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/instruction-selector.h"
     13 #include "src/compiler/raw-machine-assembler.h"
     14 #include "src/test/test-utils.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 namespace compiler {
     19 
     20 class InstructionSelectorTest : public TestWithContext, public TestWithZone {
     21  public:
     22   InstructionSelectorTest();
     23   virtual ~InstructionSelectorTest();
     24 
     25   base::RandomNumberGenerator* rng() { return &rng_; }
     26 
     27   class Stream;
     28 
     29   enum StreamBuilderMode {
     30     kAllInstructions,
     31     kTargetInstructions,
     32     kAllExceptNopInstructions
     33   };
     34 
     35   class StreamBuilder FINAL : public RawMachineAssembler {
     36    public:
     37     StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
     38         : RawMachineAssembler(new (test->zone()) Graph(test->zone()),
     39                               MakeMachineSignature(test->zone(), return_type)),
     40           test_(test) {}
     41     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
     42                   MachineType parameter0_type)
     43         : RawMachineAssembler(
     44               new (test->zone()) Graph(test->zone()),
     45               MakeMachineSignature(test->zone(), return_type, parameter0_type)),
     46           test_(test) {}
     47     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
     48                   MachineType parameter0_type, MachineType parameter1_type)
     49         : RawMachineAssembler(
     50               new (test->zone()) Graph(test->zone()),
     51               MakeMachineSignature(test->zone(), return_type, parameter0_type,
     52                                    parameter1_type)),
     53           test_(test) {}
     54     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
     55                   MachineType parameter0_type, MachineType parameter1_type,
     56                   MachineType parameter2_type)
     57         : RawMachineAssembler(
     58               new (test->zone()) Graph(test->zone()),
     59               MakeMachineSignature(test->zone(), return_type, parameter0_type,
     60                                    parameter1_type, parameter2_type)),
     61           test_(test) {}
     62 
     63     Stream Build(CpuFeature feature) {
     64       return Build(InstructionSelector::Features(feature));
     65     }
     66     Stream Build(CpuFeature feature1, CpuFeature feature2) {
     67       return Build(InstructionSelector::Features(feature1, feature2));
     68     }
     69     Stream Build(StreamBuilderMode mode = kTargetInstructions) {
     70       return Build(InstructionSelector::Features(), mode);
     71     }
     72     Stream Build(InstructionSelector::Features features,
     73                  StreamBuilderMode mode = kTargetInstructions);
     74 
     75    private:
     76     MachineSignature* MakeMachineSignature(Zone* zone,
     77                                            MachineType return_type) {
     78       MachineSignature::Builder builder(zone, 1, 0);
     79       builder.AddReturn(return_type);
     80       return builder.Build();
     81     }
     82 
     83     MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
     84                                            MachineType parameter0_type) {
     85       MachineSignature::Builder builder(zone, 1, 1);
     86       builder.AddReturn(return_type);
     87       builder.AddParam(parameter0_type);
     88       return builder.Build();
     89     }
     90 
     91     MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
     92                                            MachineType parameter0_type,
     93                                            MachineType parameter1_type) {
     94       MachineSignature::Builder builder(zone, 1, 2);
     95       builder.AddReturn(return_type);
     96       builder.AddParam(parameter0_type);
     97       builder.AddParam(parameter1_type);
     98       return builder.Build();
     99     }
    100 
    101     MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
    102                                            MachineType parameter0_type,
    103                                            MachineType parameter1_type,
    104                                            MachineType parameter2_type) {
    105       MachineSignature::Builder builder(zone, 1, 3);
    106       builder.AddReturn(return_type);
    107       builder.AddParam(parameter0_type);
    108       builder.AddParam(parameter1_type);
    109       builder.AddParam(parameter2_type);
    110       return builder.Build();
    111     }
    112 
    113    private:
    114     InstructionSelectorTest* test_;
    115   };
    116 
    117   class Stream FINAL {
    118    public:
    119     size_t size() const { return instructions_.size(); }
    120     const Instruction* operator[](size_t index) const {
    121       EXPECT_LT(index, size());
    122       return instructions_[index];
    123     }
    124 
    125     bool IsDouble(const InstructionOperand* operand) const {
    126       return IsDouble(ToVreg(operand));
    127     }
    128     bool IsDouble(int virtual_register) const {
    129       return doubles_.find(virtual_register) != doubles_.end();
    130     }
    131 
    132     bool IsInteger(const InstructionOperand* operand) const {
    133       return IsInteger(ToVreg(operand));
    134     }
    135     bool IsInteger(int virtual_register) const {
    136       return !IsDouble(virtual_register) && !IsReference(virtual_register);
    137     }
    138 
    139     bool IsReference(const InstructionOperand* operand) const {
    140       return IsReference(ToVreg(operand));
    141     }
    142     bool IsReference(int virtual_register) const {
    143       return references_.find(virtual_register) != references_.end();
    144     }
    145 
    146     int32_t ToInt32(const InstructionOperand* operand) const {
    147       return ToConstant(operand).ToInt32();
    148     }
    149 
    150     int64_t ToInt64(const InstructionOperand* operand) const {
    151       return ToConstant(operand).ToInt64();
    152     }
    153 
    154     int ToVreg(const InstructionOperand* operand) const {
    155       if (operand->IsConstant()) return operand->index();
    156       EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
    157       return UnallocatedOperand::cast(operand)->virtual_register();
    158     }
    159 
    160     FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
    161       EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
    162       return deoptimization_entries_[deoptimization_id];
    163     }
    164 
    165     int GetFrameStateDescriptorCount() {
    166       return static_cast<int>(deoptimization_entries_.size());
    167     }
    168 
    169    private:
    170     Constant ToConstant(const InstructionOperand* operand) const {
    171       ConstantMap::const_iterator i;
    172       if (operand->IsConstant()) {
    173         i = constants_.find(operand->index());
    174         EXPECT_FALSE(constants_.end() == i);
    175       } else {
    176         EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
    177         i = immediates_.find(operand->index());
    178         EXPECT_FALSE(immediates_.end() == i);
    179       }
    180       EXPECT_EQ(operand->index(), i->first);
    181       return i->second;
    182     }
    183 
    184     friend class StreamBuilder;
    185 
    186     typedef std::map<int, Constant> ConstantMap;
    187 
    188     ConstantMap constants_;
    189     ConstantMap immediates_;
    190     std::deque<Instruction*> instructions_;
    191     std::set<int> doubles_;
    192     std::set<int> references_;
    193     std::deque<FrameStateDescriptor*> deoptimization_entries_;
    194   };
    195 
    196   base::RandomNumberGenerator rng_;
    197 };
    198 
    199 
    200 template <typename T>
    201 class InstructionSelectorTestWithParam
    202     : public InstructionSelectorTest,
    203       public ::testing::WithParamInterface<T> {};
    204 
    205 }  // namespace compiler
    206 }  // namespace internal
    207 }  // namespace v8
    208 
    209 #endif  // V8_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
    210