| 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 |