Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: runtime/vm/object.cc

Issue 2755723003: Make sure the signature of the call method is finalized before involving it (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/become.h" 10 #include "vm/become.h"
(...skipping 1978 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 1989
1990 bool Class::IsInFullSnapshot() const { 1990 bool Class::IsInFullSnapshot() const {
1991 NoSafepointScope no_safepoint; 1991 NoSafepointScope no_safepoint;
1992 return raw_ptr()->library_->ptr()->is_in_fullsnapshot_; 1992 return raw_ptr()->library_->ptr()->is_in_fullsnapshot_;
1993 } 1993 }
1994 1994
1995 1995
1996 RawAbstractType* Class::RareType() const { 1996 RawAbstractType* Class::RareType() const {
1997 const Type& type = Type::Handle(Type::New( 1997 const Type& type = Type::Handle(Type::New(
1998 *this, Object::null_type_arguments(), TokenPosition::kNoSource)); 1998 *this, Object::null_type_arguments(), TokenPosition::kNoSource));
1999 return ClassFinalizer::FinalizeType(*this, type, 1999 return ClassFinalizer::FinalizeType(*this, type);
2000 ClassFinalizer::kCanonicalize);
2001 } 2000 }
2002 2001
2003 2002
2004 RawAbstractType* Class::DeclarationType() const { 2003 RawAbstractType* Class::DeclarationType() const {
2005 const TypeArguments& args = TypeArguments::Handle(type_parameters()); 2004 const TypeArguments& args = TypeArguments::Handle(type_parameters());
2006 const Type& type = 2005 const Type& type =
2007 Type::Handle(Type::New(*this, args, TokenPosition::kNoSource)); 2006 Type::Handle(Type::New(*this, args, TokenPosition::kNoSource));
2008 return ClassFinalizer::FinalizeType(*this, type, 2007 return ClassFinalizer::FinalizeType(*this, type);
2009 ClassFinalizer::kCanonicalize);
2010 } 2008 }
2011 2009
2012 2010
2013 template <class FakeObject> 2011 template <class FakeObject>
2014 RawClass* Class::New() { 2012 RawClass* Class::New() {
2015 ASSERT(Object::class_class() != Class::null()); 2013 ASSERT(Object::class_class() != Class::null());
2016 Class& result = Class::Handle(); 2014 Class& result = Class::Handle();
2017 { 2015 {
2018 RawObject* raw = 2016 RawObject* raw =
2019 Object::Allocate(Class::kClassId, Class::InstanceSize(), Heap::kOld); 2017 Object::Allocate(Class::kClassId, Class::InstanceSize(), Heap::kOld);
(...skipping 1807 matching lines...) Expand 10 before | Expand all | Expand 10 after
3827 // it would have to have all dynamic type arguments which is checked 3825 // it would have to have all dynamic type arguments which is checked
3828 // above. 3826 // above.
3829 return test_kind == Class::kIsSubtypeOf; 3827 return test_kind == Class::kIsSubtypeOf;
3830 } 3828 }
3831 return type_arguments.TypeTest(test_kind, other_type_arguments, 3829 return type_arguments.TypeTest(test_kind, other_type_arguments,
3832 from_index, num_type_params, bound_error, 3830 from_index, num_type_params, bound_error,
3833 bound_trail, space); 3831 bound_trail, space);
3834 } 3832 }
3835 if (other.IsDartFunctionClass()) { 3833 if (other.IsDartFunctionClass()) {
3836 // Check if type S has a call() method. 3834 // Check if type S has a call() method.
3837 Function& function = Function::Handle( 3835 const Function& call_function =
3838 zone, thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call())); 3836 Function::Handle(zone, thsi.LookupCallFunctionForTypeTest());
3839 if (function.IsNull()) { 3837 if (!call_function.IsNull()) {
3840 // Walk up the super_class chain.
3841 Class& cls = Class::Handle(zone, thsi.SuperClass());
3842 while (!cls.IsNull() && function.IsNull()) {
3843 function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
3844 cls = cls.SuperClass();
3845 }
3846 }
3847 if (!function.IsNull()) {
3848 return true; 3838 return true;
3849 } 3839 }
3850 } 3840 }
3851 // Check for 'direct super type' specified in the implements clause 3841 // Check for 'direct super type' specified in the implements clause
3852 // and check for transitivity at the same time. 3842 // and check for transitivity at the same time.
3853 Array& interfaces = Array::Handle(zone, thsi.interfaces()); 3843 Array& interfaces = Array::Handle(zone, thsi.interfaces());
3854 AbstractType& interface = AbstractType::Handle(zone); 3844 AbstractType& interface = AbstractType::Handle(zone);
3855 Class& interface_class = Class::Handle(zone); 3845 Class& interface_class = Class::Handle(zone);
3856 TypeArguments& interface_args = TypeArguments::Handle(zone); 3846 TypeArguments& interface_args = TypeArguments::Handle(zone);
3857 Error& error = Error::Handle(zone); 3847 Error& error = Error::Handle(zone);
3858 for (intptr_t i = 0; i < interfaces.Length(); i++) { 3848 for (intptr_t i = 0; i < interfaces.Length(); i++) {
3859 interface ^= interfaces.At(i); 3849 interface ^= interfaces.At(i);
3860 if (!interface.IsFinalized()) { 3850 if (!interface.IsFinalized()) {
3861 // We may be checking bounds at finalization time and can encounter 3851 // We may be checking bounds at finalization time and can encounter
3862 // a still unfinalized interface. 3852 // a still unfinalized interface.
3863 if (interface.IsBeingFinalized()) { 3853 if (interface.IsBeingFinalized()) {
3864 // Interface is part of a still unfinalized recursive type graph. 3854 // Interface is part of a still unfinalized recursive type graph.
3865 // Skip it. The caller will create a bounded type to be checked at 3855 // Skip it. The caller will create a bounded type to be checked at
3866 // runtime if this type test returns false at compile time. 3856 // runtime if this type test returns false at compile time.
3867 continue; 3857 continue;
3868 } 3858 }
3869 ClassFinalizer::FinalizeType(thsi, interface, 3859 ClassFinalizer::FinalizeType(thsi, interface);
3870 ClassFinalizer::kCanonicalize);
3871 interfaces.SetAt(i, interface); 3860 interfaces.SetAt(i, interface);
3872 } 3861 }
3873 if (interface.IsMalbounded()) { 3862 if (interface.IsMalbounded()) {
3874 // Return the first bound error to the caller if it requests it. 3863 // Return the first bound error to the caller if it requests it.
3875 if ((bound_error != NULL) && bound_error->IsNull()) { 3864 if ((bound_error != NULL) && bound_error->IsNull()) {
3876 *bound_error = interface.error(); 3865 *bound_error = interface.error();
3877 } 3866 }
3878 continue; // Another interface may work better. 3867 continue; // Another interface may work better.
3879 } 3868 }
3880 interface_class = interface.type_class(); 3869 interface_class = interface.type_class();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3995 RawFunction* Class::LookupFunction(const String& name) const { 3984 RawFunction* Class::LookupFunction(const String& name) const {
3996 return LookupFunction(name, kAny); 3985 return LookupFunction(name, kAny);
3997 } 3986 }
3998 3987
3999 3988
4000 RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const { 3989 RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
4001 return LookupFunctionAllowPrivate(name, kAny); 3990 return LookupFunctionAllowPrivate(name, kAny);
4002 } 3991 }
4003 3992
4004 3993
3994 RawFunction* Class::LookupCallFunctionForTypeTest() const {
3995 // If this class is not compiled yet, it is too early to lookup a call
3996 // function. This case should only occur during bounds checking at compile
3997 // time. Return null as if the call method did not exist, so the type test
3998 // may return false, but without a bound error, and the bound check will get
3999 // postponed to runtime.
4000 if (!is_finalized()) {
4001 return Function::null();
4002 }
4003 Zone* zone = Thread::Current()->zone();
4004 Class& cls = Class::Handle(zone, raw());
4005 Function& call_function = Function::Handle(zone);
4006 do {
4007 ASSERT(cls.is_finalized());
4008 call_function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
4009 cls = cls.SuperClass();
4010 } while (call_function.IsNull() && !cls.IsNull());
4011 if (!call_function.IsNull()) {
4012 // Make sure the signature is finalized before using it in a type test.
4013 ClassFinalizer::FinalizeSignature(
4014 cls, call_function, ClassFinalizer::kFinalize); // No bounds checking.
4015 }
4016 return call_function.raw();
4017 }
4018
4019
4005 // Returns true if 'prefix' and 'accessor_name' match 'name'. 4020 // Returns true if 'prefix' and 'accessor_name' match 'name'.
4006 static bool MatchesAccessorName(const String& name, 4021 static bool MatchesAccessorName(const String& name,
4007 const char* prefix, 4022 const char* prefix,
4008 intptr_t prefix_length, 4023 intptr_t prefix_length,
4009 const String& accessor_name) { 4024 const String& accessor_name) {
4010 intptr_t name_len = name.Length(); 4025 intptr_t name_len = name.Length();
4011 intptr_t accessor_name_len = accessor_name.Length(); 4026 intptr_t accessor_name_len = accessor_name.Length();
4012 4027
4013 if (name_len != (accessor_name_len + prefix_length)) { 4028 if (name_len != (accessor_name_len + prefix_length)) {
4014 return false; 4029 return false;
(...skipping 2775 matching lines...) Expand 10 before | Expand all | Expand 10 after
6790 for (int i = kClosure; i < num_params; i++) { 6805 for (int i = kClosure; i < num_params; i++) {
6791 param_type = ParameterTypeAt(has_receiver - kClosure + i); 6806 param_type = ParameterTypeAt(has_receiver - kClosure + i);
6792 closure_function.SetParameterTypeAt(i, param_type); 6807 closure_function.SetParameterTypeAt(i, param_type);
6793 param_name = ParameterNameAt(has_receiver - kClosure + i); 6808 param_name = ParameterNameAt(has_receiver - kClosure + i);
6794 closure_function.SetParameterNameAt(i, param_name); 6809 closure_function.SetParameterNameAt(i, param_name);
6795 } 6810 }
6796 closure_function.set_kernel_function(kernel_function()); 6811 closure_function.set_kernel_function(kernel_function());
6797 6812
6798 const Type& signature_type = Type::Handle(closure_function.SignatureType()); 6813 const Type& signature_type = Type::Handle(closure_function.SignatureType());
6799 if (!signature_type.IsFinalized()) { 6814 if (!signature_type.IsFinalized()) {
6800 ClassFinalizer::FinalizeType(Class::Handle(Owner()), signature_type, 6815 ClassFinalizer::FinalizeType(Class::Handle(Owner()), signature_type);
6801 ClassFinalizer::kCanonicalize);
6802 } 6816 }
6803 set_implicit_closure_function(closure_function); 6817 set_implicit_closure_function(closure_function);
6804 ASSERT(closure_function.IsImplicitClosureFunction()); 6818 ASSERT(closure_function.IsImplicitClosureFunction());
6805 return closure_function.raw(); 6819 return closure_function.raw();
6806 } 6820 }
6807 6821
6808 6822
6809 void Function::DropUncompiledImplicitClosureFunction() const { 6823 void Function::DropUncompiledImplicitClosureFunction() const {
6810 if (implicit_closure_function() != Function::null()) { 6824 if (implicit_closure_function() != Function::null()) {
6811 const Function& func = Function::Handle(implicit_closure_function()); 6825 const Function& func = Function::Handle(implicit_closure_function());
(...skipping 8943 matching lines...) Expand 10 before | Expand all | Expand 10 after
15755 instantiated_other = TypeRef::Cast(instantiated_other).type(); 15769 instantiated_other = TypeRef::Cast(instantiated_other).type();
15756 } 15770 }
15757 if (instantiated_other.IsDynamicType()) { 15771 if (instantiated_other.IsDynamicType()) {
15758 return true; 15772 return true;
15759 } 15773 }
15760 } 15774 }
15761 other_type_arguments = instantiated_other.arguments(); 15775 other_type_arguments = instantiated_other.arguments();
15762 const bool other_is_dart_function = instantiated_other.IsDartFunctionType(); 15776 const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
15763 if (other_is_dart_function || instantiated_other.IsFunctionType()) { 15777 if (other_is_dart_function || instantiated_other.IsFunctionType()) {
15764 // Check if this instance understands a call() method of a compatible type. 15778 // Check if this instance understands a call() method of a compatible type.
15765 Function& call = Function::Handle( 15779 const Function& call_function =
15766 zone, cls.LookupDynamicFunctionAllowAbstract(Symbols::Call())); 15780 Function::Handle(zone, cls.LookupCallFunctionForTypeTest());
15767 if (call.IsNull()) { 15781 if (!call_function.IsNull()) {
15768 // Walk up the super_class chain.
15769 Class& super_cls = Class::Handle(zone, cls.SuperClass());
15770 while (!super_cls.IsNull() && call.IsNull()) {
15771 call = super_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
15772 super_cls = super_cls.SuperClass();
15773 }
15774 }
15775 if (!call.IsNull()) {
15776 if (other_is_dart_function) { 15782 if (other_is_dart_function) {
15777 return true; 15783 return true;
15778 } 15784 }
15779 const Function& other_signature = 15785 const Function& other_signature =
15780 Function::Handle(zone, Type::Cast(instantiated_other).signature()); 15786 Function::Handle(zone, Type::Cast(instantiated_other).signature());
15781 if (call.IsSubtypeOf(type_arguments, other_signature, 15787 if (call_function.IsSubtypeOf(type_arguments, other_signature,
15782 other_type_arguments, bound_error, Heap::kOld)) { 15788 other_type_arguments, bound_error,
15789 Heap::kOld)) {
15783 return true; 15790 return true;
15784 } 15791 }
15785 } 15792 }
15786 } 15793 }
15787 if (!instantiated_other.IsType()) { 15794 if (!instantiated_other.IsType()) {
15788 return false; 15795 return false;
15789 } 15796 }
15790 other_class = instantiated_other.type_class(); 15797 other_class = instantiated_other.type_class();
15791 if (IsNull()) { 15798 if (IsNull()) {
15792 ASSERT(cls.IsNullClass()); 15799 ASSERT(cls.IsNullClass());
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after
16574 const Function& other_fun = 16581 const Function& other_fun =
16575 Function::Handle(zone, Type::Cast(other).signature()); 16582 Function::Handle(zone, Type::Cast(other).signature());
16576 // Check for two function types. 16583 // Check for two function types.
16577 const Function& fun = 16584 const Function& fun =
16578 Function::Handle(zone, Type::Cast(*this).signature()); 16585 Function::Handle(zone, Type::Cast(*this).signature());
16579 return fun.TypeTest( 16586 return fun.TypeTest(
16580 test_kind, TypeArguments::Handle(zone, arguments()), other_fun, 16587 test_kind, TypeArguments::Handle(zone, arguments()), other_fun,
16581 TypeArguments::Handle(zone, other.arguments()), bound_error, space); 16588 TypeArguments::Handle(zone, other.arguments()), bound_error, space);
16582 } 16589 }
16583 // Check if type S has a call() method of function type T. 16590 // Check if type S has a call() method of function type T.
16584 Function& function = Function::Handle( 16591 const Function& call_function =
16585 zone, type_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call())); 16592 Function::Handle(zone, type_cls.LookupCallFunctionForTypeTest());
16586 if (function.IsNull()) { 16593 if (!call_function.IsNull()) {
16587 // Walk up the super_class chain.
16588 Class& cls = Class::Handle(zone, type_cls.SuperClass());
16589 while (!cls.IsNull() && function.IsNull()) {
16590 function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
16591 cls = cls.SuperClass();
16592 }
16593 }
16594 if (!function.IsNull()) {
16595 if (other_is_dart_function_type || 16594 if (other_is_dart_function_type ||
16596 function.TypeTest( 16595 call_function.TypeTest(
16597 test_kind, TypeArguments::Handle(zone, arguments()), 16596 test_kind, TypeArguments::Handle(zone, arguments()),
16598 Function::Handle(zone, Type::Cast(other).signature()), 16597 Function::Handle(zone, Type::Cast(other).signature()),
16599 TypeArguments::Handle(zone, other.arguments()), bound_error, 16598 TypeArguments::Handle(zone, other.arguments()), bound_error,
16600 space)) { 16599 space)) {
16601 return true; 16600 return true;
16602 } 16601 }
16603 } 16602 }
16604 } 16603 }
16605 if (IsFunctionType()) { 16604 if (IsFunctionType()) {
16606 return false; 16605 return false;
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
16877 ASSERT(num_type_args > 0); 16876 ASSERT(num_type_args > 0);
16878 // This type is not instantiated if it refers to type parameters. 16877 // This type is not instantiated if it refers to type parameters.
16879 // Although this type may still be unresolved, the type parameters it may 16878 // Although this type may still be unresolved, the type parameters it may
16880 // refer to are resolved by definition. We can therefore return the correct 16879 // refer to are resolved by definition. We can therefore return the correct
16881 // result even for an unresolved type. We just need to look at all type 16880 // result even for an unresolved type. We just need to look at all type
16882 // arguments and not just at the type parameters. 16881 // arguments and not just at the type parameters.
16883 if (HasResolvedTypeClass()) { 16882 if (HasResolvedTypeClass()) {
16884 const Class& cls = Class::Handle(type_class()); 16883 const Class& cls = Class::Handle(type_class());
16885 len = cls.NumTypeParameters(); // Check the type parameters only. 16884 len = cls.NumTypeParameters(); // Check the type parameters only.
16886 } 16885 }
16887 return (len == 0) || args.IsSubvectorInstantiated(num_type_args - len, len); 16886 return (len == 0) ||
16887 args.IsSubvectorInstantiated(num_type_args - len, len, trail);
16888 } 16888 }
16889 16889
16890 16890
16891 RawAbstractType* Type::InstantiateFrom( 16891 RawAbstractType* Type::InstantiateFrom(
16892 const TypeArguments& instantiator_type_arguments, 16892 const TypeArguments& instantiator_type_arguments,
16893 Error* bound_error, 16893 Error* bound_error,
16894 TrailPtr instantiation_trail, 16894 TrailPtr instantiation_trail,
16895 TrailPtr bound_trail, 16895 TrailPtr bound_trail,
16896 Heap::Space space) const { 16896 Heap::Space space) const {
16897 Zone* zone = Thread::Current()->zone(); 16897 Zone* zone = Thread::Current()->zone();
(...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after
17857 } 17857 }
17858 17858
17859 if (bounded_type.IsSubtypeOf(upper_bound, bound_error, bound_trail, space)) { 17859 if (bounded_type.IsSubtypeOf(upper_bound, bound_error, bound_trail, space)) {
17860 return true; 17860 return true;
17861 } 17861 }
17862 // Set bound_error if the caller is interested and if this is the first error. 17862 // Set bound_error if the caller is interested and if this is the first error.
17863 if ((bound_error != NULL) && bound_error->IsNull()) { 17863 if ((bound_error != NULL) && bound_error->IsNull()) {
17864 // Report the bound error only if both the bounded type and the upper bound 17864 // Report the bound error only if both the bounded type and the upper bound
17865 // are instantiated. Otherwise, we cannot tell yet it is a bound error. 17865 // are instantiated. Otherwise, we cannot tell yet it is a bound error.
17866 if (bounded_type.IsInstantiated() && upper_bound.IsInstantiated()) { 17866 if (bounded_type.IsInstantiated() && upper_bound.IsInstantiated()) {
17867 // There is another special case where we do not want to report a bound
17868 // error yet: if the upper bound is a function type, but the bounded type
17869 // is not and its class is not compiled yet, i.e. we cannot look for
17870 // a call method yet.
17871 if (!bounded_type.IsFunctionType() && upper_bound.IsFunctionType() &&
17872 bounded_type.HasResolvedTypeClass() &&
17873 !Class::Handle(bounded_type.type_class()).is_finalized()) {
17874 return false; // Not a subtype yet, but no bound error yet.
17875 }
17867 const String& bounded_type_name = 17876 const String& bounded_type_name =
17868 String::Handle(bounded_type.UserVisibleName()); 17877 String::Handle(bounded_type.UserVisibleName());
17869 const String& upper_bound_name = 17878 const String& upper_bound_name =
17870 String::Handle(upper_bound.UserVisibleName()); 17879 String::Handle(upper_bound.UserVisibleName());
17871 const AbstractType& declared_bound = AbstractType::Handle(bound()); 17880 const AbstractType& declared_bound = AbstractType::Handle(bound());
17872 const String& declared_bound_name = 17881 const String& declared_bound_name =
17873 String::Handle(declared_bound.UserVisibleName()); 17882 String::Handle(declared_bound.UserVisibleName());
17874 const String& type_param_name = String::Handle(UserVisibleName()); 17883 const String& type_param_name = String::Handle(UserVisibleName());
17875 const Class& cls = Class::Handle(parameterized_class()); 17884 const Class& cls = Class::Handle(parameterized_class());
17876 const String& class_name = String::Handle(cls.Name()); 17885 const String& class_name = String::Handle(cls.Name());
(...skipping 5093 matching lines...) Expand 10 before | Expand all | Expand 10 after
22970 return UserTag::null(); 22979 return UserTag::null();
22971 } 22980 }
22972 22981
22973 22982
22974 const char* UserTag::ToCString() const { 22983 const char* UserTag::ToCString() const {
22975 const String& tag_label = String::Handle(label()); 22984 const String& tag_label = String::Handle(label());
22976 return tag_label.ToCString(); 22985 return tag_label.ToCString();
22977 } 22986 }
22978 22987
22979 } // namespace dart 22988 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698