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/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { | 808 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { |
809 VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero)); | 809 VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero)); |
810 } | 810 } |
811 | 811 |
812 | 812 |
813 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { | 813 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { |
814 UNREACHABLE(); | 814 UNREACHABLE(); |
815 } | 815 } |
816 | 816 |
817 | 817 |
818 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler, | 818 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
819 CallMode call_mode) { | |
820 IA32OperandGenerator g(this); | 819 IA32OperandGenerator g(this); |
821 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | 820 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
822 | 821 |
823 FrameStateDescriptor* frame_state_descriptor = NULL; | 822 FrameStateDescriptor* frame_state_descriptor = nullptr; |
824 | |
825 if (descriptor->NeedsFrameState()) { | 823 if (descriptor->NeedsFrameState()) { |
826 frame_state_descriptor = | 824 frame_state_descriptor = |
827 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 825 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); |
828 } | 826 } |
829 | 827 |
830 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 828 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
831 | 829 |
832 // Compute InstructionOperands for inputs and outputs. | 830 // Compute InstructionOperands for inputs and outputs. |
833 InitializeCallBuffer(node, &buffer, true, true); | 831 InitializeCallBuffer(node, &buffer, true, true); |
834 | 832 |
835 // Push any stack arguments. | 833 // Push any stack arguments. |
836 for (Node* node : base::Reversed(buffer.pushed_nodes)) { | 834 for (Node* node : base::Reversed(buffer.pushed_nodes)) { |
837 // TODO(titzer): handle pushing double parameters. | 835 // TODO(titzer): handle pushing double parameters. |
838 InstructionOperand value = | 836 InstructionOperand value = |
839 g.CanBeImmediate(node) | 837 g.CanBeImmediate(node) |
840 ? g.UseImmediate(node) | 838 ? g.UseImmediate(node) |
841 : IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node); | 839 : IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node); |
842 Emit(kIA32Push, g.NoOutput(), value); | 840 Emit(kIA32Push, g.NoOutput(), value); |
843 } | 841 } |
844 | 842 |
845 // Pass label of exception handler block. | 843 // Pass label of exception handler block. |
846 CallDescriptor::Flags flags = descriptor->flags(); | 844 CallDescriptor::Flags flags = descriptor->flags(); |
847 if (handler != nullptr) { | 845 if (handler) { |
848 flags |= CallDescriptor::kHasExceptionHandler; | 846 flags |= CallDescriptor::kHasExceptionHandler; |
849 buffer.instruction_args.push_back(g.Label(handler)); | 847 buffer.instruction_args.push_back(g.Label(handler)); |
850 } | 848 } |
851 | 849 |
852 // Select the appropriate opcode based on the call type. | 850 // Select the appropriate opcode based on the call type. |
853 bool is_tail_call = call_mode == TAIL_CALL; | |
854 InstructionCode opcode; | 851 InstructionCode opcode; |
855 switch (descriptor->kind()) { | 852 switch (descriptor->kind()) { |
856 case CallDescriptor::kCallCodeObject: { | 853 case CallDescriptor::kCallCodeObject: { |
857 opcode = is_tail_call ? kArchTailCallCodeObject : kArchCallCodeObject; | 854 opcode = kArchCallCodeObject; |
858 break; | 855 break; |
859 } | 856 } |
860 case CallDescriptor::kCallJSFunction: | 857 case CallDescriptor::kCallJSFunction: |
861 opcode = is_tail_call ? kArchTailCallJSFunction : kArchCallJSFunction; | 858 opcode = kArchCallJSFunction; |
862 break; | 859 break; |
863 default: | 860 default: |
864 UNREACHABLE(); | 861 UNREACHABLE(); |
865 return; | 862 return; |
866 } | 863 } |
867 opcode |= MiscField::encode(flags); | 864 opcode |= MiscField::encode(flags); |
868 | 865 |
869 // Emit the call instruction. | 866 // Emit the call instruction. |
870 size_t size = is_tail_call ? 0 : buffer.outputs.size(); | 867 size_t const output_count = buffer.outputs.size(); |
871 InstructionOperand* first_output = | 868 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
872 size > 0 ? &buffer.outputs.front() : nullptr; | 869 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
873 Instruction* call_instr = | 870 &buffer.instruction_args.front())->MarkAsCall(); |
874 Emit(opcode, size, first_output, buffer.instruction_args.size(), | |
875 &buffer.instruction_args.front()); | |
876 call_instr->MarkAsCall(); | |
877 } | 871 } |
878 | 872 |
879 | 873 |
| 874 void InstructionSelector::VisitTailCall(Node* node) { |
| 875 IA32OperandGenerator g(this); |
| 876 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
| 877 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 878 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
| 879 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
| 880 |
| 881 // TODO(turbofan): Relax restriction for stack parameters. |
| 882 if (descriptor->UsesOnlyRegisters() && |
| 883 descriptor->HasSameReturnLocationsAs( |
| 884 linkage()->GetIncomingDescriptor())) { |
| 885 CallBuffer buffer(zone(), descriptor, nullptr); |
| 886 |
| 887 // Compute InstructionOperands for inputs and outputs. |
| 888 InitializeCallBuffer(node, &buffer, true, true); |
| 889 |
| 890 DCHECK_EQ(0u, buffer.pushed_nodes.size()); |
| 891 |
| 892 // Select the appropriate opcode based on the call type. |
| 893 InstructionCode opcode; |
| 894 switch (descriptor->kind()) { |
| 895 case CallDescriptor::kCallCodeObject: |
| 896 opcode = kArchTailCallCodeObject; |
| 897 break; |
| 898 case CallDescriptor::kCallJSFunction: |
| 899 opcode = kArchTailCallJSFunction; |
| 900 break; |
| 901 default: |
| 902 UNREACHABLE(); |
| 903 return; |
| 904 } |
| 905 opcode |= MiscField::encode(descriptor->flags()); |
| 906 |
| 907 // Emit the tailcall instruction. |
| 908 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 909 &buffer.instruction_args.front()); |
| 910 } else { |
| 911 FrameStateDescriptor* frame_state_descriptor = |
| 912 descriptor->NeedsFrameState() |
| 913 ? GetFrameStateDescriptor( |
| 914 node->InputAt(static_cast<int>(descriptor->InputCount()))) |
| 915 : nullptr; |
| 916 |
| 917 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 918 |
| 919 // Compute InstructionOperands for inputs and outputs. |
| 920 InitializeCallBuffer(node, &buffer, true, true); |
| 921 |
| 922 // Push any stack arguments. |
| 923 for (Node* node : base::Reversed(buffer.pushed_nodes)) { |
| 924 // TODO(titzer): Handle pushing double parameters. |
| 925 InstructionOperand value = |
| 926 g.CanBeImmediate(node) |
| 927 ? g.UseImmediate(node) |
| 928 : IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node); |
| 929 Emit(kIA32Push, g.NoOutput(), value); |
| 930 } |
| 931 |
| 932 // Select the appropriate opcode based on the call type. |
| 933 InstructionCode opcode; |
| 934 switch (descriptor->kind()) { |
| 935 case CallDescriptor::kCallCodeObject: |
| 936 opcode = kArchCallCodeObject; |
| 937 break; |
| 938 case CallDescriptor::kCallJSFunction: |
| 939 opcode = kArchCallJSFunction; |
| 940 break; |
| 941 default: |
| 942 UNREACHABLE(); |
| 943 return; |
| 944 } |
| 945 opcode |= MiscField::encode(descriptor->flags()); |
| 946 |
| 947 // Emit the call instruction. |
| 948 size_t output_count = buffer.outputs.size(); |
| 949 auto* outputs = &buffer.outputs.front(); |
| 950 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
| 951 &buffer.instruction_args.front())->MarkAsCall(); |
| 952 Emit(kArchRet, 0, nullptr, output_count, outputs); |
| 953 } |
| 954 } |
| 955 |
| 956 |
880 namespace { | 957 namespace { |
881 | 958 |
882 // Shared routine for multiple compare operations. | 959 // Shared routine for multiple compare operations. |
883 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 960 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
884 InstructionOperand left, InstructionOperand right, | 961 InstructionOperand left, InstructionOperand right, |
885 FlagsContinuation* cont) { | 962 FlagsContinuation* cont) { |
886 IA32OperandGenerator g(selector); | 963 IA32OperandGenerator g(selector); |
887 if (cont->IsBranch()) { | 964 if (cont->IsBranch()) { |
888 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, | 965 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, |
889 g.Label(cont->true_block()), g.Label(cont->false_block())); | 966 g.Label(cont->true_block()), g.Label(cont->false_block())); |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1239 if (CpuFeatures::IsSupported(SSE4_1)) { | 1316 if (CpuFeatures::IsSupported(SSE4_1)) { |
1240 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1317 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
1241 MachineOperatorBuilder::kFloat64RoundTruncate; | 1318 MachineOperatorBuilder::kFloat64RoundTruncate; |
1242 } | 1319 } |
1243 return flags; | 1320 return flags; |
1244 } | 1321 } |
1245 | 1322 |
1246 } // namespace compiler | 1323 } // namespace compiler |
1247 } // namespace internal | 1324 } // namespace internal |
1248 } // namespace v8 | 1325 } // namespace v8 |
OLD | NEW |