| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 case Token::kDIV: | 1489 case Token::kDIV: |
| 1490 if (ShouldSpecializeForDouble(ic_data) || | 1490 if (ShouldSpecializeForDouble(ic_data) || |
| 1491 HasOnlyTwoOf(ic_data, kSmiCid)) { | 1491 HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1492 operands_type = kDoubleCid; | 1492 operands_type = kDoubleCid; |
| 1493 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { | 1493 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { |
| 1494 operands_type = kFloat32x4Cid; | 1494 operands_type = kFloat32x4Cid; |
| 1495 } else { | 1495 } else { |
| 1496 return false; | 1496 return false; |
| 1497 } | 1497 } |
| 1498 break; | 1498 break; |
| 1499 case Token::kMOD: | |
| 1500 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | |
| 1501 operands_type = kSmiCid; | |
| 1502 } else { | |
| 1503 return false; | |
| 1504 } | |
| 1505 break; | |
| 1506 case Token::kBIT_AND: | 1499 case Token::kBIT_AND: |
| 1507 case Token::kBIT_OR: | 1500 case Token::kBIT_OR: |
| 1508 case Token::kBIT_XOR: | 1501 case Token::kBIT_XOR: |
| 1509 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1502 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1510 operands_type = kSmiCid; | 1503 operands_type = kSmiCid; |
| 1511 } else if (HasTwoMintOrSmi(ic_data)) { | 1504 } else if (HasTwoMintOrSmi(ic_data)) { |
| 1512 operands_type = kMintCid; | 1505 operands_type = kMintCid; |
| 1513 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { | 1506 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { |
| 1514 operands_type = kInt32x4Cid; | 1507 operands_type = kInt32x4Cid; |
| 1515 } else { | 1508 } else { |
| 1516 return false; | 1509 return false; |
| 1517 } | 1510 } |
| 1518 break; | 1511 break; |
| 1519 case Token::kSHR: | 1512 case Token::kSHR: |
| 1520 case Token::kSHL: | 1513 case Token::kSHL: |
| 1521 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1514 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1522 // Left shift may overflow from smi into mint or big ints. | 1515 // Left shift may overflow from smi into mint or big ints. |
| 1523 // Don't generate smi code if the IC data is marked because | 1516 // Don't generate smi code if the IC data is marked because |
| 1524 // of an overflow. | 1517 // of an overflow. |
| 1525 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; | 1518 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { |
| 1519 return false; |
| 1520 } |
| 1526 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) | 1521 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) |
| 1527 ? kMintCid | 1522 ? kMintCid |
| 1528 : kSmiCid; | 1523 : kSmiCid; |
| 1529 } else if (HasTwoMintOrSmi(ic_data) && | 1524 } else if (HasTwoMintOrSmi(ic_data) && |
| 1530 HasOnlyOneSmi(ICData::Handle( | 1525 HasOnlyOneSmi(ICData::Handle( |
| 1531 ic_data.AsUnaryClassChecksForArgNr(1)))) { | 1526 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 1532 // Don't generate mint code if the IC data is marked because of an | 1527 // Don't generate mint code if the IC data is marked because of an |
| 1533 // overflow. | 1528 // overflow. |
| 1534 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; | 1529 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { |
| 1530 return false; |
| 1531 } |
| 1535 // Check for smi/mint << smi or smi/mint >> smi. | 1532 // Check for smi/mint << smi or smi/mint >> smi. |
| 1536 operands_type = kMintCid; | 1533 operands_type = kMintCid; |
| 1537 } else { | 1534 } else { |
| 1538 return false; | 1535 return false; |
| 1539 } | 1536 } |
| 1540 break; | 1537 break; |
| 1538 case Token::kMOD: |
| 1541 case Token::kTRUNCDIV: | 1539 case Token::kTRUNCDIV: |
| 1542 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1540 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1543 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; | 1541 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) { |
| 1542 return false; |
| 1543 } |
| 1544 operands_type = kSmiCid; | 1544 operands_type = kSmiCid; |
| 1545 } else { | 1545 } else { |
| 1546 return false; | 1546 return false; |
| 1547 } | 1547 } |
| 1548 break; | 1548 break; |
| 1549 default: | 1549 default: |
| 1550 UNREACHABLE(); | 1550 UNREACHABLE(); |
| 1551 } | 1551 } |
| 1552 | 1552 |
| 1553 ASSERT(call->ArgumentCount() == 2); | 1553 ASSERT(call->ArgumentCount() == 2); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1581 BinaryMintOpInstr* bin_op = | 1581 BinaryMintOpInstr* bin_op = |
| 1582 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 1582 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1583 call->deopt_id()); | 1583 call->deopt_id()); |
| 1584 ReplaceCall(call, bin_op); | 1584 ReplaceCall(call, bin_op); |
| 1585 } | 1585 } |
| 1586 } else if (operands_type == kFloat32x4Cid) { | 1586 } else if (operands_type == kFloat32x4Cid) { |
| 1587 return InlineFloat32x4BinaryOp(call, op_kind); | 1587 return InlineFloat32x4BinaryOp(call, op_kind); |
| 1588 } else if (operands_type == kInt32x4Cid) { | 1588 } else if (operands_type == kInt32x4Cid) { |
| 1589 return InlineInt32x4BinaryOp(call, op_kind); | 1589 return InlineInt32x4BinaryOp(call, op_kind); |
| 1590 } else if (op_kind == Token::kMOD) { | 1590 } else if (op_kind == Token::kMOD) { |
| 1591 // TODO(vegorov): implement fast path code for modulo. | |
| 1592 ASSERT(operands_type == kSmiCid); | 1591 ASSERT(operands_type == kSmiCid); |
| 1593 if (!right->IsConstant()) return false; | 1592 if (right->IsConstant()) { |
| 1594 const Object& obj = right->AsConstant()->value(); | 1593 const Object& obj = right->AsConstant()->value(); |
| 1595 if (!obj.IsSmi()) return false; | 1594 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { |
| 1596 const intptr_t value = Smi::Cast(obj).Value(); | 1595 // Insert smi check and attach a copy of the original environment |
| 1597 if (!Utils::IsPowerOfTwo(value)) return false; | 1596 // because the smi operation can still deoptimize. |
| 1598 | 1597 InsertBefore(call, |
| 1599 // Insert smi check and attach a copy of the original environment | 1598 new CheckSmiInstr(new Value(left), call->deopt_id()), |
| 1600 // because the smi operation can still deoptimize. | 1599 call->env(), |
| 1601 InsertBefore(call, | 1600 Definition::kEffect); |
| 1602 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1601 ConstantInstr* constant = |
| 1603 call->env(), | 1602 flow_graph()->GetConstant(Smi::Handle( |
| 1604 Definition::kEffect); | 1603 Smi::New(Smi::Cast(obj).Value() - 1))); |
| 1605 ConstantInstr* constant = | 1604 BinarySmiOpInstr* bin_op = |
| 1606 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1))); | 1605 new BinarySmiOpInstr(Token::kBIT_AND, |
| 1606 new Value(left), |
| 1607 new Value(constant), |
| 1608 call->deopt_id()); |
| 1609 ReplaceCall(call, bin_op); |
| 1610 return true; |
| 1611 } |
| 1612 } |
| 1613 // Insert two smi checks and attach a copy of the original |
| 1614 // environment because the smi operation can still deoptimize. |
| 1615 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 1616 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 1607 BinarySmiOpInstr* bin_op = | 1617 BinarySmiOpInstr* bin_op = |
| 1608 new BinarySmiOpInstr(Token::kBIT_AND, | 1618 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), |
| 1609 new Value(left), | |
| 1610 new Value(constant), | |
| 1611 call->deopt_id()); | 1619 call->deopt_id()); |
| 1612 ReplaceCall(call, bin_op); | 1620 ReplaceCall(call, bin_op); |
| 1613 } else { | 1621 } else { |
| 1614 ASSERT(operands_type == kSmiCid); | 1622 ASSERT(operands_type == kSmiCid); |
| 1615 // Insert two smi checks and attach a copy of the original | 1623 // Insert two smi checks and attach a copy of the original |
| 1616 // environment because the smi operation can still deoptimize. | 1624 // environment because the smi operation can still deoptimize. |
| 1617 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 1625 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 1618 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 1626 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 1619 if (left->IsConstant() && | 1627 if (left->IsConstant() && |
| 1620 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 1628 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
| (...skipping 6246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7867 } | 7875 } |
| 7868 | 7876 |
| 7869 // Insert materializations at environment uses. | 7877 // Insert materializations at environment uses. |
| 7870 for (intptr_t i = 0; i < exits.length(); i++) { | 7878 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7871 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7879 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7872 } | 7880 } |
| 7873 } | 7881 } |
| 7874 | 7882 |
| 7875 | 7883 |
| 7876 } // namespace dart | 7884 } // namespace dart |
| OLD | NEW |