| 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-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 buffer->output_nodes.push_back(call); | 291 buffer->output_nodes.push_back(call); |
| 292 } else { | 292 } else { |
| 293 buffer->output_nodes.resize(buffer->descriptor->ReturnCount(), NULL); | 293 buffer->output_nodes.resize(buffer->descriptor->ReturnCount(), NULL); |
| 294 call->CollectProjections(&buffer->output_nodes); | 294 call->CollectProjections(&buffer->output_nodes); |
| 295 } | 295 } |
| 296 | 296 |
| 297 // Filter out the outputs that aren't live because no projection uses them. | 297 // Filter out the outputs that aren't live because no projection uses them. |
| 298 for (size_t i = 0; i < buffer->output_nodes.size(); i++) { | 298 for (size_t i = 0; i < buffer->output_nodes.size(); i++) { |
| 299 if (buffer->output_nodes[i] != NULL) { | 299 if (buffer->output_nodes[i] != NULL) { |
| 300 Node* output = buffer->output_nodes[i]; | 300 Node* output = buffer->output_nodes[i]; |
| 301 MachineType type = |
| 302 buffer->descriptor->GetReturnType(static_cast<int>(i)); |
| 301 LinkageLocation location = | 303 LinkageLocation location = |
| 302 buffer->descriptor->GetReturnLocation(static_cast<int>(i)); | 304 buffer->descriptor->GetReturnLocation(static_cast<int>(i)); |
| 303 MarkAsRepresentation(location.representation(), output); | 305 MarkAsRepresentation(type, output); |
| 304 buffer->outputs.push_back(g.DefineAsLocation(output, location)); | 306 buffer->outputs.push_back(g.DefineAsLocation(output, location, type)); |
| 305 } | 307 } |
| 306 } | 308 } |
| 307 } | 309 } |
| 308 | 310 |
| 309 // The first argument is always the callee code. | 311 // The first argument is always the callee code. |
| 310 Node* callee = call->InputAt(0); | 312 Node* callee = call->InputAt(0); |
| 311 switch (buffer->descriptor->kind()) { | 313 switch (buffer->descriptor->kind()) { |
| 312 case CallDescriptor::kCallCodeObject: | 314 case CallDescriptor::kCallCodeObject: |
| 313 buffer->instruction_args.push_back( | 315 buffer->instruction_args.push_back( |
| 314 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) | 316 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) |
| 315 ? g.UseImmediate(callee) | 317 ? g.UseImmediate(callee) |
| 316 : g.UseRegister(callee)); | 318 : g.UseRegister(callee)); |
| 317 break; | 319 break; |
| 318 case CallDescriptor::kCallAddress: | 320 case CallDescriptor::kCallAddress: |
| 319 buffer->instruction_args.push_back( | 321 buffer->instruction_args.push_back( |
| 320 (call_address_immediate && | 322 (call_address_immediate && |
| 321 (callee->opcode() == IrOpcode::kInt32Constant || | 323 (callee->opcode() == IrOpcode::kInt32Constant || |
| 322 callee->opcode() == IrOpcode::kInt64Constant)) | 324 callee->opcode() == IrOpcode::kInt64Constant)) |
| 323 ? g.UseImmediate(callee) | 325 ? g.UseImmediate(callee) |
| 324 : g.UseRegister(callee)); | 326 : g.UseRegister(callee)); |
| 325 break; | 327 break; |
| 326 case CallDescriptor::kCallJSFunction: | 328 case CallDescriptor::kCallJSFunction: |
| 327 buffer->instruction_args.push_back( | 329 buffer->instruction_args.push_back( |
| 328 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0))); | 330 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0), |
| 331 buffer->descriptor->GetInputType(0))); |
| 329 break; | 332 break; |
| 330 } | 333 } |
| 331 DCHECK_EQ(1, buffer->instruction_args.size()); | 334 DCHECK_EQ(1, buffer->instruction_args.size()); |
| 332 | 335 |
| 333 // If the call needs a frame state, we insert the state information as | 336 // If the call needs a frame state, we insert the state information as |
| 334 // follows (n is the number of value inputs to the frame state): | 337 // follows (n is the number of value inputs to the frame state): |
| 335 // arg 1 : deoptimization id. | 338 // arg 1 : deoptimization id. |
| 336 // arg 2 - arg (n + 1) : value inputs to the frame state. | 339 // arg 2 - arg (n + 1) : value inputs to the frame state. |
| 337 if (buffer->frame_state_descriptor != NULL) { | 340 if (buffer->frame_state_descriptor != NULL) { |
| 338 InstructionSequence::StateId state_id = | 341 InstructionSequence::StateId state_id = |
| 339 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); | 342 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); |
| 340 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); | 343 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); |
| 341 | 344 |
| 342 Node* frame_state = call->InputAt(buffer->descriptor->InputCount()); | 345 Node* frame_state = call->InputAt(buffer->descriptor->InputCount()); |
| 343 AddFrameStateInputs(frame_state, &buffer->instruction_args, | 346 AddFrameStateInputs(frame_state, &buffer->instruction_args, |
| 344 buffer->frame_state_descriptor); | 347 buffer->frame_state_descriptor); |
| 345 } | 348 } |
| 346 DCHECK_EQ(1 + buffer->frame_state_value_count(), | 349 DCHECK(1 + buffer->frame_state_value_count() == |
| 347 buffer->instruction_args.size()); | 350 buffer->instruction_args.size()); |
| 348 | 351 |
| 349 int input_count = buffer->input_count(); | 352 int input_count = buffer->input_count(); |
| 350 | 353 |
| 351 // Split the arguments into pushed_nodes and instruction_args. Pushed | 354 // Split the arguments into pushed_nodes and instruction_args. Pushed |
| 352 // arguments require an explicit push instruction before the call and do | 355 // arguments require an explicit push instruction before the call and do |
| 353 // not appear as arguments to the call. Everything else ends up | 356 // not appear as arguments to the call. Everything else ends up |
| 354 // as an InstructionOperand argument to the call. | 357 // as an InstructionOperand argument to the call. |
| 355 InputIter iter(call->inputs().begin()); | 358 InputIter iter(call->inputs().begin()); |
| 356 int pushed_count = 0; | 359 int pushed_count = 0; |
| 357 for (int index = 0; index < input_count; ++iter, ++index) { | 360 for (int index = 0; index < input_count; ++iter, ++index) { |
| 358 DCHECK(iter != call->inputs().end()); | 361 DCHECK(iter != call->inputs().end()); |
| 359 DCHECK(index == iter.index()); | 362 DCHECK(index == iter.index()); |
| 360 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); | 363 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); |
| 361 if (index == 0) continue; // The first argument (callee) is already done. | 364 if (index == 0) continue; // The first argument (callee) is already done. |
| 362 InstructionOperand* op = | 365 InstructionOperand* op = |
| 363 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index)); | 366 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index), |
| 367 buffer->descriptor->GetInputType(index)); |
| 364 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { | 368 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { |
| 365 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; | 369 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; |
| 366 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { | 370 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { |
| 367 buffer->pushed_nodes.resize(stack_index + 1, NULL); | 371 buffer->pushed_nodes.resize(stack_index + 1, NULL); |
| 368 } | 372 } |
| 369 DCHECK_EQ(NULL, buffer->pushed_nodes[stack_index]); | 373 DCHECK_EQ(NULL, buffer->pushed_nodes[stack_index]); |
| 370 buffer->pushed_nodes[stack_index] = *iter; | 374 buffer->pushed_nodes[stack_index] = *iter; |
| 371 pushed_count++; | 375 pushed_count++; |
| 372 } else { | 376 } else { |
| 373 buffer->instruction_args.push_back(op); | 377 buffer->instruction_args.push_back(op); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 case IrOpcode::kBranch: | 481 case IrOpcode::kBranch: |
| 478 case IrOpcode::kIfTrue: | 482 case IrOpcode::kIfTrue: |
| 479 case IrOpcode::kIfFalse: | 483 case IrOpcode::kIfFalse: |
| 480 case IrOpcode::kEffectPhi: | 484 case IrOpcode::kEffectPhi: |
| 481 case IrOpcode::kMerge: | 485 case IrOpcode::kMerge: |
| 482 // No code needed for these graph artifacts. | 486 // No code needed for these graph artifacts. |
| 483 return; | 487 return; |
| 484 case IrOpcode::kFinish: | 488 case IrOpcode::kFinish: |
| 485 return VisitFinish(node); | 489 return VisitFinish(node); |
| 486 case IrOpcode::kParameter: { | 490 case IrOpcode::kParameter: { |
| 487 LinkageLocation location = | 491 MachineType type = linkage()->GetParameterType(OpParameter<int>(node)); |
| 488 linkage()->GetParameterLocation(OpParameter<int>(node)); | 492 MarkAsRepresentation(type, node); |
| 489 MarkAsRepresentation(location.representation(), node); | |
| 490 return VisitParameter(node); | 493 return VisitParameter(node); |
| 491 } | 494 } |
| 492 case IrOpcode::kPhi: | 495 case IrOpcode::kPhi: |
| 493 return VisitPhi(node); | 496 return VisitPhi(node); |
| 494 case IrOpcode::kProjection: | 497 case IrOpcode::kProjection: |
| 495 return VisitProjection(node); | 498 return VisitProjection(node); |
| 496 case IrOpcode::kInt32Constant: | 499 case IrOpcode::kInt32Constant: |
| 497 case IrOpcode::kInt64Constant: | 500 case IrOpcode::kInt64Constant: |
| 498 case IrOpcode::kExternalConstant: | 501 case IrOpcode::kExternalConstant: |
| 499 return VisitConstant(node); | 502 return VisitConstant(node); |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 | 818 |
| 816 void InstructionSelector::VisitFinish(Node* node) { | 819 void InstructionSelector::VisitFinish(Node* node) { |
| 817 OperandGenerator g(this); | 820 OperandGenerator g(this); |
| 818 Node* value = node->InputAt(0); | 821 Node* value = node->InputAt(0); |
| 819 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); | 822 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); |
| 820 } | 823 } |
| 821 | 824 |
| 822 | 825 |
| 823 void InstructionSelector::VisitParameter(Node* node) { | 826 void InstructionSelector::VisitParameter(Node* node) { |
| 824 OperandGenerator g(this); | 827 OperandGenerator g(this); |
| 825 Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetParameterLocation( | 828 int index = OpParameter<int>(node); |
| 826 OpParameter<int>(node)))); | 829 Emit(kArchNop, |
| 830 g.DefineAsLocation(node, linkage()->GetParameterLocation(index), |
| 831 linkage()->GetParameterType(index))); |
| 827 } | 832 } |
| 828 | 833 |
| 829 | 834 |
| 830 void InstructionSelector::VisitPhi(Node* node) { | 835 void InstructionSelector::VisitPhi(Node* node) { |
| 831 // TODO(bmeurer): Emit a PhiInstruction here. | 836 // TODO(bmeurer): Emit a PhiInstruction here. |
| 832 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { | 837 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { |
| 833 MarkAsUsed(*i); | 838 MarkAsUsed(*i); |
| 834 } | 839 } |
| 835 } | 840 } |
| 836 | 841 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 } | 985 } |
| 981 | 986 |
| 982 // Branch could not be combined with a compare, emit compare against 0. | 987 // Branch could not be combined with a compare, emit compare against 0. |
| 983 VisitWord32Test(value, &cont); | 988 VisitWord32Test(value, &cont); |
| 984 } | 989 } |
| 985 | 990 |
| 986 | 991 |
| 987 void InstructionSelector::VisitReturn(Node* value) { | 992 void InstructionSelector::VisitReturn(Node* value) { |
| 988 OperandGenerator g(this); | 993 OperandGenerator g(this); |
| 989 if (value != NULL) { | 994 if (value != NULL) { |
| 990 Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation())); | 995 Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation(), |
| 996 linkage()->GetReturnType())); |
| 991 } else { | 997 } else { |
| 992 Emit(kArchRet, NULL); | 998 Emit(kArchRet, NULL); |
| 993 } | 999 } |
| 994 } | 1000 } |
| 995 | 1001 |
| 996 | 1002 |
| 997 void InstructionSelector::VisitThrow(Node* value) { | 1003 void InstructionSelector::VisitThrow(Node* value) { |
| 998 UNIMPLEMENTED(); // TODO(titzer) | 1004 UNIMPLEMENTED(); // TODO(titzer) |
| 999 } | 1005 } |
| 1000 | 1006 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 | 1102 |
| 1097 | 1103 |
| 1098 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 1104 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
| 1099 BasicBlock* deoptimization) {} | 1105 BasicBlock* deoptimization) {} |
| 1100 | 1106 |
| 1101 #endif // !V8_TURBOFAN_BACKEND | 1107 #endif // !V8_TURBOFAN_BACKEND |
| 1102 | 1108 |
| 1103 } // namespace compiler | 1109 } // namespace compiler |
| 1104 } // namespace internal | 1110 } // namespace internal |
| 1105 } // namespace v8 | 1111 } // namespace v8 |
| OLD | NEW |