| 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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 cls ^= class_array.At(i); | 140 cls ^= class_array.At(i); |
| 141 if (FLAG_trace_class_finalization) { | 141 if (FLAG_trace_class_finalization) { |
| 142 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); | 142 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); |
| 143 } | 143 } |
| 144 GrowableArray<intptr_t> visited_interfaces; | 144 GrowableArray<intptr_t> visited_interfaces; |
| 145 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 145 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
| 146 } | 146 } |
| 147 // Finalize all classes. | 147 // Finalize all classes. |
| 148 for (intptr_t i = 0; i < class_array.Length(); i++) { | 148 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 149 cls ^= class_array.At(i); | 149 cls ^= class_array.At(i); |
| 150 FinalizeClass(cls); | 150 FinalizeTypesInClass(cls); |
| 151 } | 151 } |
| 152 if (FLAG_print_classes) { | 152 if (FLAG_print_classes) { |
| 153 for (intptr_t i = 0; i < class_array.Length(); i++) { | 153 for (intptr_t i = 0; i < class_array.Length(); i++) { |
| 154 cls ^= class_array.At(i); | 154 cls ^= class_array.At(i); |
| 155 PrintClassInformation(cls); | 155 PrintClassInformation(cls); |
| 156 } | 156 } |
| 157 } | 157 } |
| 158 // Clear pending classes array. | 158 // Clear pending classes array. |
| 159 class_array = GrowableObjectArray::New(); | 159 class_array = GrowableObjectArray::New(); |
| 160 object_store->set_pending_classes(class_array); | 160 object_store->set_pending_classes(class_array); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 // Input: C<String, double> expressed as | 497 // Input: C<String, double> expressed as |
| 498 // cls = C, arguments = [null, null, String, double], | 498 // cls = C, arguments = [null, null, String, double], |
| 499 // i.e. cls_args = [String, double], offset = 2, length = 2. | 499 // i.e. cls_args = [String, double], offset = 2, length = 2. |
| 500 // Output: arguments = [int, double, String, double] | 500 // Output: arguments = [int, double, String, double] |
| 501 void ClassFinalizer::FinalizeTypeArguments( | 501 void ClassFinalizer::FinalizeTypeArguments( |
| 502 const Class& cls, | 502 const Class& cls, |
| 503 const AbstractTypeArguments& arguments, | 503 const AbstractTypeArguments& arguments, |
| 504 FinalizationKind finalization, | 504 FinalizationKind finalization, |
| 505 Error* bound_error) { | 505 Error* bound_error) { |
| 506 ASSERT(arguments.Length() >= cls.NumTypeArguments()); | 506 ASSERT(arguments.Length() >= cls.NumTypeArguments()); |
| 507 if (!cls.is_finalized()) { | 507 if (!cls.is_type_finalized()) { |
| 508 FinalizeTypeParameters(cls); | 508 FinalizeTypeParameters(cls); |
| 509 ResolveUpperBounds(cls); | 509 ResolveUpperBounds(cls); |
| 510 } | 510 } |
| 511 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 511 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 512 if (!super_type.IsNull()) { | 512 if (!super_type.IsNull()) { |
| 513 const Class& super_class = Class::Handle(super_type.type_class()); | 513 const Class& super_class = Class::Handle(super_type.type_class()); |
| 514 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); | 514 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); |
| 515 if (super_type.IsBeingFinalized()) { | 515 if (super_type.IsBeingFinalized()) { |
| 516 // This type references itself via its type arguments. This is legal, but | 516 // This type references itself via its type arguments. This is legal, but |
| 517 // we must avoid endless recursion. We therefore map the innermost | 517 // we must avoid endless recursion. We therefore map the innermost |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 | 566 |
| 567 // Check the type argument vector 'arguments' against the corresponding bounds | 567 // Check the type argument vector 'arguments' against the corresponding bounds |
| 568 // of the type parameters of class 'cls' and, recursively, of its superclasses. | 568 // of the type parameters of class 'cls' and, recursively, of its superclasses. |
| 569 // Replace a type argument that cannot be checked at compile time by a | 569 // Replace a type argument that cannot be checked at compile time by a |
| 570 // BoundedType, thereby postponing the bound check to run time. | 570 // BoundedType, thereby postponing the bound check to run time. |
| 571 // Return a bound error if a type argument is not within bound at compile time. | 571 // Return a bound error if a type argument is not within bound at compile time. |
| 572 void ClassFinalizer::CheckTypeArgumentBounds( | 572 void ClassFinalizer::CheckTypeArgumentBounds( |
| 573 const Class& cls, | 573 const Class& cls, |
| 574 const AbstractTypeArguments& arguments, | 574 const AbstractTypeArguments& arguments, |
| 575 Error* bound_error) { | 575 Error* bound_error) { |
| 576 if (!cls.is_finalized()) { | 576 if (!cls.is_type_finalized()) { |
| 577 FinalizeUpperBounds(cls); | 577 FinalizeUpperBounds(cls); |
| 578 } | 578 } |
| 579 // Note that when finalizing a type, we need to verify the bounds in both | 579 // Note that when finalizing a type, we need to verify the bounds in both |
| 580 // production mode and checked mode, because the finalized type may be written | 580 // production mode and checked mode, because the finalized type may be written |
| 581 // to a snapshot. It would be wrong to ignore bounds when generating the | 581 // to a snapshot. It would be wrong to ignore bounds when generating the |
| 582 // snapshot in production mode and then use the unchecked type in checked mode | 582 // snapshot in production mode and then use the unchecked type in checked mode |
| 583 // after reading it from the snapshot. | 583 // after reading it from the snapshot. |
| 584 // However, we do not immediately report a bound error, which would be wrong | 584 // However, we do not immediately report a bound error, which would be wrong |
| 585 // in production mode, but simply postpone the bound checking to runtime. | 585 // in production mode, but simply postpone the bound checking to runtime. |
| 586 const intptr_t num_type_params = cls.NumTypeParameters(); | 586 const intptr_t num_type_params = cls.NumTypeParameters(); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 } else { | 676 } else { |
| 677 return type.Canonicalize(); | 677 return type.Canonicalize(); |
| 678 } | 678 } |
| 679 } | 679 } |
| 680 return type.raw(); | 680 return type.raw(); |
| 681 } | 681 } |
| 682 ASSERT(type.IsResolved()); | 682 ASSERT(type.IsResolved()); |
| 683 ASSERT(finalization >= kFinalize); | 683 ASSERT(finalization >= kFinalize); |
| 684 | 684 |
| 685 if (FLAG_trace_type_finalization) { | 685 if (FLAG_trace_type_finalization) { |
| 686 OS::Print("Finalize type '%s'\n", String::Handle(type.Name()).ToCString()); | 686 OS::Print("Finalize type '%s' for class %s\n", |
| 687 String::Handle(type.Name()).ToCString(), |
| 688 cls.ToCString()); |
| 687 } | 689 } |
| 688 | 690 |
| 689 if (type.IsTypeParameter()) { | 691 if (type.IsTypeParameter()) { |
| 690 const TypeParameter& type_parameter = TypeParameter::Cast(type); | 692 const TypeParameter& type_parameter = TypeParameter::Cast(type); |
| 691 const Class& parameterized_class = | 693 const Class& parameterized_class = |
| 692 Class::Handle(type_parameter.parameterized_class()); | 694 Class::Handle(type_parameter.parameterized_class()); |
| 693 ASSERT(!parameterized_class.IsNull()); | 695 ASSERT(!parameterized_class.IsNull()); |
| 694 // The index must reflect the position of this type parameter in the type | 696 // The index must reflect the position of this type parameter in the type |
| 695 // arguments vector of its parameterized class. The offset to add is the | 697 // arguments vector of its parameterized class. The offset to add is the |
| 696 // number of type arguments in the super type, which is equal to the | 698 // number of type arguments in the super type, which is equal to the |
| (...skipping 22 matching lines...) Expand all Loading... |
| 719 | 721 |
| 720 // Mark type as being finalized in order to detect illegal self reference. | 722 // Mark type as being finalized in order to detect illegal self reference. |
| 721 parameterized_type.set_is_being_finalized(); | 723 parameterized_type.set_is_being_finalized(); |
| 722 | 724 |
| 723 // The type class does not need to be finalized in order to finalize the type, | 725 // The type class does not need to be finalized in order to finalize the type, |
| 724 // however, it must at least be resolved (this was done as part of resolving | 726 // however, it must at least be resolved (this was done as part of resolving |
| 725 // the type itself, a precondition to calling FinalizeType). | 727 // the type itself, a precondition to calling FinalizeType). |
| 726 // Also, the interfaces of the type class must be resolved and the type | 728 // Also, the interfaces of the type class must be resolved and the type |
| 727 // parameters of the type class must be finalized. | 729 // parameters of the type class must be finalized. |
| 728 Class& type_class = Class::Handle(parameterized_type.type_class()); | 730 Class& type_class = Class::Handle(parameterized_type.type_class()); |
| 729 if (!type_class.is_finalized()) { | 731 if (!type_class.is_type_finalized()) { |
| 730 FinalizeTypeParameters(type_class); | 732 FinalizeTypeParameters(type_class); |
| 731 ResolveUpperBounds(type_class); | 733 ResolveUpperBounds(type_class); |
| 732 } | 734 } |
| 733 | 735 |
| 734 // Finalize the current type arguments of the type, which are still the | 736 // Finalize the current type arguments of the type, which are still the |
| 735 // parsed type arguments. | 737 // parsed type arguments. |
| 736 AbstractTypeArguments& arguments = | 738 AbstractTypeArguments& arguments = |
| 737 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 739 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
| 738 if (!arguments.IsNull()) { | 740 if (!arguments.IsNull()) { |
| 739 intptr_t num_arguments = arguments.Length(); | 741 intptr_t num_arguments = arguments.Length(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 } | 854 } |
| 853 | 855 |
| 854 // If the type class is a signature class, we are currently finalizing a | 856 // If the type class is a signature class, we are currently finalizing a |
| 855 // signature type, i.e. finalizing the result type and parameter types of the | 857 // signature type, i.e. finalizing the result type and parameter types of the |
| 856 // signature function of this signature type. | 858 // signature function of this signature type. |
| 857 // We do this after marking this type as finalized in order to allow a | 859 // We do this after marking this type as finalized in order to allow a |
| 858 // function type to refer to itself via its parameter types and result type. | 860 // function type to refer to itself via its parameter types and result type. |
| 859 if (type_class.IsSignatureClass()) { | 861 if (type_class.IsSignatureClass()) { |
| 860 // The class may be created while parsing a function body, after all | 862 // The class may be created while parsing a function body, after all |
| 861 // pending classes have already been finalized. | 863 // pending classes have already been finalized. |
| 862 FinalizeClass(type_class); | 864 FinalizeTypesInClass(type_class); |
| 863 } | 865 } |
| 864 | 866 |
| 865 // If a bound error occurred, return a BoundedType with a malformed bound. | 867 // If a bound error occurred, return a BoundedType with a malformed bound. |
| 866 // The malformed bound will be ignored in production mode. | 868 // The malformed bound will be ignored in production mode. |
| 867 if (!bound_error.IsNull()) { | 869 if (!bound_error.IsNull()) { |
| 868 FinalizationKind bound_finalization = kTryResolve; // No compile error. | 870 FinalizationKind bound_finalization = kTryResolve; // No compile error. |
| 869 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { | 871 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { |
| 870 bound_finalization = finalization; | 872 bound_finalization = finalization; |
| 871 } | 873 } |
| 872 const String& parameterized_type_name = String::Handle( | 874 const String& parameterized_type_name = String::Handle( |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 param_bound, | 1248 param_bound, |
| 1247 param.token_pos()); | 1249 param.token_pos()); |
| 1248 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | 1250 cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
| 1249 cloned_index++; | 1251 cloned_index++; |
| 1250 } | 1252 } |
| 1251 } | 1253 } |
| 1252 mixapp_class.set_type_parameters(cloned_type_params); | 1254 mixapp_class.set_type_parameters(cloned_type_params); |
| 1253 } | 1255 } |
| 1254 | 1256 |
| 1255 | 1257 |
| 1256 void ClassFinalizer::ApplyMixin(const Class& cls) { | 1258 void ClassFinalizer::ApplyMixinTypes(const Class& cls) { |
| 1257 const Type& mixin_type = Type::Handle(cls.mixin()); | 1259 const Type& mixin_type = Type::Handle(cls.mixin()); |
| 1258 ASSERT(!mixin_type.IsNull()); | 1260 ASSERT(!mixin_type.IsNull()); |
| 1259 ASSERT(mixin_type.HasResolvedTypeClass()); | 1261 ASSERT(mixin_type.HasResolvedTypeClass()); |
| 1260 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); | 1262 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); |
| 1261 | 1263 |
| 1262 if (FLAG_trace_class_finalization) { | 1264 if (FLAG_trace_class_finalization) { |
| 1263 OS::Print("Applying mixin '%s' to '%s' at pos %"Pd"\n", | 1265 OS::Print("Applying mixin type '%s' to '%s' at pos %"Pd"\n", |
| 1264 String::Handle(mixin_cls.Name()).ToCString(), | 1266 String::Handle(mixin_cls.Name()).ToCString(), |
| 1265 cls.ToCString(), | 1267 cls.ToCString(), |
| 1266 cls.token_pos()); | 1268 cls.token_pos()); |
| 1267 } | 1269 } |
| 1268 | 1270 |
| 1269 // Check that the super class of the mixin class is extending | 1271 // Check that the super class of the mixin class is extending |
| 1270 // class Object. | 1272 // class Object. |
| 1271 const AbstractType& mixin_super_type = | 1273 const AbstractType& mixin_super_type = |
| 1272 AbstractType::Handle(mixin_cls.super_type()); | 1274 AbstractType::Handle(mixin_cls.super_type()); |
| 1273 if (!mixin_super_type.IsObjectType()) { | 1275 if (!mixin_super_type.IsObjectType()) { |
| 1274 const Script& script = Script::Handle(cls.script()); | 1276 const Script& script = Script::Handle(cls.script()); |
| 1275 const String& class_name = String::Handle(mixin_cls.Name()); | 1277 const String& class_name = String::Handle(mixin_cls.Name()); |
| 1276 ReportError(script, cls.token_pos(), | 1278 ReportError(script, cls.token_pos(), |
| 1277 "mixin class %s must extend class Object", | 1279 "mixin class %s must extend class Object", |
| 1278 class_name.ToCString()); | 1280 class_name.ToCString()); |
| 1279 } | 1281 } |
| 1280 | 1282 |
| 1281 // Copy type parameters to mixin application class. | 1283 // Copy type parameters to mixin application class. |
| 1282 CloneTypeParameters(cls); | 1284 CloneTypeParameters(cls); |
| 1283 | 1285 |
| 1286 if (FLAG_trace_class_finalization) { |
| 1287 OS::Print("done mixin type appl %s %s extending %s\n", |
| 1288 String::Handle(cls.Name()).ToCString(), |
| 1289 TypeArguments::Handle(cls.type_parameters()).ToCString(), |
| 1290 AbstractType::Handle(cls.super_type()).ToCString()); |
| 1291 } |
| 1292 } |
| 1293 |
| 1294 |
| 1295 void ClassFinalizer::ApplyMixin(const Class& cls) { |
| 1296 Isolate* isolate = Isolate::Current(); |
| 1297 const Type& mixin_type = Type::Handle(isolate, cls.mixin()); |
| 1298 ASSERT(!mixin_type.IsNull()); |
| 1299 ASSERT(mixin_type.HasResolvedTypeClass()); |
| 1300 const Class& mixin_cls = Class::Handle(isolate, mixin_type.type_class()); |
| 1301 mixin_cls.EnsureIsParsed(isolate); |
| 1302 |
| 1303 if (FLAG_trace_class_finalization) { |
| 1304 OS::Print("Applying mixin '%s' to '%s' at pos %"Pd"\n", |
| 1305 String::Handle(mixin_cls.Name()).ToCString(), |
| 1306 cls.ToCString(), |
| 1307 cls.token_pos()); |
| 1308 } |
| 1309 |
| 1284 const GrowableObjectArray& cloned_funcs = | 1310 const GrowableObjectArray& cloned_funcs = |
| 1285 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1311 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 1286 Array& functions = Array::Handle(); | 1312 Array& functions = Array::Handle(isolate); |
| 1287 Function& func = Function::Handle(); | 1313 Function& func = Function::Handle(isolate); |
| 1288 // The parser creates the mixin application class and adds just | 1314 // The parser creates the mixin application class and adds just |
| 1289 // one function, the implicit constructor. | 1315 // one function, the implicit constructor. |
| 1290 functions = cls.functions(); | 1316 functions = cls.functions(); |
| 1291 ASSERT(functions.Length() == 1); | 1317 ASSERT(functions.Length() == 1); |
| 1292 func ^= functions.At(0); | 1318 func ^= functions.At(0); |
| 1293 ASSERT(func.IsImplicitConstructor()); | 1319 ASSERT(func.IsImplicitConstructor()); |
| 1294 cloned_funcs.Add(func); | 1320 cloned_funcs.Add(func); |
| 1295 // Now clone the functions from the mixin class. | 1321 // Now clone the functions from the mixin class. |
| 1296 functions = mixin_cls.functions(); | 1322 functions = mixin_cls.functions(); |
| 1297 const intptr_t num_functions = functions.Length(); | 1323 const intptr_t num_functions = functions.Length(); |
| 1298 for (int i = 0; i < num_functions; i++) { | 1324 for (int i = 0; i < num_functions; i++) { |
| 1299 func ^= functions.At(i); | 1325 func ^= functions.At(i); |
| 1300 if (func.IsConstructor()) { | 1326 if (func.IsConstructor()) { |
| 1301 // A mixin class must not have explicit constructors. | 1327 // A mixin class must not have explicit constructors. |
| 1302 if (!func.IsImplicitConstructor()) { | 1328 if (!func.IsImplicitConstructor()) { |
| 1303 const Script& script = Script::Handle(cls.script()); | 1329 const Script& script = Script::Handle(isolate, cls.script()); |
| 1304 ReportError(script, cls.token_pos(), | 1330 ReportError(script, cls.token_pos(), |
| 1305 "mixin class %s must not have constructors\n", | 1331 "mixin class %s must not have constructors\n", |
| 1306 String::Handle(mixin_cls.Name()).ToCString()); | 1332 String::Handle(isolate, mixin_cls.Name()).ToCString()); |
| 1307 } | 1333 } |
| 1308 continue; // Skip the implicit constructor. | 1334 continue; // Skip the implicit constructor. |
| 1309 } | 1335 } |
| 1310 if (!func.is_static()) { | 1336 if (!func.is_static()) { |
| 1311 func = func.Clone(cls); | 1337 func = func.Clone(cls); |
| 1312 cloned_funcs.Add(func); | 1338 cloned_funcs.Add(func); |
| 1313 } | 1339 } |
| 1314 } | 1340 } |
| 1315 functions = Array::MakeArray(cloned_funcs); | 1341 functions = Array::MakeArray(cloned_funcs); |
| 1316 cls.SetFunctions(functions); | 1342 cls.SetFunctions(functions); |
| 1317 | 1343 |
| 1318 // Now clone the fields from the mixin class. There should be no | 1344 // Now clone the fields from the mixin class. There should be no |
| 1319 // existing fields in the mixin application class. | 1345 // existing fields in the mixin application class. |
| 1320 ASSERT(Array::Handle(cls.fields()).Length() == 0); | 1346 ASSERT(Array::Handle(cls.fields()).Length() == 0); |
| 1321 Array& fields = Array::Handle(mixin_cls.fields()); | 1347 Array& fields = Array::Handle(isolate, mixin_cls.fields()); |
| 1322 Field& field = Field::Handle(); | 1348 Field& field = Field::Handle(isolate); |
| 1323 const GrowableObjectArray& cloned_fields = | 1349 const GrowableObjectArray& cloned_fields = |
| 1324 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1350 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 1325 const intptr_t num_fields = fields.Length(); | 1351 const intptr_t num_fields = fields.Length(); |
| 1326 for (int i = 0; i < num_fields; i++) { | 1352 for (int i = 0; i < num_fields; i++) { |
| 1327 field ^= fields.At(i); | 1353 field ^= fields.At(i); |
| 1328 if (!field.is_static()) { | 1354 if (!field.is_static()) { |
| 1329 field = field.Clone(cls); | 1355 field = field.Clone(cls); |
| 1330 cloned_fields.Add(field); | 1356 cloned_fields.Add(field); |
| 1331 } | 1357 } |
| 1332 } | 1358 } |
| 1333 fields = Array::MakeArray(cloned_fields); | 1359 fields = Array::MakeArray(cloned_fields); |
| 1334 cls.SetFields(fields); | 1360 cls.SetFields(fields); |
| 1335 | 1361 |
| 1336 if (FLAG_trace_class_finalization) { | 1362 if (FLAG_trace_class_finalization) { |
| 1337 OS::Print("done mixin appl %s %s extending %s\n", | 1363 OS::Print("done mixin appl %s %s extending %s\n", |
| 1338 String::Handle(cls.Name()).ToCString(), | 1364 String::Handle(cls.Name()).ToCString(), |
| 1339 TypeArguments::Handle(cls.type_parameters()).ToCString(), | 1365 TypeArguments::Handle(cls.type_parameters()).ToCString(), |
| 1340 AbstractType::Handle(cls.super_type()).ToCString()); | 1366 AbstractType::Handle(cls.super_type()).ToCString()); |
| 1341 } | 1367 } |
| 1342 } | 1368 } |
| 1343 | 1369 |
| 1344 | 1370 |
| 1345 void ClassFinalizer::FinalizeClass(const Class& cls) { | 1371 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
| 1346 HANDLESCOPE(Isolate::Current()); | 1372 HANDLESCOPE(Isolate::Current()); |
| 1347 if (cls.is_finalized()) { | 1373 if (cls.is_type_finalized()) { |
| 1348 return; | 1374 return; |
| 1349 } | 1375 } |
| 1350 if (FLAG_trace_class_finalization) { | 1376 if (FLAG_trace_class_finalization) { |
| 1351 OS::Print("Finalize %s\n", cls.ToCString()); | 1377 OS::Print("Finalize %s\n", cls.ToCString()); |
| 1352 } | 1378 } |
| 1353 if (!IsSuperCycleFree(cls)) { | 1379 if (!IsSuperCycleFree(cls)) { |
| 1354 const String& name = String::Handle(cls.Name()); | 1380 const String& name = String::Handle(cls.Name()); |
| 1355 const Script& script = Script::Handle(cls.script()); | 1381 const Script& script = Script::Handle(cls.script()); |
| 1356 ReportError(script, cls.token_pos(), | 1382 ReportError(script, cls.token_pos(), |
| 1357 "class '%s' has a cycle in its superclass relationship", | 1383 "class '%s' has a cycle in its superclass relationship", |
| 1358 name.ToCString()); | 1384 name.ToCString()); |
| 1359 } | 1385 } |
| 1360 // Finalize super class. | 1386 // Finalize super class. |
| 1361 const Class& super_class = Class::Handle(cls.SuperClass()); | 1387 const Class& super_class = Class::Handle(cls.SuperClass()); |
| 1362 if (!super_class.IsNull()) { | 1388 if (!super_class.IsNull()) { |
| 1363 FinalizeClass(super_class); | 1389 FinalizeTypesInClass(super_class); |
| 1364 } | 1390 } |
| 1365 if (cls.mixin() != Type::null()) { | 1391 if (cls.mixin() != Type::null()) { |
| 1366 // Copy instance methods and fields from the mixin class. | 1392 // Copy the type parameters to the mixin application. |
| 1367 // This has to happen before the check whether the methods of | 1393 ApplyMixinTypes(cls); |
| 1368 // the class conflict with inherited methods. | |
| 1369 ApplyMixin(cls); | |
| 1370 } | 1394 } |
| 1371 // Finalize type parameters before finalizing the super type. | 1395 // Finalize type parameters before finalizing the super type. |
| 1372 FinalizeTypeParameters(cls); | 1396 FinalizeTypeParameters(cls); |
| 1373 ResolveUpperBounds(cls); | 1397 ResolveUpperBounds(cls); |
| 1374 // Finalize super type. | 1398 // Finalize super type. |
| 1375 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 1399 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 1376 if (!super_type.IsNull()) { | 1400 if (!super_type.IsNull()) { |
| 1377 // In case of a bound error in the super type in production mode, the | 1401 // In case of a bound error in the super type in production mode, the |
| 1378 // finalized super type will be a BoundedType with a malformed bound. | 1402 // finalized super type will be a BoundedType with a malformed bound. |
| 1379 // It should not be a problem if the class is written to a snapshot and | 1403 // It should not be a problem if the class is written to a snapshot and |
| 1380 // later executed in checked mode. Note that the finalized type argument | 1404 // later executed in checked mode. Note that the finalized type argument |
| 1381 // vector of any type of the base class will contain a BoundedType for the | 1405 // vector of any type of the base class will contain a BoundedType for the |
| 1382 // out of bound type argument. | 1406 // out of bound type argument. |
| 1383 super_type = FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1407 super_type = FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
| 1384 cls.set_super_type(super_type); | 1408 cls.set_super_type(super_type); |
| 1385 } | 1409 } |
| 1386 if (cls.IsSignatureClass()) { | 1410 if (cls.IsSignatureClass()) { |
| 1387 // Check for illegal self references. | 1411 // Check for illegal self references. |
| 1388 GrowableArray<intptr_t> visited_aliases; | 1412 GrowableArray<intptr_t> visited_aliases; |
| 1389 if (!IsAliasCycleFree(cls, &visited_aliases)) { | 1413 if (!IsAliasCycleFree(cls, &visited_aliases)) { |
| 1390 const String& name = String::Handle(cls.Name()); | 1414 const String& name = String::Handle(cls.Name()); |
| 1391 const Script& script = Script::Handle(cls.script()); | 1415 const Script& script = Script::Handle(cls.script()); |
| 1392 ReportError(script, cls.token_pos(), | 1416 ReportError(script, cls.token_pos(), |
| 1393 "typedef '%s' illegally refers to itself", | 1417 "typedef '%s' illegally refers to itself", |
| 1394 name.ToCString()); | 1418 name.ToCString()); |
| 1395 } | 1419 } |
| 1396 cls.Finalize(); | 1420 cls.set_is_type_finalized(); |
| 1397 // Signature classes extend Object. No need to add this class to the direct | 1421 // Signature classes extend Object. No need to add this class to the direct |
| 1398 // subclasses of Object. | 1422 // subclasses of Object. |
| 1399 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1423 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
| 1400 | 1424 |
| 1401 // The type parameters of signature classes may have bounds. | 1425 // The type parameters of signature classes may have bounds. |
| 1402 FinalizeUpperBounds(cls); | 1426 FinalizeUpperBounds(cls); |
| 1403 | 1427 |
| 1404 // Resolve and finalize the result and parameter types of the signature | 1428 // Resolve and finalize the result and parameter types of the signature |
| 1405 // function of this signature class. | 1429 // function of this signature class. |
| 1406 const Function& sig_function = Function::Handle(cls.signature_function()); | 1430 const Function& sig_function = Function::Handle(cls.signature_function()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 if (interface_type.Equals(seen_interf)) { | 1462 if (interface_type.Equals(seen_interf)) { |
| 1439 const Script& script = Script::Handle(cls.script()); | 1463 const Script& script = Script::Handle(cls.script()); |
| 1440 ReportError(script, cls.token_pos(), | 1464 ReportError(script, cls.token_pos(), |
| 1441 "interface '%s' appears twice in " | 1465 "interface '%s' appears twice in " |
| 1442 "implements clause of class '%s'", | 1466 "implements clause of class '%s'", |
| 1443 String::Handle(interface_type.Name()).ToCString(), | 1467 String::Handle(interface_type.Name()).ToCString(), |
| 1444 String::Handle(cls.Name()).ToCString()); | 1468 String::Handle(cls.Name()).ToCString()); |
| 1445 } | 1469 } |
| 1446 } | 1470 } |
| 1447 } | 1471 } |
| 1448 // Mark as finalized before resolving type parameter upper bounds and member | 1472 // Mark as type finalized before resolving type parameter upper bounds and |
| 1449 // types in order to break cycles. | 1473 // member types in order to break cycles. |
| 1450 cls.Finalize(); | 1474 cls.set_is_type_finalized(); |
| 1451 // Finalize bounds even if running in production mode, so that a snapshot | 1475 // Finalize bounds even if running in production mode, so that a snapshot |
| 1452 // contains them. | 1476 // contains them. |
| 1453 FinalizeUpperBounds(cls); | 1477 FinalizeUpperBounds(cls); |
| 1454 ResolveAndFinalizeMemberTypes(cls); | |
| 1455 // Run additional checks after all types are finalized. | |
| 1456 if (cls.is_const()) { | |
| 1457 CheckForLegalConstClass(cls); | |
| 1458 } | |
| 1459 // Add this class to the direct subclasses of the superclass, unless the | 1478 // Add this class to the direct subclasses of the superclass, unless the |
| 1460 // superclass is Object. | 1479 // superclass is Object. |
| 1461 if (!super_type.IsNull() && !super_type.IsObjectType()) { | 1480 if (!super_type.IsNull() && !super_type.IsObjectType()) { |
| 1462 ASSERT(!super_class.IsNull()); | 1481 ASSERT(!super_class.IsNull()); |
| 1463 super_class.AddDirectSubclass(cls); | 1482 super_class.AddDirectSubclass(cls); |
| 1464 } | 1483 } |
| 1484 if (cls.is_parsed()) { |
| 1485 ClassFinalizer::FinalizeClass(cls); |
| 1486 } |
| 1487 } |
| 1488 |
| 1489 |
| 1490 void ClassFinalizer::FinalizeClass(const Class& cls) { |
| 1491 HANDLESCOPE(Isolate::Current()); |
| 1492 if (cls.is_finalized()) { |
| 1493 return; |
| 1494 } |
| 1495 if (cls.mixin() != Type::null()) { |
| 1496 // Copy instance methods and fields from the mixin class. |
| 1497 // This has to happen before the check whether the methods of |
| 1498 // the class conflict with inherited methods. |
| 1499 ApplyMixin(cls); |
| 1500 } |
| 1501 // Mark as parsed and finalized. |
| 1502 cls.Finalize(); |
| 1503 // Resolve and finalize all member types. |
| 1504 ResolveAndFinalizeMemberTypes(cls); |
| 1505 // Run additional checks after all types are finalized. |
| 1506 if (cls.is_const()) { |
| 1507 CheckForLegalConstClass(cls); |
| 1508 } |
| 1465 } | 1509 } |
| 1466 | 1510 |
| 1467 | 1511 |
| 1468 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 1512 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
| 1469 Class& test1 = Class::Handle(cls.raw()); | 1513 Class& test1 = Class::Handle(cls.raw()); |
| 1470 Class& test2 = Class::Handle(cls.SuperClass()); | 1514 Class& test2 = Class::Handle(cls.SuperClass()); |
| 1471 // A finalized class has been checked for cycles. | 1515 // A finalized class has been checked for cycles. |
| 1472 // Using the hare and tortoise algorithm for locating cycles. | 1516 // Using the hare and tortoise algorithm for locating cycles. |
| 1473 while (!test1.is_finalized() && | 1517 while (!test1.is_type_finalized() && |
| 1474 !test2.IsNull() && !test2.is_finalized()) { | 1518 !test2.IsNull() && !test2.is_type_finalized()) { |
| 1475 if (test1.raw() == test2.raw()) { | 1519 if (test1.raw() == test2.raw()) { |
| 1476 // Found a cycle. | 1520 // Found a cycle. |
| 1477 return false; | 1521 return false; |
| 1478 } | 1522 } |
| 1479 test1 = test1.SuperClass(); | 1523 test1 = test1.SuperClass(); |
| 1480 test2 = test2.SuperClass(); | 1524 test2 = test2.SuperClass(); |
| 1481 if (!test2.IsNull()) { | 1525 if (!test2.IsNull()) { |
| 1482 test2 = test2.SuperClass(); | 1526 test2 = test2.SuperClass(); |
| 1483 } | 1527 } |
| 1484 } | 1528 } |
| 1485 // No cycles. | 1529 // No cycles. |
| 1486 return true; | 1530 return true; |
| 1487 } | 1531 } |
| 1488 | 1532 |
| 1489 | 1533 |
| 1490 // Returns false if the function type alias illegally refers to itself. | 1534 // Returns false if the function type alias illegally refers to itself. |
| 1491 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, | 1535 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
| 1492 GrowableArray<intptr_t>* visited) { | 1536 GrowableArray<intptr_t>* visited) { |
| 1493 ASSERT(cls.IsSignatureClass()); | 1537 ASSERT(cls.IsSignatureClass()); |
| 1494 ASSERT(!cls.is_finalized()); | 1538 ASSERT(!cls.is_type_finalized()); |
| 1495 ASSERT(visited != NULL); | 1539 ASSERT(visited != NULL); |
| 1496 const intptr_t cls_index = cls.id(); | 1540 const intptr_t cls_index = cls.id(); |
| 1497 for (int i = 0; i < visited->length(); i++) { | 1541 for (int i = 0; i < visited->length(); i++) { |
| 1498 if ((*visited)[i] == cls_index) { | 1542 if ((*visited)[i] == cls_index) { |
| 1499 // We have already visited alias 'cls'. We found a cycle. | 1543 // We have already visited alias 'cls'. We found a cycle. |
| 1500 return false; | 1544 return false; |
| 1501 } | 1545 } |
| 1502 } | 1546 } |
| 1503 | 1547 |
| 1504 // Visit the result type and parameter types of this signature type. | 1548 // Visit the result type and parameter types of this signature type. |
| 1505 visited->Add(cls.id()); | 1549 visited->Add(cls.id()); |
| 1506 const Function& function = Function::Handle(cls.signature_function()); | 1550 const Function& function = Function::Handle(cls.signature_function()); |
| 1507 // Check class of result type. | 1551 // Check class of result type. |
| 1508 AbstractType& type = AbstractType::Handle(function.result_type()); | 1552 AbstractType& type = AbstractType::Handle(function.result_type()); |
| 1509 ResolveType(cls, type, kCanonicalize); | 1553 ResolveType(cls, type, kCanonicalize); |
| 1510 if (type.IsType() && !type.IsMalformed()) { | 1554 if (type.IsType() && !type.IsMalformed()) { |
| 1511 const Class& type_class = Class::Handle(type.type_class()); | 1555 const Class& type_class = Class::Handle(type.type_class()); |
| 1512 if (!type_class.is_finalized() && | 1556 if (!type_class.is_type_finalized() && |
| 1513 type_class.IsSignatureClass() && | 1557 type_class.IsSignatureClass() && |
| 1514 !IsAliasCycleFree(type_class, visited)) { | 1558 !IsAliasCycleFree(type_class, visited)) { |
| 1515 return false; | 1559 return false; |
| 1516 } | 1560 } |
| 1517 } | 1561 } |
| 1518 // Check classes of formal parameter types. | 1562 // Check classes of formal parameter types. |
| 1519 const intptr_t num_parameters = function.NumParameters(); | 1563 const intptr_t num_parameters = function.NumParameters(); |
| 1520 for (intptr_t i = 0; i < num_parameters; i++) { | 1564 for (intptr_t i = 0; i < num_parameters; i++) { |
| 1521 type = function.ParameterTypeAt(i); | 1565 type = function.ParameterTypeAt(i); |
| 1522 ResolveType(cls, type, kCanonicalize); | 1566 ResolveType(cls, type, kCanonicalize); |
| 1523 if (type.IsType() && !type.IsMalformed()) { | 1567 if (type.IsType() && !type.IsMalformed()) { |
| 1524 const Class& type_class = Class::Handle(type.type_class()); | 1568 const Class& type_class = Class::Handle(type.type_class()); |
| 1525 if (!type_class.is_finalized() && | 1569 if (!type_class.is_type_finalized() && |
| 1526 type_class.IsSignatureClass() && | 1570 type_class.IsSignatureClass() && |
| 1527 !IsAliasCycleFree(type_class, visited)) { | 1571 !IsAliasCycleFree(type_class, visited)) { |
| 1528 return false; | 1572 return false; |
| 1529 } | 1573 } |
| 1530 } | 1574 } |
| 1531 } | 1575 } |
| 1532 visited->RemoveLast(); | 1576 visited->RemoveLast(); |
| 1533 return true; | 1577 return true; |
| 1534 } | 1578 } |
| 1535 | 1579 |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 va_start(args, format); | 1983 va_start(args, format); |
| 1940 const Error& error = Error::Handle( | 1984 const Error& error = Error::Handle( |
| 1941 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1985 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1942 va_end(args); | 1986 va_end(args); |
| 1943 ReportError(error); | 1987 ReportError(error); |
| 1944 } | 1988 } |
| 1945 | 1989 |
| 1946 | 1990 |
| 1947 void ClassFinalizer::VerifyImplicitFieldOffsets() { | 1991 void ClassFinalizer::VerifyImplicitFieldOffsets() { |
| 1948 #ifdef DEBUG | 1992 #ifdef DEBUG |
| 1949 const ClassTable& class_table = *(Isolate::Current()->class_table()); | 1993 Isolate* isolate = Isolate::Current(); |
| 1950 Class& cls = Class::Handle(); | 1994 const ClassTable& class_table = *(isolate->class_table()); |
| 1951 Array& fields_array = Array::Handle(); | 1995 Class& cls = Class::Handle(isolate); |
| 1952 Field& field = Field::Handle(); | 1996 Array& fields_array = Array::Handle(isolate); |
| 1953 String& name = String::Handle(); | 1997 Field& field = Field::Handle(isolate); |
| 1954 String& expected_name = String::Handle(); | 1998 String& name = String::Handle(isolate); |
| 1999 String& expected_name = String::Handle(isolate); |
| 2000 Error& error = Error::Handle(isolate); |
| 1955 | 2001 |
| 1956 // First verify field offsets of all the TypedDataView classes. | 2002 // First verify field offsets of all the TypedDataView classes. |
| 1957 for (intptr_t cid = kTypedDataInt8ArrayViewCid; | 2003 for (intptr_t cid = kTypedDataInt8ArrayViewCid; |
| 1958 cid <= kTypedDataFloat32x4ArrayViewCid; | 2004 cid <= kTypedDataFloat32x4ArrayViewCid; |
| 1959 cid++) { | 2005 cid++) { |
| 1960 cls = class_table.At(cid); // Get the TypedDataView class. | 2006 cls = class_table.At(cid); // Get the TypedDataView class. |
| 2007 error = cls.EnsureIsParsed(isolate); |
| 2008 ASSERT(error.IsNull()); |
| 1961 cls = cls.SuperClass(); // Get it's super class '_TypedListView'. | 2009 cls = cls.SuperClass(); // Get it's super class '_TypedListView'. |
| 1962 fields_array ^= cls.fields(); | 2010 fields_array ^= cls.fields(); |
| 1963 ASSERT(fields_array.Length() == TypedDataView::NumberOfFields()); | 2011 ASSERT(fields_array.Length() == TypedDataView::NumberOfFields()); |
| 1964 field ^= fields_array.At(0); | 2012 field ^= fields_array.At(0); |
| 1965 ASSERT(field.Offset() == TypedDataView::data_offset()); | 2013 ASSERT(field.Offset() == TypedDataView::data_offset()); |
| 1966 name ^= field.name(); | 2014 name ^= field.name(); |
| 1967 expected_name ^= String::New("_typedData"); | 2015 expected_name ^= String::New("_typedData"); |
| 1968 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2016 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 1969 field ^= fields_array.At(1); | 2017 field ^= fields_array.At(1); |
| 1970 ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset()); | 2018 ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset()); |
| 1971 name ^= field.name(); | 2019 name ^= field.name(); |
| 1972 ASSERT(name.Equals("offsetInBytes")); | 2020 ASSERT(name.Equals("offsetInBytes")); |
| 1973 field ^= fields_array.At(2); | 2021 field ^= fields_array.At(2); |
| 1974 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2022 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 1975 name ^= field.name(); | 2023 name ^= field.name(); |
| 1976 ASSERT(name.Equals("length")); | 2024 ASSERT(name.Equals("length")); |
| 1977 } | 2025 } |
| 1978 | 2026 |
| 1979 // Now verify field offsets of '_ByteDataView' class. | 2027 // Now verify field offsets of '_ByteDataView' class. |
| 1980 cls = class_table.At(kByteDataViewCid); | 2028 cls = class_table.At(kByteDataViewCid); |
| 2029 error = cls.EnsureIsParsed(isolate); |
| 2030 ASSERT(error.IsNull()); |
| 1981 fields_array ^= cls.fields(); | 2031 fields_array ^= cls.fields(); |
| 1982 ASSERT(fields_array.Length() == TypedDataView::NumberOfFields()); | 2032 ASSERT(fields_array.Length() == TypedDataView::NumberOfFields()); |
| 1983 field ^= fields_array.At(0); | 2033 field ^= fields_array.At(0); |
| 1984 ASSERT(field.Offset() == TypedDataView::data_offset()); | 2034 ASSERT(field.Offset() == TypedDataView::data_offset()); |
| 1985 name ^= field.name(); | 2035 name ^= field.name(); |
| 1986 expected_name ^= String::New("_typedData"); | 2036 expected_name ^= String::New("_typedData"); |
| 1987 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2037 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 1988 field ^= fields_array.At(1); | 2038 field ^= fields_array.At(1); |
| 1989 ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset()); | 2039 ASSERT(field.Offset() == TypedDataView::offset_in_bytes_offset()); |
| 1990 name ^= field.name(); | 2040 name ^= field.name(); |
| 1991 expected_name ^= String::New("_offset"); | 2041 expected_name ^= String::New("_offset"); |
| 1992 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2042 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 1993 field ^= fields_array.At(2); | 2043 field ^= fields_array.At(2); |
| 1994 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2044 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 1995 name ^= field.name(); | 2045 name ^= field.name(); |
| 1996 ASSERT(name.Equals("length")); | 2046 ASSERT(name.Equals("length")); |
| 1997 #endif | 2047 #endif |
| 1998 } | 2048 } |
| 1999 | 2049 |
| 2000 } // namespace dart | 2050 } // namespace dart |
| OLD | NEW |