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 |