| 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_allocator.h" | 10 #include "vm/flow_graph_allocator.h" |
| 11 #include "vm/flow_graph_builder.h" | 11 #include "vm/flow_graph_builder.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/flow_graph_optimizer.h" | 13 #include "vm/flow_graph_optimizer.h" |
| 14 #include "vm/locations.h" | 14 #include "vm/locations.h" |
| 15 #include "vm/object.h" | 15 #include "vm/object.h" |
| 16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 17 #include "vm/os.h" | 17 #include "vm/os.h" |
| 18 #include "vm/resolver.h" | 18 #include "vm/resolver.h" |
| 19 #include "vm/scopes.h" | 19 #include "vm/scopes.h" |
| 20 #include "vm/stub_code.h" | 20 #include "vm/stub_code.h" |
| 21 #include "vm/symbols.h" | 21 #include "vm/symbols.h" |
| 22 | 22 |
| 23 #include "vm/il_printer.h" | 23 #include "vm/il_printer.h" |
| 24 | 24 |
| 25 namespace dart { | 25 namespace dart { |
| 26 | 26 |
| 27 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, | |
| 28 "Maximum number of polymorphic checks in equality operator," | |
| 29 " otherwise use megamorphic dispatch."); | |
| 30 DEFINE_FLAG(bool, new_identity_spec, true, | 27 DEFINE_FLAG(bool, new_identity_spec, true, |
| 31 "Use new identity check rules for numbers."); | 28 "Use new identity check rules for numbers."); |
| 32 DEFINE_FLAG(bool, propagate_ic_data, true, | 29 DEFINE_FLAG(bool, propagate_ic_data, true, |
| 33 "Propagate IC data from unoptimized to optimized IC calls."); | 30 "Propagate IC data from unoptimized to optimized IC calls."); |
| 34 DECLARE_FLAG(bool, enable_type_checks); | 31 DECLARE_FLAG(bool, enable_type_checks); |
| 35 DECLARE_FLAG(bool, eliminate_type_checks); | 32 DECLARE_FLAG(bool, eliminate_type_checks); |
| 36 DECLARE_FLAG(int, max_polymorphic_checks); | |
| 37 DECLARE_FLAG(bool, trace_optimization); | 33 DECLARE_FLAG(bool, trace_optimization); |
| 38 DECLARE_FLAG(bool, trace_constant_propagation); | 34 DECLARE_FLAG(bool, trace_constant_propagation); |
| 39 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 35 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 40 | 36 |
| 41 Definition::Definition() | 37 Definition::Definition() |
| 42 : range_(NULL), | 38 : range_(NULL), |
| 43 type_(NULL), | 39 type_(NULL), |
| 44 temp_index_(-1), | 40 temp_index_(-1), |
| 45 ssa_temp_index_(-1), | 41 ssa_temp_index_(-1), |
| 46 input_use_list_(NULL), | 42 input_use_list_(NULL), |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 } | 159 } |
| 164 | 160 |
| 165 | 161 |
| 166 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const { | 162 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const { |
| 167 MathMinMaxInstr* other_op = other->AsMathMinMax(); | 163 MathMinMaxInstr* other_op = other->AsMathMinMax(); |
| 168 ASSERT(other_op != NULL); | 164 ASSERT(other_op != NULL); |
| 169 return (op_kind() == other_op->op_kind()) && | 165 return (op_kind() == other_op->op_kind()) && |
| 170 (result_cid() == other_op->result_cid()); | 166 (result_cid() == other_op->result_cid()); |
| 171 } | 167 } |
| 172 | 168 |
| 169 |
| 173 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const { | 170 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const { |
| 174 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); | 171 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); |
| 175 ASSERT(other_op != NULL); | 172 ASSERT(other_op != NULL); |
| 176 return (op_kind() == other_op->op_kind()) && | 173 return (op_kind() == other_op->op_kind()) && |
| 177 (overflow_ == other_op->overflow_) && | 174 (overflow_ == other_op->overflow_) && |
| 178 (is_truncating_ == other_op->is_truncating_); | 175 (is_truncating_ == other_op->is_truncating_); |
| 179 } | 176 } |
| 180 | 177 |
| 181 | 178 |
| 182 EffectSet LoadFieldInstr::Dependencies() const { | 179 EffectSet LoadFieldInstr::Dependencies() const { |
| (...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 ASSERT(index == 0); | 1109 ASSERT(index == 0); |
| 1113 return successor(); | 1110 return successor(); |
| 1114 } | 1111 } |
| 1115 | 1112 |
| 1116 | 1113 |
| 1117 void Instruction::Goto(JoinEntryInstr* entry) { | 1114 void Instruction::Goto(JoinEntryInstr* entry) { |
| 1118 LinkTo(new GotoInstr(entry)); | 1115 LinkTo(new GotoInstr(entry)); |
| 1119 } | 1116 } |
| 1120 | 1117 |
| 1121 | 1118 |
| 1122 bool EqualityCompareInstr::IsPolymorphic() const { | |
| 1123 return HasICData() && | |
| 1124 (ic_data()->NumberOfChecks() > 0) && | |
| 1125 (ic_data()->NumberOfChecks() <= FLAG_max_polymorphic_checks); | |
| 1126 } | |
| 1127 | |
| 1128 | |
| 1129 bool EqualityCompareInstr::IsCheckedStrictEqual() const { | |
| 1130 if (!HasICData()) return false; | |
| 1131 return ic_data()->AllTargetsHaveSameOwner(kInstanceCid) && | |
| 1132 (unary_ic_data_->NumberOfChecks() <= | |
| 1133 FLAG_max_equality_polymorphic_checks); | |
| 1134 } | |
| 1135 | |
| 1136 | |
| 1137 bool BinarySmiOpInstr::CanDeoptimize() const { | 1119 bool BinarySmiOpInstr::CanDeoptimize() const { |
| 1138 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) { | 1120 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) { |
| 1139 // If Smi's are bigger than 32-bits, then the instruction could deoptimize | 1121 // If Smi's are bigger than 32-bits, then the instruction could deoptimize |
| 1140 // if the result is too big. | 1122 // if the result is too big. |
| 1141 return true; | 1123 return true; |
| 1142 } | 1124 } |
| 1143 switch (op_kind()) { | 1125 switch (op_kind()) { |
| 1144 case Token::kBIT_AND: | 1126 case Token::kBIT_AND: |
| 1145 case Token::kBIT_OR: | 1127 case Token::kBIT_OR: |
| 1146 case Token::kBIT_XOR: | 1128 case Token::kBIT_XOR: |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 | 1517 |
| 1536 Definition* UnboxUint32x4Instr::Canonicalize(FlowGraph* flow_graph) { | 1518 Definition* UnboxUint32x4Instr::Canonicalize(FlowGraph* flow_graph) { |
| 1537 // Fold away UnboxUint32x4(BoxUint32x4(v)). | 1519 // Fold away UnboxUint32x4(BoxUint32x4(v)). |
| 1538 BoxUint32x4Instr* defn = value()->definition()->AsBoxUint32x4(); | 1520 BoxUint32x4Instr* defn = value()->definition()->AsBoxUint32x4(); |
| 1539 return (defn != NULL) ? defn->value()->definition() : this; | 1521 return (defn != NULL) ? defn->value()->definition() : this; |
| 1540 } | 1522 } |
| 1541 | 1523 |
| 1542 | 1524 |
| 1543 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { | 1525 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1544 Definition* defn = value()->definition(); | 1526 Definition* defn = value()->definition(); |
| 1545 if (defn->IsComparison() && | 1527 if (defn->IsComparison() && defn->HasOnlyUse(value())) { |
| 1546 (value()->Type()->ToCid() == kBoolCid) && | 1528 // Comparisons always have a bool result. |
| 1547 defn->HasOnlyUse(value())) { | 1529 ASSERT(value()->Type()->ToCid() == kBoolCid); |
| 1548 defn->AsComparison()->NegateComparison(); | 1530 defn->AsComparison()->NegateComparison(); |
| 1549 return defn; | 1531 return defn; |
| 1550 } | 1532 } |
| 1551 return this; | 1533 return this; |
| 1552 } | 1534 } |
| 1553 | 1535 |
| 1554 | 1536 |
| 1555 static bool MayBeBoxableNumber(intptr_t cid) { | 1537 static bool MayBeBoxableNumber(intptr_t cid) { |
| 1556 return (cid == kDynamicCid) || | 1538 return (cid == kDynamicCid) || |
| 1557 (cid == kMintCid) || | 1539 (cid == kMintCid) || |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1606 (constant.raw() == Bool::True().raw()) && | 1588 (constant.raw() == Bool::True().raw()) && |
| 1607 (other->Type()->ToCid() == kBoolCid)) { | 1589 (other->Type()->ToCid() == kBoolCid)) { |
| 1608 return other_defn; | 1590 return other_defn; |
| 1609 } | 1591 } |
| 1610 // Handle e !== false. | 1592 // Handle e !== false. |
| 1611 if ((kind == Token::kNE_STRICT) && | 1593 if ((kind == Token::kNE_STRICT) && |
| 1612 (constant.raw() == Bool::False().raw()) && | 1594 (constant.raw() == Bool::False().raw()) && |
| 1613 (other->Type()->ToCid() == kBoolCid)) { | 1595 (other->Type()->ToCid() == kBoolCid)) { |
| 1614 return other_defn; | 1596 return other_defn; |
| 1615 } | 1597 } |
| 1616 // Handle e !== true | 1598 // Handle e !== true. |
| 1617 if ((kind == Token::kNE_STRICT) && | 1599 if ((kind == Token::kNE_STRICT) && |
| 1618 (constant.raw() == Bool::True().raw()) && | 1600 (constant.raw() == Bool::True().raw()) && |
| 1619 other_defn->IsComparison() && | 1601 other_defn->IsComparison() && |
| 1620 (other->Type()->ToCid() == kBoolCid) && | 1602 (other->Type()->ToCid() == kBoolCid) && |
| 1621 other_defn->HasOnlyUse(other)) { | 1603 other_defn->HasOnlyUse(other)) { |
| 1622 *negated = true; | 1604 *negated = true; |
| 1623 return other_defn; | 1605 return other_defn; |
| 1624 } | 1606 } |
| 1607 // Handle e === false. |
| 1625 if ((kind == Token::kEQ_STRICT) && | 1608 if ((kind == Token::kEQ_STRICT) && |
| 1626 (constant.raw() == Bool::False().raw()) && | 1609 (constant.raw() == Bool::False().raw()) && |
| 1627 other_defn->IsComparison() && | 1610 other_defn->IsComparison() && |
| 1628 (other->Type()->ToCid() == kBoolCid) && | 1611 (other->Type()->ToCid() == kBoolCid) && |
| 1629 other_defn->HasOnlyUse(other)) { | 1612 other_defn->HasOnlyUse(other)) { |
| 1630 *negated = true; | 1613 *negated = true; |
| 1631 return other_defn; | 1614 return other_defn; |
| 1632 } | 1615 } |
| 1633 return compare; | 1616 return compare; |
| 1634 } | 1617 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1659 | 1642 |
| 1660 // Replace the comparison if the replacement is used at this branch, | 1643 // Replace the comparison if the replacement is used at this branch, |
| 1661 // and has exactly one use. | 1644 // and has exactly one use. |
| 1662 Value* use = comp->input_use_list(); | 1645 Value* use = comp->input_use_list(); |
| 1663 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { | 1646 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
| 1664 if (negated) { | 1647 if (negated) { |
| 1665 comp->NegateComparison(); | 1648 comp->NegateComparison(); |
| 1666 } | 1649 } |
| 1667 RemoveEnvironment(); | 1650 RemoveEnvironment(); |
| 1668 flow_graph->CopyDeoptTarget(this, comp); | 1651 flow_graph->CopyDeoptTarget(this, comp); |
| 1652 // Unlink environment from the comparison since it is copied to the |
| 1653 // branch instruction. |
| 1654 comp->RemoveEnvironment(); |
| 1669 | 1655 |
| 1670 comp->RemoveFromGraph(); | 1656 comp->RemoveFromGraph(); |
| 1671 SetComparison(comp); | 1657 SetComparison(comp); |
| 1672 if (FLAG_trace_optimization) { | 1658 if (FLAG_trace_optimization) { |
| 1673 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); | 1659 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); |
| 1674 } | 1660 } |
| 1675 // Clear the comparison's temp index and ssa temp index since the | 1661 // Clear the comparison's temp index and ssa temp index since the |
| 1676 // value of the comparison is not used outside the branch anymore. | 1662 // value of the comparison is not used outside the branch anymore. |
| 1677 ASSERT(comp->input_use_list() == NULL); | 1663 ASSERT(comp->input_use_list() == NULL); |
| 1678 comp->ClearSSATempIndex(); | 1664 comp->ClearSSATempIndex(); |
| (...skipping 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2892 return kCosRuntimeEntry; | 2878 return kCosRuntimeEntry; |
| 2893 default: | 2879 default: |
| 2894 UNREACHABLE(); | 2880 UNREACHABLE(); |
| 2895 } | 2881 } |
| 2896 return kSinRuntimeEntry; | 2882 return kSinRuntimeEntry; |
| 2897 } | 2883 } |
| 2898 | 2884 |
| 2899 #undef __ | 2885 #undef __ |
| 2900 | 2886 |
| 2901 } // namespace dart | 2887 } // namespace dart |
| OLD | NEW |