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 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2891 return kCosRuntimeEntry; | 2877 return kCosRuntimeEntry; |
2892 default: | 2878 default: |
2893 UNREACHABLE(); | 2879 UNREACHABLE(); |
2894 } | 2880 } |
2895 return kSinRuntimeEntry; | 2881 return kSinRuntimeEntry; |
2896 } | 2882 } |
2897 | 2883 |
2898 #undef __ | 2884 #undef __ |
2899 | 2885 |
2900 } // namespace dart | 2886 } // namespace dart |
OLD | NEW |