From 7483dbd5fcb9b8a5a4d0b44c9a52eca1b716166f Mon Sep 17 00:00:00 2001 From: bmeurer Date: Wed, 27 May 2015 04:01:51 -0700 Subject: [PATCH] [turbofan] Use Start as sentinel for frame states. This simplifies inlining, in that we only need to update uses of Start and inputs of End instead of walking the whole inlinee to update all outer frame states. R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/1146403008 Cr-Commit-Position: refs/heads/master@{#28649} --- src/compiler/ast-graph-builder.cc | 2 +- src/compiler/js-graph.cc | 2 +- src/compiler/js-inlining.cc | 23 +++++++---------------- src/compiler/js-inlining.h | 2 +- src/compiler/verifier.cc | 4 ++-- test/cctest/compiler/test-run-inlining.cc | 14 ++++++++++++++ 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 9778c79..bc96c4c 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -856,7 +856,7 @@ Node* AstGraphBuilder::Environment::Checkpoint( Node* result = graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, builder()->current_context(), builder()->GetFunctionClosure(), - builder()->jsgraph()->UndefinedConstant()); + builder()->graph()->start()); DCHECK(IsLivenessBlockConsistent()); if (liveness_block() != nullptr) { diff --git a/src/compiler/js-graph.cc b/src/compiler/js-graph.cc index 44d5c52..4d83c86 100644 --- a/src/compiler/js-graph.cc +++ b/src/compiler/js-graph.cc @@ -191,7 +191,7 @@ Node* JSGraph::EmptyFrameState() { common()->FrameState(JS_FRAME, BailoutId::None(), OutputFrameStateCombine::Ignore()), state_values, state_values, state_values, NoContextConstant(), - UndefinedConstant(), UndefinedConstant()); + UndefinedConstant(), graph()->start()); cached_nodes_[kEmptyFrameState] = empty_frame_state; } return empty_frame_state; diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc index 72f12fc..6964e5e 100644 --- a/src/compiler/js-inlining.cc +++ b/src/compiler/js-inlining.cc @@ -116,7 +116,8 @@ class CopyVisitor { }; -Reduction JSInliner::InlineCall(Node* call, Node* start, Node* end) { +Reduction JSInliner::InlineCall(Node* call, Node* frame_state, Node* start, + Node* end) { // The scheduler is smart enough to place our code; we just ensure {control} // becomes the control input of the start of the inlinee, and {effect} becomes // the effect input of the start of the inlinee. @@ -158,6 +159,8 @@ Reduction JSInliner::InlineCall(Node* call, Node* start, Node* end) { edge.UpdateTo(effect); } else if (NodeProperties::IsControlEdge(edge)) { edge.UpdateTo(control); + } else if (NodeProperties::IsFrameStateEdge(edge)) { + edge.UpdateTo(frame_state); } else { UNREACHABLE(); } @@ -284,7 +287,7 @@ Reduction JSInliner::Reduce(Node* node) { Node* start = visitor.GetCopy(graph.start()); Node* end = visitor.GetCopy(graph.end()); - Node* outer_frame_state = call.frame_state(); + Node* frame_state = call.frame_state(); size_t const inlinee_formal_parameters = start->op()->ValueOutputCount() - 3; // Insert argument adaptor frame if required. if (call.formal_arguments() != inlinee_formal_parameters) { @@ -294,22 +297,10 @@ Reduction JSInliner::Reduce(Node* node) { call.formal_arguments() < inlinee_formal_parameters) { return NoChange(); } - outer_frame_state = CreateArgumentsAdaptorFrameState(&call, info.zone()); + frame_state = CreateArgumentsAdaptorFrameState(&call, info.zone()); } - // Fix up all outer frame states from the inlinee. - for (Node* const node : visitor.copies()) { - if (node->opcode() == IrOpcode::kFrameState) { - DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); - // Don't touch this frame state, if it already has an "outer frame state". - if (NodeProperties::GetFrameStateInput(node, 0)->opcode() != - IrOpcode::kFrameState) { - NodeProperties::ReplaceFrameStateInput(node, 0, outer_frame_state); - } - } - } - - return InlineCall(node, start, end); + return InlineCall(node, frame_state, start, end); } } // namespace compiler diff --git a/src/compiler/js-inlining.h b/src/compiler/js-inlining.h index f7a0ba3..af82ed6 100644 --- a/src/compiler/js-inlining.h +++ b/src/compiler/js-inlining.h @@ -37,7 +37,7 @@ class JSInliner final : public AdvancedReducer { Node* CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call, Zone* temp_zone); - Reduction InlineCall(Node* call, Node* start, Node* end); + Reduction InlineCall(Node* call, Node* frame_state, Node* start, Node* end); }; } // namespace compiler diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index da94390..d258203 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -118,9 +118,9 @@ void Verifier::Visitor::Check(Node* node) { for (int i = 0; i < frame_state_count; i++) { Node* frame_state = NodeProperties::GetFrameStateInput(node, i); CHECK(frame_state->opcode() == IrOpcode::kFrameState || - // kFrameState uses undefined as a sentinel. + // kFrameState uses Start as a sentinel. (node->opcode() == IrOpcode::kFrameState && - frame_state->opcode() == IrOpcode::kHeapConstant)); + frame_state->opcode() == IrOpcode::kStart)); CHECK(IsDefUseChainLinkPresent(frame_state, node)); CHECK(IsUseDefChainLinkPresent(frame_state, node)); } diff --git a/test/cctest/compiler/test-run-inlining.cc b/test/cctest/compiler/test-run-inlining.cc index 2ab7217..3de929c 100644 --- a/test/cctest/compiler/test-run-inlining.cc +++ b/test/cctest/compiler/test-run-inlining.cc @@ -78,6 +78,20 @@ TEST(SimpleInliningDeopt) { } +TEST(SimpleInliningDeoptSelf) { + FunctionTester T( + "(function(){" + " function foo(s) { %_DeoptimizeNow(); return s; };" + " function bar(s, t) { return foo(s); };" + " return bar;" + "})();", + kInlineFlags); + + InstallAssertInlineCountHelper(CcTest::isolate()); + T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); +} + + TEST(SimpleInliningContext) { FunctionTester T( "(function () {" -- 2.7.4