| 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/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| 11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
| 12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
| 13 #include "vm/symbols.h" | 13 #include "vm/symbols.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 | 16 |
| 17 DEFINE_FLAG(bool, error_on_malformed_type, false, |
| 18 "Report error for malformed types."); |
| 17 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); | 19 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
| 18 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 20 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
| 19 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 21 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
| 20 DEFINE_FLAG(bool, verify_implements, false, | |
| 21 "Verify that all classes implement their interface."); | |
| 22 DECLARE_FLAG(bool, enable_type_checks); | 22 DECLARE_FLAG(bool, enable_type_checks); |
| 23 | 23 |
| 24 | 24 |
| 25 bool ClassFinalizer::AllClassesFinalized() { | 25 bool ClassFinalizer::AllClassesFinalized() { |
| 26 ObjectStore* object_store = Isolate::Current()->object_store(); | 26 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 27 const GrowableObjectArray& classes = | 27 const GrowableObjectArray& classes = |
| 28 GrowableObjectArray::Handle(object_store->pending_classes()); | 28 GrowableObjectArray::Handle(object_store->pending_classes()); |
| 29 return classes.Length() == 0; | 29 return classes.Length() == 0; |
| 30 } | 30 } |
| 31 | 31 |
| 32 | 32 |
| 33 // Class finalization occurs: | 33 // Class finalization occurs: |
| 34 // a) when bootstrap process completes (VerifyBootstrapClasses). | 34 // a) when bootstrap process completes (VerifyBootstrapClasses). |
| 35 // b) after the user classes are loaded (dart_api). | 35 // b) after the user classes are loaded (dart_api). |
| 36 bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) { | 36 bool ClassFinalizer::FinalizePendingClasses() { |
| 37 bool retval = true; | 37 bool retval = true; |
| 38 Isolate* isolate = Isolate::Current(); | 38 Isolate* isolate = Isolate::Current(); |
| 39 ASSERT(isolate != NULL); | 39 ASSERT(isolate != NULL); |
| 40 ObjectStore* object_store = isolate->object_store(); | 40 ObjectStore* object_store = isolate->object_store(); |
| 41 const Error& error = Error::Handle(object_store->sticky_error()); | 41 const Error& error = Error::Handle(object_store->sticky_error()); |
| 42 if (!error.IsNull()) { | 42 if (!error.IsNull()) { |
| 43 return false; | 43 return false; |
| 44 } | 44 } |
| 45 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
| 46 class_array = object_store->pending_classes(); |
| 47 ASSERT(!class_array.IsNull()); |
| 48 if (class_array.Length() == 0) { |
| 49 return true; |
| 50 } |
| 45 LongJump* base = isolate->long_jump_base(); | 51 LongJump* base = isolate->long_jump_base(); |
| 46 LongJump jump; | 52 LongJump jump; |
| 47 isolate->set_long_jump_base(&jump); | 53 isolate->set_long_jump_base(&jump); |
| 48 if (setjmp(*jump.Set()) == 0) { | 54 if (setjmp(*jump.Set()) == 0) { |
| 49 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); | |
| 50 class_array = object_store->pending_classes(); | |
| 51 ASSERT(!class_array.IsNull()); | |
| 52 Class& cls = Class::Handle(); | 55 Class& cls = Class::Handle(); |
| 53 // First resolve all superclasses. | 56 // First resolve all superclasses. |
| 54 for (intptr_t i = 0; i < class_array.Length(); i++) { | 57 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 55 cls ^= class_array.At(i); | 58 cls ^= class_array.At(i); |
| 56 if (FLAG_trace_class_finalization) { | 59 if (FLAG_trace_class_finalization) { |
| 57 OS::Print("Resolving super and default: %s\n", cls.ToCString()); | 60 OS::Print("Resolving super and default: %s\n", cls.ToCString()); |
| 58 } | 61 } |
| 59 ResolveSuperType(cls); | 62 ResolveSuperType(cls); |
| 60 if (cls.is_interface()) { | 63 if (cls.is_interface()) { |
| 61 ResolveFactoryClass(cls); | 64 ResolveFactoryClass(cls); |
| 62 } | 65 } |
| 63 } | 66 } |
| 64 // Finalize all classes. | 67 // Finalize all classes. |
| 65 for (intptr_t i = 0; i < class_array.Length(); i++) { | 68 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 66 cls ^= class_array.At(i); | 69 cls ^= class_array.At(i); |
| 67 FinalizeClass(cls, generating_snapshot); | 70 FinalizeClass(cls); |
| 68 } | 71 } |
| 69 if (FLAG_print_classes) { | 72 if (FLAG_print_classes) { |
| 70 for (intptr_t i = 0; i < class_array.Length(); i++) { | 73 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 71 cls ^= class_array.At(i); | 74 cls ^= class_array.At(i); |
| 72 PrintClassInformation(cls); | 75 PrintClassInformation(cls); |
| 73 } | 76 } |
| 74 } | 77 } |
| 75 if (FLAG_verify_implements) { | |
| 76 for (intptr_t i = 0; i < class_array.Length(); i++) { | |
| 77 cls ^= class_array.At(i); | |
| 78 if (!cls.is_interface()) { | |
| 79 VerifyClassImplements(cls); | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 // Clear pending classes array. | 78 // Clear pending classes array. |
| 84 class_array = GrowableObjectArray::New(); | 79 class_array = GrowableObjectArray::New(); |
| 85 object_store->set_pending_classes(class_array); | 80 object_store->set_pending_classes(class_array); |
| 86 } else { | 81 } else { |
| 87 retval = false; | 82 retval = false; |
| 88 } | 83 } |
| 89 isolate->set_long_jump_base(base); | 84 isolate->set_long_jump_base(base); |
| 90 return retval; | 85 return retval; |
| 91 } | 86 } |
| 92 | 87 |
| 93 | 88 |
| 94 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. | 89 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. |
| 95 // No cycles are allowed. | 90 // No cycles are allowed. |
| 96 void ClassFinalizer::CollectInterfaces(const Class& cls, | 91 void ClassFinalizer::CollectInterfaces(const Class& cls, |
| 97 const GrowableObjectArray& collected) { | 92 const GrowableObjectArray& collected) { |
| 98 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); | 93 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); |
| 99 AbstractType& interface = AbstractType::Handle(); | 94 AbstractType& interface = AbstractType::Handle(); |
| 100 Class& interface_class = Class::Handle(); | 95 Class& interface_class = Class::Handle(); |
| 101 for (intptr_t i = 0; i < interface_array.Length(); i++) { | 96 for (intptr_t i = 0; i < interface_array.Length(); i++) { |
| 102 interface ^= interface_array.At(i); | 97 interface ^= interface_array.At(i); |
| 103 interface_class = interface.type_class(); | 98 interface_class = interface.type_class(); |
| 104 collected.Add(interface_class); | 99 collected.Add(interface_class); |
| 105 CollectInterfaces(interface_class, collected); | 100 CollectInterfaces(interface_class, collected); |
| 106 } | 101 } |
| 107 } | 102 } |
| 108 | 103 |
| 109 | 104 |
| 110 #if defined (DEBUG) | |
| 111 // Collect all interfaces of the class 'cls' and check that every function | |
| 112 // defined in each interface can be found in the class. | |
| 113 // No need to check instance fields since they have been turned into | |
| 114 // getters/setters. | |
| 115 void ClassFinalizer::VerifyClassImplements(const Class& cls) { | |
| 116 ASSERT(!cls.is_interface()); | |
| 117 const GrowableObjectArray& interfaces = | |
| 118 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
| 119 CollectInterfaces(cls, interfaces); | |
| 120 const String& class_name = String::Handle(cls.Name()); | |
| 121 Class& interface_class = Class::Handle(); | |
| 122 String& interface_name = String::Handle(); | |
| 123 Array& interface_functions = Array::Handle(); | |
| 124 for (int i = 0; i < interfaces.Length(); i++) { | |
| 125 interface_class ^= interfaces.At(i); | |
| 126 interface_name = interface_class.Name(); | |
| 127 interface_functions = interface_class.functions(); | |
| 128 for (intptr_t f = 0; f < interface_functions.Length(); f++) { | |
| 129 Function& interface_function = Function::Handle(); | |
| 130 interface_function ^= interface_functions.At(f); | |
| 131 const String& function_name = String::Handle(interface_function.name()); | |
| 132 // Check for constructor/factory. | |
| 133 if (function_name.StartsWith(interface_name)) { | |
| 134 // TODO(srdjan): convert 'InterfaceName.' to 'ClassName.' and check. | |
| 135 continue; | |
| 136 } | |
| 137 if (interface_function.kind() == RawFunction::kConstImplicitGetter) { | |
| 138 // This interface constants are not overridable. | |
| 139 continue; | |
| 140 } | |
| 141 // Lookup function in 'cls' and all its super classes. | |
| 142 Class& test_class = Class::Handle(cls.raw()); | |
| 143 Function& class_function = | |
| 144 Function::Handle(test_class.LookupDynamicFunction(function_name)); | |
| 145 while (class_function.IsNull()) { | |
| 146 test_class = test_class.SuperClass(); | |
| 147 if (test_class.IsNull()) break; | |
| 148 class_function = test_class.LookupDynamicFunction(function_name); | |
| 149 } | |
| 150 if (class_function.IsNull()) { | |
| 151 OS::PrintErr("%s implements '%s' missing: '%s'\n", | |
| 152 class_name.ToCString(), | |
| 153 interface_name.ToCString(), | |
| 154 function_name.ToCString()); | |
| 155 } else { | |
| 156 Error& malformed_error = Error::Handle(); | |
| 157 if (!class_function.IsSubtypeOf(TypeArguments::Handle(), | |
| 158 interface_function, | |
| 159 TypeArguments::Handle(), | |
| 160 &malformed_error)) { | |
| 161 if (!malformed_error.IsNull()) { | |
| 162 OS::PrintErr("%s\n", malformed_error.ToErrorCString()); | |
| 163 } | |
| 164 OS::PrintErr("The type of instance method '%s' in class '%s' is not " | |
| 165 "a subtype of the type of '%s' in interface '%s'\n", | |
| 166 function_name.ToCString(), | |
| 167 class_name.ToCString(), | |
| 168 function_name.ToCString(), | |
| 169 interface_name.ToCString()); | |
| 170 } | |
| 171 } | |
| 172 } | |
| 173 } | |
| 174 } | |
| 175 #else | |
| 176 | |
| 177 void ClassFinalizer::VerifyClassImplements(const Class& cls) {} | |
| 178 | |
| 179 #endif | |
| 180 | |
| 181 | |
| 182 void ClassFinalizer::VerifyBootstrapClasses() { | 105 void ClassFinalizer::VerifyBootstrapClasses() { |
| 183 if (FLAG_trace_class_finalization) { | 106 if (FLAG_trace_class_finalization) { |
| 184 OS::Print("VerifyBootstrapClasses START.\n"); | 107 OS::Print("VerifyBootstrapClasses START.\n"); |
| 185 } | 108 } |
| 186 ObjectStore* object_store = Isolate::Current()->object_store(); | 109 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 187 | 110 |
| 188 Class& cls = Class::Handle(); | 111 Class& cls = Class::Handle(); |
| 189 #if defined(DEBUG) | 112 #if defined(DEBUG) |
| 190 // Basic checking. | 113 // Basic checking. |
| 191 cls = object_store->object_class(); | 114 cls = object_store->object_class(); |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 594 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
| 672 if (!arguments.IsNull()) { | 595 if (!arguments.IsNull()) { |
| 673 intptr_t num_arguments = arguments.Length(); | 596 intptr_t num_arguments = arguments.Length(); |
| 674 AbstractType& type_argument = AbstractType::Handle(); | 597 AbstractType& type_argument = AbstractType::Handle(); |
| 675 for (intptr_t i = 0; i < num_arguments; i++) { | 598 for (intptr_t i = 0; i < num_arguments; i++) { |
| 676 type_argument = arguments.TypeAt(i); | 599 type_argument = arguments.TypeAt(i); |
| 677 type_argument = FinalizeType(cls, type_argument, finalization); | 600 type_argument = FinalizeType(cls, type_argument, finalization); |
| 678 if (type_argument.IsMalformed()) { | 601 if (type_argument.IsMalformed()) { |
| 679 // In production mode, malformed type arguments are mapped to Dynamic. | 602 // In production mode, malformed type arguments are mapped to Dynamic. |
| 680 // In checked mode, a type with malformed type arguments is malformed. | 603 // In checked mode, a type with malformed type arguments is malformed. |
| 681 if (FLAG_enable_type_checks) { | 604 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { |
| 682 const Error& error = Error::Handle(type_argument.malformed_error()); | 605 const Error& error = Error::Handle(type_argument.malformed_error()); |
| 683 const String& type_name = | 606 const String& type_name = |
| 684 String::Handle(parameterized_type.UserVisibleName()); | 607 String::Handle(parameterized_type.UserVisibleName()); |
| 685 FinalizeMalformedType(error, cls, parameterized_type, finalization, | 608 FinalizeMalformedType(error, cls, parameterized_type, finalization, |
| 686 "type '%s' has malformed type argument", | 609 "type '%s' has malformed type argument", |
| 687 type_name.ToCString()); | 610 type_name.ToCString()); |
| 688 return parameterized_type.raw(); | 611 return parameterized_type.raw(); |
| 689 } else { | 612 } else { |
| 690 type_argument = Type::DynamicType(); | 613 type_argument = Type::DynamicType(); |
| 691 } | 614 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 if (type_class.IsCanonicalSignatureClass()) { | 729 if (type_class.IsCanonicalSignatureClass()) { |
| 807 ASSERT(type_class.is_finalized()); | 730 ASSERT(type_class.is_finalized()); |
| 808 // Resolve and finalize the result and parameter types of the signature | 731 // Resolve and finalize the result and parameter types of the signature |
| 809 // function of this signature class. | 732 // function of this signature class. |
| 810 ASSERT(type_class.SignatureType() == type.raw()); | 733 ASSERT(type_class.SignatureType() == type.raw()); |
| 811 ResolveAndFinalizeSignature( | 734 ResolveAndFinalizeSignature( |
| 812 type_class, Function::Handle(type_class.signature_function())); | 735 type_class, Function::Handle(type_class.signature_function())); |
| 813 } else { | 736 } else { |
| 814 // This type is a function type alias. Its class may need to be finalized | 737 // This type is a function type alias. Its class may need to be finalized |
| 815 // and checked for illegal self reference. | 738 // and checked for illegal self reference. |
| 816 FinalizeClass(type_class, false); | 739 FinalizeClass(type_class); |
| 817 // Finalizing the signature function here (as in the canonical case above) | 740 // Finalizing the signature function here (as in the canonical case above) |
| 818 // would not mark the canonical signature type as finalized. | 741 // would not mark the canonical signature type as finalized. |
| 819 const Type& signature_type = Type::Handle(type_class.SignatureType()); | 742 const Type& signature_type = Type::Handle(type_class.SignatureType()); |
| 820 FinalizeType(cls, signature_type, finalization); | 743 FinalizeType(cls, signature_type, finalization); |
| 821 } | 744 } |
| 822 } | 745 } |
| 823 | 746 |
| 824 if (finalization >= kCanonicalize) { | 747 if (finalization >= kCanonicalize) { |
| 825 return parameterized_type.Canonicalize(); | 748 return parameterized_type.Canonicalize(); |
| 826 } else { | 749 } else { |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1072 function_name.ToCString(), | 995 function_name.ToCString(), |
| 1073 class_name.ToCString(), | 996 class_name.ToCString(), |
| 1074 function_name.ToCString(), | 997 function_name.ToCString(), |
| 1075 super_class_name.ToCString()); | 998 super_class_name.ToCString()); |
| 1076 } | 999 } |
| 1077 } | 1000 } |
| 1078 } | 1001 } |
| 1079 } | 1002 } |
| 1080 | 1003 |
| 1081 | 1004 |
| 1082 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { | 1005 void ClassFinalizer::FinalizeClass(const Class& cls) { |
| 1083 if (cls.is_finalized()) { | 1006 if (cls.is_finalized()) { |
| 1084 return; | 1007 return; |
| 1085 } | 1008 } |
| 1086 if (FLAG_trace_class_finalization) { | 1009 if (FLAG_trace_class_finalization) { |
| 1087 OS::Print("Finalize %s\n", cls.ToCString()); | 1010 OS::Print("Finalize %s\n", cls.ToCString()); |
| 1088 } | 1011 } |
| 1089 if (!IsSuperCycleFree(cls)) { | 1012 if (!IsSuperCycleFree(cls)) { |
| 1090 const String& name = String::Handle(cls.Name()); | 1013 const String& name = String::Handle(cls.Name()); |
| 1091 const Script& script = Script::Handle(cls.script()); | 1014 const Script& script = Script::Handle(cls.script()); |
| 1092 ReportError(script, cls.token_pos(), | 1015 ReportError(script, cls.token_pos(), |
| 1093 "class '%s' has a cycle in its superclass relationship", | 1016 "class '%s' has a cycle in its superclass relationship", |
| 1094 name.ToCString()); | 1017 name.ToCString()); |
| 1095 } | 1018 } |
| 1096 GrowableArray<intptr_t> visited_interfaces; | 1019 GrowableArray<intptr_t> visited_interfaces; |
| 1097 ResolveInterfaces(cls, &visited_interfaces); | 1020 ResolveInterfaces(cls, &visited_interfaces); |
| 1098 // Finalize super class. | 1021 // Finalize super class. |
| 1099 const Class& super_class = Class::Handle(cls.SuperClass()); | 1022 const Class& super_class = Class::Handle(cls.SuperClass()); |
| 1100 if (!super_class.IsNull()) { | 1023 if (!super_class.IsNull()) { |
| 1101 FinalizeClass(super_class, generating_snapshot); | 1024 FinalizeClass(super_class); |
| 1102 } | 1025 } |
| 1103 // Finalize type parameters before finalizing the super type. | 1026 // Finalize type parameters before finalizing the super type. |
| 1104 FinalizeTypeParameters(cls); | 1027 FinalizeTypeParameters(cls); |
| 1105 // Finalize super type. | 1028 // Finalize super type. |
| 1106 Type& super_type = Type::Handle(cls.super_type()); | 1029 Type& super_type = Type::Handle(cls.super_type()); |
| 1107 if (!super_type.IsNull()) { | 1030 if (!super_type.IsNull()) { |
| 1108 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1031 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
| 1109 cls.set_super_type(super_type); | 1032 cls.set_super_type(super_type); |
| 1110 } | 1033 } |
| 1111 // Signature classes are finalized upon creation, except function type | 1034 // Signature classes are finalized upon creation, except function type |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1125 // Signature classes extend Object. No need to add this class to the direct | 1048 // Signature classes extend Object. No need to add this class to the direct |
| 1126 // subclasses of Object. | 1049 // subclasses of Object. |
| 1127 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1050 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
| 1128 return; | 1051 return; |
| 1129 } | 1052 } |
| 1130 // Finalize factory class, if any. | 1053 // Finalize factory class, if any. |
| 1131 if (cls.is_interface()) { | 1054 if (cls.is_interface()) { |
| 1132 if (cls.HasFactoryClass()) { | 1055 if (cls.HasFactoryClass()) { |
| 1133 const Class& factory_class = Class::Handle(cls.FactoryClass()); | 1056 const Class& factory_class = Class::Handle(cls.FactoryClass()); |
| 1134 if (!factory_class.is_finalized()) { | 1057 if (!factory_class.is_finalized()) { |
| 1135 FinalizeClass(factory_class, generating_snapshot); | 1058 FinalizeClass(factory_class); |
| 1136 // Finalizing the factory class may indirectly finalize this interface. | 1059 // Finalizing the factory class may indirectly finalize this interface. |
| 1137 if (cls.is_finalized()) { | 1060 if (cls.is_finalized()) { |
| 1138 return; | 1061 return; |
| 1139 } | 1062 } |
| 1140 } | 1063 } |
| 1141 } | 1064 } |
| 1142 } | 1065 } |
| 1143 // Finalize interface types (but not necessarily interface classes). | 1066 // Finalize interface types (but not necessarily interface classes). |
| 1144 Array& interface_types = Array::Handle(cls.interfaces()); | 1067 Array& interface_types = Array::Handle(cls.interfaces()); |
| 1145 AbstractType& interface_type = AbstractType::Handle(); | 1068 AbstractType& interface_type = AbstractType::Handle(); |
| 1146 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 1069 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
| 1147 interface_type ^= interface_types.At(i); | 1070 interface_type ^= interface_types.At(i); |
| 1148 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1071 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
| 1149 interface_types.SetAt(i, interface_type); | 1072 interface_types.SetAt(i, interface_type); |
| 1150 } | 1073 } |
| 1151 // Mark as finalized before resolving type parameter upper bounds and member | 1074 // Mark as finalized before resolving type parameter upper bounds and member |
| 1152 // types in order to break cycles. | 1075 // types in order to break cycles. |
| 1153 cls.Finalize(); | 1076 cls.Finalize(); |
| 1154 ResolveAndFinalizeUpperBounds(cls); | 1077 ResolveAndFinalizeUpperBounds(cls); |
| 1155 ResolveAndFinalizeMemberTypes(cls); | 1078 ResolveAndFinalizeMemberTypes(cls); |
| 1156 // Run additional checks after all types are finalized. | 1079 // Run additional checks after all types are finalized. |
| 1157 if (cls.is_const()) { | 1080 if (cls.is_const()) { |
| 1158 CheckForLegalConstClass(cls); | 1081 CheckForLegalConstClass(cls); |
| 1159 } | 1082 } |
| 1160 // Check to ensure we don't have classes with native fields in libraries | 1083 // Check to ensure we don't have classes with native fields in libraries |
| 1161 // which do not have a native resolver. | 1084 // which do not have a native resolver. |
| 1162 if (!generating_snapshot && cls.num_native_fields() != 0) { | 1085 if (cls.num_native_fields() != 0) { |
| 1163 const Library& lib = Library::Handle(cls.library()); | 1086 const Library& lib = Library::Handle(cls.library()); |
| 1164 if (lib.native_entry_resolver() == NULL) { | 1087 if (lib.native_entry_resolver() == NULL) { |
| 1165 const String& cls_name = String::Handle(cls.Name()); | 1088 const String& cls_name = String::Handle(cls.Name()); |
| 1166 const String& lib_name = String::Handle(lib.url()); | 1089 const String& lib_name = String::Handle(lib.url()); |
| 1167 const Script& script = Script::Handle(cls.script()); | 1090 const Script& script = Script::Handle(cls.script()); |
| 1168 ReportError(script, cls.token_pos(), | 1091 ReportError(script, cls.token_pos(), |
| 1169 "class '%s' is trying to extend a native fields class, " | 1092 "class '%s' is trying to extend a native fields class, " |
| 1170 "but library '%s' has no native resolvers", | 1093 "but library '%s' has no native resolvers", |
| 1171 cls_name.ToCString(), lib_name.ToCString()); | 1094 cls_name.ToCString(), lib_name.ToCString()); |
| 1172 } | 1095 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 return false; | 1170 return false; |
| 1248 } | 1171 } |
| 1249 } | 1172 } |
| 1250 } | 1173 } |
| 1251 } | 1174 } |
| 1252 visited->RemoveLast(); | 1175 visited->RemoveLast(); |
| 1253 return true; | 1176 return true; |
| 1254 } | 1177 } |
| 1255 | 1178 |
| 1256 | 1179 |
| 1257 bool ClassFinalizer::AddInterfaceIfUnique( | |
| 1258 const GrowableObjectArray& interface_list, | |
| 1259 const AbstractType& interface, | |
| 1260 AbstractType* conflicting) { | |
| 1261 String& interface_class_name = String::Handle(interface.ClassName()); | |
| 1262 String& existing_interface_class_name = String::Handle(); | |
| 1263 String& interface_name = String::Handle(); | |
| 1264 String& existing_interface_name = String::Handle(); | |
| 1265 AbstractType& other_interface = AbstractType::Handle(); | |
| 1266 for (intptr_t i = 0; i < interface_list.Length(); i++) { | |
| 1267 other_interface ^= interface_list.At(i); | |
| 1268 existing_interface_class_name = other_interface.ClassName(); | |
| 1269 if (interface_class_name.Equals(existing_interface_class_name)) { | |
| 1270 // Same interface class name, now check names of type arguments. | |
| 1271 interface_name = interface.Name(); | |
| 1272 existing_interface_name = other_interface.Name(); | |
| 1273 // TODO(regis): Revisit depending on the outcome of issue 4905685. | |
| 1274 if (!interface_name.Equals(existing_interface_name)) { | |
| 1275 *conflicting = other_interface.raw(); | |
| 1276 return false; | |
| 1277 } else { | |
| 1278 return true; | |
| 1279 } | |
| 1280 } | |
| 1281 } | |
| 1282 interface_list.Add(interface); | |
| 1283 return true; | |
| 1284 } | |
| 1285 | |
| 1286 | |
| 1287 // Walks the graph of explicitly declared interfaces of classes and | 1180 // Walks the graph of explicitly declared interfaces of classes and |
| 1288 // interfaces recursively. Resolves unresolved interfaces. | 1181 // interfaces recursively. Resolves unresolved interfaces. |
| 1289 // Returns false if there is an interface reference that cannot be | 1182 // Returns false if there is an interface reference that cannot be |
| 1290 // resolved, or if there is a cycle in the graph. We detect cycles by | 1183 // resolved, or if there is a cycle in the graph. We detect cycles by |
| 1291 // remembering interfaces we've visited in each path through the | 1184 // remembering interfaces we've visited in each path through the |
| 1292 // graph. If we visit an interface a second time on a given path, | 1185 // graph. If we visit an interface a second time on a given path, |
| 1293 // we found a loop. | 1186 // we found a loop. |
| 1294 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1187 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
| 1295 GrowableArray<intptr_t>* visited) { | 1188 GrowableArray<intptr_t>* visited) { |
| 1296 ASSERT(visited != NULL); | 1189 ASSERT(visited != NULL); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, | 1340 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
| 1448 const Class& cls, | 1341 const Class& cls, |
| 1449 const Type& type, | 1342 const Type& type, |
| 1450 FinalizationKind finalization, | 1343 FinalizationKind finalization, |
| 1451 const char* format, ...) { | 1344 const char* format, ...) { |
| 1452 va_list args; | 1345 va_list args; |
| 1453 va_start(args, format); | 1346 va_start(args, format); |
| 1454 LanguageError& error = LanguageError::Handle(); | 1347 LanguageError& error = LanguageError::Handle(); |
| 1455 if (FLAG_enable_type_checks || | 1348 if (FLAG_enable_type_checks || |
| 1456 !type.HasResolvedTypeClass() || | 1349 !type.HasResolvedTypeClass() || |
| 1457 (finalization == kCanonicalizeWellFormed)) { | 1350 (finalization == kCanonicalizeWellFormed) || |
| 1351 FLAG_error_on_malformed_type) { |
| 1458 const Script& script = Script::Handle(cls.script()); | 1352 const Script& script = Script::Handle(cls.script()); |
| 1459 if (prev_error.IsNull()) { | 1353 if (prev_error.IsNull()) { |
| 1460 error ^= Parser::FormatError( | 1354 error ^= Parser::FormatError( |
| 1461 script, type.token_pos(), "Error", format, args); | 1355 script, type.token_pos(), "Error", format, args); |
| 1462 } else { | 1356 } else { |
| 1463 error ^= Parser::FormatErrorWithAppend( | 1357 error ^= Parser::FormatErrorWithAppend( |
| 1464 prev_error, script, type.token_pos(), "Error", format, args); | 1358 prev_error, script, type.token_pos(), "Error", format, args); |
| 1465 } | 1359 } |
| 1466 if (finalization == kCanonicalizeWellFormed) { | 1360 if ((finalization == kCanonicalizeWellFormed) || |
| 1361 FLAG_error_on_malformed_type) { |
| 1467 ReportError(error); | 1362 ReportError(error); |
| 1468 } | 1363 } |
| 1469 } | 1364 } |
| 1470 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { | 1365 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
| 1471 // In check mode, always mark the type as malformed. | 1366 // In check mode, always mark the type as malformed. |
| 1472 // In production mode, mark the type as malformed only if its type class is | 1367 // In production mode, mark the type as malformed only if its type class is |
| 1473 // not resolved. | 1368 // not resolved. |
| 1474 type.set_malformed_error(error); | 1369 type.set_malformed_error(error); |
| 1475 } else { | 1370 } else { |
| 1476 // In production mode, do not mark the type with a resolved type class as | 1371 // In production mode, do not mark the type with a resolved type class as |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1509 void ClassFinalizer::ReportError(const char* format, ...) { | 1404 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1510 va_list args; | 1405 va_list args; |
| 1511 va_start(args, format); | 1406 va_start(args, format); |
| 1512 const Error& error = Error::Handle( | 1407 const Error& error = Error::Handle( |
| 1513 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1408 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1514 va_end(args); | 1409 va_end(args); |
| 1515 ReportError(error); | 1410 ReportError(error); |
| 1516 } | 1411 } |
| 1517 | 1412 |
| 1518 } // namespace dart | 1413 } // namespace dart |
| OLD | NEW |