| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 return AbstractType::null(); | 1460 return AbstractType::null(); |
| 1461 } | 1461 } |
| 1462 | 1462 |
| 1463 | 1463 |
| 1464 RawAbstractType* CheckEitherNonSmiInstr::CompileType() const { | 1464 RawAbstractType* CheckEitherNonSmiInstr::CompileType() const { |
| 1465 return AbstractType::null(); | 1465 return AbstractType::null(); |
| 1466 } | 1466 } |
| 1467 | 1467 |
| 1468 | 1468 |
| 1469 // Optimizations that eliminate or simplify individual instructions. | 1469 // Optimizations that eliminate or simplify individual instructions. |
| 1470 Instruction* Instruction::Canonicalize() { | 1470 Instruction* Instruction::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1471 return this; | 1471 return this; |
| 1472 } | 1472 } |
| 1473 | 1473 |
| 1474 | 1474 |
| 1475 Definition* Definition::Canonicalize() { | 1475 Definition* Definition::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1476 return this; | 1476 return this; |
| 1477 } | 1477 } |
| 1478 | 1478 |
| 1479 | 1479 |
| 1480 Definition* AssertBooleanInstr::Canonicalize() { | 1480 Definition* AssertBooleanInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1481 const intptr_t value_cid = value()->ResultCid(); | 1481 const intptr_t value_cid = value()->ResultCid(); |
| 1482 return (value_cid == kBoolCid) ? value()->definition() : this; | 1482 return (value_cid == kBoolCid) ? value()->definition() : this; |
| 1483 } | 1483 } |
| 1484 | 1484 |
| 1485 | 1485 |
| 1486 Definition* AssertAssignableInstr::Canonicalize() { | 1486 Definition* AssertAssignableInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1487 // (1) Replace the assert with its input if the input has a known compatible | 1487 // (1) Replace the assert with its input if the input has a known compatible |
| 1488 // class-id. The class-ids handled here are those that are known to be | 1488 // class-id. The class-ids handled here are those that are known to be |
| 1489 // results of IL instructions. | 1489 // results of IL instructions. |
| 1490 intptr_t cid = value()->ResultCid(); | 1490 intptr_t cid = value()->ResultCid(); |
| 1491 bool is_redundant = false; | 1491 bool is_redundant = false; |
| 1492 if (dst_type().IsIntType()) { | 1492 if (dst_type().IsIntType()) { |
| 1493 is_redundant = (cid == kSmiCid) || (cid == kMintCid); | 1493 is_redundant = (cid == kSmiCid) || (cid == kMintCid); |
| 1494 } else if (dst_type().IsDoubleType()) { | 1494 } else if (dst_type().IsDoubleType()) { |
| 1495 is_redundant = (cid == kDoubleCid); | 1495 is_redundant = (cid == kDoubleCid); |
| 1496 } else if (dst_type().IsBoolType()) { | 1496 } else if (dst_type().IsBoolType()) { |
| 1497 is_redundant = (cid == kBoolCid); | 1497 is_redundant = (cid == kBoolCid); |
| 1498 } | 1498 } |
| 1499 if (is_redundant) return value()->definition(); | 1499 if (is_redundant) return value()->definition(); |
| 1500 | 1500 |
| 1501 // (2) Replace the assert with its input if the input is the result of a | 1501 // (2) Replace the assert with its input if the input is the result of a |
| 1502 // compatible assert itself. | 1502 // compatible assert itself. |
| 1503 AssertAssignableInstr* check = value()->definition()->AsAssertAssignable(); | 1503 AssertAssignableInstr* check = value()->definition()->AsAssertAssignable(); |
| 1504 if ((check != NULL) && (check->dst_type().raw() == dst_type().raw())) { | 1504 if ((check != NULL) && check->dst_type().Equals(dst_type())) { |
| 1505 // TODO(fschneider): Propagate type-assertions across phi-nodes. | 1505 // TODO(fschneider): Propagate type-assertions across phi-nodes. |
| 1506 // TODO(fschneider): Eliminate more asserts with subtype relation. | 1506 // TODO(fschneider): Eliminate more asserts with subtype relation. |
| 1507 return check; | 1507 return check; |
| 1508 } | 1508 } |
| 1509 |
| 1510 // (3) For uninstantiated target types: If the instantiator type arguments |
| 1511 // are constant, instantiate the target type here. |
| 1512 if (dst_type().IsInstantiated()) return this; |
| 1513 |
| 1514 ConstantInstr* constant_type_args = |
| 1515 instantiator_type_arguments()->definition()->AsConstant(); |
| 1516 if (constant_type_args != NULL && |
| 1517 !constant_type_args->value().IsNull() && |
| 1518 constant_type_args->value().IsTypeArguments()) { |
| 1519 const TypeArguments& instantiator_type_args = |
| 1520 TypeArguments::Cast(constant_type_args->value()); |
| 1521 const AbstractType& new_dst_type = AbstractType::Handle( |
| 1522 dst_type().InstantiateFrom(instantiator_type_args)); |
| 1523 set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize())); |
| 1524 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); |
| 1525 // It is ok to insert instructions before the current during |
| 1526 // forward iteration. |
| 1527 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); |
| 1528 instantiator_type_arguments()->RemoveFromInputUseList(); |
| 1529 instantiator_type_arguments()->set_definition(null_constant); |
| 1530 instantiator_type_arguments()->AddToInputUseList(); |
| 1531 } |
| 1509 return this; | 1532 return this; |
| 1510 } | 1533 } |
| 1511 | 1534 |
| 1512 Definition* StrictCompareInstr::Canonicalize() { | 1535 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1513 if (!right()->BindsToConstant()) return this; | 1536 if (!right()->BindsToConstant()) return this; |
| 1514 const Object& right_constant = right()->BoundConstant(); | 1537 const Object& right_constant = right()->BoundConstant(); |
| 1515 Definition* left_defn = left()->definition(); | 1538 Definition* left_defn = left()->definition(); |
| 1516 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | 1539 // TODO(fschneider): Handle other cases: e === false and e !== true/false. |
| 1517 // Handles e === true. | 1540 // Handles e === true. |
| 1518 if ((kind() == Token::kEQ_STRICT) && | 1541 if ((kind() == Token::kEQ_STRICT) && |
| 1519 (right_constant.raw() == Bool::True()) && | 1542 (right_constant.raw() == Bool::True()) && |
| 1520 (left()->ResultCid() == kBoolCid)) { | 1543 (left()->ResultCid() == kBoolCid)) { |
| 1521 // Return left subexpression as the replacement for this instruction. | 1544 // Return left subexpression as the replacement for this instruction. |
| 1522 return left_defn; | 1545 return left_defn; |
| 1523 } | 1546 } |
| 1524 return this; | 1547 return this; |
| 1525 } | 1548 } |
| 1526 | 1549 |
| 1527 | 1550 |
| 1528 Instruction* CheckClassInstr::Canonicalize() { | 1551 Instruction* CheckClassInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1529 const intptr_t value_cid = value()->ResultCid(); | 1552 const intptr_t value_cid = value()->ResultCid(); |
| 1530 const intptr_t num_checks = unary_checks().NumberOfChecks(); | 1553 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 1531 if ((num_checks == 1) && | 1554 if ((num_checks == 1) && |
| 1532 (value_cid == unary_checks().GetReceiverClassIdAt(0))) { | 1555 (value_cid == unary_checks().GetReceiverClassIdAt(0))) { |
| 1533 // No checks needed. | 1556 // No checks needed. |
| 1534 return NULL; | 1557 return NULL; |
| 1535 } | 1558 } |
| 1536 return this; | 1559 return this; |
| 1537 } | 1560 } |
| 1538 | 1561 |
| 1539 | 1562 |
| 1540 Instruction* CheckSmiInstr::Canonicalize() { | 1563 Instruction* CheckSmiInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1541 return (value()->ResultCid() == kSmiCid) ? NULL : this; | 1564 return (value()->ResultCid() == kSmiCid) ? NULL : this; |
| 1542 } | 1565 } |
| 1543 | 1566 |
| 1544 | 1567 |
| 1545 Instruction* CheckEitherNonSmiInstr::Canonicalize() { | 1568 Instruction* CheckEitherNonSmiInstr::Canonicalize( |
| 1569 FlowGraphOptimizer* optimizer) { |
| 1546 if ((left()->ResultCid() == kDoubleCid) || | 1570 if ((left()->ResultCid() == kDoubleCid) || |
| 1547 (right()->ResultCid() == kDoubleCid)) { | 1571 (right()->ResultCid() == kDoubleCid)) { |
| 1548 return NULL; // Remove from the graph. | 1572 return NULL; // Remove from the graph. |
| 1549 } | 1573 } |
| 1550 return this; | 1574 return this; |
| 1551 } | 1575 } |
| 1552 | 1576 |
| 1553 | 1577 |
| 1554 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and | 1578 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and |
| 1555 // PrepareEntry). Only assembly code that can be shared across all architectures | 1579 // PrepareEntry). Only assembly code that can be shared across all architectures |
| (...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2728 default: | 2752 default: |
| 2729 UNREACHABLE(); | 2753 UNREACHABLE(); |
| 2730 return -1; | 2754 return -1; |
| 2731 } | 2755 } |
| 2732 } | 2756 } |
| 2733 | 2757 |
| 2734 | 2758 |
| 2735 #undef __ | 2759 #undef __ |
| 2736 | 2760 |
| 2737 } // namespace dart | 2761 } // namespace dart |
| OLD | NEW |