Chromium Code Reviews| 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 } | 142 } |
| 143 | 143 |
| 144 | 144 |
| 145 void ForwardInstructionIterator::RemoveCurrentFromGraph() { | 145 void ForwardInstructionIterator::RemoveCurrentFromGraph() { |
| 146 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. | 146 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. |
| 147 } | 147 } |
| 148 | 148 |
| 149 | 149 |
| 150 // Default implementation of visiting basic blocks. Can be overridden. | 150 // Default implementation of visiting basic blocks. Can be overridden. |
| 151 void FlowGraphVisitor::VisitBlocks() { | 151 void FlowGraphVisitor::VisitBlocks() { |
| 152 ASSERT(current_iterator_ == NULL); | |
| 152 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 153 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 153 BlockEntryInstr* entry = block_order_[i]; | 154 BlockEntryInstr* entry = block_order_[i]; |
| 154 entry->Accept(this); | 155 entry->Accept(this); |
| 155 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 156 ForwardInstructionIterator it(entry); |
| 157 current_iterator_ = ⁢ | |
| 158 for (; !it.Done(); it.Advance()) { | |
| 156 it.Current()->Accept(this); | 159 it.Current()->Accept(this); |
| 157 } | 160 } |
| 161 current_iterator_ = NULL; | |
| 158 } | 162 } |
| 159 } | 163 } |
| 160 | 164 |
| 161 | 165 |
| 166 // Returns true if the value is constant null. | |
| 167 bool Value::IsConstantNull() const { | |
| 168 return IsConstant() && AsConstant()->value().IsNull(); | |
| 169 } | |
|
srdjan
2012/08/15 17:49:56
How about making it virtual and implementing in Us
regis
2012/08/15 22:49:18
Good point. It is a bit more complex than just ret
| |
| 170 | |
| 171 | |
| 162 // Returns true if the compile type of this value is more specific than the | 172 // Returns true if the compile type of this value is more specific than the |
| 163 // given dst_type. | 173 // given dst_type. |
| 164 // TODO(regis): Support a set of compile types for the given value. | 174 // TODO(regis): Support a set of compile types for the given value. |
| 165 bool Value::CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const { | 175 bool Value::CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const { |
| 166 ASSERT(!dst_type.IsMalformed()); // Should be tested by caller. | 176 // No type is more specific than a malformed type. |
| 167 ASSERT(!dst_type.IsDynamicType()); // Should be tested by caller. | 177 if (dst_type.IsMalformed()) { |
| 168 ASSERT(!dst_type.IsObjectType()); // Should be tested by caller. | 178 return false; |
| 179 } | |
| 169 | 180 |
| 170 // If the value is the null constant, its type (NullType) is more specific | 181 // If the value is the null constant, its type (NullType) is more specific |
| 171 // than the destination type, even if the destination type is the void type, | 182 // than the destination type, even if the destination type is the void type, |
| 172 // since a void function is allowed to return null. | 183 // since a void function is allowed to return null. |
| 173 if (IsConstant() && AsConstant()->value().IsNull()) { | 184 if (IsConstantNull()) { |
| 174 return true; | 185 return true; |
| 175 } | 186 } |
| 176 | 187 |
| 177 // Functions that do not explicitly return a value, implicitly return null, | 188 // Functions that do not explicitly return a value, implicitly return null, |
| 178 // except generative constructors, which return the object being constructed. | 189 // except generative constructors, which return the object being constructed. |
| 179 // It is therefore acceptable for void functions to return null. | 190 // It is therefore acceptable for void functions to return null. |
| 180 // In case of a null constant, we have already returned true above, else we | 191 // In case of a null constant, we have already returned true above, else we |
| 181 // return false here. | 192 // return false here. |
| 182 if (dst_type.IsVoidType()) { | 193 if (dst_type.IsVoidType()) { |
| 183 return false; | 194 return false; |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 return Type::DynamicType(); | 633 return Type::DynamicType(); |
| 623 } | 634 } |
| 624 | 635 |
| 625 | 636 |
| 626 RawAbstractType* PolymorphicInstanceCallComp::CompileType() const { | 637 RawAbstractType* PolymorphicInstanceCallComp::CompileType() const { |
| 627 return Type::DynamicType(); | 638 return Type::DynamicType(); |
| 628 } | 639 } |
| 629 | 640 |
| 630 | 641 |
| 631 RawAbstractType* StaticCallComp::CompileType() const { | 642 RawAbstractType* StaticCallComp::CompileType() const { |
| 632 return function().result_type(); | 643 if (FLAG_enable_type_checks) { |
| 644 return function().result_type(); | |
| 645 } | |
| 646 return Type::DynamicType(); | |
| 633 } | 647 } |
| 634 | 648 |
| 635 | 649 |
| 636 RawAbstractType* LoadLocalComp::CompileType() const { | 650 RawAbstractType* LoadLocalComp::CompileType() const { |
| 637 if (FLAG_enable_type_checks) { | 651 if (FLAG_enable_type_checks) { |
| 638 return local().type().raw(); | 652 return local().type().raw(); |
| 639 } | 653 } |
| 640 return Type::DynamicType(); | 654 return Type::DynamicType(); |
| 641 } | 655 } |
| 642 | 656 |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1056 BindInstr* right = right_use->definition()->AsBind(); | 1070 BindInstr* right = right_use->definition()->AsBind(); |
| 1057 if (right == NULL) return NULL; | 1071 if (right == NULL) return NULL; |
| 1058 ConstantVal* right_constant = right->computation()->AsConstant(); | 1072 ConstantVal* right_constant = right->computation()->AsConstant(); |
| 1059 if (right_constant == NULL) return NULL; | 1073 if (right_constant == NULL) return NULL; |
| 1060 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | 1074 // TODO(fschneider): Handle other cases: e === false and e !== true/false. |
| 1061 // Handles e === true. | 1075 // Handles e === true. |
| 1062 if ((kind() == Token::kEQ_STRICT) && | 1076 if ((kind() == Token::kEQ_STRICT) && |
| 1063 (right_constant->value().raw() == Bool::True()) && | 1077 (right_constant->value().raw() == Bool::True()) && |
| 1064 left_use->CompileTypeIsMoreSpecificThan( | 1078 left_use->CompileTypeIsMoreSpecificThan( |
| 1065 Type::Handle(Type::BoolInterface()))) { | 1079 Type::Handle(Type::BoolInterface()))) { |
| 1080 // TODO(regis): I am not sure this optimization is correct. | |
| 1081 // Although the compile type of left_use is bool, left_use may be null at | |
| 1082 // runtime, e.g. true === f(), with bool f() { bool x; return x }. | |
| 1083 // In this case, the optimized strict equal returns null. | |
|
srdjan
2012/08/15 17:49:56
See also TODO(srdjan) above
regis
2012/08/15 22:49:18
I removed my TODO, now that the problem is underst
| |
| 1084 | |
| 1066 // Remove the constant from the graph. | 1085 // Remove the constant from the graph. |
| 1067 right->RemoveFromGraph(); | 1086 right->RemoveFromGraph(); |
| 1068 // Return left subexpression as the replacement for this instruction. | 1087 // Return left subexpression as the replacement for this instruction. |
| 1069 return left; | 1088 return left; |
| 1070 } | 1089 } |
| 1071 return NULL; | 1090 return NULL; |
| 1072 } | 1091 } |
| 1073 | 1092 |
| 1074 | 1093 |
| 1075 LocationSummary* StrictCompareComp::MakeLocationSummary() const { | 1094 LocationSummary* StrictCompareComp::MakeLocationSummary() const { |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1314 if (compiler->is_ssa()) { | 1333 if (compiler->is_ssa()) { |
| 1315 ASSERT(locs()->in(0).IsRegister()); | 1334 ASSERT(locs()->in(0).IsRegister()); |
| 1316 __ PushRegister(locs()->in(0).reg()); | 1335 __ PushRegister(locs()->in(0).reg()); |
| 1317 } | 1336 } |
| 1318 } | 1337 } |
| 1319 | 1338 |
| 1320 | 1339 |
| 1321 #undef __ | 1340 #undef __ |
| 1322 | 1341 |
| 1323 } // namespace dart | 1342 } // namespace dart |
| OLD | NEW |