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/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 #include "src/compiler.h" | 6 #include "src/compiler.h" |
7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
8 #include "src/compiler/frame.h" | 8 #include "src/compiler/frame.h" |
9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
10 #include "src/compiler/node.h" | 10 #include "src/compiler/node.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 bool CallDescriptor::HasSameReturnLocationsAs( | 82 bool CallDescriptor::HasSameReturnLocationsAs( |
83 const CallDescriptor* other) const { | 83 const CallDescriptor* other) const { |
84 if (ReturnCount() != other->ReturnCount()) return false; | 84 if (ReturnCount() != other->ReturnCount()) return false; |
85 for (size_t i = 0; i < ReturnCount(); ++i) { | 85 for (size_t i = 0; i < ReturnCount(); ++i) { |
86 if (GetReturnLocation(i) != other->GetReturnLocation(i)) return false; | 86 if (GetReturnLocation(i) != other->GetReturnLocation(i)) return false; |
87 } | 87 } |
88 return true; | 88 return true; |
89 } | 89 } |
90 | 90 |
91 | 91 |
92 bool CallDescriptor::CanTailCall(const Node* node) const { | 92 bool CallDescriptor::CanTailCall(const Node* node, |
93 // Determine the number of stack parameters passed in | 93 int* stack_param_delta) const { |
94 size_t stack_params = 0; | 94 // TODO(danno): TF only current supports tail calls where the number of stack |
95 for (size_t i = 0; i < InputCount(); ++i) { | 95 // parameters of the callee is the same or fewer of the caller. |
96 if (!GetInputLocation(i).IsRegister()) { | |
97 ++stack_params; | |
98 } | |
99 } | |
100 // Ensure the input linkage contains the stack parameters in the right order | |
101 size_t current_stack_param = 0; | |
102 for (size_t i = 0; i < InputCount(); ++i) { | |
103 if (!GetInputLocation(i).IsRegister()) { | |
104 if (GetInputLocation(i) != LinkageLocation::ForCallerFrameSlot( | |
105 static_cast<int>(current_stack_param) - | |
106 static_cast<int>(stack_params))) { | |
107 return false; | |
108 } | |
109 ++current_stack_param; | |
110 } | |
111 } | |
112 // Tail calling is currently allowed if return locations match and all | |
113 // parameters are either in registers or on the stack but match exactly in | |
114 // number and content. | |
115 CallDescriptor const* other = OpParameter<CallDescriptor const*>(node); | 96 CallDescriptor const* other = OpParameter<CallDescriptor const*>(node); |
116 if (!HasSameReturnLocationsAs(other)) return false; | 97 if (!HasSameReturnLocationsAs(other)) return false; |
117 size_t current_input = 0; | 98 size_t current_input = 0; |
118 size_t other_input = 0; | 99 size_t other_input = 0; |
119 while (true) { | 100 *stack_param_delta = 0; |
120 if (other_input >= other->InputCount()) { | 101 bool more_other = true; |
121 while (current_input < InputCount()) { | 102 bool more_this = true; |
122 if (!GetInputLocation(current_input).IsRegister()) { | 103 while (more_other || more_this) { |
123 return false; | 104 if (other_input < other->InputCount()) { |
124 } | 105 if (!other->GetInputLocation(other_input).IsRegister()) { |
125 ++current_input; | 106 (*stack_param_delta)++; |
126 } | 107 } |
127 return true; | 108 } else { |
| 109 more_other = false; |
128 } | 110 } |
129 if (current_input >= InputCount()) { | 111 if (current_input < InputCount()) { |
130 while (other_input < other->InputCount()) { | 112 if (!GetInputLocation(current_input).IsRegister()) { |
131 if (!other->GetInputLocation(other_input).IsRegister()) { | 113 (*stack_param_delta)--; |
132 return false; | |
133 } | |
134 ++other_input; | |
135 } | 114 } |
136 return true; | 115 } else { |
137 } | 116 more_this = false; |
138 if (GetInputLocation(current_input).IsRegister()) { | |
139 ++current_input; | |
140 continue; | |
141 } | |
142 if (other->GetInputLocation(other_input).IsRegister()) { | |
143 ++other_input; | |
144 continue; | |
145 } | |
146 if (GetInputLocation(current_input) != | |
147 other->GetInputLocation(other_input)) { | |
148 return false; | |
149 } | |
150 Node* input = node->InputAt(static_cast<int>(other_input)); | |
151 if (input->opcode() != IrOpcode::kParameter) { | |
152 return false; | |
153 } | |
154 // Make sure that the parameter input passed through to the tail call | |
155 // corresponds to the correct stack slot. | |
156 size_t param_index = ParameterIndexOf(input->op()); | |
157 if (param_index != current_input - 1) { | |
158 return false; | |
159 } | 117 } |
160 ++current_input; | 118 ++current_input; |
161 ++other_input; | 119 ++other_input; |
162 } | 120 } |
163 UNREACHABLE(); | 121 return *stack_param_delta <= 0; |
164 return false; | |
165 } | 122 } |
166 | 123 |
167 | 124 |
168 CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) { | 125 CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) { |
169 if (info->code_stub() != NULL) { | 126 if (info->code_stub() != NULL) { |
170 // Use the code stub interface descriptor. | 127 // Use the code stub interface descriptor. |
171 CodeStub* stub = info->code_stub(); | 128 CodeStub* stub = info->code_stub(); |
172 CallInterfaceDescriptor descriptor = stub->GetCallInterfaceDescriptor(); | 129 CallInterfaceDescriptor descriptor = stub->GetCallInterfaceDescriptor(); |
173 return GetStubCallDescriptor( | 130 return GetStubCallDescriptor( |
174 info->isolate(), zone, descriptor, stub->GetStackParameterCount(), | 131 info->isolate(), zone, descriptor, stub->GetStackParameterCount(), |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 case Runtime::kInlineToLength: | 207 case Runtime::kInlineToLength: |
251 case Runtime::kInlineToName: | 208 case Runtime::kInlineToName: |
252 case Runtime::kInlineToNumber: | 209 case Runtime::kInlineToNumber: |
253 case Runtime::kInlineToObject: | 210 case Runtime::kInlineToObject: |
254 case Runtime::kInlineToPrimitive_Number: | 211 case Runtime::kInlineToPrimitive_Number: |
255 case Runtime::kInlineToPrimitive_String: | 212 case Runtime::kInlineToPrimitive_String: |
256 case Runtime::kInlineToPrimitive: | 213 case Runtime::kInlineToPrimitive: |
257 case Runtime::kInlineToString: | 214 case Runtime::kInlineToString: |
258 return 1; | 215 return 1; |
259 case Runtime::kInlineCall: | 216 case Runtime::kInlineCall: |
| 217 case Runtime::kInlineTailCall: |
260 case Runtime::kInlineDeoptimizeNow: | 218 case Runtime::kInlineDeoptimizeNow: |
261 case Runtime::kInlineThrowNotDateError: | 219 case Runtime::kInlineThrowNotDateError: |
262 return 2; | 220 return 2; |
263 default: | 221 default: |
264 break; | 222 break; |
265 } | 223 } |
266 | 224 |
267 // Most inlined runtime functions (except the ones listed above) can be called | 225 // Most inlined runtime functions (except the ones listed above) can be called |
268 // without a FrameState or will be lowered by JSIntrinsicLowering internally. | 226 // without a FrameState or will be lowered by JSIntrinsicLowering internally. |
269 const Runtime::Function* const f = Runtime::FunctionForId(function); | 227 const Runtime::Function* const f = Runtime::FunctionForId(function); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 return LinkageLocation::ForCalleeFrameSlot(spill_index); | 519 return LinkageLocation::ForCalleeFrameSlot(spill_index); |
562 } else { | 520 } else { |
563 // Parameter. Use the assigned location from the incoming call descriptor. | 521 // Parameter. Use the assigned location from the incoming call descriptor. |
564 int parameter_index = 1 + index; // skip index 0, which is the target. | 522 int parameter_index = 1 + index; // skip index 0, which is the target. |
565 return incoming_->GetInputLocation(parameter_index); | 523 return incoming_->GetInputLocation(parameter_index); |
566 } | 524 } |
567 } | 525 } |
568 } // namespace compiler | 526 } // namespace compiler |
569 } // namespace internal | 527 } // namespace internal |
570 } // namespace v8 | 528 } // namespace v8 |
OLD | NEW |