| 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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 | 244 |
| 245 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { | 245 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { |
| 246 DCHECK_NOT_NULL(node); | 246 DCHECK_NOT_NULL(node); |
| 247 if (RepresentationOf(rep) == kRepFloat64) MarkAsDouble(node); | 247 if (RepresentationOf(rep) == kRepFloat64) MarkAsDouble(node); |
| 248 if (RepresentationOf(rep) == kRepTagged) MarkAsReference(node); | 248 if (RepresentationOf(rep) == kRepTagged) MarkAsReference(node); |
| 249 } | 249 } |
| 250 | 250 |
| 251 | 251 |
| 252 // TODO(bmeurer): Get rid of the CallBuffer business and make | 252 // TODO(bmeurer): Get rid of the CallBuffer business and make |
| 253 // InstructionSelector::VisitCall platform independent instead. | 253 // InstructionSelector::VisitCall platform independent instead. |
| 254 CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d) | 254 CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d, |
| 255 : output_count(0), | 255 FrameStateDescriptor* frame_desc) |
| 256 descriptor(d), | 256 : descriptor(d), |
| 257 output_nodes(zone->NewArray<Node*>(d->ReturnCount())), | 257 frame_state_descriptor(frame_desc), |
| 258 outputs(zone->NewArray<InstructionOperand*>(d->ReturnCount())), | 258 output_nodes(NodeVector::allocator_type(zone)), |
| 259 fixed_and_control_args( | 259 outputs(InstructionOperandVector::allocator_type(zone)), |
| 260 zone->NewArray<InstructionOperand*>(input_count() + control_count())), | 260 instruction_args(InstructionOperandVector::allocator_type(zone)), |
| 261 fixed_count(0), | 261 pushed_nodes(NodeVector::allocator_type(zone)) { |
| 262 pushed_nodes(zone->NewArray<Node*>(input_count())), | 262 output_nodes.reserve(d->ReturnCount()); |
| 263 pushed_count(0) { | 263 outputs.reserve(d->ReturnCount()); |
| 264 if (d->ReturnCount() > 1) { | 264 pushed_nodes.reserve(input_count()); |
| 265 memset(output_nodes, 0, sizeof(Node*) * d->ReturnCount()); // NOLINT | 265 instruction_args.reserve(input_count() + control_count() + |
| 266 } | 266 frame_state_value_count()); |
| 267 memset(pushed_nodes, 0, sizeof(Node*) * input_count()); // NOLINT | |
| 268 } | 267 } |
| 269 | 268 |
| 270 | 269 |
| 271 // TODO(bmeurer): Get rid of the CallBuffer business and make | 270 // TODO(bmeurer): Get rid of the CallBuffer business and make |
| 272 // InstructionSelector::VisitCall platform independent instead. | 271 // InstructionSelector::VisitCall platform independent instead. |
| 273 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, | 272 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, |
| 274 bool call_code_immediate, | 273 bool call_code_immediate, |
| 275 bool call_address_immediate, | 274 bool call_address_immediate, |
| 276 BasicBlock* cont_node, | 275 BasicBlock* cont_node, |
| 277 BasicBlock* deopt_node) { | 276 BasicBlock* deopt_node) { |
| 278 OperandGenerator g(this); | 277 OperandGenerator g(this); |
| 279 DCHECK_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount()); | 278 DCHECK_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount()); |
| 280 DCHECK_EQ(OperatorProperties::GetValueInputCount(call->op()), | 279 DCHECK_EQ(OperatorProperties::GetValueInputCount(call->op()), |
| 281 buffer->input_count()); | 280 buffer->input_count() + buffer->frame_state_count()); |
| 282 | 281 |
| 283 if (buffer->descriptor->ReturnCount() > 0) { | 282 if (buffer->descriptor->ReturnCount() > 0) { |
| 284 // Collect the projections that represent multiple outputs from this call. | 283 // Collect the projections that represent multiple outputs from this call. |
| 285 if (buffer->descriptor->ReturnCount() == 1) { | 284 if (buffer->descriptor->ReturnCount() == 1) { |
| 286 buffer->output_nodes[0] = call; | 285 buffer->output_nodes.push_back(call); |
| 287 } else { | 286 } else { |
| 288 call->CollectProjections(buffer->descriptor->ReturnCount(), | 287 call->CollectProjections(&buffer->output_nodes); |
| 289 buffer->output_nodes); | 288 DCHECK(buffer->output_nodes.size() <= |
| 289 static_cast<size_t>(buffer->descriptor->ReturnCount())); |
| 290 } | 290 } |
| 291 | 291 |
| 292 // Filter out the outputs that aren't live because no projection uses them. | 292 // Filter out the outputs that aren't live because no projection uses them. |
| 293 for (int i = 0; i < buffer->descriptor->ReturnCount(); i++) { | 293 for (size_t i = 0; i < buffer->output_nodes.size(); i++) { |
| 294 if (buffer->output_nodes[i] != NULL) { | 294 if (buffer->output_nodes[i] != NULL) { |
| 295 Node* output = buffer->output_nodes[i]; | 295 Node* output = buffer->output_nodes[i]; |
| 296 LinkageLocation location = buffer->descriptor->GetReturnLocation(i); | 296 LinkageLocation location = |
| 297 buffer->descriptor->GetReturnLocation(static_cast<int>(i)); |
| 297 MarkAsRepresentation(location.representation(), output); | 298 MarkAsRepresentation(location.representation(), output); |
| 298 buffer->outputs[buffer->output_count++] = | 299 buffer->outputs.push_back(g.DefineAsLocation(output, location)); |
| 299 g.DefineAsLocation(output, location); | |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 } | 302 } |
| 303 | 303 |
| 304 buffer->fixed_count = 1; // First argument is always the callee. | 304 // The first argument is always the callee code. |
| 305 Node* callee = call->InputAt(0); | 305 Node* callee = call->InputAt(0); |
| 306 switch (buffer->descriptor->kind()) { | 306 switch (buffer->descriptor->kind()) { |
| 307 case CallDescriptor::kCallCodeObject: | 307 case CallDescriptor::kCallCodeObject: |
| 308 buffer->fixed_and_control_args[0] = | 308 buffer->instruction_args.push_back( |
| 309 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) | 309 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) |
| 310 ? g.UseImmediate(callee) | 310 ? g.UseImmediate(callee) |
| 311 : g.UseRegister(callee); | 311 : g.UseRegister(callee)); |
| 312 break; | 312 break; |
| 313 case CallDescriptor::kCallAddress: | 313 case CallDescriptor::kCallAddress: |
| 314 buffer->fixed_and_control_args[0] = | 314 buffer->instruction_args.push_back( |
| 315 (call_address_immediate && | 315 (call_address_immediate && |
| 316 (callee->opcode() == IrOpcode::kInt32Constant || | 316 (callee->opcode() == IrOpcode::kInt32Constant || |
| 317 callee->opcode() == IrOpcode::kInt64Constant)) | 317 callee->opcode() == IrOpcode::kInt64Constant)) |
| 318 ? g.UseImmediate(callee) | 318 ? g.UseImmediate(callee) |
| 319 : g.UseRegister(callee); | 319 : g.UseRegister(callee)); |
| 320 break; | 320 break; |
| 321 case CallDescriptor::kCallJSFunction: | 321 case CallDescriptor::kCallJSFunction: |
| 322 buffer->fixed_and_control_args[0] = | 322 buffer->instruction_args.push_back( |
| 323 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0)); | 323 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0))); |
| 324 break; | 324 break; |
| 325 } | 325 } |
| 326 DCHECK_EQ(1, buffer->instruction_args.size()); |
| 327 |
| 328 // If the call needs a frame state, we insert the state information as |
| 329 // follows (n is the number of value inputs to the frame state): |
| 330 // arg 1 : deoptimization id. |
| 331 // arg 2 - arg (n + 1) : value inputs to the frame state. |
| 332 if (buffer->frame_state_descriptor != NULL) { |
| 333 int deoptimization_id = |
| 334 sequence()->AddDeoptimizationEntry(buffer->frame_state_descriptor); |
| 335 buffer->instruction_args.push_back(g.TempImmediate(deoptimization_id)); |
| 336 |
| 337 Node* frame_state = call->InputAt(buffer->descriptor->InputCount()); |
| 338 AddFrameStateInputs(frame_state, &buffer->instruction_args, |
| 339 buffer->frame_state_descriptor); |
| 340 } |
| 341 DCHECK_EQ(1 + buffer->frame_state_value_count(), |
| 342 buffer->instruction_args.size()); |
| 326 | 343 |
| 327 int input_count = buffer->input_count(); | 344 int input_count = buffer->input_count(); |
| 328 | 345 |
| 329 // Split the arguments into pushed_nodes and fixed_args. Pushed arguments | 346 // Split the arguments into pushed_nodes and instruction_args. Pushed |
| 330 // require an explicit push instruction before the call and do not appear | 347 // arguments require an explicit push instruction before the call and do |
| 331 // as arguments to the call. Everything else ends up as an InstructionOperand | 348 // not appear as arguments to the call. Everything else ends up |
| 332 // argument to the call. | 349 // as an InstructionOperand argument to the call. |
| 333 InputIter iter(call->inputs().begin()); | 350 InputIter iter(call->inputs().begin()); |
| 351 int pushed_count = 0; |
| 334 for (int index = 0; index < input_count; ++iter, ++index) { | 352 for (int index = 0; index < input_count; ++iter, ++index) { |
| 335 DCHECK(iter != call->inputs().end()); | 353 DCHECK(iter != call->inputs().end()); |
| 336 DCHECK(index == iter.index()); | 354 DCHECK(index == iter.index()); |
| 355 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); |
| 337 if (index == 0) continue; // The first argument (callee) is already done. | 356 if (index == 0) continue; // The first argument (callee) is already done. |
| 338 InstructionOperand* op = | 357 InstructionOperand* op = |
| 339 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index)); | 358 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index)); |
| 340 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { | 359 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { |
| 341 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; | 360 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; |
| 342 DCHECK(buffer->pushed_nodes[stack_index] == NULL); | 361 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { |
| 362 buffer->pushed_nodes.resize(stack_index + 1, NULL); |
| 363 } |
| 364 DCHECK_EQ(NULL, buffer->pushed_nodes[stack_index]); |
| 343 buffer->pushed_nodes[stack_index] = *iter; | 365 buffer->pushed_nodes[stack_index] = *iter; |
| 344 buffer->pushed_count++; | 366 pushed_count++; |
| 345 } else { | 367 } else { |
| 346 buffer->fixed_and_control_args[buffer->fixed_count] = op; | 368 buffer->instruction_args.push_back(op); |
| 347 buffer->fixed_count++; | |
| 348 } | 369 } |
| 349 } | 370 } |
| 371 CHECK_EQ(pushed_count, static_cast<int>(buffer->pushed_nodes.size())); |
| 350 | 372 |
| 351 // If the call can deoptimize, we add the continuation and deoptimization | 373 // If the call can deoptimize, we add the continuation and deoptimization |
| 352 // block labels. | 374 // block labels. |
| 353 if (buffer->descriptor->CanLazilyDeoptimize()) { | 375 if (buffer->descriptor->CanLazilyDeoptimize()) { |
| 354 DCHECK(cont_node != NULL); | 376 DCHECK(cont_node != NULL); |
| 355 DCHECK(deopt_node != NULL); | 377 DCHECK(deopt_node != NULL); |
| 356 buffer->fixed_and_control_args[buffer->fixed_count] = g.Label(cont_node); | 378 buffer->instruction_args.push_back(g.Label(cont_node)); |
| 357 buffer->fixed_and_control_args[buffer->fixed_count + 1] = | 379 buffer->instruction_args.push_back(g.Label(deopt_node)); |
| 358 g.Label(deopt_node); | |
| 359 } else { | 380 } else { |
| 360 DCHECK(cont_node == NULL); | 381 DCHECK(cont_node == NULL); |
| 361 DCHECK(deopt_node == NULL); | 382 DCHECK(deopt_node == NULL); |
| 362 } | 383 } |
| 363 | 384 |
| 364 DCHECK(input_count == (buffer->fixed_count + buffer->pushed_count)); | 385 DCHECK(input_count == |
| 386 (buffer->instruction_args.size() - buffer->control_count() + |
| 387 buffer->pushed_nodes.size() - buffer->frame_state_value_count())); |
| 365 } | 388 } |
| 366 | 389 |
| 367 | 390 |
| 368 void InstructionSelector::VisitBlock(BasicBlock* block) { | 391 void InstructionSelector::VisitBlock(BasicBlock* block) { |
| 369 DCHECK_EQ(NULL, current_block_); | 392 DCHECK_EQ(NULL, current_block_); |
| 370 current_block_ = block; | 393 current_block_ = block; |
| 371 int current_block_end = static_cast<int>(instructions_.size()); | 394 int current_block_end = static_cast<int>(instructions_.size()); |
| 372 | 395 |
| 373 // Generate code for the block control "top down", but schedule the code | 396 // Generate code for the block control "top down", but schedule the code |
| 374 // "bottom up". | 397 // "bottom up". |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 Emit(kArchRet, NULL); | 1010 Emit(kArchRet, NULL); |
| 988 } | 1011 } |
| 989 } | 1012 } |
| 990 | 1013 |
| 991 | 1014 |
| 992 void InstructionSelector::VisitThrow(Node* value) { | 1015 void InstructionSelector::VisitThrow(Node* value) { |
| 993 UNIMPLEMENTED(); // TODO(titzer) | 1016 UNIMPLEMENTED(); // TODO(titzer) |
| 994 } | 1017 } |
| 995 | 1018 |
| 996 | 1019 |
| 1020 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( |
| 1021 Node* state) { |
| 1022 DCHECK(state->op()->opcode() == IrOpcode::kFrameState); |
| 1023 BailoutId ast_id = OpParameter<BailoutId>(state); |
| 1024 Node* parameters = state->InputAt(0); |
| 1025 Node* locals = state->InputAt(1); |
| 1026 Node* stack = state->InputAt(2); |
| 1027 |
| 1028 return new (instruction_zone()) |
| 1029 FrameStateDescriptor(ast_id, OpParameter<int>(parameters), |
| 1030 OpParameter<int>(locals), OpParameter<int>(stack)); |
| 1031 } |
| 1032 |
| 1033 |
| 997 static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) { | 1034 static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) { |
| 998 switch (input->opcode()) { | 1035 switch (input->opcode()) { |
| 999 case IrOpcode::kInt32Constant: | 1036 case IrOpcode::kInt32Constant: |
| 1000 case IrOpcode::kNumberConstant: | 1037 case IrOpcode::kNumberConstant: |
| 1001 case IrOpcode::kFloat64Constant: | 1038 case IrOpcode::kFloat64Constant: |
| 1002 case IrOpcode::kHeapConstant: | 1039 case IrOpcode::kHeapConstant: |
| 1003 return g->UseImmediate(input); | 1040 return g->UseImmediate(input); |
| 1004 default: | 1041 default: |
| 1005 return g->Use(input); | 1042 return g->Use(input); |
| 1006 } | 1043 } |
| 1007 } | 1044 } |
| 1008 | 1045 |
| 1009 | 1046 |
| 1047 void InstructionSelector::AddFrameStateInputs( |
| 1048 Node* state, InstructionOperandVector* inputs, |
| 1049 FrameStateDescriptor* descriptor) { |
| 1050 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); |
| 1051 |
| 1052 Node* parameters = state->InputAt(0); |
| 1053 Node* locals = state->InputAt(1); |
| 1054 Node* stack = state->InputAt(2); |
| 1055 |
| 1056 DCHECK_EQ(descriptor->parameters_count(), parameters->InputCount()); |
| 1057 DCHECK_EQ(descriptor->locals_count(), locals->InputCount()); |
| 1058 DCHECK_EQ(descriptor->stack_count(), stack->InputCount()); |
| 1059 |
| 1060 OperandGenerator g(this); |
| 1061 for (int i = 0; i < descriptor->parameters_count(); i++) { |
| 1062 inputs->push_back(UseOrImmediate(&g, parameters->InputAt(i))); |
| 1063 } |
| 1064 for (int i = 0; i < descriptor->locals_count(); i++) { |
| 1065 inputs->push_back(UseOrImmediate(&g, locals->InputAt(i))); |
| 1066 } |
| 1067 for (int i = 0; i < descriptor->stack_count(); i++) { |
| 1068 inputs->push_back(UseOrImmediate(&g, stack->InputAt(i))); |
| 1069 } |
| 1070 } |
| 1071 |
| 1072 |
| 1010 void InstructionSelector::VisitDeoptimize(Node* deopt) { | 1073 void InstructionSelector::VisitDeoptimize(Node* deopt) { |
| 1011 DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize); | 1074 DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize); |
| 1012 Node* state = deopt->InputAt(0); | 1075 Node* state = deopt->InputAt(0); |
| 1013 DCHECK(state->op()->opcode() == IrOpcode::kFrameState); | 1076 FrameStateDescriptor* descriptor = GetFrameStateDescriptor(state); |
| 1014 BailoutId ast_id = OpParameter<BailoutId>(state); | |
| 1015 | 1077 |
| 1016 // Add the inputs. | 1078 InstructionOperandVector inputs( |
| 1017 Node* parameters = state->InputAt(0); | 1079 (InstructionOperandVector::allocator_type(zone()))); |
| 1018 int parameters_count = OpParameter<int>(parameters); | 1080 inputs.reserve(descriptor->size()); |
| 1019 | 1081 |
| 1020 Node* locals = state->InputAt(1); | 1082 AddFrameStateInputs(state, &inputs, descriptor); |
| 1021 int locals_count = OpParameter<int>(locals); | |
| 1022 | |
| 1023 Node* stack = state->InputAt(2); | |
| 1024 int stack_count = OpParameter<int>(stack); | |
| 1025 | |
| 1026 OperandGenerator g(this); | |
| 1027 std::vector<InstructionOperand*> inputs; | |
| 1028 inputs.reserve(parameters_count + locals_count + stack_count); | |
| 1029 for (int i = 0; i < parameters_count; i++) { | |
| 1030 inputs.push_back(UseOrImmediate(&g, parameters->InputAt(i))); | |
| 1031 } | |
| 1032 for (int i = 0; i < locals_count; i++) { | |
| 1033 inputs.push_back(UseOrImmediate(&g, locals->InputAt(i))); | |
| 1034 } | |
| 1035 for (int i = 0; i < stack_count; i++) { | |
| 1036 inputs.push_back(UseOrImmediate(&g, stack->InputAt(i))); | |
| 1037 } | |
| 1038 | |
| 1039 FrameStateDescriptor* descriptor = new (instruction_zone()) | |
| 1040 FrameStateDescriptor(ast_id, parameters_count, locals_count, stack_count); | |
| 1041 | 1083 |
| 1042 DCHECK_EQ(descriptor->size(), inputs.size()); | 1084 DCHECK_EQ(descriptor->size(), inputs.size()); |
| 1043 | 1085 |
| 1044 int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor); | 1086 int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor); |
| 1045 Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), 0, NULL, | 1087 Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), 0, NULL, |
| 1046 inputs.size(), &inputs.front(), 0, NULL); | 1088 inputs.size(), &inputs.front(), 0, NULL); |
| 1047 } | 1089 } |
| 1048 | 1090 |
| 1049 | 1091 |
| 1050 #if !V8_TURBOFAN_BACKEND | 1092 #if !V8_TURBOFAN_BACKEND |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 | 1127 |
| 1086 | 1128 |
| 1087 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 1129 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
| 1088 BasicBlock* deoptimization) {} | 1130 BasicBlock* deoptimization) {} |
| 1089 | 1131 |
| 1090 #endif // !V8_TURBOFAN_BACKEND | 1132 #endif // !V8_TURBOFAN_BACKEND |
| 1091 | 1133 |
| 1092 } // namespace compiler | 1134 } // namespace compiler |
| 1093 } // namespace internal | 1135 } // namespace internal |
| 1094 } // namespace v8 | 1136 } // namespace v8 |
| OLD | NEW |