| 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/code_descriptors.h" | 10 #include "vm/code_descriptors.h" |
| (...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 // Type nodes are used when a type is referenced as a literal. Type nodes | 845 // Type nodes are used when a type is referenced as a literal. Type nodes |
| 846 // can also be used for the right-hand side of instanceof comparisons, | 846 // can also be used for the right-hand side of instanceof comparisons, |
| 847 // but they are handled specially in that context, not here. | 847 // but they are handled specially in that context, not here. |
| 848 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { | 848 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { |
| 849 return; | 849 return; |
| 850 } | 850 } |
| 851 | 851 |
| 852 | 852 |
| 853 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { | 853 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { |
| 854 const AbstractType& type = node->type(); | 854 const AbstractType& type = node->type(); |
| 855 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 855 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded(NULL)); |
| 856 if (type.IsInstantiated()) { | 856 if (type.IsInstantiated()) { |
| 857 ReturnDefinition(new ConstantInstr(type)); | 857 ReturnDefinition(new ConstantInstr(type)); |
| 858 } else { | 858 } else { |
| 859 const Class& instantiator_class = Class::ZoneHandle( | 859 const Class& instantiator_class = Class::ZoneHandle( |
| 860 owner()->parsed_function()->function().Owner()); | 860 owner()->parsed_function()->function().Owner()); |
| 861 Value* instantiator_value = BuildInstantiatorTypeArguments( | 861 Value* instantiator_value = BuildInstantiatorTypeArguments( |
| 862 node->token_pos(), instantiator_class, NULL); | 862 node->token_pos(), instantiator_class, NULL); |
| 863 ReturnDefinition(new InstantiateTypeInstr( | 863 ReturnDefinition(new InstantiateTypeInstr( |
| 864 node->token_pos(), type, instantiator_class, instantiator_value)); | 864 node->token_pos(), type, instantiator_class, instantiator_value)); |
| 865 } | 865 } |
| 866 } | 866 } |
| 867 | 867 |
| 868 | 868 |
| 869 // Returns true if the type check can be skipped, for example, if the | 869 // Returns true if the type check can be skipped, for example, if the |
| 870 // destination type is dynamic or if the compile type of the value is a subtype | 870 // destination type is dynamic or if the compile type of the value is a subtype |
| 871 // of the destination type. | 871 // of the destination type. |
| 872 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos, | 872 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos, |
| 873 Value* value, | 873 Value* value, |
| 874 const AbstractType& dst_type, | 874 const AbstractType& dst_type, |
| 875 const String& dst_name) { | 875 const String& dst_name) { |
| 876 ASSERT(!dst_type.IsNull()); | 876 ASSERT(!dst_type.IsNull()); |
| 877 ASSERT(dst_type.IsFinalized()); | 877 ASSERT(dst_type.IsFinalized()); |
| 878 | 878 |
| 879 // If the destination type is malformed, a dynamic type error must be thrown | 879 // If the destination type is malformed or malbounded, a dynamic type error |
| 880 // at run time. | 880 // must be thrown at run time. |
| 881 if (dst_type.IsMalformed()) { | 881 if (dst_type.IsMalformed() || dst_type.IsMalbounded(NULL)) { |
| 882 return false; | 882 return false; |
| 883 } | 883 } |
| 884 | 884 |
| 885 // Any type is more specific than the dynamic type and than the Object type. | 885 // Any type is more specific than the dynamic type and than the Object type. |
| 886 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { | 886 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { |
| 887 return true; | 887 return true; |
| 888 } | 888 } |
| 889 | 889 |
| 890 // Do not perform type check elimination if this optimization is turned off. | 890 // Do not perform type check elimination if this optimization is turned off. |
| 891 if (!FLAG_eliminate_type_checks) { | 891 if (!FLAG_eliminate_type_checks) { |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 ASSERT(Token::IsTypeTestOperator(node->kind())); | 1196 ASSERT(Token::IsTypeTestOperator(node->kind())); |
| 1197 EffectGraphVisitor for_left_value(owner(), temp_index()); | 1197 EffectGraphVisitor for_left_value(owner(), temp_index()); |
| 1198 node->left()->Visit(&for_left_value); | 1198 node->left()->Visit(&for_left_value); |
| 1199 Append(for_left_value); | 1199 Append(for_left_value); |
| 1200 } | 1200 } |
| 1201 | 1201 |
| 1202 | 1202 |
| 1203 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { | 1203 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
| 1204 ASSERT(Token::IsTypeTestOperator(node->kind())); | 1204 ASSERT(Token::IsTypeTestOperator(node->kind())); |
| 1205 const AbstractType& type = node->right()->AsTypeNode()->type(); | 1205 const AbstractType& type = node->right()->AsTypeNode()->type(); |
| 1206 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 1206 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded(NULL)); |
| 1207 const bool negate_result = (node->kind() == Token::kISNOT); | 1207 const bool negate_result = (node->kind() == Token::kISNOT); |
| 1208 // All objects are instances of type T if Object type is a subtype of type T. | 1208 // All objects are instances of type T if Object type is a subtype of type T. |
| 1209 const Type& object_type = Type::Handle(Type::ObjectType()); | 1209 const Type& object_type = Type::Handle(Type::ObjectType()); |
| 1210 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { | 1210 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { |
| 1211 // Must evaluate left side. | 1211 // Must evaluate left side. |
| 1212 EffectGraphVisitor for_left_value(owner(), temp_index()); | 1212 EffectGraphVisitor for_left_value(owner(), temp_index()); |
| 1213 node->left()->Visit(&for_left_value); | 1213 node->left()->Visit(&for_left_value); |
| 1214 Append(for_left_value); | 1214 Append(for_left_value); |
| 1215 ReturnDefinition(new ConstantInstr(negate_result ? | 1215 ReturnDefinition(new ConstantInstr(negate_result ? |
| 1216 Bool::False() : Bool::True())); | 1216 Bool::False() : Bool::True())); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1299 void ValueGraphVisitor::BuildTypeCast(ComparisonNode* node) { | 1299 void ValueGraphVisitor::BuildTypeCast(ComparisonNode* node) { |
| 1300 ASSERT(Token::IsTypeCastOperator(node->kind())); | 1300 ASSERT(Token::IsTypeCastOperator(node->kind())); |
| 1301 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 1301 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
| 1302 const AbstractType& type = node->right()->AsTypeNode()->type(); | 1302 const AbstractType& type = node->right()->AsTypeNode()->type(); |
| 1303 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed. | 1303 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed. |
| 1304 ValueGraphVisitor for_value(owner(), temp_index()); | 1304 ValueGraphVisitor for_value(owner(), temp_index()); |
| 1305 node->left()->Visit(&for_value); | 1305 node->left()->Visit(&for_value); |
| 1306 Append(for_value); | 1306 Append(for_value); |
| 1307 const String& dst_name = String::ZoneHandle( | 1307 const String& dst_name = String::ZoneHandle( |
| 1308 Symbols::New(Exceptions::kCastErrorDstName)); | 1308 Symbols::New(Exceptions::kCastErrorDstName)); |
| 1309 if (type.IsMalformed()) { | 1309 if (type.IsMalformed() || type.IsMalbounded(NULL)) { |
| 1310 ReturnValue(BuildAssignableValue(node->token_pos(), | 1310 ReturnValue(BuildAssignableValue(node->token_pos(), |
| 1311 for_value.value(), | 1311 for_value.value(), |
| 1312 type, | 1312 type, |
| 1313 dst_name)); | 1313 dst_name)); |
| 1314 } else { | 1314 } else { |
| 1315 if (CanSkipTypeCheck(node->token_pos(), | 1315 if (CanSkipTypeCheck(node->token_pos(), |
| 1316 for_value.value(), | 1316 for_value.value(), |
| 1317 type, | 1317 type, |
| 1318 dst_name)) { | 1318 dst_name)) { |
| 1319 ReturnValue(for_value.value()); | 1319 ReturnValue(for_value.value()); |
| (...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2460 const Class& instantiator_class, | 2460 const Class& instantiator_class, |
| 2461 Value* instantiator) { | 2461 Value* instantiator) { |
| 2462 if (instantiator_class.NumTypeParameters() == 0) { | 2462 if (instantiator_class.NumTypeParameters() == 0) { |
| 2463 // The type arguments are compile time constants. | 2463 // The type arguments are compile time constants. |
| 2464 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); | 2464 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); |
| 2465 // Type is temporary. Only its type arguments are preserved. | 2465 // Type is temporary. Only its type arguments are preserved. |
| 2466 Type& type = Type::Handle( | 2466 Type& type = Type::Handle( |
| 2467 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); | 2467 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); |
| 2468 type ^= ClassFinalizer::FinalizeType( | 2468 type ^= ClassFinalizer::FinalizeType( |
| 2469 instantiator_class, type, ClassFinalizer::kFinalize); | 2469 instantiator_class, type, ClassFinalizer::kFinalize); |
| 2470 ASSERT(!type.IsMalformed()); | 2470 ASSERT(!type.IsMalformed() && !type.IsMalbounded(NULL)); |
| 2471 type_arguments = type.arguments(); | 2471 type_arguments = type.arguments(); |
| 2472 type_arguments = type_arguments.Canonicalize(); | 2472 type_arguments = type_arguments.Canonicalize(); |
| 2473 return Bind(new ConstantInstr(type_arguments)); | 2473 return Bind(new ConstantInstr(type_arguments)); |
| 2474 } | 2474 } |
| 2475 Function& outer_function = | 2475 Function& outer_function = |
| 2476 Function::Handle(owner()->parsed_function()->function().raw()); | 2476 Function::Handle(owner()->parsed_function()->function().raw()); |
| 2477 while (outer_function.IsLocalFunction()) { | 2477 while (outer_function.IsLocalFunction()) { |
| 2478 outer_function = outer_function.parent_function(); | 2478 outer_function = outer_function.parent_function(); |
| 2479 } | 2479 } |
| 2480 if (outer_function.IsFactory()) { | 2480 if (outer_function.IsFactory()) { |
| (...skipping 1262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3743 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3743 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 3744 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3744 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 3745 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3745 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 3746 const Error& error = Error::Handle( | 3746 const Error& error = Error::Handle( |
| 3747 LanguageError::New(String::Handle(String::New(chars)))); | 3747 LanguageError::New(String::Handle(String::New(chars)))); |
| 3748 Isolate::Current()->long_jump_base()->Jump(1, error); | 3748 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 3749 } | 3749 } |
| 3750 | 3750 |
| 3751 | 3751 |
| 3752 } // namespace dart | 3752 } // namespace dart |
| OLD | NEW |