| Index: src/compiler/linkage.cc
|
| diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc
|
| index a460f4a980bd19db7dd688b9677bc2916077ed58..19ebfdfb3b61c63313c750c804acc925e8284c71 100644
|
| --- a/src/compiler/linkage.cc
|
| +++ b/src/compiler/linkage.cc
|
| @@ -52,12 +52,19 @@ bool CallDescriptor::HasSameReturnLocationsAs(
|
| }
|
|
|
|
|
| -bool CallDescriptor::CanTailCall(const Node* node) const {
|
| +bool CallDescriptor::CanTailCall(const Node* node, size_t* stack_parameters_in,
|
| + size_t* preserved_stack_parameters_in,
|
| + size_t* stack_parameters_out,
|
| + size_t* register_parameters_out) const {
|
| + *stack_parameters_in = 0;
|
| + *stack_parameters_out = 0;
|
| + *preserved_stack_parameters_in = 0;
|
| + *register_parameters_out = 0;
|
| +
|
| // Determine the number of stack parameters passed in
|
| - size_t stack_params = 0;
|
| for (size_t i = 0; i < InputCount(); ++i) {
|
| if (!GetInputLocation(i).is_register()) {
|
| - ++stack_params;
|
| + ++(*stack_parameters_in);
|
| }
|
| }
|
| // Ensure the input linkage contains the stack parameters in the right order
|
| @@ -66,7 +73,7 @@ bool CallDescriptor::CanTailCall(const Node* node) const {
|
| if (!GetInputLocation(i).is_register()) {
|
| if (GetInputLocation(i) !=
|
| LinkageLocation(static_cast<int>(current_stack_param) -
|
| - static_cast<int>(stack_params))) {
|
| + static_cast<int>(*stack_parameters_in))) {
|
| return false;
|
| }
|
| ++current_stack_param;
|
| @@ -77,25 +84,24 @@ bool CallDescriptor::CanTailCall(const Node* node) const {
|
| // 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;
|
| + bool stack_param_match = true;
|
| 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;
|
| + (*stack_parameters_out)++;
|
| + } else {
|
| + ++(*register_parameters_out);
|
| }
|
| ++other_input;
|
| }
|
| + // Allow adding stack parameters for the tail call
|
| return true;
|
| }
|
| if (GetInputLocation(current_input).is_register()) {
|
| @@ -104,22 +110,24 @@ bool CallDescriptor::CanTailCall(const Node* node) const {
|
| }
|
| if (other->GetInputLocation(other_input).is_register()) {
|
| ++other_input;
|
| + ++(*register_parameters_out);
|
| 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;
|
| + stack_param_match = false;
|
| + } else {
|
| + // Make sure that the parameter input passed through to the tail call
|
| + // corresponds to the correct stack slot.
|
| + size_t param_index = ParameterIndexOf(input->op());
|
| + if (param_index != current_input - 1) {
|
| + stack_param_match = false;
|
| + }
|
| }
|
| - // Make sure that the parameter input passed through to the tail call
|
| - // corresponds to the correct stack slot.
|
| - size_t param_index = ParameterIndexOf(input->op());
|
| - if (param_index != current_input - 1) {
|
| - return false;
|
| + if (stack_param_match) {
|
| + (*preserved_stack_parameters_in)++;
|
| }
|
| + (*stack_parameters_out)++;
|
| ++current_input;
|
| ++other_input;
|
| }
|
|
|