Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10942006: Fix bad optimization of instance-of with uninstantiated types (issue 5216). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698