| 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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 // method) having the same name as an instance member in a super class. | 962 // method) having the same name as an instance member in a super class. |
| 963 | 963 |
| 964 // Resolve type of fields and check for conflicts in super classes. | 964 // Resolve type of fields and check for conflicts in super classes. |
| 965 Array& array = Array::Handle(cls.fields()); | 965 Array& array = Array::Handle(cls.fields()); |
| 966 Field& field = Field::Handle(); | 966 Field& field = Field::Handle(); |
| 967 AbstractType& type = AbstractType::Handle(); | 967 AbstractType& type = AbstractType::Handle(); |
| 968 String& name = String::Handle(); | 968 String& name = String::Handle(); |
| 969 Class& super_class = Class::Handle(); | 969 Class& super_class = Class::Handle(); |
| 970 intptr_t num_fields = array.Length(); | 970 intptr_t num_fields = array.Length(); |
| 971 for (intptr_t i = 0; i < num_fields; i++) { | 971 for (intptr_t i = 0; i < num_fields; i++) { |
| 972 field |= array.At(i); | 972 field ^= array.At(i); |
| 973 type = field.type(); | 973 type = field.type(); |
| 974 ResolveType(cls, type, kCanonicalize); | 974 ResolveType(cls, type, kCanonicalize); |
| 975 type = FinalizeType(cls, type, kCanonicalize); | 975 type = FinalizeType(cls, type, kCanonicalize); |
| 976 field.set_type(type); | 976 field.set_type(type); |
| 977 name = field.name(); | 977 name = field.name(); |
| 978 if (field.is_static()) { | 978 if (field.is_static()) { |
| 979 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 979 super_class = FindSuperOwnerOfInstanceMember(cls, name); |
| 980 if (!super_class.IsNull()) { | 980 if (!super_class.IsNull()) { |
| 981 const String& class_name = String::Handle(cls.Name()); | 981 const String& class_name = String::Handle(cls.Name()); |
| 982 const String& super_class_name = String::Handle(super_class.Name()); | 982 const String& super_class_name = String::Handle(super_class.Name()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 super_class = super_class.SuperClass(); | 1018 super_class = super_class.SuperClass(); |
| 1019 } | 1019 } |
| 1020 // Resolve function signatures and check for conflicts in super classes and | 1020 // Resolve function signatures and check for conflicts in super classes and |
| 1021 // interfaces. | 1021 // interfaces. |
| 1022 array = cls.functions(); | 1022 array = cls.functions(); |
| 1023 Function& function = Function::Handle(); | 1023 Function& function = Function::Handle(); |
| 1024 Function& overridden_function = Function::Handle(); | 1024 Function& overridden_function = Function::Handle(); |
| 1025 intptr_t num_functions = array.Length(); | 1025 intptr_t num_functions = array.Length(); |
| 1026 String& function_name = String::Handle(); | 1026 String& function_name = String::Handle(); |
| 1027 for (intptr_t i = 0; i < num_functions; i++) { | 1027 for (intptr_t i = 0; i < num_functions; i++) { |
| 1028 function |= array.At(i); | 1028 function ^= array.At(i); |
| 1029 ResolveAndFinalizeSignature(cls, function); | 1029 ResolveAndFinalizeSignature(cls, function); |
| 1030 function_name = function.name(); | 1030 function_name = function.name(); |
| 1031 if (function.is_static()) { | 1031 if (function.is_static()) { |
| 1032 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 1032 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); |
| 1033 if (!super_class.IsNull()) { | 1033 if (!super_class.IsNull()) { |
| 1034 const String& class_name = String::Handle(cls.Name()); | 1034 const String& class_name = String::Handle(cls.Name()); |
| 1035 const String& super_class_name = String::Handle(super_class.Name()); | 1035 const String& super_class_name = String::Handle(super_class.Name()); |
| 1036 const Script& script = Script::Handle(cls.script()); | 1036 const Script& script = Script::Handle(cls.script()); |
| 1037 ReportError(script, function.token_pos(), | 1037 ReportError(script, function.token_pos(), |
| 1038 "static function '%s' of class '%s' conflicts with " | 1038 "static function '%s' of class '%s' conflicts with " |
| 1039 "instance member '%s' of super class '%s'", | 1039 "instance member '%s' of super class '%s'", |
| 1040 function_name.ToCString(), | 1040 function_name.ToCString(), |
| 1041 class_name.ToCString(), | 1041 class_name.ToCString(), |
| 1042 function_name.ToCString(), | 1042 function_name.ToCString(), |
| 1043 super_class_name.ToCString()); | 1043 super_class_name.ToCString()); |
| 1044 } | 1044 } |
| 1045 if (function.IsRedirectingFactory()) { | 1045 if (function.IsRedirectingFactory()) { |
| 1046 const GrowableObjectArray& redirecting_factories = | 1046 const GrowableObjectArray& redirecting_factories = |
| 1047 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1047 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1048 ResolveRedirectingFactoryTarget(cls, function, redirecting_factories); | 1048 ResolveRedirectingFactoryTarget(cls, function, redirecting_factories); |
| 1049 } | 1049 } |
| 1050 } else { | 1050 } else { |
| 1051 for (int i = 0; i < interfaces.Length(); i++) { | 1051 for (int i = 0; i < interfaces.Length(); i++) { |
| 1052 super_class |= interfaces.At(i); | 1052 super_class ^= interfaces.At(i); |
| 1053 overridden_function = super_class.LookupDynamicFunction(function_name); | 1053 overridden_function = super_class.LookupDynamicFunction(function_name); |
| 1054 if (!overridden_function.IsNull() && | 1054 if (!overridden_function.IsNull() && |
| 1055 !function.HasCompatibleParametersWith(overridden_function)) { | 1055 !function.HasCompatibleParametersWith(overridden_function)) { |
| 1056 // Function types are purposely not checked for subtyping. | 1056 // Function types are purposely not checked for subtyping. |
| 1057 const String& class_name = String::Handle(cls.Name()); | 1057 const String& class_name = String::Handle(cls.Name()); |
| 1058 const String& super_class_name = String::Handle(super_class.Name()); | 1058 const String& super_class_name = String::Handle(super_class.Name()); |
| 1059 const Script& script = Script::Handle(cls.script()); | 1059 const Script& script = Script::Handle(cls.script()); |
| 1060 ReportError(script, function.token_pos(), | 1060 ReportError(script, function.token_pos(), |
| 1061 "class '%s' overrides function '%s' of super class '%s' " | 1061 "class '%s' overrides function '%s' of super class '%s' " |
| 1062 "with incompatible parameters", | 1062 "with incompatible parameters", |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 if (!super.IsNull() && !super.is_const()) { | 1415 if (!super.IsNull() && !super.is_const()) { |
| 1416 String& name = String::Handle(super.Name()); | 1416 String& name = String::Handle(super.Name()); |
| 1417 const Script& script = Script::Handle(cls.script()); | 1417 const Script& script = Script::Handle(cls.script()); |
| 1418 ReportError(script, cls.token_pos(), | 1418 ReportError(script, cls.token_pos(), |
| 1419 "superclass '%s' must be const", name.ToCString()); | 1419 "superclass '%s' must be const", name.ToCString()); |
| 1420 } | 1420 } |
| 1421 const Array& fields_array = Array::Handle(cls.fields()); | 1421 const Array& fields_array = Array::Handle(cls.fields()); |
| 1422 intptr_t len = fields_array.Length(); | 1422 intptr_t len = fields_array.Length(); |
| 1423 Field& field = Field::Handle(); | 1423 Field& field = Field::Handle(); |
| 1424 for (intptr_t i = 0; i < len; i++) { | 1424 for (intptr_t i = 0; i < len; i++) { |
| 1425 field |= fields_array.At(i); | 1425 field ^= fields_array.At(i); |
| 1426 if (!field.is_static() && !field.is_final()) { | 1426 if (!field.is_static() && !field.is_final()) { |
| 1427 const String& class_name = String::Handle(cls.Name()); | 1427 const String& class_name = String::Handle(cls.Name()); |
| 1428 const String& field_name = String::Handle(field.name()); | 1428 const String& field_name = String::Handle(field.name()); |
| 1429 const Script& script = Script::Handle(cls.script()); | 1429 const Script& script = Script::Handle(cls.script()); |
| 1430 ReportError(script, field.token_pos(), | 1430 ReportError(script, field.token_pos(), |
| 1431 "const class '%s' has non-final field '%s'", | 1431 "const class '%s' has non-final field '%s'", |
| 1432 class_name.ToCString(), field_name.ToCString()); | 1432 class_name.ToCString(), field_name.ToCString()); |
| 1433 } | 1433 } |
| 1434 } | 1434 } |
| 1435 } | 1435 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1462 for (intptr_t i = 0; i < len; i++) { | 1462 for (intptr_t i = 0; i < len; i++) { |
| 1463 interface ^= interfaces_array.At(i); | 1463 interface ^= interfaces_array.At(i); |
| 1464 OS::Print(" %s ", interface.ToCString()); | 1464 OS::Print(" %s ", interface.ToCString()); |
| 1465 } | 1465 } |
| 1466 } | 1466 } |
| 1467 OS::Print("\n"); | 1467 OS::Print("\n"); |
| 1468 const Array& functions_array = Array::Handle(cls.functions()); | 1468 const Array& functions_array = Array::Handle(cls.functions()); |
| 1469 Function& function = Function::Handle(); | 1469 Function& function = Function::Handle(); |
| 1470 intptr_t len = functions_array.Length(); | 1470 intptr_t len = functions_array.Length(); |
| 1471 for (intptr_t i = 0; i < len; i++) { | 1471 for (intptr_t i = 0; i < len; i++) { |
| 1472 function |= functions_array.At(i); | 1472 function ^= functions_array.At(i); |
| 1473 OS::Print(" %s\n", function.ToCString()); | 1473 OS::Print(" %s\n", function.ToCString()); |
| 1474 } | 1474 } |
| 1475 const Array& fields_array = Array::Handle(cls.fields()); | 1475 const Array& fields_array = Array::Handle(cls.fields()); |
| 1476 Field& field = Field::Handle(); | 1476 Field& field = Field::Handle(); |
| 1477 len = fields_array.Length(); | 1477 len = fields_array.Length(); |
| 1478 for (intptr_t i = 0; i < len; i++) { | 1478 for (intptr_t i = 0; i < len; i++) { |
| 1479 field |= fields_array.At(i); | 1479 field ^= fields_array.At(i); |
| 1480 OS::Print(" %s\n", field.ToCString()); | 1480 OS::Print(" %s\n", field.ToCString()); |
| 1481 } | 1481 } |
| 1482 } | 1482 } |
| 1483 | 1483 |
| 1484 // Either report an error or mark the type as malformed. | 1484 // Either report an error or mark the type as malformed. |
| 1485 void ClassFinalizer::ReportMalformedType(const Error& prev_error, | 1485 void ClassFinalizer::ReportMalformedType(const Error& prev_error, |
| 1486 const Class& cls, | 1486 const Class& cls, |
| 1487 const Type& type, | 1487 const Type& type, |
| 1488 FinalizationKind finalization, | 1488 FinalizationKind finalization, |
| 1489 const char* format, | 1489 const char* format, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 void ClassFinalizer::ReportError(const char* format, ...) { | 1582 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1583 va_list args; | 1583 va_list args; |
| 1584 va_start(args, format); | 1584 va_start(args, format); |
| 1585 const Error& error = Error::Handle( | 1585 const Error& error = Error::Handle( |
| 1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1587 va_end(args); | 1587 va_end(args); |
| 1588 ReportError(error); | 1588 ReportError(error); |
| 1589 } | 1589 } |
| 1590 | 1590 |
| 1591 } // namespace dart | 1591 } // namespace dart |
| OLD | NEW |