| 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_ = kDynamicCid; | 600 cid_ = kNullCid; |
| 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() || type.IsVoidType()) { | 687 if (type.IsDynamicType() || type.IsObjectType()) { |
| 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 |
| 699 if (compile_type.IsMalformedOrMalbounded()) { | 704 if (compile_type.IsMalformedOrMalbounded()) { |
| 700 return false; | 705 return false; |
| 701 } | 706 } |
| 702 | 707 |
| 703 // The null instance is an instance of Null, of Object, and of dynamic. | 708 // The null instance is an instance of Null, of Object, and of dynamic. |
| 704 // Functions that do not explicitly return a value, implicitly return null, | 709 // Functions that do not explicitly return a value, implicitly return null, |
| 705 // except generative constructors, which return the object being constructed. | 710 // except generative constructors, which return the object being constructed. |
| 706 // It is therefore acceptable for void functions to return null. | 711 // It is therefore acceptable for void functions to return null. |
| 707 if (compile_type.IsNullType()) { | 712 if (compile_type.IsNullType()) { |
| 708 *is_instance = is_nullable || type.IsObjectType() || type.IsDynamicType() || | 713 *is_instance = is_nullable || type.IsObjectType() || type.IsDynamicType() || |
| 709 type.IsNullType() || type.IsVoidType(); | 714 type.IsNullType() || type.IsVoidType(); |
| 710 return true; | 715 return true; |
| 711 } | 716 } |
| 712 | 717 |
| 718 // A non-null value is not an instance of void. |
| 719 if (type.IsVoidType()) { |
| 720 *is_instance = IsNull(); |
| 721 return HasDecidableNullability(); |
| 722 } |
| 723 |
| 713 // If the value can be null then we can't eliminate the | 724 // If the value can be null then we can't eliminate the |
| 714 // check unless null is allowed. | 725 // check unless null is allowed. |
| 715 if (is_nullable_ && !is_nullable) { | 726 if (is_nullable_ && !is_nullable) { |
| 716 return false; | 727 return false; |
| 717 } | 728 } |
| 718 | 729 |
| 719 *is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld); | 730 *is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld); |
| 720 return *is_instance; | 731 return *is_instance; |
| 721 } | 732 } |
| 722 | 733 |
| 723 | 734 |
| 724 bool CompileType::IsMoreSpecificThan(const AbstractType& other) { | 735 bool CompileType::IsMoreSpecificThan(const AbstractType& other) { |
| 725 if (IsNone()) { | 736 if (IsNone()) { |
| 726 return false; | 737 return false; |
| 727 } | 738 } |
| 728 | 739 |
| 740 if (other.IsVoidType()) { |
| 741 // The only value assignable to void is null. |
| 742 return IsNull(); |
| 743 } |
| 744 |
| 729 return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld); | 745 return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld); |
| 730 } | 746 } |
| 731 | 747 |
| 732 | 748 |
| 733 CompileType* Value::Type() { | 749 CompileType* Value::Type() { |
| 734 if (reaching_type_ == NULL) { | 750 if (reaching_type_ == NULL) { |
| 735 reaching_type_ = definition()->Type(); | 751 reaching_type_ = definition()->Type(); |
| 736 } | 752 } |
| 737 return reaching_type_; | 753 return reaching_type_; |
| 738 } | 754 } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 } | 936 } |
| 921 | 937 |
| 922 | 938 |
| 923 CompileType AssertAssignableInstr::ComputeType() const { | 939 CompileType AssertAssignableInstr::ComputeType() const { |
| 924 CompileType* value_type = value()->Type(); | 940 CompileType* value_type = value()->Type(); |
| 925 | 941 |
| 926 if (value_type->IsMoreSpecificThan(dst_type())) { | 942 if (value_type->IsMoreSpecificThan(dst_type())) { |
| 927 return *value_type; | 943 return *value_type; |
| 928 } | 944 } |
| 929 | 945 |
| 946 if (dst_type().IsVoidType()) { |
| 947 // The only value assignable to void is null. |
| 948 return CompileType::Null(); |
| 949 } |
| 950 |
| 930 return CompileType::Create(value_type->ToCid(), dst_type()); | 951 return CompileType::Create(value_type->ToCid(), dst_type()); |
| 931 } | 952 } |
| 932 | 953 |
| 933 | 954 |
| 934 bool AssertAssignableInstr::RecomputeType() { | 955 bool AssertAssignableInstr::RecomputeType() { |
| 935 return UpdateType(ComputeType()); | 956 return UpdateType(ComputeType()); |
| 936 } | 957 } |
| 937 | 958 |
| 938 | 959 |
| 939 CompileType AssertBooleanInstr::ComputeType() const { | 960 CompileType AssertBooleanInstr::ComputeType() const { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 : CompileType::Dynamic(); | 1031 : CompileType::Dynamic(); |
| 1011 } | 1032 } |
| 1012 | 1033 |
| 1013 | 1034 |
| 1014 CompileType StaticCallInstr::ComputeType() const { | 1035 CompileType StaticCallInstr::ComputeType() const { |
| 1015 if (result_cid_ != kDynamicCid) { | 1036 if (result_cid_ != kDynamicCid) { |
| 1016 return CompileType::FromCid(result_cid_); | 1037 return CompileType::FromCid(result_cid_); |
| 1017 } | 1038 } |
| 1018 | 1039 |
| 1019 if (Isolate::Current()->type_checks()) { | 1040 if (Isolate::Current()->type_checks()) { |
| 1041 // Void functions are known to return null, which is checked at the return |
| 1042 // from the function. |
| 1020 const AbstractType& result_type = | 1043 const AbstractType& result_type = |
| 1021 AbstractType::ZoneHandle(function().result_type()); | 1044 AbstractType::ZoneHandle(function().result_type()); |
| 1022 return CompileType::FromAbstractType(result_type); | 1045 return CompileType::FromAbstractType( |
| 1046 result_type.IsVoidType() ? AbstractType::ZoneHandle(Type::NullType()) |
| 1047 : result_type); |
| 1023 } | 1048 } |
| 1024 | 1049 |
| 1025 return CompileType::Dynamic(); | 1050 return CompileType::Dynamic(); |
| 1026 } | 1051 } |
| 1027 | 1052 |
| 1028 | 1053 |
| 1029 CompileType LoadLocalInstr::ComputeType() const { | 1054 CompileType LoadLocalInstr::ComputeType() const { |
| 1030 if (Isolate::Current()->type_checks()) { | 1055 if (Isolate::Current()->type_checks()) { |
| 1031 return CompileType::FromAbstractType(local().type()); | 1056 return CompileType::FromAbstractType(local().type()); |
| 1032 } | 1057 } |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1519 CompileType MergedMathInstr::ComputeType() const { | 1544 CompileType MergedMathInstr::ComputeType() const { |
| 1520 return CompileType::Dynamic(); | 1545 return CompileType::Dynamic(); |
| 1521 } | 1546 } |
| 1522 | 1547 |
| 1523 | 1548 |
| 1524 CompileType ExtractNthOutputInstr::ComputeType() const { | 1549 CompileType ExtractNthOutputInstr::ComputeType() const { |
| 1525 return CompileType::FromCid(definition_cid_); | 1550 return CompileType::FromCid(definition_cid_); |
| 1526 } | 1551 } |
| 1527 | 1552 |
| 1528 } // namespace dart | 1553 } // namespace dart |
| OLD | NEW |