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/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 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 if (descriptor->NeedsFrameState()) { | 827 if (descriptor->NeedsFrameState()) { |
| 828 frame_state_descriptor = | 828 frame_state_descriptor = |
| 829 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 829 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); |
| 830 } | 830 } |
| 831 | 831 |
| 832 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 832 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 833 | 833 |
| 834 // Compute InstructionOperands for inputs and outputs. | 834 // Compute InstructionOperands for inputs and outputs. |
| 835 InitializeCallBuffer(node, &buffer, true, true); | 835 InitializeCallBuffer(node, &buffer, true, true); |
| 836 | 836 |
| 837 InstructionBlock* current_block = sequence()->InstructionBlockAt( | |
| 838 RpoNumber::FromInt(current_block_->rpo_number())); | |
| 839 current_block->mark_needs_frame(); | |
| 840 // TODO(danno): For now, any instruction block that needs a frame forces | |
| 841 // the entire function to have a frame. | |
| 842 sequence()->frame()->MarkNeedsFrame(); | |
| 843 | |
| 837 // Prepare for C function call. | 844 // Prepare for C function call. |
| 838 if (descriptor->IsCFunctionCall()) { | 845 if (descriptor->IsCFunctionCall()) { |
| 839 InstructionOperand temps[] = {g.TempRegister()}; | 846 InstructionOperand temps[] = {g.TempRegister()}; |
| 840 size_t const temp_count = arraysize(temps); | 847 size_t const temp_count = arraysize(temps); |
| 841 Emit(kArchPrepareCallCFunction | | 848 Emit(kArchPrepareCallCFunction | |
| 842 MiscField::encode(static_cast<int>(descriptor->CParameterCount())), | 849 MiscField::encode(static_cast<int>(descriptor->CParameterCount())), |
| 843 0, nullptr, 0, nullptr, temp_count, temps); | 850 0, nullptr, 0, nullptr, temp_count, temps); |
| 844 | 851 |
| 845 // Poke any stack arguments. | 852 // Poke any stack arguments. |
| 846 for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) { | 853 for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 895 } | 902 } |
| 896 | 903 |
| 897 // Emit the call instruction. | 904 // Emit the call instruction. |
| 898 size_t const output_count = buffer.outputs.size(); | 905 size_t const output_count = buffer.outputs.size(); |
| 899 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; | 906 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
| 900 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | 907 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
| 901 &buffer.instruction_args.front())->MarkAsCall(); | 908 &buffer.instruction_args.front())->MarkAsCall(); |
| 902 } | 909 } |
| 903 | 910 |
| 904 | 911 |
| 905 void InstructionSelector::VisitTailCall(Node* node) { | 912 bool InstructionSelector::EmitTailCallSetup(Node* node, CallBuffer* buffer, |
|
Benedikt Meurer
2015/07/30 06:47:24
See my comment in code-generator-ia32.cc.
Can we s
| |
| 913 InstructionCode* opcode) { | |
| 906 IA32OperandGenerator g(this); | 914 IA32OperandGenerator g(this); |
| 907 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); | 915 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
| 908 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 916 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 909 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); | 917 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
| 910 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); | 918 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
| 911 | 919 |
| 912 // TODO(turbofan): Relax restriction for stack parameters. | 920 size_t stack_parameters_in = 0; |
| 913 | 921 size_t preserved_stack_parameters_in = 0; |
| 914 if (linkage()->GetIncomingDescriptor()->CanTailCall(node)) { | 922 size_t stack_parameters_out = 0; |
| 915 CallBuffer buffer(zone(), descriptor, nullptr); | 923 size_t register_parameters_out = 0; |
| 924 if (!linkage()->GetIncomingDescriptor()->CanTailCall( | |
| 925 node, &stack_parameters_in, &preserved_stack_parameters_in, | |
| 926 &stack_parameters_out, ®ister_parameters_out)) { | |
| 927 return false; | |
| 928 } | |
| 916 | 929 |
| 917 // Compute InstructionOperands for inputs and outputs. | 930 // Compute InstructionOperands for inputs and outputs. |
| 918 InitializeCallBuffer(node, &buffer, true, true); | 931 InitializeCallBuffer(node, buffer, true, true); |
| 919 | 932 |
| 920 // Select the appropriate opcode based on the call type. | 933 // Select the appropriate opcode based on the call type. |
| 921 InstructionCode opcode; | 934 switch (descriptor->kind()) { |
| 922 switch (descriptor->kind()) { | 935 case CallDescriptor::kCallCodeObject: |
| 923 case CallDescriptor::kCallCodeObject: | 936 case CallDescriptor::kInterpreterDispatch: |
| 924 case CallDescriptor::kInterpreterDispatch: | 937 *opcode = kArchTailCallCodeObject; |
| 925 opcode = kArchTailCallCodeObject; | 938 break; |
| 926 break; | 939 case CallDescriptor::kCallJSFunction: |
| 927 case CallDescriptor::kCallJSFunction: | 940 *opcode = kArchTailCallJSFunction; |
| 928 opcode = kArchTailCallJSFunction; | 941 break; |
| 929 break; | 942 default: |
| 930 default: | 943 UNREACHABLE(); |
| 931 UNREACHABLE(); | 944 return false; |
| 932 return; | 945 } |
| 946 *opcode |= MiscField::encode(descriptor->flags()); | |
| 947 | |
| 948 DCHECK(Register::kMaxNumAllocatableRegisters > register_parameters_out); | |
| 949 int remaining_registers = | |
| 950 Register::kMaxNumAllocatableRegisters - register_parameters_out; | |
| 951 if (buffer->instruction_args[0].IsImmediate()) { | |
| 952 // If the destination of the call is immediate, then there is actually an | |
| 953 // additional register free. | |
| 954 remaining_registers++; | |
| 955 } | |
| 956 int pushed_parameters = 0; | |
| 957 size_t current = 0; | |
| 958 | |
| 959 bool frame_has_been_deconstructed = false; | |
| 960 | |
| 961 // If we need to overwrite the return address, reserve a register. | |
| 962 if (stack_parameters_out > stack_parameters_in) { | |
| 963 remaining_registers--; | |
| 964 } | |
| 965 | |
| 966 buffer->instruction_args.push_back( | |
| 967 ImmediateOperand(ImmediateOperand::INLINE, kParametersReady)); | |
| 968 | |
| 969 for (Node* node : base::Reversed(buffer->pushed_nodes)) { | |
| 970 if (current == stack_parameters_in) { | |
| 971 DCHECK(remaining_registers > 0); | |
| 972 // Special case for the parameter which will replace the caller's | |
| 973 // return address: load into a register for swapping. | |
| 974 InstructionOperand value = g.UseRegister(node); | |
| 975 buffer->instruction_args.push_back(value); | |
| 976 buffer->instruction_args.push_back( | |
| 977 ImmediateOperand(ImmediateOperand::INLINE, kReplaceReturn)); | |
| 978 } else if (current >= preserved_stack_parameters_in) { | |
| 979 int location = stack_parameters_in - current; | |
| 980 if (remaining_registers > 0) { | |
| 981 buffer->instruction_args.push_back( | |
| 982 ImmediateOperand(ImmediateOperand::INLINE, location)); | |
| 983 InstructionOperand value = | |
| 984 g.CanBeImmediate(node) ? g.UseImmediate(node) : g.UseRegister(node); | |
| 985 buffer->instruction_args.push_back(value); | |
| 986 buffer->instruction_args.push_back( | |
| 987 ImmediateOperand(ImmediateOperand::INLINE, kStore)); | |
| 988 if (!g.CanBeImmediate(node)) { | |
| 989 remaining_registers--; | |
| 990 } | |
| 991 } else { | |
| 992 if (!frame_has_been_deconstructed) { | |
| 993 buffer->instruction_args.push_back( | |
| 994 ImmediateOperand(ImmediateOperand::INLINE, kDeconstructFrame)); | |
| 995 frame_has_been_deconstructed = true; | |
| 996 } | |
| 997 buffer->instruction_args.push_back( | |
| 998 ImmediateOperand(ImmediateOperand::INLINE, location)); | |
| 999 InstructionOperand value = | |
| 1000 g.CanBeImmediate(node) | |
| 1001 ? g.UseImmediate(node) | |
| 1002 : IsSupported(ATOM) ? g.UseRegister(node) : g.Use(node); | |
| 1003 Emit(kIA32Push, g.NoOutput(), value); | |
| 1004 InstructionBlock* current_block = sequence()->InstructionBlockAt( | |
| 1005 RpoNumber::FromInt(current_block_->rpo_number())); | |
| 1006 current_block->mark_needs_frame(); | |
| 1007 // TODO(danno): For now, any instruction block that needs a frame | |
| 1008 // forces the entire function to have a frame. | |
| 1009 sequence()->frame()->MarkNeedsFrame(); | |
| 1010 ++pushed_parameters; | |
| 1011 buffer->instruction_args.push_back( | |
| 1012 ImmediateOperand(ImmediateOperand::INLINE, kPopAndStore)); | |
| 1013 } | |
| 933 } | 1014 } |
| 934 opcode |= MiscField::encode(descriptor->flags()); | 1015 current++; |
| 1016 } | |
| 935 | 1017 |
| 1018 if (!frame_has_been_deconstructed) { | |
| 1019 buffer->instruction_args.push_back( | |
| 1020 ImmediateOperand(ImmediateOperand::INLINE, kDeconstructFrame)); | |
| 1021 } | |
| 1022 | |
| 1023 buffer->instruction_args.push_back( | |
| 1024 ImmediateOperand(ImmediateOperand::INLINE, pushed_parameters)); | |
| 1025 int stack_delta = | |
| 1026 stack_parameters_out - static_cast<int>(stack_parameters_in); | |
| 1027 buffer->instruction_args.push_back( | |
| 1028 ImmediateOperand(ImmediateOperand::INLINE, stack_delta)); | |
| 1029 sequence()->frame()->UpdateMaxTailCallStackDelta(stack_delta); | |
| 1030 | |
| 1031 return true; | |
| 1032 } | |
| 1033 | |
| 1034 | |
| 1035 void InstructionSelector::VisitTailCall(Node* node) { | |
| 1036 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); | |
| 1037 CallBuffer buffer(zone(), descriptor, nullptr); | |
| 1038 InstructionCode opcode; | |
| 1039 if (EmitTailCallSetup(node, &buffer, &opcode)) { | |
| 936 // Emit the tailcall instruction. | 1040 // Emit the tailcall instruction. |
| 937 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | 1041 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 938 &buffer.instruction_args.front()); | 1042 &buffer.instruction_args.front()); |
| 939 } else { | 1043 } else { |
| 1044 IA32OperandGenerator g(this); | |
| 940 FrameStateDescriptor* frame_state_descriptor = | 1045 FrameStateDescriptor* frame_state_descriptor = |
| 941 descriptor->NeedsFrameState() | 1046 descriptor->NeedsFrameState() |
| 942 ? GetFrameStateDescriptor( | 1047 ? GetFrameStateDescriptor( |
| 943 node->InputAt(static_cast<int>(descriptor->InputCount()))) | 1048 node->InputAt(static_cast<int>(descriptor->InputCount()))) |
| 944 : nullptr; | 1049 : nullptr; |
| 945 | 1050 |
| 946 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1051 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 947 | 1052 |
| 948 // Compute InstructionOperands for inputs and outputs. | 1053 // Compute InstructionOperands for inputs and outputs. |
| 949 InitializeCallBuffer(node, &buffer, true, true); | 1054 InitializeCallBuffer(node, &buffer, true, true); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1343 if (CpuFeatures::IsSupported(SSE4_1)) { | 1448 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 1344 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1449 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
| 1345 MachineOperatorBuilder::kFloat64RoundTruncate; | 1450 MachineOperatorBuilder::kFloat64RoundTruncate; |
| 1346 } | 1451 } |
| 1347 return flags; | 1452 return flags; |
| 1348 } | 1453 } |
| 1349 | 1454 |
| 1350 } // namespace compiler | 1455 } // namespace compiler |
| 1351 } // namespace internal | 1456 } // namespace internal |
| 1352 } // namespace v8 | 1457 } // namespace v8 |
| OLD | NEW |