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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |