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 #include "src/compiler/js-operator.h"
      6 #include "src/compiler/opcodes.h"
      7 #include "src/compiler/operator.h"
      8 #include "src/compiler/operator-properties.h"
      9 #include "test/unittests/test-utils.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 namespace {
     16 
     17 const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
     18 
     19 
     20 #if GTEST_HAS_COMBINE
     21 
     22 template <typename T>
     23 class JSOperatorTestWithLanguageModeAndParam
     24     : public TestWithZone,
     25       public ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> {
     26  protected:
     27   LanguageMode language_mode() const {
     28     return ::testing::get<0>(B::GetParam());
     29   }
     30   const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
     31 
     32  private:
     33   typedef ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> B;
     34 };
     35 
     36 #endif  // GTEST_HAS_COMBINE
     37 
     38 }  // namespace
     39 
     40 
     41 // -----------------------------------------------------------------------------
     42 // Shared operators without language mode.
     43 
     44 namespace {
     45 
     46 struct SharedOperator {
     47   const Operator* (JSOperatorBuilder::*constructor)();
     48   IrOpcode::Value opcode;
     49   Operator::Properties properties;
     50   int value_input_count;
     51   int frame_state_input_count;
     52   int effect_input_count;
     53   int control_input_count;
     54   int value_output_count;
     55   int effect_output_count;
     56   int control_output_count;
     57 };
     58 
     59 
     60 const SharedOperator kSharedOperators[] = {
     61 #define SHARED(Name, properties, value_input_count, frame_state_input_count, \
     62                effect_input_count, control_input_count, value_output_count,  \
     63                effect_output_count, control_output_count)                    \
     64   {                                                                          \
     65     &JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties,               \
     66         value_input_count, frame_state_input_count, effect_input_count,      \
     67         control_input_count, value_output_count, effect_output_count,        \
     68         control_output_count                                                 \
     69   }
     70     SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
     71     SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
     72     SHARED(StrictEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
     73     SHARED(StrictNotEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
     74     SHARED(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
     75     SHARED(ToString, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
     76     SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
     77     SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
     78     SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
     79     SHARED(Create, Operator::kEliminatable, 2, 1, 1, 0, 1, 1, 0),
     80     SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
     81     SHARED(TypeOf, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
     82     SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
     83     SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
     84     SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
     85 #undef SHARED
     86 };
     87 
     88 
     89 std::ostream& operator<<(std::ostream& os, const SharedOperator& sop) {
     90   return os << IrOpcode::Mnemonic(sop.opcode);
     91 }
     92 
     93 }  // namespace
     94 
     95 
     96 class JSSharedOperatorTest
     97     : public TestWithZone,
     98       public ::testing::WithParamInterface<SharedOperator> {};
     99 
    100 
    101 TEST_P(JSSharedOperatorTest, InstancesAreGloballyShared) {
    102   const SharedOperator& sop = GetParam();
    103   JSOperatorBuilder javascript1(zone());
    104   JSOperatorBuilder javascript2(zone());
    105   EXPECT_EQ((javascript1.*sop.constructor)(), (javascript2.*sop.constructor)());
    106 }
    107 
    108 
    109 TEST_P(JSSharedOperatorTest, NumberOfInputsAndOutputs) {
    110   JSOperatorBuilder javascript(zone());
    111   const SharedOperator& sop = GetParam();
    112   const Operator* op = (javascript.*sop.constructor)();
    113 
    114   const int context_input_count = 1;
    115   EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
    116   EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
    117   EXPECT_EQ(sop.frame_state_input_count,
    118             OperatorProperties::GetFrameStateInputCount(op));
    119   EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
    120   EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
    121   EXPECT_EQ(sop.value_input_count + context_input_count +
    122                 sop.frame_state_input_count + sop.effect_input_count +
    123                 sop.control_input_count,
    124             OperatorProperties::GetTotalInputCount(op));
    125 
    126   EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
    127   EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
    128   EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
    129 }
    130 
    131 
    132 TEST_P(JSSharedOperatorTest, OpcodeIsCorrect) {
    133   JSOperatorBuilder javascript(zone());
    134   const SharedOperator& sop = GetParam();
    135   const Operator* op = (javascript.*sop.constructor)();
    136   EXPECT_EQ(sop.opcode, op->opcode());
    137 }
    138 
    139 
    140 TEST_P(JSSharedOperatorTest, Properties) {
    141   JSOperatorBuilder javascript(zone());
    142   const SharedOperator& sop = GetParam();
    143   const Operator* op = (javascript.*sop.constructor)();
    144   EXPECT_EQ(sop.properties, op->properties());
    145 }
    146 
    147 
    148 INSTANTIATE_TEST_CASE_P(JSOperatorTest, JSSharedOperatorTest,
    149                         ::testing::ValuesIn(kSharedOperators));
    150 
    151 
    152 // -----------------------------------------------------------------------------
    153 // Shared operators with language mode.
    154 
    155 
    156 #if GTEST_HAS_COMBINE
    157 
    158 namespace {
    159 
    160 struct SharedOperatorWithLanguageMode {
    161   const Operator* (JSOperatorBuilder::*constructor)(LanguageMode);
    162   IrOpcode::Value opcode;
    163   Operator::Properties properties;
    164   int value_input_count;
    165   int frame_state_input_count;
    166   int effect_input_count;
    167   int control_input_count;
    168   int value_output_count;
    169   int effect_output_count;
    170   int control_output_count;
    171 };
    172 
    173 
    174 const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
    175 #define SHARED(Name, properties, value_input_count, frame_state_input_count, \
    176                effect_input_count, control_input_count, value_output_count,  \
    177                effect_output_count, control_output_count)                    \
    178   {                                                                          \
    179     &JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties,               \
    180         value_input_count, frame_state_input_count, effect_input_count,      \
    181         control_input_count, value_output_count, effect_output_count,        \
    182         control_output_count                                                 \
    183   }
    184     SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
    185     SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
    186     SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
    187     SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
    188 #undef SHARED
    189 };
    190 
    191 
    192 std::ostream& operator<<(std::ostream& os,
    193                          const SharedOperatorWithLanguageMode& sop) {
    194   return os << IrOpcode::Mnemonic(sop.opcode);
    195 }
    196 
    197 }  // namespace
    198 
    199 
    200 class JSSharedOperatorWithLanguageModeTest
    201     : public JSOperatorTestWithLanguageModeAndParam<
    202           SharedOperatorWithLanguageMode> {};
    203 
    204 
    205 TEST_P(JSSharedOperatorWithLanguageModeTest, InstancesAreGloballyShared) {
    206   const SharedOperatorWithLanguageMode& sop = GetParam();
    207   JSOperatorBuilder javascript1(zone());
    208   JSOperatorBuilder javascript2(zone());
    209   EXPECT_EQ((javascript1.*sop.constructor)(language_mode()),
    210             (javascript2.*sop.constructor)(language_mode()));
    211 }
    212 
    213 
    214 TEST_P(JSSharedOperatorWithLanguageModeTest, NumberOfInputsAndOutputs) {
    215   JSOperatorBuilder javascript(zone());
    216   const SharedOperatorWithLanguageMode& sop = GetParam();
    217   const Operator* op = (javascript.*sop.constructor)(language_mode());
    218 
    219   const int context_input_count = 1;
    220   EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
    221   EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
    222   EXPECT_EQ(sop.frame_state_input_count,
    223             OperatorProperties::GetFrameStateInputCount(op));
    224   EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
    225   EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
    226   EXPECT_EQ(sop.value_input_count + context_input_count +
    227                 sop.frame_state_input_count + sop.effect_input_count +
    228                 sop.control_input_count,
    229             OperatorProperties::GetTotalInputCount(op));
    230 
    231   EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
    232   EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
    233   EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
    234 }
    235 
    236 
    237 TEST_P(JSSharedOperatorWithLanguageModeTest, OpcodeIsCorrect) {
    238   JSOperatorBuilder javascript(zone());
    239   const SharedOperatorWithLanguageMode& sop = GetParam();
    240   const Operator* op = (javascript.*sop.constructor)(language_mode());
    241   EXPECT_EQ(sop.opcode, op->opcode());
    242 }
    243 
    244 
    245 TEST_P(JSSharedOperatorWithLanguageModeTest, Parameter) {
    246   JSOperatorBuilder javascript(zone());
    247   const SharedOperatorWithLanguageMode& sop = GetParam();
    248   const Operator* op = (javascript.*sop.constructor)(language_mode());
    249   EXPECT_EQ(language_mode(), OpParameter<LanguageMode>(op));
    250 }
    251 
    252 
    253 TEST_P(JSSharedOperatorWithLanguageModeTest, Properties) {
    254   JSOperatorBuilder javascript(zone());
    255   const SharedOperatorWithLanguageMode& sop = GetParam();
    256   const Operator* op = (javascript.*sop.constructor)(language_mode());
    257   EXPECT_EQ(sop.properties, op->properties());
    258 }
    259 
    260 
    261 INSTANTIATE_TEST_CASE_P(
    262     JSOperatorTest, JSSharedOperatorWithLanguageModeTest,
    263     ::testing::Combine(::testing::ValuesIn(kLanguageModes),
    264                        ::testing::ValuesIn(kSharedOperatorsWithLanguageMode)));
    265 
    266 #endif  // GTEST_HAS_COMBINE
    267 
    268 }  // namespace compiler
    269 }  // namespace internal
    270 }  // namespace v8
    271