Mark the simulate before EnterInlined with BailoutId::None(), and set ReturnId on EnterInlined. When merging simulates into the simulate before enter-inlined, adopt the last AST id that gets merged into it.
BUG=v8:3282 LOG=n R=titzer@chromium.org Review URL: https://codereview.chromium.org/257583004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20949 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2e0c29654c
commit
a55821eef2
@ -2521,6 +2521,7 @@ LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
||||
HEnvironment* outer = current_block_->last_environment();
|
||||
outer->set_ast_id(instr->ReturnId());
|
||||
HConstant* undefined = graph()->GetConstantUndefined();
|
||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
||||
instr->arguments_count(),
|
||||
|
@ -1454,6 +1454,7 @@ LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
||||
HEnvironment* outer = current_block_->last_environment();
|
||||
outer->set_ast_id(instr->ReturnId());
|
||||
HConstant* undefined = graph()->GetConstantUndefined();
|
||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
||||
instr->arguments_count(),
|
||||
|
@ -2595,6 +2595,9 @@ void HPhi::AddIndirectUsesTo(int* dest) {
|
||||
|
||||
|
||||
void HSimulate::MergeWith(ZoneList<HSimulate*>* list) {
|
||||
if (!list->is_empty() && !HasAstId()) {
|
||||
set_ast_id(list->last()->ast_id());
|
||||
}
|
||||
while (!list->is_empty()) {
|
||||
HSimulate* from = list->RemoveLast();
|
||||
ZoneList<HValue*>* from_values = &from->values_;
|
||||
@ -4504,7 +4507,7 @@ void HPhi::Verify() {
|
||||
|
||||
void HSimulate::Verify() {
|
||||
HInstruction::Verify();
|
||||
ASSERT(HasAstId());
|
||||
ASSERT(HasAstId() || next()->IsEnterInlined());
|
||||
}
|
||||
|
||||
|
||||
|
@ -2085,14 +2085,15 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
|
||||
public:
|
||||
static HEnterInlined* New(Zone* zone,
|
||||
HValue* context,
|
||||
BailoutId return_id,
|
||||
Handle<JSFunction> closure,
|
||||
int arguments_count,
|
||||
FunctionLiteral* function,
|
||||
InliningKind inlining_kind,
|
||||
Variable* arguments_var,
|
||||
HArgumentsObject* arguments_object) {
|
||||
return new(zone) HEnterInlined(closure, arguments_count, function,
|
||||
inlining_kind, arguments_var,
|
||||
return new(zone) HEnterInlined(return_id, closure, arguments_count,
|
||||
function, inlining_kind, arguments_var,
|
||||
arguments_object, zone);
|
||||
}
|
||||
|
||||
@ -2107,6 +2108,7 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
|
||||
void set_arguments_pushed() { arguments_pushed_ = true; }
|
||||
FunctionLiteral* function() const { return function_; }
|
||||
InliningKind inlining_kind() const { return inlining_kind_; }
|
||||
BailoutId ReturnId() const { return return_id_; }
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
|
||||
return Representation::None();
|
||||
@ -2118,14 +2120,16 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
|
||||
DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
|
||||
|
||||
private:
|
||||
HEnterInlined(Handle<JSFunction> closure,
|
||||
HEnterInlined(BailoutId return_id,
|
||||
Handle<JSFunction> closure,
|
||||
int arguments_count,
|
||||
FunctionLiteral* function,
|
||||
InliningKind inlining_kind,
|
||||
Variable* arguments_var,
|
||||
HArgumentsObject* arguments_object,
|
||||
Zone* zone)
|
||||
: closure_(closure),
|
||||
: return_id_(return_id),
|
||||
closure_(closure),
|
||||
arguments_count_(arguments_count),
|
||||
arguments_pushed_(false),
|
||||
function_(function),
|
||||
@ -2135,6 +2139,7 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
|
||||
return_targets_(2, zone) {
|
||||
}
|
||||
|
||||
BailoutId return_id_;
|
||||
Handle<JSFunction> closure_;
|
||||
int arguments_count_;
|
||||
bool arguments_pushed_;
|
||||
|
@ -7383,8 +7383,6 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
||||
HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
|
||||
inner_env->BindContext(context);
|
||||
|
||||
Add<HSimulate>(return_id);
|
||||
current_block()->UpdateEnvironment(inner_env);
|
||||
HArgumentsObject* arguments_object = NULL;
|
||||
|
||||
// If the function uses arguments object create and bind one, also copy
|
||||
@ -7400,8 +7398,17 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
||||
}
|
||||
}
|
||||
|
||||
// Capture the state before invoking the inlined function for deopt in the
|
||||
// inlined function. This simulate has no bailout-id since it's not directly
|
||||
// reachable for deopt, and is only used to capture the state. If the simulate
|
||||
// becomes reachable by merging, the ast id of the simulate merged into it is
|
||||
// adopted.
|
||||
Add<HSimulate>(BailoutId::None());
|
||||
|
||||
current_block()->UpdateEnvironment(inner_env);
|
||||
|
||||
HEnterInlined* enter_inlined =
|
||||
Add<HEnterInlined>(target, arguments_count, function,
|
||||
Add<HEnterInlined>(return_id, target, arguments_count, function,
|
||||
function_state()->inlining_kind(),
|
||||
function->scope()->arguments(),
|
||||
arguments_object);
|
||||
|
@ -2658,6 +2658,7 @@ LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
||||
HEnvironment* outer = current_block_->last_environment();
|
||||
outer->set_ast_id(instr->ReturnId());
|
||||
HConstant* undefined = graph()->GetConstantUndefined();
|
||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
||||
instr->arguments_count(),
|
||||
|
@ -2472,6 +2472,7 @@ LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
||||
HEnvironment* outer = current_block_->last_environment();
|
||||
outer->set_ast_id(instr->ReturnId());
|
||||
HConstant* undefined = graph()->GetConstantUndefined();
|
||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
||||
instr->arguments_count(),
|
||||
|
@ -2546,6 +2546,7 @@ LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
|
||||
|
||||
LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
||||
HEnvironment* outer = current_block_->last_environment();
|
||||
outer->set_ast_id(instr->ReturnId());
|
||||
HConstant* undefined = graph()->GetConstantUndefined();
|
||||
HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
||||
instr->arguments_count(),
|
||||
|
24
test/mjsunit/regress/regress-lazy-deopt-inlining.js
Normal file
24
test/mjsunit/regress/regress-lazy-deopt-inlining.js
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2014 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: --allow-natives-syntax
|
||||
|
||||
"use strict";
|
||||
function f1(d) {
|
||||
return 1 + f2(f3(d));
|
||||
}
|
||||
|
||||
function f2(v) { return v; }
|
||||
|
||||
function f3(d) {
|
||||
if (d) %DeoptimizeFunction(f1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
%NeverOptimizeFunction(f3);
|
||||
|
||||
f1(false);
|
||||
f1(false);
|
||||
%OptimizeFunctionOnNextCall(f1);
|
||||
assertEquals(3, f1(true));
|
Loading…
Reference in New Issue
Block a user