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 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 } |
|
Michael Starzinger
2016/10/28 14:12:14
nit: Indentation of the rest of the function off,
danno
2016/10/31 10:06:39
Done.
| |
| 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()) { | 1908 switch (descriptor->kind()) { |
| 1909 case CallDescriptor::kCallCodeObject: | 1909 case CallDescriptor::kCallCodeObject: |
| 1910 opcode = kArchTailCallCodeObjectFromJSFunction; | 1910 opcode = kArchTailCallCodeObjectFromJSFunction; |
| 1911 break; | 1911 break; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1942 | 1942 |
| 1943 int first_unused_stack_slot = | 1943 int first_unused_stack_slot = |
| 1944 (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0) + | 1944 (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0) + |
| 1945 stack_param_delta; | 1945 stack_param_delta; |
| 1946 buffer.instruction_args.push_back(g.TempImmediate(first_unused_stack_slot)); | 1946 buffer.instruction_args.push_back(g.TempImmediate(first_unused_stack_slot)); |
| 1947 | 1947 |
| 1948 // Emit the tailcall instruction. | 1948 // Emit the tailcall instruction. |
| 1949 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | 1949 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 1950 &buffer.instruction_args.front(), temps.size(), | 1950 &buffer.instruction_args.front(), temps.size(), |
| 1951 temps.empty() ? nullptr : &temps.front()); | 1951 temps.empty() ? nullptr : &temps.front()); |
| 1952 } else { | |
| 1953 FrameStateDescriptor* frame_state_descriptor = | |
| 1954 descriptor->NeedsFrameState() | |
| 1955 ? GetFrameStateDescriptor( | |
| 1956 node->InputAt(static_cast<int>(descriptor->InputCount()))) | |
| 1957 : nullptr; | |
| 1958 | |
| 1959 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | |
| 1960 | |
| 1961 // Compute InstructionOperands for inputs and outputs. | |
| 1962 CallBufferFlags flags = kCallCodeImmediate; | |
| 1963 if (IsTailCallAddressImmediate()) { | |
| 1964 flags |= kCallAddressImmediate; | |
| 1965 } | |
| 1966 InitializeCallBuffer(node, &buffer, flags); | |
| 1967 | |
| 1968 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); | |
| 1969 | |
| 1970 // Select the appropriate opcode based on the call type. | |
| 1971 InstructionCode opcode; | |
| 1972 switch (descriptor->kind()) { | |
| 1973 case CallDescriptor::kCallCodeObject: | |
| 1974 opcode = kArchCallCodeObject; | |
| 1975 break; | |
| 1976 case CallDescriptor::kCallJSFunction: | |
| 1977 opcode = kArchCallJSFunction; | |
| 1978 break; | |
| 1979 default: | |
| 1980 UNREACHABLE(); | |
| 1981 return; | |
| 1982 } | |
| 1983 opcode |= MiscField::encode(descriptor->flags()); | |
| 1984 | |
| 1985 // Emit the call instruction. | |
| 1986 size_t output_count = buffer.outputs.size(); | |
| 1987 auto* outputs = &buffer.outputs.front(); | |
| 1988 Instruction* call_instr = | |
| 1989 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | |
| 1990 &buffer.instruction_args.front()); | |
| 1991 if (instruction_selection_failed()) return; | |
| 1992 call_instr->MarkAsCall(); | |
| 1993 Emit(kArchRet, 0, nullptr, output_count, outputs); | |
| 1994 } | |
| 1995 } | 1952 } |
| 1996 | 1953 |
| 1997 | 1954 |
| 1998 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1955 void InstructionSelector::VisitGoto(BasicBlock* target) { |
| 1999 // jump to the next block. | 1956 // jump to the next block. |
| 2000 OperandGenerator g(this); | 1957 OperandGenerator g(this); |
| 2001 Emit(kArchJmp, g.NoOutput(), g.Label(target)); | 1958 Emit(kArchJmp, g.NoOutput(), g.Label(target)); |
| 2002 } | 1959 } |
| 2003 | 1960 |
| 2004 | |
| 2005 void InstructionSelector::VisitReturn(Node* ret) { | 1961 void InstructionSelector::VisitReturn(Node* ret) { |
| 2006 OperandGenerator g(this); | 1962 OperandGenerator g(this); |
| 2007 if (linkage()->GetIncomingDescriptor()->ReturnCount() == 0) { | 1963 const int ret_count = linkage()->GetIncomingDescriptor()->ReturnCount() == 0 |
|
Michael Starzinger
2016/10/28 14:12:14
nit: s/ret_count/input_count/ because the semantic
danno
2016/10/31 10:06:39
Done.
| |
| 2008 Emit(kArchRet, g.NoOutput()); | 1964 ? 1 |
| 2009 } else { | 1965 : ret->op()->ValueInputCount(); |
| 2010 const int ret_count = ret->op()->ValueInputCount(); | 1966 DCHECK_GE(ret_count, 1); |
| 2011 auto value_locations = zone()->NewArray<InstructionOperand>(ret_count); | 1967 auto value_locations = zone()->NewArray<InstructionOperand>(ret_count); |
| 2012 for (int i = 0; i < ret_count; ++i) { | 1968 Node* pop_count = ret->InputAt(0); |
| 2013 value_locations[i] = | 1969 value_locations[0] = pop_count->opcode() == IrOpcode::kInt32Constant |
|
Michael Starzinger
2016/10/28 14:12:14
nit: Can we use g.CanBeImmediate here?
danno
2016/10/31 10:06:39
Unfortunately, no. IFAICT, CanBeImmediate is platf
Michael Starzinger
2016/10/31 10:23:19
Acknowledged. Nah, I thought it would be "an easy"
| |
| 2014 g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i)); | 1970 ? g.UseImmediate(pop_count) |
| 2015 } | 1971 : g.UseRegister(pop_count); |
| 2016 Emit(kArchRet, 0, nullptr, ret_count, value_locations); | 1972 for (int i = 1; i < ret_count; ++i) { |
| 1973 value_locations[i] = | |
| 1974 g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i - 1)); | |
| 2017 } | 1975 } |
| 1976 Emit(kArchRet, 0, nullptr, ret_count, value_locations); | |
| 2018 } | 1977 } |
| 2019 | 1978 |
| 2020 Instruction* InstructionSelector::EmitDeoptimize( | 1979 Instruction* InstructionSelector::EmitDeoptimize( |
| 2021 InstructionCode opcode, InstructionOperand output, InstructionOperand a, | 1980 InstructionCode opcode, InstructionOperand output, InstructionOperand a, |
| 2022 InstructionOperand b, DeoptimizeReason reason, Node* frame_state) { | 1981 InstructionOperand b, DeoptimizeReason reason, Node* frame_state) { |
| 2023 size_t output_count = output.IsInvalid() ? 0 : 1; | 1982 size_t output_count = output.IsInvalid() ? 0 : 1; |
| 2024 InstructionOperand inputs[] = {a, b}; | 1983 InstructionOperand inputs[] = {a, b}; |
| 2025 size_t input_count = arraysize(inputs); | 1984 size_t input_count = arraysize(inputs); |
| 2026 return EmitDeoptimize(opcode, output_count, &output, input_count, inputs, | 1985 return EmitDeoptimize(opcode, output_count, &output, input_count, inputs, |
| 2027 reason, frame_state); | 1986 reason, frame_state); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2135 return new (instruction_zone()) FrameStateDescriptor( | 2094 return new (instruction_zone()) FrameStateDescriptor( |
| 2136 instruction_zone(), state_info.type(), state_info.bailout_id(), | 2095 instruction_zone(), state_info.type(), state_info.bailout_id(), |
| 2137 state_info.state_combine(), parameters, locals, stack, | 2096 state_info.state_combine(), parameters, locals, stack, |
| 2138 state_info.shared_info(), outer_state); | 2097 state_info.shared_info(), outer_state); |
| 2139 } | 2098 } |
| 2140 | 2099 |
| 2141 | 2100 |
| 2142 } // namespace compiler | 2101 } // namespace compiler |
| 2143 } // namespace internal | 2102 } // namespace internal |
| 2144 } // namespace v8 | 2103 } // namespace v8 |
| OLD | NEW |