| 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 #ifndef DART_PRECOMPILED_RUNTIME | 4 #ifndef DART_PRECOMPILED_RUNTIME |
| 5 #include "vm/jit_optimizer.h" | 5 #include "vm/jit_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 661 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 662 // Don't generate smi code if the IC data is marked because | 662 // Don't generate smi code if the IC data is marked because |
| 663 // of an overflow. | 663 // of an overflow. |
| 664 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) | 664 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) |
| 665 ? kMintCid | 665 ? kMintCid |
| 666 : kSmiCid; | 666 : kSmiCid; |
| 667 } else if (HasTwoMintOrSmi(ic_data) && | 667 } else if (HasTwoMintOrSmi(ic_data) && |
| 668 FlowGraphCompiler::SupportsUnboxedMints()) { | 668 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 669 // Don't generate mint code if the IC data is marked because of an | 669 // Don't generate mint code if the IC data is marked because of an |
| 670 // overflow. | 670 // overflow. |
| 671 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) return false; | 671 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryInt64Op)) return false; |
| 672 operands_type = kMintCid; | 672 operands_type = kMintCid; |
| 673 } else if (ShouldSpecializeForDouble(ic_data)) { | 673 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 674 operands_type = kDoubleCid; | 674 operands_type = kDoubleCid; |
| 675 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { | 675 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { |
| 676 operands_type = kFloat32x4Cid; | 676 operands_type = kFloat32x4Cid; |
| 677 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { | 677 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { |
| 678 ASSERT(op_kind != Token::kMUL); // Int32x4 doesn't have a multiply op. | 678 ASSERT(op_kind != Token::kMUL); // Int32x4 doesn't have a multiply op. |
| 679 operands_type = kInt32x4Cid; | 679 operands_type = kInt32x4Cid; |
| 680 } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) { | 680 } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) { |
| 681 operands_type = kFloat64x2Cid; | 681 operands_type = kFloat64x2Cid; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 708 } else { | 708 } else { |
| 709 return false; | 709 return false; |
| 710 } | 710 } |
| 711 break; | 711 break; |
| 712 case Token::kSHR: | 712 case Token::kSHR: |
| 713 case Token::kSHL: | 713 case Token::kSHL: |
| 714 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 714 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 715 // Left shift may overflow from smi into mint or big ints. | 715 // Left shift may overflow from smi into mint or big ints. |
| 716 // Don't generate smi code if the IC data is marked because | 716 // Don't generate smi code if the IC data is marked because |
| 717 // of an overflow. | 717 // of an overflow. |
| 718 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) { | 718 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryInt64Op)) { |
| 719 return false; | 719 return false; |
| 720 } | 720 } |
| 721 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) | 721 operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp) |
| 722 ? kMintCid | 722 ? kMintCid |
| 723 : kSmiCid; | 723 : kSmiCid; |
| 724 } else if (HasTwoMintOrSmi(ic_data) && | 724 } else if (HasTwoMintOrSmi(ic_data) && |
| 725 HasOnlyOneSmi(ICData::Handle( | 725 HasOnlyOneSmi(ICData::Handle( |
| 726 Z, ic_data.AsUnaryClassChecksForArgNr(1)))) { | 726 Z, ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 727 // Don't generate mint code if the IC data is marked because of an | 727 // Don't generate mint code if the IC data is marked because of an |
| 728 // overflow. | 728 // overflow. |
| 729 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) { | 729 if (ic_data.HasDeoptReason(ICData::kDeoptBinaryInt64Op)) { |
| 730 return false; | 730 return false; |
| 731 } | 731 } |
| 732 // Check for smi/mint << smi or smi/mint >> smi. | 732 // Check for smi/mint << smi or smi/mint >> smi. |
| 733 operands_type = kMintCid; | 733 operands_type = kMintCid; |
| 734 } else { | 734 } else { |
| 735 return false; | 735 return false; |
| 736 } | 736 } |
| 737 break; | 737 break; |
| 738 case Token::kMOD: | 738 case Token::kMOD: |
| 739 case Token::kTRUNCDIV: | 739 case Token::kTRUNCDIV: |
| (...skipping 29 matching lines...) Expand all Loading... |
| 769 call->env(), FlowGraph::kEffect); | 769 call->env(), FlowGraph::kEffect); |
| 770 } | 770 } |
| 771 | 771 |
| 772 BinaryDoubleOpInstr* double_bin_op = new (Z) | 772 BinaryDoubleOpInstr* double_bin_op = new (Z) |
| 773 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), | 773 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), |
| 774 call->deopt_id(), call->token_pos()); | 774 call->deopt_id(), call->token_pos()); |
| 775 ReplaceCall(call, double_bin_op); | 775 ReplaceCall(call, double_bin_op); |
| 776 } else if (operands_type == kMintCid) { | 776 } else if (operands_type == kMintCid) { |
| 777 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 777 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
| 778 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 778 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
| 779 ShiftMintOpInstr* shift_op = new (Z) ShiftMintOpInstr( | 779 ShiftInt64OpInstr* shift_op = new (Z) ShiftInt64OpInstr( |
| 780 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 780 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
| 781 ReplaceCall(call, shift_op); | 781 ReplaceCall(call, shift_op); |
| 782 } else { | 782 } else { |
| 783 BinaryMintOpInstr* bin_op = new (Z) BinaryMintOpInstr( | 783 BinaryInt64OpInstr* bin_op = new (Z) BinaryInt64OpInstr( |
| 784 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); | 784 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); |
| 785 ReplaceCall(call, bin_op); | 785 ReplaceCall(call, bin_op); |
| 786 } | 786 } |
| 787 } else if (operands_type == kFloat32x4Cid) { | 787 } else if (operands_type == kFloat32x4Cid) { |
| 788 return InlineFloat32x4BinaryOp(call, op_kind); | 788 return InlineFloat32x4BinaryOp(call, op_kind); |
| 789 } else if (operands_type == kInt32x4Cid) { | 789 } else if (operands_type == kInt32x4Cid) { |
| 790 return InlineInt32x4BinaryOp(call, op_kind); | 790 return InlineInt32x4BinaryOp(call, op_kind); |
| 791 } else if (operands_type == kFloat64x2Cid) { | 791 } else if (operands_type == kFloat64x2Cid) { |
| 792 return InlineFloat64x2BinaryOp(call, op_kind); | 792 return InlineFloat64x2BinaryOp(call, op_kind); |
| 793 } else if (op_kind == Token::kMOD) { | 793 } else if (op_kind == Token::kMOD) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 InsertBefore(call, | 846 InsertBefore(call, |
| 847 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(), | 847 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(), |
| 848 call->token_pos()), | 848 call->token_pos()), |
| 849 call->env(), FlowGraph::kEffect); | 849 call->env(), FlowGraph::kEffect); |
| 850 unary_op = new (Z) | 850 unary_op = new (Z) |
| 851 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id()); | 851 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id()); |
| 852 } else if ((op_kind == Token::kBIT_NOT) && | 852 } else if ((op_kind == Token::kBIT_NOT) && |
| 853 HasOnlySmiOrMint(*call->ic_data()) && | 853 HasOnlySmiOrMint(*call->ic_data()) && |
| 854 FlowGraphCompiler::SupportsUnboxedMints()) { | 854 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 855 unary_op = new (Z) | 855 unary_op = new (Z) |
| 856 UnaryMintOpInstr(op_kind, new (Z) Value(input), call->deopt_id()); | 856 UnaryInt64OpInstr(op_kind, new (Z) Value(input), call->deopt_id()); |
| 857 } else if (HasOnlyOneDouble(*call->ic_data()) && | 857 } else if (HasOnlyOneDouble(*call->ic_data()) && |
| 858 (op_kind == Token::kNEGATE) && CanUnboxDouble()) { | 858 (op_kind == Token::kNEGATE) && CanUnboxDouble()) { |
| 859 AddReceiverCheck(call); | 859 AddReceiverCheck(call); |
| 860 unary_op = new (Z) UnaryDoubleOpInstr(Token::kNEGATE, new (Z) Value(input), | 860 unary_op = new (Z) UnaryDoubleOpInstr(Token::kNEGATE, new (Z) Value(input), |
| 861 call->deopt_id()); | 861 call->deopt_id()); |
| 862 } else { | 862 } else { |
| 863 return false; | 863 return false; |
| 864 } | 864 } |
| 865 ASSERT(unary_op != NULL); | 865 ASSERT(unary_op != NULL); |
| 866 ReplaceCall(call, unary_op); | 866 ReplaceCall(call, unary_op); |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1602 // elimination and ensure proper GC barrier. | 1602 // elimination and ensure proper GC barrier. |
| 1603 store->set_is_initialization(true); | 1603 store->set_is_initialization(true); |
| 1604 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); | 1604 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); |
| 1605 cursor = store; | 1605 cursor = store; |
| 1606 } | 1606 } |
| 1607 } | 1607 } |
| 1608 | 1608 |
| 1609 void JitOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | 1609 void JitOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
| 1610 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. | 1610 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. |
| 1611 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | 1611 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
| 1612 if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedMint); | 1612 if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedInt64); |
| 1613 #endif | 1613 #endif |
| 1614 } | 1614 } |
| 1615 | 1615 |
| 1616 bool JitOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, | 1616 bool JitOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
| 1617 const ICData& unary_ic_data) { | 1617 const ICData& unary_ic_data) { |
| 1618 ASSERT(!unary_ic_data.NumberOfChecksIs(0) && | 1618 ASSERT(!unary_ic_data.NumberOfChecksIs(0) && |
| 1619 (unary_ic_data.NumArgsTested() == 1)); | 1619 (unary_ic_data.NumArgsTested() == 1)); |
| 1620 if (I->type_checks()) { | 1620 if (I->type_checks()) { |
| 1621 // Checked mode setters are inlined like normal methods by conventional | 1621 // Checked mode setters are inlined like normal methods by conventional |
| 1622 // inlining. | 1622 // inlining. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1680 | 1680 |
| 1681 // Discard the environment from the original instruction because the store | 1681 // Discard the environment from the original instruction because the store |
| 1682 // can't deoptimize. | 1682 // can't deoptimize. |
| 1683 instr->RemoveEnvironment(); | 1683 instr->RemoveEnvironment(); |
| 1684 ReplaceCall(instr, store); | 1684 ReplaceCall(instr, store); |
| 1685 return true; | 1685 return true; |
| 1686 } | 1686 } |
| 1687 | 1687 |
| 1688 } // namespace dart | 1688 } // namespace dart |
| 1689 #endif // DART_PRECOMPILED_RUNTIME | 1689 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |