Chromium Code Reviews| 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" |
| (...skipping 1497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1508 } | 1508 } |
| 1509 | 1509 |
| 1510 | 1510 |
| 1511 Definition* UnboxUint32x4Instr::Canonicalize(FlowGraph* flow_graph) { | 1511 Definition* UnboxUint32x4Instr::Canonicalize(FlowGraph* flow_graph) { |
| 1512 // Fold away UnboxUint32x4(BoxUint32x4(v)). | 1512 // Fold away UnboxUint32x4(BoxUint32x4(v)). |
| 1513 BoxUint32x4Instr* defn = value()->definition()->AsBoxUint32x4(); | 1513 BoxUint32x4Instr* defn = value()->definition()->AsBoxUint32x4(); |
| 1514 return (defn != NULL) ? defn->value()->definition() : this; | 1514 return (defn != NULL) ? defn->value()->definition() : this; |
| 1515 } | 1515 } |
| 1516 | 1516 |
| 1517 | 1517 |
| 1518 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare, | |
| 1519 bool* negated) { | |
| 1520 ASSERT(!*negated); | |
|
srdjan
2013/10/15 15:10:16
It seems safer to set *negated to false here than
Florian Schneider
2013/10/15 15:15:03
Done.
| |
| 1521 if (!compare->right()->BindsToConstant()) { | |
| 1522 return compare; | |
| 1523 } | |
| 1524 const Object& right_constant = compare->right()->BoundConstant(); | |
| 1525 Definition* left_defn = compare->left()->definition(); | |
| 1526 | |
| 1527 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | |
| 1528 // Handles e === true. | |
| 1529 if ((compare->kind() == Token::kEQ_STRICT) && | |
| 1530 (right_constant.raw() == Bool::True().raw()) && | |
| 1531 (compare->left()->Type()->ToCid() == kBoolCid)) { | |
| 1532 // Return left subexpression as the replacement for this instruction. | |
| 1533 return left_defn; | |
| 1534 } | |
| 1535 // x = (a === b); y = x !== true; -> y = a !== b. | |
| 1536 // In order to merge two strict compares, 'left_strict' must have only one | |
| 1537 // use. Do not check left's cid as it is required to be a strict compare. | |
| 1538 StrictCompareInstr* left_strict = left_defn->AsStrictCompare(); | |
| 1539 if ((compare->kind() == Token::kNE_STRICT) && | |
| 1540 (right_constant.raw() == Bool::True().raw()) && | |
| 1541 (left_strict != NULL) && | |
| 1542 (left_strict->HasOnlyUse(compare->left()))) { | |
| 1543 *negated = true; | |
| 1544 return left_strict; | |
| 1545 } | |
| 1546 return compare; | |
| 1547 } | |
| 1548 | |
| 1549 | |
| 1518 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { | 1550 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1519 // Only handle strict-compares. | 1551 // Only handle strict-compares. |
| 1520 if (comparison()->IsStrictCompare()) { | 1552 if (comparison()->IsStrictCompare()) { |
| 1521 Definition* replacement = comparison()->Canonicalize(flow_graph); | 1553 bool negated = false; |
| 1522 if ((replacement == comparison()) || (replacement == NULL)) { | 1554 Definition* replacement = |
| 1555 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); | |
| 1556 if (replacement == comparison()) { | |
| 1523 return this; | 1557 return this; |
| 1524 } | 1558 } |
| 1525 ComparisonInstr* comp = replacement->AsComparison(); | 1559 ComparisonInstr* comp = replacement->AsComparison(); |
| 1526 if ((comp == NULL) || comp->CanDeoptimize()) { | 1560 if ((comp == NULL) || comp->CanDeoptimize()) { |
| 1527 return this; | 1561 return this; |
| 1528 } | 1562 } |
| 1529 | 1563 |
| 1530 // Check that comparison is not serving as a pending deoptimization target | 1564 // Assert that the comparison is not serving as a pending deoptimization |
| 1531 // for conversions. | 1565 // target for conversions. |
| 1532 for (intptr_t i = 0; i < comp->InputCount(); i++) { | 1566 for (intptr_t i = 0; i < comp->InputCount(); i++) { |
| 1533 if (comp->RequiredInputRepresentation(i) != | 1567 if (comp->RequiredInputRepresentation(i) != |
| 1534 comp->InputAt(i)->definition()->representation()) { | 1568 comp->InputAt(i)->definition()->representation()) { |
| 1535 return this; | 1569 return this; |
| 1536 } | 1570 } |
| 1537 } | 1571 } |
| 1538 | 1572 |
| 1539 // Replace the comparison if the replacement is used at this branch, | 1573 // Replace the comparison if the replacement is used at this branch, |
| 1540 // and has exactly one use. | 1574 // and has exactly one use. |
| 1541 Value* use = comp->input_use_list(); | 1575 Value* use = comp->input_use_list(); |
| 1542 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { | 1576 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
| 1577 if (negated) { | |
| 1578 comp->NegateComparison(); | |
| 1579 } | |
| 1543 RemoveEnvironment(); | 1580 RemoveEnvironment(); |
| 1544 flow_graph->CopyDeoptTarget(this, comp); | 1581 flow_graph->CopyDeoptTarget(this, comp); |
| 1545 | 1582 |
| 1546 comp->RemoveFromGraph(); | 1583 comp->RemoveFromGraph(); |
| 1547 SetComparison(comp); | 1584 SetComparison(comp); |
| 1548 if (FLAG_trace_optimization) { | 1585 if (FLAG_trace_optimization) { |
| 1549 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); | 1586 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); |
| 1550 } | 1587 } |
| 1551 // Clear the comparison's temp index and ssa temp index since the | 1588 // Clear the comparison's temp index and ssa temp index since the |
| 1552 // value of the comparison is not used outside the branch anymore. | 1589 // value of the comparison is not used outside the branch anymore. |
| 1553 ASSERT(comp->input_use_list() == NULL); | 1590 ASSERT(comp->input_use_list() == NULL); |
| 1554 comp->ClearSSATempIndex(); | 1591 comp->ClearSSATempIndex(); |
| 1555 comp->ClearTempIndex(); | 1592 comp->ClearTempIndex(); |
| 1556 } | 1593 } |
| 1557 } | 1594 } |
| 1558 return this; | 1595 return this; |
| 1559 } | 1596 } |
| 1560 | 1597 |
| 1561 | 1598 |
| 1562 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { | 1599 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1563 if (!right()->BindsToConstant()) { | 1600 bool negated = false; |
| 1564 return this; | 1601 Definition* replacement = CanonicalizeStrictCompare(this, &negated); |
| 1602 if (negated && replacement->IsComparison()) { | |
| 1603 ASSERT(replacement != this); | |
| 1604 replacement->AsComparison()->NegateComparison(); | |
| 1565 } | 1605 } |
| 1566 const Object& right_constant = right()->BoundConstant(); | 1606 return replacement; |
| 1567 Definition* left_defn = left()->definition(); | |
| 1568 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | |
| 1569 // Handles e === true. | |
| 1570 if ((kind() == Token::kEQ_STRICT) && | |
| 1571 (right_constant.raw() == Bool::True().raw()) && | |
| 1572 (left()->Type()->ToCid() == kBoolCid)) { | |
| 1573 // Return left subexpression as the replacement for this instruction. | |
| 1574 return left_defn; | |
| 1575 } | |
| 1576 // x = (a === b); y = x !== true; -> y = a !== b. | |
| 1577 // In order to merge two strict comares, 'left_strict' must have only one use. | |
| 1578 // Do not check left's cid as it is required to be a strict compare. | |
| 1579 StrictCompareInstr* left_strict = left_defn->AsStrictCompare(); | |
| 1580 if ((kind() == Token::kNE_STRICT) && | |
| 1581 (right_constant.raw() == Bool::True().raw()) && | |
| 1582 (left_strict != NULL) && | |
| 1583 (left_strict->HasOnlyUse(left()))) { | |
| 1584 left_strict->set_kind(Token::NegateComparison(left_strict->kind())); | |
| 1585 return left_strict; | |
| 1586 } | |
| 1587 | |
| 1588 return this; | |
| 1589 } | 1607 } |
| 1590 | 1608 |
| 1591 | 1609 |
| 1592 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { | 1610 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1593 // TODO(vegorov): Replace class checks with null checks when ToNullableCid | 1611 // TODO(vegorov): Replace class checks with null checks when ToNullableCid |
| 1594 // matches. | 1612 // matches. |
| 1595 | 1613 |
| 1596 const intptr_t value_cid = value()->Type()->ToCid(); | 1614 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1597 if (value_cid == kDynamicCid) { | 1615 if (value_cid == kDynamicCid) { |
| 1598 return this; | 1616 return this; |
| (...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2700 return kCosRuntimeEntry; | 2718 return kCosRuntimeEntry; |
| 2701 default: | 2719 default: |
| 2702 UNREACHABLE(); | 2720 UNREACHABLE(); |
| 2703 } | 2721 } |
| 2704 return kSinRuntimeEntry; | 2722 return kSinRuntimeEntry; |
| 2705 } | 2723 } |
| 2706 | 2724 |
| 2707 #undef __ | 2725 #undef __ |
| 2708 | 2726 |
| 2709 } // namespace dart | 2727 } // namespace dart |
| OLD | NEW |