| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 Class& cls = Class::Handle(); | 47 Class& cls = Class::Handle(); |
| 48 Array& array = Array::Handle(); | 48 Array& array = Array::Handle(); |
| 49 Function& function = Function::Handle(); | 49 Function& function = Function::Handle(); |
| 50 for (intptr_t i = 0; i < added_subclasses_to_cids.length(); i++) { | 50 for (intptr_t i = 0; i < added_subclasses_to_cids.length(); i++) { |
| 51 intptr_t cid = added_subclasses_to_cids[i]; | 51 intptr_t cid = added_subclasses_to_cids[i]; |
| 52 cls = class_table.At(cid); | 52 cls = class_table.At(cid); |
| 53 ASSERT(!cls.IsNull()); | 53 ASSERT(!cls.IsNull()); |
| 54 array = cls.functions(); | 54 array = cls.functions(); |
| 55 intptr_t num_functions = array.IsNull() ? 0 : array.Length(); | 55 intptr_t num_functions = array.IsNull() ? 0 : array.Length(); |
| 56 for (intptr_t f = 0; f < num_functions; f++) { | 56 for (intptr_t f = 0; f < num_functions; f++) { |
| 57 function ^= array.At(f); | 57 function |= array.At(f); |
| 58 ASSERT(!function.IsNull()); | 58 ASSERT(!function.IsNull()); |
| 59 if (function.HasOptimizedCode()) { | 59 if (function.HasOptimizedCode()) { |
| 60 function.SwitchToUnoptimizedCode(); | 60 function.SwitchToUnoptimizedCode(); |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 #endif | 64 #endif |
| 65 } | 65 } |
| 66 | 66 |
| 67 | 67 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 87 | 87 |
| 88 | 88 |
| 89 // Use array instead of set since we expect very few subclassed classes | 89 // Use array instead of set since we expect very few subclassed classes |
| 90 // to occur. | 90 // to occur. |
| 91 static void CollectFinalizedSuperClasses( | 91 static void CollectFinalizedSuperClasses( |
| 92 const GrowableObjectArray& pending_classes, | 92 const GrowableObjectArray& pending_classes, |
| 93 GrowableArray<intptr_t>* finalized_super_classes) { | 93 GrowableArray<intptr_t>* finalized_super_classes) { |
| 94 Class& cls = Class::Handle(); | 94 Class& cls = Class::Handle(); |
| 95 Type& super_type = Type::Handle(); | 95 Type& super_type = Type::Handle(); |
| 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { | 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { |
| 97 cls ^= pending_classes.At(i); | 97 cls |= pending_classes.At(i); |
| 98 ASSERT(!cls.is_finalized()); | 98 ASSERT(!cls.is_finalized()); |
| 99 super_type ^= cls.super_type(); | 99 super_type ^= cls.super_type(); |
| 100 if (!super_type.IsNull()) { | 100 if (!super_type.IsNull()) { |
| 101 if (super_type.HasResolvedTypeClass() && | 101 if (super_type.HasResolvedTypeClass() && |
| 102 Class::Handle(super_type.type_class()).is_finalized()) { | 102 Class::Handle(super_type.type_class()).is_finalized()) { |
| 103 AddSuperType(super_type, finalized_super_classes); | 103 AddSuperType(super_type, finalized_super_classes); |
| 104 } | 104 } |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 } | 107 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 131 if (setjmp(*jump.Set()) == 0) { | 131 if (setjmp(*jump.Set()) == 0) { |
| 132 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); | 132 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
| 133 class_array = object_store->pending_classes(); | 133 class_array = object_store->pending_classes(); |
| 134 ASSERT(!class_array.IsNull()); | 134 ASSERT(!class_array.IsNull()); |
| 135 // Collect superclasses that were already finalized before this run of | 135 // Collect superclasses that were already finalized before this run of |
| 136 // finalization. | 136 // finalization. |
| 137 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); | 137 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); |
| 138 Class& cls = Class::Handle(); | 138 Class& cls = Class::Handle(); |
| 139 // First resolve all superclasses. | 139 // First resolve all superclasses. |
| 140 for (intptr_t i = 0; i < class_array.Length(); i++) { | 140 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 141 cls ^= class_array.At(i); | 141 cls |= class_array.At(i); |
| 142 if (FLAG_trace_class_finalization) { | 142 if (FLAG_trace_class_finalization) { |
| 143 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); | 143 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); |
| 144 } | 144 } |
| 145 GrowableArray<intptr_t> visited_interfaces; | 145 GrowableArray<intptr_t> visited_interfaces; |
| 146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
| 147 } | 147 } |
| 148 // Finalize all classes. | 148 // Finalize all classes. |
| 149 for (intptr_t i = 0; i < class_array.Length(); i++) { | 149 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 150 cls ^= class_array.At(i); | 150 cls |= class_array.At(i); |
| 151 FinalizeClass(cls); | 151 FinalizeClass(cls); |
| 152 } | 152 } |
| 153 if (FLAG_print_classes) { | 153 if (FLAG_print_classes) { |
| 154 for (intptr_t i = 0; i < class_array.Length(); i++) { | 154 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 155 cls ^= class_array.At(i); | 155 cls |= class_array.At(i); |
| 156 PrintClassInformation(cls); | 156 PrintClassInformation(cls); |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 // Clear pending classes array. | 159 // Clear pending classes array. |
| 160 class_array = GrowableObjectArray::New(); | 160 class_array = GrowableObjectArray::New(); |
| 161 object_store->set_pending_classes(class_array); | 161 object_store->set_pending_classes(class_array); |
| 162 } else { | 162 } else { |
| 163 retval = false; | 163 retval = false; |
| 164 } | 164 } |
| 165 isolate->set_long_jump_base(base); | 165 isolate->set_long_jump_base(base); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 ASSERT(ExternalFloat64Array::InstanceSize() == cls.instance_size()); | 263 ASSERT(ExternalFloat64Array::InstanceSize() == cls.instance_size()); |
| 264 cls = object_store->weak_property_class(); | 264 cls = object_store->weak_property_class(); |
| 265 ASSERT(WeakProperty::InstanceSize() == cls.instance_size()); | 265 ASSERT(WeakProperty::InstanceSize() == cls.instance_size()); |
| 266 #endif // defined(DEBUG) | 266 #endif // defined(DEBUG) |
| 267 | 267 |
| 268 // Remember the currently pending classes. | 268 // Remember the currently pending classes. |
| 269 const GrowableObjectArray& class_array = | 269 const GrowableObjectArray& class_array = |
| 270 GrowableObjectArray::Handle(object_store->pending_classes()); | 270 GrowableObjectArray::Handle(object_store->pending_classes()); |
| 271 for (intptr_t i = 0; i < class_array.Length(); i++) { | 271 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 272 // TODO(iposva): Add real checks. | 272 // TODO(iposva): Add real checks. |
| 273 cls ^= class_array.At(i); | 273 cls |= class_array.At(i); |
| 274 if (cls.is_finalized() || cls.is_prefinalized()) { | 274 if (cls.is_finalized() || cls.is_prefinalized()) { |
| 275 // Pre-finalized bootstrap classes must not define any fields. | 275 // Pre-finalized bootstrap classes must not define any fields. |
| 276 ASSERT(!cls.HasInstanceFields()); | 276 ASSERT(!cls.HasInstanceFields()); |
| 277 } | 277 } |
| 278 } | 278 } |
| 279 | 279 |
| 280 // Finalize classes that aren't pre-finalized by Object::Init(). | 280 // Finalize classes that aren't pre-finalized by Object::Init(). |
| 281 if (!FinalizePendingClasses()) { | 281 if (!FinalizePendingClasses()) { |
| 282 // TODO(srdjan): Exit like a real VM instead. | 282 // TODO(srdjan): Exit like a real VM instead. |
| 283 const Error& err = Error::Handle(object_store->sticky_error()); | 283 const Error& err = Error::Handle(object_store->sticky_error()); |
| (...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 // method) having the same name as an instance member in a super class. | 960 // method) having the same name as an instance member in a super class. |
| 961 | 961 |
| 962 // Resolve type of fields and check for conflicts in super classes. | 962 // Resolve type of fields and check for conflicts in super classes. |
| 963 Array& array = Array::Handle(cls.fields()); | 963 Array& array = Array::Handle(cls.fields()); |
| 964 Field& field = Field::Handle(); | 964 Field& field = Field::Handle(); |
| 965 AbstractType& type = AbstractType::Handle(); | 965 AbstractType& type = AbstractType::Handle(); |
| 966 String& name = String::Handle(); | 966 String& name = String::Handle(); |
| 967 Class& super_class = Class::Handle(); | 967 Class& super_class = Class::Handle(); |
| 968 intptr_t num_fields = array.Length(); | 968 intptr_t num_fields = array.Length(); |
| 969 for (intptr_t i = 0; i < num_fields; i++) { | 969 for (intptr_t i = 0; i < num_fields; i++) { |
| 970 field ^= array.At(i); | 970 field |= array.At(i); |
| 971 type = field.type(); | 971 type = field.type(); |
| 972 ResolveType(cls, type, kCanonicalize); | 972 ResolveType(cls, type, kCanonicalize); |
| 973 type = FinalizeType(cls, type, kCanonicalize); | 973 type = FinalizeType(cls, type, kCanonicalize); |
| 974 field.set_type(type); | 974 field.set_type(type); |
| 975 name = field.name(); | 975 name = field.name(); |
| 976 if (field.is_static()) { | 976 if (field.is_static()) { |
| 977 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 977 super_class = FindSuperOwnerOfInstanceMember(cls, name); |
| 978 if (!super_class.IsNull()) { | 978 if (!super_class.IsNull()) { |
| 979 const String& class_name = String::Handle(cls.Name()); | 979 const String& class_name = String::Handle(cls.Name()); |
| 980 const String& super_class_name = String::Handle(super_class.Name()); | 980 const String& super_class_name = String::Handle(super_class.Name()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 super_class = super_class.SuperClass(); | 1016 super_class = super_class.SuperClass(); |
| 1017 } | 1017 } |
| 1018 // Resolve function signatures and check for conflicts in super classes and | 1018 // Resolve function signatures and check for conflicts in super classes and |
| 1019 // interfaces. | 1019 // interfaces. |
| 1020 array = cls.functions(); | 1020 array = cls.functions(); |
| 1021 Function& function = Function::Handle(); | 1021 Function& function = Function::Handle(); |
| 1022 Function& overridden_function = Function::Handle(); | 1022 Function& overridden_function = Function::Handle(); |
| 1023 intptr_t num_functions = array.Length(); | 1023 intptr_t num_functions = array.Length(); |
| 1024 String& function_name = String::Handle(); | 1024 String& function_name = String::Handle(); |
| 1025 for (intptr_t i = 0; i < num_functions; i++) { | 1025 for (intptr_t i = 0; i < num_functions; i++) { |
| 1026 function ^= array.At(i); | 1026 function |= array.At(i); |
| 1027 ResolveAndFinalizeSignature(cls, function); | 1027 ResolveAndFinalizeSignature(cls, function); |
| 1028 function_name = function.name(); | 1028 function_name = function.name(); |
| 1029 if (function.is_static()) { | 1029 if (function.is_static()) { |
| 1030 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 1030 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); |
| 1031 if (!super_class.IsNull()) { | 1031 if (!super_class.IsNull()) { |
| 1032 const String& class_name = String::Handle(cls.Name()); | 1032 const String& class_name = String::Handle(cls.Name()); |
| 1033 const String& super_class_name = String::Handle(super_class.Name()); | 1033 const String& super_class_name = String::Handle(super_class.Name()); |
| 1034 const Script& script = Script::Handle(cls.script()); | 1034 const Script& script = Script::Handle(cls.script()); |
| 1035 ReportError(script, function.token_pos(), | 1035 ReportError(script, function.token_pos(), |
| 1036 "static function '%s' of class '%s' conflicts with " | 1036 "static function '%s' of class '%s' conflicts with " |
| 1037 "instance member '%s' of super class '%s'", | 1037 "instance member '%s' of super class '%s'", |
| 1038 function_name.ToCString(), | 1038 function_name.ToCString(), |
| 1039 class_name.ToCString(), | 1039 class_name.ToCString(), |
| 1040 function_name.ToCString(), | 1040 function_name.ToCString(), |
| 1041 super_class_name.ToCString()); | 1041 super_class_name.ToCString()); |
| 1042 } | 1042 } |
| 1043 if (function.IsRedirectingFactory()) { | 1043 if (function.IsRedirectingFactory()) { |
| 1044 const GrowableObjectArray& redirecting_factories = | 1044 const GrowableObjectArray& redirecting_factories = |
| 1045 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1045 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1046 ResolveRedirectingFactoryTarget(cls, function, redirecting_factories); | 1046 ResolveRedirectingFactoryTarget(cls, function, redirecting_factories); |
| 1047 } | 1047 } |
| 1048 } else { | 1048 } else { |
| 1049 for (int i = 0; i < interfaces.Length(); i++) { | 1049 for (int i = 0; i < interfaces.Length(); i++) { |
| 1050 super_class ^= interfaces.At(i); | 1050 super_class |= interfaces.At(i); |
| 1051 overridden_function = super_class.LookupDynamicFunction(function_name); | 1051 overridden_function = super_class.LookupDynamicFunction(function_name); |
| 1052 if (!overridden_function.IsNull() && | 1052 if (!overridden_function.IsNull() && |
| 1053 !function.HasCompatibleParametersWith(overridden_function)) { | 1053 !function.HasCompatibleParametersWith(overridden_function)) { |
| 1054 // Function types are purposely not checked for subtyping. | 1054 // Function types are purposely not checked for subtyping. |
| 1055 const String& class_name = String::Handle(cls.Name()); | 1055 const String& class_name = String::Handle(cls.Name()); |
| 1056 const String& super_class_name = String::Handle(super_class.Name()); | 1056 const String& super_class_name = String::Handle(super_class.Name()); |
| 1057 const Script& script = Script::Handle(cls.script()); | 1057 const Script& script = Script::Handle(cls.script()); |
| 1058 ReportError(script, function.token_pos(), | 1058 ReportError(script, function.token_pos(), |
| 1059 "class '%s' overrides function '%s' of super class '%s' " | 1059 "class '%s' overrides function '%s' of super class '%s' " |
| 1060 "with incompatible parameters", | 1060 "with incompatible parameters", |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 if (!super.IsNull() && !super.is_const()) { | 1413 if (!super.IsNull() && !super.is_const()) { |
| 1414 String& name = String::Handle(super.Name()); | 1414 String& name = String::Handle(super.Name()); |
| 1415 const Script& script = Script::Handle(cls.script()); | 1415 const Script& script = Script::Handle(cls.script()); |
| 1416 ReportError(script, cls.token_pos(), | 1416 ReportError(script, cls.token_pos(), |
| 1417 "superclass '%s' must be const", name.ToCString()); | 1417 "superclass '%s' must be const", name.ToCString()); |
| 1418 } | 1418 } |
| 1419 const Array& fields_array = Array::Handle(cls.fields()); | 1419 const Array& fields_array = Array::Handle(cls.fields()); |
| 1420 intptr_t len = fields_array.Length(); | 1420 intptr_t len = fields_array.Length(); |
| 1421 Field& field = Field::Handle(); | 1421 Field& field = Field::Handle(); |
| 1422 for (intptr_t i = 0; i < len; i++) { | 1422 for (intptr_t i = 0; i < len; i++) { |
| 1423 field ^= fields_array.At(i); | 1423 field |= fields_array.At(i); |
| 1424 if (!field.is_static() && !field.is_final()) { | 1424 if (!field.is_static() && !field.is_final()) { |
| 1425 const String& class_name = String::Handle(cls.Name()); | 1425 const String& class_name = String::Handle(cls.Name()); |
| 1426 const String& field_name = String::Handle(field.name()); | 1426 const String& field_name = String::Handle(field.name()); |
| 1427 const Script& script = Script::Handle(cls.script()); | 1427 const Script& script = Script::Handle(cls.script()); |
| 1428 ReportError(script, field.token_pos(), | 1428 ReportError(script, field.token_pos(), |
| 1429 "const class '%s' has non-final field '%s'", | 1429 "const class '%s' has non-final field '%s'", |
| 1430 class_name.ToCString(), field_name.ToCString()); | 1430 class_name.ToCString(), field_name.ToCString()); |
| 1431 } | 1431 } |
| 1432 } | 1432 } |
| 1433 } | 1433 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1460 for (intptr_t i = 0; i < len; i++) { | 1460 for (intptr_t i = 0; i < len; i++) { |
| 1461 interface ^= interfaces_array.At(i); | 1461 interface ^= interfaces_array.At(i); |
| 1462 OS::Print(" %s ", interface.ToCString()); | 1462 OS::Print(" %s ", interface.ToCString()); |
| 1463 } | 1463 } |
| 1464 } | 1464 } |
| 1465 OS::Print("\n"); | 1465 OS::Print("\n"); |
| 1466 const Array& functions_array = Array::Handle(cls.functions()); | 1466 const Array& functions_array = Array::Handle(cls.functions()); |
| 1467 Function& function = Function::Handle(); | 1467 Function& function = Function::Handle(); |
| 1468 intptr_t len = functions_array.Length(); | 1468 intptr_t len = functions_array.Length(); |
| 1469 for (intptr_t i = 0; i < len; i++) { | 1469 for (intptr_t i = 0; i < len; i++) { |
| 1470 function ^= functions_array.At(i); | 1470 function |= functions_array.At(i); |
| 1471 OS::Print(" %s\n", function.ToCString()); | 1471 OS::Print(" %s\n", function.ToCString()); |
| 1472 } | 1472 } |
| 1473 const Array& fields_array = Array::Handle(cls.fields()); | 1473 const Array& fields_array = Array::Handle(cls.fields()); |
| 1474 Field& field = Field::Handle(); | 1474 Field& field = Field::Handle(); |
| 1475 len = fields_array.Length(); | 1475 len = fields_array.Length(); |
| 1476 for (intptr_t i = 0; i < len; i++) { | 1476 for (intptr_t i = 0; i < len; i++) { |
| 1477 field ^= fields_array.At(i); | 1477 field |= fields_array.At(i); |
| 1478 OS::Print(" %s\n", field.ToCString()); | 1478 OS::Print(" %s\n", field.ToCString()); |
| 1479 } | 1479 } |
| 1480 } | 1480 } |
| 1481 | 1481 |
| 1482 // Either report an error or mark the type as malformed. | 1482 // Either report an error or mark the type as malformed. |
| 1483 void ClassFinalizer::ReportMalformedType(const Error& prev_error, | 1483 void ClassFinalizer::ReportMalformedType(const Error& prev_error, |
| 1484 const Class& cls, | 1484 const Class& cls, |
| 1485 const Type& type, | 1485 const Type& type, |
| 1486 FinalizationKind finalization, | 1486 FinalizationKind finalization, |
| 1487 const char* format, | 1487 const char* format, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1580 void ClassFinalizer::ReportError(const char* format, ...) { | 1580 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1581 va_list args; | 1581 va_list args; |
| 1582 va_start(args, format); | 1582 va_start(args, format); |
| 1583 const Error& error = Error::Handle( | 1583 const Error& error = Error::Handle( |
| 1584 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1584 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1585 va_end(args); | 1585 va_end(args); |
| 1586 ReportError(error); | 1586 ReportError(error); |
| 1587 } | 1587 } |
| 1588 | 1588 |
| 1589 } // namespace dart | 1589 } // namespace dart |
| OLD | NEW |