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/compiler/js-builtin-reducer.h" | 5 #include "src/compiler/js-builtin-reducer.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/simplified-operator.h" | 8 #include "src/compiler/simplified-operator.h" |
9 #include "src/compiler/typer.h" | 9 #include "src/compiler/typer.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 SimplifiedOperatorBuilder simplified(zone()); | 31 SimplifiedOperatorBuilder simplified(zone()); |
32 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified, | 32 JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified, |
33 &machine); | 33 &machine); |
34 // TODO(titzer): mock the GraphReducer here for better unit testing. | 34 // TODO(titzer): mock the GraphReducer here for better unit testing. |
35 GraphReducer graph_reducer(zone(), graph()); | 35 GraphReducer graph_reducer(zone(), graph()); |
36 JSBuiltinReducer reducer(&graph_reducer, &jsgraph, | 36 JSBuiltinReducer reducer(&graph_reducer, &jsgraph, |
37 JSBuiltinReducer::kNoFlags, nullptr); | 37 JSBuiltinReducer::kNoFlags, nullptr); |
38 return reducer.Reduce(node); | 38 return reducer.Reduce(node); |
39 } | 39 } |
40 | 40 |
| 41 Node* GlobalFunction(const char* name) { |
| 42 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 43 Object::GetProperty( |
| 44 isolate()->global_object(), |
| 45 isolate()->factory()->NewStringFromAsciiChecked(name)) |
| 46 .ToHandleChecked()); |
| 47 return HeapConstant(f); |
| 48 } |
| 49 |
41 Node* MathFunction(const char* name) { | 50 Node* MathFunction(const char* name) { |
42 Handle<Object> m = | 51 Handle<Object> m = |
43 JSObject::GetProperty(isolate()->global_object(), | 52 JSObject::GetProperty(isolate()->global_object(), |
44 isolate()->factory()->NewStringFromAsciiChecked( | 53 isolate()->factory()->NewStringFromAsciiChecked( |
45 "Math")).ToHandleChecked(); | 54 "Math")).ToHandleChecked(); |
46 Handle<JSFunction> f = Handle<JSFunction>::cast( | 55 Handle<JSFunction> f = Handle<JSFunction>::cast( |
47 Object::GetProperty( | 56 Object::GetProperty( |
48 m, isolate()->factory()->NewStringFromAsciiChecked(name)) | 57 m, isolate()->factory()->NewStringFromAsciiChecked(name)) |
49 .ToHandleChecked()); | 58 .ToHandleChecked()); |
50 return HeapConstant(f); | 59 return HeapConstant(f); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 Type* const kNumberTypes[] = { | 103 Type* const kNumberTypes[] = { |
95 Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(), | 104 Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(), |
96 Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(), | 105 Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(), |
97 Type::Integral32(), Type::MinusZero(), Type::NaN(), | 106 Type::Integral32(), Type::MinusZero(), Type::NaN(), |
98 Type::OrderedNumber(), Type::PlainNumber(), Type::Number()}; | 107 Type::OrderedNumber(), Type::PlainNumber(), Type::Number()}; |
99 | 108 |
100 } // namespace | 109 } // namespace |
101 | 110 |
102 | 111 |
103 // ----------------------------------------------------------------------------- | 112 // ----------------------------------------------------------------------------- |
| 113 // isFinite |
| 114 |
| 115 TEST_F(JSBuiltinReducerTest, GlobalIsFiniteWithNumber) { |
| 116 Node* function = GlobalFunction("isFinite"); |
| 117 |
| 118 Node* effect = graph()->start(); |
| 119 Node* control = graph()->start(); |
| 120 Node* context = UndefinedConstant(); |
| 121 Node* frame_state = graph()->start(); |
| 122 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 123 Node* p0 = Parameter(t0, 0); |
| 124 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 125 UndefinedConstant(), p0, context, frame_state, |
| 126 effect, control); |
| 127 Reduction r = Reduce(call); |
| 128 |
| 129 ASSERT_TRUE(r.Changed()); |
| 130 EXPECT_THAT(r.replacement(), IsNumberEqual(IsNumberSubtract(p0, p0), |
| 131 IsNumberSubtract(p0, p0))); |
| 132 } |
| 133 } |
| 134 |
| 135 TEST_F(JSBuiltinReducerTest, GlobalIsFiniteWithPlainPrimitive) { |
| 136 Node* function = GlobalFunction("isFinite"); |
| 137 |
| 138 Node* effect = graph()->start(); |
| 139 Node* control = graph()->start(); |
| 140 Node* context = UndefinedConstant(); |
| 141 Node* frame_state = graph()->start(); |
| 142 Node* p0 = Parameter(Type::PlainPrimitive(), 0); |
| 143 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 144 UndefinedConstant(), p0, context, frame_state, |
| 145 effect, control); |
| 146 Reduction r = Reduce(call); |
| 147 |
| 148 ASSERT_TRUE(r.Changed()); |
| 149 EXPECT_THAT(r.replacement(), |
| 150 IsNumberEqual(IsNumberSubtract(IsPlainPrimitiveToNumber(p0), |
| 151 IsPlainPrimitiveToNumber(p0)), |
| 152 IsNumberSubtract(IsPlainPrimitiveToNumber(p0), |
| 153 IsPlainPrimitiveToNumber(p0)))); |
| 154 } |
| 155 |
| 156 // ----------------------------------------------------------------------------- |
| 157 // isNaN |
| 158 |
| 159 TEST_F(JSBuiltinReducerTest, GlobalIsNaNWithNumber) { |
| 160 Node* function = GlobalFunction("isNaN"); |
| 161 |
| 162 Node* effect = graph()->start(); |
| 163 Node* control = graph()->start(); |
| 164 Node* context = UndefinedConstant(); |
| 165 Node* frame_state = graph()->start(); |
| 166 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 167 Node* p0 = Parameter(t0, 0); |
| 168 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 169 UndefinedConstant(), p0, context, frame_state, |
| 170 effect, control); |
| 171 Reduction r = Reduce(call); |
| 172 |
| 173 ASSERT_TRUE(r.Changed()); |
| 174 EXPECT_THAT(r.replacement(), IsBooleanNot(IsNumberEqual(p0, p0))); |
| 175 } |
| 176 } |
| 177 |
| 178 TEST_F(JSBuiltinReducerTest, GlobalIsNaNWithPlainPrimitive) { |
| 179 Node* function = GlobalFunction("isNaN"); |
| 180 |
| 181 Node* effect = graph()->start(); |
| 182 Node* control = graph()->start(); |
| 183 Node* context = UndefinedConstant(); |
| 184 Node* frame_state = graph()->start(); |
| 185 Node* p0 = Parameter(Type::PlainPrimitive(), 0); |
| 186 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 187 UndefinedConstant(), p0, context, frame_state, |
| 188 effect, control); |
| 189 Reduction r = Reduce(call); |
| 190 |
| 191 ASSERT_TRUE(r.Changed()); |
| 192 EXPECT_THAT(r.replacement(), |
| 193 IsBooleanNot(IsNumberEqual(IsPlainPrimitiveToNumber(p0), |
| 194 IsPlainPrimitiveToNumber(p0)))); |
| 195 } |
| 196 |
| 197 // ----------------------------------------------------------------------------- |
104 // Math.abs | 198 // Math.abs |
105 | 199 |
106 TEST_F(JSBuiltinReducerTest, MathAbsWithNumber) { | 200 TEST_F(JSBuiltinReducerTest, MathAbsWithNumber) { |
107 Node* function = MathFunction("abs"); | 201 Node* function = MathFunction("abs"); |
108 | 202 |
109 Node* effect = graph()->start(); | 203 Node* effect = graph()->start(); |
110 Node* control = graph()->start(); | 204 Node* control = graph()->start(); |
111 Node* context = UndefinedConstant(); | 205 Node* context = UndefinedConstant(); |
112 Node* frame_state = graph()->start(); | 206 Node* frame_state = graph()->start(); |
113 TRACED_FOREACH(Type*, t0, kNumberTypes) { | 207 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, | 1402 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
1309 UndefinedConstant(), p0, context, frame_state, | 1403 UndefinedConstant(), p0, context, frame_state, |
1310 effect, control); | 1404 effect, control); |
1311 Reduction r = Reduce(call); | 1405 Reduction r = Reduce(call); |
1312 | 1406 |
1313 ASSERT_TRUE(r.Changed()); | 1407 ASSERT_TRUE(r.Changed()); |
1314 EXPECT_THAT(r.replacement(), IsNumberTrunc(IsPlainPrimitiveToNumber(p0))); | 1408 EXPECT_THAT(r.replacement(), IsNumberTrunc(IsPlainPrimitiveToNumber(p0))); |
1315 } | 1409 } |
1316 | 1410 |
1317 // ----------------------------------------------------------------------------- | 1411 // ----------------------------------------------------------------------------- |
| 1412 // Number.isFinite |
| 1413 |
| 1414 TEST_F(JSBuiltinReducerTest, NumberIsFiniteWithNumber) { |
| 1415 Node* function = NumberFunction("isFinite"); |
| 1416 |
| 1417 Node* effect = graph()->start(); |
| 1418 Node* control = graph()->start(); |
| 1419 Node* context = UndefinedConstant(); |
| 1420 Node* frame_state = graph()->start(); |
| 1421 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 1422 Node* p0 = Parameter(t0, 0); |
| 1423 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 1424 UndefinedConstant(), p0, context, frame_state, |
| 1425 effect, control); |
| 1426 Reduction r = Reduce(call); |
| 1427 |
| 1428 ASSERT_TRUE(r.Changed()); |
| 1429 EXPECT_THAT(r.replacement(), IsNumberEqual(IsNumberSubtract(p0, p0), |
| 1430 IsNumberSubtract(p0, p0))); |
| 1431 } |
| 1432 } |
| 1433 |
| 1434 // ----------------------------------------------------------------------------- |
| 1435 // Number.isInteger |
| 1436 |
| 1437 TEST_F(JSBuiltinReducerTest, NumberIsIntegerWithNumber) { |
| 1438 Node* function = NumberFunction("isInteger"); |
| 1439 |
| 1440 Node* effect = graph()->start(); |
| 1441 Node* control = graph()->start(); |
| 1442 Node* context = UndefinedConstant(); |
| 1443 Node* frame_state = graph()->start(); |
| 1444 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 1445 Node* p0 = Parameter(t0, 0); |
| 1446 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 1447 UndefinedConstant(), p0, context, frame_state, |
| 1448 effect, control); |
| 1449 Reduction r = Reduce(call); |
| 1450 |
| 1451 ASSERT_TRUE(r.Changed()); |
| 1452 EXPECT_THAT(r.replacement(), |
| 1453 IsNumberEqual(IsNumberSubtract(p0, IsNumberTrunc(p0)), |
| 1454 IsNumberConstant(0.0))); |
| 1455 } |
| 1456 } |
| 1457 |
| 1458 // ----------------------------------------------------------------------------- |
| 1459 // Number.isNaN |
| 1460 |
| 1461 TEST_F(JSBuiltinReducerTest, NumberIsNaNWithNumber) { |
| 1462 Node* function = NumberFunction("isNaN"); |
| 1463 |
| 1464 Node* effect = graph()->start(); |
| 1465 Node* control = graph()->start(); |
| 1466 Node* context = UndefinedConstant(); |
| 1467 Node* frame_state = graph()->start(); |
| 1468 TRACED_FOREACH(Type*, t0, kNumberTypes) { |
| 1469 Node* p0 = Parameter(t0, 0); |
| 1470 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 1471 UndefinedConstant(), p0, context, frame_state, |
| 1472 effect, control); |
| 1473 Reduction r = Reduce(call); |
| 1474 |
| 1475 ASSERT_TRUE(r.Changed()); |
| 1476 EXPECT_THAT(r.replacement(), IsBooleanNot(IsNumberEqual(p0, p0))); |
| 1477 } |
| 1478 } |
| 1479 |
| 1480 // ----------------------------------------------------------------------------- |
| 1481 // Number.isSafeInteger |
| 1482 |
| 1483 TEST_F(JSBuiltinReducerTest, NumberIsSafeIntegerWithIntegral32) { |
| 1484 Node* function = NumberFunction("isSafeInteger"); |
| 1485 |
| 1486 Node* effect = graph()->start(); |
| 1487 Node* control = graph()->start(); |
| 1488 Node* context = UndefinedConstant(); |
| 1489 Node* frame_state = graph()->start(); |
| 1490 TRACED_FOREACH(Type*, t0, kIntegral32Types) { |
| 1491 Node* p0 = Parameter(t0, 0); |
| 1492 Node* call = graph()->NewNode(javascript()->CallFunction(3), function, |
| 1493 UndefinedConstant(), p0, context, frame_state, |
| 1494 effect, control); |
| 1495 Reduction r = Reduce(call); |
| 1496 |
| 1497 ASSERT_TRUE(r.Changed()); |
| 1498 EXPECT_THAT(r.replacement(), IsTrueConstant()); |
| 1499 } |
| 1500 } |
| 1501 |
| 1502 // ----------------------------------------------------------------------------- |
1318 // Number.parseInt | 1503 // Number.parseInt |
1319 | 1504 |
1320 TEST_F(JSBuiltinReducerTest, NumberParseIntWithIntegral32) { | 1505 TEST_F(JSBuiltinReducerTest, NumberParseIntWithIntegral32) { |
1321 Node* function = NumberFunction("parseInt"); | 1506 Node* function = NumberFunction("parseInt"); |
1322 | 1507 |
1323 Node* effect = graph()->start(); | 1508 Node* effect = graph()->start(); |
1324 Node* control = graph()->start(); | 1509 Node* control = graph()->start(); |
1325 Node* context = UndefinedConstant(); | 1510 Node* context = UndefinedConstant(); |
1326 Node* frame_state = graph()->start(); | 1511 Node* frame_state = graph()->start(); |
1327 TRACED_FOREACH(Type*, t0, kIntegral32Types) { | 1512 TRACED_FOREACH(Type*, t0, kIntegral32Types) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 Reduction r = Reduce(call); | 1577 Reduction r = Reduce(call); |
1393 | 1578 |
1394 ASSERT_TRUE(r.Changed()); | 1579 ASSERT_TRUE(r.Changed()); |
1395 EXPECT_THAT(r.replacement(), | 1580 EXPECT_THAT(r.replacement(), |
1396 IsStringFromCharCode(IsPlainPrimitiveToNumber(p0))); | 1581 IsStringFromCharCode(IsPlainPrimitiveToNumber(p0))); |
1397 } | 1582 } |
1398 | 1583 |
1399 } // namespace compiler | 1584 } // namespace compiler |
1400 } // namespace internal | 1585 } // namespace internal |
1401 } // namespace v8 | 1586 } // namespace v8 |
OLD | NEW |