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