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

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

Issue 75713002: Distinguish between malformed and malbounded types more efficiently using the (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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') | 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/cpu.h" 10 #include "vm/cpu.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 "Show names of internal classes (e.g. \"OneByteString\") in error messages " 55 "Show names of internal classes (e.g. \"OneByteString\") in error messages "
56 "instead of showing the corresponding interface names (e.g. \"String\")"); 56 "instead of showing the corresponding interface names (e.g. \"String\")");
57 DEFINE_FLAG(bool, trace_disabling_optimized_code, false, 57 DEFINE_FLAG(bool, trace_disabling_optimized_code, false,
58 "Trace disabling optimized code."); 58 "Trace disabling optimized code.");
59 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, 59 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
60 "Throw an exception when the result of an integer calculation will not " 60 "Throw an exception when the result of an integer calculation will not "
61 "fit into a javascript integer."); 61 "fit into a javascript integer.");
62 DECLARE_FLAG(bool, eliminate_type_checks); 62 DECLARE_FLAG(bool, eliminate_type_checks);
63 DECLARE_FLAG(bool, enable_type_checks); 63 DECLARE_FLAG(bool, enable_type_checks);
64 DECLARE_FLAG(bool, error_on_bad_override); 64 DECLARE_FLAG(bool, error_on_bad_override);
65 DECLARE_FLAG(bool, error_on_bad_type);
66 DECLARE_FLAG(bool, trace_compiler); 65 DECLARE_FLAG(bool, trace_compiler);
67 DECLARE_FLAG(bool, trace_deoptimization); 66 DECLARE_FLAG(bool, trace_deoptimization);
68 DECLARE_FLAG(bool, trace_deoptimization_verbose); 67 DECLARE_FLAG(bool, trace_deoptimization_verbose);
69 DECLARE_FLAG(bool, verbose_stacktrace); 68 DECLARE_FLAG(bool, verbose_stacktrace);
70 DECLARE_FLAG(charp, coverage_dir); 69 DECLARE_FLAG(charp, coverage_dir);
71 70
72 static const char* kGetterPrefix = "get:"; 71 static const char* kGetterPrefix = "get:";
73 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); 72 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
74 static const char* kSetterPrefix = "set:"; 73 static const char* kSetterPrefix = "set:";
75 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); 74 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix);
(...skipping 2770 matching lines...) Expand 10 before | Expand all | Expand 10 after
2846 Error& error = Error::Handle(); 2845 Error& error = Error::Handle();
2847 for (intptr_t i = 0; i < interfaces.Length(); i++) { 2846 for (intptr_t i = 0; i < interfaces.Length(); i++) {
2848 interface ^= interfaces.At(i); 2847 interface ^= interfaces.At(i);
2849 if (!interface.IsFinalized()) { 2848 if (!interface.IsFinalized()) {
2850 // We may be checking bounds at finalization time and can encounter 2849 // We may be checking bounds at finalization time and can encounter
2851 // a still unfinalized interface. 2850 // a still unfinalized interface.
2852 ClassFinalizer::FinalizeType( 2851 ClassFinalizer::FinalizeType(
2853 thsi, interface, ClassFinalizer::kCanonicalize); 2852 thsi, interface, ClassFinalizer::kCanonicalize);
2854 interfaces.SetAt(i, interface); 2853 interfaces.SetAt(i, interface);
2855 } 2854 }
2856 error = Error::null(); 2855 if (interface.IsMalbounded()) {
2857 if (interface.IsMalboundedWithError(&error)) {
2858 // Return the first bound error to the caller if it requests it. 2856 // Return the first bound error to the caller if it requests it.
2859 if ((bound_error != NULL) && bound_error->IsNull()) { 2857 if ((bound_error != NULL) && bound_error->IsNull()) {
2860 ASSERT(!error.IsNull()); 2858 *bound_error = interface.error();
2861 *bound_error = error.raw();
2862 } 2859 }
2863 continue; // Another interface may work better. 2860 continue; // Another interface may work better.
2864 } 2861 }
2865 interface_class = interface.type_class(); 2862 interface_class = interface.type_class();
2866 interface_args = interface.arguments(); 2863 interface_args = interface.arguments();
2867 if (!interface_args.IsNull() && !interface_args.IsInstantiated()) { 2864 if (!interface_args.IsNull() && !interface_args.IsInstantiated()) {
2868 // This type class implements an interface that is parameterized with 2865 // This type class implements an interface that is parameterized with
2869 // generic type(s), e.g. it implements List<T>. 2866 // generic type(s), e.g. it implements List<T>.
2870 // The uninstantiated type T must be instantiated using the type 2867 // The uninstantiated type T must be instantiated using the type
2871 // parameters of this type before performing the type test. 2868 // parameters of this type before performing the type test.
(...skipping 8533 matching lines...) Expand 10 before | Expand all | Expand 10 after
11405 } 11402 }
11406 11403
11407 11404
11408 bool AbstractType::IsMalformed() const { 11405 bool AbstractType::IsMalformed() const {
11409 // AbstractType is an abstract class. 11406 // AbstractType is an abstract class.
11410 UNREACHABLE(); 11407 UNREACHABLE();
11411 return false; 11408 return false;
11412 } 11409 }
11413 11410
11414 11411
11415 bool AbstractType::IsMalboundedWithError(Error* bound_error) const { 11412 bool AbstractType::IsMalbounded() const {
11416 // AbstractType is an abstract class. 11413 // AbstractType is an abstract class.
11417 UNREACHABLE(); 11414 UNREACHABLE();
11418 return false; 11415 return false;
11419 } 11416 }
11420 11417
11421 11418
11422 RawError* AbstractType::malformed_error() const { 11419 bool AbstractType::IsMalformedOrMalbounded() const {
11423 // AbstractType is an abstract class. 11420 // AbstractType is an abstract class.
11424 UNREACHABLE(); 11421 UNREACHABLE();
11425 return Error::null(); 11422 return false;
11426 } 11423 }
11427 11424
11428 11425
11429 void AbstractType::set_malformed_error(const Error& value) const { 11426 RawLanguageError* AbstractType::error() const {
11427 // AbstractType is an abstract class.
11428 UNREACHABLE();
11429 return LanguageError::null();
11430 }
11431
11432
11433 void AbstractType::set_error(const LanguageError& value) const {
11430 // AbstractType is an abstract class. 11434 // AbstractType is an abstract class.
11431 UNREACHABLE(); 11435 UNREACHABLE();
11432 } 11436 }
11433 11437
11434 11438
11435 bool AbstractType::Equals(const Instance& other) const { 11439 bool AbstractType::Equals(const Instance& other) const {
11436 // AbstractType is an abstract class. 11440 // AbstractType is an abstract class.
11437 ASSERT(raw() == AbstractType::null()); 11441 ASSERT(raw() == AbstractType::null());
11438 return other.IsNull(); 11442 return other.IsNull();
11439 } 11443 }
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
11648 return false; 11652 return false;
11649 } 11653 }
11650 // In case the type checked in a type test is malbounded, the code generator 11654 // In case the type checked in a type test is malbounded, the code generator
11651 // may compile a throw instead of a run time call performing the type check. 11655 // may compile a throw instead of a run time call performing the type check.
11652 // However, in checked mode, a function type may include malbounded result 11656 // However, in checked mode, a function type may include malbounded result
11653 // type and/or malbounded parameter types, which will then be encountered here 11657 // type and/or malbounded parameter types, which will then be encountered here
11654 // at run time. 11658 // at run time.
11655 if (IsMalbounded()) { 11659 if (IsMalbounded()) {
11656 ASSERT(FLAG_enable_type_checks); 11660 ASSERT(FLAG_enable_type_checks);
11657 if ((bound_error != NULL) && bound_error->IsNull()) { 11661 if ((bound_error != NULL) && bound_error->IsNull()) {
11658 const bool is_malbounded = IsMalboundedWithError(bound_error); 11662 *bound_error = error();
11659 ASSERT(is_malbounded);
11660 } 11663 }
11661 return false; 11664 return false;
11662 } 11665 }
11663 if (other.IsMalbounded()) { 11666 if (other.IsMalbounded()) {
11664 ASSERT(FLAG_enable_type_checks); 11667 ASSERT(FLAG_enable_type_checks);
11665 if ((bound_error != NULL) && bound_error->IsNull()) { 11668 if ((bound_error != NULL) && bound_error->IsNull()) {
11666 const bool other_is_malbounded = other.IsMalboundedWithError(bound_error); 11669 *bound_error = other.error();
11667 ASSERT(other_is_malbounded);
11668 } 11670 }
11669 return false; 11671 return false;
11670 } 11672 }
11671 if (IsBoundedType() || other.IsBoundedType()) { 11673 if (IsBoundedType() || other.IsBoundedType()) {
11672 if (Equals(other)) { 11674 if (Equals(other)) {
11673 return true; 11675 return true;
11674 } 11676 }
11675 return false; // TODO(regis): We should return "maybe after instantiation". 11677 return false; // TODO(regis): We should return "maybe after instantiation".
11676 } 11678 }
11677 // Type parameters cannot be handled by Class::TypeTest(). 11679 // Type parameters cannot be handled by Class::TypeTest().
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
11836 } 11838 }
11837 11839
11838 11840
11839 void Type::set_is_being_finalized() const { 11841 void Type::set_is_being_finalized() const {
11840 ASSERT(!IsFinalized() && !IsBeingFinalized()); 11842 ASSERT(!IsFinalized() && !IsBeingFinalized());
11841 set_type_state(RawType::kBeingFinalized); 11843 set_type_state(RawType::kBeingFinalized);
11842 } 11844 }
11843 11845
11844 11846
11845 bool Type::IsMalformed() const { 11847 bool Type::IsMalformed() const {
11846 return raw_ptr()->malformed_error_ != Error::null(); 11848 if (raw_ptr()->error_ == LanguageError::null()) {
11849 return false;
11850 }
11851 const LanguageError& type_error = LanguageError::Handle(error());
11852 return type_error.kind() == LanguageError::kMalformedType;
11847 } 11853 }
11848 11854
11849 11855
11850 bool Type::IsMalboundedWithError(Error* bound_error) const { 11856 bool Type::IsMalbounded() const {
11851 if (!FLAG_enable_type_checks && !FLAG_error_on_bad_type) { 11857 if (!FLAG_enable_type_checks) {
11852 return false; 11858 return false;
11853 } 11859 }
11854 ASSERT(IsResolved()); 11860 if (raw_ptr()->error_ == LanguageError::null()) {
11855 ASSERT(!IsMalformed()); // Must be checked first.
11856 if (arguments() == AbstractTypeArguments::null()) {
11857 return false; 11861 return false;
11858 } 11862 }
11859 const AbstractTypeArguments& type_arguments = 11863 const LanguageError& type_error = LanguageError::Handle(error());
11860 AbstractTypeArguments::Handle(arguments()); 11864 return type_error.kind() == LanguageError::kMalboundedType;
11861 const intptr_t num_type_args = type_arguments.Length();
11862 AbstractType& type_arg = AbstractType::Handle();
11863 for (intptr_t i = 0; i < num_type_args; i++) {
11864 type_arg = type_arguments.TypeAt(i);
11865 ASSERT(!type_arg.IsNull());
11866 if (type_arg.IsMalboundedWithError(bound_error)) {
11867 return true;
11868 }
11869 }
11870 return false;
11871 } 11865 }
11872 11866
11873 11867
11874 void Type::set_malformed_error(const Error& value) const { 11868 bool Type::IsMalformedOrMalbounded() const {
11875 StorePointer(&raw_ptr()->malformed_error_, value.raw()); 11869 if (raw_ptr()->error_ == LanguageError::null()) {
11870 return false;
11871 }
11872 const LanguageError& type_error = LanguageError::Handle(error());
11873 if (type_error.kind() == LanguageError::kMalformedType) {
11874 return true;
11875 }
11876 ASSERT(type_error.kind() == LanguageError::kMalboundedType);
11877 return FLAG_enable_type_checks;
11876 } 11878 }
11877 11879
11878 11880
11879 RawError* Type::malformed_error() const { 11881 void Type::set_error(const LanguageError& value) const {
11880 ASSERT(IsMalformed()); 11882 StorePointer(&raw_ptr()->error_, value.raw());
11881 return raw_ptr()->malformed_error_;
11882 } 11883 }
11883 11884
11884 11885
11885 bool Type::IsResolved() const { 11886 bool Type::IsResolved() const {
11886 if (IsFinalized()) { 11887 if (IsFinalized()) {
11887 return true; 11888 return true;
11888 } 11889 }
11889 if (!HasResolvedTypeClass()) { 11890 if (!HasResolvedTypeClass()) {
11890 return false; 11891 return false;
11891 } 11892 }
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
12375 void TypeParameter::PrintToJSONStream(JSONStream* stream, bool ref) const { 12376 void TypeParameter::PrintToJSONStream(JSONStream* stream, bool ref) const {
12376 JSONObject jsobj(stream); 12377 JSONObject jsobj(stream);
12377 } 12378 }
12378 12379
12379 12380
12380 bool BoundedType::IsMalformed() const { 12381 bool BoundedType::IsMalformed() const {
12381 return AbstractType::Handle(type()).IsMalformed(); 12382 return AbstractType::Handle(type()).IsMalformed();
12382 } 12383 }
12383 12384
12384 12385
12385 bool BoundedType::IsMalboundedWithError(Error* bound_error) const { 12386 bool BoundedType::IsMalbounded() const {
12386 if (FLAG_enable_type_checks || FLAG_error_on_bad_type) { 12387 return AbstractType::Handle(type()).IsMalbounded();
12387 const AbstractType& upper_bound = AbstractType::Handle(bound());
12388 if (upper_bound.IsMalformed()) {
12389 if (bound_error != NULL) {
12390 *bound_error = upper_bound.malformed_error();
12391 ASSERT(!bound_error->IsNull());
12392 }
12393 return true;
12394 }
12395 }
12396 return AbstractType::Handle(type()).IsMalboundedWithError(bound_error);
12397 } 12388 }
12398 12389
12399 12390
12400 RawError* BoundedType::malformed_error() const { 12391 bool BoundedType::IsMalformedOrMalbounded() const {
12401 return AbstractType::Handle(type()).malformed_error(); 12392 return AbstractType::Handle(type()).IsMalformedOrMalbounded();
12393 }
12394
12395
12396 RawLanguageError* BoundedType::error() const {
12397 return AbstractType::Handle(type()).error();
12402 } 12398 }
12403 12399
12404 12400
12405 bool BoundedType::Equals(const Instance& other) const { 12401 bool BoundedType::Equals(const Instance& other) const {
12406 // BoundedType are not canonicalized, because their bound may get finalized 12402 // BoundedType are not canonicalized, because their bound may get finalized
12407 // after the BoundedType is created and initialized. 12403 // after the BoundedType is created and initialized.
12408 if (raw() == other.raw()) { 12404 if (raw() == other.raw()) {
12409 return true; 12405 return true;
12410 } 12406 }
12411 if (!other.IsBoundedType()) { 12407 if (!other.IsBoundedType()) {
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
12538 const BoundedType& result = BoundedType::Handle(BoundedType::New()); 12534 const BoundedType& result = BoundedType::Handle(BoundedType::New());
12539 result.set_type(type); 12535 result.set_type(type);
12540 result.set_bound(bound); 12536 result.set_bound(bound);
12541 result.set_type_parameter(type_parameter); 12537 result.set_type_parameter(type_parameter);
12542 result.set_is_being_checked(false); 12538 result.set_is_being_checked(false);
12543 return result.raw(); 12539 return result.raw();
12544 } 12540 }
12545 12541
12546 12542
12547 const char* BoundedType::ToCString() const { 12543 const char* BoundedType::ToCString() const {
12548 const char* format = "BoundedType: type %s; bound: %s; type param: %s%s%s"; 12544 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s";
12549 const char* type_cstr = String::Handle(AbstractType::Handle( 12545 const char* type_cstr = String::Handle(AbstractType::Handle(
12550 type()).Name()).ToCString(); 12546 type()).Name()).ToCString();
12551 const char* bound_cstr = String::Handle(AbstractType::Handle( 12547 const char* bound_cstr = String::Handle(AbstractType::Handle(
12552 bound()).Name()).ToCString(); 12548 bound()).Name()).ToCString();
12553 const TypeParameter& type_param = TypeParameter::Handle(type_parameter()); 12549 const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
12554 const char* type_param_cstr = "null"; 12550 const char* type_param_cstr = String::Handle(type_param.name()).ToCString();
12555 const char* of_cstr = ""; 12551 const Class& cls = Class::Handle(type_param.parameterized_class());
12556 const char* cls_cstr = ""; 12552 const char* cls_cstr = String::Handle(cls.Name()).ToCString();
12557 if (!type_param.IsNull()) { 12553 intptr_t len = OS::SNPrint(
12558 type_param_cstr = String::Handle(type_param.name()).ToCString(); 12554 NULL, 0, format, type_cstr, bound_cstr, type_param_cstr, cls_cstr) + 1;
12559 const Class& cls = Class::Handle(type_param.parameterized_class());
12560 if (!cls.IsNull()) {
12561 of_cstr = " of ";
12562 cls_cstr = String::Handle(cls.Name()).ToCString();
12563 }
12564 }
12565 intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr, bound_cstr,
12566 type_param_cstr, of_cstr, cls_cstr) + 1;
12567 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 12555 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
12568 OS::SNPrint(chars, len, format, type_cstr, bound_cstr, type_param_cstr, 12556 OS::SNPrint(
12569 of_cstr, cls_cstr); 12557 chars, len, format, type_cstr, bound_cstr, type_param_cstr, cls_cstr);
12570 return chars; 12558 return chars;
12571 } 12559 }
12572 12560
12573 12561
12574 void BoundedType::PrintToJSONStream(JSONStream* stream, bool ref) const { 12562 void BoundedType::PrintToJSONStream(JSONStream* stream, bool ref) const {
12575 JSONObject jsobj(stream); 12563 JSONObject jsobj(stream);
12576 } 12564 }
12577 12565
12578 12566
12579 intptr_t MixinAppType::token_pos() const { 12567 intptr_t MixinAppType::token_pos() const {
(...skipping 3348 matching lines...) Expand 10 before | Expand all | Expand 10 after
15928 return "_MirrorReference"; 15916 return "_MirrorReference";
15929 } 15917 }
15930 15918
15931 15919
15932 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 15920 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
15933 JSONObject jsobj(stream); 15921 JSONObject jsobj(stream);
15934 } 15922 }
15935 15923
15936 15924
15937 } // namespace dart 15925 } // 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