| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
| 6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
| 7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
| 8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 | 705 |
| 706 | 706 |
| 707 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index, | 707 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index, |
| 708 InstructionOperand* operand) { | 708 InstructionOperand* operand) { |
| 709 DCHECK(HasNoSpillType()); | 709 DCHECK(HasNoSpillType()); |
| 710 spills_at_definition_ = new (zone) | 710 spills_at_definition_ = new (zone) |
| 711 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); | 711 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); |
| 712 } | 712 } |
| 713 | 713 |
| 714 | 714 |
| 715 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock( | 715 void TopLevelLiveRange::MarkSpilledInDeferredBlock( |
| 716 InstructionSequence* code, const InstructionOperand& spill_operand) { | 716 const InstructionSequence* code) { |
| 717 if (!FLAG_turbo_preprocess_ranges || IsEmpty() || HasNoSpillType() || | 717 if (!FLAG_turbo_preprocess_ranges || IsEmpty() || HasNoSpillType() || |
| 718 spill_operand.IsConstant() || spill_operand.IsImmediate()) { | 718 !HasSpillRange()) { |
| 719 return false; | 719 return; |
| 720 } | 720 } |
| 721 | 721 |
| 722 int count = 0; | 722 int count = 0; |
| 723 for (const LiveRange* child = this; child != nullptr; child = child->next()) { | 723 for (const LiveRange* child = this; child != nullptr; child = child->next()) { |
| 724 int first_instr = child->Start().ToInstructionIndex(); | 724 int first_instr = child->Start().ToInstructionIndex(); |
| 725 | 725 |
| 726 // If the range starts at instruction end, the first instruction index is | 726 // If the range starts at instruction end, the first instruction index is |
| 727 // the next one. | 727 // the next one. |
| 728 if (!child->Start().IsGapPosition() && !child->Start().IsStart()) { | 728 if (!child->Start().IsGapPosition() && !child->Start().IsStart()) { |
| 729 ++first_instr; | 729 ++first_instr; |
| 730 } | 730 } |
| 731 | 731 |
| 732 // We only look at where the range starts. It doesn't matter where it ends: | 732 // We only look at where the range starts. It doesn't matter where it ends: |
| 733 // if it ends past this block, then either there is a phi there already, | 733 // if it ends past this block, then either there is a phi there already, |
| 734 // or ResolveControlFlow will adapt the last instruction gap of this block | 734 // or ResolveControlFlow will adapt the last instruction gap of this block |
| 735 // as if there were a phi. In either case, data flow will be correct. | 735 // as if there were a phi. In either case, data flow will be correct. |
| 736 const InstructionBlock* block = code->GetInstructionBlock(first_instr); | 736 const InstructionBlock* block = code->GetInstructionBlock(first_instr); |
| 737 | 737 |
| 738 // If we have slot uses in a subrange, bail out, because we need the value | 738 // If we have slot uses in a subrange, bail out, because we need the value |
| 739 // on the stack before that use. | 739 // on the stack before that use. |
| 740 bool has_slot_use = child->NextSlotPosition(child->Start()) != nullptr; | 740 bool has_slot_use = child->NextSlotPosition(child->Start()) != nullptr; |
| 741 if (!block->IsDeferred()) { | 741 if (!block->IsDeferred()) { |
| 742 if (child->spilled() || has_slot_use) { | 742 if (child->spilled() || has_slot_use) { |
| 743 TRACE( | 743 TRACE( |
| 744 "Live Range %d must be spilled at definition: found a " | 744 "Live Range %d must be spilled at definition: found a " |
| 745 "slot-requiring non-deferred child range %d.\n", | 745 "slot-requiring non-deferred child range %d.\n", |
| 746 TopLevel()->vreg(), child->relative_id()); | 746 TopLevel()->vreg(), child->relative_id()); |
| 747 return false; | 747 return; |
| 748 } | 748 } |
| 749 } else { | 749 } else { |
| 750 if (child->spilled() || has_slot_use) ++count; | 750 if (child->spilled() || has_slot_use) ++count; |
| 751 } | 751 } |
| 752 } | 752 } |
| 753 if (count == 0) return false; | 753 if (count == 0) return; |
| 754 | 754 |
| 755 spill_start_index_ = -1; | 755 spill_start_index_ = -1; |
| 756 spilled_in_deferred_blocks_ = true; | 756 spilled_in_deferred_blocks_ = true; |
| 757 spills_at_definition_ = nullptr; |
| 758 } |
| 759 |
| 760 |
| 761 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock( |
| 762 InstructionSequence* code, const InstructionOperand& spill_operand) { |
| 763 if (!IsSpilledOnlyInDeferredBlocks()) return false; |
| 757 | 764 |
| 758 TRACE("Live Range %d will be spilled only in deferred blocks.\n", vreg()); | 765 TRACE("Live Range %d will be spilled only in deferred blocks.\n", vreg()); |
| 759 // If we have ranges that aren't spilled but require the operand on the stack, | 766 // If we have ranges that aren't spilled but require the operand on the stack, |
| 760 // make sure we insert the spill. | 767 // make sure we insert the spill. |
| 761 for (const LiveRange* child = this; child != nullptr; child = child->next()) { | 768 for (const LiveRange* child = this; child != nullptr; child = child->next()) { |
| 762 if (!child->spilled() && | 769 if (!child->spilled() && |
| 763 child->NextSlotPosition(child->Start()) != nullptr) { | 770 child->NextSlotPosition(child->Start()) != nullptr) { |
| 764 auto instr = code->InstructionAt(child->Start().ToInstructionIndex()); | 771 auto instr = code->InstructionAt(child->Start().ToInstructionIndex()); |
| 765 // Insert spill at the end to let live range connections happen at START. | 772 // Insert spill at the end to let live range connections happen at START. |
| 766 auto move = | 773 auto move = |
| (...skipping 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2955 SpillSlotLocator::SpillSlotLocator(RegisterAllocationData* data) | 2962 SpillSlotLocator::SpillSlotLocator(RegisterAllocationData* data) |
| 2956 : data_(data) {} | 2963 : data_(data) {} |
| 2957 | 2964 |
| 2958 | 2965 |
| 2959 void SpillSlotLocator::LocateSpillSlots() { | 2966 void SpillSlotLocator::LocateSpillSlots() { |
| 2960 auto code = data()->code(); | 2967 auto code = data()->code(); |
| 2961 for (TopLevelLiveRange* range : data()->live_ranges()) { | 2968 for (TopLevelLiveRange* range : data()->live_ranges()) { |
| 2962 if (range == nullptr || range->IsEmpty()) continue; | 2969 if (range == nullptr || range->IsEmpty()) continue; |
| 2963 // We care only about ranges which spill in the frame. | 2970 // We care only about ranges which spill in the frame. |
| 2964 if (!range->HasSpillRange()) continue; | 2971 if (!range->HasSpillRange()) continue; |
| 2965 auto spills = range->spills_at_definition(); | 2972 range->MarkSpilledInDeferredBlock(data()->code()); |
| 2966 DCHECK_NOT_NULL(spills); | 2973 if (range->IsSpilledOnlyInDeferredBlocks()) { |
| 2967 for (; spills != nullptr; spills = spills->next) { | 2974 for (LiveRange* child = range; child != nullptr; child = child->next()) { |
| 2968 code->GetInstructionBlock(spills->gap_index)->mark_needs_frame(); | 2975 if (child->spilled()) { |
| 2976 code->GetInstructionBlock(child->Start().ToInstructionIndex()) |
| 2977 ->mark_needs_frame(); |
| 2978 } |
| 2979 } |
| 2980 } else { |
| 2981 auto spills = range->spills_at_definition(); |
| 2982 DCHECK_NOT_NULL(spills); |
| 2983 for (; spills != nullptr; spills = spills->next) { |
| 2984 code->GetInstructionBlock(spills->gap_index)->mark_needs_frame(); |
| 2985 } |
| 2969 } | 2986 } |
| 2970 } | 2987 } |
| 2971 } | 2988 } |
| 2972 | 2989 |
| 2973 | 2990 |
| 2974 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} | 2991 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} |
| 2975 | 2992 |
| 2976 | 2993 |
| 2977 void OperandAssigner::AssignSpillSlots() { | 2994 void OperandAssigner::AssignSpillSlots() { |
| 2978 ZoneVector<SpillRange*>& spill_ranges = data()->spill_ranges(); | 2995 ZoneVector<SpillRange*>& spill_ranges = data()->spill_ranges(); |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3443 auto eliminate = moves->PrepareInsertAfter(move); | 3460 auto eliminate = moves->PrepareInsertAfter(move); |
| 3444 to_insert.push_back(move); | 3461 to_insert.push_back(move); |
| 3445 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3462 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
| 3446 } | 3463 } |
| 3447 } | 3464 } |
| 3448 | 3465 |
| 3449 | 3466 |
| 3450 } // namespace compiler | 3467 } // namespace compiler |
| 3451 } // namespace internal | 3468 } // namespace internal |
| 3452 } // namespace v8 | 3469 } // namespace v8 |
| OLD | NEW |