Commit ecb8fcfc authored by ishell's avatar ishell Committed by Commit bot

[crankshaft] [turbofan] Fix environment handling when generating a tail call from inlined function.

This CL ensures that we build environments/frame states so that tail caller frame will never become topmost.

BUG=chromium:598998, v8:4698
LOG=N

Review URL: https://codereview.chromium.org/1849503002

Cr-Commit-Position: refs/heads/master@{#35188}
parent 6df9a22c
......@@ -615,15 +615,17 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
if (buffer->descriptor->SupportsTailCalls()) {
frame_state = NodeProperties::GetFrameStateInput(frame_state, 0);
buffer->frame_state_descriptor =
buffer->frame_state_descriptor->outer_state();
if (buffer->frame_state_descriptor != nullptr &&
buffer->frame_state_descriptor->type() ==
FrameStateType::kArgumentsAdaptor) {
while (buffer->frame_state_descriptor != nullptr &&
(buffer->frame_state_descriptor->type() ==
FrameStateType::kArgumentsAdaptor ||
buffer->frame_state_descriptor->type() ==
FrameStateType::kTailCallerFunction)) {
frame_state = NodeProperties::GetFrameStateInput(frame_state, 0);
buffer->frame_state_descriptor =
buffer->frame_state_descriptor->outer_state();
......
......@@ -877,10 +877,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -720,10 +720,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -910,10 +910,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -887,10 +887,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -887,10 +887,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -892,10 +892,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -816,10 +816,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -902,10 +902,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
......@@ -925,10 +925,12 @@ void LChunkBuilder::AddInstruction(LInstruction* instr,
DCHECK_NOT_NULL(hydrogen_env);
if (instr->IsSyntacticTailCall()) {
// If it was a syntactic tail call we need to drop the current frame and
// an arguments adaptor frame on top of it (if the latter is present).
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
hydrogen_env = hydrogen_env->outer();
if (hydrogen_env != nullptr &&
hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
while (hydrogen_env != nullptr &&
(hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR ||
hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION)) {
hydrogen_env = hydrogen_env->outer();
}
if (hydrogen_env != nullptr) {
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-tailcalls --allow-natives-syntax
"use strict";
function deopt_function(func) {
%DeoptimizeFunction(func);
}
function f(x) {
return deopt_function(h);
}
function g(x) {
return f(x, 1);
}
function h(x) {
g(x, 1);
}
%SetForceInlineFlag(g);
%SetForceInlineFlag(f);
%NeverOptimizeFunction(deopt_function);
h(1);
h(1);
%OptimizeFunctionOnNextCall(h);
h(1);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment