| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { | 655 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { |
| 656 return false; | 656 return false; |
| 657 } | 657 } |
| 658 break; | 658 break; |
| 659 } | 659 } |
| 660 default: | 660 default: |
| 661 // TODO(fschneider): Add support for other array types. | 661 // TODO(fschneider): Add support for other array types. |
| 662 return false; | 662 return false; |
| 663 } | 663 } |
| 664 | 664 |
| 665 BuildStoreIndexed(call, value_check, class_id); |
| 666 return true; |
| 667 } |
| 668 |
| 669 |
| 670 bool FlowGraphOptimizer::TryInlineByteArraySetIndexed(InstanceCallInstr* call) { |
| 671 const intptr_t class_id = ReceiverClassId(call); |
| 672 ICData& value_check = ICData::ZoneHandle(); |
| 673 switch (class_id) { |
| 674 case kInt8ArrayCid: |
| 675 case kUint8ArrayCid: |
| 676 case kUint8ClampedArrayCid: |
| 677 case kExternalUint8ArrayCid: |
| 678 case kExternalUint8ClampedArrayCid: |
| 679 case kInt16ArrayCid: |
| 680 case kUint16ArrayCid: { |
| 681 // Check that value is always smi. |
| 682 value_check = ICData::New(Function::Handle(), |
| 683 String::Handle(), |
| 684 Isolate::kNoDeoptId, |
| 685 1); |
| 686 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); |
| 687 break; |
| 688 } |
| 689 case kInt32ArrayCid: |
| 690 case kUint32ArrayCid: |
| 691 // We don't have ICData for the value stored, so we optimistically assume |
| 692 // smis first. If we ever deoptimized here, we require to unbox the value |
| 693 // before storing to handle the mint case, too. |
| 694 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { |
| 695 value_check = ICData::New(Function::Handle(), |
| 696 String::Handle(), |
| 697 Isolate::kNoDeoptId, |
| 698 1); |
| 699 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); |
| 700 } |
| 701 break; |
| 702 case kFloat32ArrayCid: |
| 703 case kFloat64ArrayCid: { |
| 704 // Check that value is always double. |
| 705 value_check = ICData::New(Function::Handle(), |
| 706 String::Handle(), |
| 707 Isolate::kNoDeoptId, |
| 708 1); |
| 709 value_check.AddReceiverCheck(kDoubleCid, Function::Handle()); |
| 710 break; |
| 711 } |
| 712 default: |
| 713 return false; |
| 714 } |
| 715 BuildStoreIndexed(call, value_check, class_id); |
| 716 return true; |
| 717 } |
| 718 |
| 719 |
| 720 void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call, |
| 721 const ICData& value_check, |
| 722 intptr_t class_id) { |
| 665 Definition* array = call->ArgumentAt(0); | 723 Definition* array = call->ArgumentAt(0); |
| 666 Definition* index = call->ArgumentAt(1); | 724 Definition* index = call->ArgumentAt(1); |
| 667 Definition* stored_value = call->ArgumentAt(2); | 725 Definition* stored_value = call->ArgumentAt(2); |
| 668 if (FLAG_enable_type_checks) { | 726 if (FLAG_enable_type_checks) { |
| 669 // Only type check for the value. A type check for the index is not | 727 // Only type check for the value. A type check for the index is not |
| 670 // needed here because we insert a deoptimizing smi-check for the case | 728 // needed here because we insert a deoptimizing smi-check for the case |
| 671 // the index is not a smi. | 729 // the index is not a smi. |
| 672 const Function& target = | 730 const Function& target = |
| 673 Function::ZoneHandle(call->ic_data()->GetTargetAt(0)); | 731 Function::ZoneHandle(call->ic_data()->GetTargetAt(0)); |
| 674 const AbstractType& value_type = | 732 const AbstractType& value_type = |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 Symbols::Value()); | 780 Symbols::Value()); |
| 723 // Newly inserted instructions that can deoptimize or throw an exception | 781 // Newly inserted instructions that can deoptimize or throw an exception |
| 724 // must have a deoptimization id that is valid for lookup in the unoptimized | 782 // must have a deoptimization id that is valid for lookup in the unoptimized |
| 725 // code. | 783 // code. |
| 726 assert_value->deopt_id_ = call->deopt_id(); | 784 assert_value->deopt_id_ = call->deopt_id(); |
| 727 InsertBefore(call, assert_value, call->env(), Definition::kValue); | 785 InsertBefore(call, assert_value, call->env(), Definition::kValue); |
| 728 } | 786 } |
| 729 | 787 |
| 730 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); | 788 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); |
| 731 // Check if store barrier is needed. | 789 // Check if store barrier is needed. |
| 732 bool needs_store_barrier = true; | 790 bool needs_store_barrier = !RawObject::IsByteArrayClassId(array_cid); |
| 733 if (!value_check.IsNull()) { | 791 if (!value_check.IsNull()) { |
| 734 needs_store_barrier = false; | 792 needs_store_barrier = false; |
| 735 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | 793 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), |
| 736 call); | 794 call); |
| 737 } | 795 } |
| 738 | 796 |
| 739 Definition* array_op = new StoreIndexedInstr(new Value(array), | 797 Definition* array_op = new StoreIndexedInstr(new Value(array), |
| 740 new Value(index), | 798 new Value(index), |
| 741 new Value(stored_value), | 799 new Value(stored_value), |
| 742 needs_store_barrier, | 800 needs_store_barrier, |
| 743 array_cid, | 801 array_cid, |
| 744 call->deopt_id()); | 802 call->deopt_id()); |
| 745 ReplaceCall(call, array_op); | 803 ReplaceCall(call, array_op); |
| 746 return true; | |
| 747 } | 804 } |
| 748 | 805 |
| 749 | 806 |
| 750 | 807 |
| 751 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 808 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 752 const intptr_t class_id = ReceiverClassId(call); | 809 const intptr_t class_id = ReceiverClassId(call); |
| 753 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. | 810 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. |
| 754 intptr_t deopt_id = Isolate::kNoDeoptId; | 811 intptr_t deopt_id = Isolate::kNoDeoptId; |
| 755 switch (class_id) { | 812 switch (class_id) { |
| 756 case kArrayCid: | 813 case kArrayCid: |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 case MethodRecognizer::kInt8ArrayGetIndexed: | 1410 case MethodRecognizer::kInt8ArrayGetIndexed: |
| 1354 case MethodRecognizer::kUint8ArrayGetIndexed: | 1411 case MethodRecognizer::kUint8ArrayGetIndexed: |
| 1355 case MethodRecognizer::kUint8ClampedArrayGetIndexed: | 1412 case MethodRecognizer::kUint8ClampedArrayGetIndexed: |
| 1356 case MethodRecognizer::kExternalUint8ArrayGetIndexed: | 1413 case MethodRecognizer::kExternalUint8ArrayGetIndexed: |
| 1357 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed: | 1414 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed: |
| 1358 case MethodRecognizer::kInt16ArrayGetIndexed: | 1415 case MethodRecognizer::kInt16ArrayGetIndexed: |
| 1359 case MethodRecognizer::kUint16ArrayGetIndexed: | 1416 case MethodRecognizer::kUint16ArrayGetIndexed: |
| 1360 case MethodRecognizer::kInt32ArrayGetIndexed: | 1417 case MethodRecognizer::kInt32ArrayGetIndexed: |
| 1361 case MethodRecognizer::kUint32ArrayGetIndexed: | 1418 case MethodRecognizer::kUint32ArrayGetIndexed: |
| 1362 return TryReplaceWithLoadIndexed(call); | 1419 return TryReplaceWithLoadIndexed(call); |
| 1420 |
| 1421 case MethodRecognizer::kFloat32ArraySetIndexed: |
| 1422 case MethodRecognizer::kFloat64ArraySetIndexed: |
| 1423 case MethodRecognizer::kInt8ArraySetIndexed: |
| 1424 case MethodRecognizer::kUint8ArraySetIndexed: |
| 1425 case MethodRecognizer::kUint8ClampedArraySetIndexed: |
| 1426 case MethodRecognizer::kExternalUint8ArraySetIndexed: |
| 1427 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed: |
| 1428 case MethodRecognizer::kInt16ArraySetIndexed: |
| 1429 case MethodRecognizer::kUint16ArraySetIndexed: |
| 1430 case MethodRecognizer::kInt32ArraySetIndexed: |
| 1431 case MethodRecognizer::kUint32ArraySetIndexed: |
| 1432 return TryInlineByteArraySetIndexed(call); |
| 1433 |
| 1363 default: | 1434 default: |
| 1364 break; | 1435 break; |
| 1365 } | 1436 } |
| 1366 | 1437 |
| 1367 if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) && | 1438 if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) && |
| 1368 (ic_data.NumberOfChecks() == 1) && | 1439 (ic_data.NumberOfChecks() == 1) && |
| 1369 ((class_ids[0] == kOneByteStringCid) || | 1440 ((class_ids[0] == kOneByteStringCid) || |
| 1370 (class_ids[0] == kTwoByteStringCid))) { | 1441 (class_ids[0] == kTwoByteStringCid))) { |
| 1371 LoadIndexedInstr* instr = BuildStringCharCodeAt(call, class_ids[0]); | 1442 LoadIndexedInstr* instr = BuildStringCharCodeAt(call, class_ids[0]); |
| 1372 ReplaceCall(call, instr); | 1443 ReplaceCall(call, instr); |
| (...skipping 2813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4186 | 4257 |
| 4187 if (FLAG_trace_constant_propagation) { | 4258 if (FLAG_trace_constant_propagation) { |
| 4188 OS::Print("\n==== After constant propagation ====\n"); | 4259 OS::Print("\n==== After constant propagation ====\n"); |
| 4189 FlowGraphPrinter printer(*graph_); | 4260 FlowGraphPrinter printer(*graph_); |
| 4190 printer.PrintBlocks(); | 4261 printer.PrintBlocks(); |
| 4191 } | 4262 } |
| 4192 } | 4263 } |
| 4193 | 4264 |
| 4194 | 4265 |
| 4195 } // namespace dart | 4266 } // namespace dart |
| OLD | NEW |