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" |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 if (super_type.IsNull()) { | 318 if (super_type.IsNull()) { |
319 return; | 319 return; |
320 } | 320 } |
321 // Resolve failures lead to a longjmp. | 321 // Resolve failures lead to a longjmp. |
322 ResolveType(cls, super_type, kFinalizeWellFormed); | 322 ResolveType(cls, super_type, kFinalizeWellFormed); |
323 const Class& super_class = Class::Handle(super_type.type_class()); | 323 const Class& super_class = Class::Handle(super_type.type_class()); |
324 if (cls.is_interface() != super_class.is_interface()) { | 324 if (cls.is_interface() != super_class.is_interface()) { |
325 String& class_name = String::Handle(cls.Name()); | 325 String& class_name = String::Handle(cls.Name()); |
326 String& super_class_name = String::Handle(super_class.Name()); | 326 String& super_class_name = String::Handle(super_class.Name()); |
327 const Script& script = Script::Handle(cls.script()); | 327 const Script& script = Script::Handle(cls.script()); |
328 ReportError(script, cls.token_index(), | 328 ReportError(script, cls.token_pos(), |
329 "class '%s' and superclass '%s' are not " | 329 "class '%s' and superclass '%s' are not " |
330 "both classes or both interfaces", | 330 "both classes or both interfaces", |
331 class_name.ToCString(), | 331 class_name.ToCString(), |
332 super_class_name.ToCString()); | 332 super_class_name.ToCString()); |
333 } | 333 } |
334 // If cls belongs to core lib or to core lib's implementation, restrictions | 334 // If cls belongs to core lib or to core lib's implementation, restrictions |
335 // about allowed interfaces are lifted. | 335 // about allowed interfaces are lifted. |
336 if ((cls.library() != Library::CoreLibrary()) && | 336 if ((cls.library() != Library::CoreLibrary()) && |
337 (cls.library() != Library::CoreImplLibrary())) { | 337 (cls.library() != Library::CoreImplLibrary())) { |
338 // Prevent extending core implementation classes Bool, Double, ObjectArray, | 338 // Prevent extending core implementation classes Bool, Double, ObjectArray, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 (super_class.raw() == object_store->external_float32_array_class()) || | 374 (super_class.raw() == object_store->external_float32_array_class()) || |
375 (super_class.raw() == object_store->external_float64_array_class()) || | 375 (super_class.raw() == object_store->external_float64_array_class()) || |
376 (super_class.raw() == integer_implementation_class.raw()) || | 376 (super_class.raw() == integer_implementation_class.raw()) || |
377 (super_class.raw() == object_store->smi_class()) || | 377 (super_class.raw() == object_store->smi_class()) || |
378 (super_class.raw() == object_store->mint_class()) || | 378 (super_class.raw() == object_store->mint_class()) || |
379 (super_class.raw() == object_store->bigint_class()) || | 379 (super_class.raw() == object_store->bigint_class()) || |
380 (super_class.raw() == object_store->one_byte_string_class()) || | 380 (super_class.raw() == object_store->one_byte_string_class()) || |
381 (super_class.raw() == object_store->two_byte_string_class()) || | 381 (super_class.raw() == object_store->two_byte_string_class()) || |
382 (super_class.raw() == object_store->four_byte_string_class())) { | 382 (super_class.raw() == object_store->four_byte_string_class())) { |
383 const Script& script = Script::Handle(cls.script()); | 383 const Script& script = Script::Handle(cls.script()); |
384 ReportError(script, cls.token_index(), | 384 ReportError(script, cls.token_pos(), |
385 "'%s' is not allowed to extend '%s'", | 385 "'%s' is not allowed to extend '%s'", |
386 String::Handle(cls.Name()).ToCString(), | 386 String::Handle(cls.Name()).ToCString(), |
387 String::Handle(super_class.Name()).ToCString()); | 387 String::Handle(super_class.Name()).ToCString()); |
388 } | 388 } |
389 } | 389 } |
390 return; | 390 return; |
391 } | 391 } |
392 | 392 |
393 | 393 |
394 void ClassFinalizer::ResolveFactoryClass(const Class& interface) { | 394 void ClassFinalizer::ResolveFactoryClass(const Class& interface) { |
395 ASSERT(interface.is_interface()); | 395 ASSERT(interface.is_interface()); |
396 if (interface.is_finalized() || | 396 if (interface.is_finalized() || |
397 !interface.HasFactoryClass() || | 397 !interface.HasFactoryClass() || |
398 interface.HasResolvedFactoryClass()) { | 398 interface.HasResolvedFactoryClass()) { |
399 return; | 399 return; |
400 } | 400 } |
401 const UnresolvedClass& unresolved_factory_class = | 401 const UnresolvedClass& unresolved_factory_class = |
402 UnresolvedClass::Handle(interface.UnresolvedFactoryClass()); | 402 UnresolvedClass::Handle(interface.UnresolvedFactoryClass()); |
403 | 403 |
404 // Lookup the factory class. | 404 // Lookup the factory class. |
405 const Class& factory_class = | 405 const Class& factory_class = |
406 Class::Handle(ResolveClass(interface, unresolved_factory_class)); | 406 Class::Handle(ResolveClass(interface, unresolved_factory_class)); |
407 if (factory_class.IsNull()) { | 407 if (factory_class.IsNull()) { |
408 const Script& script = Script::Handle(interface.script()); | 408 const Script& script = Script::Handle(interface.script()); |
409 ReportError(script, unresolved_factory_class.token_index(), | 409 ReportError(script, unresolved_factory_class.token_pos(), |
410 "cannot resolve factory class name '%s' from '%s'", | 410 "cannot resolve factory class name '%s' from '%s'", |
411 String::Handle(unresolved_factory_class.Name()).ToCString(), | 411 String::Handle(unresolved_factory_class.Name()).ToCString(), |
412 String::Handle(interface.Name()).ToCString()); | 412 String::Handle(interface.Name()).ToCString()); |
413 } | 413 } |
414 if (factory_class.is_interface()) { | 414 if (factory_class.is_interface()) { |
415 const String& interface_name = String::Handle(interface.Name()); | 415 const String& interface_name = String::Handle(interface.Name()); |
416 const String& factory_name = String::Handle(factory_class.Name()); | 416 const String& factory_name = String::Handle(factory_class.Name()); |
417 const Script& script = Script::Handle(interface.script()); | 417 const Script& script = Script::Handle(interface.script()); |
418 ReportError(script, unresolved_factory_class.token_index(), | 418 ReportError(script, unresolved_factory_class.token_pos(), |
419 "default clause of interface '%s' names non-class '%s'", | 419 "default clause of interface '%s' names non-class '%s'", |
420 interface_name.ToCString(), | 420 interface_name.ToCString(), |
421 factory_name.ToCString()); | 421 factory_name.ToCString()); |
422 } | 422 } |
423 interface.set_factory_class(factory_class); | 423 interface.set_factory_class(factory_class); |
424 // It is not necessary to finalize the bounds before comparing them between | 424 // It is not necessary to finalize the bounds before comparing them between |
425 // the expected and actual factory class. | 425 // the expected and actual factory class. |
426 const Class& factory_signature_class = Class::Handle( | 426 const Class& factory_signature_class = Class::Handle( |
427 unresolved_factory_class.factory_signature_class()); | 427 unresolved_factory_class.factory_signature_class()); |
428 ASSERT(!factory_signature_class.IsNull()); | 428 ASSERT(!factory_signature_class.IsNull()); |
429 // If a type parameter list is included in the default factory clause (it | 429 // If a type parameter list is included in the default factory clause (it |
430 // can be omitted), verify that it matches the list of type parameters of | 430 // can be omitted), verify that it matches the list of type parameters of |
431 // the factory class in number, names, and bounds. | 431 // the factory class in number, names, and bounds. |
432 if (factory_signature_class.NumTypeParameters() > 0) { | 432 if (factory_signature_class.NumTypeParameters() > 0) { |
433 const TypeArguments& expected_type_parameters = | 433 const TypeArguments& expected_type_parameters = |
434 TypeArguments::Handle(factory_signature_class.type_parameters()); | 434 TypeArguments::Handle(factory_signature_class.type_parameters()); |
435 const TypeArguments& actual_type_parameters = | 435 const TypeArguments& actual_type_parameters = |
436 TypeArguments::Handle(factory_class.type_parameters()); | 436 TypeArguments::Handle(factory_class.type_parameters()); |
437 const TypeArguments& expected_type_parameter_bounds = | 437 const TypeArguments& expected_type_parameter_bounds = |
438 TypeArguments::Handle(factory_signature_class.type_parameter_bounds()); | 438 TypeArguments::Handle(factory_signature_class.type_parameter_bounds()); |
439 const TypeArguments& actual_type_parameter_bounds = | 439 const TypeArguments& actual_type_parameter_bounds = |
440 TypeArguments::Handle(factory_class.type_parameter_bounds()); | 440 TypeArguments::Handle(factory_class.type_parameter_bounds()); |
441 if (!AbstractTypeArguments::AreIdentical(expected_type_parameters, | 441 if (!AbstractTypeArguments::AreIdentical(expected_type_parameters, |
442 actual_type_parameters) || | 442 actual_type_parameters) || |
443 !AbstractTypeArguments::AreIdentical(expected_type_parameter_bounds, | 443 !AbstractTypeArguments::AreIdentical(expected_type_parameter_bounds, |
444 actual_type_parameter_bounds)) { | 444 actual_type_parameter_bounds)) { |
445 const String& interface_name = String::Handle(interface.Name()); | 445 const String& interface_name = String::Handle(interface.Name()); |
446 const String& factory_name = String::Handle(factory_class.Name()); | 446 const String& factory_name = String::Handle(factory_class.Name()); |
447 const Script& script = Script::Handle(interface.script()); | 447 const Script& script = Script::Handle(interface.script()); |
448 ReportError(script, unresolved_factory_class.token_index(), | 448 ReportError(script, unresolved_factory_class.token_pos(), |
449 "mismatch in number, names, or bounds of type parameters " | 449 "mismatch in number, names, or bounds of type parameters " |
450 "between default clause of interface '%s' and actual factory " | 450 "between default clause of interface '%s' and actual factory " |
451 "class '%s'", | 451 "class '%s'", |
452 interface_name.ToCString(), | 452 interface_name.ToCString(), |
453 factory_name.ToCString()); | 453 factory_name.ToCString()); |
454 } | 454 } |
455 } | 455 } |
456 // Verify that the type parameters of the factory class and of the interface | 456 // Verify that the type parameters of the factory class and of the interface |
457 // have identical names. | 457 // have identical names. |
458 const TypeArguments& interface_type_parameters = | 458 const TypeArguments& interface_type_parameters = |
459 TypeArguments::Handle(interface.type_parameters()); | 459 TypeArguments::Handle(interface.type_parameters()); |
460 const TypeArguments& factory_type_parameters = | 460 const TypeArguments& factory_type_parameters = |
461 TypeArguments::Handle(factory_class.type_parameters()); | 461 TypeArguments::Handle(factory_class.type_parameters()); |
462 if (!AbstractTypeArguments::AreIdentical(interface_type_parameters, | 462 if (!AbstractTypeArguments::AreIdentical(interface_type_parameters, |
463 factory_type_parameters)) { | 463 factory_type_parameters)) { |
464 const String& interface_name = String::Handle(interface.Name()); | 464 const String& interface_name = String::Handle(interface.Name()); |
465 const String& factory_name = String::Handle(factory_class.Name()); | 465 const String& factory_name = String::Handle(factory_class.Name()); |
466 const Script& script = Script::Handle(interface.script()); | 466 const Script& script = Script::Handle(interface.script()); |
467 ReportError(script, unresolved_factory_class.token_index(), | 467 ReportError(script, unresolved_factory_class.token_pos(), |
468 "mismatch in number or names of type parameters between " | 468 "mismatch in number or names of type parameters between " |
469 "interface '%s' and default factory class '%s'", | 469 "interface '%s' and default factory class '%s'", |
470 interface_name.ToCString(), | 470 interface_name.ToCString(), |
471 factory_name.ToCString()); | 471 factory_name.ToCString()); |
472 } | 472 } |
473 } | 473 } |
474 | 474 |
475 | 475 |
476 void ClassFinalizer::ResolveType(const Class& cls, | 476 void ClassFinalizer::ResolveType(const Class& cls, |
477 const AbstractType& type, | 477 const AbstractType& type, |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 type = field.type(); | 945 type = field.type(); |
946 ResolveType(cls, type, kFinalize); | 946 ResolveType(cls, type, kFinalize); |
947 type = FinalizeType(cls, type, kFinalize); | 947 type = FinalizeType(cls, type, kFinalize); |
948 field.set_type(type); | 948 field.set_type(type); |
949 name = field.name(); | 949 name = field.name(); |
950 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 950 super_class = FindSuperOwnerOfInstanceMember(cls, name); |
951 if (!super_class.IsNull()) { | 951 if (!super_class.IsNull()) { |
952 const String& class_name = String::Handle(cls.Name()); | 952 const String& class_name = String::Handle(cls.Name()); |
953 const String& super_class_name = String::Handle(super_class.Name()); | 953 const String& super_class_name = String::Handle(super_class.Name()); |
954 const Script& script = Script::Handle(cls.script()); | 954 const Script& script = Script::Handle(cls.script()); |
955 ReportError(script, field.token_index(), | 955 ReportError(script, field.token_pos(), |
956 "field '%s' of class '%s' conflicts with instance " | 956 "field '%s' of class '%s' conflicts with instance " |
957 "member '%s' of super class '%s'", | 957 "member '%s' of super class '%s'", |
958 name.ToCString(), | 958 name.ToCString(), |
959 class_name.ToCString(), | 959 class_name.ToCString(), |
960 name.ToCString(), | 960 name.ToCString(), |
961 super_class_name.ToCString()); | 961 super_class_name.ToCString()); |
962 } | 962 } |
963 } | 963 } |
964 // Collect interfaces, super interfaces, and super classes of this class. | 964 // Collect interfaces, super interfaces, and super classes of this class. |
965 const GrowableObjectArray& interfaces = | 965 const GrowableObjectArray& interfaces = |
(...skipping 15 matching lines...) Expand all Loading... |
981 for (intptr_t i = 0; i < num_functions; i++) { | 981 for (intptr_t i = 0; i < num_functions; i++) { |
982 function ^= array.At(i); | 982 function ^= array.At(i); |
983 ResolveAndFinalizeSignature(cls, function); | 983 ResolveAndFinalizeSignature(cls, function); |
984 function_name = function.name(); | 984 function_name = function.name(); |
985 if (function.is_static()) { | 985 if (function.is_static()) { |
986 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 986 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); |
987 if (!super_class.IsNull()) { | 987 if (!super_class.IsNull()) { |
988 const String& class_name = String::Handle(cls.Name()); | 988 const String& class_name = String::Handle(cls.Name()); |
989 const String& super_class_name = String::Handle(super_class.Name()); | 989 const String& super_class_name = String::Handle(super_class.Name()); |
990 const Script& script = Script::Handle(cls.script()); | 990 const Script& script = Script::Handle(cls.script()); |
991 ReportError(script, function.token_index(), | 991 ReportError(script, function.token_pos(), |
992 "static function '%s' of class '%s' conflicts with " | 992 "static function '%s' of class '%s' conflicts with " |
993 "instance member '%s' of super class '%s'", | 993 "instance member '%s' of super class '%s'", |
994 function_name.ToCString(), | 994 function_name.ToCString(), |
995 class_name.ToCString(), | 995 class_name.ToCString(), |
996 function_name.ToCString(), | 996 function_name.ToCString(), |
997 super_class_name.ToCString()); | 997 super_class_name.ToCString()); |
998 } | 998 } |
999 } else { | 999 } else { |
1000 for (int i = 0; i < interfaces.Length(); i++) { | 1000 for (int i = 0; i < interfaces.Length(); i++) { |
1001 super_class ^= interfaces.At(i); | 1001 super_class ^= interfaces.At(i); |
1002 overridden_function = super_class.LookupDynamicFunction(function_name); | 1002 overridden_function = super_class.LookupDynamicFunction(function_name); |
1003 if (!overridden_function.IsNull() && | 1003 if (!overridden_function.IsNull() && |
1004 !function.HasCompatibleParametersWith(overridden_function)) { | 1004 !function.HasCompatibleParametersWith(overridden_function)) { |
1005 // Function types are purposely not checked for subtyping. | 1005 // Function types are purposely not checked for subtyping. |
1006 const String& class_name = String::Handle(cls.Name()); | 1006 const String& class_name = String::Handle(cls.Name()); |
1007 const String& super_class_name = String::Handle(super_class.Name()); | 1007 const String& super_class_name = String::Handle(super_class.Name()); |
1008 const Script& script = Script::Handle(cls.script()); | 1008 const Script& script = Script::Handle(cls.script()); |
1009 ReportError(script, function.token_index(), | 1009 ReportError(script, function.token_pos(), |
1010 "class '%s' overrides function '%s' of %s '%s' " | 1010 "class '%s' overrides function '%s' of %s '%s' " |
1011 "with incompatible parameters", | 1011 "with incompatible parameters", |
1012 class_name.ToCString(), | 1012 class_name.ToCString(), |
1013 function_name.ToCString(), | 1013 function_name.ToCString(), |
1014 super_class.is_interface() ? "interface" : "super class", | 1014 super_class.is_interface() ? "interface" : "super class", |
1015 super_class_name.ToCString()); | 1015 super_class_name.ToCString()); |
1016 } | 1016 } |
1017 } | 1017 } |
1018 } | 1018 } |
1019 if (function.kind() == RawFunction::kGetterFunction) { | 1019 if (function.kind() == RawFunction::kGetterFunction) { |
1020 name = Field::NameFromGetter(function_name); | 1020 name = Field::NameFromGetter(function_name); |
1021 super_class = FindSuperOwnerOfFunction(cls, name); | 1021 super_class = FindSuperOwnerOfFunction(cls, name); |
1022 if (!super_class.IsNull()) { | 1022 if (!super_class.IsNull()) { |
1023 const String& class_name = String::Handle(cls.Name()); | 1023 const String& class_name = String::Handle(cls.Name()); |
1024 const String& super_class_name = String::Handle(super_class.Name()); | 1024 const String& super_class_name = String::Handle(super_class.Name()); |
1025 const Script& script = Script::Handle(cls.script()); | 1025 const Script& script = Script::Handle(cls.script()); |
1026 ReportError(script, function.token_index(), | 1026 ReportError(script, function.token_pos(), |
1027 "getter '%s' of class '%s' conflicts with " | 1027 "getter '%s' of class '%s' conflicts with " |
1028 "function '%s' of super class '%s'", | 1028 "function '%s' of super class '%s'", |
1029 name.ToCString(), | 1029 name.ToCString(), |
1030 class_name.ToCString(), | 1030 class_name.ToCString(), |
1031 name.ToCString(), | 1031 name.ToCString(), |
1032 super_class_name.ToCString()); | 1032 super_class_name.ToCString()); |
1033 } | 1033 } |
1034 } else if (function.kind() == RawFunction::kSetterFunction) { | 1034 } else if (function.kind() == RawFunction::kSetterFunction) { |
1035 name = Field::NameFromSetter(function_name); | 1035 name = Field::NameFromSetter(function_name); |
1036 super_class = FindSuperOwnerOfFunction(cls, name); | 1036 super_class = FindSuperOwnerOfFunction(cls, name); |
1037 if (!super_class.IsNull()) { | 1037 if (!super_class.IsNull()) { |
1038 const String& class_name = String::Handle(cls.Name()); | 1038 const String& class_name = String::Handle(cls.Name()); |
1039 const String& super_class_name = String::Handle(super_class.Name()); | 1039 const String& super_class_name = String::Handle(super_class.Name()); |
1040 const Script& script = Script::Handle(cls.script()); | 1040 const Script& script = Script::Handle(cls.script()); |
1041 ReportError(script, function.token_index(), | 1041 ReportError(script, function.token_pos(), |
1042 "setter '%s' of class '%s' conflicts with " | 1042 "setter '%s' of class '%s' conflicts with " |
1043 "function '%s' of super class '%s'", | 1043 "function '%s' of super class '%s'", |
1044 name.ToCString(), | 1044 name.ToCString(), |
1045 class_name.ToCString(), | 1045 class_name.ToCString(), |
1046 name.ToCString(), | 1046 name.ToCString(), |
1047 super_class_name.ToCString()); | 1047 super_class_name.ToCString()); |
1048 } | 1048 } |
1049 } else { | 1049 } else { |
1050 name = Field::GetterName(function_name); | 1050 name = Field::GetterName(function_name); |
1051 super_class = FindSuperOwnerOfFunction(cls, name); | 1051 super_class = FindSuperOwnerOfFunction(cls, name); |
1052 if (!super_class.IsNull()) { | 1052 if (!super_class.IsNull()) { |
1053 const String& class_name = String::Handle(cls.Name()); | 1053 const String& class_name = String::Handle(cls.Name()); |
1054 const String& super_class_name = String::Handle(super_class.Name()); | 1054 const String& super_class_name = String::Handle(super_class.Name()); |
1055 const Script& script = Script::Handle(cls.script()); | 1055 const Script& script = Script::Handle(cls.script()); |
1056 ReportError(script, function.token_index(), | 1056 ReportError(script, function.token_pos(), |
1057 "function '%s' of class '%s' conflicts with " | 1057 "function '%s' of class '%s' conflicts with " |
1058 "getter '%s' of super class '%s'", | 1058 "getter '%s' of super class '%s'", |
1059 function_name.ToCString(), | 1059 function_name.ToCString(), |
1060 class_name.ToCString(), | 1060 class_name.ToCString(), |
1061 function_name.ToCString(), | 1061 function_name.ToCString(), |
1062 super_class_name.ToCString()); | 1062 super_class_name.ToCString()); |
1063 } | 1063 } |
1064 name = Field::SetterName(function_name); | 1064 name = Field::SetterName(function_name); |
1065 super_class = FindSuperOwnerOfFunction(cls, name); | 1065 super_class = FindSuperOwnerOfFunction(cls, name); |
1066 if (!super_class.IsNull()) { | 1066 if (!super_class.IsNull()) { |
1067 const String& class_name = String::Handle(cls.Name()); | 1067 const String& class_name = String::Handle(cls.Name()); |
1068 const String& super_class_name = String::Handle(super_class.Name()); | 1068 const String& super_class_name = String::Handle(super_class.Name()); |
1069 const Script& script = Script::Handle(cls.script()); | 1069 const Script& script = Script::Handle(cls.script()); |
1070 ReportError(script, function.token_index(), | 1070 ReportError(script, function.token_pos(), |
1071 "function '%s' of class '%s' conflicts with " | 1071 "function '%s' of class '%s' conflicts with " |
1072 "setter '%s' of super class '%s'", | 1072 "setter '%s' of super class '%s'", |
1073 function_name.ToCString(), | 1073 function_name.ToCString(), |
1074 class_name.ToCString(), | 1074 class_name.ToCString(), |
1075 function_name.ToCString(), | 1075 function_name.ToCString(), |
1076 super_class_name.ToCString()); | 1076 super_class_name.ToCString()); |
1077 } | 1077 } |
1078 } | 1078 } |
1079 } | 1079 } |
1080 } | 1080 } |
1081 | 1081 |
1082 | 1082 |
1083 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { | 1083 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { |
1084 if (cls.is_finalized()) { | 1084 if (cls.is_finalized()) { |
1085 return; | 1085 return; |
1086 } | 1086 } |
1087 if (FLAG_trace_class_finalization) { | 1087 if (FLAG_trace_class_finalization) { |
1088 OS::Print("Finalize %s\n", cls.ToCString()); | 1088 OS::Print("Finalize %s\n", cls.ToCString()); |
1089 } | 1089 } |
1090 if (!IsSuperCycleFree(cls)) { | 1090 if (!IsSuperCycleFree(cls)) { |
1091 const String& name = String::Handle(cls.Name()); | 1091 const String& name = String::Handle(cls.Name()); |
1092 const Script& script = Script::Handle(cls.script()); | 1092 const Script& script = Script::Handle(cls.script()); |
1093 ReportError(script, cls.token_index(), | 1093 ReportError(script, cls.token_pos(), |
1094 "class '%s' has a cycle in its superclass relationship", | 1094 "class '%s' has a cycle in its superclass relationship", |
1095 name.ToCString()); | 1095 name.ToCString()); |
1096 } | 1096 } |
1097 GrowableArray<intptr_t> visited_interfaces; | 1097 GrowableArray<intptr_t> visited_interfaces; |
1098 ResolveInterfaces(cls, &visited_interfaces); | 1098 ResolveInterfaces(cls, &visited_interfaces); |
1099 // Finalize super class. | 1099 // Finalize super class. |
1100 const Class& super_class = Class::Handle(cls.SuperClass()); | 1100 const Class& super_class = Class::Handle(cls.SuperClass()); |
1101 if (!super_class.IsNull()) { | 1101 if (!super_class.IsNull()) { |
1102 FinalizeClass(super_class, generating_snapshot); | 1102 FinalizeClass(super_class, generating_snapshot); |
1103 } | 1103 } |
1104 // Finalize type parameters before finalizing the super type. | 1104 // Finalize type parameters before finalizing the super type. |
1105 FinalizeTypeParameters(cls); | 1105 FinalizeTypeParameters(cls); |
1106 // Finalize super type. | 1106 // Finalize super type. |
1107 Type& super_type = Type::Handle(cls.super_type()); | 1107 Type& super_type = Type::Handle(cls.super_type()); |
1108 if (!super_type.IsNull()) { | 1108 if (!super_type.IsNull()) { |
1109 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); | 1109 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); |
1110 cls.set_super_type(super_type); | 1110 cls.set_super_type(super_type); |
1111 } | 1111 } |
1112 // Signature classes are finalized upon creation, except function type | 1112 // Signature classes are finalized upon creation, except function type |
1113 // aliases. | 1113 // aliases. |
1114 if (cls.IsSignatureClass()) { | 1114 if (cls.IsSignatureClass()) { |
1115 ASSERT(!cls.IsCanonicalSignatureClass()); | 1115 ASSERT(!cls.IsCanonicalSignatureClass()); |
1116 // Check for illegal self references. | 1116 // Check for illegal self references. |
1117 GrowableArray<intptr_t> visited_aliases; | 1117 GrowableArray<intptr_t> visited_aliases; |
1118 if (!IsAliasCycleFree(cls, &visited_aliases)) { | 1118 if (!IsAliasCycleFree(cls, &visited_aliases)) { |
1119 const String& name = String::Handle(cls.Name()); | 1119 const String& name = String::Handle(cls.Name()); |
1120 const Script& script = Script::Handle(cls.script()); | 1120 const Script& script = Script::Handle(cls.script()); |
1121 ReportError(script, cls.token_index(), | 1121 ReportError(script, cls.token_pos(), |
1122 "typedef '%s' illegally refers to itself", | 1122 "typedef '%s' illegally refers to itself", |
1123 name.ToCString()); | 1123 name.ToCString()); |
1124 } | 1124 } |
1125 cls.Finalize(); | 1125 cls.Finalize(); |
1126 return; | 1126 return; |
1127 } | 1127 } |
1128 // Finalize factory class, if any. | 1128 // Finalize factory class, if any. |
1129 if (cls.is_interface()) { | 1129 if (cls.is_interface()) { |
1130 if (cls.HasFactoryClass()) { | 1130 if (cls.HasFactoryClass()) { |
1131 const Class& factory_class = Class::Handle(cls.FactoryClass()); | 1131 const Class& factory_class = Class::Handle(cls.FactoryClass()); |
(...skipping 24 matching lines...) Expand all Loading... |
1156 CheckForLegalConstClass(cls); | 1156 CheckForLegalConstClass(cls); |
1157 } | 1157 } |
1158 // Check to ensure we don't have classes with native fields in libraries | 1158 // Check to ensure we don't have classes with native fields in libraries |
1159 // which do not have a native resolver. | 1159 // which do not have a native resolver. |
1160 if (!generating_snapshot && cls.num_native_fields() != 0) { | 1160 if (!generating_snapshot && cls.num_native_fields() != 0) { |
1161 const Library& lib = Library::Handle(cls.library()); | 1161 const Library& lib = Library::Handle(cls.library()); |
1162 if (lib.native_entry_resolver() == NULL) { | 1162 if (lib.native_entry_resolver() == NULL) { |
1163 const String& cls_name = String::Handle(cls.Name()); | 1163 const String& cls_name = String::Handle(cls.Name()); |
1164 const String& lib_name = String::Handle(lib.url()); | 1164 const String& lib_name = String::Handle(lib.url()); |
1165 const Script& script = Script::Handle(cls.script()); | 1165 const Script& script = Script::Handle(cls.script()); |
1166 ReportError(script, cls.token_index(), | 1166 ReportError(script, cls.token_pos(), |
1167 "class '%s' is trying to extend a native fields class, " | 1167 "class '%s' is trying to extend a native fields class, " |
1168 "but library '%s' has no native resolvers", | 1168 "but library '%s' has no native resolvers", |
1169 cls_name.ToCString(), lib_name.ToCString()); | 1169 cls_name.ToCString(), lib_name.ToCString()); |
1170 } | 1170 } |
1171 } | 1171 } |
1172 } | 1172 } |
1173 | 1173 |
1174 | 1174 |
1175 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 1175 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
1176 Class& test1 = Class::Handle(cls.raw()); | 1176 Class& test1 = Class::Handle(cls.raw()); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 // we found a loop. | 1285 // we found a loop. |
1286 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1286 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
1287 GrowableArray<intptr_t>* visited) { | 1287 GrowableArray<intptr_t>* visited) { |
1288 ASSERT(visited != NULL); | 1288 ASSERT(visited != NULL); |
1289 const intptr_t cls_index = cls.id(); | 1289 const intptr_t cls_index = cls.id(); |
1290 for (int i = 0; i < visited->length(); i++) { | 1290 for (int i = 0; i < visited->length(); i++) { |
1291 if ((*visited)[i] == cls_index) { | 1291 if ((*visited)[i] == cls_index) { |
1292 // We have already visited interface class 'cls'. We found a cycle. | 1292 // We have already visited interface class 'cls'. We found a cycle. |
1293 const String& interface_name = String::Handle(cls.Name()); | 1293 const String& interface_name = String::Handle(cls.Name()); |
1294 const Script& script = Script::Handle(cls.script()); | 1294 const Script& script = Script::Handle(cls.script()); |
1295 ReportError(script, cls.token_index(), | 1295 ReportError(script, cls.token_pos(), |
1296 "cyclic reference found for interface '%s'", | 1296 "cyclic reference found for interface '%s'", |
1297 interface_name.ToCString()); | 1297 interface_name.ToCString()); |
1298 } | 1298 } |
1299 } | 1299 } |
1300 | 1300 |
1301 // If the class/interface has no explicit interfaces, we are done. | 1301 // If the class/interface has no explicit interfaces, we are done. |
1302 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1302 Array& super_interfaces = Array::Handle(cls.interfaces()); |
1303 if (super_interfaces.Length() == 0) { | 1303 if (super_interfaces.Length() == 0) { |
1304 return; | 1304 return; |
1305 } | 1305 } |
1306 | 1306 |
1307 // If cls belongs to core lib or to core lib's implementation, restrictions | 1307 // If cls belongs to core lib or to core lib's implementation, restrictions |
1308 // about allowed interfaces are lifted. | 1308 // about allowed interfaces are lifted. |
1309 const bool cls_belongs_to_core_lib = | 1309 const bool cls_belongs_to_core_lib = |
1310 (cls.library() == Library::CoreLibrary()) || | 1310 (cls.library() == Library::CoreLibrary()) || |
1311 (cls.library() == Library::CoreImplLibrary()); | 1311 (cls.library() == Library::CoreImplLibrary()); |
1312 | 1312 |
1313 // Resolve and check the interfaces of cls. | 1313 // Resolve and check the interfaces of cls. |
1314 visited->Add(cls_index); | 1314 visited->Add(cls_index); |
1315 AbstractType& interface = AbstractType::Handle(); | 1315 AbstractType& interface = AbstractType::Handle(); |
1316 Class& interface_class = Class::Handle(); | 1316 Class& interface_class = Class::Handle(); |
1317 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { | 1317 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { |
1318 interface ^= super_interfaces.At(i); | 1318 interface ^= super_interfaces.At(i); |
1319 ResolveType(cls, interface, kFinalizeWellFormed); | 1319 ResolveType(cls, interface, kFinalizeWellFormed); |
1320 if (interface.IsTypeParameter()) { | 1320 if (interface.IsTypeParameter()) { |
1321 const Script& script = Script::Handle(cls.script()); | 1321 const Script& script = Script::Handle(cls.script()); |
1322 ReportError(script, cls.token_index(), | 1322 ReportError(script, cls.token_pos(), |
1323 "type parameter '%s' cannot be used as interface", | 1323 "type parameter '%s' cannot be used as interface", |
1324 String::Handle(interface.Name()).ToCString()); | 1324 String::Handle(interface.Name()).ToCString()); |
1325 } | 1325 } |
1326 interface_class = interface.type_class(); | 1326 interface_class = interface.type_class(); |
1327 if (interface_class.IsSignatureClass()) { | 1327 if (interface_class.IsSignatureClass()) { |
1328 const Script& script = Script::Handle(cls.script()); | 1328 const Script& script = Script::Handle(cls.script()); |
1329 ReportError(script, cls.token_index(), | 1329 ReportError(script, cls.token_pos(), |
1330 "'%s' is used where an interface or class name is expected", | 1330 "'%s' is used where an interface or class name is expected", |
1331 String::Handle(interface_class.Name()).ToCString()); | 1331 String::Handle(interface_class.Name()).ToCString()); |
1332 } | 1332 } |
1333 // Verify that unless cls belongs to core lib, it cannot extend or implement | 1333 // Verify that unless cls belongs to core lib, it cannot extend or implement |
1334 // any of bool, num, int, double, String, Function, Dynamic. | 1334 // any of bool, num, int, double, String, Function, Dynamic. |
1335 // The exception is signature classes, which are compiler generated and | 1335 // The exception is signature classes, which are compiler generated and |
1336 // represent a function type, therefore implementing the Function interface. | 1336 // represent a function type, therefore implementing the Function interface. |
1337 if (!cls_belongs_to_core_lib) { | 1337 if (!cls_belongs_to_core_lib) { |
1338 if (interface.IsBoolInterface() || | 1338 if (interface.IsBoolInterface() || |
1339 interface.IsNumberInterface() || | 1339 interface.IsNumberInterface() || |
1340 interface.IsIntInterface() || | 1340 interface.IsIntInterface() || |
1341 interface.IsDoubleInterface() || | 1341 interface.IsDoubleInterface() || |
1342 interface.IsStringInterface() || | 1342 interface.IsStringInterface() || |
1343 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || | 1343 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || |
1344 interface.IsDynamicType()) { | 1344 interface.IsDynamicType()) { |
1345 const Script& script = Script::Handle(cls.script()); | 1345 const Script& script = Script::Handle(cls.script()); |
1346 ReportError(script, cls.token_index(), | 1346 ReportError(script, cls.token_pos(), |
1347 "'%s' is not allowed to extend or implement '%s'", | 1347 "'%s' is not allowed to extend or implement '%s'", |
1348 String::Handle(cls.Name()).ToCString(), | 1348 String::Handle(cls.Name()).ToCString(), |
1349 String::Handle(interface_class.Name()).ToCString()); | 1349 String::Handle(interface_class.Name()).ToCString()); |
1350 } | 1350 } |
1351 } | 1351 } |
1352 // Now resolve the super interfaces. | 1352 // Now resolve the super interfaces. |
1353 ResolveInterfaces(interface_class, visited); | 1353 ResolveInterfaces(interface_class, visited); |
1354 } | 1354 } |
1355 visited->RemoveLast(); | 1355 visited->RemoveLast(); |
1356 } | 1356 } |
1357 | 1357 |
1358 | 1358 |
1359 // A class is marked as constant if it has one constant constructor. | 1359 // A class is marked as constant if it has one constant constructor. |
1360 // A constant class: | 1360 // A constant class: |
1361 // - may extend only const classes. | 1361 // - may extend only const classes. |
1362 // - has only const instance fields. | 1362 // - has only const instance fields. |
1363 // Note: we must check for cycles before checking for const properties. | 1363 // Note: we must check for cycles before checking for const properties. |
1364 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 1364 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
1365 ASSERT(cls.is_const()); | 1365 ASSERT(cls.is_const()); |
1366 const Class& super = Class::Handle(cls.SuperClass()); | 1366 const Class& super = Class::Handle(cls.SuperClass()); |
1367 if (!super.IsNull() && !super.is_const()) { | 1367 if (!super.IsNull() && !super.is_const()) { |
1368 String& name = String::Handle(super.Name()); | 1368 String& name = String::Handle(super.Name()); |
1369 const Script& script = Script::Handle(cls.script()); | 1369 const Script& script = Script::Handle(cls.script()); |
1370 ReportError(script, cls.token_index(), | 1370 ReportError(script, cls.token_pos(), |
1371 "superclass '%s' must be const", name.ToCString()); | 1371 "superclass '%s' must be const", name.ToCString()); |
1372 } | 1372 } |
1373 const Array& fields_array = Array::Handle(cls.fields()); | 1373 const Array& fields_array = Array::Handle(cls.fields()); |
1374 intptr_t len = fields_array.Length(); | 1374 intptr_t len = fields_array.Length(); |
1375 Field& field = Field::Handle(); | 1375 Field& field = Field::Handle(); |
1376 for (intptr_t i = 0; i < len; i++) { | 1376 for (intptr_t i = 0; i < len; i++) { |
1377 field ^= fields_array.At(i); | 1377 field ^= fields_array.At(i); |
1378 if (!field.is_static() && !field.is_final()) { | 1378 if (!field.is_static() && !field.is_final()) { |
1379 const String& class_name = String::Handle(cls.Name()); | 1379 const String& class_name = String::Handle(cls.Name()); |
1380 const String& field_name = String::Handle(field.name()); | 1380 const String& field_name = String::Handle(field.name()); |
1381 const Script& script = Script::Handle(cls.script()); | 1381 const Script& script = Script::Handle(cls.script()); |
1382 ReportError(script, field.token_index(), | 1382 ReportError(script, field.token_pos(), |
1383 "const class '%s' has non-final field '%s'", | 1383 "const class '%s' has non-final field '%s'", |
1384 class_name.ToCString(), field_name.ToCString()); | 1384 class_name.ToCString(), field_name.ToCString()); |
1385 } | 1385 } |
1386 } | 1386 } |
1387 } | 1387 } |
1388 | 1388 |
1389 | 1389 |
1390 void ClassFinalizer::PrintClassInformation(const Class& cls) { | 1390 void ClassFinalizer::PrintClassInformation(const Class& cls) { |
1391 HANDLESCOPE(Isolate::Current()); | 1391 HANDLESCOPE(Isolate::Current()); |
1392 const String& class_name = String::Handle(cls.Name()); | 1392 const String& class_name = String::Handle(cls.Name()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1443 const char* format, ...) { | 1443 const char* format, ...) { |
1444 va_list args; | 1444 va_list args; |
1445 va_start(args, format); | 1445 va_start(args, format); |
1446 LanguageError& error = LanguageError::Handle(); | 1446 LanguageError& error = LanguageError::Handle(); |
1447 if (FLAG_enable_type_checks || | 1447 if (FLAG_enable_type_checks || |
1448 !type.HasResolvedTypeClass() || | 1448 !type.HasResolvedTypeClass() || |
1449 (finalization == kFinalizeWellFormed)) { | 1449 (finalization == kFinalizeWellFormed)) { |
1450 const Script& script = Script::Handle(cls.script()); | 1450 const Script& script = Script::Handle(cls.script()); |
1451 if (prev_error.IsNull()) { | 1451 if (prev_error.IsNull()) { |
1452 error ^= Parser::FormatError( | 1452 error ^= Parser::FormatError( |
1453 script, type.token_index(), "Error", format, args); | 1453 script, type.token_pos(), "Error", format, args); |
1454 } else { | 1454 } else { |
1455 error ^= Parser::FormatErrorWithAppend( | 1455 error ^= Parser::FormatErrorWithAppend( |
1456 prev_error, script, type.token_index(), "Error", format, args); | 1456 prev_error, script, type.token_pos(), "Error", format, args); |
1457 } | 1457 } |
1458 if (finalization == kFinalizeWellFormed) { | 1458 if (finalization == kFinalizeWellFormed) { |
1459 ReportError(error); | 1459 ReportError(error); |
1460 } | 1460 } |
1461 } | 1461 } |
1462 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { | 1462 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
1463 // In check mode, always mark the type as malformed. | 1463 // In check mode, always mark the type as malformed. |
1464 // In production mode, mark the type as malformed only if its type class is | 1464 // In production mode, mark the type as malformed only if its type class is |
1465 // not resolved. | 1465 // not resolved. |
1466 type.set_malformed_error(error); | 1466 type.set_malformed_error(error); |
(...skipping 14 matching lines...) Expand all Loading... |
1481 } | 1481 } |
1482 | 1482 |
1483 | 1483 |
1484 void ClassFinalizer::ReportError(const Error& error) { | 1484 void ClassFinalizer::ReportError(const Error& error) { |
1485 Isolate::Current()->long_jump_base()->Jump(1, error); | 1485 Isolate::Current()->long_jump_base()->Jump(1, error); |
1486 UNREACHABLE(); | 1486 UNREACHABLE(); |
1487 } | 1487 } |
1488 | 1488 |
1489 | 1489 |
1490 void ClassFinalizer::ReportError(const Script& script, | 1490 void ClassFinalizer::ReportError(const Script& script, |
1491 intptr_t token_index, | 1491 intptr_t token_pos, |
1492 const char* format, ...) { | 1492 const char* format, ...) { |
1493 va_list args; | 1493 va_list args; |
1494 va_start(args, format); | 1494 va_start(args, format); |
1495 const Error& error = Error::Handle( | 1495 const Error& error = Error::Handle( |
1496 Parser::FormatError(script, token_index, "Error", format, args)); | 1496 Parser::FormatError(script, token_pos, "Error", format, args)); |
1497 ReportError(error); | 1497 ReportError(error); |
1498 } | 1498 } |
1499 | 1499 |
1500 | 1500 |
1501 void ClassFinalizer::ReportError(const char* format, ...) { | 1501 void ClassFinalizer::ReportError(const char* format, ...) { |
1502 va_list args; | 1502 va_list args; |
1503 va_start(args, format); | 1503 va_start(args, format); |
1504 const Error& error = Error::Handle( | 1504 const Error& error = Error::Handle( |
1505 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1505 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1506 va_end(args); | 1506 va_end(args); |
1507 ReportError(error); | 1507 ReportError(error); |
1508 } | 1508 } |
1509 | 1509 |
1510 } // namespace dart | 1510 } // namespace dart |
OLD | NEW |