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 |