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 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 Value* EffectGraphVisitor::BuildAssignableValue(TokenPosition token_pos, | 1536 Value* EffectGraphVisitor::BuildAssignableValue(TokenPosition token_pos, |
1537 Value* value, | 1537 Value* value, |
1538 const AbstractType& dst_type, | 1538 const AbstractType& dst_type, |
1539 const String& dst_name) { | 1539 const String& dst_name) { |
1540 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { | 1540 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { |
1541 return value; | 1541 return value; |
1542 } | 1542 } |
1543 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); | 1543 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); |
1544 } | 1544 } |
1545 | 1545 |
| 1546 static bool simpleInstanceOfType(const AbstractType& type) { |
| 1547 // Bail if the type is unknown at compile time. |
| 1548 if (!type.IsInstantiated()) return false; |
| 1549 |
| 1550 // Bail if the type is a function. |
| 1551 if (type.IsFunctionType() || type.IsDartFunctionType()) return false; |
| 1552 |
| 1553 const Class& type_class = Class::Handle(type.type_class()); |
| 1554 // Bail if the type is any type parameters. |
| 1555 if (type_class.IsGeneric()) return false; |
| 1556 |
| 1557 // Finally a simple class for instance of checking. |
| 1558 return true; |
| 1559 } |
| 1560 |
1546 | 1561 |
1547 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { | 1562 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
1548 ASSERT(Token::IsTypeTestOperator(node->kind())); | 1563 ASSERT(Token::IsTypeTestOperator(node->kind())); |
1549 const AbstractType& type = node->right()->AsTypeNode()->type(); | 1564 const AbstractType& type = node->right()->AsTypeNode()->type(); |
1550 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); | 1565 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); |
1551 const bool negate_result = (node->kind() == Token::kISNOT); | 1566 const bool negate_result = (node->kind() == Token::kISNOT); |
1552 // All objects are instances of type T if Object type is a subtype of type T. | 1567 // All objects are instances of type T if Object type is a subtype of type T. |
1553 const Type& object_type = Type::Handle(Z, Type::ObjectType()); | 1568 const Type& object_type = Type::Handle(Z, Type::ObjectType()); |
1554 if (type.IsInstantiated() && | 1569 if (type.IsInstantiated() && |
1555 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { | 1570 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 Library::PrivateCoreLibName(method_name), | 1607 Library::PrivateCoreLibName(method_name), |
1593 node->kind(), | 1608 node->kind(), |
1594 arguments, | 1609 arguments, |
1595 Object::null_array(), // No argument names. | 1610 Object::null_array(), // No argument names. |
1596 kNumArgsChecked, | 1611 kNumArgsChecked, |
1597 owner()->ic_data_array()); | 1612 owner()->ic_data_array()); |
1598 ReturnDefinition(call); | 1613 ReturnDefinition(call); |
1599 return; | 1614 return; |
1600 } | 1615 } |
1601 | 1616 |
| 1617 // We now know type is a real class (!num, !int, !smi, !string) |
| 1618 // and the type check could NOT be removed at compile time. |
1602 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1619 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1603 PushArgumentInstr* push_type_args = NULL; | 1620 if (simpleInstanceOfType(type) && (node->kind() == Token::kIS)) { |
1604 if (type.IsInstantiated()) { | 1621 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
1605 push_type_args = PushArgument(BuildNullValue(node->token_pos())); | 1622 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1623 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| 1624 arguments->Add(push_left); |
| 1625 Value* type_const = Bind(new(Z) ConstantInstr(type)); |
| 1626 arguments->Add(PushArgument(type_const)); |
| 1627 const intptr_t kNumArgsChecked = 2; |
| 1628 InstanceCallInstr* call = new(Z) InstanceCallInstr( |
| 1629 node->token_pos(), |
| 1630 Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), |
| 1631 node->kind(), |
| 1632 arguments, |
| 1633 Object::null_array(), // No argument names. |
| 1634 kNumArgsChecked, |
| 1635 owner()->ic_data_array()); |
| 1636 ReturnDefinition(call); |
1606 } else { | 1637 } else { |
1607 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); | 1638 PushArgumentInstr* push_type_args = NULL; |
| 1639 if (type.IsInstantiated()) { |
| 1640 push_type_args = PushArgument(BuildNullValue(node->token_pos())); |
| 1641 } else { |
| 1642 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); |
| 1643 } |
| 1644 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 1645 new(Z) ZoneGrowableArray<PushArgumentInstr*>(4); |
| 1646 arguments->Add(push_left); |
| 1647 arguments->Add(push_type_args); |
| 1648 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
| 1649 Value* type_const = Bind(new(Z) ConstantInstr(type)); |
| 1650 arguments->Add(PushArgument(type_const)); |
| 1651 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); |
| 1652 Value* negate_arg = Bind(new(Z) ConstantInstr(negate)); |
| 1653 arguments->Add(PushArgument(negate_arg)); |
| 1654 const intptr_t kNumArgsChecked = 1; |
| 1655 InstanceCallInstr* call = new(Z) InstanceCallInstr( |
| 1656 node->token_pos(), |
| 1657 Library::PrivateCoreLibName(Symbols::_instanceOf()), |
| 1658 node->kind(), |
| 1659 arguments, |
| 1660 Object::null_array(), // No argument names. |
| 1661 kNumArgsChecked, |
| 1662 owner()->ic_data_array()); |
| 1663 ReturnDefinition(call); |
1608 } | 1664 } |
1609 ZoneGrowableArray<PushArgumentInstr*>* arguments = | |
1610 new(Z) ZoneGrowableArray<PushArgumentInstr*>(4); | |
1611 arguments->Add(push_left); | |
1612 arguments->Add(push_type_args); | |
1613 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | |
1614 Value* type_const = Bind(new(Z) ConstantInstr(type)); | |
1615 arguments->Add(PushArgument(type_const)); | |
1616 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); | |
1617 Value* negate_arg = Bind(new(Z) ConstantInstr(negate)); | |
1618 arguments->Add(PushArgument(negate_arg)); | |
1619 const intptr_t kNumArgsChecked = 1; | |
1620 InstanceCallInstr* call = new(Z) InstanceCallInstr( | |
1621 node->token_pos(), | |
1622 Library::PrivateCoreLibName(Symbols::_instanceOf()), | |
1623 node->kind(), | |
1624 arguments, | |
1625 Object::null_array(), // No argument names. | |
1626 kNumArgsChecked, | |
1627 owner()->ic_data_array()); | |
1628 ReturnDefinition(call); | |
1629 } | 1665 } |
1630 | 1666 |
1631 | 1667 |
1632 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { | 1668 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { |
1633 ASSERT(Token::IsTypeCastOperator(node->kind())); | 1669 ASSERT(Token::IsTypeCastOperator(node->kind())); |
1634 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 1670 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
1635 const AbstractType& type = node->right()->AsTypeNode()->type(); | 1671 const AbstractType& type = node->right()->AsTypeNode()->type(); |
1636 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); | 1672 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
1637 ValueGraphVisitor for_value(owner()); | 1673 ValueGraphVisitor for_value(owner()); |
1638 node->left()->Visit(&for_value); | 1674 node->left()->Visit(&for_value); |
(...skipping 2942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4581 block_marks); | 4617 block_marks); |
4582 ASSERT(found); | 4618 ASSERT(found); |
4583 } | 4619 } |
4584 | 4620 |
4585 | 4621 |
4586 void FlowGraphBuilder::Bailout(const char* reason) const { | 4622 void FlowGraphBuilder::Bailout(const char* reason) const { |
4587 parsed_function_.Bailout("FlowGraphBuilder", reason); | 4623 parsed_function_.Bailout("FlowGraphBuilder", reason); |
4588 } | 4624 } |
4589 | 4625 |
4590 } // namespace dart | 4626 } // namespace dart |
OLD | NEW |