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 |