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/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 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 return class_id; | 541 return class_id; |
542 } | 542 } |
543 | 543 |
544 | 544 |
545 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 545 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { |
546 const intptr_t class_id = ReceiverClassId(call); | 546 const intptr_t class_id = ReceiverClassId(call); |
547 ICData& value_check = ICData::ZoneHandle(); | 547 ICData& value_check = ICData::ZoneHandle(); |
548 switch (class_id) { | 548 switch (class_id) { |
549 case kArrayCid: | 549 case kArrayCid: |
550 case kGrowableObjectArrayCid: | 550 case kGrowableObjectArrayCid: |
551 // Acceptable store index classes. | 551 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) { |
| 552 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
| 553 } |
552 break; | 554 break; |
| 555 case kUint8ArrayCid: |
| 556 // Check that value is always smi. |
| 557 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
| 558 if ((value_check.NumberOfChecks() != 1) || |
| 559 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) { |
| 560 return false; |
| 561 } |
| 562 break; |
| 563 |
553 case kFloat32ArrayCid: | 564 case kFloat32ArrayCid: |
554 case kFloat64ArrayCid: { | 565 case kFloat64ArrayCid: { |
555 // Check that value is always double. | 566 // Check that value is always double. |
556 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); | 567 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
557 if ((value_check.NumberOfChecks() != 1) || | 568 if ((value_check.NumberOfChecks() != 1) || |
558 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { | 569 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { |
559 return false; | 570 return false; |
560 } | 571 } |
561 break; | 572 break; |
562 } | 573 } |
(...skipping 22 matching lines...) Expand all Loading... |
585 instantiator_class.type_arguments_field_offset(); | 596 instantiator_class.type_arguments_field_offset(); |
586 LoadFieldInstr* load_type_args = | 597 LoadFieldInstr* load_type_args = |
587 new LoadFieldInstr(array->Copy(), | 598 new LoadFieldInstr(array->Copy(), |
588 type_arguments_field_offset, | 599 type_arguments_field_offset, |
589 Type::ZoneHandle()); // No type. | 600 Type::ZoneHandle()); // No type. |
590 InsertBefore(call, load_type_args, NULL, Definition::kValue); | 601 InsertBefore(call, load_type_args, NULL, Definition::kValue); |
591 instantiator = array->Copy(); | 602 instantiator = array->Copy(); |
592 type_args = new Value(load_type_args); | 603 type_args = new Value(load_type_args); |
593 break; | 604 break; |
594 } | 605 } |
| 606 case kUint8ArrayCid: |
595 case kFloat32ArrayCid: | 607 case kFloat32ArrayCid: |
596 case kFloat64ArrayCid: { | 608 case kFloat64ArrayCid: { |
597 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); | 609 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); |
598 InsertBefore(call, null_constant, NULL, Definition::kValue); | 610 InsertBefore(call, null_constant, NULL, Definition::kValue); |
599 instantiator = new Value(null_constant); | 611 instantiator = new Value(null_constant); |
600 type_args = new Value(null_constant); | 612 type_args = new Value(null_constant); |
601 ASSERT(value_type.IsDoubleType()); | 613 ASSERT((class_id != kUint8ArrayCid) || value_type.IsIntType()); |
| 614 ASSERT((class_id != kFloat32ArrayCid && class_id != kFloat64ArrayCid) || |
| 615 value_type.IsDoubleType()); |
602 ASSERT(value_type.IsInstantiated()); | 616 ASSERT(value_type.IsInstantiated()); |
603 break; | 617 break; |
604 } | 618 } |
605 default: | 619 default: |
606 // TODO(fschneider): Add support for other array types. | 620 // TODO(fschneider): Add support for other array types. |
607 UNREACHABLE(); | 621 UNREACHABLE(); |
608 } | 622 } |
609 AssertAssignableInstr* assert_value = | 623 AssertAssignableInstr* assert_value = |
610 new AssertAssignableInstr(call->token_pos(), | 624 new AssertAssignableInstr(call->token_pos(), |
611 value->Copy(), | 625 value->Copy(), |
612 instantiator, | 626 instantiator, |
613 type_args, | 627 type_args, |
614 value_type, | 628 value_type, |
615 Symbols::Value()); | 629 Symbols::Value()); |
616 InsertBefore(call, assert_value, NULL, Definition::kValue); | 630 InsertBefore(call, assert_value, NULL, Definition::kValue); |
617 } | 631 } |
618 | 632 |
619 Value* array = NULL; | 633 Value* array = NULL; |
620 Value* index = NULL; | 634 Value* index = NULL; |
621 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); | 635 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); |
622 Value* value = call->ArgumentAt(2)->value(); | 636 Value* value = call->ArgumentAt(2)->value(); |
623 // Check if store barrier is needed. | 637 // Check if store barrier is needed. |
624 bool needs_store_barrier = true; | 638 bool needs_store_barrier = true; |
625 if ((class_id == kFloat32ArrayCid) || (class_id == kFloat64ArrayCid)) { | 639 if (!value_check.IsNull()) { |
626 ASSERT(!value_check.IsNull()); | 640 ASSERT(value_check.NumberOfChecks() == 1); |
627 InsertBefore(call, | 641 if (value_check.GetReceiverClassIdAt(0) == kSmiCid) { |
628 new CheckClassInstr(value->Copy(), | 642 InsertBefore(call, |
629 call->deopt_id(), | 643 new CheckSmiInstr(value->Copy(), call->deopt_id()), |
630 value_check), | 644 call->env(), |
631 call->env(), | 645 Definition::kEffect); |
632 Definition::kEffect); | 646 needs_store_barrier = false; |
633 needs_store_barrier = false; | 647 } else { |
634 } else if (ArgIsAlwaysSmi(*call->ic_data(), 2)) { | 648 ASSERT(value_check.GetReceiverClassIdAt(0) == kDoubleCid); |
635 InsertBefore(call, | 649 InsertBefore(call, |
636 new CheckSmiInstr(value->Copy(), call->deopt_id()), | 650 new CheckClassInstr(value->Copy(), |
637 call->env(), | 651 call->deopt_id(), |
638 Definition::kEffect); | 652 value_check), |
639 needs_store_barrier = false; | 653 call->env(), |
| 654 Definition::kEffect); |
| 655 needs_store_barrier = false; |
| 656 } |
640 } | 657 } |
641 | 658 |
642 Definition* array_op = | 659 Definition* array_op = |
643 new StoreIndexedInstr(array, index, value, | 660 new StoreIndexedInstr(array, index, value, |
644 needs_store_barrier, array_cid, call->deopt_id()); | 661 needs_store_barrier, array_cid, call->deopt_id()); |
645 call->ReplaceWith(array_op, current_iterator()); | 662 call->ReplaceWith(array_op, current_iterator()); |
646 RemovePushArguments(call); | 663 RemovePushArguments(call); |
647 return true; | 664 return true; |
648 } | 665 } |
649 | 666 |
(...skipping 3764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4414 | 4431 |
4415 if (FLAG_trace_constant_propagation) { | 4432 if (FLAG_trace_constant_propagation) { |
4416 OS::Print("\n==== After constant propagation ====\n"); | 4433 OS::Print("\n==== After constant propagation ====\n"); |
4417 FlowGraphPrinter printer(*graph_); | 4434 FlowGraphPrinter printer(*graph_); |
4418 printer.PrintBlocks(); | 4435 printer.PrintBlocks(); |
4419 } | 4436 } |
4420 } | 4437 } |
4421 | 4438 |
4422 | 4439 |
4423 } // namespace dart | 4440 } // namespace dart |
OLD | NEW |