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

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

Issue 11048032: Support for mixed null/smi equality: do not deoptimize, emit same optimized code as if that was smi… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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
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/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 const GrowableArray<intptr_t>& class_ids) { 223 const GrowableArray<intptr_t>& class_ids) {
224 for (intptr_t i = 0; i < class_ids.length(); i++) { 224 for (intptr_t i = 0; i < class_ids.length(); i++) {
225 if (class_ids[i] == class_id) { 225 if (class_ids[i] == class_id) {
226 return true; 226 return true;
227 } 227 }
228 } 228 }
229 return false; 229 return false;
230 } 230 }
231 231
232 232
233 // Returns true if ICData tests two arguments and all ICData cids are in the
234 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively.
233 static bool ICDataHasOnlyReceiverArgumentClassIds( 235 static bool ICDataHasOnlyReceiverArgumentClassIds(
234 const ICData& ic_data, 236 const ICData& ic_data,
235 const GrowableArray<intptr_t>& receiver_class_ids, 237 const GrowableArray<intptr_t>& receiver_class_ids,
236 const GrowableArray<intptr_t>& argument_class_ids) { 238 const GrowableArray<intptr_t>& argument_class_ids) {
237 if (ic_data.num_args_tested() != 2) return false; 239 if (ic_data.num_args_tested() != 2) return false;
238
239 Function& target = Function::Handle(); 240 Function& target = Function::Handle();
240 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 241 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
241 GrowableArray<intptr_t> class_ids; 242 GrowableArray<intptr_t> class_ids;
242 ic_data.GetCheckAt(i, &class_ids, &target); 243 ic_data.GetCheckAt(i, &class_ids, &target);
243 ASSERT(class_ids.length() == 2); 244 ASSERT(class_ids.length() == 2);
244 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || 245 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) ||
245 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { 246 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) {
246 return false; 247 return false;
247 } 248 }
248 } 249 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 ic_data.GetOneClassCheckAt(0, &class_id, &target); 339 ic_data.GetOneClassCheckAt(0, &class_id, &target);
339 return class_id; 340 return class_id;
340 } 341 }
341 342
342 343
343 void FlowGraphOptimizer::AddCheckClass(InstanceCallInstr* call, 344 void FlowGraphOptimizer::AddCheckClass(InstanceCallInstr* call,
344 Value* value) { 345 Value* value) {
345 // Type propagation has not run yet, we cannot eliminate the check. 346 // Type propagation has not run yet, we cannot eliminate the check.
346 const ICData& unary_checks = 347 const ICData& unary_checks =
347 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); 348 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks());
348 CheckClassInstr* check = new CheckClassInstr(value, call, unary_checks); 349 CheckClassInstr* check =
350 new CheckClassInstr(value, call->deopt_id(), unary_checks);
349 InsertBefore(call, check, call->env(), Definition::kEffect); 351 InsertBefore(call, check, call->env(), Definition::kEffect);
350 } 352 }
351 353
352 354
353 static bool ArgIsAlwaysSmi(const ICData& ic_data, intptr_t arg_n) { 355 static bool ArgIsAlwaysSmi(const ICData& ic_data, intptr_t arg_n) {
354 ASSERT(ic_data.num_args_tested() > arg_n); 356 ASSERT(ic_data.num_args_tested() > arg_n);
355 if (ic_data.NumberOfChecks() == 0) return false; 357 if (ic_data.NumberOfChecks() == 0) return false;
356 GrowableArray<intptr_t> class_ids; 358 GrowableArray<intptr_t> class_ids;
357 Function& target = Function::Handle(); 359 Function& target = Function::Handle();
358 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 360 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 // If one of the inputs is null, no ICdata will be collected. 1079 // If one of the inputs is null, no ICdata will be collected.
1078 if (comp->left()->BindsToConstantNull() || 1080 if (comp->left()->BindsToConstantNull() ||
1079 comp->right()->BindsToConstantNull()) { 1081 comp->right()->BindsToConstantNull()) {
1080 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ? 1082 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ?
1081 Token::kEQ_STRICT : Token::kNE_STRICT; 1083 Token::kEQ_STRICT : Token::kNE_STRICT;
1082 StrictCompareInstr* strict_comp = 1084 StrictCompareInstr* strict_comp =
1083 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); 1085 new StrictCompareInstr(strict_kind, comp->left(), comp->right());
1084 instr->ReplaceWith(strict_comp, iterator); 1086 instr->ReplaceWith(strict_comp, iterator);
1085 return; 1087 return;
1086 } 1088 }
1087 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; 1089 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) {
1090 return;
1091 }
1092 ASSERT(comp->ic_data()->num_args_tested() == 2);
1088 if (comp->ic_data()->NumberOfChecks() == 1) { 1093 if (comp->ic_data()->NumberOfChecks() == 1) {
1089 ASSERT(comp->ic_data()->num_args_tested() == 2);
1090 GrowableArray<intptr_t> class_ids; 1094 GrowableArray<intptr_t> class_ids;
1091 Function& target = Function::Handle(); 1095 Function& target = Function::Handle();
1092 comp->ic_data()->GetCheckAt(0, &class_ids, &target); 1096 comp->ic_data()->GetCheckAt(0, &class_ids, &target);
1093 // TODO(srdjan): allow for mixed mode int/double comparison. 1097 // TODO(srdjan): allow for mixed mode int/double comparison.
1094 1098
1095 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { 1099 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) {
1096 optimizer->InsertBefore( 1100 optimizer->InsertBefore(
1097 instr, 1101 instr,
1098 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), 1102 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
1099 instr->env(), 1103 instr->env(),
(...skipping 11 matching lines...) Expand all
1111 comp->set_receiver_class_id(kMintCid); 1115 comp->set_receiver_class_id(kMintCid);
1112 } else { 1116 } else {
1113 ASSERT(comp->receiver_class_id() == kIllegalCid); 1117 ASSERT(comp->receiver_class_id() == kIllegalCid);
1114 } 1118 }
1115 } else if (HasTwoMintOrSmi(*comp->ic_data()) && 1119 } else if (HasTwoMintOrSmi(*comp->ic_data()) &&
1116 FlowGraphCompiler::SupportsUnboxedMints()) { 1120 FlowGraphCompiler::SupportsUnboxedMints()) {
1117 comp->set_receiver_class_id(kMintCid); 1121 comp->set_receiver_class_id(kMintCid);
1118 } else if (comp->ic_data()->AllReceiversAreNumbers()) { 1122 } else if (comp->ic_data()->AllReceiversAreNumbers()) {
1119 comp->set_receiver_class_id(kNumberCid); 1123 comp->set_receiver_class_id(kNumberCid);
1120 } 1124 }
1125
1126 if (comp->receiver_class_id() != kIllegalCid) {
1127 // Done.
1128 return;
1129 }
1130
1131 // Check if ICDData contains checks with Smi/Null combinations. In that case
1132 // we can still emit the optimized Smi equality operation but need to add
1133 // checks for null or Smi.
1134 // TODO(srdjan): Add it for Double and Mint.
1135 GrowableArray<intptr_t> smi_or_null(2);
1136 smi_or_null.Add(kSmiCid);
1137 smi_or_null.Add(kNullCid);
1138 if (ICDataHasOnlyReceiverArgumentClassIds(
1139 *comp->ic_data(), smi_or_null, smi_or_null)) {
1140 ICData& unary_checks =
1141 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
1142 const intptr_t deopt_id = comp->deopt_id();
1143 if ((unary_checks.NumberOfChecks() == 1) &&
1144 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) {
1145 // Smi only.
1146 optimizer->InsertBefore(
1147 instr,
1148 new CheckSmiInstr(comp->left()->Copy(), deopt_id),
1149 instr->env(),
1150 Definition::kEffect);
1151 } else {
1152 // Smi or NULL.
1153 optimizer->InsertBefore(
1154 instr,
1155 new CheckClassInstr(comp->left()->Copy(), deopt_id, unary_checks),
1156 instr->env(),
1157 Definition::kEffect);
1158 }
1159
1160 unary_checks = comp->ic_data()->AsUnaryClassChecksForArgNr(1);
1161 if ((unary_checks.NumberOfChecks() == 1) &&
1162 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) {
1163 // Smi only.
1164 optimizer->InsertBefore(
1165 instr,
1166 new CheckSmiInstr(comp->right()->Copy(), deopt_id),
1167 instr->env(),
1168 Definition::kEffect);
1169 } else {
1170 // Smi or NULL.
1171 optimizer->InsertBefore(
1172 instr,
1173 new CheckClassInstr(comp->right()->Copy(), deopt_id, unary_checks),
1174 instr->env(),
1175 Definition::kEffect);
1176 }
1177 comp->set_receiver_class_id(kSmiCid);
1178 }
1121 } 1179 }
1122 1180
1123 1181
1124 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { 1182 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) {
1125 HandleEqualityCompare(this, instr, instr, current_iterator()); 1183 HandleEqualityCompare(this, instr, instr, current_iterator());
1126 } 1184 }
1127 1185
1128 1186
1129 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { 1187 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) {
1130 ComparisonInstr* comparison = instr->comparison(); 1188 ComparisonInstr* comparison = instr->comparison();
(...skipping 2040 matching lines...) Expand 10 before | Expand all | Expand 10 after
3171 3229
3172 if (FLAG_trace_constant_propagation) { 3230 if (FLAG_trace_constant_propagation) {
3173 OS::Print("\n==== After constant propagation ====\n"); 3231 OS::Print("\n==== After constant propagation ====\n");
3174 FlowGraphPrinter printer(*graph_); 3232 FlowGraphPrinter printer(*graph_);
3175 printer.PrintBlocks(); 3233 printer.PrintBlocks();
3176 } 3234 }
3177 } 3235 }
3178 3236
3179 3237
3180 } // namespace dart 3238 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698