Index: src/compiler/linkage.cc |
diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc |
index 9338a5bed7029d4783618b9734df6fb06bcd0a4e..93bf21a84291918f40b2d63b65f6a52f9aa6e083 100644 |
--- a/src/compiler/linkage.cc |
+++ b/src/compiler/linkage.cc |
@@ -4,6 +4,7 @@ |
#include "src/code-stubs.h" |
#include "src/compiler.h" |
+#include "src/compiler/common-operator.h" |
#include "src/compiler/linkage.h" |
#include "src/compiler/node.h" |
#include "src/compiler/pipeline.h" |
@@ -48,6 +49,63 @@ bool CallDescriptor::HasSameReturnLocationsAs( |
} |
+bool CallDescriptor::CanTailCall(const Node* node) const { |
+ // Tail calling is currently allowed if return locations match and all |
+ // parameters are either in registers or on the stack but match exactly in |
+ // number and content. |
+ CallDescriptor const* other = OpParameter<CallDescriptor const*>(node); |
+ if (!HasSameReturnLocationsAs(other)) return false; |
+ size_t current_input = 0; |
+ size_t other_input = 0; |
+ size_t stack_parameter = 0; |
+ while (true) { |
+ if (other_input >= other->InputCount()) { |
+ while (current_input <= InputCount()) { |
+ if (!GetInputLocation(current_input).is_register()) { |
+ return false; |
+ } |
+ ++current_input; |
+ } |
+ return true; |
+ } |
+ if (current_input >= InputCount()) { |
+ while (other_input < other->InputCount()) { |
+ if (!other->GetInputLocation(other_input).is_register()) { |
+ return false; |
+ } |
+ ++other_input; |
+ } |
+ return true; |
+ } |
+ if (GetInputLocation(current_input).is_register()) { |
+ ++current_input; |
+ continue; |
+ } |
+ if (other->GetInputLocation(other_input).is_register()) { |
+ ++other_input; |
+ continue; |
+ } |
+ if (GetInputLocation(current_input) != |
+ other->GetInputLocation(other_input)) { |
+ return false; |
+ } |
+ Node* input = node->InputAt(static_cast<int>(other_input)); |
+ if (input->opcode() != IrOpcode::kParameter) { |
+ return false; |
+ } |
+ size_t param_index = ParameterIndexOf(input->op()); |
+ if (param_index != stack_parameter) { |
+ return false; |
+ } |
+ ++stack_parameter; |
+ ++current_input; |
+ ++other_input; |
+ } |
+ UNREACHABLE(); |
+ return false; |
+} |
+ |
+ |
CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) { |
if (info->code_stub() != NULL) { |
// Use the code stub interface descriptor. |