Chromium Code Reviews| 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/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 2719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2730 return (!function.IsNull() && (function.signature_class() == raw())); | 2730 return (!function.IsNull() && (function.signature_class() == raw())); |
| 2731 } | 2731 } |
| 2732 | 2732 |
| 2733 | 2733 |
| 2734 // If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T. | 2734 // If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T. |
| 2735 // If test_kind == kIsMoreSpecificThan, checks if S is more specific than T. | 2735 // If test_kind == kIsMoreSpecificThan, checks if S is more specific than T. |
| 2736 // Type S is specified by this class parameterized with 'type_arguments', and | 2736 // Type S is specified by this class parameterized with 'type_arguments', and |
| 2737 // type T by class 'other' parameterized with 'other_type_arguments'. | 2737 // type T by class 'other' parameterized with 'other_type_arguments'. |
| 2738 // This class and class 'other' do not need to be finalized, however, they must | 2738 // This class and class 'other' do not need to be finalized, however, they must |
| 2739 // be resolved as well as their interfaces. | 2739 // be resolved as well as their interfaces. |
| 2740 bool Class::TypeTestNonRecursive( | |
|
regis
2013/11/05 18:17:40
Why do you need a new function that is forwarded t
| |
| 2741 const Class& cls, | |
| 2742 Class::TypeTestKind test_kind, | |
| 2743 const AbstractTypeArguments& type_arguments, | |
| 2744 const Class& other, | |
| 2745 const AbstractTypeArguments& other_type_arguments, | |
| 2746 Error* bound_error) { | |
| 2747 // Use the thsi object as if it was the receiver of this method, but instead | |
| 2748 // of recursing reset it to the super class and loop. | |
| 2749 Class& thsi = Class::Handle(cls.raw()); | |
| 2750 while (true) { | |
| 2751 ASSERT(!thsi.IsVoidClass()); | |
|
Ivan Posva
2013/11/05 04:48:29
The contents of this loop is what was being done a
| |
| 2752 // Check for DynamicType. | |
| 2753 // Each occurrence of DynamicType in type T is interpreted as the dynamic | |
| 2754 // type, a supertype of all types. | |
| 2755 if (other.IsDynamicClass()) { | |
| 2756 return true; | |
| 2757 } | |
| 2758 // In the case of a subtype test, each occurrence of DynamicType in type S | |
| 2759 // is interpreted as the bottom type, a subtype of all types. | |
| 2760 // However, DynamicType is not more specific than any type. | |
| 2761 if (thsi.IsDynamicClass()) { | |
| 2762 return test_kind == Class::kIsSubtypeOf; | |
| 2763 } | |
| 2764 // Check for NullType, which is only a subtype of ObjectType, of | |
| 2765 // DynamicType, or of itself, and which is more specific than any type. | |
| 2766 if (thsi.IsNullClass()) { | |
| 2767 // We already checked for other.IsDynamicClass() above. | |
| 2768 return (test_kind == Class::kIsMoreSpecificThan) || | |
| 2769 other.IsObjectClass() || other.IsNullClass(); | |
| 2770 } | |
| 2771 // Check for ObjectType. Any type that is not NullType or DynamicType | |
| 2772 // (already checked above), is more specific than ObjectType. | |
| 2773 if (other.IsObjectClass()) { | |
| 2774 return true; | |
| 2775 } | |
| 2776 // Check for reflexivity. | |
| 2777 if (thsi.raw() == other.raw()) { | |
| 2778 const intptr_t len = thsi.NumTypeArguments(); | |
| 2779 if (len == 0) { | |
| 2780 return true; | |
| 2781 } | |
| 2782 // Since we do not truncate the type argument vector of a subclass (see | |
| 2783 // below), we only check a prefix of the proper length. | |
| 2784 // Check for covariance. | |
| 2785 if (other_type_arguments.IsNull() || other_type_arguments.IsRaw(len)) { | |
| 2786 return true; | |
| 2787 } | |
| 2788 if (type_arguments.IsNull() || type_arguments.IsRaw(len)) { | |
| 2789 // Other type can't be more specific than this one because for that | |
| 2790 // it would have to have all dynamic type arguments which is checked | |
| 2791 // above. | |
| 2792 return test_kind == Class::kIsSubtypeOf; | |
| 2793 } | |
| 2794 return type_arguments.TypeTest(test_kind, | |
| 2795 other_type_arguments, | |
| 2796 len, | |
| 2797 bound_error); | |
| 2798 } | |
| 2799 const bool other_is_function_class = other.IsFunctionClass(); | |
| 2800 if (other.IsSignatureClass() || other_is_function_class) { | |
| 2801 const Function& other_fun = Function::Handle(other.signature_function()); | |
| 2802 if (thsi.IsSignatureClass()) { | |
| 2803 if (other_is_function_class) { | |
| 2804 return true; | |
| 2805 } | |
| 2806 // Check for two function types. | |
| 2807 const Function& fun = Function::Handle(thsi.signature_function()); | |
| 2808 return fun.TypeTest(test_kind, | |
| 2809 type_arguments, | |
| 2810 other_fun, | |
| 2811 other_type_arguments, | |
| 2812 bound_error); | |
| 2813 } | |
| 2814 // Check if type S has a call() method of function type T. | |
| 2815 Function& function = | |
| 2816 Function::Handle(thsi.LookupDynamicFunction(Symbols::Call())); | |
| 2817 if (function.IsNull()) { | |
| 2818 // Walk up the super_class chain. | |
| 2819 Class& cls = Class::Handle(thsi.SuperClass()); | |
| 2820 while (!cls.IsNull() && function.IsNull()) { | |
| 2821 function = cls.LookupDynamicFunction(Symbols::Call()); | |
| 2822 cls = cls.SuperClass(); | |
| 2823 } | |
| 2824 } | |
| 2825 if (!function.IsNull()) { | |
| 2826 if (other_is_function_class || | |
| 2827 function.TypeTest(test_kind, | |
| 2828 type_arguments, | |
| 2829 other_fun, | |
| 2830 other_type_arguments, | |
| 2831 bound_error)) { | |
| 2832 return true; | |
| 2833 } | |
| 2834 } | |
| 2835 } | |
| 2836 // Check for 'direct super type' specified in the implements clause | |
| 2837 // and check for transitivity at the same time. | |
| 2838 Array& interfaces = Array::Handle(thsi.interfaces()); | |
| 2839 AbstractType& interface = AbstractType::Handle(); | |
| 2840 Class& interface_class = Class::Handle(); | |
| 2841 AbstractTypeArguments& interface_args = AbstractTypeArguments::Handle(); | |
| 2842 Error& error = Error::Handle(); | |
| 2843 for (intptr_t i = 0; i < interfaces.Length(); i++) { | |
| 2844 interface ^= interfaces.At(i); | |
| 2845 if (!interface.IsFinalized()) { | |
| 2846 // We may be checking bounds at finalization time. Skipping this | |
| 2847 // unfinalized interface will postpone bound checking to run time. | |
| 2848 continue; | |
| 2849 } | |
| 2850 error = Error::null(); | |
| 2851 if (interface.IsMalboundedWithError(&error)) { | |
| 2852 // Return the first bound error to the caller if it requests it. | |
| 2853 if ((bound_error != NULL) && bound_error->IsNull()) { | |
| 2854 ASSERT(!error.IsNull()); | |
| 2855 *bound_error = error.raw(); | |
| 2856 } | |
| 2857 continue; // Another interface may work better. | |
| 2858 } | |
| 2859 interface_class = interface.type_class(); | |
| 2860 interface_args = interface.arguments(); | |
| 2861 if (!interface_args.IsNull() && !interface_args.IsInstantiated()) { | |
| 2862 // This type class implements an interface that is parameterized with | |
| 2863 // generic type(s), e.g. it implements List<T>. | |
| 2864 // The uninstantiated type T must be instantiated using the type | |
| 2865 // parameters of this type before performing the type test. | |
| 2866 // The type arguments of this type that are referred to by the type | |
| 2867 // parameters of the interface are at the end of the type vector, | |
| 2868 // after the type arguments of the super type of this type. | |
| 2869 // The index of the type parameters is adjusted upon finalization. | |
| 2870 error = Error::null(); | |
| 2871 interface_args = interface_args.InstantiateFrom(type_arguments, &error); | |
| 2872 if (!error.IsNull()) { | |
| 2873 // Return the first bound error to the caller if it requests it. | |
| 2874 if ((bound_error != NULL) && bound_error->IsNull()) { | |
| 2875 *bound_error = error.raw(); | |
| 2876 } | |
| 2877 continue; // Another interface may work better. | |
| 2878 } | |
| 2879 } | |
| 2880 if (interface_class.TypeTest(test_kind, | |
| 2881 interface_args, | |
| 2882 other, | |
| 2883 other_type_arguments, | |
| 2884 bound_error)) { | |
| 2885 return true; | |
| 2886 } | |
| 2887 } | |
| 2888 // "Recurse" up the class hierarchy until we have reached the top. | |
| 2889 thsi = thsi.SuperClass(); | |
| 2890 if (thsi.IsNull()) { | |
| 2891 return false; | |
| 2892 } | |
| 2893 } | |
| 2894 UNREACHABLE(); | |
| 2895 return false; | |
| 2896 } | |
| 2897 | |
| 2898 | |
| 2899 // If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T. | |
| 2900 // If test_kind == kIsMoreSpecificThan, checks if S is more specific than T. | |
| 2901 // Type S is specified by this class parameterized with 'type_arguments', and | |
| 2902 // type T by class 'other' parameterized with 'other_type_arguments'. | |
| 2903 // This class and class 'other' do not need to be finalized, however, they must | |
| 2904 // be resolved as well as their interfaces. | |
| 2740 bool Class::TypeTest( | 2905 bool Class::TypeTest( |
| 2741 TypeTestKind test_kind, | 2906 TypeTestKind test_kind, |
| 2742 const AbstractTypeArguments& type_arguments, | 2907 const AbstractTypeArguments& type_arguments, |
| 2743 const Class& other, | 2908 const Class& other, |
| 2744 const AbstractTypeArguments& other_type_arguments, | 2909 const AbstractTypeArguments& other_type_arguments, |
| 2745 Error* bound_error) const { | 2910 Error* bound_error) const { |
| 2746 ASSERT(!IsVoidClass()); | 2911 return TypeTestNonRecursive(*this, |
| 2747 // Check for DynamicType. | 2912 test_kind, |
| 2748 // Each occurrence of DynamicType in type T is interpreted as the dynamic | |
| 2749 // type, a supertype of all types. | |
| 2750 if (other.IsDynamicClass()) { | |
| 2751 return true; | |
| 2752 } | |
| 2753 // In the case of a subtype test, each occurrence of DynamicType in type S is | |
| 2754 // interpreted as the bottom type, a subtype of all types. | |
| 2755 // However, DynamicType is not more specific than any type. | |
| 2756 if (IsDynamicClass()) { | |
| 2757 return test_kind == kIsSubtypeOf; | |
| 2758 } | |
| 2759 // Check for NullType, which is only a subtype of ObjectType, of DynamicType, | |
| 2760 // or of itself, and which is more specific than any type. | |
| 2761 if (IsNullClass()) { | |
| 2762 // We already checked for other.IsDynamicClass() above. | |
| 2763 return (test_kind == kIsMoreSpecificThan) || | |
| 2764 other.IsObjectClass() || other.IsNullClass(); | |
| 2765 } | |
| 2766 // Check for ObjectType. Any type that is not NullType or DynamicType (already | |
| 2767 // checked above), is more specific than ObjectType. | |
| 2768 if (other.IsObjectClass()) { | |
| 2769 return true; | |
| 2770 } | |
| 2771 // Check for reflexivity. | |
| 2772 if (raw() == other.raw()) { | |
| 2773 const intptr_t len = NumTypeArguments(); | |
| 2774 if (len == 0) { | |
| 2775 return true; | |
| 2776 } | |
| 2777 // Since we do not truncate the type argument vector of a subclass (see | |
| 2778 // below), we only check a prefix of the proper length. | |
| 2779 // Check for covariance. | |
| 2780 if (other_type_arguments.IsNull() || other_type_arguments.IsRaw(len)) { | |
| 2781 return true; | |
| 2782 } | |
| 2783 if (type_arguments.IsNull() || type_arguments.IsRaw(len)) { | |
| 2784 // Other type can't be more specific than this one because for that | |
| 2785 // it would have to have all dynamic type arguments which is checked | |
| 2786 // above. | |
| 2787 return test_kind == kIsSubtypeOf; | |
| 2788 } | |
| 2789 return type_arguments.TypeTest(test_kind, | |
| 2790 other_type_arguments, | |
| 2791 len, | |
| 2792 bound_error); | |
| 2793 } | |
| 2794 const bool other_is_function_class = other.IsFunctionClass(); | |
| 2795 if (other.IsSignatureClass() || other_is_function_class) { | |
| 2796 const Function& other_fun = Function::Handle(other.signature_function()); | |
| 2797 if (IsSignatureClass()) { | |
| 2798 if (other_is_function_class) { | |
| 2799 return true; | |
| 2800 } | |
| 2801 // Check for two function types. | |
| 2802 const Function& fun = Function::Handle(signature_function()); | |
| 2803 return fun.TypeTest(test_kind, | |
| 2804 type_arguments, | |
| 2805 other_fun, | |
| 2806 other_type_arguments, | |
| 2807 bound_error); | |
| 2808 } | |
| 2809 // Check if type S has a call() method of function type T. | |
| 2810 Function& function = | |
| 2811 Function::Handle(LookupDynamicFunction(Symbols::Call())); | |
| 2812 if (function.IsNull()) { | |
| 2813 // Walk up the super_class chain. | |
| 2814 Class& cls = Class::Handle(SuperClass()); | |
| 2815 while (!cls.IsNull() && function.IsNull()) { | |
| 2816 function = cls.LookupDynamicFunction(Symbols::Call()); | |
| 2817 cls = cls.SuperClass(); | |
| 2818 } | |
| 2819 } | |
| 2820 if (!function.IsNull()) { | |
| 2821 if (other_is_function_class || | |
| 2822 function.TypeTest(test_kind, | |
| 2823 type_arguments, | |
| 2824 other_fun, | |
| 2825 other_type_arguments, | |
| 2826 bound_error)) { | |
| 2827 return true; | |
| 2828 } | |
| 2829 } | |
| 2830 } | |
| 2831 // Check for 'direct super type' specified in the implements clause | |
| 2832 // and check for transitivity at the same time. | |
| 2833 Array& interfaces = Array::Handle(this->interfaces()); | |
| 2834 AbstractType& interface = AbstractType::Handle(); | |
| 2835 Class& interface_class = Class::Handle(); | |
| 2836 AbstractTypeArguments& interface_args = AbstractTypeArguments::Handle(); | |
| 2837 Error& error = Error::Handle(); | |
| 2838 for (intptr_t i = 0; i < interfaces.Length(); i++) { | |
| 2839 interface ^= interfaces.At(i); | |
| 2840 if (!interface.IsFinalized()) { | |
| 2841 // We may be checking bounds at finalization time. Skipping this | |
| 2842 // unfinalized interface will postpone bound checking to run time. | |
| 2843 continue; | |
| 2844 } | |
| 2845 error = Error::null(); | |
| 2846 if (interface.IsMalboundedWithError(&error)) { | |
| 2847 // Return the first bound error to the caller if it requests it. | |
| 2848 if ((bound_error != NULL) && bound_error->IsNull()) { | |
| 2849 ASSERT(!error.IsNull()); | |
| 2850 *bound_error = error.raw(); | |
| 2851 } | |
| 2852 continue; // Another interface may work better. | |
| 2853 } | |
| 2854 interface_class = interface.type_class(); | |
| 2855 interface_args = interface.arguments(); | |
| 2856 if (!interface_args.IsNull() && !interface_args.IsInstantiated()) { | |
| 2857 // This type class implements an interface that is parameterized with | |
| 2858 // generic type(s), e.g. it implements List<T>. | |
| 2859 // The uninstantiated type T must be instantiated using the type | |
| 2860 // parameters of this type before performing the type test. | |
| 2861 // The type arguments of this type that are referred to by the type | |
| 2862 // parameters of the interface are at the end of the type vector, | |
| 2863 // after the type arguments of the super type of this type. | |
| 2864 // The index of the type parameters is adjusted upon finalization. | |
| 2865 error = Error::null(); | |
| 2866 interface_args = interface_args.InstantiateFrom(type_arguments, &error); | |
| 2867 if (!error.IsNull()) { | |
| 2868 // Return the first bound error to the caller if it requests it. | |
| 2869 if ((bound_error != NULL) && bound_error->IsNull()) { | |
| 2870 *bound_error = error.raw(); | |
| 2871 } | |
| 2872 continue; // Another interface may work better. | |
| 2873 } | |
| 2874 } | |
| 2875 if (interface_class.TypeTest(test_kind, | |
| 2876 interface_args, | |
| 2877 other, | |
| 2878 other_type_arguments, | |
| 2879 bound_error)) { | |
| 2880 return true; | |
| 2881 } | |
| 2882 } | |
| 2883 const Class& super_class = Class::Handle(SuperClass()); | |
| 2884 if (super_class.IsNull()) { | |
| 2885 return false; | |
| 2886 } | |
| 2887 // Instead of truncating the type argument vector to the length of the super | |
| 2888 // type argument vector, we make sure that the code works with a vector that | |
| 2889 // is longer than necessary. | |
| 2890 return super_class.TypeTest(test_kind, | |
| 2891 type_arguments, | 2913 type_arguments, |
| 2892 other, | 2914 other, |
| 2893 other_type_arguments, | 2915 other_type_arguments, |
| 2894 bound_error); | 2916 bound_error); |
| 2895 } | 2917 } |
| 2896 | 2918 |
| 2897 | 2919 |
| 2898 bool Class::IsTopLevel() const { | 2920 bool Class::IsTopLevel() const { |
| 2899 return Name() == Symbols::TopLevel().raw(); | 2921 return Name() == Symbols::TopLevel().raw(); |
| 2900 } | 2922 } |
| (...skipping 12816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15717 return "_MirrorReference"; | 15739 return "_MirrorReference"; |
| 15718 } | 15740 } |
| 15719 | 15741 |
| 15720 | 15742 |
| 15721 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 15743 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
| 15722 JSONObject jsobj(stream); | 15744 JSONObject jsobj(stream); |
| 15723 } | 15745 } |
| 15724 | 15746 |
| 15725 | 15747 |
| 15726 } // namespace dart | 15748 } // namespace dart |
| OLD | NEW |