| 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/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 | 387 |
| 388 // Pattern recognized. | 388 // Pattern recognized. |
| 389 smi_shift_left->mark_truncating(); | 389 smi_shift_left->mark_truncating(); |
| 390 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 390 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); |
| 391 if (bit_and_instr->IsBinaryMintOp()) { | 391 if (bit_and_instr->IsBinaryMintOp()) { |
| 392 // Replace Mint op with Smi op. | 392 // Replace Mint op with Smi op. |
| 393 BinarySmiOpInstr* smi_op = new(Z) BinarySmiOpInstr( | 393 BinarySmiOpInstr* smi_op = new(Z) BinarySmiOpInstr( |
| 394 Token::kBIT_AND, | 394 Token::kBIT_AND, |
| 395 new(Z) Value(left_instr), | 395 new(Z) Value(left_instr), |
| 396 new(Z) Value(right_instr), | 396 new(Z) Value(right_instr), |
| 397 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize. | 397 Thread::kNoDeoptId); // BIT_AND cannot deoptimize. |
| 398 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 398 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
| 399 } | 399 } |
| 400 } | 400 } |
| 401 | 401 |
| 402 | 402 |
| 403 | 403 |
| 404 // Used by TryMergeDivMod. | 404 // Used by TryMergeDivMod. |
| 405 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, | 405 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, |
| 406 // and the using instruction. This is an intermediate step before merging. | 406 // and the using instruction. This is an intermediate step before merging. |
| 407 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, | 407 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, |
| 408 intptr_t ix, | 408 intptr_t ix, |
| 409 intptr_t cid) { | 409 intptr_t cid) { |
| 410 const intptr_t index_scale = Instance::ElementSizeFor(cid); | 410 const intptr_t index_scale = Instance::ElementSizeFor(cid); |
| 411 ConstantInstr* index_instr = | 411 ConstantInstr* index_instr = |
| 412 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(ix))); | 412 flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(ix))); |
| 413 LoadIndexedInstr* load = | 413 LoadIndexedInstr* load = |
| 414 new(Z) LoadIndexedInstr(new(Z) Value(instr), | 414 new(Z) LoadIndexedInstr(new(Z) Value(instr), |
| 415 new(Z) Value(index_instr), | 415 new(Z) Value(index_instr), |
| 416 index_scale, | 416 index_scale, |
| 417 cid, | 417 cid, |
| 418 Isolate::kNoDeoptId, | 418 Thread::kNoDeoptId, |
| 419 instr->token_pos()); | 419 instr->token_pos()); |
| 420 instr->ReplaceUsesWith(load); | 420 instr->ReplaceUsesWith(load); |
| 421 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); | 421 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, | 425 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, |
| 426 intptr_t index, | 426 intptr_t index, |
| 427 Representation rep, | 427 Representation rep, |
| 428 intptr_t cid) { | 428 intptr_t cid) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 insert_before = | 706 insert_before = |
| 707 phi->block()->PredecessorAt(use->use_index())->last_instruction(); | 707 phi->block()->PredecessorAt(use->use_index())->last_instruction(); |
| 708 deopt_target = NULL; | 708 deopt_target = NULL; |
| 709 } else { | 709 } else { |
| 710 deopt_target = insert_before = use->instruction(); | 710 deopt_target = insert_before = use->instruction(); |
| 711 } | 711 } |
| 712 | 712 |
| 713 Definition* converted = NULL; | 713 Definition* converted = NULL; |
| 714 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { | 714 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { |
| 715 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ? | 715 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ? |
| 716 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 716 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; |
| 717 converted = new(Z) UnboxedIntConverterInstr(from, | 717 converted = new(Z) UnboxedIntConverterInstr(from, |
| 718 to, | 718 to, |
| 719 use->CopyWithType(), | 719 use->CopyWithType(), |
| 720 deopt_id); | 720 deopt_id); |
| 721 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { | 721 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { |
| 722 converted = new Int32ToDoubleInstr(use->CopyWithType()); | 722 converted = new Int32ToDoubleInstr(use->CopyWithType()); |
| 723 } else if ((from == kUnboxedMint) && | 723 } else if ((from == kUnboxedMint) && |
| 724 (to == kUnboxedDouble) && | 724 (to == kUnboxedDouble) && |
| 725 CanConvertUnboxedMintToDouble()) { | 725 CanConvertUnboxedMintToDouble()) { |
| 726 const intptr_t deopt_id = (deopt_target != NULL) ? | 726 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 727 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 727 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; |
| 728 ASSERT(CanUnboxDouble()); | 728 ASSERT(CanUnboxDouble()); |
| 729 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id); | 729 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id); |
| 730 } else if ((from == kTagged) && Boxing::Supports(to)) { | 730 } else if ((from == kTagged) && Boxing::Supports(to)) { |
| 731 const intptr_t deopt_id = (deopt_target != NULL) ? | 731 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 732 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 732 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; |
| 733 converted = UnboxInstr::Create(to, use->CopyWithType(), deopt_id); | 733 converted = UnboxInstr::Create(to, use->CopyWithType(), deopt_id); |
| 734 } else if ((to == kTagged) && Boxing::Supports(from)) { | 734 } else if ((to == kTagged) && Boxing::Supports(from)) { |
| 735 converted = BoxInstr::Create(from, use->CopyWithType()); | 735 converted = BoxInstr::Create(from, use->CopyWithType()); |
| 736 } else { | 736 } else { |
| 737 // We have failed to find a suitable conversion instruction. | 737 // We have failed to find a suitable conversion instruction. |
| 738 // Insert two "dummy" conversion instructions with the correct | 738 // Insert two "dummy" conversion instructions with the correct |
| 739 // "from" and "to" representation. The inserted instructions will | 739 // "from" and "to" representation. The inserted instructions will |
| 740 // trigger a deoptimization if executed. See #12417 for a discussion. | 740 // trigger a deoptimization if executed. See #12417 for a discussion. |
| 741 const intptr_t deopt_id = (deopt_target != NULL) ? | 741 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 742 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 742 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; |
| 743 ASSERT(Boxing::Supports(from)); | 743 ASSERT(Boxing::Supports(from)); |
| 744 ASSERT(Boxing::Supports(to)); | 744 ASSERT(Boxing::Supports(to)); |
| 745 Definition* boxed = BoxInstr::Create(from, use->CopyWithType()); | 745 Definition* boxed = BoxInstr::Create(from, use->CopyWithType()); |
| 746 use->BindTo(boxed); | 746 use->BindTo(boxed); |
| 747 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | 747 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
| 748 converted = UnboxInstr::Create(to, new(Z) Value(boxed), deopt_id); | 748 converted = UnboxInstr::Create(to, new(Z) Value(boxed), deopt_id); |
| 749 } | 749 } |
| 750 ASSERT(converted != NULL); | 750 ASSERT(converted != NULL); |
| 751 InsertBefore(insert_before, converted, use->instruction()->env(), | 751 InsertBefore(insert_before, converted, use->instruction()->env(), |
| 752 FlowGraph::kValue); | 752 FlowGraph::kValue); |
| (...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1747 call->GetBlock()->try_index()); | 1747 call->GetBlock()->try_index()); |
| 1748 (*entry)->InheritDeoptTarget(Z, call); | 1748 (*entry)->InheritDeoptTarget(Z, call); |
| 1749 Instruction* cursor = *entry; | 1749 Instruction* cursor = *entry; |
| 1750 | 1750 |
| 1751 array_cid = PrepareInlineIndexedOp(call, | 1751 array_cid = PrepareInlineIndexedOp(call, |
| 1752 array_cid, | 1752 array_cid, |
| 1753 &array, | 1753 &array, |
| 1754 index, | 1754 index, |
| 1755 &cursor); | 1755 &cursor); |
| 1756 | 1756 |
| 1757 intptr_t deopt_id = Isolate::kNoDeoptId; | 1757 intptr_t deopt_id = Thread::kNoDeoptId; |
| 1758 if ((array_cid == kTypedDataInt32ArrayCid) || | 1758 if ((array_cid == kTypedDataInt32ArrayCid) || |
| 1759 (array_cid == kTypedDataUint32ArrayCid)) { | 1759 (array_cid == kTypedDataUint32ArrayCid)) { |
| 1760 // Deoptimization may be needed if result does not always fit in a Smi. | 1760 // Deoptimization may be needed if result does not always fit in a Smi. |
| 1761 deopt_id = (kSmiBits >= 32) ? Isolate::kNoDeoptId : call->deopt_id(); | 1761 deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id(); |
| 1762 } | 1762 } |
| 1763 | 1763 |
| 1764 // Array load and return. | 1764 // Array load and return. |
| 1765 intptr_t index_scale = Instance::ElementSizeFor(array_cid); | 1765 intptr_t index_scale = Instance::ElementSizeFor(array_cid); |
| 1766 *last = new(Z) LoadIndexedInstr(new(Z) Value(array), | 1766 *last = new(Z) LoadIndexedInstr(new(Z) Value(array), |
| 1767 new(Z) Value(index), | 1767 new(Z) Value(index), |
| 1768 index_scale, | 1768 index_scale, |
| 1769 array_cid, | 1769 array_cid, |
| 1770 deopt_id, | 1770 deopt_id, |
| 1771 call->token_pos()); | 1771 call->token_pos()); |
| 1772 cursor = flow_graph()->AppendTo( | 1772 cursor = flow_graph()->AppendTo( |
| 1773 cursor, | 1773 cursor, |
| 1774 *last, | 1774 *last, |
| 1775 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1775 deopt_id != Thread::kNoDeoptId ? call->env() : NULL, |
| 1776 FlowGraph::kValue); | 1776 FlowGraph::kValue); |
| 1777 | 1777 |
| 1778 if (array_cid == kTypedDataFloat32ArrayCid) { | 1778 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1779 *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id); | 1779 *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id); |
| 1780 flow_graph()->AppendTo(cursor, | 1780 flow_graph()->AppendTo(cursor, |
| 1781 *last, | 1781 *last, |
| 1782 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1782 deopt_id != Thread::kNoDeoptId ? call->env() : NULL, |
| 1783 FlowGraph::kValue); | 1783 FlowGraph::kValue); |
| 1784 } | 1784 } |
| 1785 return true; | 1785 return true; |
| 1786 } | 1786 } |
| 1787 | 1787 |
| 1788 | 1788 |
| 1789 // Return true if d is a string of length one (a constant or result from | 1789 // Return true if d is a string of length one (a constant or result from |
| 1790 // from string-from-char-code instruction. | 1790 // from string-from-char-code instruction. |
| 1791 static bool IsLengthOneString(Definition* d) { | 1791 static bool IsLengthOneString(Definition* d) { |
| 1792 if (d->IsConstant()) { | 1792 if (d->IsConstant()) { |
| (...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2788 new(Z) Value(index), | 2788 new(Z) Value(index), |
| 2789 call->deopt_id()), | 2789 call->deopt_id()), |
| 2790 call->env(), | 2790 call->env(), |
| 2791 FlowGraph::kEffect); | 2791 FlowGraph::kEffect); |
| 2792 | 2792 |
| 2793 LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr( | 2793 LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr( |
| 2794 new(Z) Value(str), | 2794 new(Z) Value(str), |
| 2795 new(Z) Value(index), | 2795 new(Z) Value(index), |
| 2796 Instance::ElementSizeFor(cid), | 2796 Instance::ElementSizeFor(cid), |
| 2797 cid, | 2797 cid, |
| 2798 Isolate::kNoDeoptId, | 2798 Thread::kNoDeoptId, |
| 2799 call->token_pos()); | 2799 call->token_pos()); |
| 2800 | 2800 |
| 2801 cursor = flow_graph()->AppendTo(cursor, | 2801 cursor = flow_graph()->AppendTo(cursor, |
| 2802 load_indexed, | 2802 load_indexed, |
| 2803 NULL, | 2803 NULL, |
| 2804 FlowGraph::kValue); | 2804 FlowGraph::kValue); |
| 2805 ASSERT(cursor == load_indexed); | 2805 ASSERT(cursor == load_indexed); |
| 2806 return load_indexed; | 2806 return load_indexed; |
| 2807 } | 2807 } |
| 2808 | 2808 |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3653 (*entry)->InheritDeoptTarget(Z, call); | 3653 (*entry)->InheritDeoptTarget(Z, call); |
| 3654 Instruction* cursor = *entry; | 3654 Instruction* cursor = *entry; |
| 3655 | 3655 |
| 3656 array_cid = PrepareInlineByteArrayBaseOp(call, | 3656 array_cid = PrepareInlineByteArrayBaseOp(call, |
| 3657 array_cid, | 3657 array_cid, |
| 3658 view_cid, | 3658 view_cid, |
| 3659 &array, | 3659 &array, |
| 3660 index, | 3660 index, |
| 3661 &cursor); | 3661 &cursor); |
| 3662 | 3662 |
| 3663 intptr_t deopt_id = Isolate::kNoDeoptId; | 3663 intptr_t deopt_id = Thread::kNoDeoptId; |
| 3664 if ((array_cid == kTypedDataInt32ArrayCid) || | 3664 if ((array_cid == kTypedDataInt32ArrayCid) || |
| 3665 (array_cid == kTypedDataUint32ArrayCid)) { | 3665 (array_cid == kTypedDataUint32ArrayCid)) { |
| 3666 // Deoptimization may be needed if result does not always fit in a Smi. | 3666 // Deoptimization may be needed if result does not always fit in a Smi. |
| 3667 deopt_id = (kSmiBits >= 32) ? Isolate::kNoDeoptId : call->deopt_id(); | 3667 deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id(); |
| 3668 } | 3668 } |
| 3669 | 3669 |
| 3670 *last = new(Z) LoadIndexedInstr(new(Z) Value(array), | 3670 *last = new(Z) LoadIndexedInstr(new(Z) Value(array), |
| 3671 new(Z) Value(index), | 3671 new(Z) Value(index), |
| 3672 1, | 3672 1, |
| 3673 view_cid, | 3673 view_cid, |
| 3674 deopt_id, | 3674 deopt_id, |
| 3675 call->token_pos()); | 3675 call->token_pos()); |
| 3676 cursor = flow_graph()->AppendTo( | 3676 cursor = flow_graph()->AppendTo( |
| 3677 cursor, | 3677 cursor, |
| 3678 *last, | 3678 *last, |
| 3679 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3679 deopt_id != Thread::kNoDeoptId ? call->env() : NULL, |
| 3680 FlowGraph::kValue); | 3680 FlowGraph::kValue); |
| 3681 | 3681 |
| 3682 if (view_cid == kTypedDataFloat32ArrayCid) { | 3682 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3683 *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id); | 3683 *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id); |
| 3684 flow_graph()->AppendTo(cursor, | 3684 flow_graph()->AppendTo(cursor, |
| 3685 *last, | 3685 *last, |
| 3686 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3686 deopt_id != Thread::kNoDeoptId ? call->env() : NULL, |
| 3687 FlowGraph::kValue); | 3687 FlowGraph::kValue); |
| 3688 } | 3688 } |
| 3689 return true; | 3689 return true; |
| 3690 } | 3690 } |
| 3691 | 3691 |
| 3692 | 3692 |
| 3693 bool FlowGraphOptimizer::InlineByteArrayBaseStore(const Function& target, | 3693 bool FlowGraphOptimizer::InlineByteArrayBaseStore(const Function& target, |
| 3694 Instruction* call, | 3694 Instruction* call, |
| 3695 Definition* receiver, | 3695 Definition* receiver, |
| 3696 intptr_t array_cid, | 3696 intptr_t array_cid, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3729 case kTypedDataUint8ArrayCid: | 3729 case kTypedDataUint8ArrayCid: |
| 3730 case kTypedDataUint8ClampedArrayCid: | 3730 case kTypedDataUint8ClampedArrayCid: |
| 3731 case kExternalTypedDataUint8ArrayCid: | 3731 case kExternalTypedDataUint8ArrayCid: |
| 3732 case kExternalTypedDataUint8ClampedArrayCid: | 3732 case kExternalTypedDataUint8ClampedArrayCid: |
| 3733 case kTypedDataInt16ArrayCid: | 3733 case kTypedDataInt16ArrayCid: |
| 3734 case kTypedDataUint16ArrayCid: { | 3734 case kTypedDataUint16ArrayCid: { |
| 3735 // Check that value is always smi. | 3735 // Check that value is always smi. |
| 3736 value_check = ICData::New(flow_graph_->function(), | 3736 value_check = ICData::New(flow_graph_->function(), |
| 3737 i_call->function_name(), | 3737 i_call->function_name(), |
| 3738 Object::empty_array(), // Dummy args. descr. | 3738 Object::empty_array(), // Dummy args. descr. |
| 3739 Isolate::kNoDeoptId, | 3739 Thread::kNoDeoptId, |
| 3740 1); | 3740 1); |
| 3741 value_check.AddReceiverCheck(kSmiCid, target); | 3741 value_check.AddReceiverCheck(kSmiCid, target); |
| 3742 break; | 3742 break; |
| 3743 } | 3743 } |
| 3744 case kTypedDataInt32ArrayCid: | 3744 case kTypedDataInt32ArrayCid: |
| 3745 case kTypedDataUint32ArrayCid: | 3745 case kTypedDataUint32ArrayCid: |
| 3746 // On 64-bit platforms assume that stored value is always a smi. | 3746 // On 64-bit platforms assume that stored value is always a smi. |
| 3747 if (kSmiBits >= 32) { | 3747 if (kSmiBits >= 32) { |
| 3748 value_check = ICData::New(flow_graph_->function(), | 3748 value_check = ICData::New(flow_graph_->function(), |
| 3749 i_call->function_name(), | 3749 i_call->function_name(), |
| 3750 Object::empty_array(), // Dummy args. descr. | 3750 Object::empty_array(), // Dummy args. descr. |
| 3751 Isolate::kNoDeoptId, | 3751 Thread::kNoDeoptId, |
| 3752 1); | 3752 1); |
| 3753 value_check.AddReceiverCheck(kSmiCid, target); | 3753 value_check.AddReceiverCheck(kSmiCid, target); |
| 3754 } | 3754 } |
| 3755 break; | 3755 break; |
| 3756 case kTypedDataFloat32ArrayCid: | 3756 case kTypedDataFloat32ArrayCid: |
| 3757 case kTypedDataFloat64ArrayCid: { | 3757 case kTypedDataFloat64ArrayCid: { |
| 3758 // Check that value is always double. | 3758 // Check that value is always double. |
| 3759 value_check = ICData::New(flow_graph_->function(), | 3759 value_check = ICData::New(flow_graph_->function(), |
| 3760 i_call->function_name(), | 3760 i_call->function_name(), |
| 3761 Object::empty_array(), // Dummy args. descr. | 3761 Object::empty_array(), // Dummy args. descr. |
| 3762 Isolate::kNoDeoptId, | 3762 Thread::kNoDeoptId, |
| 3763 1); | 3763 1); |
| 3764 value_check.AddReceiverCheck(kDoubleCid, target); | 3764 value_check.AddReceiverCheck(kDoubleCid, target); |
| 3765 break; | 3765 break; |
| 3766 } | 3766 } |
| 3767 case kTypedDataInt32x4ArrayCid: { | 3767 case kTypedDataInt32x4ArrayCid: { |
| 3768 // Check that value is always Int32x4. | 3768 // Check that value is always Int32x4. |
| 3769 value_check = ICData::New(flow_graph_->function(), | 3769 value_check = ICData::New(flow_graph_->function(), |
| 3770 i_call->function_name(), | 3770 i_call->function_name(), |
| 3771 Object::empty_array(), // Dummy args. descr. | 3771 Object::empty_array(), // Dummy args. descr. |
| 3772 Isolate::kNoDeoptId, | 3772 Thread::kNoDeoptId, |
| 3773 1); | 3773 1); |
| 3774 value_check.AddReceiverCheck(kInt32x4Cid, target); | 3774 value_check.AddReceiverCheck(kInt32x4Cid, target); |
| 3775 break; | 3775 break; |
| 3776 } | 3776 } |
| 3777 case kTypedDataFloat32x4ArrayCid: { | 3777 case kTypedDataFloat32x4ArrayCid: { |
| 3778 // Check that value is always Float32x4. | 3778 // Check that value is always Float32x4. |
| 3779 value_check = ICData::New(flow_graph_->function(), | 3779 value_check = ICData::New(flow_graph_->function(), |
| 3780 i_call->function_name(), | 3780 i_call->function_name(), |
| 3781 Object::empty_array(), // Dummy args. descr. | 3781 Object::empty_array(), // Dummy args. descr. |
| 3782 Isolate::kNoDeoptId, | 3782 Thread::kNoDeoptId, |
| 3783 1); | 3783 1); |
| 3784 value_check.AddReceiverCheck(kFloat32x4Cid, target); | 3784 value_check.AddReceiverCheck(kFloat32x4Cid, target); |
| 3785 break; | 3785 break; |
| 3786 } | 3786 } |
| 3787 default: | 3787 default: |
| 3788 // Array cids are already checked in the caller. | 3788 // Array cids are already checked in the caller. |
| 3789 UNREACHABLE(); | 3789 UNREACHABLE(); |
| 3790 } | 3790 } |
| 3791 | 3791 |
| 3792 Definition* stored_value = call->ArgumentAt(2); | 3792 Definition* stored_value = call->ArgumentAt(2); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3827 new(Z) Value(index), | 3827 new(Z) Value(index), |
| 3828 new(Z) Value(stored_value), | 3828 new(Z) Value(stored_value), |
| 3829 needs_store_barrier, | 3829 needs_store_barrier, |
| 3830 1, // Index scale | 3830 1, // Index scale |
| 3831 view_cid, | 3831 view_cid, |
| 3832 call->deopt_id(), | 3832 call->deopt_id(), |
| 3833 call->token_pos()); | 3833 call->token_pos()); |
| 3834 | 3834 |
| 3835 flow_graph()->AppendTo(cursor, | 3835 flow_graph()->AppendTo(cursor, |
| 3836 *last, | 3836 *last, |
| 3837 call->deopt_id() != Isolate::kNoDeoptId ? | 3837 call->deopt_id() != Thread::kNoDeoptId ? |
| 3838 call->env() : NULL, | 3838 call->env() : NULL, |
| 3839 FlowGraph::kEffect); | 3839 FlowGraph::kEffect); |
| 3840 return true; | 3840 return true; |
| 3841 } | 3841 } |
| 3842 | 3842 |
| 3843 | 3843 |
| 3844 | 3844 |
| 3845 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayBaseOp( | 3845 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayBaseOp( |
| 3846 Instruction* call, | 3846 Instruction* call, |
| 3847 intptr_t array_cid, | 3847 intptr_t array_cid, |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4183 Bool& as_bool = | 4183 Bool& as_bool = |
| 4184 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 4184 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 4185 if (as_bool.IsNull()) { | 4185 if (as_bool.IsNull()) { |
| 4186 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 4186 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
| 4187 const bool can_deopt = TryExpandTestCidsResult(results, type); | 4187 const bool can_deopt = TryExpandTestCidsResult(results, type); |
| 4188 TestCidsInstr* test_cids = new(Z) TestCidsInstr( | 4188 TestCidsInstr* test_cids = new(Z) TestCidsInstr( |
| 4189 call->token_pos(), | 4189 call->token_pos(), |
| 4190 negate ? Token::kISNOT : Token::kIS, | 4190 negate ? Token::kISNOT : Token::kIS, |
| 4191 new(Z) Value(left), | 4191 new(Z) Value(left), |
| 4192 *results, | 4192 *results, |
| 4193 can_deopt ? call->deopt_id() : Isolate::kNoDeoptId); | 4193 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
| 4194 // Remove type. | 4194 // Remove type. |
| 4195 ReplaceCall(call, test_cids); | 4195 ReplaceCall(call, test_cids); |
| 4196 return; | 4196 return; |
| 4197 } | 4197 } |
| 4198 } else { | 4198 } else { |
| 4199 // TODO(srdjan): Use TestCidsInstr also for this case. | 4199 // TODO(srdjan): Use TestCidsInstr also for this case. |
| 4200 // One result only. | 4200 // One result only. |
| 4201 AddReceiverCheck(call); | 4201 AddReceiverCheck(call); |
| 4202 if (negate) { | 4202 if (negate) { |
| 4203 as_bool = Bool::Get(!as_bool.value()).raw(); | 4203 as_bool = Bool::Get(!as_bool.value()).raw(); |
| (...skipping 4588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8792 | 8792 |
| 8793 // Insert materializations at environment uses. | 8793 // Insert materializations at environment uses. |
| 8794 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8794 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8795 CreateMaterializationAt( | 8795 CreateMaterializationAt( |
| 8796 exits_collector_.exits()[i], alloc, *slots); | 8796 exits_collector_.exits()[i], alloc, *slots); |
| 8797 } | 8797 } |
| 8798 } | 8798 } |
| 8799 | 8799 |
| 8800 | 8800 |
| 8801 } // namespace dart | 8801 } // namespace dart |
| OLD | NEW |