Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1019)

Side by Side Diff: src/compiler/instruction-selector.cc

Issue 2390303002: [turbofan] Check instruction input/output count limits in instruction selector. (Closed)
Patch Set: Fix silly mistakes in the test. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698