| 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 |