| 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 | 
|---|