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 <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/adapters.h" | 9 #include "src/base/adapters.h" |
10 #include "src/compiler/instruction-selector-impl.h" | 10 #include "src/compiler/instruction-selector-impl.h" |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register()); | 247 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register()); |
248 } | 248 } |
249 | 249 |
250 | 250 |
251 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { | 251 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { |
252 rep = RepresentationOf(rep); | 252 rep = RepresentationOf(rep); |
253 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); | 253 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); |
254 } | 254 } |
255 | 255 |
256 | 256 |
257 namespace { | |
258 | |
259 enum class FrameStateInputKind { kAny, kStackSlot }; | |
260 | |
261 | |
262 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, | |
263 FrameStateInputKind kind) { | |
264 switch (input->opcode()) { | |
265 case IrOpcode::kInt32Constant: | |
266 case IrOpcode::kNumberConstant: | |
267 case IrOpcode::kFloat32Constant: | |
268 case IrOpcode::kFloat64Constant: | |
269 case IrOpcode::kHeapConstant: | |
270 return g->UseImmediate(input); | |
271 default: | |
272 switch (kind) { | |
273 case FrameStateInputKind::kStackSlot: | |
274 return g->UseUniqueSlot(input); | |
275 case FrameStateInputKind::kAny: | |
276 return g->UseAny(input); | |
277 } | |
278 UNREACHABLE(); | |
279 return InstructionOperand(); | |
280 } | |
281 } | |
282 | |
283 | |
284 void AddFrameStateInputs(Node* state, OperandGenerator* g, | |
285 InstructionOperandVector* inputs, | |
286 FrameStateDescriptor* descriptor, | |
287 FrameStateInputKind kind, Zone* zone) { | |
288 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); | |
289 | |
290 if (descriptor->outer_state()) { | |
291 AddFrameStateInputs(state->InputAt(kFrameStateOuterStateInput), g, inputs, | |
292 descriptor->outer_state(), kind, zone); | |
293 } | |
294 | |
295 Node* parameters = state->InputAt(kFrameStateParametersInput); | |
296 Node* locals = state->InputAt(kFrameStateLocalsInput); | |
297 Node* stack = state->InputAt(kFrameStateStackInput); | |
298 Node* context = state->InputAt(kFrameStateContextInput); | |
299 Node* function = state->InputAt(kFrameStateFunctionInput); | |
300 | |
301 DCHECK_EQ(descriptor->parameters_count(), | |
302 StateValuesAccess(parameters).size()); | |
303 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); | |
304 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); | |
305 | |
306 ZoneVector<MachineType> types(zone); | |
307 types.reserve(descriptor->GetSize()); | |
308 | |
309 size_t value_index = 0; | |
310 inputs->push_back(OperandForDeopt(g, function, kind)); | |
311 descriptor->SetType(value_index++, kMachAnyTagged); | |
312 for (StateValuesAccess::TypedNode input_node : | |
313 StateValuesAccess(parameters)) { | |
314 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); | |
315 descriptor->SetType(value_index++, input_node.type); | |
316 } | |
317 if (descriptor->HasContext()) { | |
318 inputs->push_back(OperandForDeopt(g, context, kind)); | |
319 descriptor->SetType(value_index++, kMachAnyTagged); | |
320 } | |
321 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { | |
322 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); | |
323 descriptor->SetType(value_index++, input_node.type); | |
324 } | |
325 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { | |
326 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); | |
327 descriptor->SetType(value_index++, input_node.type); | |
328 } | |
329 DCHECK(value_index == descriptor->GetSize()); | |
330 } | |
331 | |
332 } // namespace | |
333 | |
334 | |
335 // An internal helper class for generating the operands to calls. | 257 // An internal helper class for generating the operands to calls. |
336 // TODO(bmeurer): Get rid of the CallBuffer business and make | 258 // TODO(bmeurer): Get rid of the CallBuffer business and make |
337 // InstructionSelector::VisitCall platform independent instead. | 259 // InstructionSelector::VisitCall platform independent instead. |
338 struct CallBuffer { | 260 struct CallBuffer { |
339 CallBuffer(Zone* zone, const CallDescriptor* descriptor, | 261 CallBuffer(Zone* zone, const CallDescriptor* descriptor, |
340 FrameStateDescriptor* frame_state) | 262 FrameStateDescriptor* frame_state) |
341 : descriptor(descriptor), | 263 : descriptor(descriptor), |
342 frame_state_descriptor(frame_state), | 264 frame_state_descriptor(frame_state), |
343 output_nodes(zone), | 265 output_nodes(zone), |
344 outputs(zone), | 266 outputs(zone), |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 // The target is ignored, but we still need to pass a value here. | 373 // The target is ignored, but we still need to pass a value here. |
452 buffer->instruction_args.push_back(g.UseImmediate(callee)); | 374 buffer->instruction_args.push_back(g.UseImmediate(callee)); |
453 break; | 375 break; |
454 } | 376 } |
455 DCHECK_EQ(1u, buffer->instruction_args.size()); | 377 DCHECK_EQ(1u, buffer->instruction_args.size()); |
456 | 378 |
457 // If the call needs a frame state, we insert the state information as | 379 // If the call needs a frame state, we insert the state information as |
458 // follows (n is the number of value inputs to the frame state): | 380 // follows (n is the number of value inputs to the frame state): |
459 // arg 1 : deoptimization id. | 381 // arg 1 : deoptimization id. |
460 // arg 2 - arg (n + 1) : value inputs to the frame state. | 382 // arg 2 - arg (n + 1) : value inputs to the frame state. |
383 size_t frame_state_entries = 0; | |
461 if (buffer->frame_state_descriptor != NULL) { | 384 if (buffer->frame_state_descriptor != NULL) { |
462 InstructionSequence::StateId state_id = | 385 InstructionSequence::StateId state_id = |
463 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); | 386 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); |
464 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); | 387 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); |
465 | 388 |
466 Node* frame_state = | 389 Node* frame_state = |
467 call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); | 390 call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); |
468 AddFrameStateInputs(frame_state, &g, &buffer->instruction_args, | 391 |
469 buffer->frame_state_descriptor, | 392 StateObjectCache cache(instruction_zone()); |
470 FrameStateInputKind::kStackSlot, instruction_zone()); | 393 |
394 frame_state_entries = | |
395 1 + | |
396 buffer->frame_state_descriptor->AddInputs( | |
397 frame_state, &g, &cache, &buffer->instruction_args, | |
398 FrameStateInputKind::kStackSlot, instruction_zone()); | |
399 | |
400 DCHECK_EQ(1 + frame_state_entries, buffer->instruction_args.size()); | |
471 } | 401 } |
472 DCHECK(1 + buffer->frame_state_value_count() == | |
473 buffer->instruction_args.size()); | |
474 | 402 |
475 size_t input_count = static_cast<size_t>(buffer->input_count()); | 403 size_t input_count = static_cast<size_t>(buffer->input_count()); |
476 | 404 |
477 // Split the arguments into pushed_nodes and instruction_args. Pushed | 405 // Split the arguments into pushed_nodes and instruction_args. Pushed |
478 // arguments require an explicit push instruction before the call and do | 406 // arguments require an explicit push instruction before the call and do |
479 // not appear as arguments to the call. Everything else ends up | 407 // not appear as arguments to the call. Everything else ends up |
480 // as an InstructionOperand argument to the call. | 408 // as an InstructionOperand argument to the call. |
481 auto iter(call->inputs().begin()); | 409 auto iter(call->inputs().begin()); |
482 size_t pushed_count = 0; | 410 size_t pushed_count = 0; |
483 bool call_tail = (flags & kCallTail) != 0; | 411 bool call_tail = (flags & kCallTail) != 0; |
(...skipping 15 matching lines...) Expand all Loading... | |
499 buffer->pushed_nodes.resize(stack_index + 1, NULL); | 427 buffer->pushed_nodes.resize(stack_index + 1, NULL); |
500 } | 428 } |
501 DCHECK(!buffer->pushed_nodes[stack_index]); | 429 DCHECK(!buffer->pushed_nodes[stack_index]); |
502 buffer->pushed_nodes[stack_index] = *iter; | 430 buffer->pushed_nodes[stack_index] = *iter; |
503 pushed_count++; | 431 pushed_count++; |
504 } else { | 432 } else { |
505 buffer->instruction_args.push_back(op); | 433 buffer->instruction_args.push_back(op); |
506 } | 434 } |
507 } | 435 } |
508 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count - | 436 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count - |
509 buffer->frame_state_value_count()); | 437 frame_state_entries); |
Jarin
2015/12/02 12:24:34
Hmm, does not the compiler complain that frame_sta
sigurds
2015/12/02 16:35:13
Done.
| |
510 if (call_tail && stack_param_delta != 0) { | 438 if (call_tail && stack_param_delta != 0) { |
511 // For tail calls that change the size of their parameter list, move the | 439 // For tail calls that change the size of their parameter list, move the |
512 // saved caller return address, parent frame pointer and parent constant | 440 // saved caller return address, parent frame pointer and parent constant |
513 // pool pointer to just above the parameters. | 441 // pool pointer to just above the parameters. |
514 | 442 |
515 // Return address | 443 // Return address |
516 LinkageLocation saved_return_location = | 444 LinkageLocation saved_return_location = |
517 LinkageLocation::ForSavedCallerReturnAddress(); | 445 LinkageLocation::ForSavedCallerReturnAddress(); |
518 InstructionOperand return_address = | 446 InstructionOperand return_address = |
519 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation( | 447 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation( |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 return MarkAsReference(node), VisitConstant(node); | 654 return MarkAsReference(node), VisitConstant(node); |
727 case IrOpcode::kNumberConstant: { | 655 case IrOpcode::kNumberConstant: { |
728 double value = OpParameter<double>(node); | 656 double value = OpParameter<double>(node); |
729 if (!IsSmiDouble(value)) MarkAsReference(node); | 657 if (!IsSmiDouble(value)) MarkAsReference(node); |
730 return VisitConstant(node); | 658 return VisitConstant(node); |
731 } | 659 } |
732 case IrOpcode::kCall: | 660 case IrOpcode::kCall: |
733 return VisitCall(node); | 661 return VisitCall(node); |
734 case IrOpcode::kFrameState: | 662 case IrOpcode::kFrameState: |
735 case IrOpcode::kStateValues: | 663 case IrOpcode::kStateValues: |
664 case IrOpcode::kObjectState: | |
736 return; | 665 return; |
737 case IrOpcode::kLoad: { | 666 case IrOpcode::kLoad: { |
738 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); | 667 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); |
739 MarkAsRepresentation(rep, node); | 668 MarkAsRepresentation(rep, node); |
740 return VisitLoad(node); | 669 return VisitLoad(node); |
741 } | 670 } |
742 case IrOpcode::kStore: | 671 case IrOpcode::kStore: |
743 return VisitStore(node); | 672 return VisitStore(node); |
744 case IrOpcode::kWord32And: | 673 case IrOpcode::kWord32And: |
745 return MarkAsWord32(node), VisitWord32And(node); | 674 return MarkAsWord32(node), VisitWord32And(node); |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1414 } | 1343 } |
1415 Emit(kArchRet, 0, nullptr, ret_count, value_locations); | 1344 Emit(kArchRet, 0, nullptr, ret_count, value_locations); |
1416 } | 1345 } |
1417 } | 1346 } |
1418 | 1347 |
1419 | 1348 |
1420 void InstructionSelector::VisitDeoptimize(Node* value) { | 1349 void InstructionSelector::VisitDeoptimize(Node* value) { |
1421 OperandGenerator g(this); | 1350 OperandGenerator g(this); |
1422 | 1351 |
1423 FrameStateDescriptor* desc = GetFrameStateDescriptor(value); | 1352 FrameStateDescriptor* desc = GetFrameStateDescriptor(value); |
1424 size_t arg_count = desc->GetTotalSize() + 1; // Include deopt id. | |
1425 | 1353 |
1426 InstructionOperandVector args(instruction_zone()); | 1354 InstructionOperandVector args(instruction_zone()); |
1427 args.reserve(arg_count); | 1355 args.reserve(desc->GetTotalSize() + 1); // Include deopt id. |
1428 | 1356 |
1429 InstructionSequence::StateId state_id = | 1357 InstructionSequence::StateId state_id = |
1430 sequence()->AddFrameStateDescriptor(desc); | 1358 sequence()->AddFrameStateDescriptor(desc); |
1431 args.push_back(g.TempImmediate(state_id.ToInt())); | 1359 args.push_back(g.TempImmediate(state_id.ToInt())); |
1432 | 1360 |
1433 AddFrameStateInputs(value, &g, &args, desc, FrameStateInputKind::kAny, | 1361 StateObjectCache cache(instruction_zone()); |
1434 instruction_zone()); | |
1435 | 1362 |
1436 DCHECK_EQ(args.size(), arg_count); | 1363 desc->AddInputs(value, &g, &cache, &args, FrameStateInputKind::kAny, |
1364 instruction_zone()); | |
1437 | 1365 |
1438 Emit(kArchDeoptimize, 0, nullptr, arg_count, &args.front(), 0, nullptr); | 1366 Emit(kArchDeoptimize, 0, nullptr, args.size(), &args.front(), 0, nullptr); |
1439 } | 1367 } |
1440 | 1368 |
1441 | 1369 |
1442 void InstructionSelector::VisitThrow(Node* value) { | 1370 void InstructionSelector::VisitThrow(Node* value) { |
1443 OperandGenerator g(this); | 1371 OperandGenerator g(this); |
1444 Emit(kArchNop, g.NoOutput()); // TODO(titzer) | 1372 Emit(kArchNop, g.NoOutput()); // TODO(titzer) |
1445 } | 1373 } |
1446 | 1374 |
1447 | 1375 |
1448 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( | 1376 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( |
(...skipping 21 matching lines...) Expand all Loading... | |
1470 return new (instruction_zone()) FrameStateDescriptor( | 1398 return new (instruction_zone()) FrameStateDescriptor( |
1471 instruction_zone(), state_info.type(), state_info.bailout_id(), | 1399 instruction_zone(), state_info.type(), state_info.bailout_id(), |
1472 state_info.state_combine(), parameters, locals, stack, | 1400 state_info.state_combine(), parameters, locals, stack, |
1473 state_info.shared_info(), outer_state); | 1401 state_info.shared_info(), outer_state); |
1474 } | 1402 } |
1475 | 1403 |
1476 | 1404 |
1477 } // namespace compiler | 1405 } // namespace compiler |
1478 } // namespace internal | 1406 } // namespace internal |
1479 } // namespace v8 | 1407 } // namespace v8 |
OLD | NEW |