[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}
This commit is contained in:
parent
cc2d376f11
commit
7483dbd5fc
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 () {"
|
||||
|
Loading…
Reference in New Issue
Block a user