| 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/hash_map.h" | 10 #include "vm/hash_map.h" |
| (...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 still_changing_ = defn->SetPropagatedCid(cid) || still_changing_; | 1175 still_changing_ = defn->SetPropagatedCid(cid) || still_changing_; |
| 1176 } | 1176 } |
| 1177 } | 1177 } |
| 1178 current_iterator_ = NULL; | 1178 current_iterator_ = NULL; |
| 1179 } | 1179 } |
| 1180 } | 1180 } |
| 1181 | 1181 |
| 1182 | 1182 |
| 1183 void FlowGraphTypePropagator::VisitAssertAssignable( | 1183 void FlowGraphTypePropagator::VisitAssertAssignable( |
| 1184 AssertAssignableInstr* instr) { | 1184 AssertAssignableInstr* instr) { |
| 1185 bool is_null, is_instance; |
| 1185 if (FLAG_eliminate_type_checks && | 1186 if (FLAG_eliminate_type_checks && |
| 1186 !instr->is_eliminated() && | 1187 !instr->is_eliminated() && |
| 1187 instr->value()->CompileTypeIsMoreSpecificThan(instr->dst_type())) { | 1188 ((instr->value()->CanComputeIsNull(&is_null) && is_null) || |
| 1189 (instr->value()->CanComputeIsInstanceOf(instr->dst_type(), &is_instance) |
| 1190 && is_instance))) { |
| 1188 // TODO(regis): Remove is_eliminated_ field and support. | 1191 // TODO(regis): Remove is_eliminated_ field and support. |
| 1189 instr->eliminate(); | 1192 instr->eliminate(); |
| 1190 | 1193 |
| 1191 Value* use = instr->value(); | 1194 Value* use = instr->value(); |
| 1192 ASSERT(use != NULL); | 1195 ASSERT(use != NULL); |
| 1193 Definition* result = use->definition(); | 1196 Definition* result = use->definition(); |
| 1194 ASSERT(result != NULL); | 1197 ASSERT(result != NULL); |
| 1195 // Replace uses and remove the current instruction via the iterator. | 1198 // Replace uses and remove the current instruction via the iterator. |
| 1196 instr->ReplaceUsesWith(result); | 1199 instr->ReplaceUsesWith(result); |
| 1197 ASSERT(current_iterator()->Current() == instr); | 1200 ASSERT(current_iterator()->Current() == instr); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1208 instr->value(), | 1211 instr->value(), |
| 1209 instr->dst_type(), | 1212 instr->dst_type(), |
| 1210 instr->dst_name(), | 1213 instr->dst_name(), |
| 1211 instr->is_eliminated()); | 1214 instr->is_eliminated()); |
| 1212 } | 1215 } |
| 1213 } | 1216 } |
| 1214 } | 1217 } |
| 1215 | 1218 |
| 1216 | 1219 |
| 1217 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanInstr* instr) { | 1220 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanInstr* instr) { |
| 1218 // TODO(regis): Propagate NullType as well and revise the comment and code | 1221 bool is_null, is_bool; |
| 1219 // below to also eliminate the test for non-null and non-constant value. | |
| 1220 | |
| 1221 // We can only eliminate an 'assert boolean' test when the checked value is | |
| 1222 // a constant time constant. Indeed, a variable of the proper compile time | |
| 1223 // type (bool) may still hold null at run time and therefore fail the test. | |
| 1224 if (FLAG_eliminate_type_checks && | 1222 if (FLAG_eliminate_type_checks && |
| 1225 !instr->is_eliminated() && | 1223 !instr->is_eliminated() && |
| 1226 instr->value()->BindsToConstant() && | 1224 instr->value()->CanComputeIsNull(&is_null) && |
| 1227 !instr->value()->BindsToConstantNull() && | 1225 !is_null && |
| 1228 instr->value()->CompileTypeIsMoreSpecificThan( | 1226 instr->value()->CanComputeIsInstanceOf(Type::Handle(Type::BoolType()), |
| 1229 Type::Handle(Type::BoolType()))) { | 1227 &is_bool) && |
| 1228 is_bool) { |
| 1230 // TODO(regis): Remove is_eliminated_ field and support. | 1229 // TODO(regis): Remove is_eliminated_ field and support. |
| 1231 instr->eliminate(); | 1230 instr->eliminate(); |
| 1232 | |
| 1233 Value* use = instr->value(); | 1231 Value* use = instr->value(); |
| 1234 Definition* result = use->definition(); | 1232 Definition* result = use->definition(); |
| 1235 ASSERT(result != NULL); | 1233 ASSERT(result != NULL); |
| 1236 // Replace uses and remove the current instruction via the iterator. | 1234 // Replace uses and remove the current instruction via the iterator. |
| 1237 instr->ReplaceUsesWith(result); | 1235 instr->ReplaceUsesWith(result); |
| 1238 ASSERT(current_iterator()->Current() == instr); | 1236 ASSERT(current_iterator()->Current() == instr); |
| 1239 current_iterator()->RemoveCurrentFromGraph(); | 1237 current_iterator()->RemoveCurrentFromGraph(); |
| 1240 if (FLAG_trace_optimization) { | 1238 if (FLAG_trace_optimization) { |
| 1241 OS::Print("Replacing v%"Pd" with v%"Pd"\n", | 1239 OS::Print("Replacing v%"Pd" with v%"Pd"\n", |
| 1242 instr->ssa_temp_index(), | 1240 instr->ssa_temp_index(), |
| 1243 result->ssa_temp_index()); | 1241 result->ssa_temp_index()); |
| 1244 } | 1242 } |
| 1245 | 1243 |
| 1246 if (FLAG_trace_type_check_elimination) { | 1244 if (FLAG_trace_type_check_elimination) { |
| 1247 const String& name = String::Handle(Symbols::New("boolean expression")); | 1245 const String& name = String::Handle(Symbols::New("boolean expression")); |
| 1248 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 1246 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 1249 instr->token_pos(), | 1247 instr->token_pos(), |
| 1250 instr->value(), | 1248 instr->value(), |
| 1251 Type::Handle(Type::BoolType()), | 1249 Type::Handle(Type::BoolType()), |
| 1252 name, | 1250 name, |
| 1253 instr->is_eliminated()); | 1251 instr->is_eliminated()); |
| 1254 } | 1252 } |
| 1255 } | 1253 } |
| 1256 } | 1254 } |
| 1257 | 1255 |
| 1258 | 1256 |
| 1259 void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfInstr* instr) { | 1257 void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfInstr* instr) { |
| 1260 // TODO(regis): Propagate NullType as well and revise the comment and code | 1258 bool is_null; |
| 1261 // below to also eliminate the test for non-null and non-constant value. | 1259 bool is_instance = false; |
| 1262 | |
| 1263 // We can only eliminate an 'instance of' test when the checked value is | |
| 1264 // a constant time constant. Indeed, a variable of the proper compile time | |
| 1265 // type may still hold null at run time and therefore fail the test. | |
| 1266 // We do not bother checking for Object destination type, since the graph | |
| 1267 // builder did already. | |
| 1268 if (FLAG_eliminate_type_checks && | 1260 if (FLAG_eliminate_type_checks && |
| 1269 instr->value()->BindsToConstant() && | 1261 instr->value()->CanComputeIsNull(&is_null) && |
| 1270 !instr->value()->BindsToConstantNull()) { | 1262 (is_null || |
| 1271 const Bool& bool_result = | 1263 instr->value()->CanComputeIsInstanceOf(instr->type(), &is_instance))) { |
| 1272 instr->value()->CompileTypeIsMoreSpecificThan(instr->type()) ? | 1264 Definition* result = new ConstantInstr(Bool::ZoneHandle(Bool::Get( |
| 1273 Bool::ZoneHandle(Bool::True()) : Bool::ZoneHandle(Bool::False()); | 1265 instr->negate_result() ? !is_instance : is_instance))); |
| 1274 Definition* result = new ConstantInstr(bool_result); | |
| 1275 result->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | 1266 result->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
| 1276 result->InsertBefore(instr); | 1267 result->InsertBefore(instr); |
| 1277 // Replace uses and remove the current instruction via the iterator. | 1268 // Replace uses and remove the current instruction via the iterator. |
| 1278 instr->ReplaceUsesWith(result); | 1269 instr->ReplaceUsesWith(result); |
| 1279 ASSERT(current_iterator()->Current() == instr); | 1270 ASSERT(current_iterator()->Current() == instr); |
| 1280 current_iterator()->RemoveCurrentFromGraph(); | 1271 current_iterator()->RemoveCurrentFromGraph(); |
| 1281 if (FLAG_trace_optimization) { | 1272 if (FLAG_trace_optimization) { |
| 1282 OS::Print("Replacing v%"Pd" with v%"Pd"\n", | 1273 OS::Print("Replacing v%"Pd" with v%"Pd"\n", |
| 1283 instr->ssa_temp_index(), | 1274 instr->ssa_temp_index(), |
| 1284 result->ssa_temp_index()); | 1275 result->ssa_temp_index()); |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1779 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. | 1770 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. |
| 1780 OptimizeRecursive(child, &child_map); | 1771 OptimizeRecursive(child, &child_map); |
| 1781 } else { | 1772 } else { |
| 1782 OptimizeRecursive(child, map); // Reuse map for the last child. | 1773 OptimizeRecursive(child, map); // Reuse map for the last child. |
| 1783 } | 1774 } |
| 1784 } | 1775 } |
| 1785 } | 1776 } |
| 1786 | 1777 |
| 1787 | 1778 |
| 1788 } // namespace dart | 1779 } // namespace dart |
| OLD | NEW |