From a55821eef22bbc63264f7421cbe043e1edbfb029 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Thu, 24 Apr 2014 15:20:53 +0000 Subject: [PATCH] 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 --- src/arm/lithium-arm.cc | 1 + src/arm64/lithium-arm64.cc | 1 + src/hydrogen-instructions.cc | 5 ++++- src/hydrogen-instructions.h | 13 ++++++++---- src/hydrogen.cc | 13 +++++++++--- src/ia32/lithium-ia32.cc | 1 + src/mips/lithium-mips.cc | 1 + src/x64/lithium-x64.cc | 1 + .../mjsunit/regress/regress-lazy-deopt-inlining.js | 24 ++++++++++++++++++++++ 9 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 test/mjsunit/regress/regress-lazy-deopt-inlining.js diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index b173853..1515278 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -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(), diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc index 61bfdf4..b5802ab 100644 --- a/src/arm64/lithium-arm64.cc +++ b/src/arm64/lithium-arm64.cc @@ -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(), diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index c56f5dc..ceedafc 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -2595,6 +2595,9 @@ void HPhi::AddIndirectUsesTo(int* dest) { void HSimulate::MergeWith(ZoneList* list) { + if (!list->is_empty() && !HasAstId()) { + set_ast_id(list->last()->ast_id()); + } while (!list->is_empty()) { HSimulate* from = list->RemoveLast(); ZoneList* from_values = &from->values_; @@ -4504,7 +4507,7 @@ void HPhi::Verify() { void HSimulate::Verify() { HInstruction::Verify(); - ASSERT(HasAstId()); + ASSERT(HasAstId() || next()->IsEnterInlined()); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 3b486e7..eb0d4e1 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -2085,14 +2085,15 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> { public: static HEnterInlined* New(Zone* zone, HValue* context, + BailoutId return_id, Handle 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 closure, + HEnterInlined(BailoutId return_id, + Handle 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 closure_; int arguments_count_; bool arguments_pushed_; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 6d932d4..4c02c90 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -7383,8 +7383,6 @@ bool HOptimizedGraphBuilder::TryInline(Handle target, HConstant* context = Add(Handle(target->context())); inner_env->BindContext(context); - Add(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 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(BailoutId::None()); + + current_block()->UpdateEnvironment(inner_env); + HEnterInlined* enter_inlined = - Add(target, arguments_count, function, + Add(return_id, target, arguments_count, function, function_state()->inlining_kind(), function->scope()->arguments(), arguments_object); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index cfd49ca..965b15a 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -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(), diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 886d941..bbf422f 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -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(), diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 978fafd..a6f9140 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -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(), diff --git a/test/mjsunit/regress/regress-lazy-deopt-inlining.js b/test/mjsunit/regress/regress-lazy-deopt-inlining.js new file mode 100644 index 0000000..6cda168 --- /dev/null +++ b/test/mjsunit/regress/regress-lazy-deopt-inlining.js @@ -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)); -- 2.7.4