| 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/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 17 matching lines...) Expand all Loading... |
| 28 return true; | 28 return true; |
| 29 } | 29 } |
| 30 } | 30 } |
| 31 return false; | 31 return false; |
| 32 } | 32 } |
| 33 | 33 |
| 34 | 34 |
| 35 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, | 35 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, |
| 36 intptr_t receiver_class_id, | 36 intptr_t receiver_class_id, |
| 37 intptr_t argument_class_id) { | 37 intptr_t argument_class_id) { |
| 38 ASSERT(receiver_class_id != kIllegalObjectKind); | 38 ASSERT(receiver_class_id != kIllegalCid); |
| 39 ASSERT(argument_class_id != kIllegalObjectKind); | 39 ASSERT(argument_class_id != kIllegalCid); |
| 40 if (ic_data.num_args_tested() != 2) return false; | 40 if (ic_data.num_args_tested() != 2) return false; |
| 41 | 41 |
| 42 Function& target = Function::Handle(); | 42 Function& target = Function::Handle(); |
| 43 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 43 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 44 GrowableArray<intptr_t> class_ids; | 44 GrowableArray<intptr_t> class_ids; |
| 45 ic_data.GetCheckAt(i, &class_ids, &target); | 45 ic_data.GetCheckAt(i, &class_ids, &target); |
| 46 ASSERT(class_ids.length() == 2); | 46 ASSERT(class_ids.length() == 2); |
| 47 if ((class_ids[0] == receiver_class_id) && | 47 if ((class_ids[0] == receiver_class_id) && |
| 48 (class_ids[1] == argument_class_id)) { | 48 (class_ids[1] == argument_class_id)) { |
| 49 return true; | 49 return true; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 78 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || | 78 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || |
| 79 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { | 79 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { |
| 80 return false; | 80 return false; |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 return true; | 83 return true; |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 static bool HasOneSmi(const ICData& ic_data) { | 87 static bool HasOneSmi(const ICData& ic_data) { |
| 88 return ICDataHasReceiverClassId(ic_data, kSmi); | 88 return ICDataHasReceiverClassId(ic_data, kSmiCid); |
| 89 } | 89 } |
| 90 | 90 |
| 91 | 91 |
| 92 static bool HasOnlyTwoSmi(const ICData& ic_data) { | 92 static bool HasOnlyTwoSmi(const ICData& ic_data) { |
| 93 return (ic_data.NumberOfChecks() == 1) && | 93 return (ic_data.NumberOfChecks() == 1) && |
| 94 ICDataHasReceiverArgumentClassIds(ic_data, kSmi, kSmi); | 94 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); |
| 95 } | 95 } |
| 96 | 96 |
| 97 | 97 |
| 98 // Returns false if the ICData contains anything other than the 4 combinations | 98 // Returns false if the ICData contains anything other than the 4 combinations |
| 99 // of Mint and Smi for the receiver and argument classes. | 99 // of Mint and Smi for the receiver and argument classes. |
| 100 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 100 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
| 101 GrowableArray<intptr_t> class_ids; | 101 GrowableArray<intptr_t> class_ids; |
| 102 class_ids.Add(kSmi); | 102 class_ids.Add(kSmiCid); |
| 103 class_ids.Add(kMint); | 103 class_ids.Add(kMintCid); |
| 104 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, &class_ids, &class_ids); | 104 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, &class_ids, &class_ids); |
| 105 } | 105 } |
| 106 | 106 |
| 107 | 107 |
| 108 static bool HasOneDouble(const ICData& ic_data) { | 108 static bool HasOneDouble(const ICData& ic_data) { |
| 109 return ICDataHasReceiverClassId(ic_data, kDouble); | 109 return ICDataHasReceiverClassId(ic_data, kDoubleCid); |
| 110 } | 110 } |
| 111 | 111 |
| 112 | 112 |
| 113 static bool HasOnlyTwoDouble(const ICData& ic_data) { | 113 static bool HasOnlyTwoDouble(const ICData& ic_data) { |
| 114 return (ic_data.NumberOfChecks() == 1) && | 114 return (ic_data.NumberOfChecks() == 1) && |
| 115 ICDataHasReceiverArgumentClassIds(ic_data, kDouble, kDouble); | 115 ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid); |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 static void RemovePushArguments(InstanceCallComp* comp) { | 119 static void RemovePushArguments(InstanceCallComp* comp) { |
| 120 // Remove original push arguments. | 120 // Remove original push arguments. |
| 121 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { | 121 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { |
| 122 comp->ArgumentAt(i)->RemoveFromGraph(); | 122 comp->ArgumentAt(i)->RemoveFromGraph(); |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) { | 344 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) { |
| 345 // No type feedback collected. | 345 // No type feedback collected. |
| 346 return false; | 346 return false; |
| 347 } | 347 } |
| 348 Function& target = Function::Handle(); | 348 Function& target = Function::Handle(); |
| 349 GrowableArray<intptr_t> class_ids; | 349 GrowableArray<intptr_t> class_ids; |
| 350 ic_data.GetCheckAt(0, &class_ids, &target); | 350 ic_data.GetCheckAt(0, &class_ids, &target); |
| 351 MethodRecognizer::Kind recognized_kind = | 351 MethodRecognizer::Kind recognized_kind = |
| 352 MethodRecognizer::RecognizeKind(target); | 352 MethodRecognizer::RecognizeKind(target); |
| 353 | 353 |
| 354 ObjectKind from_kind; | 354 intptr_t from_class_id; |
| 355 if (recognized_kind == MethodRecognizer::kDoubleToDouble) { | 355 if (recognized_kind == MethodRecognizer::kDoubleToDouble) { |
| 356 from_kind = kDouble; | 356 from_class_id = kDoubleCid; |
| 357 } else if (recognized_kind == MethodRecognizer::kIntegerToDouble) { | 357 } else if (recognized_kind == MethodRecognizer::kIntegerToDouble) { |
| 358 from_kind = kSmi; | 358 from_class_id = kSmiCid; |
| 359 } else { | 359 } else { |
| 360 return false; | 360 return false; |
| 361 } | 361 } |
| 362 | 362 |
| 363 if (class_ids[0] != from_kind) { | 363 if (class_ids[0] != from_class_id) { |
| 364 return false; | 364 return false; |
| 365 } | 365 } |
| 366 ToDoubleComp* coerce = new ToDoubleComp( | 366 ToDoubleComp* coerce = new ToDoubleComp( |
| 367 comp->ArgumentAt(0)->value(), from_kind, comp); | 367 comp->ArgumentAt(0)->value(), from_class_id, comp); |
| 368 instr->set_computation(coerce); | 368 instr->set_computation(coerce); |
| 369 RemovePushArguments(comp); | 369 RemovePushArguments(comp); |
| 370 return true; | 370 return true; |
| 371 } | 371 } |
| 372 | 372 |
| 373 | 373 |
| 374 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp, | 374 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp, |
| 375 BindInstr* instr) { | 375 BindInstr* instr) { |
| 376 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) { | 376 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) { |
| 377 const Token::Kind op_kind = comp->token_kind(); | 377 const Token::Kind op_kind = comp->token_kind(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 } | 458 } |
| 459 | 459 |
| 460 | 460 |
| 461 enum IndexedAccessType { | 461 enum IndexedAccessType { |
| 462 kIndexedLoad, | 462 kIndexedLoad, |
| 463 kIndexedStore | 463 kIndexedStore |
| 464 }; | 464 }; |
| 465 | 465 |
| 466 | 466 |
| 467 static intptr_t ReceiverClassId(Computation* comp) { | 467 static intptr_t ReceiverClassId(Computation* comp) { |
| 468 if (!comp->HasICData()) return kIllegalObjectKind; | 468 if (!comp->HasICData()) return kIllegalCid; |
| 469 | 469 |
| 470 const ICData& ic_data = *comp->ic_data(); | 470 const ICData& ic_data = *comp->ic_data(); |
| 471 | 471 |
| 472 if (ic_data.NumberOfChecks() == 0) return kIllegalObjectKind; | 472 if (ic_data.NumberOfChecks() == 0) return kIllegalCid; |
| 473 // TODO(vegorov): Add multiple receiver type support. | 473 // TODO(vegorov): Add multiple receiver type support. |
| 474 if (ic_data.NumberOfChecks() != 1) return kIllegalObjectKind; | 474 if (ic_data.NumberOfChecks() != 1) return kIllegalCid; |
| 475 ASSERT(HasOneTarget(ic_data)); | 475 ASSERT(HasOneTarget(ic_data)); |
| 476 | 476 |
| 477 Function& target = Function::Handle(); | 477 Function& target = Function::Handle(); |
| 478 intptr_t class_id; | 478 intptr_t class_id; |
| 479 ic_data.GetOneClassCheckAt(0, &class_id, &target); | 479 ic_data.GetOneClassCheckAt(0, &class_id, &target); |
| 480 return class_id; | 480 return class_id; |
| 481 } | 481 } |
| 482 | 482 |
| 483 | 483 |
| 484 void FlowGraphOptimizer::VisitLoadIndexed(LoadIndexedComp* comp, | 484 void FlowGraphOptimizer::VisitLoadIndexed(LoadIndexedComp* comp, |
| 485 BindInstr* instr) { | 485 BindInstr* instr) { |
| 486 const intptr_t class_id = ReceiverClassId(comp); | 486 const intptr_t class_id = ReceiverClassId(comp); |
| 487 switch (class_id) { | 487 switch (class_id) { |
| 488 case kArray: | 488 case kArrayCid: |
| 489 case kImmutableArray: | 489 case kImmutableArrayCid: |
| 490 case kGrowableObjectArray: | 490 case kGrowableObjectArrayCid: |
| 491 comp->set_receiver_type(static_cast<ObjectKind>(class_id)); | 491 comp->set_receiver_type(class_id); |
| 492 } | 492 } |
| 493 } | 493 } |
| 494 | 494 |
| 495 | 495 |
| 496 void FlowGraphOptimizer::VisitStoreIndexed(StoreIndexedComp* comp, | 496 void FlowGraphOptimizer::VisitStoreIndexed(StoreIndexedComp* comp, |
| 497 BindInstr* instr) { | 497 BindInstr* instr) { |
| 498 if (FLAG_enable_type_checks) return; | 498 if (FLAG_enable_type_checks) return; |
| 499 | 499 |
| 500 const intptr_t class_id = ReceiverClassId(comp); | 500 const intptr_t class_id = ReceiverClassId(comp); |
| 501 switch (class_id) { | 501 switch (class_id) { |
| 502 case kArray: | 502 case kArrayCid: |
| 503 case kGrowableObjectArray: | 503 case kGrowableObjectArrayCid: |
| 504 comp->set_receiver_type(static_cast<ObjectKind>(class_id)); | 504 comp->set_receiver_type(class_id); |
| 505 } | 505 } |
| 506 } | 506 } |
| 507 | 507 |
| 508 | 508 |
| 509 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp, | 509 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp, |
| 510 BindInstr* instr) { | 510 BindInstr* instr) { |
| 511 if (!comp->HasICData()) return; | 511 if (!comp->HasICData()) return; |
| 512 | 512 |
| 513 const ICData& ic_data = *comp->ic_data(); | 513 const ICData& ic_data = *comp->ic_data(); |
| 514 if (ic_data.NumberOfChecks() == 0) return; | 514 if (ic_data.NumberOfChecks() == 0) return; |
| 515 // TODO(srdjan): Add multiple receiver type support. | 515 // TODO(srdjan): Add multiple receiver type support. |
| 516 if (ic_data.NumberOfChecks() != 1) return; | 516 if (ic_data.NumberOfChecks() != 1) return; |
| 517 ASSERT(HasOneTarget(ic_data)); | 517 ASSERT(HasOneTarget(ic_data)); |
| 518 | 518 |
| 519 if (HasOnlyTwoSmi(ic_data)) { | 519 if (HasOnlyTwoSmi(ic_data)) { |
| 520 comp->set_operands_class_id(kSmi); | 520 comp->set_operands_class_id(kSmiCid); |
| 521 } else if (HasOnlyTwoDouble(ic_data)) { | 521 } else if (HasOnlyTwoDouble(ic_data)) { |
| 522 comp->set_operands_class_id(kDouble); | 522 comp->set_operands_class_id(kDoubleCid); |
| 523 } | 523 } |
| 524 } | 524 } |
| 525 | 525 |
| 526 | 526 |
| 527 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp, | 527 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp, |
| 528 BindInstr* instr) { | 528 BindInstr* instr) { |
| 529 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() == 1)) { | 529 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() == 1)) { |
| 530 ASSERT(comp->ic_data()->num_args_tested() == 2); | 530 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 531 GrowableArray<intptr_t> class_ids; | 531 GrowableArray<intptr_t> class_ids; |
| 532 Function& target = Function::Handle(); | 532 Function& target = Function::Handle(); |
| 533 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 533 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 534 // TODO(srdjan): allow for mixed mode comparison. | 534 // TODO(srdjan): allow for mixed mode comparison. |
| 535 if ((class_ids[0] == kSmi) && (class_ids[1] == kSmi)) { | 535 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 536 comp->set_receiver_class_id(kSmi); | 536 comp->set_receiver_class_id(kSmiCid); |
| 537 } else if ((class_ids[0] == kDouble) && (class_ids[1] == kDouble)) { | 537 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { |
| 538 comp->set_receiver_class_id(kDouble); | 538 comp->set_receiver_class_id(kDoubleCid); |
| 539 } | 539 } |
| 540 } | 540 } |
| 541 } | 541 } |
| 542 | 542 |
| 543 | 543 |
| 544 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 544 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
| 545 instr->computation()->Accept(this, instr); | 545 instr->computation()->Accept(this, instr); |
| 546 } | 546 } |
| 547 | 547 |
| 548 | 548 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 } | 583 } |
| 584 } | 584 } |
| 585 } | 585 } |
| 586 | 586 |
| 587 | 587 |
| 588 void FlowGraphTypePropagator::PropagateTypes() { | 588 void FlowGraphTypePropagator::PropagateTypes() { |
| 589 VisitBlocks(); | 589 VisitBlocks(); |
| 590 } | 590 } |
| 591 | 591 |
| 592 } // namespace dart | 592 } // namespace dart |
| OLD | NEW |