| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/assembler.h" | 5 #include "src/assembler.h" |
| 6 #include "src/compiler/js-graph.h" | 6 #include "src/compiler/js-graph.h" |
| 7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
| 8 #include "src/compiler/typer.h" | |
| 9 #include "src/types.h" | |
| 10 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
| 11 #include "test/cctest/compiler/value-helper.h" | 9 #include "test/cctest/compiler/value-helper.h" |
| 12 | 10 |
| 13 namespace v8 { | 11 namespace v8 { |
| 14 namespace internal { | 12 namespace internal { |
| 15 namespace compiler { | 13 namespace compiler { |
| 16 | 14 |
| 17 class JSCacheTesterHelper { | 15 class JSCacheTesterHelper { |
| 18 protected: | 16 protected: |
| 19 JSCacheTesterHelper(Isolate* isolate, Zone* zone) | 17 JSCacheTesterHelper(Isolate* isolate, Zone* zone) |
| 20 : main_graph_(zone), | 18 : main_graph_(zone), |
| 21 main_common_(zone), | 19 main_common_(zone), |
| 22 main_javascript_(zone), | 20 main_javascript_(zone), |
| 23 main_typer_(isolate, &main_graph_), | |
| 24 main_machine_(zone) {} | 21 main_machine_(zone) {} |
| 25 Graph main_graph_; | 22 Graph main_graph_; |
| 26 CommonOperatorBuilder main_common_; | 23 CommonOperatorBuilder main_common_; |
| 27 JSOperatorBuilder main_javascript_; | 24 JSOperatorBuilder main_javascript_; |
| 28 Typer main_typer_; | |
| 29 MachineOperatorBuilder main_machine_; | 25 MachineOperatorBuilder main_machine_; |
| 30 }; | 26 }; |
| 31 | 27 |
| 32 | 28 |
| 33 // TODO(dcarney): JSConstantCacheTester inherits from JSGraph??? | 29 // TODO(dcarney): JSConstantCacheTester inherits from JSGraph??? |
| 34 class JSConstantCacheTester : public HandleAndZoneScope, | 30 class JSConstantCacheTester : public HandleAndZoneScope, |
| 35 public JSCacheTesterHelper, | 31 public JSCacheTesterHelper, |
| 36 public JSGraph { | 32 public JSGraph { |
| 37 public: | 33 public: |
| 38 JSConstantCacheTester() | 34 JSConstantCacheTester() |
| 39 : JSCacheTesterHelper(main_isolate(), main_zone()), | 35 : JSCacheTesterHelper(main_isolate(), main_zone()), |
| 40 JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_, | 36 JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_, |
| 41 nullptr, &main_machine_) { | 37 nullptr, &main_machine_) { |
| 42 main_graph_.SetStart(main_graph_.NewNode(common()->Start(0))); | 38 main_graph_.SetStart(main_graph_.NewNode(common()->Start(0))); |
| 43 main_graph_.SetEnd( | 39 main_graph_.SetEnd( |
| 44 main_graph_.NewNode(common()->End(1), main_graph_.start())); | 40 main_graph_.NewNode(common()->End(1), main_graph_.start())); |
| 45 main_typer_.Run(); | |
| 46 } | 41 } |
| 47 | 42 |
| 48 Type* TypeOf(Node* node) { return NodeProperties::GetType(node); } | |
| 49 | |
| 50 Handle<HeapObject> handle(Node* node) { | 43 Handle<HeapObject> handle(Node* node) { |
| 51 CHECK_EQ(IrOpcode::kHeapConstant, node->opcode()); | 44 CHECK_EQ(IrOpcode::kHeapConstant, node->opcode()); |
| 52 return OpParameter<Handle<HeapObject>>(node); | 45 return OpParameter<Handle<HeapObject>>(node); |
| 53 } | 46 } |
| 54 | 47 |
| 55 Factory* factory() { return main_isolate()->factory(); } | 48 Factory* factory() { return main_isolate()->factory(); } |
| 56 }; | 49 }; |
| 57 | 50 |
| 58 | 51 |
| 59 TEST(ZeroConstant1) { | 52 TEST(ZeroConstant1) { |
| 60 JSConstantCacheTester T; | 53 JSConstantCacheTester T; |
| 61 | 54 |
| 62 Node* zero = T.ZeroConstant(); | 55 Node* zero = T.ZeroConstant(); |
| 63 | 56 |
| 64 CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode()); | 57 CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode()); |
| 65 CHECK_EQ(zero, T.Constant(0)); | 58 CHECK_EQ(zero, T.Constant(0)); |
| 66 CHECK_NE(zero, T.Constant(-0.0)); | 59 CHECK_NE(zero, T.Constant(-0.0)); |
| 67 CHECK_NE(zero, T.Constant(1.0)); | 60 CHECK_NE(zero, T.Constant(1.0)); |
| 68 CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN())); | 61 CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN())); |
| 69 CHECK_NE(zero, T.Float64Constant(0)); | 62 CHECK_NE(zero, T.Float64Constant(0)); |
| 70 CHECK_NE(zero, T.Int32Constant(0)); | 63 CHECK_NE(zero, T.Int32Constant(0)); |
| 71 | |
| 72 Type* t = T.TypeOf(zero); | |
| 73 | |
| 74 CHECK(t->Is(Type::Number())); | |
| 75 CHECK(t->Is(Type::Integral32())); | |
| 76 CHECK(t->Is(Type::Signed32())); | |
| 77 CHECK(t->Is(Type::Unsigned32())); | |
| 78 CHECK(t->Is(Type::SignedSmall())); | |
| 79 CHECK(t->Is(Type::UnsignedSmall())); | |
| 80 } | 64 } |
| 81 | 65 |
| 82 | 66 |
| 83 TEST(MinusZeroConstant) { | 67 TEST(MinusZeroConstant) { |
| 84 JSConstantCacheTester T; | 68 JSConstantCacheTester T; |
| 85 | 69 |
| 86 Node* minus_zero = T.Constant(-0.0); | 70 Node* minus_zero = T.Constant(-0.0); |
| 87 Node* zero = T.ZeroConstant(); | 71 Node* zero = T.ZeroConstant(); |
| 88 | 72 |
| 89 CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode()); | 73 CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode()); |
| 90 CHECK_EQ(minus_zero, T.Constant(-0.0)); | 74 CHECK_EQ(minus_zero, T.Constant(-0.0)); |
| 91 CHECK_NE(zero, minus_zero); | 75 CHECK_NE(zero, minus_zero); |
| 92 | 76 |
| 93 Type* t = T.TypeOf(minus_zero); | |
| 94 | |
| 95 CHECK(t->Is(Type::Number())); | |
| 96 CHECK(t->Is(Type::MinusZero())); | |
| 97 CHECK(!t->Is(Type::Integral32())); | |
| 98 CHECK(!t->Is(Type::Signed32())); | |
| 99 CHECK(!t->Is(Type::Unsigned32())); | |
| 100 CHECK(!t->Is(Type::SignedSmall())); | |
| 101 CHECK(!t->Is(Type::UnsignedSmall())); | |
| 102 | |
| 103 double zero_value = OpParameter<double>(zero); | 77 double zero_value = OpParameter<double>(zero); |
| 104 double minus_zero_value = OpParameter<double>(minus_zero); | 78 double minus_zero_value = OpParameter<double>(minus_zero); |
| 105 | 79 |
| 106 CHECK(bit_cast<uint64_t>(0.0) == bit_cast<uint64_t>(zero_value)); | 80 CHECK(bit_cast<uint64_t>(0.0) == bit_cast<uint64_t>(zero_value)); |
| 107 CHECK(bit_cast<uint64_t>(-0.0) != bit_cast<uint64_t>(zero_value)); | 81 CHECK(bit_cast<uint64_t>(-0.0) != bit_cast<uint64_t>(zero_value)); |
| 108 CHECK(bit_cast<uint64_t>(0.0) != bit_cast<uint64_t>(minus_zero_value)); | 82 CHECK(bit_cast<uint64_t>(0.0) != bit_cast<uint64_t>(minus_zero_value)); |
| 109 CHECK(bit_cast<uint64_t>(-0.0) == bit_cast<uint64_t>(minus_zero_value)); | 83 CHECK(bit_cast<uint64_t>(-0.0) == bit_cast<uint64_t>(minus_zero_value)); |
| 110 } | 84 } |
| 111 | 85 |
| 112 | 86 |
| 113 TEST(ZeroConstant2) { | 87 TEST(ZeroConstant2) { |
| 114 JSConstantCacheTester T; | 88 JSConstantCacheTester T; |
| 115 | 89 |
| 116 Node* zero = T.Constant(0); | 90 Node* zero = T.Constant(0); |
| 117 | 91 |
| 118 CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode()); | 92 CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode()); |
| 119 CHECK_EQ(zero, T.ZeroConstant()); | 93 CHECK_EQ(zero, T.ZeroConstant()); |
| 120 CHECK_NE(zero, T.Constant(-0.0)); | 94 CHECK_NE(zero, T.Constant(-0.0)); |
| 121 CHECK_NE(zero, T.Constant(1.0)); | 95 CHECK_NE(zero, T.Constant(1.0)); |
| 122 CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN())); | 96 CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN())); |
| 123 CHECK_NE(zero, T.Float64Constant(0)); | 97 CHECK_NE(zero, T.Float64Constant(0)); |
| 124 CHECK_NE(zero, T.Int32Constant(0)); | 98 CHECK_NE(zero, T.Int32Constant(0)); |
| 125 | |
| 126 Type* t = T.TypeOf(zero); | |
| 127 | |
| 128 CHECK(t->Is(Type::Number())); | |
| 129 CHECK(t->Is(Type::Integral32())); | |
| 130 CHECK(t->Is(Type::Signed32())); | |
| 131 CHECK(t->Is(Type::Unsigned32())); | |
| 132 CHECK(t->Is(Type::SignedSmall())); | |
| 133 CHECK(t->Is(Type::UnsignedSmall())); | |
| 134 } | 99 } |
| 135 | 100 |
| 136 | 101 |
| 137 TEST(OneConstant1) { | 102 TEST(OneConstant1) { |
| 138 JSConstantCacheTester T; | 103 JSConstantCacheTester T; |
| 139 | 104 |
| 140 Node* one = T.OneConstant(); | 105 Node* one = T.OneConstant(); |
| 141 | 106 |
| 142 CHECK_EQ(IrOpcode::kNumberConstant, one->opcode()); | 107 CHECK_EQ(IrOpcode::kNumberConstant, one->opcode()); |
| 143 CHECK_EQ(one, T.Constant(1)); | 108 CHECK_EQ(one, T.Constant(1)); |
| 144 CHECK_EQ(one, T.Constant(1.0)); | 109 CHECK_EQ(one, T.Constant(1.0)); |
| 145 CHECK_NE(one, T.Constant(1.01)); | 110 CHECK_NE(one, T.Constant(1.01)); |
| 146 CHECK_NE(one, T.Constant(-1.01)); | 111 CHECK_NE(one, T.Constant(-1.01)); |
| 147 CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN())); | 112 CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN())); |
| 148 CHECK_NE(one, T.Float64Constant(1.0)); | 113 CHECK_NE(one, T.Float64Constant(1.0)); |
| 149 CHECK_NE(one, T.Int32Constant(1)); | 114 CHECK_NE(one, T.Int32Constant(1)); |
| 150 | |
| 151 Type* t = T.TypeOf(one); | |
| 152 | |
| 153 CHECK(t->Is(Type::Number())); | |
| 154 CHECK(t->Is(Type::Integral32())); | |
| 155 CHECK(t->Is(Type::Signed32())); | |
| 156 CHECK(t->Is(Type::Unsigned32())); | |
| 157 CHECK(t->Is(Type::SignedSmall())); | |
| 158 CHECK(t->Is(Type::UnsignedSmall())); | |
| 159 } | 115 } |
| 160 | 116 |
| 161 | 117 |
| 162 TEST(OneConstant2) { | 118 TEST(OneConstant2) { |
| 163 JSConstantCacheTester T; | 119 JSConstantCacheTester T; |
| 164 | 120 |
| 165 Node* one = T.Constant(1); | 121 Node* one = T.Constant(1); |
| 166 | 122 |
| 167 CHECK_EQ(IrOpcode::kNumberConstant, one->opcode()); | 123 CHECK_EQ(IrOpcode::kNumberConstant, one->opcode()); |
| 168 CHECK_EQ(one, T.OneConstant()); | 124 CHECK_EQ(one, T.OneConstant()); |
| 169 CHECK_EQ(one, T.Constant(1.0)); | 125 CHECK_EQ(one, T.Constant(1.0)); |
| 170 CHECK_NE(one, T.Constant(1.01)); | 126 CHECK_NE(one, T.Constant(1.01)); |
| 171 CHECK_NE(one, T.Constant(-1.01)); | 127 CHECK_NE(one, T.Constant(-1.01)); |
| 172 CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN())); | 128 CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN())); |
| 173 CHECK_NE(one, T.Float64Constant(1.0)); | 129 CHECK_NE(one, T.Float64Constant(1.0)); |
| 174 CHECK_NE(one, T.Int32Constant(1)); | 130 CHECK_NE(one, T.Int32Constant(1)); |
| 175 | |
| 176 Type* t = T.TypeOf(one); | |
| 177 | |
| 178 CHECK(t->Is(Type::Number())); | |
| 179 CHECK(t->Is(Type::Integral32())); | |
| 180 CHECK(t->Is(Type::Signed32())); | |
| 181 CHECK(t->Is(Type::Unsigned32())); | |
| 182 CHECK(t->Is(Type::SignedSmall())); | |
| 183 CHECK(t->Is(Type::UnsignedSmall())); | |
| 184 } | 131 } |
| 185 | 132 |
| 186 | 133 |
| 187 TEST(Canonicalizations) { | 134 TEST(Canonicalizations) { |
| 188 JSConstantCacheTester T; | 135 JSConstantCacheTester T; |
| 189 | 136 |
| 190 CHECK_EQ(T.ZeroConstant(), T.ZeroConstant()); | 137 CHECK_EQ(T.ZeroConstant(), T.ZeroConstant()); |
| 191 CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant()); | 138 CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant()); |
| 192 CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant()); | 139 CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant()); |
| 193 CHECK_EQ(T.TrueConstant(), T.TrueConstant()); | 140 CHECK_EQ(T.TrueConstant(), T.TrueConstant()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 220 | 167 |
| 221 FOR_FLOAT64_INPUTS(i) { | 168 FOR_FLOAT64_INPUTS(i) { |
| 222 Node* node = T.Constant(*i); | 169 Node* node = T.Constant(*i); |
| 223 for (int j = 0; j < 5; j++) { | 170 for (int j = 0; j < 5; j++) { |
| 224 CHECK_EQ(node, T.Constant(*i)); | 171 CHECK_EQ(node, T.Constant(*i)); |
| 225 } | 172 } |
| 226 } | 173 } |
| 227 } | 174 } |
| 228 | 175 |
| 229 | 176 |
| 230 TEST(NumberTypes) { | |
| 231 JSConstantCacheTester T; | |
| 232 | |
| 233 FOR_FLOAT64_INPUTS(i) { | |
| 234 double value = *i; | |
| 235 Node* node = T.Constant(value); | |
| 236 CHECK(T.TypeOf(node)->Is(Type::Of(value, T.main_zone()))); | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 | |
| 241 TEST(HeapNumbers) { | 177 TEST(HeapNumbers) { |
| 242 JSConstantCacheTester T; | 178 JSConstantCacheTester T; |
| 243 | 179 |
| 244 FOR_FLOAT64_INPUTS(i) { | 180 FOR_FLOAT64_INPUTS(i) { |
| 245 double value = *i; | 181 double value = *i; |
| 246 Handle<Object> num = T.factory()->NewNumber(value); | 182 Handle<Object> num = T.factory()->NewNumber(value); |
| 247 Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value); | 183 Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value); |
| 248 Node* node1 = T.Constant(value); | 184 Node* node1 = T.Constant(value); |
| 249 Node* node2 = T.Constant(num); | 185 Node* node2 = T.Constant(num); |
| 250 Node* node3 = T.Constant(heap); | 186 Node* node3 = T.Constant(heap); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 270 JSConstantCacheTester T; | 206 JSConstantCacheTester T; |
| 271 | 207 |
| 272 CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant())); | 208 CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant())); |
| 273 CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant())); | 209 CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant())); |
| 274 CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant())); | 210 CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant())); |
| 275 CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant())); | 211 CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant())); |
| 276 CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant())); | 212 CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant())); |
| 277 } | 213 } |
| 278 | 214 |
| 279 | 215 |
| 280 TEST(OddballTypes) { | |
| 281 JSConstantCacheTester T; | |
| 282 | |
| 283 CHECK(T.TypeOf(T.UndefinedConstant())->Is(Type::Undefined())); | |
| 284 // TODO(dcarney): figure this out. | |
| 285 // CHECK(T.TypeOf(T.TheHoleConstant())->Is(Type::Internal())); | |
| 286 CHECK(T.TypeOf(T.TrueConstant())->Is(Type::Boolean())); | |
| 287 CHECK(T.TypeOf(T.FalseConstant())->Is(Type::Boolean())); | |
| 288 CHECK(T.TypeOf(T.NullConstant())->Is(Type::Null())); | |
| 289 CHECK(T.TypeOf(T.ZeroConstant())->Is(Type::Number())); | |
| 290 CHECK(T.TypeOf(T.OneConstant())->Is(Type::Number())); | |
| 291 CHECK(T.TypeOf(T.NaNConstant())->Is(Type::NaN())); | |
| 292 } | |
| 293 | |
| 294 | |
| 295 TEST(ExternalReferences) { | 216 TEST(ExternalReferences) { |
| 296 // TODO(titzer): test canonicalization of external references. | 217 // TODO(titzer): test canonicalization of external references. |
| 297 } | 218 } |
| 298 | 219 |
| 299 | 220 |
| 300 static bool Contains(NodeVector* nodes, Node* n) { | 221 static bool Contains(NodeVector* nodes, Node* n) { |
| 301 for (size_t i = 0; i < nodes->size(); i++) { | 222 for (size_t i = 0; i < nodes->size(); i++) { |
| 302 if (nodes->at(i) == n) return true; | 223 if (nodes->at(i) == n) return true; |
| 303 } | 224 } |
| 304 return false; | 225 return false; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 T.GetCachedNodes(&nodes); | 390 T.GetCachedNodes(&nodes); |
| 470 | 391 |
| 471 for (size_t i = 0; i < arraysize(constants); i++) { | 392 for (size_t i = 0; i < arraysize(constants); i++) { |
| 472 CHECK(Contains(&nodes, constants[i])); | 393 CHECK(Contains(&nodes, constants[i])); |
| 473 } | 394 } |
| 474 } | 395 } |
| 475 | 396 |
| 476 } // namespace compiler | 397 } // namespace compiler |
| 477 } // namespace internal | 398 } // namespace internal |
| 478 } // namespace v8 | 399 } // namespace v8 |
| OLD | NEW |