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 |