| 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 return false; | 52 return false; |
| 53 } | 53 } |
| 54 ConstantVal* constant = bind->computation()->AsConstant(); | 54 ConstantVal* constant = bind->computation()->AsConstant(); |
| 55 if (constant != NULL) { | 55 if (constant != NULL) { |
| 56 return constant->value().IsNull(); | 56 return constant->value().IsNull(); |
| 57 } | 57 } |
| 58 return false; | 58 return false; |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 const Object& UseVal::BoundConstant() const { |
| 63 ASSERT(BindsToConstant()); |
| 64 BindInstr* bind = definition()->AsBind(); |
| 65 ASSERT(bind != NULL); |
| 66 ConstantVal* constant = bind->computation()->AsConstant(); |
| 67 ASSERT(constant != NULL); |
| 68 return constant->value(); |
| 69 } |
| 70 |
| 71 |
| 62 void UseVal::RemoveFromUseList() { | 72 void UseVal::RemoveFromUseList() { |
| 63 ASSERT(definition_ != NULL); | 73 ASSERT(definition_ != NULL); |
| 64 if (next_use_ != NULL) { | 74 if (next_use_ != NULL) { |
| 65 next_use_->previous_use_ = previous_use_; | 75 next_use_->previous_use_ = previous_use_; |
| 66 } | 76 } |
| 67 if (previous_use_ != NULL) { | 77 if (previous_use_ != NULL) { |
| 68 previous_use_->next_use_ = next_use_; | 78 previous_use_->next_use_ = next_use_; |
| 69 } else { | 79 } else { |
| 70 // This is the head of the list. | 80 // This is the head of the list. |
| 71 ASSERT(definition_->use_list() == this); | 81 ASSERT(definition_->use_list() == this); |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 (receiver_class_id() == kNumberCid)) { | 739 (receiver_class_id() == kNumberCid)) { |
| 730 return Type::BoolInterface(); | 740 return Type::BoolInterface(); |
| 731 } | 741 } |
| 732 if (HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid)) { | 742 if (HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid)) { |
| 733 return Type::BoolInterface(); | 743 return Type::BoolInterface(); |
| 734 } | 744 } |
| 735 return Type::DynamicType(); | 745 return Type::DynamicType(); |
| 736 } | 746 } |
| 737 | 747 |
| 738 | 748 |
| 749 intptr_t EqualityCompareComp::ResultCid() const { |
| 750 if ((receiver_class_id() == kSmiCid) || |
| 751 (receiver_class_id() == kDoubleCid) || |
| 752 (receiver_class_id() == kNumberCid)) { |
| 753 // Known/library equalities that are guaranteed to return Boolean. |
| 754 return kBoolCid; |
| 755 } |
| 756 if (HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid)) { |
| 757 return kBoolCid; |
| 758 } |
| 759 return kDynamicCid; |
| 760 } |
| 761 |
| 762 |
| 739 RawAbstractType* RelationalOpComp::CompileType() const { | 763 RawAbstractType* RelationalOpComp::CompileType() const { |
| 740 if ((operands_class_id() == kSmiCid) || | 764 if ((operands_class_id() == kSmiCid) || |
| 741 (operands_class_id() == kDoubleCid) || | 765 (operands_class_id() == kDoubleCid) || |
| 742 (operands_class_id() == kNumberCid)) { | 766 (operands_class_id() == kNumberCid)) { |
| 767 // Known/library relational ops that are guaranteed to return Boolean. |
| 743 return Type::BoolInterface(); | 768 return Type::BoolInterface(); |
| 744 } | 769 } |
| 745 return Type::DynamicType(); | 770 return Type::DynamicType(); |
| 746 } | 771 } |
| 747 | 772 |
| 748 | 773 |
| 774 intptr_t RelationalOpComp::ResultCid() const { |
| 775 if ((operands_class_id() == kSmiCid) || |
| 776 (operands_class_id() == kDoubleCid) || |
| 777 (operands_class_id() == kNumberCid)) { |
| 778 // Known/library relational ops that are guaranteed to return Boolean. |
| 779 return kBoolCid; |
| 780 } |
| 781 return kDynamicCid; |
| 782 } |
| 783 |
| 784 |
| 749 RawAbstractType* NativeCallComp::CompileType() const { | 785 RawAbstractType* NativeCallComp::CompileType() const { |
| 750 // The result type of the native function is identical to the result type of | 786 // The result type of the native function is identical to the result type of |
| 751 // the enclosing native Dart function. However, we prefer to check the type | 787 // the enclosing native Dart function. However, we prefer to check the type |
| 752 // of the value returned from the native call. | 788 // of the value returned from the native call. |
| 753 return Type::DynamicType(); | 789 return Type::DynamicType(); |
| 754 } | 790 } |
| 755 | 791 |
| 756 | 792 |
| 757 RawAbstractType* LoadIndexedComp::CompileType() const { | 793 RawAbstractType* LoadIndexedComp::CompileType() const { |
| 758 return Type::DynamicType(); | 794 return Type::DynamicType(); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 return AbstractType::null(); | 906 return AbstractType::null(); |
| 871 } | 907 } |
| 872 | 908 |
| 873 | 909 |
| 874 RawAbstractType* CheckStackOverflowComp::CompileType() const { | 910 RawAbstractType* CheckStackOverflowComp::CompileType() const { |
| 875 return AbstractType::null(); | 911 return AbstractType::null(); |
| 876 } | 912 } |
| 877 | 913 |
| 878 | 914 |
| 879 RawAbstractType* BinaryOpComp::CompileType() const { | 915 RawAbstractType* BinaryOpComp::CompileType() const { |
| 880 // TODO(srdjan): Convert to use with class-ids instead of types. | 916 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 881 if (operands_type() == kMintOperands) { | 917 if (operands_type() == kMintOperands) { |
| 882 return Isolate::Current()->object_store()->mint_type(); | 918 return object_store->mint_type(); |
| 883 } else if (op_kind() == Token::kSHL) { | 919 } |
| 920 if (op_kind() == Token::kSHL) { |
| 884 return Type::IntInterface(); | 921 return Type::IntInterface(); |
| 885 } else { | |
| 886 ASSERT(operands_type() == kSmiOperands); | |
| 887 return Isolate::Current()->object_store()->smi_type(); | |
| 888 } | 922 } |
| 923 ASSERT(operands_type() == kSmiOperands); |
| 924 return object_store->smi_type(); |
| 925 } |
| 926 |
| 927 |
| 928 intptr_t BinaryOpComp::ResultCid() const { |
| 929 if (operands_type() == kMintOperands) { |
| 930 return kMintCid; |
| 931 } |
| 932 ASSERT(operands_type() == kSmiOperands); |
| 933 return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid; |
| 889 } | 934 } |
| 890 | 935 |
| 891 | 936 |
| 892 RawAbstractType* DoubleBinaryOpComp::CompileType() const { | 937 RawAbstractType* DoubleBinaryOpComp::CompileType() const { |
| 893 return Type::DoubleInterface(); | 938 return Type::DoubleInterface(); |
| 894 } | 939 } |
| 895 | 940 |
| 896 | 941 |
| 942 intptr_t DoubleBinaryOpComp::ResultCid() const { |
| 943 return kDoubleCid; |
| 944 } |
| 945 |
| 946 |
| 897 RawAbstractType* UnarySmiOpComp::CompileType() const { | 947 RawAbstractType* UnarySmiOpComp::CompileType() const { |
| 898 return Type::IntInterface(); | 948 return Type::IntInterface(); |
| 899 } | 949 } |
| 900 | 950 |
| 901 | 951 |
| 902 RawAbstractType* NumberNegateComp::CompileType() const { | 952 RawAbstractType* NumberNegateComp::CompileType() const { |
| 903 return Type::NumberInterface(); | 953 // Implemented only for doubles. |
| 954 return Type::DoubleInterface(); |
| 904 } | 955 } |
| 905 | 956 |
| 906 | 957 |
| 907 RawAbstractType* DoubleToDoubleComp::CompileType() const { | 958 RawAbstractType* DoubleToDoubleComp::CompileType() const { |
| 908 return Type::DoubleInterface(); | 959 return Type::DoubleInterface(); |
| 909 } | 960 } |
| 910 | 961 |
| 911 | 962 |
| 912 RawAbstractType* SmiToDoubleComp::CompileType() const { | 963 RawAbstractType* SmiToDoubleComp::CompileType() const { |
| 913 return Type::DoubleInterface(); | 964 return Type::DoubleInterface(); |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 } | 1162 } |
| 1112 | 1163 |
| 1113 | 1164 |
| 1114 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1165 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1115 // Nothing to do. Context register were loaded by register allocator. | 1166 // Nothing to do. Context register were loaded by register allocator. |
| 1116 ASSERT(locs()->in(0).reg() == CTX); | 1167 ASSERT(locs()->in(0).reg() == CTX); |
| 1117 } | 1168 } |
| 1118 | 1169 |
| 1119 | 1170 |
| 1120 Definition* StrictCompareComp::TryReplace(BindInstr* instr) { | 1171 Definition* StrictCompareComp::TryReplace(BindInstr* instr) { |
| 1121 // TODO(srdjan): Do not use CompileType for class check elimination. | |
| 1122 return NULL; | |
| 1123 UseVal* left_use = left()->AsUse(); | 1172 UseVal* left_use = left()->AsUse(); |
| 1124 UseVal* right_use = right()->AsUse(); | 1173 UseVal* right_use = right()->AsUse(); |
| 1125 if ((right_use == NULL) || (left_use == NULL)) return NULL; | 1174 if ((right_use == NULL) || (left_use == NULL)) return NULL; |
| 1175 if (!right_use->BindsToConstant()) return NULL; |
| 1176 const Object& right_constant = right_use->BoundConstant(); |
| 1126 Definition* left = left_use->definition(); | 1177 Definition* left = left_use->definition(); |
| 1127 BindInstr* right = right_use->definition()->AsBind(); | |
| 1128 if (right == NULL) return NULL; | |
| 1129 ConstantVal* right_constant = right->computation()->AsConstant(); | |
| 1130 if (right_constant == NULL) return NULL; | |
| 1131 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | 1178 // TODO(fschneider): Handle other cases: e === false and e !== true/false. |
| 1132 // Handles e === true. | 1179 // Handles e === true. |
| 1133 if ((kind() == Token::kEQ_STRICT) && | 1180 if ((kind() == Token::kEQ_STRICT) && |
| 1134 (right_constant->value().raw() == Bool::True()) && | 1181 (right_constant.raw() == Bool::True()) && |
| 1135 left_use->CompileTypeIsMoreSpecificThan( | 1182 (left_use->ResultCid() == kBoolCid)) { |
| 1136 Type::Handle(Type::BoolInterface()))) { | |
| 1137 // Remove the constant from the graph. | 1183 // Remove the constant from the graph. |
| 1138 right->RemoveFromGraph(); | 1184 BindInstr* right = right_use->definition()->AsBind(); |
| 1185 if (right != NULL) { |
| 1186 right->set_use_list(NULL); |
| 1187 right->RemoveFromGraph(); |
| 1188 } |
| 1139 // Return left subexpression as the replacement for this instruction. | 1189 // Return left subexpression as the replacement for this instruction. |
| 1140 return left; | 1190 return left; |
| 1141 } | 1191 } |
| 1142 return NULL; | 1192 return NULL; |
| 1143 } | 1193 } |
| 1144 | 1194 |
| 1145 | 1195 |
| 1146 LocationSummary* StrictCompareComp::MakeLocationSummary() const { | 1196 LocationSummary* StrictCompareComp::MakeLocationSummary() const { |
| 1147 return LocationSummary::Make(2, | 1197 return LocationSummary::Make(2, |
| 1148 Location::SameAsFirstInput(), | 1198 Location::SameAsFirstInput(), |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1385 if (compiler->is_ssa()) { | 1435 if (compiler->is_ssa()) { |
| 1386 ASSERT(locs()->in(0).IsRegister()); | 1436 ASSERT(locs()->in(0).IsRegister()); |
| 1387 __ PushRegister(locs()->in(0).reg()); | 1437 __ PushRegister(locs()->in(0).reg()); |
| 1388 } | 1438 } |
| 1389 } | 1439 } |
| 1390 | 1440 |
| 1391 | 1441 |
| 1392 #undef __ | 1442 #undef __ |
| 1393 | 1443 |
| 1394 } // namespace dart | 1444 } // namespace dart |
| OLD | NEW |