| 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 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); | 16 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
| 17 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 17 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
| 18 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 18 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
| 19 DEFINE_FLAG(bool, verify_implements, false, | 19 DEFINE_FLAG(bool, verify_implements, false, |
| 20 "Verify that all classes implement their interface."); | 20 "Verify that all classes implement their interface."); |
| 21 DECLARE_FLAG(bool, enable_type_checks); | 21 DECLARE_FLAG(bool, enable_type_checks); |
| 22 | 22 |
| 23 void ClassFinalizer::AddPendingClasses( | |
| 24 const GrowableArray<const Class*>& classes) { | |
| 25 if (!classes.is_empty()) { | |
| 26 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 27 const Array& old_array = Array::Handle(object_store->pending_classes()); | |
| 28 const intptr_t old_length = old_array.Length(); | |
| 29 const int new_length = old_length + classes.length(); | |
| 30 const Array& new_array = Array::Handle(Array::Grow(old_array, new_length)); | |
| 31 // Add new classes. | |
| 32 for (int i = 0; i < classes.length(); i++) { | |
| 33 new_array.SetAt(i + old_length, *classes[i]); | |
| 34 } | |
| 35 object_store->set_pending_classes(new_array); | |
| 36 } | |
| 37 } | |
| 38 | |
| 39 | 23 |
| 40 bool ClassFinalizer::AllClassesFinalized() { | 24 bool ClassFinalizer::AllClassesFinalized() { |
| 41 ObjectStore* object_store = Isolate::Current()->object_store(); | 25 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 42 const Array& classes = Array::Handle(object_store->pending_classes()); | 26 const GrowableObjectArray& classes = |
| 27 GrowableObjectArray::Handle(object_store->pending_classes()); |
| 43 return classes.Length() == 0; | 28 return classes.Length() == 0; |
| 44 } | 29 } |
| 45 | 30 |
| 46 | 31 |
| 47 // Class finalization occurs: | 32 // Class finalization occurs: |
| 48 // a) when bootstrap process completes (VerifyBootstrapClasses). | 33 // a) when bootstrap process completes (VerifyBootstrapClasses). |
| 49 // b) after the user classes are loaded (dart_api). | 34 // b) after the user classes are loaded (dart_api). |
| 50 bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) { | 35 bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) { |
| 51 bool retval = true; | 36 bool retval = true; |
| 52 Isolate* isolate = Isolate::Current(); | 37 Isolate* isolate = Isolate::Current(); |
| 53 ASSERT(isolate != NULL); | 38 ASSERT(isolate != NULL); |
| 54 ObjectStore* object_store = isolate->object_store(); | 39 ObjectStore* object_store = isolate->object_store(); |
| 55 const Error& error = Error::Handle(object_store->sticky_error()); | 40 const Error& error = Error::Handle(object_store->sticky_error()); |
| 56 if (!error.IsNull()) { | 41 if (!error.IsNull()) { |
| 57 return false; | 42 return false; |
| 58 } | 43 } |
| 59 LongJump* base = isolate->long_jump_base(); | 44 LongJump* base = isolate->long_jump_base(); |
| 60 LongJump jump; | 45 LongJump jump; |
| 61 isolate->set_long_jump_base(&jump); | 46 isolate->set_long_jump_base(&jump); |
| 62 if (setjmp(*jump.Set()) == 0) { | 47 if (setjmp(*jump.Set()) == 0) { |
| 63 const Array& class_array = Array::Handle(object_store->pending_classes()); | 48 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
| 49 class_array = object_store->pending_classes(); |
| 64 ASSERT(!class_array.IsNull()); | 50 ASSERT(!class_array.IsNull()); |
| 65 Class& cls = Class::Handle(); | 51 Class& cls = Class::Handle(); |
| 66 // First resolve all superclasses. | 52 // First resolve all superclasses. |
| 67 for (intptr_t i = 0; i < class_array.Length(); i++) { | 53 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 68 cls ^= class_array.At(i); | 54 cls ^= class_array.At(i); |
| 69 if (FLAG_trace_class_finalization) { | 55 if (FLAG_trace_class_finalization) { |
| 70 OS::Print("Resolving super and default: %s\n", cls.ToCString()); | 56 OS::Print("Resolving super and default: %s\n", cls.ToCString()); |
| 71 } | 57 } |
| 72 ResolveSuperType(cls); | 58 ResolveSuperType(cls); |
| 73 if (cls.is_interface()) { | 59 if (cls.is_interface()) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 87 } | 73 } |
| 88 if (FLAG_verify_implements) { | 74 if (FLAG_verify_implements) { |
| 89 for (intptr_t i = 0; i < class_array.Length(); i++) { | 75 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 90 cls ^= class_array.At(i); | 76 cls ^= class_array.At(i); |
| 91 if (!cls.is_interface()) { | 77 if (!cls.is_interface()) { |
| 92 VerifyClassImplements(cls); | 78 VerifyClassImplements(cls); |
| 93 } | 79 } |
| 94 } | 80 } |
| 95 } | 81 } |
| 96 // Clear pending classes array. | 82 // Clear pending classes array. |
| 97 object_store->set_pending_classes(Array::Handle(Array::Empty())); | 83 class_array = GrowableObjectArray::New(); |
| 84 object_store->set_pending_classes(class_array); |
| 98 | 85 |
| 99 // Check to ensure there are no duplicate definitions in the library | 86 // Check to ensure there are no duplicate definitions in the library |
| 100 // hierarchy. | 87 // hierarchy. |
| 101 const String& str = String::Handle(Library::CheckForDuplicateDefinition()); | 88 const String& str = String::Handle(Library::CheckForDuplicateDefinition()); |
| 102 if (!str.IsNull()) { | 89 if (!str.IsNull()) { |
| 103 ReportError("Duplicate definition : %s\n", str.ToCString()); | 90 ReportError("Duplicate definition : %s\n", str.ToCString()); |
| 104 } | 91 } |
| 105 } else { | 92 } else { |
| 106 retval = false; | 93 retval = false; |
| 107 } | 94 } |
| 108 isolate->set_long_jump_base(base); | 95 isolate->set_long_jump_base(base); |
| 109 return retval; | 96 return retval; |
| 110 } | 97 } |
| 111 | 98 |
| 112 | 99 |
| 113 #if defined (DEBUG) | 100 #if defined (DEBUG) |
| 114 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. | 101 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. |
| 115 // No cycles are allowed. | 102 // No cycles are allowed. |
| 116 void ClassFinalizer::CollectInterfaces(const Class& cls, | 103 void ClassFinalizer::CollectInterfaces(const Class& cls, |
| 117 GrowableArray<const Class*>* collected) { | 104 const GrowableObjectArray& collected) { |
| 118 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); | 105 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); |
| 106 AbstractType& interface = AbstractType::Handle(); |
| 107 Class& interface_class = Class::Handle(); |
| 119 for (intptr_t i = 0; i < interface_array.Length(); i++) { | 108 for (intptr_t i = 0; i < interface_array.Length(); i++) { |
| 120 AbstractType& interface = AbstractType::Handle(); | |
| 121 interface ^= interface_array.At(i); | 109 interface ^= interface_array.At(i); |
| 122 const Class& interface_class = Class::ZoneHandle(interface.type_class()); | 110 interface_class = interface.type_class(); |
| 123 collected->Add(&interface_class); | 111 collected.Add(interface_class); |
| 124 CollectInterfaces(interface_class, collected); | 112 CollectInterfaces(interface_class, collected); |
| 125 } | 113 } |
| 126 } | 114 } |
| 127 | 115 |
| 128 | 116 |
| 129 // Collect all interfaces of the class 'cls' and check that every function | 117 // Collect all interfaces of the class 'cls' and check that every function |
| 130 // defined in each interface can be found in the class. | 118 // defined in each interface can be found in the class. |
| 131 // No need to check instance fields since they have been turned into | 119 // No need to check instance fields since they have been turned into |
| 132 // getters/setters. | 120 // getters/setters. |
| 133 void ClassFinalizer::VerifyClassImplements(const Class& cls) { | 121 void ClassFinalizer::VerifyClassImplements(const Class& cls) { |
| 134 ASSERT(!cls.is_interface()); | 122 ASSERT(!cls.is_interface()); |
| 135 GrowableArray<const Class*> interfaces; | 123 const GrowableObjectArray& interfaces = |
| 136 CollectInterfaces(cls, &interfaces); | 124 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 125 CollectInterfaces(cls, interfaces); |
| 137 const String& class_name = String::Handle(cls.Name()); | 126 const String& class_name = String::Handle(cls.Name()); |
| 138 for (int i = 0; i < interfaces.length(); i++) { | 127 Class& interface_class = Class::Handle(); |
| 139 const String& interface_name = String::Handle(interfaces[i]->Name()); | 128 String& interface_name = String::Handle(); |
| 140 const Array& interface_functions = | 129 Array& interface_functions = Array::Handle(); |
| 141 Array::Handle(interfaces[i]->functions()); | 130 for (int i = 0; i < interfaces.Length(); i++) { |
| 131 interface_class ^= interfaces.At(i); |
| 132 interface_name = interface_class.Name(); |
| 133 interface_functions = interface_class.functions(); |
| 142 for (intptr_t f = 0; f < interface_functions.Length(); f++) { | 134 for (intptr_t f = 0; f < interface_functions.Length(); f++) { |
| 143 Function& interface_function = Function::Handle(); | 135 Function& interface_function = Function::Handle(); |
| 144 interface_function ^= interface_functions.At(f); | 136 interface_function ^= interface_functions.At(f); |
| 145 const String& function_name = String::Handle(interface_function.name()); | 137 const String& function_name = String::Handle(interface_function.name()); |
| 146 // Check for constructor/factory. | 138 // Check for constructor/factory. |
| 147 if (function_name.StartsWith(interface_name)) { | 139 if (function_name.StartsWith(interface_name)) { |
| 148 // TODO(srdjan): convert 'InterfaceName.' to 'ClassName.' and check. | 140 // TODO(srdjan): convert 'InterfaceName.' to 'ClassName.' and check. |
| 149 continue; | 141 continue; |
| 150 } | 142 } |
| 151 if (interface_function.kind() == RawFunction::kConstImplicitGetter) { | 143 if (interface_function.kind() == RawFunction::kConstImplicitGetter) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 ASSERT(Array::InstanceSize() == cls.instance_size()); | 215 ASSERT(Array::InstanceSize() == cls.instance_size()); |
| 224 cls = object_store->immutable_array_class(); | 216 cls = object_store->immutable_array_class(); |
| 225 ASSERT(ImmutableArray::InstanceSize() == cls.instance_size()); | 217 ASSERT(ImmutableArray::InstanceSize() == cls.instance_size()); |
| 226 cls = object_store->internal_byte_array_class(); | 218 cls = object_store->internal_byte_array_class(); |
| 227 ASSERT(InternalByteArray::InstanceSize() == cls.instance_size()); | 219 ASSERT(InternalByteArray::InstanceSize() == cls.instance_size()); |
| 228 cls = object_store->external_byte_array_class(); | 220 cls = object_store->external_byte_array_class(); |
| 229 ASSERT(ExternalByteArray::InstanceSize() == cls.instance_size()); | 221 ASSERT(ExternalByteArray::InstanceSize() == cls.instance_size()); |
| 230 #endif // defined(DEBUG) | 222 #endif // defined(DEBUG) |
| 231 | 223 |
| 232 // Remember the currently pending classes. | 224 // Remember the currently pending classes. |
| 233 const Array& class_array = Array::Handle(object_store->pending_classes()); | 225 const GrowableObjectArray& class_array = |
| 226 GrowableObjectArray::Handle(object_store->pending_classes()); |
| 234 for (intptr_t i = 0; i < class_array.Length(); i++) { | 227 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 235 // TODO(iposva): Add real checks. | 228 // TODO(iposva): Add real checks. |
| 236 cls ^= class_array.At(i); | 229 cls ^= class_array.At(i); |
| 237 if (cls.is_finalized() || cls.is_prefinalized()) { | 230 if (cls.is_finalized() || cls.is_prefinalized()) { |
| 238 // Pre-finalized bootstrap classes must not define any fields. | 231 // Pre-finalized bootstrap classes must not define any fields. |
| 239 ASSERT(Array::Handle(cls.fields()).Length() == 0); | 232 ASSERT(Array::Handle(cls.fields()).Length() == 0); |
| 240 } | 233 } |
| 241 } | 234 } |
| 242 | 235 |
| 243 // Finalize classes that aren't pre-finalized by Object::Init(). | 236 // Finalize classes that aren't pre-finalized by Object::Init(). |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 } | 896 } |
| 904 // Signature classes are finalized upon creation. | 897 // Signature classes are finalized upon creation. |
| 905 ASSERT(!cls.IsSignatureClass()); | 898 ASSERT(!cls.IsSignatureClass()); |
| 906 if (!IsSuperCycleFree(cls)) { | 899 if (!IsSuperCycleFree(cls)) { |
| 907 const String& name = String::Handle(cls.Name()); | 900 const String& name = String::Handle(cls.Name()); |
| 908 const Script& script = Script::Handle(cls.script()); | 901 const Script& script = Script::Handle(cls.script()); |
| 909 ReportError(script, cls.token_index(), | 902 ReportError(script, cls.token_index(), |
| 910 "class '%s' has a cycle in its superclass relationship", | 903 "class '%s' has a cycle in its superclass relationship", |
| 911 name.ToCString()); | 904 name.ToCString()); |
| 912 } | 905 } |
| 913 GrowableArray<const Class*> visited; | 906 const GrowableObjectArray& visited = |
| 914 ResolveInterfaces(cls, &visited); | 907 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 908 ResolveInterfaces(cls, visited); |
| 915 Type& super_type = Type::Handle(cls.super_type()); | 909 Type& super_type = Type::Handle(cls.super_type()); |
| 916 if (!super_type.IsNull()) { | 910 if (!super_type.IsNull()) { |
| 917 const Class& super_class = Class::Handle(super_type.type_class()); | 911 const Class& super_class = Class::Handle(super_type.type_class()); |
| 918 // Finalize super class and super type. | 912 // Finalize super class and super type. |
| 919 FinalizeClass(super_class, generating_snapshot); | 913 FinalizeClass(super_class, generating_snapshot); |
| 920 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); | 914 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); |
| 921 cls.set_super_type(super_type); | 915 cls.set_super_type(super_type); |
| 922 } | 916 } |
| 923 if (cls.is_interface()) { | 917 if (cls.is_interface()) { |
| 924 if (cls.HasFactoryClass()) { | 918 if (cls.HasFactoryClass()) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 if (!test2.IsNull()) { | 977 if (!test2.IsNull()) { |
| 984 test2 = test2.SuperClass(); | 978 test2 = test2.SuperClass(); |
| 985 } | 979 } |
| 986 } | 980 } |
| 987 // No cycles. | 981 // No cycles. |
| 988 return true; | 982 return true; |
| 989 } | 983 } |
| 990 | 984 |
| 991 | 985 |
| 992 bool ClassFinalizer::AddInterfaceIfUnique( | 986 bool ClassFinalizer::AddInterfaceIfUnique( |
| 993 GrowableArray<AbstractType*>* interface_list, | 987 const GrowableObjectArray& interface_list, |
| 994 AbstractType* interface, | 988 const AbstractType& interface, |
| 995 AbstractType* conflicting) { | 989 AbstractType* conflicting) { |
| 996 String& interface_class_name = String::Handle(interface->ClassName()); | 990 String& interface_class_name = String::Handle(interface.ClassName()); |
| 997 String& existing_interface_class_name = String::Handle(); | 991 String& existing_interface_class_name = String::Handle(); |
| 998 for (intptr_t i = 0; i < interface_list->length(); i++) { | 992 String& interface_name = String::Handle(); |
| 999 existing_interface_class_name = (*interface_list)[i]->ClassName(); | 993 String& existing_interface_name = String::Handle(); |
| 994 AbstractType& other_interface = AbstractType::Handle(); |
| 995 for (intptr_t i = 0; i < interface_list.Length(); i++) { |
| 996 other_interface ^= interface_list.At(i); |
| 997 existing_interface_class_name = other_interface.ClassName(); |
| 1000 if (interface_class_name.Equals(existing_interface_class_name)) { | 998 if (interface_class_name.Equals(existing_interface_class_name)) { |
| 1001 // Same interface class name, now check names of type arguments. | 999 // Same interface class name, now check names of type arguments. |
| 1002 const String& interface_name = String::Handle(interface->Name()); | 1000 interface_name = interface.Name(); |
| 1003 const String& existing_interface_name = | 1001 existing_interface_name = other_interface.Name(); |
| 1004 String::Handle((*interface_list)[i]->Name()); | |
| 1005 // TODO(regis): Revisit depending on the outcome of issue 4905685. | 1002 // TODO(regis): Revisit depending on the outcome of issue 4905685. |
| 1006 if (!interface_name.Equals(existing_interface_name)) { | 1003 if (!interface_name.Equals(existing_interface_name)) { |
| 1007 *conflicting = (*interface_list)[i]->raw(); | 1004 *conflicting = other_interface.raw(); |
| 1008 return false; | 1005 return false; |
| 1009 } else { | 1006 } else { |
| 1010 return true; | 1007 return true; |
| 1011 } | 1008 } |
| 1012 } | 1009 } |
| 1013 } | 1010 } |
| 1014 interface_list->Add(interface); | 1011 interface_list.Add(interface); |
| 1015 return true; | 1012 return true; |
| 1016 } | 1013 } |
| 1017 | 1014 |
| 1018 | 1015 |
| 1019 template<typename T> | |
| 1020 static RawArray* NewArray(const GrowableArray<T*>& objs) { | |
| 1021 Array& a = Array::Handle(Array::New(objs.length())); | |
| 1022 for (int i = 0; i < objs.length(); i++) { | |
| 1023 a.SetAt(i, *objs[i]); | |
| 1024 } | |
| 1025 return a.raw(); | |
| 1026 } | |
| 1027 | |
| 1028 | |
| 1029 // Walks the graph of explicitly declared interfaces of classes and | 1016 // Walks the graph of explicitly declared interfaces of classes and |
| 1030 // interfaces recursively. Resolves unresolved interfaces. | 1017 // interfaces recursively. Resolves unresolved interfaces. |
| 1031 // Returns false if there is an interface reference that cannot be | 1018 // Returns false if there is an interface reference that cannot be |
| 1032 // resolved, or if there is a cycle in the graph. We detect cycles by | 1019 // resolved, or if there is a cycle in the graph. We detect cycles by |
| 1033 // remembering interfaces we've visited in each path through the | 1020 // remembering interfaces we've visited in each path through the |
| 1034 // graph. If we visit an interface a second time on a given path, | 1021 // graph. If we visit an interface a second time on a given path, |
| 1035 // we found a loop. | 1022 // we found a loop. |
| 1036 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1023 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
| 1037 GrowableArray<const Class*>* visited) { | 1024 const GrowableObjectArray& visited) { |
| 1038 ASSERT(visited != NULL); | 1025 ASSERT(!visited.IsNull()); |
| 1039 for (int i = 0; i < visited->length(); i++) { | 1026 Class& visited_cls = Class::Handle(); |
| 1040 if ((*visited)[i]->raw() == cls.raw()) { | 1027 for (int i = 0; i < visited.Length(); i++) { |
| 1028 visited_cls ^= visited.At(i); |
| 1029 if (visited_cls.raw() == cls.raw()) { |
| 1041 // We have already visited interface class 'cls'. We found a cycle. | 1030 // We have already visited interface class 'cls'. We found a cycle. |
| 1042 const String& interface_name = String::Handle(cls.Name()); | 1031 const String& interface_name = String::Handle(cls.Name()); |
| 1043 const Script& script = Script::Handle(cls.script()); | 1032 const Script& script = Script::Handle(cls.script()); |
| 1044 ReportError(script, cls.token_index(), | 1033 ReportError(script, cls.token_index(), |
| 1045 "cyclic reference found for interface '%s'", | 1034 "cyclic reference found for interface '%s'", |
| 1046 interface_name.ToCString()); | 1035 interface_name.ToCString()); |
| 1047 } | 1036 } |
| 1048 } | 1037 } |
| 1049 | 1038 |
| 1050 // If the class/interface has no explicit interfaces, we are done. | 1039 // If the class/interface has no explicit interfaces, we are done. |
| 1051 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1040 Array& super_interfaces = Array::Handle(cls.interfaces()); |
| 1052 if (super_interfaces.Length() == 0) { | 1041 if (super_interfaces.Length() == 0) { |
| 1053 return; | 1042 return; |
| 1054 } | 1043 } |
| 1055 | 1044 |
| 1056 // If cls belongs to core lib or to core lib's implementation, restrictions | 1045 // If cls belongs to core lib or to core lib's implementation, restrictions |
| 1057 // about allowed interfaces are lifted. | 1046 // about allowed interfaces are lifted. |
| 1058 const bool cls_belongs_to_core_lib = | 1047 const bool cls_belongs_to_core_lib = |
| 1059 (cls.library() == Library::CoreLibrary()) || | 1048 (cls.library() == Library::CoreLibrary()) || |
| 1060 (cls.library() == Library::CoreImplLibrary()); | 1049 (cls.library() == Library::CoreImplLibrary()); |
| 1061 | 1050 |
| 1062 // Resolve and check the interfaces of cls. | 1051 // Resolve and check the interfaces of cls. |
| 1063 visited->Add(&cls); | 1052 visited.Add(cls); |
| 1064 AbstractType& interface = AbstractType::Handle(); | 1053 AbstractType& interface = AbstractType::Handle(); |
| 1054 Class& interface_class = Class::Handle(); |
| 1065 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { | 1055 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { |
| 1066 interface ^= super_interfaces.At(i); | 1056 interface ^= super_interfaces.At(i); |
| 1067 ResolveType(cls, interface, kFinalizeWellFormed); | 1057 ResolveType(cls, interface, kFinalizeWellFormed); |
| 1068 if (interface.IsTypeParameter()) { | 1058 if (interface.IsTypeParameter()) { |
| 1069 const Script& script = Script::Handle(cls.script()); | 1059 const Script& script = Script::Handle(cls.script()); |
| 1070 ReportError(script, cls.token_index(), | 1060 ReportError(script, cls.token_index(), |
| 1071 "type parameter '%s' cannot be used as interface", | 1061 "type parameter '%s' cannot be used as interface", |
| 1072 String::Handle(interface.Name()).ToCString()); | 1062 String::Handle(interface.Name()).ToCString()); |
| 1073 } | 1063 } |
| 1074 const Class& interface_class = Class::Handle(interface.type_class()); | 1064 interface_class = interface.type_class(); |
| 1075 if (!interface_class.is_interface()) { | 1065 if (!interface_class.is_interface()) { |
| 1076 const Script& script = Script::Handle(cls.script()); | 1066 const Script& script = Script::Handle(cls.script()); |
| 1077 ReportError(script, cls.token_index(), | 1067 ReportError(script, cls.token_index(), |
| 1078 "class '%s' is used where an interface is expected", | 1068 "class '%s' is used where an interface is expected", |
| 1079 String::Handle(interface_class.Name()).ToCString()); | 1069 String::Handle(interface_class.Name()).ToCString()); |
| 1080 } | 1070 } |
| 1081 // Verify that unless cls belongs to core lib, it cannot extend or implement | 1071 // Verify that unless cls belongs to core lib, it cannot extend or implement |
| 1082 // any of bool, num, int, double, String, Function, Dynamic. | 1072 // any of bool, num, int, double, String, Function, Dynamic. |
| 1083 // The exception is signature classes, which are compiler generated and | 1073 // The exception is signature classes, which are compiler generated and |
| 1084 // represent a function type, therefore implementing the Function interface. | 1074 // represent a function type, therefore implementing the Function interface. |
| 1085 if (!cls_belongs_to_core_lib) { | 1075 if (!cls_belongs_to_core_lib) { |
| 1086 if (interface.IsBoolInterface() || | 1076 if (interface.IsBoolInterface() || |
| 1087 interface.IsNumberInterface() || | 1077 interface.IsNumberInterface() || |
| 1088 interface.IsIntInterface() || | 1078 interface.IsIntInterface() || |
| 1089 interface.IsDoubleInterface() || | 1079 interface.IsDoubleInterface() || |
| 1090 interface.IsStringInterface() || | 1080 interface.IsStringInterface() || |
| 1091 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || | 1081 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || |
| 1092 interface.IsDynamicType()) { | 1082 interface.IsDynamicType()) { |
| 1093 const Script& script = Script::Handle(cls.script()); | 1083 const Script& script = Script::Handle(cls.script()); |
| 1094 ReportError(script, cls.token_index(), | 1084 ReportError(script, cls.token_index(), |
| 1095 "'%s' is not allowed to extend or implement '%s'", | 1085 "'%s' is not allowed to extend or implement '%s'", |
| 1096 String::Handle(cls.Name()).ToCString(), | 1086 String::Handle(cls.Name()).ToCString(), |
| 1097 String::Handle(interface_class.Name()).ToCString()); | 1087 String::Handle(interface_class.Name()).ToCString()); |
| 1098 } | 1088 } |
| 1099 } | 1089 } |
| 1100 // Now resolve the super interfaces. | 1090 // Now resolve the super interfaces. |
| 1101 ResolveInterfaces(interface_class, visited); | 1091 ResolveInterfaces(interface_class, visited); |
| 1102 } | 1092 } |
| 1103 visited->RemoveLast(); | 1093 visited.RemoveLast(); |
| 1104 } | 1094 } |
| 1105 | 1095 |
| 1106 | 1096 |
| 1107 // A class is marked as constant if it has one constant constructor. | 1097 // A class is marked as constant if it has one constant constructor. |
| 1108 // A constant class: | 1098 // A constant class: |
| 1109 // - may extend only const classes. | 1099 // - may extend only const classes. |
| 1110 // - has only const instance fields. | 1100 // - has only const instance fields. |
| 1111 // Note: we must check for cycles before checking for const properties. | 1101 // Note: we must check for cycles before checking for const properties. |
| 1112 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 1102 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
| 1113 ASSERT(cls.is_const()); | 1103 ASSERT(cls.is_const()); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 void ClassFinalizer::ReportError(const char* format, ...) { | 1210 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1221 va_list args; | 1211 va_list args; |
| 1222 va_start(args, format); | 1212 va_start(args, format); |
| 1223 const Error& error = Error::Handle( | 1213 const Error& error = Error::Handle( |
| 1224 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1214 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1225 va_end(args); | 1215 va_end(args); |
| 1226 ReportError(error); | 1216 ReportError(error); |
| 1227 } | 1217 } |
| 1228 | 1218 |
| 1229 } // namespace dart | 1219 } // namespace dart |
| OLD | NEW |