Commit 3548c5c6 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Make IfException projections consume effects.

This is needed in order to allow expansion of a throwing node into a
set of nodes that produce different effects for the successful and the
exceptional continuation.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1179543002

Cr-Commit-Position: refs/heads/master@{#28918}
parent ec4baaed
...@@ -3845,8 +3845,10 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, ...@@ -3845,8 +3845,10 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
// Copy the environment for the success continuation. // Copy the environment for the success continuation.
Environment* success_env = environment()->CopyForConditional(); Environment* success_env = environment()->CopyForConditional();
const Operator* op = common()->IfException(hint); const Operator* op = common()->IfException(hint);
Node* on_exception = graph()->NewNode(op, result); Node* effect = environment()->GetEffectDependency();
Node* on_exception = graph()->NewNode(op, effect, result);
environment_->UpdateControlDependency(on_exception); environment_->UpdateControlDependency(on_exception);
environment_->UpdateEffectDependency(on_exception);
execution_control()->ThrowValue(on_exception); execution_control()->ThrowValue(on_exception);
set_environment(success_env); set_environment(success_env);
} }
......
...@@ -230,7 +230,7 @@ struct CommonOperatorGlobalCache final { ...@@ -230,7 +230,7 @@ struct CommonOperatorGlobalCache final {
: Operator1<IfExceptionHint>( // -- : Operator1<IfExceptionHint>( // --
IrOpcode::kIfException, Operator::kKontrol, // opcode IrOpcode::kIfException, Operator::kKontrol, // opcode
"IfException", // name "IfException", // name
0, 0, 1, 1, 0, 1, // counts 0, 1, 1, 1, 1, 1, // counts
kCaughtLocally) {} // parameter kCaughtLocally) {} // parameter
}; };
IfExceptionOperator<IfExceptionHint::kLocallyCaught> kIfExceptionCOperator; IfExceptionOperator<IfExceptionHint::kLocallyCaught> kIfExceptionCOperator;
......
...@@ -231,9 +231,10 @@ void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect, ...@@ -231,9 +231,10 @@ void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect,
} else if (user->opcode() == IrOpcode::kIfException) { } else if (user->opcode() == IrOpcode::kIfException) {
for (Edge e : user->use_edges()) { for (Edge e : user->use_edges()) {
if (NodeProperties::IsValueEdge(e)) e.UpdateTo(dead_value_); if (NodeProperties::IsValueEdge(e)) e.UpdateTo(dead_value_);
if (NodeProperties::IsEffectEdge(e)) e.UpdateTo(graph()->start());
if (NodeProperties::IsControlEdge(e)) e.UpdateTo(dead_control_); if (NodeProperties::IsControlEdge(e)) e.UpdateTo(dead_control_);
} }
user->Kill(); edge.UpdateTo(user);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
...@@ -242,6 +243,7 @@ void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect, ...@@ -242,6 +243,7 @@ void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect,
edge.UpdateTo(effect); edge.UpdateTo(effect);
Revisit(user); Revisit(user);
} else { } else {
DCHECK_NOT_NULL(value);
edge.UpdateTo(value); edge.UpdateTo(value);
Revisit(user); Revisit(user);
} }
......
...@@ -931,7 +931,7 @@ void InstructionSelector::VisitParameter(Node* node) { ...@@ -931,7 +931,7 @@ void InstructionSelector::VisitParameter(Node* node) {
void InstructionSelector::VisitIfException(Node* node) { void InstructionSelector::VisitIfException(Node* node) {
OperandGenerator g(this); OperandGenerator g(this);
Node* call = node->InputAt(0); Node* call = node->InputAt(1);
DCHECK_EQ(IrOpcode::kCall, call->opcode()); DCHECK_EQ(IrOpcode::kCall, call->opcode());
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(call); const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(call);
Emit(kArchNop, g.DefineAsLocation(node, descriptor->GetReturnLocation(0), Emit(kArchNop, g.DefineAsLocation(node, descriptor->GetReturnLocation(0),
......
...@@ -214,7 +214,9 @@ void NodeProperties::CollectControlProjections(Node* node, Node** projections, ...@@ -214,7 +214,9 @@ void NodeProperties::CollectControlProjections(Node* node, Node** projections,
std::memset(projections, 0, sizeof(*projections) * projection_count); std::memset(projections, 0, sizeof(*projections) * projection_count);
#endif #endif
size_t if_value_index = 0; size_t if_value_index = 0;
for (Node* const use : node->uses()) { for (Edge const edge : node->use_edges()) {
if (!IsControlEdge(edge)) continue;
Node* use = edge.from();
size_t index; size_t index;
switch (use->opcode()) { switch (use->opcode()) {
case IrOpcode::kIfTrue: case IrOpcode::kIfTrue:
......
...@@ -225,11 +225,11 @@ TEST_F(CommonOperatorTest, IfException) { ...@@ -225,11 +225,11 @@ TEST_F(CommonOperatorTest, IfException) {
EXPECT_EQ(IrOpcode::kIfException, op->opcode()); EXPECT_EQ(IrOpcode::kIfException, op->opcode());
EXPECT_EQ(Operator::kKontrol, op->properties()); EXPECT_EQ(Operator::kKontrol, op->properties());
EXPECT_EQ(0, op->ValueInputCount()); EXPECT_EQ(0, op->ValueInputCount());
EXPECT_EQ(0, op->EffectInputCount()); EXPECT_EQ(1, op->EffectInputCount());
EXPECT_EQ(1, op->ControlInputCount()); EXPECT_EQ(1, op->ControlInputCount());
EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(1, op->ValueOutputCount()); EXPECT_EQ(1, op->ValueOutputCount());
EXPECT_EQ(0, op->EffectOutputCount()); EXPECT_EQ(1, op->EffectOutputCount());
EXPECT_EQ(1, op->ControlOutputCount()); EXPECT_EQ(1, op->ControlOutputCount());
} }
} }
......
...@@ -340,10 +340,11 @@ TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse1) { ...@@ -340,10 +340,11 @@ TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse1) {
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) { TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) {
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1)); Node* start = graph()->NewNode(common.Start(1));
Node* effect = graph()->NewNode(&kMockOperator);
Node* dead = graph()->NewNode(&kMockOperator); Node* dead = graph()->NewNode(&kMockOperator);
Node* node = graph()->NewNode(&kMockOpControl, start); Node* node = graph()->NewNode(&kMockOpControl, start);
Node* success = graph()->NewNode(common.IfSuccess(), node); Node* success = graph()->NewNode(common.IfSuccess(), node);
Node* exception = graph()->NewNode(common.IfException(kNoHint), node); Node* exception = graph()->NewNode(common.IfException(kNoHint), effect, node);
Node* use_control = graph()->NewNode(common.Merge(1), success); Node* use_control = graph()->NewNode(common.Merge(1), success);
Node* use_exception_control = graph()->NewNode(common.Merge(1), exception); Node* use_exception_control = graph()->NewNode(common.Merge(1), exception);
Node* replacement = graph()->NewNode(&kMockOperator); Node* replacement = graph()->NewNode(&kMockOperator);
...@@ -364,10 +365,11 @@ TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) { ...@@ -364,10 +365,11 @@ TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) {
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) { TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) {
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1)); Node* start = graph()->NewNode(common.Start(1));
Node* effect = graph()->NewNode(&kMockOperator);
Node* dead = graph()->NewNode(&kMockOperator); Node* dead = graph()->NewNode(&kMockOperator);
Node* node = graph()->NewNode(&kMockOpControl, start); Node* node = graph()->NewNode(&kMockOpControl, start);
Node* success = graph()->NewNode(common.IfSuccess(), node); Node* success = graph()->NewNode(common.IfSuccess(), node);
Node* exception = graph()->NewNode(common.IfException(kNoHint), node); Node* exception = graph()->NewNode(common.IfException(kNoHint), effect, node);
Node* use_control = graph()->NewNode(common.Merge(1), success); Node* use_control = graph()->NewNode(common.Merge(1), success);
Node* use_exception_value = graph()->NewNode(common.Return(), exception); Node* use_exception_value = graph()->NewNode(common.Return(), exception);
Node* replacement = graph()->NewNode(&kMockOperator); Node* replacement = graph()->NewNode(&kMockOperator);
......
...@@ -17,8 +17,16 @@ namespace compiler { ...@@ -17,8 +17,16 @@ namespace compiler {
class NodePropertiesTest : public TestWithZone { class NodePropertiesTest : public TestWithZone {
public: public:
Node* NewMockNode(const Operator* op, int input_count, Node** inputs) { Node* NewMockNode(const Operator* op) {
return Node::New(zone(), 0, op, input_count, inputs, false); return Node::New(zone(), 0, op, 0, nullptr, false);
}
Node* NewMockNode(const Operator* op, Node* n1) {
Node* nodes[] = {n1};
return Node::New(zone(), 0, op, arraysize(nodes), nodes, false);
}
Node* NewMockNode(const Operator* op, Node* n1, Node* n2) {
Node* nodes[] = {n1, n2};
return Node::New(zone(), 0, op, arraysize(nodes), nodes, false);
} }
}; };
...@@ -29,26 +37,28 @@ const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties, ...@@ -29,26 +37,28 @@ const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties, const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
"MockCallOperator", 0, 0, 0, 0, 0, 2); "MockCallOperator", 0, 0, 0, 0, 0, 2);
const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
} // namespace } // namespace
TEST_F(NodePropertiesTest, ReplaceUses) { TEST_F(NodePropertiesTest, ReplaceUses) {
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught; Node* node = NewMockNode(&kMockOperator);
Node* node = NewMockNode(&kMockOperator, 0, nullptr); Node* effect = NewMockNode(&kMockOperator);
Node* use_value = NewMockNode(common.Return(), 1, &node); Node* use_value = NewMockNode(common.Return(), node);
Node* use_effect = NewMockNode(common.EffectPhi(1), 1, &node); Node* use_effect = NewMockNode(common.EffectPhi(1), node);
Node* use_success = NewMockNode(common.IfSuccess(), 1, &node); Node* use_success = NewMockNode(common.IfSuccess(), node);
Node* use_exception = NewMockNode(common.IfException(kNoHint), 1, &node); Node* use_exception = NewMockNode(common.IfException(kNoHint), effect, node);
Node* r_value = NewMockNode(&kMockOperator, 0, nullptr); Node* r_value = NewMockNode(&kMockOperator);
Node* r_effect = NewMockNode(&kMockOperator, 0, nullptr); Node* r_effect = NewMockNode(&kMockOperator);
Node* r_success = NewMockNode(&kMockOperator, 0, nullptr); Node* r_success = NewMockNode(&kMockOperator);
Node* r_exception = NewMockNode(&kMockOperator, 0, nullptr); Node* r_exception = NewMockNode(&kMockOperator);
NodeProperties::ReplaceUses(node, r_value, r_effect, r_success, r_exception); NodeProperties::ReplaceUses(node, r_value, r_effect, r_success, r_exception);
EXPECT_EQ(r_value, use_value->InputAt(0)); EXPECT_EQ(r_value, use_value->InputAt(0));
EXPECT_EQ(r_effect, use_effect->InputAt(0)); EXPECT_EQ(r_effect, use_effect->InputAt(0));
EXPECT_EQ(r_success, use_success->InputAt(0)); EXPECT_EQ(r_success, use_success->InputAt(0));
EXPECT_EQ(r_exception, use_exception->InputAt(0)); EXPECT_EQ(r_exception, use_exception->InputAt(1));
EXPECT_EQ(0, node->UseCount()); EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(1, r_value->UseCount()); EXPECT_EQ(1, r_value->UseCount());
EXPECT_EQ(1, r_effect->UseCount()); EXPECT_EQ(1, r_effect->UseCount());
...@@ -63,9 +73,9 @@ TEST_F(NodePropertiesTest, ReplaceUses) { ...@@ -63,9 +73,9 @@ TEST_F(NodePropertiesTest, ReplaceUses) {
TEST_F(NodePropertiesTest, FindProjection) { TEST_F(NodePropertiesTest, FindProjection) {
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false); Node* start = NewMockNode(common.Start(1));
Node* proj0 = Node::New(zone(), 1, common.Projection(0), 1, &start, false); Node* proj0 = NewMockNode(common.Projection(0), start);
Node* proj1 = Node::New(zone(), 2, common.Projection(1), 1, &start, false); Node* proj1 = NewMockNode(common.Projection(1), start);
EXPECT_EQ(proj0, NodeProperties::FindProjection(start, 0)); EXPECT_EQ(proj0, NodeProperties::FindProjection(start, 0));
EXPECT_EQ(proj1, NodeProperties::FindProjection(start, 1)); EXPECT_EQ(proj1, NodeProperties::FindProjection(start, 1));
EXPECT_THAT(NodeProperties::FindProjection(start, 2), IsNull()); EXPECT_THAT(NodeProperties::FindProjection(start, 2), IsNull());
...@@ -76,9 +86,9 @@ TEST_F(NodePropertiesTest, FindProjection) { ...@@ -76,9 +86,9 @@ TEST_F(NodePropertiesTest, FindProjection) {
TEST_F(NodePropertiesTest, CollectControlProjections_Branch) { TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
Node* result[2]; Node* result[2];
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
Node* branch = Node::New(zone(), 1, common.Branch(), 0, nullptr, false); Node* branch = NewMockNode(common.Branch());
Node* if_false = Node::New(zone(), 2, common.IfFalse(), 1, &branch, false); Node* if_false = NewMockNode(common.IfFalse(), branch);
Node* if_true = Node::New(zone(), 3, common.IfTrue(), 1, &branch, false); Node* if_true = NewMockNode(common.IfTrue(), branch);
NodeProperties::CollectControlProjections(branch, result, arraysize(result)); NodeProperties::CollectControlProjections(branch, result, arraysize(result));
EXPECT_EQ(if_true, result[0]); EXPECT_EQ(if_true, result[0]);
EXPECT_EQ(if_false, result[1]); EXPECT_EQ(if_false, result[1]);
...@@ -88,10 +98,9 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Branch) { ...@@ -88,10 +98,9 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
TEST_F(NodePropertiesTest, CollectControlProjections_Call) { TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
Node* result[2]; Node* result[2];
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
IfExceptionHint h = IfExceptionHint::kLocallyUncaught; Node* call = NewMockNode(&kMockCallOperator);
Node* call = Node::New(zone(), 1, &kMockCallOperator, 0, nullptr, false); Node* if_ex = NewMockNode(common.IfException(kNoHint), call, call);
Node* if_ex = Node::New(zone(), 2, common.IfException(h), 1, &call, false); Node* if_ok = NewMockNode(common.IfSuccess(), call);
Node* if_ok = Node::New(zone(), 3, common.IfSuccess(), 1, &call, false);
NodeProperties::CollectControlProjections(call, result, arraysize(result)); NodeProperties::CollectControlProjections(call, result, arraysize(result));
EXPECT_EQ(if_ok, result[0]); EXPECT_EQ(if_ok, result[0]);
EXPECT_EQ(if_ex, result[1]); EXPECT_EQ(if_ex, result[1]);
...@@ -101,10 +110,10 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Call) { ...@@ -101,10 +110,10 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
TEST_F(NodePropertiesTest, CollectControlProjections_Switch) { TEST_F(NodePropertiesTest, CollectControlProjections_Switch) {
Node* result[3]; Node* result[3];
CommonOperatorBuilder common(zone()); CommonOperatorBuilder common(zone());
Node* sw = Node::New(zone(), 1, common.Switch(3), 0, nullptr, false); Node* sw = NewMockNode(common.Switch(3));
Node* if_default = Node::New(zone(), 2, common.IfDefault(), 1, &sw, false); Node* if_default = NewMockNode(common.IfDefault(), sw);
Node* if_value1 = Node::New(zone(), 3, common.IfValue(1), 1, &sw, false); Node* if_value1 = NewMockNode(common.IfValue(1), sw);
Node* if_value2 = Node::New(zone(), 4, common.IfValue(2), 1, &sw, false); Node* if_value2 = NewMockNode(common.IfValue(2), sw);
NodeProperties::CollectControlProjections(sw, result, arraysize(result)); NodeProperties::CollectControlProjections(sw, result, arraysize(result));
EXPECT_THAT(result[0], AnyOf(if_value1, if_value2)); EXPECT_THAT(result[0], AnyOf(if_value1, if_value2));
EXPECT_THAT(result[1], AnyOf(if_value1, if_value2)); EXPECT_THAT(result[1], AnyOf(if_value1, if_value2));
......
...@@ -1060,11 +1060,11 @@ TARGET_TEST_F(SchedulerTest, CallException) { ...@@ -1060,11 +1060,11 @@ TARGET_TEST_F(SchedulerTest, CallException) {
Node* c1 = graph()->NewNode(&kMockCall, start); Node* c1 = graph()->NewNode(&kMockCall, start);
Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1); Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1);
Node* ex1 = graph()->NewNode( Node* ex1 = graph()->NewNode(
common()->IfException(IfExceptionHint::kLocallyUncaught), c1); common()->IfException(IfExceptionHint::kLocallyUncaught), c1, c1);
Node* c2 = graph()->NewNode(&kMockCall, ok1); Node* c2 = graph()->NewNode(&kMockCall, ok1);
Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2); Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2);
Node* ex2 = graph()->NewNode( Node* ex2 = graph()->NewNode(
common()->IfException(IfExceptionHint::kLocallyUncaught), c2); common()->IfException(IfExceptionHint::kLocallyUncaught), c2, c2);
Node* hdl = graph()->NewNode(common()->Merge(2), ex1, ex2); Node* hdl = graph()->NewNode(common()->Merge(2), ex1, ex2);
Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl); Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0, m); Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0, m);
......
...@@ -60,7 +60,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) { ...@@ -60,7 +60,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) {
graph()->start(), graph()->start()); graph()->start(), graph()->start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), call); Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
Node* if_exception = graph()->NewNode( Node* if_exception = graph()->NewNode(
common()->IfException(IfExceptionHint::kLocallyUncaught), call); common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
Node* end = graph()->NewNode(common()->End(1), if_exception); Node* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end); graph()->SetEnd(end);
...@@ -126,7 +126,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) { ...@@ -126,7 +126,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) {
graph()->start(), graph()->start()); graph()->start(), graph()->start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), call); Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
Node* if_exception = graph()->NewNode( Node* if_exception = graph()->NewNode(
common()->IfException(IfExceptionHint::kLocallyUncaught), call); common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
Node* end = graph()->NewNode(common()->End(1), if_exception); Node* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end); graph()->SetEnd(end);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment