| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/flow_graph_type_propagator.h" | 5 #include "vm/flow_graph_type_propagator.h" |
| 6 | 6 |
| 7 #include "vm/cha.h" | 7 #include "vm/cha.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
| 10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| (...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 | 590 |
| 591 | 591 |
| 592 intptr_t CompileType::ToNullableCid() { | 592 intptr_t CompileType::ToNullableCid() { |
| 593 if (cid_ == kIllegalCid) { | 593 if (cid_ == kIllegalCid) { |
| 594 if (type_ == NULL) { | 594 if (type_ == NULL) { |
| 595 // Type propagation is turned off or has not yet run. | 595 // Type propagation is turned off or has not yet run. |
| 596 return kDynamicCid; | 596 return kDynamicCid; |
| 597 } else if (type_->IsMalformed()) { | 597 } else if (type_->IsMalformed()) { |
| 598 cid_ = kDynamicCid; | 598 cid_ = kDynamicCid; |
| 599 } else if (type_->IsVoidType()) { | 599 } else if (type_->IsVoidType()) { |
| 600 cid_ = kNullCid; | 600 cid_ = kDynamicCid; |
| 601 } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) { | 601 } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) { |
| 602 cid_ = kClosureCid; | 602 cid_ = kClosureCid; |
| 603 } else if (type_->HasResolvedTypeClass()) { | 603 } else if (type_->HasResolvedTypeClass()) { |
| 604 const Class& type_class = Class::Handle(type_->type_class()); | 604 const Class& type_class = Class::Handle(type_->type_class()); |
| 605 Thread* thread = Thread::Current(); | 605 Thread* thread = Thread::Current(); |
| 606 CHA* cha = thread->cha(); | 606 CHA* cha = thread->cha(); |
| 607 // Don't infer a cid from an abstract type since there can be multiple | 607 // Don't infer a cid from an abstract type since there can be multiple |
| 608 // compatible classes with different cids. | 608 // compatible classes with different cids. |
| 609 if (!CHA::IsImplemented(type_class) && !CHA::HasSubclasses(type_class)) { | 609 if (!CHA::IsImplemented(type_class) && !CHA::HasSubclasses(type_class)) { |
| 610 if (type_class.IsPrivate()) { | 610 if (type_class.IsPrivate()) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 | 677 |
| 678 bool CompileType::CanComputeIsInstanceOf(const AbstractType& type, | 678 bool CompileType::CanComputeIsInstanceOf(const AbstractType& type, |
| 679 bool is_nullable, | 679 bool is_nullable, |
| 680 bool* is_instance) { | 680 bool* is_instance) { |
| 681 ASSERT(is_instance != NULL); | 681 ASSERT(is_instance != NULL); |
| 682 // We cannot give an answer if the given type is malformed or malbounded. | 682 // We cannot give an answer if the given type is malformed or malbounded. |
| 683 if (type.IsMalformedOrMalbounded()) { | 683 if (type.IsMalformedOrMalbounded()) { |
| 684 return false; | 684 return false; |
| 685 } | 685 } |
| 686 | 686 |
| 687 if (type.IsDynamicType() || type.IsObjectType()) { | 687 if (type.IsDynamicType() || type.IsObjectType() || type.IsVoidType()) { |
| 688 *is_instance = true; | 688 *is_instance = true; |
| 689 return true; | 689 return true; |
| 690 } | 690 } |
| 691 | 691 |
| 692 if (IsNone()) { | 692 if (IsNone()) { |
| 693 return false; | 693 return false; |
| 694 } | 694 } |
| 695 | 695 |
| 696 // Consider the compile type of the value. | 696 // Consider the compile type of the value. |
| 697 const AbstractType& compile_type = *ToAbstractType(); | 697 const AbstractType& compile_type = *ToAbstractType(); |
| 698 | 698 |
| 699 // The compile-type of a value should never be void. The result of a void | |
| 700 // function must always be null, which was checked to be null at the return | |
| 701 // statement inside the function. | |
| 702 ASSERT(!compile_type.IsVoidType()); | |
| 703 | |
| 704 if (compile_type.IsMalformedOrMalbounded()) { | 699 if (compile_type.IsMalformedOrMalbounded()) { |
| 705 return false; | 700 return false; |
| 706 } | 701 } |
| 707 | 702 |
| 708 // The null instance is an instance of Null, of Object, and of dynamic. | 703 // The null instance is an instance of Null, of Object, and of dynamic. |
| 709 // Functions that do not explicitly return a value, implicitly return null, | 704 // Functions that do not explicitly return a value, implicitly return null, |
| 710 // except generative constructors, which return the object being constructed. | 705 // except generative constructors, which return the object being constructed. |
| 711 // It is therefore acceptable for void functions to return null. | 706 // It is therefore acceptable for void functions to return null. |
| 712 if (compile_type.IsNullType()) { | 707 if (compile_type.IsNullType()) { |
| 713 *is_instance = is_nullable || type.IsObjectType() || type.IsDynamicType() || | 708 *is_instance = is_nullable || type.IsObjectType() || type.IsDynamicType() || |
| 714 type.IsNullType() || type.IsVoidType(); | 709 type.IsNullType() || type.IsVoidType(); |
| 715 return true; | 710 return true; |
| 716 } | 711 } |
| 717 | 712 |
| 718 // A non-null value is not an instance of void. | |
| 719 if (type.IsVoidType()) { | |
| 720 *is_instance = IsNull(); | |
| 721 return HasDecidableNullability(); | |
| 722 } | |
| 723 | |
| 724 // If the value can be null then we can't eliminate the | 713 // If the value can be null then we can't eliminate the |
| 725 // check unless null is allowed. | 714 // check unless null is allowed. |
| 726 if (is_nullable_ && !is_nullable) { | 715 if (is_nullable_ && !is_nullable) { |
| 727 return false; | 716 return false; |
| 728 } | 717 } |
| 729 | 718 |
| 730 *is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld); | 719 *is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld); |
| 731 return *is_instance; | 720 return *is_instance; |
| 732 } | 721 } |
| 733 | 722 |
| 734 | 723 |
| 735 bool CompileType::IsMoreSpecificThan(const AbstractType& other) { | 724 bool CompileType::IsMoreSpecificThan(const AbstractType& other) { |
| 736 if (IsNone()) { | 725 if (IsNone()) { |
| 737 return false; | 726 return false; |
| 738 } | 727 } |
| 739 | 728 |
| 740 if (other.IsVoidType()) { | |
| 741 // The only value assignable to void is null. | |
| 742 return IsNull(); | |
| 743 } | |
| 744 | |
| 745 return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld); | 729 return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld); |
| 746 } | 730 } |
| 747 | 731 |
| 748 | 732 |
| 749 CompileType* Value::Type() { | 733 CompileType* Value::Type() { |
| 750 if (reaching_type_ == NULL) { | 734 if (reaching_type_ == NULL) { |
| 751 reaching_type_ = definition()->Type(); | 735 reaching_type_ = definition()->Type(); |
| 752 } | 736 } |
| 753 return reaching_type_; | 737 return reaching_type_; |
| 754 } | 738 } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 } | 920 } |
| 937 | 921 |
| 938 | 922 |
| 939 CompileType AssertAssignableInstr::ComputeType() const { | 923 CompileType AssertAssignableInstr::ComputeType() const { |
| 940 CompileType* value_type = value()->Type(); | 924 CompileType* value_type = value()->Type(); |
| 941 | 925 |
| 942 if (value_type->IsMoreSpecificThan(dst_type())) { | 926 if (value_type->IsMoreSpecificThan(dst_type())) { |
| 943 return *value_type; | 927 return *value_type; |
| 944 } | 928 } |
| 945 | 929 |
| 946 if (dst_type().IsVoidType()) { | |
| 947 // The only value assignable to void is null. | |
| 948 return CompileType::Null(); | |
| 949 } | |
| 950 | |
| 951 return CompileType::Create(value_type->ToCid(), dst_type()); | 930 return CompileType::Create(value_type->ToCid(), dst_type()); |
| 952 } | 931 } |
| 953 | 932 |
| 954 | 933 |
| 955 bool AssertAssignableInstr::RecomputeType() { | 934 bool AssertAssignableInstr::RecomputeType() { |
| 956 return UpdateType(ComputeType()); | 935 return UpdateType(ComputeType()); |
| 957 } | 936 } |
| 958 | 937 |
| 959 | 938 |
| 960 CompileType AssertBooleanInstr::ComputeType() const { | 939 CompileType AssertBooleanInstr::ComputeType() const { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 : CompileType::Dynamic(); | 1010 : CompileType::Dynamic(); |
| 1032 } | 1011 } |
| 1033 | 1012 |
| 1034 | 1013 |
| 1035 CompileType StaticCallInstr::ComputeType() const { | 1014 CompileType StaticCallInstr::ComputeType() const { |
| 1036 if (result_cid_ != kDynamicCid) { | 1015 if (result_cid_ != kDynamicCid) { |
| 1037 return CompileType::FromCid(result_cid_); | 1016 return CompileType::FromCid(result_cid_); |
| 1038 } | 1017 } |
| 1039 | 1018 |
| 1040 if (Isolate::Current()->type_checks()) { | 1019 if (Isolate::Current()->type_checks()) { |
| 1041 // Void functions are known to return null, which is checked at the return | |
| 1042 // from the function. | |
| 1043 const AbstractType& result_type = | 1020 const AbstractType& result_type = |
| 1044 AbstractType::ZoneHandle(function().result_type()); | 1021 AbstractType::ZoneHandle(function().result_type()); |
| 1045 return CompileType::FromAbstractType( | 1022 return CompileType::FromAbstractType(result_type); |
| 1046 result_type.IsVoidType() ? AbstractType::ZoneHandle(Type::NullType()) | |
| 1047 : result_type); | |
| 1048 } | 1023 } |
| 1049 | 1024 |
| 1050 return CompileType::Dynamic(); | 1025 return CompileType::Dynamic(); |
| 1051 } | 1026 } |
| 1052 | 1027 |
| 1053 | 1028 |
| 1054 CompileType LoadLocalInstr::ComputeType() const { | 1029 CompileType LoadLocalInstr::ComputeType() const { |
| 1055 if (Isolate::Current()->type_checks()) { | 1030 if (Isolate::Current()->type_checks()) { |
| 1056 return CompileType::FromAbstractType(local().type()); | 1031 return CompileType::FromAbstractType(local().type()); |
| 1057 } | 1032 } |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 CompileType MergedMathInstr::ComputeType() const { | 1519 CompileType MergedMathInstr::ComputeType() const { |
| 1545 return CompileType::Dynamic(); | 1520 return CompileType::Dynamic(); |
| 1546 } | 1521 } |
| 1547 | 1522 |
| 1548 | 1523 |
| 1549 CompileType ExtractNthOutputInstr::ComputeType() const { | 1524 CompileType ExtractNthOutputInstr::ComputeType() const { |
| 1550 return CompileType::FromCid(definition_cid_); | 1525 return CompileType::FromCid(definition_cid_); |
| 1551 } | 1526 } |
| 1552 | 1527 |
| 1553 } // namespace dart | 1528 } // namespace dart |
| OLD | NEW |