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/compiler/instruction-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/adapters.h" | 9 #include "src/base/adapters.h" |
10 #include "src/compiler/instruction-selector-impl.h" | 10 #include "src/compiler/instruction-selector-impl.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 current_block_(nullptr), | 34 current_block_(nullptr), |
35 instructions_(zone), | 35 instructions_(zone), |
36 defined_(node_count, false, zone), | 36 defined_(node_count, false, zone), |
37 used_(node_count, false, zone), | 37 used_(node_count, false, zone), |
38 effect_level_(node_count, 0, zone), | 38 effect_level_(node_count, 0, zone), |
39 virtual_registers_(node_count, | 39 virtual_registers_(node_count, |
40 InstructionOperand::kInvalidVirtualRegister, zone), | 40 InstructionOperand::kInvalidVirtualRegister, zone), |
41 virtual_register_rename_(zone), | 41 virtual_register_rename_(zone), |
42 scheduler_(nullptr), | 42 scheduler_(nullptr), |
43 enable_scheduling_(enable_scheduling), | 43 enable_scheduling_(enable_scheduling), |
44 frame_(frame) { | 44 frame_(frame), |
| 45 instruction_selection_failed_(false) { |
45 instructions_.reserve(node_count); | 46 instructions_.reserve(node_count); |
46 } | 47 } |
47 | 48 |
48 void InstructionSelector::SelectInstructions() { | 49 bool InstructionSelector::SelectInstructions() { |
49 // Mark the inputs of all phis in loop headers as used. | 50 // Mark the inputs of all phis in loop headers as used. |
50 BasicBlockVector* blocks = schedule()->rpo_order(); | 51 BasicBlockVector* blocks = schedule()->rpo_order(); |
51 for (auto const block : *blocks) { | 52 for (auto const block : *blocks) { |
52 if (!block->IsLoopHeader()) continue; | 53 if (!block->IsLoopHeader()) continue; |
53 DCHECK_LE(2u, block->PredecessorCount()); | 54 DCHECK_LE(2u, block->PredecessorCount()); |
54 for (Node* const phi : *block) { | 55 for (Node* const phi : *block) { |
55 if (phi->opcode() != IrOpcode::kPhi) continue; | 56 if (phi->opcode() != IrOpcode::kPhi) continue; |
56 | 57 |
57 // Mark all inputs as used. | 58 // Mark all inputs as used. |
58 for (Node* const input : phi->inputs()) { | 59 for (Node* const input : phi->inputs()) { |
59 MarkAsUsed(input); | 60 MarkAsUsed(input); |
60 } | 61 } |
61 } | 62 } |
62 } | 63 } |
63 | 64 |
64 // Visit each basic block in post order. | 65 // Visit each basic block in post order. |
65 for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) { | 66 for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) { |
66 VisitBlock(*i); | 67 VisitBlock(*i); |
| 68 if (instruction_selection_failed()) return false; |
67 } | 69 } |
68 | 70 |
69 // Schedule the selected instructions. | 71 // Schedule the selected instructions. |
70 if (UseInstructionScheduling()) { | 72 if (UseInstructionScheduling()) { |
71 scheduler_ = new (zone()) InstructionScheduler(zone(), sequence()); | 73 scheduler_ = new (zone()) InstructionScheduler(zone(), sequence()); |
72 } | 74 } |
73 | 75 |
74 for (auto const block : *blocks) { | 76 for (auto const block : *blocks) { |
75 InstructionBlock* instruction_block = | 77 InstructionBlock* instruction_block = |
76 sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number())); | 78 sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number())); |
77 for (size_t i = 0; i < instruction_block->phis().size(); i++) { | 79 for (size_t i = 0; i < instruction_block->phis().size(); i++) { |
78 UpdateRenamesInPhi(instruction_block->PhiAt(i)); | 80 UpdateRenamesInPhi(instruction_block->PhiAt(i)); |
79 } | 81 } |
80 size_t end = instruction_block->code_end(); | 82 size_t end = instruction_block->code_end(); |
81 size_t start = instruction_block->code_start(); | 83 size_t start = instruction_block->code_start(); |
82 DCHECK_LE(end, start); | 84 DCHECK_LE(end, start); |
83 StartBlock(RpoNumber::FromInt(block->rpo_number())); | 85 StartBlock(RpoNumber::FromInt(block->rpo_number())); |
84 while (start-- > end) { | 86 while (start-- > end) { |
85 UpdateRenames(instructions_[start]); | 87 UpdateRenames(instructions_[start]); |
86 AddInstruction(instructions_[start]); | 88 AddInstruction(instructions_[start]); |
87 } | 89 } |
88 EndBlock(RpoNumber::FromInt(block->rpo_number())); | 90 EndBlock(RpoNumber::FromInt(block->rpo_number())); |
89 } | 91 } |
90 #if DEBUG | 92 #if DEBUG |
91 sequence()->ValidateSSA(); | 93 sequence()->ValidateSSA(); |
92 #endif | 94 #endif |
| 95 return true; |
93 } | 96 } |
94 | 97 |
95 void InstructionSelector::StartBlock(RpoNumber rpo) { | 98 void InstructionSelector::StartBlock(RpoNumber rpo) { |
96 if (UseInstructionScheduling()) { | 99 if (UseInstructionScheduling()) { |
97 DCHECK_NOT_NULL(scheduler_); | 100 DCHECK_NOT_NULL(scheduler_); |
98 scheduler_->StartBlock(rpo); | 101 scheduler_->StartBlock(rpo); |
99 } else { | 102 } else { |
100 sequence()->StartBlock(rpo); | 103 sequence()->StartBlock(rpo); |
101 } | 104 } |
102 } | 105 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 size_t input_count = arraysize(inputs); | 204 size_t input_count = arraysize(inputs); |
202 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, | 205 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, |
203 temps); | 206 temps); |
204 } | 207 } |
205 | 208 |
206 | 209 |
207 Instruction* InstructionSelector::Emit( | 210 Instruction* InstructionSelector::Emit( |
208 InstructionCode opcode, size_t output_count, InstructionOperand* outputs, | 211 InstructionCode opcode, size_t output_count, InstructionOperand* outputs, |
209 size_t input_count, InstructionOperand* inputs, size_t temp_count, | 212 size_t input_count, InstructionOperand* inputs, size_t temp_count, |
210 InstructionOperand* temps) { | 213 InstructionOperand* temps) { |
| 214 if (output_count >= Instruction::kMaxOutputCount || |
| 215 input_count >= Instruction::kMaxInputCount || |
| 216 temp_count >= Instruction::kMaxTempCount) { |
| 217 set_instruction_selection_failed(); |
| 218 return nullptr; |
| 219 } |
| 220 |
211 Instruction* instr = | 221 Instruction* instr = |
212 Instruction::New(instruction_zone(), opcode, output_count, outputs, | 222 Instruction::New(instruction_zone(), opcode, output_count, outputs, |
213 input_count, inputs, temp_count, temps); | 223 input_count, inputs, temp_count, temps); |
214 return Emit(instr); | 224 return Emit(instr); |
215 } | 225 } |
216 | 226 |
217 | 227 |
218 Instruction* InstructionSelector::Emit(Instruction* instr) { | 228 Instruction* InstructionSelector::Emit(Instruction* instr) { |
219 instructions_.push_back(instr); | 229 instructions_.push_back(instr); |
220 return instr; | 230 return instr; |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 LinkageLocation saved_return_location = | 770 LinkageLocation saved_return_location = |
761 LinkageLocation::ForSavedCallerReturnAddress(); | 771 LinkageLocation::ForSavedCallerReturnAddress(); |
762 InstructionOperand return_address = | 772 InstructionOperand return_address = |
763 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation( | 773 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation( |
764 saved_return_location, stack_param_delta), | 774 saved_return_location, stack_param_delta), |
765 saved_return_location); | 775 saved_return_location); |
766 buffer->instruction_args.push_back(return_address); | 776 buffer->instruction_args.push_back(return_address); |
767 } | 777 } |
768 } | 778 } |
769 | 779 |
770 | |
771 void InstructionSelector::VisitBlock(BasicBlock* block) { | 780 void InstructionSelector::VisitBlock(BasicBlock* block) { |
772 DCHECK(!current_block_); | 781 DCHECK(!current_block_); |
773 current_block_ = block; | 782 current_block_ = block; |
774 int current_block_end = static_cast<int>(instructions_.size()); | 783 int current_block_end = static_cast<int>(instructions_.size()); |
775 | 784 |
776 int effect_level = 0; | 785 int effect_level = 0; |
777 for (Node* const node : *block) { | 786 for (Node* const node : *block) { |
778 if (node->opcode() == IrOpcode::kStore || | 787 if (node->opcode() == IrOpcode::kStore || |
779 node->opcode() == IrOpcode::kUnalignedStore || | 788 node->opcode() == IrOpcode::kUnalignedStore || |
780 node->opcode() == IrOpcode::kCheckedStore || | 789 node->opcode() == IrOpcode::kCheckedStore || |
(...skipping 16 matching lines...) Expand all Loading... |
797 | 806 |
798 // Visit code in reverse control flow order, because architecture-specific | 807 // Visit code in reverse control flow order, because architecture-specific |
799 // matching may cover more than one node at a time. | 808 // matching may cover more than one node at a time. |
800 for (auto node : base::Reversed(*block)) { | 809 for (auto node : base::Reversed(*block)) { |
801 // Skip nodes that are unused or already defined. | 810 // Skip nodes that are unused or already defined. |
802 if (!IsUsed(node) || IsDefined(node)) continue; | 811 if (!IsUsed(node) || IsDefined(node)) continue; |
803 // Generate code for this node "top down", but schedule the code "bottom | 812 // Generate code for this node "top down", but schedule the code "bottom |
804 // up". | 813 // up". |
805 size_t current_node_end = instructions_.size(); | 814 size_t current_node_end = instructions_.size(); |
806 VisitNode(node); | 815 VisitNode(node); |
| 816 if (instruction_selection_failed()) return; |
807 std::reverse(instructions_.begin() + current_node_end, instructions_.end()); | 817 std::reverse(instructions_.begin() + current_node_end, instructions_.end()); |
808 if (instructions_.size() == current_node_end) continue; | 818 if (instructions_.size() == current_node_end) continue; |
809 // Mark source position on first instruction emitted. | 819 // Mark source position on first instruction emitted. |
810 SourcePosition source_position = source_positions_->GetSourcePosition(node); | 820 SourcePosition source_position = source_positions_->GetSourcePosition(node); |
811 if (source_position.IsKnown() && | 821 if (source_position.IsKnown() && |
812 (source_position_mode_ == kAllSourcePositions || | 822 (source_position_mode_ == kAllSourcePositions || |
813 node->opcode() == IrOpcode::kCall)) { | 823 node->opcode() == IrOpcode::kCall)) { |
814 sequence()->SetSourcePosition(instructions_[current_node_end], | 824 sequence()->SetSourcePosition(instructions_[current_node_end], |
815 source_position); | 825 source_position); |
816 } | 826 } |
(...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1836 opcode = kArchCallCodeObject | MiscField::encode(flags); | 1846 opcode = kArchCallCodeObject | MiscField::encode(flags); |
1837 break; | 1847 break; |
1838 case CallDescriptor::kCallJSFunction: | 1848 case CallDescriptor::kCallJSFunction: |
1839 opcode = kArchCallJSFunction | MiscField::encode(flags); | 1849 opcode = kArchCallJSFunction | MiscField::encode(flags); |
1840 break; | 1850 break; |
1841 } | 1851 } |
1842 | 1852 |
1843 // Emit the call instruction. | 1853 // Emit the call instruction. |
1844 size_t const output_count = buffer.outputs.size(); | 1854 size_t const output_count = buffer.outputs.size(); |
1845 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; | 1855 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
1846 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | 1856 Instruction* call_instr = |
1847 &buffer.instruction_args.front()) | 1857 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
1848 ->MarkAsCall(); | 1858 &buffer.instruction_args.front()); |
| 1859 if (instruction_selection_failed()) return; |
| 1860 call_instr->MarkAsCall(); |
1849 } | 1861 } |
1850 | 1862 |
1851 | 1863 |
1852 void InstructionSelector::VisitTailCall(Node* node) { | 1864 void InstructionSelector::VisitTailCall(Node* node) { |
1853 OperandGenerator g(this); | 1865 OperandGenerator g(this); |
1854 CallDescriptor const* descriptor = CallDescriptorOf(node->op()); | 1866 CallDescriptor const* descriptor = CallDescriptorOf(node->op()); |
1855 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 1867 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
1856 | 1868 |
1857 CallDescriptor* caller = linkage()->GetIncomingDescriptor(); | 1869 CallDescriptor* caller = linkage()->GetIncomingDescriptor(); |
1858 if (caller->CanTailCall(node)) { | 1870 if (caller->CanTailCall(node)) { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1944 break; | 1956 break; |
1945 default: | 1957 default: |
1946 UNREACHABLE(); | 1958 UNREACHABLE(); |
1947 return; | 1959 return; |
1948 } | 1960 } |
1949 opcode |= MiscField::encode(descriptor->flags()); | 1961 opcode |= MiscField::encode(descriptor->flags()); |
1950 | 1962 |
1951 // Emit the call instruction. | 1963 // Emit the call instruction. |
1952 size_t output_count = buffer.outputs.size(); | 1964 size_t output_count = buffer.outputs.size(); |
1953 auto* outputs = &buffer.outputs.front(); | 1965 auto* outputs = &buffer.outputs.front(); |
1954 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | 1966 Instruction* call_instr = |
1955 &buffer.instruction_args.front()) | 1967 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
1956 ->MarkAsCall(); | 1968 &buffer.instruction_args.front()); |
| 1969 if (instruction_selection_failed()) return; |
| 1970 call_instr->MarkAsCall(); |
1957 Emit(kArchRet, 0, nullptr, output_count, outputs); | 1971 Emit(kArchRet, 0, nullptr, output_count, outputs); |
1958 } | 1972 } |
1959 } | 1973 } |
1960 | 1974 |
1961 | 1975 |
1962 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1976 void InstructionSelector::VisitGoto(BasicBlock* target) { |
1963 // jump to the next block. | 1977 // jump to the next block. |
1964 OperandGenerator g(this); | 1978 OperandGenerator g(this); |
1965 Emit(kArchJmp, g.NoOutput(), g.Label(target)); | 1979 Emit(kArchJmp, g.NoOutput(), g.Label(target)); |
1966 } | 1980 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2099 return new (instruction_zone()) FrameStateDescriptor( | 2113 return new (instruction_zone()) FrameStateDescriptor( |
2100 instruction_zone(), state_info.type(), state_info.bailout_id(), | 2114 instruction_zone(), state_info.type(), state_info.bailout_id(), |
2101 state_info.state_combine(), parameters, locals, stack, | 2115 state_info.state_combine(), parameters, locals, stack, |
2102 state_info.shared_info(), outer_state); | 2116 state_info.shared_info(), outer_state); |
2103 } | 2117 } |
2104 | 2118 |
2105 | 2119 |
2106 } // namespace compiler | 2120 } // namespace compiler |
2107 } // namespace internal | 2121 } // namespace internal |
2108 } // namespace v8 | 2122 } // namespace v8 |
OLD | NEW |