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/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| 11 #include "src/compiler/access-builder.h" |
11 #include "src/compiler/common-operator.h" | 12 #include "src/compiler/common-operator.h" |
12 #include "src/compiler/diamond.h" | 13 #include "src/compiler/diamond.h" |
13 #include "src/compiler/linkage.h" | 14 #include "src/compiler/linkage.h" |
14 #include "src/compiler/node-matchers.h" | 15 #include "src/compiler/node-matchers.h" |
15 #include "src/compiler/node-properties.h" | 16 #include "src/compiler/node-properties.h" |
16 #include "src/compiler/operator-properties.h" | 17 #include "src/compiler/operator-properties.h" |
17 #include "src/compiler/representation-change.h" | 18 #include "src/compiler/representation-change.h" |
18 #include "src/compiler/simplified-operator.h" | 19 #include "src/compiler/simplified-operator.h" |
19 #include "src/compiler/source-position.h" | 20 #include "src/compiler/source-position.h" |
20 #include "src/objects.h" | 21 #include "src/objects.h" |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 ProcessInput(node, 0, UseInfo::TruncatingWord32()); | 755 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
755 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); | 756 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); |
756 break; | 757 break; |
757 case IrOpcode::kSelect: | 758 case IrOpcode::kSelect: |
758 return VisitSelect(node, truncation, lowering); | 759 return VisitSelect(node, truncation, lowering); |
759 case IrOpcode::kPhi: | 760 case IrOpcode::kPhi: |
760 return VisitPhi(node, truncation, lowering); | 761 return VisitPhi(node, truncation, lowering); |
761 case IrOpcode::kCall: | 762 case IrOpcode::kCall: |
762 return VisitCall(node, lowering); | 763 return VisitCall(node, lowering); |
763 | 764 |
764 //------------------------------------------------------------------ | 765 //------------------------------------------------------------------ |
765 // JavaScript operators. | 766 // JavaScript operators. |
766 //------------------------------------------------------------------ | 767 //------------------------------------------------------------------ |
767 // For now, we assume that all JS operators were too complex to lower | 768 case IrOpcode::kJSToNumber: { |
768 // to Simplified and that they will always require tagged value inputs | |
769 // and produce tagged value outputs. | |
770 // TODO(turbofan): it might be possible to lower some JSOperators here, | |
771 // but that responsibility really lies in the typed lowering phase. | |
772 #define DEFINE_JS_CASE(x) case IrOpcode::k##x: | |
773 JS_OP_LIST(DEFINE_JS_CASE) | |
774 #undef DEFINE_JS_CASE | |
775 VisitInputs(node); | 769 VisitInputs(node); |
776 return SetOutput(node, MachineRepresentation::kTagged); | 770 // TODO(bmeurer): Optimize somewhat based on input type? |
| 771 if (truncation.TruncatesToWord32()) { |
| 772 SetOutput(node, MachineRepresentation::kWord32); |
| 773 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this); |
| 774 } else if (truncation.TruncatesToFloat64()) { |
| 775 SetOutput(node, MachineRepresentation::kFloat64); |
| 776 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this); |
| 777 } else { |
| 778 SetOutput(node, MachineRepresentation::kTagged); |
| 779 } |
| 780 break; |
| 781 } |
777 | 782 |
778 //------------------------------------------------------------------ | 783 //------------------------------------------------------------------ |
779 // Simplified operators. | 784 // Simplified operators. |
780 //------------------------------------------------------------------ | 785 //------------------------------------------------------------------ |
781 case IrOpcode::kBooleanNot: { | 786 case IrOpcode::kBooleanNot: { |
782 if (lower()) { | 787 if (lower()) { |
783 NodeInfo* input_info = GetInfo(node->InputAt(0)); | 788 NodeInfo* input_info = GetInfo(node->InputAt(0)); |
784 if (input_info->representation() == MachineRepresentation::kBit) { | 789 if (input_info->representation() == MachineRepresentation::kBit) { |
785 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) | 790 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) |
786 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); | 791 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 source_positions_(source_positions) {} | 1461 source_positions_(source_positions) {} |
1457 | 1462 |
1458 | 1463 |
1459 void SimplifiedLowering::LowerAllNodes() { | 1464 void SimplifiedLowering::LowerAllNodes() { |
1460 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); | 1465 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); |
1461 RepresentationSelector selector(jsgraph(), zone_, &changer, | 1466 RepresentationSelector selector(jsgraph(), zone_, &changer, |
1462 source_positions_); | 1467 source_positions_); |
1463 selector.Run(this); | 1468 selector.Run(this); |
1464 } | 1469 } |
1465 | 1470 |
| 1471 void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( |
| 1472 Node* node, RepresentationSelector* selector) { |
| 1473 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); |
| 1474 Node* value = node->InputAt(0); |
| 1475 Node* context = node->InputAt(1); |
| 1476 Node* frame_state = node->InputAt(2); |
| 1477 Node* effect = node->InputAt(3); |
| 1478 Node* control = node->InputAt(4); |
| 1479 Node* throwing; |
| 1480 |
| 1481 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); |
| 1482 Node* branch0 = |
| 1483 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
| 1484 |
| 1485 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1486 Node* etrue0 = effect; |
| 1487 Node* vtrue0; |
| 1488 { |
| 1489 vtrue0 = graph()->NewNode(simplified()->ChangeSmiToInt32(), value); |
| 1490 vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0); |
| 1491 } |
| 1492 |
| 1493 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 1494 Node* efalse0 = effect; |
| 1495 Node* vfalse0; |
| 1496 { |
| 1497 throwing = vfalse0 = efalse0 = |
| 1498 graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context, |
| 1499 frame_state, efalse0, if_false0); |
| 1500 if_false0 = graph()->NewNode(common()->IfSuccess(), throwing); |
| 1501 |
| 1502 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0); |
| 1503 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); |
| 1504 |
| 1505 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1506 Node* etrue1 = efalse0; |
| 1507 Node* vtrue1; |
| 1508 { |
| 1509 vtrue1 = graph()->NewNode(simplified()->ChangeSmiToInt32(), vfalse0); |
| 1510 vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1); |
| 1511 } |
| 1512 |
| 1513 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1514 Node* efalse1 = efalse0; |
| 1515 Node* vfalse1; |
| 1516 { |
| 1517 vfalse1 = efalse1 = graph()->NewNode( |
| 1518 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, |
| 1519 efalse1, if_false1); |
| 1520 } |
| 1521 |
| 1522 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1523 efalse0 = |
| 1524 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); |
| 1525 vfalse0 = |
| 1526 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1527 vtrue1, vfalse1, if_false0); |
| 1528 } |
| 1529 |
| 1530 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 1531 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 1532 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1533 vtrue0, vfalse0, control); |
| 1534 |
| 1535 // Replace effect and control uses appropriately. |
| 1536 for (Edge edge : node->use_edges()) { |
| 1537 if (NodeProperties::IsControlEdge(edge)) { |
| 1538 if (edge.from()->opcode() == IrOpcode::kIfSuccess) { |
| 1539 edge.from()->ReplaceUses(control); |
| 1540 edge.from()->Kill(); |
| 1541 } else if (edge.from()->opcode() == IrOpcode::kIfException) { |
| 1542 edge.UpdateTo(throwing); |
| 1543 } else { |
| 1544 UNREACHABLE(); |
| 1545 } |
| 1546 } else if (NodeProperties::IsEffectEdge(edge)) { |
| 1547 edge.UpdateTo(effect); |
| 1548 } |
| 1549 } |
| 1550 |
| 1551 selector->DeferReplacement(node, value); |
| 1552 } |
| 1553 |
| 1554 void SimplifiedLowering::DoJSToNumberTruncatesToWord32( |
| 1555 Node* node, RepresentationSelector* selector) { |
| 1556 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); |
| 1557 Node* value = node->InputAt(0); |
| 1558 Node* context = node->InputAt(1); |
| 1559 Node* frame_state = node->InputAt(2); |
| 1560 Node* effect = node->InputAt(3); |
| 1561 Node* control = node->InputAt(4); |
| 1562 Node* throwing; |
| 1563 |
| 1564 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value); |
| 1565 Node* branch0 = |
| 1566 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
| 1567 |
| 1568 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1569 Node* etrue0 = effect; |
| 1570 Node* vtrue0 = graph()->NewNode(simplified()->ChangeSmiToInt32(), value); |
| 1571 |
| 1572 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 1573 Node* efalse0 = effect; |
| 1574 Node* vfalse0; |
| 1575 { |
| 1576 throwing = vfalse0 = efalse0 = |
| 1577 graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context, |
| 1578 frame_state, efalse0, if_false0); |
| 1579 if_false0 = graph()->NewNode(common()->IfSuccess(), throwing); |
| 1580 |
| 1581 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0); |
| 1582 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); |
| 1583 |
| 1584 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1585 Node* etrue1 = efalse0; |
| 1586 Node* vtrue1 = graph()->NewNode(simplified()->ChangeSmiToInt32(), vfalse0); |
| 1587 |
| 1588 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1589 Node* efalse1 = efalse0; |
| 1590 Node* vfalse1; |
| 1591 { |
| 1592 vfalse1 = efalse1 = graph()->NewNode( |
| 1593 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, |
| 1594 efalse1, if_false1); |
| 1595 vfalse1 = graph()->NewNode( |
| 1596 machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript), |
| 1597 vfalse1); |
| 1598 } |
| 1599 |
| 1600 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1601 efalse0 = |
| 1602 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); |
| 1603 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 1604 vtrue1, vfalse1, if_false0); |
| 1605 } |
| 1606 |
| 1607 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 1608 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 1609 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 1610 vtrue0, vfalse0, control); |
| 1611 |
| 1612 // Replace effect and control uses appropriately. |
| 1613 for (Edge edge : node->use_edges()) { |
| 1614 if (NodeProperties::IsControlEdge(edge)) { |
| 1615 if (edge.from()->opcode() == IrOpcode::kIfSuccess) { |
| 1616 edge.from()->ReplaceUses(control); |
| 1617 edge.from()->Kill(); |
| 1618 } else if (edge.from()->opcode() == IrOpcode::kIfException) { |
| 1619 edge.UpdateTo(throwing); |
| 1620 } else { |
| 1621 UNREACHABLE(); |
| 1622 } |
| 1623 } else if (NodeProperties::IsEffectEdge(edge)) { |
| 1624 edge.UpdateTo(effect); |
| 1625 } |
| 1626 } |
| 1627 |
| 1628 selector->DeferReplacement(node, value); |
| 1629 } |
1466 | 1630 |
1467 void SimplifiedLowering::DoLoadBuffer(Node* node, | 1631 void SimplifiedLowering::DoLoadBuffer(Node* node, |
1468 MachineRepresentation output_rep, | 1632 MachineRepresentation output_rep, |
1469 RepresentationChanger* changer) { | 1633 RepresentationChanger* changer) { |
1470 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode()); | 1634 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode()); |
1471 DCHECK_NE(MachineRepresentation::kNone, output_rep); | 1635 DCHECK_NE(MachineRepresentation::kNone, output_rep); |
1472 MachineType const access_type = BufferAccessOf(node->op()).machine_type(); | 1636 MachineType const access_type = BufferAccessOf(node->op()).machine_type(); |
1473 if (output_rep != access_type.representation()) { | 1637 if (output_rep != access_type.representation()) { |
1474 Node* const buffer = node->InputAt(0); | 1638 Node* const buffer = node->InputAt(0); |
1475 Node* const offset = node->InputAt(1); | 1639 Node* const offset = node->InputAt(1); |
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2176 void SimplifiedLowering::DoShift(Node* node, Operator const* op, | 2340 void SimplifiedLowering::DoShift(Node* node, Operator const* op, |
2177 Type* rhs_type) { | 2341 Type* rhs_type) { |
2178 Node* const rhs = NodeProperties::GetValueInput(node, 1); | 2342 Node* const rhs = NodeProperties::GetValueInput(node, 1); |
2179 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) { | 2343 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) { |
2180 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, | 2344 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, |
2181 jsgraph()->Int32Constant(0x1f))); | 2345 jsgraph()->Int32Constant(0x1f))); |
2182 } | 2346 } |
2183 NodeProperties::ChangeOp(node, op); | 2347 NodeProperties::ChangeOp(node, op); |
2184 } | 2348 } |
2185 | 2349 |
| 2350 Node* SimplifiedLowering::ToNumberCode() { |
| 2351 if (!to_number_code_.is_set()) { |
| 2352 Callable callable = CodeFactory::ToNumber(isolate()); |
| 2353 to_number_code_.set(jsgraph()->HeapConstant(callable.code())); |
| 2354 } |
| 2355 return to_number_code_.get(); |
| 2356 } |
| 2357 |
| 2358 Operator const* SimplifiedLowering::ToNumberOperator() { |
| 2359 if (!to_number_operator_.is_set()) { |
| 2360 Callable callable = CodeFactory::ToNumber(isolate()); |
| 2361 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; |
| 2362 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2363 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 2364 Operator::kNoProperties); |
| 2365 to_number_operator_.set(common()->Call(desc)); |
| 2366 } |
| 2367 return to_number_operator_.get(); |
| 2368 } |
| 2369 |
2186 } // namespace compiler | 2370 } // namespace compiler |
2187 } // namespace internal | 2371 } // namespace internal |
2188 } // namespace v8 | 2372 } // namespace v8 |
OLD | NEW |