Chromium Code Reviews| 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 |