[crankshaft] Support inlining of function calls in tail position (in ES6 sense).
BUG=v8:4698 LOG=N TBR=bmeurer@chromium.org Review URL: https://codereview.chromium.org/1782743003 Cr-Commit-Position: refs/heads/master@{#34992}
This commit is contained in:
parent
9383d14b9f
commit
df694d5524
@ -2498,11 +2498,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -1425,11 +1425,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if ((instr->arguments_var() != NULL) &&
|
if ((instr->arguments_var() != NULL) &&
|
||||||
instr->arguments_object()->IsLinked()) {
|
instr->arguments_object()->IsLinked()) {
|
||||||
|
@ -1939,10 +1939,12 @@ class HEnterInlined final : public HTemplateInstruction<0> {
|
|||||||
HConstant* closure_context, int arguments_count,
|
HConstant* closure_context, int arguments_count,
|
||||||
FunctionLiteral* function,
|
FunctionLiteral* function,
|
||||||
InliningKind inlining_kind, Variable* arguments_var,
|
InliningKind inlining_kind, Variable* arguments_var,
|
||||||
HArgumentsObject* arguments_object) {
|
HArgumentsObject* arguments_object,
|
||||||
return new (zone) HEnterInlined(return_id, closure, closure_context,
|
TailCallMode syntactic_tail_call_mode) {
|
||||||
arguments_count, function, inlining_kind,
|
return new (zone)
|
||||||
arguments_var, arguments_object, zone);
|
HEnterInlined(return_id, closure, closure_context, arguments_count,
|
||||||
|
function, inlining_kind, arguments_var, arguments_object,
|
||||||
|
syntactic_tail_call_mode, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
|
void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
|
||||||
@ -1958,6 +1960,9 @@ class HEnterInlined final : public HTemplateInstruction<0> {
|
|||||||
void set_arguments_pushed() { arguments_pushed_ = true; }
|
void set_arguments_pushed() { arguments_pushed_ = true; }
|
||||||
FunctionLiteral* function() const { return function_; }
|
FunctionLiteral* function() const { return function_; }
|
||||||
InliningKind inlining_kind() const { return inlining_kind_; }
|
InliningKind inlining_kind() const { return inlining_kind_; }
|
||||||
|
TailCallMode syntactic_tail_call_mode() const {
|
||||||
|
return syntactic_tail_call_mode_;
|
||||||
|
}
|
||||||
BailoutId ReturnId() const { return return_id_; }
|
BailoutId ReturnId() const { return return_id_; }
|
||||||
int inlining_id() const { return inlining_id_; }
|
int inlining_id() const { return inlining_id_; }
|
||||||
void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
|
void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
|
||||||
@ -1976,7 +1981,7 @@ class HEnterInlined final : public HTemplateInstruction<0> {
|
|||||||
HConstant* closure_context, int arguments_count,
|
HConstant* closure_context, int arguments_count,
|
||||||
FunctionLiteral* function, InliningKind inlining_kind,
|
FunctionLiteral* function, InliningKind inlining_kind,
|
||||||
Variable* arguments_var, HArgumentsObject* arguments_object,
|
Variable* arguments_var, HArgumentsObject* arguments_object,
|
||||||
Zone* zone)
|
TailCallMode syntactic_tail_call_mode, Zone* zone)
|
||||||
: return_id_(return_id),
|
: return_id_(return_id),
|
||||||
shared_(handle(closure->shared())),
|
shared_(handle(closure->shared())),
|
||||||
closure_(closure),
|
closure_(closure),
|
||||||
@ -1985,6 +1990,7 @@ class HEnterInlined final : public HTemplateInstruction<0> {
|
|||||||
arguments_pushed_(false),
|
arguments_pushed_(false),
|
||||||
function_(function),
|
function_(function),
|
||||||
inlining_kind_(inlining_kind),
|
inlining_kind_(inlining_kind),
|
||||||
|
syntactic_tail_call_mode_(syntactic_tail_call_mode),
|
||||||
inlining_id_(0),
|
inlining_id_(0),
|
||||||
arguments_var_(arguments_var),
|
arguments_var_(arguments_var),
|
||||||
arguments_object_(arguments_object),
|
arguments_object_(arguments_object),
|
||||||
@ -1998,6 +2004,7 @@ class HEnterInlined final : public HTemplateInstruction<0> {
|
|||||||
bool arguments_pushed_;
|
bool arguments_pushed_;
|
||||||
FunctionLiteral* function_;
|
FunctionLiteral* function_;
|
||||||
InliningKind inlining_kind_;
|
InliningKind inlining_kind_;
|
||||||
|
TailCallMode syntactic_tail_call_mode_;
|
||||||
int inlining_id_;
|
int inlining_id_;
|
||||||
Variable* arguments_var_;
|
Variable* arguments_var_;
|
||||||
HArgumentsObject* arguments_object_;
|
HArgumentsObject* arguments_object_;
|
||||||
|
@ -4114,7 +4114,7 @@ AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
|
|||||||
typeof_mode_(NOT_INSIDE_TYPEOF) {
|
typeof_mode_(NOT_INSIDE_TYPEOF) {
|
||||||
owner->set_ast_context(this); // Push.
|
owner->set_ast_context(this); // Push.
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
|
DCHECK_EQ(JS_FUNCTION, owner->environment()->frame_type());
|
||||||
original_length_ = owner->environment()->length();
|
original_length_ = owner->environment()->length();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -4126,18 +4126,18 @@ AstContext::~AstContext() {
|
|||||||
|
|
||||||
|
|
||||||
EffectContext::~EffectContext() {
|
EffectContext::~EffectContext() {
|
||||||
DCHECK(owner()->HasStackOverflow() ||
|
DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL ||
|
||||||
owner()->current_block() == NULL ||
|
|
||||||
(owner()->environment()->length() == original_length_ &&
|
(owner()->environment()->length() == original_length_ &&
|
||||||
owner()->environment()->frame_type() == JS_FUNCTION));
|
(owner()->environment()->frame_type() == JS_FUNCTION ||
|
||||||
|
owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ValueContext::~ValueContext() {
|
ValueContext::~ValueContext() {
|
||||||
DCHECK(owner()->HasStackOverflow() ||
|
DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL ||
|
||||||
owner()->current_block() == NULL ||
|
|
||||||
(owner()->environment()->length() == original_length_ + 1 &&
|
(owner()->environment()->length() == original_length_ + 1 &&
|
||||||
owner()->environment()->frame_type() == JS_FUNCTION));
|
(owner()->environment()->frame_type() == JS_FUNCTION ||
|
||||||
|
owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -8368,11 +8368,6 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
|||||||
if (nodes_added == kNotInlinable) return false;
|
if (nodes_added == kNotInlinable) return false;
|
||||||
|
|
||||||
Handle<JSFunction> caller = current_info()->closure();
|
Handle<JSFunction> caller = current_info()->closure();
|
||||||
if (syntactic_tail_call_mode == TailCallMode::kAllow) {
|
|
||||||
TraceInline(target, caller, "call is at tail position");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
|
if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
|
||||||
TraceInline(target, caller, "target AST is too large [early]");
|
TraceInline(target, caller, "target AST is too large [early]");
|
||||||
return false;
|
return false;
|
||||||
@ -8530,12 +8525,9 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
|||||||
|
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
|
|
||||||
HEnvironment* inner_env =
|
HEnvironment* inner_env = environment()->CopyForInlining(
|
||||||
environment()->CopyForInlining(target,
|
target, arguments_count, function, undefined,
|
||||||
arguments_count,
|
function_state()->inlining_kind(), syntactic_tail_call_mode);
|
||||||
function,
|
|
||||||
undefined,
|
|
||||||
function_state()->inlining_kind());
|
|
||||||
|
|
||||||
HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
|
HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
|
||||||
inner_env->BindContext(context);
|
inner_env->BindContext(context);
|
||||||
@ -8565,10 +8557,10 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
|||||||
current_block()->UpdateEnvironment(inner_env);
|
current_block()->UpdateEnvironment(inner_env);
|
||||||
Scope* saved_scope = scope();
|
Scope* saved_scope = scope();
|
||||||
set_scope(target_info.scope());
|
set_scope(target_info.scope());
|
||||||
HEnterInlined* enter_inlined =
|
HEnterInlined* enter_inlined = Add<HEnterInlined>(
|
||||||
Add<HEnterInlined>(return_id, target, context, arguments_count, function,
|
return_id, target, context, arguments_count, function,
|
||||||
function_state()->inlining_kind(),
|
function_state()->inlining_kind(), function->scope()->arguments(),
|
||||||
function->scope()->arguments(), arguments_object);
|
arguments_object, syntactic_tail_call_mode);
|
||||||
if (top_info()->is_tracking_positions()) {
|
if (top_info()->is_tracking_positions()) {
|
||||||
enter_inlined->set_inlining_id(inlining_id);
|
enter_inlined->set_inlining_id(inlining_id);
|
||||||
}
|
}
|
||||||
@ -9254,9 +9246,6 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(
|
|||||||
top_info()->closure()->context()->native_context()) {
|
top_info()->closure()->context()->native_context()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (syntactic_tail_call_mode == TailCallMode::kAllow) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (argc > CallApiCallbackStub::kArgMax) {
|
if (argc > CallApiCallbackStub::kArgMax) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -9364,14 +9353,16 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(
|
|||||||
HConstant* code_value = Add<HConstant>(code);
|
HConstant* code_value = Add<HConstant>(code);
|
||||||
call = New<HCallWithDescriptor>(
|
call = New<HCallWithDescriptor>(
|
||||||
code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
|
code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
|
||||||
Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
|
Vector<HValue*>(op_vals, arraysize(op_vals) - 1),
|
||||||
|
syntactic_tail_call_mode);
|
||||||
} else {
|
} else {
|
||||||
CallApiCallbackStub stub(isolate(), argc, call_data_undefined);
|
CallApiCallbackStub stub(isolate(), argc, call_data_undefined);
|
||||||
Handle<Code> code = stub.GetCode();
|
Handle<Code> code = stub.GetCode();
|
||||||
HConstant* code_value = Add<HConstant>(code);
|
HConstant* code_value = Add<HConstant>(code);
|
||||||
call = New<HCallWithDescriptor>(
|
call = New<HCallWithDescriptor>(
|
||||||
code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
|
code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
|
||||||
Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
|
Vector<HValue*>(op_vals, arraysize(op_vals) - 1),
|
||||||
|
syntactic_tail_call_mode);
|
||||||
Drop(1); // Drop function.
|
Drop(1); // Drop function.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13197,14 +13188,16 @@ HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
|
|||||||
return new_env;
|
return new_env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HEnvironment::MarkAsTailCaller() {
|
||||||
|
DCHECK_EQ(JS_FUNCTION, frame_type());
|
||||||
|
frame_type_ = TAIL_CALLER_FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
HEnvironment* HEnvironment::CopyForInlining(
|
HEnvironment* HEnvironment::CopyForInlining(
|
||||||
Handle<JSFunction> target,
|
Handle<JSFunction> target, int arguments, FunctionLiteral* function,
|
||||||
int arguments,
|
HConstant* undefined, InliningKind inlining_kind,
|
||||||
FunctionLiteral* function,
|
TailCallMode syntactic_tail_call_mode) const {
|
||||||
HConstant* undefined,
|
DCHECK_EQ(JS_FUNCTION, frame_type());
|
||||||
InliningKind inlining_kind) const {
|
|
||||||
DCHECK(frame_type() == JS_FUNCTION);
|
|
||||||
|
|
||||||
// Outer environment is a copy of this one without the arguments.
|
// Outer environment is a copy of this one without the arguments.
|
||||||
int arity = function->scope()->num_parameters();
|
int arity = function->scope()->num_parameters();
|
||||||
@ -13213,6 +13206,11 @@ HEnvironment* HEnvironment::CopyForInlining(
|
|||||||
outer->Drop(arguments + 1); // Including receiver.
|
outer->Drop(arguments + 1); // Including receiver.
|
||||||
outer->ClearHistory();
|
outer->ClearHistory();
|
||||||
|
|
||||||
|
if (syntactic_tail_call_mode == TailCallMode::kAllow) {
|
||||||
|
DCHECK_EQ(NORMAL_RETURN, inlining_kind);
|
||||||
|
outer->MarkAsTailCaller();
|
||||||
|
}
|
||||||
|
|
||||||
if (inlining_kind == CONSTRUCT_CALL_RETURN) {
|
if (inlining_kind == CONSTRUCT_CALL_RETURN) {
|
||||||
// Create artificial constructor stub environment. The receiver should
|
// Create artificial constructor stub environment. The receiver should
|
||||||
// actually be the constructor function, but we pass the newly allocated
|
// actually be the constructor function, but we pass the newly allocated
|
||||||
|
@ -501,10 +501,10 @@ enum FrameType {
|
|||||||
JS_GETTER,
|
JS_GETTER,
|
||||||
JS_SETTER,
|
JS_SETTER,
|
||||||
ARGUMENTS_ADAPTOR,
|
ARGUMENTS_ADAPTOR,
|
||||||
|
TAIL_CALLER_FUNCTION,
|
||||||
STUB
|
STUB
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class HEnvironment final : public ZoneObject {
|
class HEnvironment final : public ZoneObject {
|
||||||
public:
|
public:
|
||||||
HEnvironment(HEnvironment* outer,
|
HEnvironment(HEnvironment* outer,
|
||||||
@ -613,15 +613,17 @@ class HEnvironment final : public ZoneObject {
|
|||||||
// Create an "inlined version" of this environment, where the original
|
// Create an "inlined version" of this environment, where the original
|
||||||
// environment is the outer environment but the top expression stack
|
// environment is the outer environment but the top expression stack
|
||||||
// elements are moved to an inner environment as parameters.
|
// elements are moved to an inner environment as parameters.
|
||||||
HEnvironment* CopyForInlining(Handle<JSFunction> target,
|
HEnvironment* CopyForInlining(Handle<JSFunction> target, int arguments,
|
||||||
int arguments,
|
FunctionLiteral* function, HConstant* undefined,
|
||||||
FunctionLiteral* function,
|
InliningKind inlining_kind,
|
||||||
HConstant* undefined,
|
TailCallMode syntactic_tail_call_mode) const;
|
||||||
InliningKind inlining_kind) const;
|
|
||||||
|
|
||||||
HEnvironment* DiscardInlined(bool drop_extra) {
|
HEnvironment* DiscardInlined(bool drop_extra) {
|
||||||
HEnvironment* outer = outer_;
|
HEnvironment* outer = outer_;
|
||||||
while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
|
while (outer->frame_type() != JS_FUNCTION &&
|
||||||
|
outer->frame_type() != TAIL_CALLER_FUNCTION) {
|
||||||
|
outer = outer->outer_;
|
||||||
|
}
|
||||||
if (drop_extra) outer->Drop(1);
|
if (drop_extra) outer->Drop(1);
|
||||||
return outer;
|
return outer;
|
||||||
}
|
}
|
||||||
@ -680,6 +682,10 @@ class HEnvironment final : public ZoneObject {
|
|||||||
FrameType frame_type,
|
FrameType frame_type,
|
||||||
int arguments) const;
|
int arguments) const;
|
||||||
|
|
||||||
|
// Marks current environment as tail caller by setting frame type to
|
||||||
|
// TAIL_CALLER_FUNCTION.
|
||||||
|
void MarkAsTailCaller();
|
||||||
|
|
||||||
// True if index is included in the expression stack part of the environment.
|
// True if index is included in the expression stack part of the environment.
|
||||||
bool HasExpressionAt(int index) const;
|
bool HasExpressionAt(int index) const;
|
||||||
|
|
||||||
@ -1278,6 +1284,26 @@ class HGraphBuilder {
|
|||||||
return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
|
return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
|
||||||
|
class P7, class P8, class P9>
|
||||||
|
I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
|
||||||
|
return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8,
|
||||||
|
p9);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
|
||||||
|
class P7, class P8, class P9>
|
||||||
|
HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7,
|
||||||
|
P8 p8, P9 p9) {
|
||||||
|
return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8, p8));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
|
||||||
|
class P7, class P8, class P9>
|
||||||
|
I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
|
||||||
|
return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8, p9));
|
||||||
|
}
|
||||||
|
|
||||||
void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
|
void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
|
||||||
|
|
||||||
// When initializing arrays, we'll unfold the loop if the number of elements
|
// When initializing arrays, we'll unfold the loop if the number of elements
|
||||||
|
@ -2551,11 +2551,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -240,8 +240,8 @@ void LCodeGenBase::WriteTranslationFrame(LEnvironment* environment,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JS_GETTER: {
|
case JS_GETTER: {
|
||||||
DCHECK(translation_size == 1);
|
DCHECK_EQ(1, translation_size);
|
||||||
DCHECK(height == 0);
|
DCHECK_EQ(0, height);
|
||||||
int shared_id = DefineDeoptimizationLiteral(
|
int shared_id = DefineDeoptimizationLiteral(
|
||||||
environment->entry() ? environment->entry()->shared()
|
environment->entry() ? environment->entry()->shared()
|
||||||
: info()->shared_info());
|
: info()->shared_info());
|
||||||
@ -255,8 +255,8 @@ void LCodeGenBase::WriteTranslationFrame(LEnvironment* environment,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JS_SETTER: {
|
case JS_SETTER: {
|
||||||
DCHECK(translation_size == 2);
|
DCHECK_EQ(2, translation_size);
|
||||||
DCHECK(height == 0);
|
DCHECK_EQ(0, height);
|
||||||
int shared_id = DefineDeoptimizationLiteral(
|
int shared_id = DefineDeoptimizationLiteral(
|
||||||
environment->entry() ? environment->entry()->shared()
|
environment->entry() ? environment->entry()->shared()
|
||||||
: info()->shared_info());
|
: info()->shared_info());
|
||||||
@ -269,6 +269,20 @@ void LCodeGenBase::WriteTranslationFrame(LEnvironment* environment,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TAIL_CALLER_FUNCTION: {
|
||||||
|
DCHECK_EQ(0, translation_size);
|
||||||
|
int shared_id = DefineDeoptimizationLiteral(
|
||||||
|
environment->entry() ? environment->entry()->shared()
|
||||||
|
: info()->shared_info());
|
||||||
|
translation->BeginTailCallerFrame(shared_id);
|
||||||
|
if (info()->closure().is_identical_to(environment->closure())) {
|
||||||
|
translation->StoreJSFrameFunction();
|
||||||
|
} else {
|
||||||
|
int closure_id = DefineDeoptimizationLiteral(environment->closure());
|
||||||
|
translation->StoreLiteral(closure_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ARGUMENTS_ADAPTOR: {
|
case ARGUMENTS_ADAPTOR: {
|
||||||
int shared_id = DefineDeoptimizationLiteral(
|
int shared_id = DefineDeoptimizationLiteral(
|
||||||
environment->entry() ? environment->entry()->shared()
|
environment->entry() ? environment->entry()->shared()
|
||||||
|
@ -522,12 +522,28 @@ LEnvironment* LChunkBuilderBase::CreateEnvironment(
|
|||||||
ZoneList<HValue*>* objects_to_materialize) {
|
ZoneList<HValue*>* objects_to_materialize) {
|
||||||
if (hydrogen_env == NULL) return NULL;
|
if (hydrogen_env == NULL) return NULL;
|
||||||
|
|
||||||
|
BailoutId ast_id = hydrogen_env->ast_id();
|
||||||
|
DCHECK(!ast_id.IsNone() ||
|
||||||
|
(hydrogen_env->frame_type() != JS_FUNCTION &&
|
||||||
|
hydrogen_env->frame_type() != TAIL_CALLER_FUNCTION));
|
||||||
|
|
||||||
|
if (hydrogen_env->frame_type() == TAIL_CALLER_FUNCTION) {
|
||||||
|
// Skip potential outer arguments adaptor frame.
|
||||||
|
HEnvironment* outer_hydrogen_env = hydrogen_env->outer();
|
||||||
|
if (outer_hydrogen_env != nullptr &&
|
||||||
|
outer_hydrogen_env->frame_type() == ARGUMENTS_ADAPTOR) {
|
||||||
|
outer_hydrogen_env = outer_hydrogen_env->outer();
|
||||||
|
}
|
||||||
|
LEnvironment* outer = CreateEnvironment(
|
||||||
|
outer_hydrogen_env, argument_index_accumulator, objects_to_materialize);
|
||||||
|
return new (zone())
|
||||||
|
LEnvironment(hydrogen_env->closure(), hydrogen_env->frame_type(),
|
||||||
|
ast_id, 0, 0, 0, outer, hydrogen_env->entry(), zone());
|
||||||
|
}
|
||||||
|
|
||||||
LEnvironment* outer =
|
LEnvironment* outer =
|
||||||
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator,
|
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator,
|
||||||
objects_to_materialize);
|
objects_to_materialize);
|
||||||
BailoutId ast_id = hydrogen_env->ast_id();
|
|
||||||
DCHECK(!ast_id.IsNone() ||
|
|
||||||
hydrogen_env->frame_type() != JS_FUNCTION);
|
|
||||||
|
|
||||||
int omitted_count = (hydrogen_env->frame_type() == JS_FUNCTION)
|
int omitted_count = (hydrogen_env->frame_type() == JS_FUNCTION)
|
||||||
? 0
|
? 0
|
||||||
|
@ -2445,11 +2445,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -2450,11 +2450,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -2430,7 +2430,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->inlining_kind());
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -2236,7 +2236,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->inlining_kind());
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -2553,11 +2553,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
@ -2556,11 +2556,9 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
|||||||
HEnvironment* outer = current_block_->last_environment();
|
HEnvironment* outer = current_block_->last_environment();
|
||||||
outer->set_ast_id(instr->ReturnId());
|
outer->set_ast_id(instr->ReturnId());
|
||||||
HConstant* undefined = graph()->GetConstantUndefined();
|
HConstant* undefined = graph()->GetConstantUndefined();
|
||||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
HEnvironment* inner = outer->CopyForInlining(
|
||||||
instr->arguments_count(),
|
instr->closure(), instr->arguments_count(), instr->function(), undefined,
|
||||||
instr->function(),
|
instr->inlining_kind(), instr->syntactic_tail_call_mode());
|
||||||
undefined,
|
|
||||||
instr->inlining_kind());
|
|
||||||
// Only replay binding of arguments object if it wasn't removed from graph.
|
// Only replay binding of arguments object if it wasn't removed from graph.
|
||||||
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
|
||||||
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
inner->Bind(instr->arguments_var(), instr->arguments_object());
|
||||||
|
Loading…
Reference in New Issue
Block a user