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

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

Issue 10700123: Remove the instruction pointer from computations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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_optimizer.h ('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/flow_graph_builder.h" 7 #include "vm/flow_graph_builder.h"
8 #include "vm/il_printer.h" 8 #include "vm/il_printer.h"
9 #include "vm/object_store.h" 9 #include "vm/object_store.h"
10 10
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 return ICDataHasReceiverClassId(ic_data, kDouble); 124 return ICDataHasReceiverClassId(ic_data, kDouble);
125 } 125 }
126 126
127 127
128 static bool HasOnlyTwoDouble(const ICData& ic_data) { 128 static bool HasOnlyTwoDouble(const ICData& ic_data) {
129 return (ic_data.NumberOfChecks() == 1) && 129 return (ic_data.NumberOfChecks() == 1) &&
130 ICDataHasReceiverArgumentClassIds(ic_data, kDouble, kDouble); 130 ICDataHasReceiverArgumentClassIds(ic_data, kDouble, kDouble);
131 } 131 }
132 132
133 133
134 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp, 134 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr,
135 InstanceCallComp* comp,
135 Token::Kind op_kind) { 136 Token::Kind op_kind) {
136 BinaryOpComp::OperandsType operands_type = BinaryOpComp::kDynamicOperands; 137 BinaryOpComp::OperandsType operands_type = BinaryOpComp::kDynamicOperands;
137 ASSERT(comp->HasICData()); 138 ASSERT(comp->HasICData());
138 const ICData& ic_data = *comp->ic_data(); 139 const ICData& ic_data = *comp->ic_data();
139 switch (op_kind) { 140 switch (op_kind) {
140 case Token::kADD: 141 case Token::kADD:
141 case Token::kSUB: 142 case Token::kSUB:
142 case Token::kMUL: 143 case Token::kMUL:
143 if (HasOnlyTwoSmi(ic_data)) { 144 if (HasOnlyTwoSmi(ic_data)) {
144 operands_type = BinaryOpComp::kSmiOperands; 145 operands_type = BinaryOpComp::kSmiOperands;
(...skipping 27 matching lines...) Expand all
172 if (HasOnlyTwoSmi(ic_data)) { 173 if (HasOnlyTwoSmi(ic_data)) {
173 operands_type = BinaryOpComp::kSmiOperands; 174 operands_type = BinaryOpComp::kSmiOperands;
174 } else { 175 } else {
175 return false; 176 return false;
176 } 177 }
177 break; 178 break;
178 default: 179 default:
179 UNREACHABLE(); 180 UNREACHABLE();
180 }; 181 };
181 182
182 ASSERT(comp->instr() != NULL);
183 ASSERT(comp->InputCount() == 2); 183 ASSERT(comp->InputCount() == 2);
184 Value* left = comp->InputAt(0); 184 Value* left = comp->InputAt(0);
185 Value* right = comp->InputAt(1); 185 Value* right = comp->InputAt(1);
186 BinaryOpComp* bin_op = 186 BinaryOpComp* bin_op =
187 new BinaryOpComp(op_kind, 187 new BinaryOpComp(op_kind,
188 operands_type, 188 operands_type,
189 comp, 189 comp,
190 left, 190 left,
191 right); 191 right);
192 bin_op->set_ic_data(comp->ic_data()); 192 bin_op->set_ic_data(comp->ic_data());
193 comp->ReplaceWith(bin_op); 193 instr->set_computation(bin_op);
194 return true; 194 return true;
195 } 195 }
196 196
197 197
198 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallComp* comp, 198 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(BindInstr* instr,
199 InstanceCallComp* comp,
199 Token::Kind op_kind) { 200 Token::Kind op_kind) {
200 if (comp->ic_data()->NumberOfChecks() != 1) { 201 if (comp->ic_data()->NumberOfChecks() != 1) {
201 // TODO(srdjan): Not yet supported. 202 // TODO(srdjan): Not yet supported.
202 return false; 203 return false;
203 } 204 }
204 ASSERT(comp->instr() != NULL);
205 ASSERT(comp->InputCount() == 1); 205 ASSERT(comp->InputCount() == 1);
206 Computation* unary_op = NULL; 206 Computation* unary_op = NULL;
207 if (HasOneSmi(*comp->ic_data())) { 207 if (HasOneSmi(*comp->ic_data())) {
208 unary_op = new UnarySmiOpComp(op_kind, comp, comp->InputAt(0)); 208 unary_op = new UnarySmiOpComp(op_kind, comp, comp->InputAt(0));
209 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) { 209 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) {
210 unary_op = new NumberNegateComp(comp, comp->InputAt(0)); 210 unary_op = new NumberNegateComp(comp, comp->InputAt(0));
211 } 211 }
212 if (unary_op != NULL) { 212 if (unary_op != NULL) {
213 unary_op->set_ic_data(comp->ic_data()); 213 unary_op->set_ic_data(comp->ic_data());
214 comp->ReplaceWith(unary_op); 214 instr->set_computation(unary_op);
215 return true; 215 return true;
216 } 216 }
217 return false; 217 return false;
218 } 218 }
219 219
220 220
221 // Returns true if all targets are the same. 221 // Returns true if all targets are the same.
222 // TODO(srdjan): if targets are native use their C_function to compare. 222 // TODO(srdjan): if targets are native use their C_function to compare.
223 static bool HasOneTarget(const ICData& ic_data) { 223 static bool HasOneTarget(const ICData& ic_data) {
224 ASSERT(ic_data.NumberOfChecks() > 0); 224 ASSERT(ic_data.NumberOfChecks() > 0);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 // This will make sure that Smi is first if it exists. 276 // This will make sure that Smi is first if it exists.
277 result.AddReceiverCheck(class_id, 277 result.AddReceiverCheck(class_id,
278 Function::Handle(ic_data.GetTargetAt(i))); 278 Function::Handle(ic_data.GetTargetAt(i)));
279 } 279 }
280 } 280 }
281 return result.raw(); 281 return result.raw();
282 } 282 }
283 283
284 284
285 // Only unique implicit instance getters can be currently handled. 285 // Only unique implicit instance getters can be currently handled.
286 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) { 286 bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr,
287 InstanceCallComp* comp) {
287 ASSERT(comp->HasICData()); 288 ASSERT(comp->HasICData());
288 const ICData& ic_data = *comp->ic_data(); 289 const ICData& ic_data = *comp->ic_data();
289 if (ic_data.NumberOfChecks() == 0) { 290 if (ic_data.NumberOfChecks() == 0) {
290 // No type feedback collected. 291 // No type feedback collected.
291 return false; 292 return false;
292 } 293 }
293 Function& target = Function::Handle(); 294 Function& target = Function::Handle();
294 GrowableArray<intptr_t> class_ids; 295 GrowableArray<intptr_t> class_ids;
295 ic_data.GetCheckAt(0, &class_ids, &target); 296 ic_data.GetCheckAt(0, &class_ids, &target);
296 ASSERT(class_ids.length() == 1); 297 ASSERT(class_ids.length() == 1);
297 298
298 if (target.kind() == RawFunction::kImplicitGetter) { 299 if (target.kind() == RawFunction::kImplicitGetter) {
299 if (!HasOneTarget(ic_data)) { 300 if (!HasOneTarget(ic_data)) {
300 // TODO(srdjan): Implement for mutiple targets. 301 // TODO(srdjan): Implement for mutiple targets.
301 return false; 302 return false;
302 } 303 }
303 // Inline implicit instance getter. 304 // Inline implicit instance getter.
304 const String& field_name = 305 const String& field_name =
305 String::Handle(Field::NameFromGetter(comp->function_name())); 306 String::Handle(Field::NameFromGetter(comp->function_name()));
306 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); 307 const Field& field = Field::Handle(GetField(class_ids[0], field_name));
307 ASSERT(!field.IsNull()); 308 ASSERT(!field.IsNull());
308 LoadInstanceFieldComp* load = new LoadInstanceFieldComp( 309 LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
309 field, comp->InputAt(0), comp); 310 field, comp->InputAt(0), comp);
310 load->set_ic_data(comp->ic_data()); 311 load->set_ic_data(comp->ic_data());
311 comp->ReplaceWith(load); 312 instr->set_computation(load);
312 return true; 313 return true;
313 } 314 }
314 315
315 // Not an implicit getter. 316 // Not an implicit getter.
316 MethodRecognizer::Kind recognized_kind = 317 MethodRecognizer::Kind recognized_kind =
317 MethodRecognizer::RecognizeKind(target); 318 MethodRecognizer::RecognizeKind(target);
318 319
319 // VM objects length getter. 320 // VM objects length getter.
320 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || 321 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) ||
321 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || 322 (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
(...skipping 13 matching lines...) Expand all
335 break; 336 break;
336 default: 337 default:
337 UNREACHABLE(); 338 UNREACHABLE();
338 } 339 }
339 LoadVMFieldComp* load = new LoadVMFieldComp( 340 LoadVMFieldComp* load = new LoadVMFieldComp(
340 comp->InputAt(0), 341 comp->InputAt(0),
341 length_offset, 342 length_offset,
342 Type::ZoneHandle(Type::IntInterface())); 343 Type::ZoneHandle(Type::IntInterface()));
343 load->set_original(comp); 344 load->set_original(comp);
344 load->set_ic_data(comp->ic_data()); 345 load->set_ic_data(comp->ic_data());
345 comp->ReplaceWith(load); 346 instr->set_computation(load);
346 return true; 347 return true;
347 } 348 }
348 349
349 if (recognized_kind == MethodRecognizer::kStringBaseLength) { 350 if (recognized_kind == MethodRecognizer::kStringBaseLength) {
350 ASSERT(HasOneTarget(ic_data)); 351 ASSERT(HasOneTarget(ic_data));
351 LoadVMFieldComp* load = new LoadVMFieldComp( 352 LoadVMFieldComp* load = new LoadVMFieldComp(
352 comp->InputAt(0), 353 comp->InputAt(0),
353 String::length_offset(), 354 String::length_offset(),
354 Type::ZoneHandle(Type::IntInterface())); 355 Type::ZoneHandle(Type::IntInterface()));
355 load->set_original(comp); 356 load->set_original(comp);
356 load->set_ic_data(comp->ic_data()); 357 load->set_ic_data(comp->ic_data());
357 comp->ReplaceWith(load); 358 instr->set_computation(load);
358 return true; 359 return true;
359 } 360 }
360 return false; 361 return false;
361 } 362 }
362 363
363 364
364 // Inline only simple, frequently called core library methods. 365 // Inline only simple, frequently called core library methods.
365 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) { 366 bool FlowGraphOptimizer::TryInlineInstanceMethod(BindInstr* instr,
367 InstanceCallComp* comp) {
366 ASSERT(comp->HasICData()); 368 ASSERT(comp->HasICData());
367 const ICData& ic_data = *comp->ic_data(); 369 const ICData& ic_data = *comp->ic_data();
368 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) { 370 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) {
369 // No type feedback collected. 371 // No type feedback collected.
370 return false; 372 return false;
371 } 373 }
372 Function& target = Function::Handle(); 374 Function& target = Function::Handle();
373 GrowableArray<intptr_t> class_ids; 375 GrowableArray<intptr_t> class_ids;
374 ic_data.GetCheckAt(0, &class_ids, &target); 376 ic_data.GetCheckAt(0, &class_ids, &target);
375 MethodRecognizer::Kind recognized_kind = 377 MethodRecognizer::Kind recognized_kind =
376 MethodRecognizer::RecognizeKind(target); 378 MethodRecognizer::RecognizeKind(target);
377 379
378 ObjectKind from_kind; 380 ObjectKind from_kind;
379 if (recognized_kind == MethodRecognizer::kDoubleToDouble) { 381 if (recognized_kind == MethodRecognizer::kDoubleToDouble) {
380 from_kind = kDouble; 382 from_kind = kDouble;
381 } else if (recognized_kind == MethodRecognizer::kIntegerToDouble) { 383 } else if (recognized_kind == MethodRecognizer::kIntegerToDouble) {
382 from_kind = kSmi; 384 from_kind = kSmi;
383 } else { 385 } else {
384 return false; 386 return false;
385 } 387 }
386 388
387 if (class_ids[0] != from_kind) { 389 if (class_ids[0] != from_kind) {
388 return false; 390 return false;
389 } 391 }
390 ToDoubleComp* coerce = new ToDoubleComp( 392 ToDoubleComp* coerce = new ToDoubleComp(
391 comp->InputAt(0), from_kind, comp); 393 comp->InputAt(0), from_kind, comp);
392 coerce->set_instr(comp->instr()); 394 instr->set_computation(coerce);
393 comp->instr()->replace_computation(coerce);
394 return true; 395 return true;
395 } 396 }
396 397
397 398
398 399
399 400
400 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { 401 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp,
402 BindInstr* instr) {
401 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) { 403 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
402 const Token::Kind op_kind = comp->token_kind(); 404 const Token::Kind op_kind = comp->token_kind();
403 if (Token::IsBinaryToken(op_kind) && 405 if (Token::IsBinaryToken(op_kind) &&
404 TryReplaceWithBinaryOp(comp, op_kind)) { 406 TryReplaceWithBinaryOp(instr, comp, op_kind)) {
405 return; 407 return;
406 } 408 }
407 if (Token::IsUnaryToken(op_kind) && TryReplaceWithUnaryOp(comp, op_kind)) { 409 if (Token::IsUnaryToken(op_kind) &&
410 TryReplaceWithUnaryOp(instr, comp, op_kind)) {
408 return; 411 return;
409 } 412 }
410 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(comp)) { 413 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, comp)) {
411 return; 414 return;
412 } 415 }
413 if (TryInlineInstanceMethod(comp)) { 416 if (TryInlineInstanceMethod(instr, comp)) {
414 return; 417 return;
415 } 418 }
416 const intptr_t kMaxChecks = 4; 419 const intptr_t kMaxChecks = 4;
417 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { 420 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) {
418 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); 421 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
419 ICData& unary_checks = 422 ICData& unary_checks =
420 ICData::ZoneHandle(ToUnaryClassChecks(*comp->ic_data())); 423 ICData::ZoneHandle(ToUnaryClassChecks(*comp->ic_data()));
421 call->set_ic_data(&unary_checks); 424 call->set_ic_data(&unary_checks);
422 comp->ReplaceWith(call); 425 instr->set_computation(call);
423 } 426 }
424 } else { 427 } else {
425 // Mark it for deopt. 428 // Mark it for deopt.
426 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); 429 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
427 call->set_ic_data(&ICData::ZoneHandle()); 430 call->set_ic_data(&ICData::ZoneHandle());
428 comp->ReplaceWith(call); 431 instr->set_computation(call);
429 } 432 }
430 } 433 }
431 434
432 435
433 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) { 436 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp,
437 BindInstr* instr) {
434 MethodRecognizer::Kind recognized_kind = 438 MethodRecognizer::Kind recognized_kind =
435 MethodRecognizer::RecognizeKind(comp->function()); 439 MethodRecognizer::RecognizeKind(comp->function());
436 if (recognized_kind == MethodRecognizer::kMathSqrt) { 440 if (recognized_kind == MethodRecognizer::kMathSqrt) {
437 comp->set_recognized(MethodRecognizer::kMathSqrt); 441 comp->set_recognized(MethodRecognizer::kMathSqrt);
438 } 442 }
439 } 443 }
440 444
441 445
442 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) { 446 bool FlowGraphOptimizer::TryInlineInstanceSetter(BindInstr* instr,
447 InstanceSetterComp* comp) {
443 ASSERT(comp->HasICData()); 448 ASSERT(comp->HasICData());
444 const ICData& ic_data = *comp->ic_data(); 449 const ICData& ic_data = *comp->ic_data();
445 if (ic_data.NumberOfChecks() == 0) { 450 if (ic_data.NumberOfChecks() == 0) {
446 // No type feedback collected. 451 // No type feedback collected.
447 return false; 452 return false;
448 } 453 }
449 if (!HasOneTarget(ic_data)) { 454 if (!HasOneTarget(ic_data)) {
450 // TODO(srdjan): Implement when not all targets are the same. 455 // TODO(srdjan): Implement when not all targets are the same.
451 return false; 456 return false;
452 } 457 }
453 Function& target = Function::Handle(); 458 Function& target = Function::Handle();
454 intptr_t class_id; 459 intptr_t class_id;
455 ic_data.GetOneClassCheckAt(0, &class_id, &target); 460 ic_data.GetOneClassCheckAt(0, &class_id, &target);
456 if (target.kind() != RawFunction::kImplicitSetter) { 461 if (target.kind() != RawFunction::kImplicitSetter) {
457 // Not an implicit setter. 462 // Not an implicit setter.
458 // TODO(srdjan): Inline special setters. 463 // TODO(srdjan): Inline special setters.
459 return false; 464 return false;
460 } 465 }
461 // Inline implicit instance setter. 466 // Inline implicit instance setter.
462 const Field& field = Field::Handle(GetField(class_id, comp->field_name())); 467 const Field& field = Field::Handle(GetField(class_id, comp->field_name()));
463 ASSERT(!field.IsNull()); 468 ASSERT(!field.IsNull());
464 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( 469 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
465 field, 470 field,
466 comp->InputAt(0), 471 comp->InputAt(0),
467 comp->InputAt(1), 472 comp->InputAt(1),
468 comp); 473 comp);
469 store->set_ic_data(comp->ic_data()); 474 store->set_ic_data(comp->ic_data());
470 comp->ReplaceWith(store); 475 instr->set_computation(store);
471 return true; 476 return true;
472 } 477 }
473 478
474 479
475 480
476 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { 481 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp,
482 BindInstr* instr) {
477 // TODO(srdjan): Add assignable check node if --enable_type_checks. 483 // TODO(srdjan): Add assignable check node if --enable_type_checks.
478 if (comp->HasICData() && !FLAG_enable_type_checks) { 484 if (comp->HasICData() && !FLAG_enable_type_checks) {
479 if (TryInlineInstanceSetter(comp)) { 485 if (TryInlineInstanceSetter(instr, comp)) {
480 return; 486 return;
481 } 487 }
482 } 488 }
483 // TODO(srdjan): Polymorphic dispatch to setters or deoptimize. 489 // TODO(srdjan): Polymorphic dispatch to setters or deoptimize.
484 } 490 }
485 491
486 492
487 enum IndexedAccessType { 493 enum IndexedAccessType {
488 kIndexedLoad, 494 kIndexedLoad,
489 kIndexedStore 495 kIndexedStore
(...skipping 10 matching lines...) Expand all
500 if (ic_data.NumberOfChecks() != 1) return kIllegalObjectKind; 506 if (ic_data.NumberOfChecks() != 1) return kIllegalObjectKind;
501 ASSERT(HasOneTarget(ic_data)); 507 ASSERT(HasOneTarget(ic_data));
502 508
503 Function& target = Function::Handle(); 509 Function& target = Function::Handle();
504 intptr_t class_id; 510 intptr_t class_id;
505 ic_data.GetOneClassCheckAt(0, &class_id, &target); 511 ic_data.GetOneClassCheckAt(0, &class_id, &target);
506 return class_id; 512 return class_id;
507 } 513 }
508 514
509 515
510 void FlowGraphOptimizer::VisitLoadIndexed(LoadIndexedComp* comp) { 516 void FlowGraphOptimizer::VisitLoadIndexed(LoadIndexedComp* comp,
517 BindInstr* instr) {
511 const intptr_t class_id = ReceiverClassId(comp); 518 const intptr_t class_id = ReceiverClassId(comp);
512 switch (class_id) { 519 switch (class_id) {
513 case kArray: 520 case kArray:
514 case kImmutableArray: 521 case kImmutableArray:
515 case kGrowableObjectArray: 522 case kGrowableObjectArray:
516 comp->set_receiver_type(static_cast<ObjectKind>(class_id)); 523 comp->set_receiver_type(static_cast<ObjectKind>(class_id));
517 } 524 }
518 } 525 }
519 526
520 527
521 void FlowGraphOptimizer::VisitStoreIndexed(StoreIndexedComp* comp) { 528 void FlowGraphOptimizer::VisitStoreIndexed(StoreIndexedComp* comp,
529 BindInstr* instr) {
522 if (FLAG_enable_type_checks) return; 530 if (FLAG_enable_type_checks) return;
523 531
524 const intptr_t class_id = ReceiverClassId(comp); 532 const intptr_t class_id = ReceiverClassId(comp);
525 switch (class_id) { 533 switch (class_id) {
526 case kArray: 534 case kArray:
527 case kGrowableObjectArray: 535 case kGrowableObjectArray:
528 comp->set_receiver_type(static_cast<ObjectKind>(class_id)); 536 comp->set_receiver_type(static_cast<ObjectKind>(class_id));
529 } 537 }
530 } 538 }
531 539
532 540
533 static void TryFuseComparisonWithBranch(ComparisonComp* comp) { 541 static void TryFuseComparisonWithBranch(BindInstr* instr,
534 Instruction* instr = comp->instr(); 542 ComparisonComp* comp) {
535 Instruction* next_instr = instr->successor(); 543 Instruction* next_instr = instr->successor();
536 if ((next_instr != NULL) && next_instr->IsBranch()) { 544 if ((next_instr != NULL) && next_instr->IsBranch()) {
537 BranchInstr* branch = next_instr->AsBranch(); 545 BranchInstr* branch = next_instr->AsBranch();
538 UseVal* use = branch->value()->AsUse(); 546 UseVal* use = branch->value()->AsUse();
539 if (instr == use->definition()) { 547 if (instr == use->definition()) {
540 comp->MarkFusedWithBranch(branch); 548 comp->MarkFusedWithBranch(branch);
541 branch->MarkFusedWithComparison(); 549 branch->MarkFusedWithComparison();
542 return; 550 return;
543 } 551 }
544 } 552 }
545 if ((next_instr != NULL) && next_instr->IsBind()) { 553 if ((next_instr != NULL) && next_instr->IsBind()) {
546 Computation* next_comp = next_instr->AsBind()->computation(); 554 Computation* next_comp = next_instr->AsBind()->computation();
547 if (next_comp->IsBooleanNegate()) { 555 if (next_comp->IsBooleanNegate()) {
548 Instruction* next_next_instr = next_instr->successor(); 556 Instruction* next_next_instr = next_instr->successor();
549 if ((next_next_instr != NULL) && next_next_instr->IsBranch()) { 557 if ((next_next_instr != NULL) && next_next_instr->IsBranch()) {
550 BooleanNegateComp* negate = next_comp->AsBooleanNegate(); 558 BooleanNegateComp* negate = next_comp->AsBooleanNegate();
551 BranchInstr* branch = next_next_instr->AsBranch(); 559 BranchInstr* branch = next_next_instr->AsBranch();
552 if ((branch->value()->AsUse()->definition() == negate->instr()) && 560 if ((branch->value()->AsUse()->definition() == next_instr) &&
553 (negate->value()->AsUse()->definition() == instr)) { 561 (negate->value()->AsUse()->definition() == instr)) {
554 comp->MarkFusedWithBranch(branch); 562 comp->MarkFusedWithBranch(branch);
555 branch->MarkFusedWithComparison(); 563 branch->MarkFusedWithComparison();
556 branch->set_is_negated(true); 564 branch->set_is_negated(true);
557 instr->set_successor(next_next_instr); 565 instr->set_successor(next_next_instr);
558 return; 566 return;
559 } 567 }
560 } 568 }
561 } 569 }
562 } 570 }
563 } 571 }
564 572
565 573
566 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp) { 574 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp,
575 BindInstr* instr) {
567 if (!comp->HasICData()) return; 576 if (!comp->HasICData()) return;
568 577
569 const ICData& ic_data = *comp->ic_data(); 578 const ICData& ic_data = *comp->ic_data();
570 if (ic_data.NumberOfChecks() == 0) return; 579 if (ic_data.NumberOfChecks() == 0) return;
571 // TODO(srdjan): Add multiple receiver type support. 580 // TODO(srdjan): Add multiple receiver type support.
572 if (ic_data.NumberOfChecks() != 1) return; 581 if (ic_data.NumberOfChecks() != 1) return;
573 ASSERT(HasOneTarget(ic_data)); 582 ASSERT(HasOneTarget(ic_data));
574 583
575 if (HasOnlyTwoSmi(ic_data)) { 584 if (HasOnlyTwoSmi(ic_data)) {
576 comp->set_operands_class_id(kSmi); 585 comp->set_operands_class_id(kSmi);
577 } else if (HasOnlyTwoDouble(ic_data)) { 586 } else if (HasOnlyTwoDouble(ic_data)) {
578 comp->set_operands_class_id(kDouble); 587 comp->set_operands_class_id(kDouble);
579 } else { 588 } else {
580 return; 589 return;
581 } 590 }
582 591
583 // For smi and double comparisons if the next instruction is a conditional 592 // For smi and double comparisons if the next instruction is a conditional
584 // branch that uses the value of this comparison mark them as fused together 593 // branch that uses the value of this comparison mark them as fused together
585 // to avoid materializing a boolean value. 594 // to avoid materializing a boolean value.
586 TryFuseComparisonWithBranch(comp); 595 TryFuseComparisonWithBranch(instr, comp);
587 } 596 }
588 597
589 598
590 void FlowGraphOptimizer::VisitStrictCompare(StrictCompareComp* comp) { 599 void FlowGraphOptimizer::VisitStrictCompare(StrictCompareComp* comp,
591 TryFuseComparisonWithBranch(comp); 600 BindInstr* instr) {
601 TryFuseComparisonWithBranch(instr, comp);
592 } 602 }
593 603
594 604
595 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) { 605 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp,
606 BindInstr* instr) {
596 if (comp->HasICData()) { 607 if (comp->HasICData()) {
597 // Replace binary checks with unary ones since EmitNative expects it. 608 // Replace binary checks with unary ones since EmitNative expects it.
598 ICData& unary_checks = 609 ICData& unary_checks =
599 ICData::Handle(ToUnaryClassChecks(*comp->ic_data())); 610 ICData::Handle(ToUnaryClassChecks(*comp->ic_data()));
600 comp->set_ic_data(&unary_checks); 611 comp->set_ic_data(&unary_checks);
601 } 612 }
602 613
603 TryFuseComparisonWithBranch(comp); 614 TryFuseComparisonWithBranch(instr, comp);
604 } 615 }
605 616
606 617
607 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 618 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
608 instr->computation()->Accept(this); 619 instr->computation()->Accept(this, instr);
609 } 620 }
610 621
611 622
612 623
613 FlowGraphAnalyzer::FlowGraphAnalyzer( 624 FlowGraphAnalyzer::FlowGraphAnalyzer(
614 const GrowableArray<BlockEntryInstr*>& blocks) 625 const GrowableArray<BlockEntryInstr*>& blocks)
615 :blocks_(blocks), is_leaf_(false) {} 626 :blocks_(blocks), is_leaf_(false) {}
616 627
617 628
618 void FlowGraphAnalyzer::Analyze() { 629 void FlowGraphAnalyzer::Analyze() {
619 is_leaf_ = true; 630 is_leaf_ = true;
620 for (intptr_t i = 0; i < blocks_.length(); ++i) { 631 for (intptr_t i = 0; i < blocks_.length(); ++i) {
621 BlockEntryInstr* block_entry = blocks_[i]; 632 BlockEntryInstr* block_entry = blocks_[i];
622 Instruction* instr = block_entry->successor(); 633 Instruction* instr = block_entry->successor();
623 while ((instr != NULL) && !instr->IsBlockEntry()) { 634 while ((instr != NULL) && !instr->IsBlockEntry()) {
624 LocationSummary* locs = instr->locs(); 635 LocationSummary* locs = instr->locs();
625 if (locs != NULL) { 636 if (locs != NULL) {
626 if (locs->is_call()) { 637 if (locs->is_call()) {
627 is_leaf_ = false; 638 is_leaf_ = false;
628 return; 639 return;
629 } 640 }
630 } 641 }
631 instr = instr->successor(); 642 instr = instr->successor();
632 } 643 }
633 } 644 }
634 } 645 }
635 646
636 } // namespace dart 647 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698