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/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 DEFINE_FLAG(bool, eliminate_type_checks, true, | 35 DEFINE_FLAG(bool, eliminate_type_checks, true, |
36 "Eliminate type checks when allowed by static type analysis."); | 36 "Eliminate type checks when allowed by static type analysis."); |
37 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); | 37 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); |
38 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); | 38 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); |
39 DEFINE_FLAG(bool, trace_type_check_elimination, false, | 39 DEFINE_FLAG(bool, trace_type_check_elimination, false, |
40 "Trace type check elimination at compile time."); | 40 "Trace type check elimination at compile time."); |
41 | 41 |
42 DECLARE_FLAG(int, optimization_counter_threshold); | 42 DECLARE_FLAG(int, optimization_counter_threshold); |
43 DECLARE_FLAG(bool, profile_vm); | 43 DECLARE_FLAG(bool, profile_vm); |
44 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | |
45 DECLARE_FLAG(bool, use_field_guards); | 44 DECLARE_FLAG(bool, use_field_guards); |
46 | 45 |
47 // Quick access to the locally defined zone() method. | 46 // Quick access to the locally defined zone() method. |
48 #define Z (zone()) | 47 #define Z (zone()) |
49 | 48 |
50 // Quick synthetic token position. | 49 // Quick synthetic token position. |
51 #define ST(token_pos) ((token_pos).ToSynthetic()) | 50 #define ST(token_pos) ((token_pos).ToSynthetic()) |
52 | 51 |
53 // TODO(srdjan): Allow compiler to add constants as they are encountered in | 52 // TODO(srdjan): Allow compiler to add constants as they are encountered in |
54 // the compilation. | 53 // the compilation. |
(...skipping 1532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 Value* value, | 1586 Value* value, |
1588 const AbstractType& dst_type, | 1587 const AbstractType& dst_type, |
1589 const String& dst_name) { | 1588 const String& dst_name) { |
1590 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { | 1589 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { |
1591 return value; | 1590 return value; |
1592 } | 1591 } |
1593 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); | 1592 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); |
1594 } | 1593 } |
1595 | 1594 |
1596 | 1595 |
1597 bool FlowGraphBuilder::WarnOnJSIntegralNumTypeTest( | |
1598 AstNode* node, const AbstractType& type) const { | |
1599 if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) { | |
1600 return false; | |
1601 } | |
1602 const Instance& instance = node->AsLiteralNode()->literal(); | |
1603 if (type.IsIntType()) { | |
1604 if (instance.IsDouble()) { | |
1605 const Double& double_instance = Double::Cast(instance); | |
1606 double value = double_instance.value(); | |
1607 if (floor(value) == value) { | |
1608 return true; | |
1609 } | |
1610 } | |
1611 } else { | |
1612 ASSERT(type.IsDoubleType()); | |
1613 if (instance.IsInteger()) { | |
1614 return true; | |
1615 } | |
1616 } | |
1617 return false; | |
1618 } | |
1619 | |
1620 | |
1621 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { | 1596 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
1622 ASSERT(Token::IsTypeTestOperator(node->kind())); | 1597 ASSERT(Token::IsTypeTestOperator(node->kind())); |
1623 const AbstractType& type = node->right()->AsTypeNode()->type(); | 1598 const AbstractType& type = node->right()->AsTypeNode()->type(); |
1624 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); | 1599 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); |
1625 const bool negate_result = (node->kind() == Token::kISNOT); | 1600 const bool negate_result = (node->kind() == Token::kISNOT); |
1626 // All objects are instances of type T if Object type is a subtype of type T. | 1601 // All objects are instances of type T if Object type is a subtype of type T. |
1627 const Type& object_type = Type::Handle(Z, Type::ObjectType()); | 1602 const Type& object_type = Type::Handle(Z, Type::ObjectType()); |
1628 if (type.IsInstantiated() && | 1603 if (type.IsInstantiated() && |
1629 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { | 1604 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { |
1630 // Must evaluate left side. | 1605 // Must evaluate left side. |
1631 EffectGraphVisitor for_left_value(owner()); | 1606 EffectGraphVisitor for_left_value(owner()); |
1632 node->left()->Visit(&for_left_value); | 1607 node->left()->Visit(&for_left_value); |
1633 Append(for_left_value); | 1608 Append(for_left_value); |
1634 ReturnDefinition(new(Z) ConstantInstr(Bool::Get(!negate_result))); | 1609 ReturnDefinition(new(Z) ConstantInstr(Bool::Get(!negate_result))); |
1635 return; | 1610 return; |
1636 } | 1611 } |
1637 ValueGraphVisitor for_left_value(owner()); | 1612 ValueGraphVisitor for_left_value(owner()); |
1638 node->left()->Visit(&for_left_value); | 1613 node->left()->Visit(&for_left_value); |
1639 Append(for_left_value); | 1614 Append(for_left_value); |
1640 | 1615 |
1641 if (!FLAG_warn_on_javascript_compatibility) { | 1616 if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() || |
1642 if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() || | 1617 type.IsSmiType() || type.IsStringType()) { |
1643 type.IsSmiType() || type.IsStringType()) { | 1618 String& method_name = String::ZoneHandle(Z); |
1644 String& method_name = String::ZoneHandle(Z); | 1619 if (type.IsNumberType()) { |
1645 if (type.IsNumberType()) { | 1620 method_name = Symbols::_instanceOfNum().raw(); |
1646 method_name = Symbols::_instanceOfNum().raw(); | 1621 } else if (type.IsIntType()) { |
1647 } else if (type.IsIntType()) { | 1622 method_name = Symbols::_instanceOfInt().raw(); |
1648 method_name = Symbols::_instanceOfInt().raw(); | 1623 } else if (type.IsDoubleType()) { |
1649 } else if (type.IsDoubleType()) { | 1624 method_name = Symbols::_instanceOfDouble().raw(); |
1650 method_name = Symbols::_instanceOfDouble().raw(); | 1625 } else if (type.IsSmiType()) { |
1651 } else if (type.IsSmiType()) { | 1626 method_name = Symbols::_instanceOfSmi().raw(); |
1652 method_name = Symbols::_instanceOfSmi().raw(); | 1627 } else if (type.IsStringType()) { |
1653 } else if (type.IsStringType()) { | 1628 method_name = Symbols::_instanceOfString().raw(); |
1654 method_name = Symbols::_instanceOfString().raw(); | |
1655 } | |
1656 ASSERT(!method_name.IsNull()); | |
1657 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | |
1658 ZoneGrowableArray<PushArgumentInstr*>* arguments = | |
1659 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | |
1660 arguments->Add(push_left); | |
1661 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); | |
1662 Value* negate_arg = Bind(new(Z) ConstantInstr(negate)); | |
1663 arguments->Add(PushArgument(negate_arg)); | |
1664 const intptr_t kNumArgsChecked = 1; | |
1665 InstanceCallInstr* call = new(Z) InstanceCallInstr( | |
1666 node->token_pos(), | |
1667 Library::PrivateCoreLibName(method_name), | |
1668 node->kind(), | |
1669 arguments, | |
1670 Object::null_array(), // No argument names. | |
1671 kNumArgsChecked, | |
1672 owner()->ic_data_array()); | |
1673 ReturnDefinition(call); | |
1674 return; | |
1675 } | 1629 } |
| 1630 ASSERT(!method_name.IsNull()); |
| 1631 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
| 1632 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1633 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 1634 arguments->Add(push_left); |
| 1635 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); |
| 1636 Value* negate_arg = Bind(new(Z) ConstantInstr(negate)); |
| 1637 arguments->Add(PushArgument(negate_arg)); |
| 1638 const intptr_t kNumArgsChecked = 1; |
| 1639 InstanceCallInstr* call = new(Z) InstanceCallInstr( |
| 1640 node->token_pos(), |
| 1641 Library::PrivateCoreLibName(method_name), |
| 1642 node->kind(), |
| 1643 arguments, |
| 1644 Object::null_array(), // No argument names. |
| 1645 kNumArgsChecked, |
| 1646 owner()->ic_data_array()); |
| 1647 ReturnDefinition(call); |
| 1648 return; |
1676 } | 1649 } |
1677 | 1650 |
1678 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1651 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1679 PushArgumentInstr* push_type_args = NULL; | 1652 PushArgumentInstr* push_type_args = NULL; |
1680 if (type.IsInstantiated()) { | 1653 if (type.IsInstantiated()) { |
1681 push_type_args = PushArgument(BuildNullValue(node->token_pos())); | 1654 push_type_args = PushArgument(BuildNullValue(node->token_pos())); |
1682 } else { | 1655 } else { |
1683 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); | 1656 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); |
1684 } | 1657 } |
1685 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1658 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
(...skipping 26 matching lines...) Expand all Loading... |
1712 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); | 1685 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
1713 ValueGraphVisitor for_value(owner()); | 1686 ValueGraphVisitor for_value(owner()); |
1714 node->left()->Visit(&for_value); | 1687 node->left()->Visit(&for_value); |
1715 Append(for_value); | 1688 Append(for_value); |
1716 const String& dst_name = String::ZoneHandle( | 1689 const String& dst_name = String::ZoneHandle( |
1717 Z, Symbols::New(Exceptions::kCastErrorDstName)); | 1690 Z, Symbols::New(Exceptions::kCastErrorDstName)); |
1718 if (CanSkipTypeCheck(node->token_pos(), | 1691 if (CanSkipTypeCheck(node->token_pos(), |
1719 for_value.value(), | 1692 for_value.value(), |
1720 type, | 1693 type, |
1721 dst_name)) { | 1694 dst_name)) { |
1722 // Check for javascript compatibility. | 1695 ReturnValue(for_value.value()); |
1723 // Do not skip type check if javascript compatibility warning is required. | 1696 return; |
1724 if (!FLAG_warn_on_javascript_compatibility || | |
1725 !owner()->WarnOnJSIntegralNumTypeTest(node->left(), type)) { | |
1726 ReturnValue(for_value.value()); | |
1727 return; | |
1728 } | |
1729 } | 1697 } |
1730 PushArgumentInstr* push_left = PushArgument(for_value.value()); | 1698 PushArgumentInstr* push_left = PushArgument(for_value.value()); |
1731 PushArgumentInstr* push_type_args = NULL; | 1699 PushArgumentInstr* push_type_args = NULL; |
1732 if (type.IsInstantiated()) { | 1700 if (type.IsInstantiated()) { |
1733 push_type_args = PushArgument(BuildNullValue(node->token_pos())); | 1701 push_type_args = PushArgument(BuildNullValue(node->token_pos())); |
1734 } else { | 1702 } else { |
1735 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); | 1703 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); |
1736 } | 1704 } |
1737 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1705 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1738 new(Z) ZoneGrowableArray<PushArgumentInstr*>(3); | 1706 new(Z) ZoneGrowableArray<PushArgumentInstr*>(3); |
(...skipping 2944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4683 Script::Handle(function.script()), | 4651 Script::Handle(function.script()), |
4684 function.token_pos(), | 4652 function.token_pos(), |
4685 Report::AtLocation, | 4653 Report::AtLocation, |
4686 "FlowGraphBuilder Bailout: %s %s", | 4654 "FlowGraphBuilder Bailout: %s %s", |
4687 String::Handle(function.name()).ToCString(), | 4655 String::Handle(function.name()).ToCString(), |
4688 reason); | 4656 reason); |
4689 UNREACHABLE(); | 4657 UNREACHABLE(); |
4690 } | 4658 } |
4691 | 4659 |
4692 } // namespace dart | 4660 } // namespace dart |
OLD | NEW |