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