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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
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.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { | 492 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { |
493 VisitRR(this, kMipsFloat64RoundTruncate, node); | 493 VisitRR(this, kMipsFloat64RoundTruncate, node); |
494 } | 494 } |
495 | 495 |
496 | 496 |
497 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { | 497 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { |
498 UNREACHABLE(); | 498 UNREACHABLE(); |
499 } | 499 } |
500 | 500 |
501 | 501 |
502 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler, | 502 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
503 CallMode call_mode) { | |
504 MipsOperandGenerator g(this); | 503 MipsOperandGenerator g(this); |
505 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | 504 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
506 | 505 |
507 FrameStateDescriptor* frame_state_descriptor = NULL; | 506 FrameStateDescriptor* frame_state_descriptor = nullptr; |
508 if (descriptor->NeedsFrameState()) { | 507 if (descriptor->NeedsFrameState()) { |
509 frame_state_descriptor = | 508 frame_state_descriptor = |
510 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 509 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); |
511 } | 510 } |
512 | 511 |
513 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 512 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
514 | 513 |
515 // Compute InstructionOperands for inputs and outputs. | 514 // Compute InstructionOperands for inputs and outputs. |
516 InitializeCallBuffer(node, &buffer, true, false); | 515 InitializeCallBuffer(node, &buffer, true, false); |
517 // Possibly align stack here for functions. | 516 // Possibly align stack here for functions. |
518 int push_count = buffer.pushed_nodes.size(); | 517 int push_count = buffer.pushed_nodes.size(); |
519 if (push_count > 0) { | 518 if (push_count > 0) { |
520 Emit(kMipsStackClaim, g.NoOutput(), | 519 Emit(kMipsStackClaim, g.NoOutput(), |
521 g.TempImmediate(push_count << kPointerSizeLog2)); | 520 g.TempImmediate(push_count << kPointerSizeLog2)); |
522 } | 521 } |
523 int slot = buffer.pushed_nodes.size() - 1; | 522 int slot = buffer.pushed_nodes.size() - 1; |
524 for (Node* node : base::Reversed(buffer.pushed_nodes)) { | 523 for (Node* node : base::Reversed(buffer.pushed_nodes)) { |
525 Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(node), | 524 Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(node), |
526 g.TempImmediate(slot << kPointerSizeLog2)); | 525 g.TempImmediate(slot << kPointerSizeLog2)); |
527 slot--; | 526 slot--; |
528 } | 527 } |
529 | 528 |
530 // Pass label of exception handler block. | 529 // Pass label of exception handler block. |
531 CallDescriptor::Flags flags = descriptor->flags(); | 530 CallDescriptor::Flags flags = descriptor->flags(); |
532 if (handler != nullptr) { | 531 if (handler) { |
533 flags |= CallDescriptor::kHasExceptionHandler; | 532 flags |= CallDescriptor::kHasExceptionHandler; |
534 buffer.instruction_args.push_back(g.Label(handler)); | 533 buffer.instruction_args.push_back(g.Label(handler)); |
535 } | 534 } |
536 | 535 |
537 // Select the appropriate opcode based on the call type. | 536 // Select the appropriate opcode based on the call type. |
538 bool is_tail_call = call_mode == TAIL_CALL; | |
539 InstructionCode opcode; | 537 InstructionCode opcode; |
540 switch (descriptor->kind()) { | 538 switch (descriptor->kind()) { |
541 case CallDescriptor::kCallCodeObject: { | 539 case CallDescriptor::kCallCodeObject: { |
542 opcode = is_tail_call ? kArchTailCallCodeObject : kArchCallCodeObject; | 540 opcode = kArchCallCodeObject; |
543 break; | 541 break; |
544 } | 542 } |
545 case CallDescriptor::kCallJSFunction: | 543 case CallDescriptor::kCallJSFunction: |
546 opcode = is_tail_call ? kArchTailCallJSFunction : kArchCallJSFunction; | 544 opcode = kArchCallJSFunction; |
547 break; | 545 break; |
548 default: | 546 default: |
549 UNREACHABLE(); | 547 UNREACHABLE(); |
550 return; | 548 return; |
551 } | 549 } |
552 opcode |= MiscField::encode(flags); | 550 opcode |= MiscField::encode(flags); |
553 | 551 |
554 // Emit the call instruction. | 552 // Emit the call instruction. |
555 size_t size = is_tail_call ? 0 : buffer.outputs.size(); | 553 size_t const output_count = buffer.outputs.size(); |
556 InstructionOperand* first_output = | 554 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
557 size > 0 ? &buffer.outputs.front() : nullptr; | 555 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
558 Instruction* call_instr = | 556 &buffer.instruction_args.front())->MarkAsCall(); |
559 Emit(opcode, size, first_output, buffer.instruction_args.size(), | |
560 &buffer.instruction_args.front()); | |
561 call_instr->MarkAsCall(); | |
562 } | 557 } |
563 | 558 |
564 | 559 |
| 560 void InstructionSelector::VisitTailCall(Node* node) { |
| 561 MipsOperandGenerator g(this); |
| 562 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
| 563 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 564 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
| 565 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
| 566 |
| 567 // TODO(turbofan): Relax restriction for stack parameters. |
| 568 if (descriptor->UsesOnlyRegisters() && |
| 569 descriptor->HasSameReturnLocationsAs( |
| 570 linkage()->GetIncomingDescriptor())) { |
| 571 CallBuffer buffer(zone(), descriptor, nullptr); |
| 572 |
| 573 // Compute InstructionOperands for inputs and outputs. |
| 574 InitializeCallBuffer(node, &buffer, true, false); |
| 575 |
| 576 DCHECK_EQ(0u, buffer.pushed_nodes.size()); |
| 577 |
| 578 // Select the appropriate opcode based on the call type. |
| 579 InstructionCode opcode; |
| 580 switch (descriptor->kind()) { |
| 581 case CallDescriptor::kCallCodeObject: |
| 582 opcode = kArchTailCallCodeObject; |
| 583 break; |
| 584 case CallDescriptor::kCallJSFunction: |
| 585 opcode = kArchTailCallJSFunction; |
| 586 break; |
| 587 default: |
| 588 UNREACHABLE(); |
| 589 return; |
| 590 } |
| 591 opcode |= MiscField::encode(descriptor->flags()); |
| 592 |
| 593 // Emit the tailcall instruction. |
| 594 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 595 &buffer.instruction_args.front()); |
| 596 } else { |
| 597 FrameStateDescriptor* frame_state_descriptor = |
| 598 descriptor->NeedsFrameState() |
| 599 ? GetFrameStateDescriptor( |
| 600 node->InputAt(static_cast<int>(descriptor->InputCount()))) |
| 601 : nullptr; |
| 602 |
| 603 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 604 |
| 605 // Compute InstructionOperands for inputs and outputs. |
| 606 InitializeCallBuffer(node, &buffer, true, false); |
| 607 // Possibly align stack here for functions. |
| 608 int push_count = buffer.pushed_nodes.size(); |
| 609 if (push_count > 0) { |
| 610 Emit(kMipsStackClaim, g.NoOutput(), |
| 611 g.TempImmediate(push_count << kPointerSizeLog2)); |
| 612 } |
| 613 int slot = buffer.pushed_nodes.size() - 1; |
| 614 for (Node* node : base::Reversed(buffer.pushed_nodes)) { |
| 615 Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(node), |
| 616 g.TempImmediate(slot << kPointerSizeLog2)); |
| 617 slot--; |
| 618 } |
| 619 |
| 620 // Select the appropriate opcode based on the call type. |
| 621 InstructionCode opcode; |
| 622 switch (descriptor->kind()) { |
| 623 case CallDescriptor::kCallCodeObject: { |
| 624 opcode = kArchCallCodeObject; |
| 625 break; |
| 626 } |
| 627 case CallDescriptor::kCallJSFunction: |
| 628 opcode = kArchCallJSFunction; |
| 629 break; |
| 630 default: |
| 631 UNREACHABLE(); |
| 632 return; |
| 633 } |
| 634 opcode |= MiscField::encode(descriptor->flags()); |
| 635 |
| 636 // Emit the call instruction. |
| 637 size_t const output_count = buffer.outputs.size(); |
| 638 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
| 639 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
| 640 &buffer.instruction_args.front())->MarkAsCall(); |
| 641 Emit(kArchRet, 0, nullptr, output_count, outputs); |
| 642 } |
| 643 } |
| 644 |
| 645 |
565 void InstructionSelector::VisitCheckedLoad(Node* node) { | 646 void InstructionSelector::VisitCheckedLoad(Node* node) { |
566 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 647 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
567 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 648 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
568 MipsOperandGenerator g(this); | 649 MipsOperandGenerator g(this); |
569 Node* const buffer = node->InputAt(0); | 650 Node* const buffer = node->InputAt(0); |
570 Node* const offset = node->InputAt(1); | 651 Node* const offset = node->InputAt(1); |
571 Node* const length = node->InputAt(2); | 652 Node* const length = node->InputAt(2); |
572 ArchOpcode opcode; | 653 ArchOpcode opcode; |
573 switch (rep) { | 654 switch (rep) { |
574 case kRepWord8: | 655 case kRepWord8: |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 IsFp64Mode()) { | 1065 IsFp64Mode()) { |
985 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1066 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
986 MachineOperatorBuilder::kFloat64RoundTruncate; | 1067 MachineOperatorBuilder::kFloat64RoundTruncate; |
987 } | 1068 } |
988 return flags; | 1069 return flags; |
989 } | 1070 } |
990 | 1071 |
991 } // namespace compiler | 1072 } // namespace compiler |
992 } // namespace internal | 1073 } // namespace internal |
993 } // namespace v8 | 1074 } // namespace v8 |
OLD | NEW |