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

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

Issue 13653005: Prevent expensive and unnecessary error formatting in the case a bound check is (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | tests/language/f_bounded_quantification3_test.dart » ('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/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 2843 matching lines...) Expand 10 before | Expand all | Expand 10 after
2854 const TypeParameter& type_param = TypeParameter::Cast(type); 2854 const TypeParameter& type_param = TypeParameter::Cast(type);
2855 ASSERT(type_param.IsFinalized()); 2855 ASSERT(type_param.IsFinalized());
2856 if ((type_param.index() != i)) { 2856 if ((type_param.index() != i)) {
2857 return false; 2857 return false;
2858 } 2858 }
2859 // If this type parameter specifies an upper bound, then the type argument 2859 // If this type parameter specifies an upper bound, then the type argument
2860 // vector does not really represent the identity vector. It cannot be 2860 // vector does not really represent the identity vector. It cannot be
2861 // substituted by the instantiator's type argument vector without checking 2861 // substituted by the instantiator's type argument vector without checking
2862 // the upper bound. 2862 // the upper bound.
2863 const AbstractType& bound = AbstractType::Handle(type_param.bound()); 2863 const AbstractType& bound = AbstractType::Handle(type_param.bound());
2864 ASSERT(bound.IsFinalized()); 2864 ASSERT(bound.IsResolved());
2865 if (!bound.IsObjectType() && !bound.IsDynamicType()) { 2865 if (!bound.IsObjectType() && !bound.IsDynamicType()) {
2866 return false; 2866 return false;
2867 } 2867 }
2868 } 2868 }
2869 return true; 2869 return true;
2870 } 2870 }
2871 2871
2872 2872
2873 bool TypeArguments::IsBounded() const { 2873 bool TypeArguments::IsBounded() const {
2874 AbstractType& type = AbstractType::Handle(); 2874 AbstractType& type = AbstractType::Handle();
(...skipping 6381 matching lines...) Expand 10 before | Expand all | Expand 10 after
9256 9256
9257 bool AbstractType::IsFunctionType() const { 9257 bool AbstractType::IsFunctionType() const {
9258 return HasResolvedTypeClass() && 9258 return HasResolvedTypeClass() &&
9259 (type_class() == Type::Handle(Type::Function()).type_class()); 9259 (type_class() == Type::Handle(Type::Function()).type_class());
9260 } 9260 }
9261 9261
9262 9262
9263 bool AbstractType::TypeTest(TypeTestKind test_kind, 9263 bool AbstractType::TypeTest(TypeTestKind test_kind,
9264 const AbstractType& other, 9264 const AbstractType& other,
9265 Error* malformed_error) const { 9265 Error* malformed_error) const {
9266 ASSERT(IsFinalized()); 9266 ASSERT(IsResolved());
9267 ASSERT(other.IsFinalized()); 9267 ASSERT(other.IsResolved());
9268 // In case the type checked in a type test is malformed, the code generator 9268 // In case the type checked in a type test is malformed, the code generator
9269 // may compile a throw instead of a run time call performing the type check. 9269 // may compile a throw instead of a run time call performing the type check.
9270 // However, in checked mode, a function type may include malformed result type 9270 // However, in checked mode, a function type may include malformed result type
9271 // and/or malformed parameter types, which will then be encountered here at 9271 // and/or malformed parameter types, which will then be encountered here at
9272 // run time. 9272 // run time.
9273 if (IsMalformed()) { 9273 if (IsMalformed()) {
9274 ASSERT(FLAG_enable_type_checks); 9274 ASSERT(FLAG_enable_type_checks);
9275 if ((malformed_error != NULL) && malformed_error->IsNull()) { 9275 if ((malformed_error != NULL) && malformed_error->IsNull()) {
9276 *malformed_error = this->malformed_error(); 9276 *malformed_error = this->malformed_error();
9277 } 9277 }
(...skipping 16 matching lines...) Expand all
9294 return false; // TODO(regis): We should return "maybe after instantiation". 9294 return false; // TODO(regis): We should return "maybe after instantiation".
9295 } 9295 }
9296 // Type parameters cannot be handled by Class::TypeTest(). 9296 // Type parameters cannot be handled by Class::TypeTest().
9297 // When comparing two uninstantiated function types, one returning type 9297 // When comparing two uninstantiated function types, one returning type
9298 // parameter K, the other returning type parameter V, we cannot assume that K 9298 // parameter K, the other returning type parameter V, we cannot assume that K
9299 // is a subtype of V, or vice versa. We only return true if K equals V, as 9299 // is a subtype of V, or vice versa. We only return true if K equals V, as
9300 // defined by TypeParameter::Equals. 9300 // defined by TypeParameter::Equals.
9301 // The same rule applies when checking the upper bound of a still 9301 // The same rule applies when checking the upper bound of a still
9302 // uninstantiated type at compile time. Returning false will defer the test 9302 // uninstantiated type at compile time. Returning false will defer the test
9303 // to run time. 9303 // to run time.
9304 // We may think that some cases can be decided at compile time. 9304 // There are however some cases can be decided at compile time.
9305 // For example, with class A<K, V extends K>, new A<T, T> called from within 9305 // For example, with class A<K, V extends K>, new A<T, T> called from within
9306 // a class B<T> will never require a run time bound check, even if T is 9306 // a class B<T> will never require a run time bound check, even if T is
9307 // uninstantiated at compile time. 9307 // uninstantiated at compile time.
9308 // However, this is not true, because bounds are ignored in production mode,
9309 // and even if we are running in checked mode, we may generate a snapshot
9310 // that will be executed in production mode.
9311 if (IsTypeParameter()) { 9308 if (IsTypeParameter()) {
9312 const TypeParameter& type_param = TypeParameter::Cast(*this); 9309 const TypeParameter& type_param = TypeParameter::Cast(*this);
9313 if (other.IsTypeParameter()) { 9310 if (other.IsTypeParameter()) {
9314 const TypeParameter& other_type_param = TypeParameter::Cast(other); 9311 const TypeParameter& other_type_param = TypeParameter::Cast(other);
9315 if (type_param.Equals(other_type_param)) { 9312 if (type_param.Equals(other_type_param)) {
9316 return true; 9313 return true;
9317 } 9314 }
9318 } 9315 }
9316 const AbstractType& bound = AbstractType::Handle(type_param.bound());
9317 if (bound.IsMoreSpecificThan(other, malformed_error)) {
9318 return true;
9319 }
9319 return false; // TODO(regis): We should return "maybe after instantiation". 9320 return false; // TODO(regis): We should return "maybe after instantiation".
9320 } 9321 }
9321 if (other.IsTypeParameter()) { 9322 if (other.IsTypeParameter()) {
9322 return false; // TODO(regis): We should return "maybe after instantiation". 9323 return false; // TODO(regis): We should return "maybe after instantiation".
9323 } 9324 }
9324 const Class& cls = Class::Handle(type_class()); 9325 const Class& cls = Class::Handle(type_class());
9325 return cls.TypeTest(test_kind, 9326 return cls.TypeTest(test_kind,
9326 AbstractTypeArguments::Handle(arguments()), 9327 AbstractTypeArguments::Handle(arguments()),
9327 Class::Handle(other.type_class()), 9328 Class::Handle(other.type_class()),
9328 AbstractTypeArguments::Handle(other.arguments()), 9329 AbstractTypeArguments::Handle(other.arguments()),
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
9525 } 9526 }
9526 const AbstractTypeArguments& args = 9527 const AbstractTypeArguments& args =
9527 AbstractTypeArguments::Handle(arguments()); 9528 AbstractTypeArguments::Handle(arguments());
9528 return args.IsNull() || args.IsInstantiated(); 9529 return args.IsNull() || args.IsInstantiated();
9529 } 9530 }
9530 9531
9531 9532
9532 RawAbstractType* Type::InstantiateFrom( 9533 RawAbstractType* Type::InstantiateFrom(
9533 const AbstractTypeArguments& instantiator_type_arguments, 9534 const AbstractTypeArguments& instantiator_type_arguments,
9534 Error* malformed_error) const { 9535 Error* malformed_error) const {
9535 ASSERT(IsFinalized()); 9536 ASSERT(IsResolved());
9536 ASSERT(!IsInstantiated()); 9537 ASSERT(!IsInstantiated());
9537 // Return the uninstantiated type unchanged if malformed. No copy needed. 9538 // Return the uninstantiated type unchanged if malformed. No copy needed.
9538 if (IsMalformed()) { 9539 if (IsMalformed()) {
9539 return raw(); 9540 return raw();
9540 } 9541 }
9541 AbstractTypeArguments& type_arguments = 9542 AbstractTypeArguments& type_arguments =
9542 AbstractTypeArguments::Handle(arguments()); 9543 AbstractTypeArguments::Handle(arguments());
9543 type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments, 9544 type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
9544 malformed_error); 9545 malformed_error);
9545 // Note that the type class has to be resolved at this time, but not 9546 // Note that the type class has to be resolved at this time, but not
(...skipping 11 matching lines...) Expand all
9557 9558
9558 9559
9559 bool Type::Equals(const Instance& other) const { 9560 bool Type::Equals(const Instance& other) const {
9560 if (raw() == other.raw()) { 9561 if (raw() == other.raw()) {
9561 return true; 9562 return true;
9562 } 9563 }
9563 if (!other.IsType()) { 9564 if (!other.IsType()) {
9564 return false; 9565 return false;
9565 } 9566 }
9566 const Type& other_type = Type::Cast(other); 9567 const Type& other_type = Type::Cast(other);
9567 ASSERT(IsFinalized() && other_type.IsFinalized()); 9568 ASSERT(IsResolved() && other_type.IsResolved());
9568 if (IsMalformed() || other_type.IsMalformed()) { 9569 if (IsMalformed() || other_type.IsMalformed()) {
9569 return false; 9570 return false;
9570 } 9571 }
9571 if (type_class() != other_type.type_class()) { 9572 if (type_class() != other_type.type_class()) {
9572 return false; 9573 return false;
9573 } 9574 }
9575 if (!IsFinalized() || !other_type.IsFinalized()) {
9576 return false;
9577 }
9574 return AbstractTypeArguments::AreEqual( 9578 return AbstractTypeArguments::AreEqual(
9575 AbstractTypeArguments::Handle(arguments()), 9579 AbstractTypeArguments::Handle(arguments()),
9576 AbstractTypeArguments::Handle(other_type.arguments())); 9580 AbstractTypeArguments::Handle(other_type.arguments()));
9577 } 9581 }
9578 9582
9579 9583
9580 RawAbstractType* Type::Canonicalize() const { 9584 RawAbstractType* Type::Canonicalize() const {
9581 ASSERT(IsFinalized()); 9585 ASSERT(IsFinalized());
9582 if (IsCanonical() || IsMalformed()) { 9586 if (IsCanonical() || IsMalformed()) {
9583 ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld()); 9587 ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld());
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
9773 } 9777 }
9774 9778
9775 9779
9776 RawAbstractType* TypeParameter::InstantiateFrom( 9780 RawAbstractType* TypeParameter::InstantiateFrom(
9777 const AbstractTypeArguments& instantiator_type_arguments, 9781 const AbstractTypeArguments& instantiator_type_arguments,
9778 Error* malformed_error) const { 9782 Error* malformed_error) const {
9779 ASSERT(IsFinalized()); 9783 ASSERT(IsFinalized());
9780 if (instantiator_type_arguments.IsNull()) { 9784 if (instantiator_type_arguments.IsNull()) {
9781 return Type::DynamicType(); 9785 return Type::DynamicType();
9782 } 9786 }
9783 // Bound checks should never appear in the instantiator type arguments. 9787 // Bound checks may appear in the instantiator type arguments, as is the case
9784 ASSERT(!AbstractType::Handle( 9788 // with a pair of type parameters of the same class referring to each other
9785 instantiator_type_arguments.TypeAt(index())).IsBoundedType()); 9789 // via their bounds.
9786 return instantiator_type_arguments.TypeAt(index()); 9790 AbstractType& type_arg = AbstractType::Handle(
9791 instantiator_type_arguments.TypeAt(index()));
9792 if (type_arg.IsBoundedType()) {
9793 const BoundedType& bounded_type = BoundedType::Cast(type_arg);
9794 ASSERT(!bounded_type.IsInstantiated());
9795 ASSERT(AbstractType::Handle(bounded_type.bound()).IsInstantiated());
9796 type_arg = bounded_type.InstantiateFrom(AbstractTypeArguments::Handle(),
9797 malformed_error);
9798 }
9799 return type_arg.raw();
9787 } 9800 }
9788 9801
9789 9802
9790 void TypeParameter::CheckBound(const AbstractType& bounded_type, 9803 bool TypeParameter::CheckBound(const AbstractType& bounded_type,
9791 const AbstractType& upper_bound, 9804 const AbstractType& upper_bound,
9792 Error* malformed_error) const { 9805 Error* malformed_error) const {
9793 ASSERT(malformed_error->IsNull()); 9806 ASSERT((malformed_error == NULL) || malformed_error->IsNull());
9794 ASSERT(bounded_type.IsFinalized()); 9807 ASSERT(bounded_type.IsFinalized());
9795 ASSERT(upper_bound.IsFinalized()); 9808 ASSERT(upper_bound.IsFinalized());
9796 ASSERT(!bounded_type.IsMalformed()); 9809 ASSERT(!bounded_type.IsMalformed());
9797 if (bounded_type.IsSubtypeOf(upper_bound, malformed_error) || 9810 if (bounded_type.IsSubtypeOf(upper_bound, malformed_error)) {
9798 !malformed_error->IsNull()) { 9811 return true;
9799 return;
9800 } 9812 }
9801 // Report the bound error. 9813 if ((malformed_error != NULL) && malformed_error->IsNull()) {
9802 const String& bounded_type_name = String::Handle( 9814 // Report the bound error.
9803 bounded_type.UserVisibleName()); 9815 const String& bounded_type_name = String::Handle(
9804 const String& upper_bound_name = String::Handle( 9816 bounded_type.UserVisibleName());
9805 upper_bound.UserVisibleName()); 9817 const String& upper_bound_name = String::Handle(
9806 const AbstractType& declared_bound = AbstractType::Handle(bound()); 9818 upper_bound.UserVisibleName());
9807 const String& declared_bound_name = String::Handle( 9819 const AbstractType& declared_bound = AbstractType::Handle(bound());
9808 declared_bound.UserVisibleName()); 9820 const String& declared_bound_name = String::Handle(
9809 const String& type_param_name = String::Handle(UserVisibleName()); 9821 declared_bound.UserVisibleName());
9810 const Class& cls = Class::Handle(parameterized_class()); 9822 const String& type_param_name = String::Handle(UserVisibleName());
9811 const String& class_name = String::Handle(cls.Name()); 9823 const Class& cls = Class::Handle(parameterized_class());
9812 const Script& script = Script::Handle(cls.script()); 9824 const String& class_name = String::Handle(cls.Name());
9813 // Since the bound may have been canonicalized, its token index is 9825 const Script& script = Script::Handle(cls.script());
9814 // meaningless, therefore use the token index of this type parameter. 9826 // Since the bound may have been canonicalized, its token index is
9815 *malformed_error = FormatError( 9827 // meaningless, therefore use the token index of this type parameter.
9816 *malformed_error, 9828 *malformed_error = FormatError(
9817 script, 9829 *malformed_error,
9818 token_pos(), 9830 script,
9819 "type parameter '%s' of class '%s' must extend bound '%s', " 9831 token_pos(),
9820 "but type argument '%s' is not a subtype of '%s'\n", 9832 "type parameter '%s' of class '%s' must extend bound '%s', "
9821 type_param_name.ToCString(), 9833 "but type argument '%s' is not a subtype of '%s'\n",
9822 class_name.ToCString(), 9834 type_param_name.ToCString(),
9823 declared_bound_name.ToCString(), 9835 class_name.ToCString(),
9824 bounded_type_name.ToCString(), 9836 declared_bound_name.ToCString(),
9825 upper_bound_name.ToCString()); 9837 bounded_type_name.ToCString(),
9838 upper_bound_name.ToCString());
9839 }
9840 return false;
9826 } 9841 }
9827 9842
9828 9843
9829 intptr_t TypeParameter::Hash() const { 9844 intptr_t TypeParameter::Hash() const {
9830 ASSERT(IsFinalized()); 9845 ASSERT(IsFinalized());
9831 uword result = 0; 9846 uword result = 0;
9832 result += Class::Handle(parameterized_class()).id(); 9847 result += Class::Handle(parameterized_class()).id();
9833 // Do not include the hash of the bound, which could lead to cycles. 9848 // Do not include the hash of the bound, which could lead to cycles.
9834 result <<= index(); 9849 result <<= index();
9835 return FinalizeHash(result); 9850 return FinalizeHash(result);
(...skipping 3219 matching lines...) Expand 10 before | Expand all | Expand 10 after
13055 } 13070 }
13056 return result.raw(); 13071 return result.raw();
13057 } 13072 }
13058 13073
13059 13074
13060 const char* WeakProperty::ToCString() const { 13075 const char* WeakProperty::ToCString() const {
13061 return "_WeakProperty"; 13076 return "_WeakProperty";
13062 } 13077 }
13063 13078
13064 } // namespace dart 13079 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | tests/language/f_bounded_quantification3_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698