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 "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 sequence()->StartBlock(block->GetRpoNumber()); | 66 sequence()->StartBlock(block->GetRpoNumber()); |
67 while (start-- > end) { | 67 while (start-- > end) { |
68 sequence()->AddInstruction(instructions_[start]); | 68 sequence()->AddInstruction(instructions_[start]); |
69 } | 69 } |
70 sequence()->EndBlock(block->GetRpoNumber()); | 70 sequence()->EndBlock(block->GetRpoNumber()); |
71 } | 71 } |
72 } | 72 } |
73 | 73 |
74 | 74 |
75 Instruction* InstructionSelector::Emit(InstructionCode opcode, | 75 Instruction* InstructionSelector::Emit(InstructionCode opcode, |
76 InstructionOperand* output, | 76 InstructionOperand output, |
77 size_t temp_count, | 77 size_t temp_count, |
78 InstructionOperand** temps) { | 78 InstructionOperand* temps) { |
79 size_t output_count = output == NULL ? 0 : 1; | 79 size_t output_count = output.IsInvalid() ? 0 : 1; |
80 return Emit(opcode, output_count, &output, 0, NULL, temp_count, temps); | 80 return Emit(opcode, output_count, &output, 0, NULL, temp_count, temps); |
81 } | 81 } |
82 | 82 |
83 | 83 |
84 Instruction* InstructionSelector::Emit(InstructionCode opcode, | 84 Instruction* InstructionSelector::Emit(InstructionCode opcode, |
85 InstructionOperand* output, | 85 InstructionOperand output, |
86 InstructionOperand* a, size_t temp_count, | 86 InstructionOperand a, size_t temp_count, |
87 InstructionOperand** temps) { | 87 InstructionOperand* temps) { |
88 size_t output_count = output == NULL ? 0 : 1; | 88 size_t output_count = output.IsInvalid() ? 0 : 1; |
89 return Emit(opcode, output_count, &output, 1, &a, temp_count, temps); | 89 return Emit(opcode, output_count, &output, 1, &a, temp_count, temps); |
90 } | 90 } |
91 | 91 |
92 | 92 |
93 Instruction* InstructionSelector::Emit(InstructionCode opcode, | 93 Instruction* InstructionSelector::Emit(InstructionCode opcode, |
94 InstructionOperand* output, | 94 InstructionOperand output, |
95 InstructionOperand* a, | 95 InstructionOperand a, |
96 InstructionOperand* b, size_t temp_count, | 96 InstructionOperand b, size_t temp_count, |
97 InstructionOperand** temps) { | 97 InstructionOperand* temps) { |
98 size_t output_count = output == NULL ? 0 : 1; | 98 size_t output_count = output.IsInvalid() ? 0 : 1; |
99 InstructionOperand* inputs[] = {a, b}; | 99 InstructionOperand inputs[] = {a, b}; |
100 size_t input_count = arraysize(inputs); | 100 size_t input_count = arraysize(inputs); |
101 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, | 101 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, |
102 temps); | 102 temps); |
103 } | 103 } |
104 | 104 |
105 | 105 |
106 Instruction* InstructionSelector::Emit(InstructionCode opcode, | 106 Instruction* InstructionSelector::Emit(InstructionCode opcode, |
107 InstructionOperand* output, | 107 InstructionOperand output, |
108 InstructionOperand* a, | 108 InstructionOperand a, |
109 InstructionOperand* b, | 109 InstructionOperand b, |
110 InstructionOperand* c, size_t temp_count, | 110 InstructionOperand c, size_t temp_count, |
111 InstructionOperand** temps) { | 111 InstructionOperand* temps) { |
112 size_t output_count = output == NULL ? 0 : 1; | 112 size_t output_count = output.IsInvalid() ? 0 : 1; |
113 InstructionOperand* inputs[] = {a, b, c}; | 113 InstructionOperand inputs[] = {a, b, c}; |
114 size_t input_count = arraysize(inputs); | 114 size_t input_count = arraysize(inputs); |
115 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, | 115 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, |
116 temps); | 116 temps); |
117 } | 117 } |
118 | 118 |
119 | 119 |
120 Instruction* InstructionSelector::Emit( | 120 Instruction* InstructionSelector::Emit( |
121 InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, | 121 InstructionCode opcode, InstructionOperand output, InstructionOperand a, |
122 InstructionOperand* b, InstructionOperand* c, InstructionOperand* d, | 122 InstructionOperand b, InstructionOperand c, InstructionOperand d, |
123 size_t temp_count, InstructionOperand** temps) { | 123 size_t temp_count, InstructionOperand* temps) { |
124 size_t output_count = output == NULL ? 0 : 1; | 124 size_t output_count = output.IsInvalid() ? 0 : 1; |
125 InstructionOperand* inputs[] = {a, b, c, d}; | 125 InstructionOperand inputs[] = {a, b, c, d}; |
126 size_t input_count = arraysize(inputs); | 126 size_t input_count = arraysize(inputs); |
127 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, | 127 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, |
128 temps); | 128 temps); |
129 } | 129 } |
130 | 130 |
131 | 131 |
132 Instruction* InstructionSelector::Emit( | 132 Instruction* InstructionSelector::Emit( |
133 InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, | 133 InstructionCode opcode, InstructionOperand output, InstructionOperand a, |
134 InstructionOperand* b, InstructionOperand* c, InstructionOperand* d, | 134 InstructionOperand b, InstructionOperand c, InstructionOperand d, |
135 InstructionOperand* e, size_t temp_count, InstructionOperand** temps) { | 135 InstructionOperand e, size_t temp_count, InstructionOperand* temps) { |
136 size_t output_count = output == NULL ? 0 : 1; | 136 size_t output_count = output.IsInvalid() ? 0 : 1; |
137 InstructionOperand* inputs[] = {a, b, c, d, e}; | 137 InstructionOperand inputs[] = {a, b, c, d, e}; |
138 size_t input_count = arraysize(inputs); | 138 size_t input_count = arraysize(inputs); |
139 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, | 139 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, |
140 temps); | 140 temps); |
141 } | 141 } |
142 | 142 |
143 | 143 |
144 Instruction* InstructionSelector::Emit( | 144 Instruction* InstructionSelector::Emit( |
145 InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, | 145 InstructionCode opcode, InstructionOperand output, InstructionOperand a, |
146 InstructionOperand* b, InstructionOperand* c, InstructionOperand* d, | 146 InstructionOperand b, InstructionOperand c, InstructionOperand d, |
147 InstructionOperand* e, InstructionOperand* f, size_t temp_count, | 147 InstructionOperand e, InstructionOperand f, size_t temp_count, |
148 InstructionOperand** temps) { | 148 InstructionOperand* temps) { |
149 size_t output_count = output == NULL ? 0 : 1; | 149 size_t output_count = output.IsInvalid() ? 0 : 1; |
150 InstructionOperand* inputs[] = {a, b, c, d, e, f}; | 150 InstructionOperand inputs[] = {a, b, c, d, e, f}; |
151 size_t input_count = arraysize(inputs); | 151 size_t input_count = arraysize(inputs); |
152 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, | 152 return Emit(opcode, output_count, &output, input_count, inputs, temp_count, |
153 temps); | 153 temps); |
154 } | 154 } |
155 | 155 |
156 | 156 |
157 Instruction* InstructionSelector::Emit( | 157 Instruction* InstructionSelector::Emit( |
158 InstructionCode opcode, size_t output_count, InstructionOperand** outputs, | 158 InstructionCode opcode, size_t output_count, InstructionOperand* outputs, |
159 size_t input_count, InstructionOperand** inputs, size_t temp_count, | 159 size_t input_count, InstructionOperand* inputs, size_t temp_count, |
160 InstructionOperand** temps) { | 160 InstructionOperand* temps) { |
161 Instruction* instr = | 161 Instruction* instr = |
162 Instruction::New(instruction_zone(), opcode, output_count, outputs, | 162 Instruction::New(instruction_zone(), opcode, output_count, outputs, |
163 input_count, inputs, temp_count, temps); | 163 input_count, inputs, temp_count, temps); |
164 return Emit(instr); | 164 return Emit(instr); |
165 } | 165 } |
166 | 166 |
167 | 167 |
168 Instruction* InstructionSelector::Emit(Instruction* instr) { | 168 Instruction* InstructionSelector::Emit(Instruction* instr) { |
169 instructions_.push_back(instr); | 169 instructions_.push_back(instr); |
170 return instr; | 170 return instr; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 264 |
265 | 265 |
266 void InstructionSelector::MarkAsReference(Node* node) { | 266 void InstructionSelector::MarkAsReference(Node* node) { |
267 DCHECK_NOT_NULL(node); | 267 DCHECK_NOT_NULL(node); |
268 DCHECK(!IsDouble(node)); | 268 DCHECK(!IsDouble(node)); |
269 sequence()->MarkAsReference(GetVirtualRegister(node)); | 269 sequence()->MarkAsReference(GetVirtualRegister(node)); |
270 } | 270 } |
271 | 271 |
272 | 272 |
273 void InstructionSelector::MarkAsRepresentation(MachineType rep, | 273 void InstructionSelector::MarkAsRepresentation(MachineType rep, |
274 InstructionOperand* op) { | 274 const InstructionOperand& op) { |
275 UnallocatedOperand* unalloc = UnallocatedOperand::cast(op); | 275 UnallocatedOperand unalloc = UnallocatedOperand::cast(op); |
276 switch (RepresentationOf(rep)) { | 276 switch (RepresentationOf(rep)) { |
277 case kRepFloat32: | 277 case kRepFloat32: |
278 case kRepFloat64: | 278 case kRepFloat64: |
279 sequence()->MarkAsDouble(unalloc->virtual_register()); | 279 sequence()->MarkAsDouble(unalloc.virtual_register()); |
280 break; | 280 break; |
281 case kRepTagged: | 281 case kRepTagged: |
282 sequence()->MarkAsReference(unalloc->virtual_register()); | 282 sequence()->MarkAsReference(unalloc.virtual_register()); |
283 break; | 283 break; |
284 default: | 284 default: |
285 break; | 285 break; |
286 } | 286 } |
287 } | 287 } |
288 | 288 |
289 | 289 |
290 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { | 290 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { |
291 DCHECK_NOT_NULL(node); | 291 DCHECK_NOT_NULL(node); |
292 switch (RepresentationOf(rep)) { | 292 switch (RepresentationOf(rep)) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 for (size_t i = 0; i < buffer->output_nodes.size(); i++) { | 356 for (size_t i = 0; i < buffer->output_nodes.size(); i++) { |
357 bool output_is_live = | 357 bool output_is_live = |
358 buffer->output_nodes[i] != NULL || i < outputs_needed_by_framestate; | 358 buffer->output_nodes[i] != NULL || i < outputs_needed_by_framestate; |
359 if (output_is_live) { | 359 if (output_is_live) { |
360 MachineType type = | 360 MachineType type = |
361 buffer->descriptor->GetReturnType(static_cast<int>(i)); | 361 buffer->descriptor->GetReturnType(static_cast<int>(i)); |
362 LinkageLocation location = | 362 LinkageLocation location = |
363 buffer->descriptor->GetReturnLocation(static_cast<int>(i)); | 363 buffer->descriptor->GetReturnLocation(static_cast<int>(i)); |
364 | 364 |
365 Node* output = buffer->output_nodes[i]; | 365 Node* output = buffer->output_nodes[i]; |
366 InstructionOperand* op = | 366 InstructionOperand op = |
367 output == NULL ? g.TempLocation(location, type) | 367 output == NULL ? g.TempLocation(location, type) |
368 : g.DefineAsLocation(output, location, type); | 368 : g.DefineAsLocation(output, location, type); |
369 MarkAsRepresentation(type, op); | 369 MarkAsRepresentation(type, op); |
370 | 370 |
371 buffer->outputs.push_back(op); | 371 buffer->outputs.push_back(op); |
372 } | 372 } |
373 } | 373 } |
374 } | 374 } |
375 | 375 |
376 // The first argument is always the callee code. | 376 // The first argument is always the callee code. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 // Split the arguments into pushed_nodes and instruction_args. Pushed | 420 // Split the arguments into pushed_nodes and instruction_args. Pushed |
421 // arguments require an explicit push instruction before the call and do | 421 // arguments require an explicit push instruction before the call and do |
422 // not appear as arguments to the call. Everything else ends up | 422 // not appear as arguments to the call. Everything else ends up |
423 // as an InstructionOperand argument to the call. | 423 // as an InstructionOperand argument to the call. |
424 auto iter(call->inputs().begin()); | 424 auto iter(call->inputs().begin()); |
425 int pushed_count = 0; | 425 int pushed_count = 0; |
426 for (size_t index = 0; index < input_count; ++iter, ++index) { | 426 for (size_t index = 0; index < input_count; ++iter, ++index) { |
427 DCHECK(iter != call->inputs().end()); | 427 DCHECK(iter != call->inputs().end()); |
428 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); | 428 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); |
429 if (index == 0) continue; // The first argument (callee) is already done. | 429 if (index == 0) continue; // The first argument (callee) is already done. |
430 InstructionOperand* op = | 430 InstructionOperand op = |
431 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index), | 431 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index), |
432 buffer->descriptor->GetInputType(index)); | 432 buffer->descriptor->GetInputType(index)); |
433 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { | 433 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy()) { |
434 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; | 434 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1; |
435 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { | 435 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { |
436 buffer->pushed_nodes.resize(stack_index + 1, NULL); | 436 buffer->pushed_nodes.resize(stack_index + 1, NULL); |
437 } | 437 } |
438 DCHECK(!buffer->pushed_nodes[stack_index]); | 438 DCHECK(!buffer->pushed_nodes[stack_index]); |
439 buffer->pushed_nodes[stack_index] = *iter; | 439 buffer->pushed_nodes[stack_index] = *iter; |
440 pushed_count++; | 440 pushed_count++; |
441 } else { | 441 } else { |
442 buffer->instruction_args.push_back(op); | 442 buffer->instruction_args.push_back(op); |
443 } | 443 } |
444 } | 444 } |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 // We must emit a NOP here because every live range needs a defining | 1027 // We must emit a NOP here because every live range needs a defining |
1028 // instruction in the register allocator. | 1028 // instruction in the register allocator. |
1029 OperandGenerator g(this); | 1029 OperandGenerator g(this); |
1030 Emit(kArchNop, g.DefineAsConstant(node)); | 1030 Emit(kArchNop, g.DefineAsConstant(node)); |
1031 } | 1031 } |
1032 | 1032 |
1033 | 1033 |
1034 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1034 void InstructionSelector::VisitGoto(BasicBlock* target) { |
1035 // jump to the next block. | 1035 // jump to the next block. |
1036 OperandGenerator g(this); | 1036 OperandGenerator g(this); |
1037 Emit(kArchJmp, NULL, g.Label(target))->MarkAsControl(); | 1037 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl(); |
1038 } | 1038 } |
1039 | 1039 |
1040 | 1040 |
1041 void InstructionSelector::VisitReturn(Node* value) { | 1041 void InstructionSelector::VisitReturn(Node* value) { |
1042 OperandGenerator g(this); | 1042 OperandGenerator g(this); |
1043 if (value != NULL) { | 1043 if (value != NULL) { |
1044 Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation(), | 1044 Emit(kArchRet, g.NoOutput(), |
1045 linkage()->GetReturnType())); | 1045 g.UseLocation(value, linkage()->GetReturnLocation(), |
| 1046 linkage()->GetReturnType())); |
1046 } else { | 1047 } else { |
1047 Emit(kArchRet, NULL); | 1048 Emit(kArchRet, g.NoOutput()); |
1048 } | 1049 } |
1049 } | 1050 } |
1050 | 1051 |
1051 | 1052 |
1052 void InstructionSelector::VisitThrow(Node* value) { | 1053 void InstructionSelector::VisitThrow(Node* value) { |
1053 Emit(kArchNop, NULL); // TODO(titzer) | 1054 OperandGenerator g(this); |
| 1055 Emit(kArchNop, g.NoOutput()); // TODO(titzer) |
1054 } | 1056 } |
1055 | 1057 |
1056 | 1058 |
1057 void InstructionSelector::FillTypeVectorFromStateValues( | 1059 void InstructionSelector::FillTypeVectorFromStateValues( |
1058 ZoneVector<MachineType>* types, Node* state_values) { | 1060 ZoneVector<MachineType>* types, Node* state_values) { |
1059 DCHECK(state_values->opcode() == IrOpcode::kStateValues); | 1061 DCHECK(state_values->opcode() == IrOpcode::kStateValues); |
1060 int count = state_values->InputCount(); | 1062 int count = state_values->InputCount(); |
1061 types->reserve(static_cast<size_t>(count)); | 1063 types->reserve(static_cast<size_t>(count)); |
1062 for (int i = 0; i < count; i++) { | 1064 for (int i = 0; i < count; i++) { |
1063 types->push_back(GetMachineType(state_values->InputAt(i))); | 1065 types->push_back(GetMachineType(state_values->InputAt(i))); |
(...skipping 18 matching lines...) Expand all Loading... |
1082 Node* outer_node = state->InputAt(4); | 1084 Node* outer_node = state->InputAt(4); |
1083 if (outer_node->opcode() == IrOpcode::kFrameState) { | 1085 if (outer_node->opcode() == IrOpcode::kFrameState) { |
1084 outer_state = GetFrameStateDescriptor(outer_node); | 1086 outer_state = GetFrameStateDescriptor(outer_node); |
1085 } | 1087 } |
1086 | 1088 |
1087 return new (instruction_zone()) FrameStateDescriptor( | 1089 return new (instruction_zone()) FrameStateDescriptor( |
1088 instruction_zone(), state_info, parameters, locals, stack, outer_state); | 1090 instruction_zone(), state_info, parameters, locals, stack, outer_state); |
1089 } | 1091 } |
1090 | 1092 |
1091 | 1093 |
1092 static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) { | 1094 static InstructionOperand UseOrImmediate(OperandGenerator* g, Node* input) { |
1093 switch (input->opcode()) { | 1095 switch (input->opcode()) { |
1094 case IrOpcode::kInt32Constant: | 1096 case IrOpcode::kInt32Constant: |
1095 case IrOpcode::kNumberConstant: | 1097 case IrOpcode::kNumberConstant: |
1096 case IrOpcode::kFloat64Constant: | 1098 case IrOpcode::kFloat64Constant: |
1097 case IrOpcode::kHeapConstant: | 1099 case IrOpcode::kHeapConstant: |
1098 return g->UseImmediate(input); | 1100 return g->UseImmediate(input); |
1099 default: | 1101 default: |
1100 return g->UseUnique(input); | 1102 return g->UseUnique(input); |
1101 } | 1103 } |
1102 } | 1104 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 MachineOperatorBuilder::Flags | 1176 MachineOperatorBuilder::Flags |
1175 InstructionSelector::SupportedMachineOperatorFlags() { | 1177 InstructionSelector::SupportedMachineOperatorFlags() { |
1176 return MachineOperatorBuilder::Flag::kNoFlags; | 1178 return MachineOperatorBuilder::Flag::kNoFlags; |
1177 } | 1179 } |
1178 | 1180 |
1179 #endif // !V8_TURBOFAN_BACKEND | 1181 #endif // !V8_TURBOFAN_BACKEND |
1180 | 1182 |
1181 } // namespace compiler | 1183 } // namespace compiler |
1182 } // namespace internal | 1184 } // namespace internal |
1183 } // namespace v8 | 1185 } // namespace v8 |
OLD | NEW |