| 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 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1882 call_instr->MarkAsCall(); | 1882 call_instr->MarkAsCall(); |
| 1883 } | 1883 } |
| 1884 | 1884 |
| 1885 | 1885 |
| 1886 void InstructionSelector::VisitTailCall(Node* node) { | 1886 void InstructionSelector::VisitTailCall(Node* node) { |
| 1887 OperandGenerator g(this); | 1887 OperandGenerator g(this); |
| 1888 CallDescriptor const* descriptor = CallDescriptorOf(node->op()); | 1888 CallDescriptor const* descriptor = CallDescriptorOf(node->op()); |
| 1889 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 1889 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 1890 | 1890 |
| 1891 CallDescriptor* caller = linkage()->GetIncomingDescriptor(); | 1891 CallDescriptor* caller = linkage()->GetIncomingDescriptor(); |
| 1892 if (caller->CanTailCall(node)) { | 1892 DCHECK(caller->CanTailCall(node)); |
| 1893 const CallDescriptor* callee = CallDescriptorOf(node->op()); | 1893 const CallDescriptor* callee = CallDescriptorOf(node->op()); |
| 1894 int stack_param_delta = callee->GetStackParameterDelta(caller); | 1894 int stack_param_delta = callee->GetStackParameterDelta(caller); |
| 1895 CallBuffer buffer(zone(), descriptor, nullptr); | 1895 CallBuffer buffer(zone(), descriptor, nullptr); |
| 1896 | 1896 |
| 1897 // Compute InstructionOperands for inputs and outputs. | 1897 // Compute InstructionOperands for inputs and outputs. |
| 1898 CallBufferFlags flags(kCallCodeImmediate | kCallTail); | 1898 CallBufferFlags flags(kCallCodeImmediate | kCallTail); |
| 1899 if (IsTailCallAddressImmediate()) { | 1899 if (IsTailCallAddressImmediate()) { |
| 1900 flags |= kCallAddressImmediate; | 1900 flags |= kCallAddressImmediate; |
| 1901 } | 1901 } |
| 1902 InitializeCallBuffer(node, &buffer, flags, stack_param_delta); | 1902 InitializeCallBuffer(node, &buffer, flags, stack_param_delta); |
| 1903 | 1903 |
| 1904 // Select the appropriate opcode based on the call type. | 1904 // Select the appropriate opcode based on the call type. |
| 1905 InstructionCode opcode; | 1905 InstructionCode opcode; |
| 1906 InstructionOperandVector temps(zone()); | 1906 InstructionOperandVector temps(zone()); |
| 1907 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { | 1907 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { |
| 1908 switch (descriptor->kind()) { | |
| 1909 case CallDescriptor::kCallCodeObject: | |
| 1910 opcode = kArchTailCallCodeObjectFromJSFunction; | |
| 1911 break; | |
| 1912 case CallDescriptor::kCallJSFunction: | |
| 1913 opcode = kArchTailCallJSFunctionFromJSFunction; | |
| 1914 break; | |
| 1915 default: | |
| 1916 UNREACHABLE(); | |
| 1917 return; | |
| 1918 } | |
| 1919 int temps_count = GetTempsCountForTailCallFromJSFunction(); | |
| 1920 for (int i = 0; i < temps_count; i++) { | |
| 1921 temps.push_back(g.TempRegister()); | |
| 1922 } | |
| 1923 } else { | |
| 1924 switch (descriptor->kind()) { | |
| 1925 case CallDescriptor::kCallCodeObject: | |
| 1926 opcode = kArchTailCallCodeObject; | |
| 1927 break; | |
| 1928 case CallDescriptor::kCallAddress: | |
| 1929 opcode = kArchTailCallAddress; | |
| 1930 break; | |
| 1931 default: | |
| 1932 UNREACHABLE(); | |
| 1933 return; | |
| 1934 } | |
| 1935 } | |
| 1936 opcode |= MiscField::encode(descriptor->flags()); | |
| 1937 | |
| 1938 Emit(kArchPrepareTailCall, g.NoOutput()); | |
| 1939 | |
| 1940 int first_unused_stack_slot = | |
| 1941 (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0) + | |
| 1942 stack_param_delta; | |
| 1943 buffer.instruction_args.push_back(g.TempImmediate(first_unused_stack_slot)); | |
| 1944 | |
| 1945 // Emit the tailcall instruction. | |
| 1946 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | |
| 1947 &buffer.instruction_args.front(), temps.size(), | |
| 1948 temps.empty() ? nullptr : &temps.front()); | |
| 1949 } else { | |
| 1950 FrameStateDescriptor* frame_state_descriptor = | |
| 1951 descriptor->NeedsFrameState() | |
| 1952 ? GetFrameStateDescriptor( | |
| 1953 node->InputAt(static_cast<int>(descriptor->InputCount()))) | |
| 1954 : nullptr; | |
| 1955 | |
| 1956 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | |
| 1957 | |
| 1958 // Compute InstructionOperands for inputs and outputs. | |
| 1959 CallBufferFlags flags = kCallCodeImmediate; | |
| 1960 if (IsTailCallAddressImmediate()) { | |
| 1961 flags |= kCallAddressImmediate; | |
| 1962 } | |
| 1963 InitializeCallBuffer(node, &buffer, flags); | |
| 1964 | |
| 1965 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); | |
| 1966 | |
| 1967 // Select the appropriate opcode based on the call type. | |
| 1968 InstructionCode opcode; | |
| 1969 switch (descriptor->kind()) { | 1908 switch (descriptor->kind()) { |
| 1970 case CallDescriptor::kCallCodeObject: | 1909 case CallDescriptor::kCallCodeObject: |
| 1971 opcode = kArchCallCodeObject; | 1910 opcode = kArchTailCallCodeObjectFromJSFunction; |
| 1972 break; | 1911 break; |
| 1973 case CallDescriptor::kCallJSFunction: | 1912 case CallDescriptor::kCallJSFunction: |
| 1974 opcode = kArchCallJSFunction; | 1913 opcode = kArchTailCallJSFunctionFromJSFunction; |
| 1975 break; | 1914 break; |
| 1976 default: | 1915 default: |
| 1977 UNREACHABLE(); | 1916 UNREACHABLE(); |
| 1978 return; | 1917 return; |
| 1979 } | 1918 } |
| 1980 opcode |= MiscField::encode(descriptor->flags()); | 1919 int temps_count = GetTempsCountForTailCallFromJSFunction(); |
| 1920 for (int i = 0; i < temps_count; i++) { |
| 1921 temps.push_back(g.TempRegister()); |
| 1922 } |
| 1923 } else { |
| 1924 switch (descriptor->kind()) { |
| 1925 case CallDescriptor::kCallCodeObject: |
| 1926 opcode = kArchTailCallCodeObject; |
| 1927 break; |
| 1928 case CallDescriptor::kCallAddress: |
| 1929 opcode = kArchTailCallAddress; |
| 1930 break; |
| 1931 default: |
| 1932 UNREACHABLE(); |
| 1933 return; |
| 1934 } |
| 1935 } |
| 1936 opcode |= MiscField::encode(descriptor->flags()); |
| 1981 | 1937 |
| 1982 // Emit the call instruction. | 1938 Emit(kArchPrepareTailCall, g.NoOutput()); |
| 1983 size_t output_count = buffer.outputs.size(); | 1939 |
| 1984 auto* outputs = &buffer.outputs.front(); | 1940 int first_unused_stack_slot = |
| 1985 Instruction* call_instr = | 1941 (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0) + |
| 1986 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | 1942 stack_param_delta; |
| 1987 &buffer.instruction_args.front()); | 1943 buffer.instruction_args.push_back(g.TempImmediate(first_unused_stack_slot)); |
| 1988 if (instruction_selection_failed()) return; | 1944 |
| 1989 call_instr->MarkAsCall(); | 1945 // Emit the tailcall instruction. |
| 1990 Emit(kArchRet, 0, nullptr, output_count, outputs); | 1946 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 1991 } | 1947 &buffer.instruction_args.front(), temps.size(), |
| 1948 temps.empty() ? nullptr : &temps.front()); |
| 1992 } | 1949 } |
| 1993 | 1950 |
| 1994 | 1951 |
| 1995 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1952 void InstructionSelector::VisitGoto(BasicBlock* target) { |
| 1996 // jump to the next block. | 1953 // jump to the next block. |
| 1997 OperandGenerator g(this); | 1954 OperandGenerator g(this); |
| 1998 Emit(kArchJmp, g.NoOutput(), g.Label(target)); | 1955 Emit(kArchJmp, g.NoOutput(), g.Label(target)); |
| 1999 } | 1956 } |
| 2000 | 1957 |
| 2001 | |
| 2002 void InstructionSelector::VisitReturn(Node* ret) { | 1958 void InstructionSelector::VisitReturn(Node* ret) { |
| 2003 OperandGenerator g(this); | 1959 OperandGenerator g(this); |
| 2004 if (linkage()->GetIncomingDescriptor()->ReturnCount() == 0) { | 1960 const int input_count = linkage()->GetIncomingDescriptor()->ReturnCount() == 0 |
| 2005 Emit(kArchRet, g.NoOutput()); | 1961 ? 1 |
| 2006 } else { | 1962 : ret->op()->ValueInputCount(); |
| 2007 const int ret_count = ret->op()->ValueInputCount(); | 1963 DCHECK_GE(input_count, 1); |
| 2008 auto value_locations = zone()->NewArray<InstructionOperand>(ret_count); | 1964 auto value_locations = zone()->NewArray<InstructionOperand>(input_count); |
| 2009 for (int i = 0; i < ret_count; ++i) { | 1965 Node* pop_count = ret->InputAt(0); |
| 2010 value_locations[i] = | 1966 value_locations[0] = pop_count->opcode() == IrOpcode::kInt32Constant |
| 2011 g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i)); | 1967 ? g.UseImmediate(pop_count) |
| 2012 } | 1968 : g.UseRegister(pop_count); |
| 2013 Emit(kArchRet, 0, nullptr, ret_count, value_locations); | 1969 for (int i = 1; i < input_count; ++i) { |
| 1970 value_locations[i] = |
| 1971 g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i - 1)); |
| 2014 } | 1972 } |
| 1973 Emit(kArchRet, 0, nullptr, input_count, value_locations); |
| 2015 } | 1974 } |
| 2016 | 1975 |
| 2017 Instruction* InstructionSelector::EmitDeoptimize(InstructionCode opcode, | 1976 Instruction* InstructionSelector::EmitDeoptimize(InstructionCode opcode, |
| 2018 InstructionOperand output, | 1977 InstructionOperand output, |
| 2019 InstructionOperand a, | 1978 InstructionOperand a, |
| 2020 DeoptimizeReason reason, | 1979 DeoptimizeReason reason, |
| 2021 Node* frame_state) { | 1980 Node* frame_state) { |
| 2022 size_t output_count = output.IsInvalid() ? 0 : 1; | 1981 size_t output_count = output.IsInvalid() ? 0 : 1; |
| 2023 InstructionOperand inputs[] = {a}; | 1982 InstructionOperand inputs[] = {a}; |
| 2024 size_t input_count = arraysize(inputs); | 1983 size_t input_count = arraysize(inputs); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2144 return new (instruction_zone()) FrameStateDescriptor( | 2103 return new (instruction_zone()) FrameStateDescriptor( |
| 2145 instruction_zone(), state_info.type(), state_info.bailout_id(), | 2104 instruction_zone(), state_info.type(), state_info.bailout_id(), |
| 2146 state_info.state_combine(), parameters, locals, stack, | 2105 state_info.state_combine(), parameters, locals, stack, |
| 2147 state_info.shared_info(), outer_state); | 2106 state_info.shared_info(), outer_state); |
| 2148 } | 2107 } |
| 2149 | 2108 |
| 2150 | 2109 |
| 2151 } // namespace compiler | 2110 } // namespace compiler |
| 2152 } // namespace internal | 2111 } // namespace internal |
| 2153 } // namespace v8 | 2112 } // namespace v8 |
| OLD | NEW |