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 |