| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 const intptr_t num_parameters = function.NumberOfParameters(); | 553 const intptr_t num_parameters = function.NumberOfParameters(); |
| 554 for (intptr_t i = 0; i < num_parameters; i++) { | 554 for (intptr_t i = 0; i < num_parameters; i++) { |
| 555 type = function.ParameterTypeAt(i); | 555 type = function.ParameterTypeAt(i); |
| 556 type = ResolveType(cls, type); | 556 type = ResolveType(cls, type); |
| 557 function.SetParameterTypeAt(i, type); | 557 function.SetParameterTypeAt(i, type); |
| 558 FinalizeType(type); | 558 FinalizeType(type); |
| 559 } | 559 } |
| 560 } | 560 } |
| 561 | 561 |
| 562 | 562 |
| 563 static bool FuncNameExistsInSuper(const Class& cls, | 563 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls, |
| 564 const String& name) { | 564 const String& name) { |
| 565 Class& super_class = Class::Handle(); |
| 566 Function& function = Function::Handle(); |
| 567 Field& field = Field::Handle(); |
| 568 super_class = cls.SuperClass(); |
| 569 while (!super_class.IsNull()) { |
| 570 // Check if an instance member of same name exists in any super class. |
| 571 function = super_class.LookupFunction(name); |
| 572 if (!function.IsNull() && !function.is_static()) { |
| 573 return super_class.raw(); |
| 574 } |
| 575 field = super_class.LookupField(name); |
| 576 if (!field.IsNull() && !field.is_static()) { |
| 577 return super_class.raw(); |
| 578 } |
| 579 super_class = super_class.SuperClass(); |
| 580 } |
| 581 return Class::null(); |
| 582 } |
| 583 |
| 584 |
| 585 static RawClass* FindSuperOwnerOfFunction(const Class& cls, |
| 586 const String& name) { |
| 565 Class& super_class = Class::Handle(); | 587 Class& super_class = Class::Handle(); |
| 566 Function& function = Function::Handle(); | 588 Function& function = Function::Handle(); |
| 567 super_class = cls.SuperClass(); | 589 super_class = cls.SuperClass(); |
| 568 while (!super_class.IsNull()) { | 590 while (!super_class.IsNull()) { |
| 569 // Check if a field of same name exists in any super class. | 591 // Check if a function of same name exists in any super class. |
| 570 function = super_class.LookupFunction(name); | 592 function = super_class.LookupFunction(name); |
| 571 if (!function.IsNull()) { | 593 if (!function.IsNull()) { |
| 572 return true; | 594 return super_class.raw(); |
| 573 } | 595 } |
| 574 super_class = super_class.SuperClass(); | 596 super_class = super_class.SuperClass(); |
| 575 } | 597 } |
| 576 return false; | 598 return Class::null(); |
| 577 } | |
| 578 | |
| 579 | |
| 580 static bool FieldNameExistsInSuper(const Class& cls, const String& name) { | |
| 581 Class& super_class = Class::Handle(); | |
| 582 Field& field = Field::Handle(); | |
| 583 super_class = cls.SuperClass(); | |
| 584 while (!super_class.IsNull()) { | |
| 585 // Check if a function of same name exists in any super class. | |
| 586 field = super_class.LookupField(name); | |
| 587 if (!field.IsNull()) { | |
| 588 return true; | |
| 589 } | |
| 590 super_class = super_class.SuperClass(); | |
| 591 } | |
| 592 return false; | |
| 593 } | 599 } |
| 594 | 600 |
| 595 | 601 |
| 596 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { | 602 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
| 597 // Resolve type of fields. | 603 // Note that getters and setters are explicitly listed as such in the list of |
| 604 // functions of a class, so we do not need to consider fields as implicitly |
| 605 // generating getters and setters. |
| 606 // The only compile errors we report are therefore: |
| 607 // - a getter having the same name as a method (but not a getter) in a super |
| 608 // class or in a subclass. |
| 609 // - a setter having the same name as a method (but not a setter) in a super |
| 610 // class or in a subclass. |
| 611 // - a static field, instance field, or static method (but not an instance |
| 612 // method) having the same name as an instance member in a super class. |
| 613 |
| 614 // Resolve type of fields and check for conflicts in super classes. |
| 598 Array& array = Array::Handle(cls.fields()); | 615 Array& array = Array::Handle(cls.fields()); |
| 599 Field& field = Field::Handle(); | 616 Field& field = Field::Handle(); |
| 600 Type& type = Type::Handle(); | 617 Type& type = Type::Handle(); |
| 618 String& name = String::Handle(); |
| 619 Class& super_class = Class::Handle(); |
| 601 intptr_t num_fields = array.Length(); | 620 intptr_t num_fields = array.Length(); |
| 602 String& name = String::Handle(); | |
| 603 for (intptr_t i = 0; i < num_fields; i++) { | 621 for (intptr_t i = 0; i < num_fields; i++) { |
| 604 field ^= array.At(i); | 622 field ^= array.At(i); |
| 605 type = field.type(); | 623 type = field.type(); |
| 606 type = ResolveType(cls, type); | 624 type = ResolveType(cls, type); |
| 607 field.set_type(type); | 625 field.set_type(type); |
| 608 FinalizeType(type); | 626 FinalizeType(type); |
| 609 name = field.name(); | 627 name = field.name(); |
| 610 if (FuncNameExistsInSuper(cls, name)) { | 628 super_class = FindSuperOwnerOfInstanceMember(cls, name); |
| 611 ReportError("field '%s' overrides a function in the super class.\n", | 629 if (!super_class.IsNull()) { |
| 612 name.ToCString()); | 630 const String& class_name = String::Handle(cls.Name()); |
| 631 const String& super_class_name = String::Handle(super_class.Name()); |
| 632 ReportError("field '%s' of class '%s' conflicts with instance " |
| 633 "member '%s' of super class '%s'.\n", |
| 634 name.ToCString(), |
| 635 class_name.ToCString(), |
| 636 name.ToCString(), |
| 637 super_class_name.ToCString()); |
| 613 } | 638 } |
| 614 } | 639 } |
| 615 // Resolve function signatures. | 640 // Resolve function signatures and check for conflicts in super classes. |
| 616 array = cls.functions(); | 641 array = cls.functions(); |
| 617 Function& function = Function::Handle(); | 642 Function& function = Function::Handle(); |
| 643 Function& overridden_function = Function::Handle(); |
| 618 intptr_t num_functions = array.Length(); | 644 intptr_t num_functions = array.Length(); |
| 619 String& func_name = String::Handle(); | 645 String& function_name = String::Handle(); |
| 620 for (intptr_t i = 0; i < num_functions; i++) { | 646 for (intptr_t i = 0; i < num_functions; i++) { |
| 621 function ^= array.At(i); | 647 function ^= array.At(i); |
| 622 ResolveAndFinalizeSignature(cls, function); | 648 ResolveAndFinalizeSignature(cls, function); |
| 623 func_name = function.name(); | 649 function_name = function.name(); |
| 624 if (FieldNameExistsInSuper(cls, func_name)) { | 650 if (function.is_static()) { |
| 625 ReportError("function '%s' overrides a field in the super class.\n", | 651 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); |
| 626 func_name.ToCString()); | 652 if (!super_class.IsNull()) { |
| 627 } | 653 const String& class_name = String::Handle(cls.Name()); |
| 628 name = Field::GetterName(func_name); | 654 const String& super_class_name = String::Handle(super_class.Name()); |
| 629 if (FuncNameExistsInSuper(cls, name)) { | 655 ReportError("static function '%s' of class '%s' conflicts with " |
| 630 ReportError("function '%s' overrides a getter in the super class.\n", | 656 "instance member '%s' of super class '%s'.\n", |
| 631 name.ToCString()); | 657 function_name.ToCString(), |
| 632 } | 658 class_name.ToCString(), |
| 633 name = Field::SetterName(func_name); | 659 function_name.ToCString(), |
| 634 if (FuncNameExistsInSuper(cls, name)) { | 660 super_class_name.ToCString()); |
| 635 ReportError("function '%s' overrides a setter in the super class.\n", | 661 } |
| 636 name.ToCString()); | 662 } else { |
| 663 // TODO(regis): This arity check is still being debated. Revisit. |
| 664 super_class = cls.SuperClass(); |
| 665 while (!super_class.IsNull()) { |
| 666 overridden_function = super_class.LookupDynamicFunction(function_name); |
| 667 if (!overridden_function.IsNull() && |
| 668 !function.HasCompatibleParametersWith(overridden_function)) { |
| 669 // Function types are purposely not checked for subtyping. |
| 670 const String& class_name = String::Handle(cls.Name()); |
| 671 const String& super_class_name = String::Handle(super_class.Name()); |
| 672 ReportError("class '%s' overrides function '%s' of super class '%s' " |
| 673 "with incompatible parameters.\n", |
| 674 class_name.ToCString(), |
| 675 function_name.ToCString(), |
| 676 super_class_name.ToCString()); |
| 677 } |
| 678 super_class = super_class.SuperClass(); |
| 679 } |
| 637 } | 680 } |
| 638 if (function.kind() == RawFunction::kGetterFunction) { | 681 if (function.kind() == RawFunction::kGetterFunction) { |
| 639 name = String::New("get:"); | 682 name = Field::NameFromGetter(function_name); |
| 640 name = String::SubString(func_name, name.Length()); | 683 super_class = FindSuperOwnerOfFunction(cls, name); |
| 641 if (FuncNameExistsInSuper(cls, name)) { | 684 if (!super_class.IsNull()) { |
| 642 ReportError("'%s' overrides a function in the super class.\n", | 685 const String& class_name = String::Handle(cls.Name()); |
| 643 func_name.ToCString()); | 686 const String& super_class_name = String::Handle(super_class.Name()); |
| 687 ReportError("getter '%s' of class '%s' conflicts with " |
| 688 "function '%s' of super class '%s'.\n", |
| 689 name.ToCString(), |
| 690 class_name.ToCString(), |
| 691 name.ToCString(), |
| 692 super_class_name.ToCString()); |
| 644 } | 693 } |
| 645 } | 694 } else if (function.kind() == RawFunction::kSetterFunction) { |
| 646 if (function.kind() == RawFunction::kSetterFunction) { | 695 name = Field::NameFromSetter(function_name); |
| 647 name = String::New("set:"); | 696 super_class = FindSuperOwnerOfFunction(cls, name); |
| 648 name = String::SubString(func_name, name.Length()); | 697 if (!super_class.IsNull()) { |
| 649 if (FuncNameExistsInSuper(cls, name)) { | 698 const String& class_name = String::Handle(cls.Name()); |
| 650 ReportError("'%s' overrides a function in the super class.\n", | 699 const String& super_class_name = String::Handle(super_class.Name()); |
| 651 func_name.ToCString()); | 700 ReportError("setter '%s' of class '%s' conflicts with " |
| 701 "function '%s' of super class '%s'.\n", |
| 702 name.ToCString(), |
| 703 class_name.ToCString(), |
| 704 name.ToCString(), |
| 705 super_class_name.ToCString()); |
| 706 } |
| 707 } else { |
| 708 name = Field::GetterName(function_name); |
| 709 super_class = FindSuperOwnerOfFunction(cls, name); |
| 710 if (!super_class.IsNull()) { |
| 711 const String& class_name = String::Handle(cls.Name()); |
| 712 const String& super_class_name = String::Handle(super_class.Name()); |
| 713 ReportError("function '%s' of class '%s' conflicts with " |
| 714 "getter '%s' of super class '%s'.\n", |
| 715 function_name.ToCString(), |
| 716 class_name.ToCString(), |
| 717 function_name.ToCString(), |
| 718 super_class_name.ToCString()); |
| 719 } |
| 720 name = Field::SetterName(function_name); |
| 721 super_class = FindSuperOwnerOfFunction(cls, name); |
| 722 if (!super_class.IsNull()) { |
| 723 const String& class_name = String::Handle(cls.Name()); |
| 724 const String& super_class_name = String::Handle(super_class.Name()); |
| 725 ReportError("function '%s' of class '%s' conflicts with " |
| 726 "setter '%s' of super class '%s'.\n", |
| 727 function_name.ToCString(), |
| 728 class_name.ToCString(), |
| 729 function_name.ToCString(), |
| 730 super_class_name.ToCString()); |
| 652 } | 731 } |
| 653 } | 732 } |
| 654 } | 733 } |
| 655 // Resolve the signature type if this class is a signature class. | 734 // Resolve the signature type if this class is a signature class. |
| 656 if (cls.IsSignatureClass()) { | 735 if (cls.IsSignatureClass()) { |
| 657 const Type& signature_type = Type::Handle(cls.SignatureType()); | 736 const Type& signature_type = Type::Handle(cls.SignatureType()); |
| 658 FinalizeType(signature_type); | 737 FinalizeType(signature_type); |
| 659 } | 738 } |
| 660 } | 739 } |
| 661 | 740 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 Array& interface_types = Array::Handle(cls.interfaces()); | 779 Array& interface_types = Array::Handle(cls.interfaces()); |
| 701 Type& interface_type = Type::Handle(); | 780 Type& interface_type = Type::Handle(); |
| 702 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 781 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
| 703 interface_type ^= interface_types.At(i); | 782 interface_type ^= interface_types.At(i); |
| 704 FinalizeType(interface_type); | 783 FinalizeType(interface_type); |
| 705 } | 784 } |
| 706 // Mark as finalized before resolving member types in order to break cycles. | 785 // Mark as finalized before resolving member types in order to break cycles. |
| 707 cls.Finalize(); | 786 cls.Finalize(); |
| 708 ResolveAndFinalizeMemberTypes(cls); | 787 ResolveAndFinalizeMemberTypes(cls); |
| 709 // Run additional checks after all types are finalized. | 788 // Run additional checks after all types are finalized. |
| 710 if (!cls.is_interface()) { | |
| 711 CheckForLegalOverrides(cls); | |
| 712 } | |
| 713 if (cls.is_const()) { | 789 if (cls.is_const()) { |
| 714 CheckForLegalConstClass(cls); | 790 CheckForLegalConstClass(cls); |
| 715 } | 791 } |
| 716 } | 792 } |
| 717 | 793 |
| 718 | 794 |
| 719 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 795 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
| 720 Class& test1 = Class::Handle(cls.raw()); | 796 Class& test1 = Class::Handle(cls.raw()); |
| 721 Class& test2 = Class::Handle(cls.SuperClass()); | 797 Class& test2 = Class::Handle(cls.SuperClass()); |
| 722 // A finalized class has been checked for cycles. | 798 // A finalized class has been checked for cycles. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 // TODO(regis): Verify that unless cls is in core lib, it cannot implement | 893 // TODO(regis): Verify that unless cls is in core lib, it cannot implement |
| 818 // an instance of Number or String. Any other? bool? | 894 // an instance of Number or String. Any other? bool? |
| 819 | 895 |
| 820 // Now resolve the super interfaces. | 896 // Now resolve the super interfaces. |
| 821 ResolveInterfaces(interface_class, visited); | 897 ResolveInterfaces(interface_class, visited); |
| 822 } | 898 } |
| 823 visited->RemoveLast(); | 899 visited->RemoveLast(); |
| 824 } | 900 } |
| 825 | 901 |
| 826 | 902 |
| 827 void ClassFinalizer::CheckForLegalOverrides(const Class& cls) { | |
| 828 HANDLESCOPE(); | |
| 829 const Class& super = Class::Handle(cls.SuperClass()); | |
| 830 if (super.IsNull()) { | |
| 831 return; | |
| 832 } | |
| 833 if (FLAG_enable_type_checks) { | |
| 834 // Check functions. | |
| 835 const Array& functions_array = Array::Handle(cls.functions()); | |
| 836 Function& function = Function::Handle(); | |
| 837 String& function_name = String::Handle(); | |
| 838 const intptr_t len = functions_array.Length(); | |
| 839 for (intptr_t i = 0; i < len; i++) { | |
| 840 function ^= functions_array.At(i); | |
| 841 if (!function.is_static()) { | |
| 842 function_name ^= function.name(); | |
| 843 Function& overridden_function = | |
| 844 Function::Handle(super.LookupDynamicFunction(function_name)); | |
| 845 if (!overridden_function.IsNull() && | |
| 846 !function.IsSubtypeOf(overridden_function)) { | |
| 847 const String& class_name = String::Handle(cls.Name()); | |
| 848 const String& super_class_name = String::Handle( | |
| 849 Class::Handle(overridden_function.owner()).Name()); | |
| 850 ReportError("The type of instance method '%s' in class '%s' is " | |
| 851 "not a subtype of the type of overriden instance " | |
| 852 "method '%s' in class '%s'\n", | |
| 853 function_name.ToCString(), | |
| 854 class_name.ToCString(), | |
| 855 function_name.ToCString(), | |
| 856 super_class_name.ToCString()); | |
| 857 } | |
| 858 } | |
| 859 } | |
| 860 } | |
| 861 // Check fields. | |
| 862 const Array& fields_array = Array::Handle(cls.fields()); | |
| 863 Field& field = Field::Handle(); | |
| 864 String& field_name = String::Handle(); | |
| 865 const intptr_t len = fields_array.Length(); | |
| 866 for (intptr_t i = 0; i < len; i++) { | |
| 867 field ^= fields_array.At(i); | |
| 868 field_name ^= field.name(); | |
| 869 Field& super_field = Field::Handle(super.LookupStaticField(field_name)); | |
| 870 if (super_field.IsNull()) { | |
| 871 super_field = super.LookupInstanceField(field_name); | |
| 872 } | |
| 873 if (!super_field.IsNull()) { | |
| 874 // A static field may "override" a static field. | |
| 875 if (!super_field.is_static() || !field.is_static()) { | |
| 876 const String& class_name = String::Handle(cls.Name()); | |
| 877 ReportError("class '%s' cannot override field '%s'.\n", | |
| 878 class_name.ToCString(), field_name.ToCString()); | |
| 879 } | |
| 880 } | |
| 881 } | |
| 882 } | |
| 883 | |
| 884 | |
| 885 // A class is marked as constant if it has one constant constructor. | 903 // A class is marked as constant if it has one constant constructor. |
| 886 // A constant class: | 904 // A constant class: |
| 887 // - may extend only const classes. | 905 // - may extend only const classes. |
| 888 // - has only const instance fields. | 906 // - has only const instance fields. |
| 889 // Note: we must check for cycles before checking for const properties. | 907 // Note: we must check for cycles before checking for const properties. |
| 890 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 908 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
| 891 ASSERT(cls.is_const()); | 909 ASSERT(cls.is_const()); |
| 892 const Class& super = Class::Handle(cls.SuperClass()); | 910 const Class& super = Class::Handle(cls.SuperClass()); |
| 893 if (!super.IsNull() && !super.is_const()) { | 911 if (!super.IsNull() && !super.is_const()) { |
| 894 String& name = String::Handle(super.Name()); | 912 String& name = String::Handle(super.Name()); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 ASSERT(msg_buffer != NULL); | 1010 ASSERT(msg_buffer != NULL); |
| 993 va_list args; | 1011 va_list args; |
| 994 va_start(args, format); | 1012 va_start(args, format); |
| 995 OS::VSNPrint(msg_buffer, kBufferLength, format, args); | 1013 OS::VSNPrint(msg_buffer, kBufferLength, format, args); |
| 996 va_end(args); | 1014 va_end(args); |
| 997 isolate->long_jump_base()->Jump(1, msg_buffer); | 1015 isolate->long_jump_base()->Jump(1, msg_buffer); |
| 998 UNREACHABLE(); | 1016 UNREACHABLE(); |
| 999 } | 1017 } |
| 1000 | 1018 |
| 1001 } // namespace dart | 1019 } // namespace dart |
| OLD | NEW |