Reviewers: Benedikt Meurer,
Description:
[turbofan] Make IfException projections consume effects.
This is needed in order to allow expansion a throwing node into a set
of nodes that produce different effects for the successful and the
exceptional continuation.
[email protected]
Please review this at https://codereview.chromium.org/1179543002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+58, -41 lines):
M src/compiler/ast-graph-builder.cc
M src/compiler/common-operator.cc
M src/compiler/graph-reducer.cc
M src/compiler/instruction-selector.cc
M src/compiler/node-properties.cc
M test/unittests/compiler/common-operator-unittest.cc
M test/unittests/compiler/graph-reducer-unittest.cc
M test/unittests/compiler/node-properties-unittest.cc
M test/unittests/compiler/scheduler-unittest.cc
M test/unittests/compiler/tail-call-optimization-unittest.cc
Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc
b/src/compiler/ast-graph-builder.cc
index
c5a9d232776748d7158919088a14bb76e579d3bf..43d402094539cfae9c31dd3f2f3395888a17db86
100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -3845,8 +3845,10 @@ Node* AstGraphBuilder::MakeNode(const Operator* op,
int value_input_count,
// Copy the environment for the success continuation.
Environment* success_env = environment()->CopyForConditional();
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_->UpdateEffectDependency(on_exception);
execution_control()->ThrowValue(on_exception);
set_environment(success_env);
}
Index: src/compiler/common-operator.cc
diff --git a/src/compiler/common-operator.cc
b/src/compiler/common-operator.cc
index
6e0ecfd6c1610f92545c6c1f7de4ccb01f553efe..a8cfbb3049f3035e5ac6a15bba3abc9bef890481
100644
--- a/src/compiler/common-operator.cc
+++ b/src/compiler/common-operator.cc
@@ -230,7 +230,7 @@ struct CommonOperatorGlobalCache final {
: Operator1<IfExceptionHint>( // --
IrOpcode::kIfException, Operator::kKontrol, // opcode
"IfException", // name
- 0, 0, 1, 1, 0, 1, // counts
+ 0, 1, 1, 1, 1, 1, // counts
kCaughtLocally) {} // parameter
};
IfExceptionOperator<IfExceptionHint::kLocallyCaught>
kIfExceptionCOperator;
Index: src/compiler/graph-reducer.cc
diff --git a/src/compiler/graph-reducer.cc b/src/compiler/graph-reducer.cc
index
0f347adbe1e0ec56d61d4b31b59e4d44e5b1dae8..2164d1e7c505e291e261fb2f21e8e88b84e38238
100644
--- a/src/compiler/graph-reducer.cc
+++ b/src/compiler/graph-reducer.cc
@@ -231,9 +231,10 @@ void GraphReducer::ReplaceWithValue(Node* node, Node*
value, Node* effect,
} else if (user->opcode() == IrOpcode::kIfException) {
for (Edge e : user->use_edges()) {
if (NodeProperties::IsValueEdge(e)) e.UpdateTo(dead_value_);
+ if (NodeProperties::IsEffectEdge(e))
e.UpdateTo(graph()->start());
if (NodeProperties::IsControlEdge(e)) e.UpdateTo(dead_control_);
}
- user->Kill();
+ edge.UpdateTo(user);
} else {
UNREACHABLE();
}
@@ -242,6 +243,7 @@ void GraphReducer::ReplaceWithValue(Node* node, Node*
value, Node* effect,
edge.UpdateTo(effect);
Revisit(user);
} else {
+ DCHECK_NOT_NULL(value);
edge.UpdateTo(value);
Revisit(user);
}
Index: src/compiler/instruction-selector.cc
diff --git a/src/compiler/instruction-selector.cc
b/src/compiler/instruction-selector.cc
index
1c1f3fafd7f11bbe659c093226e3231ed100e19c..13a76da12ae0c6f090b288395dec147cf707b45e
100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -931,7 +931,7 @@ void InstructionSelector::VisitParameter(Node* node) {
void InstructionSelector::VisitIfException(Node* node) {
OperandGenerator g(this);
- Node* call = node->InputAt(0);
+ Node* call = node->InputAt(1);
DCHECK_EQ(IrOpcode::kCall, call->opcode());
const CallDescriptor* descriptor = OpParameter<const
CallDescriptor*>(call);
Emit(kArchNop, g.DefineAsLocation(node, descriptor->GetReturnLocation(0),
Index: src/compiler/node-properties.cc
diff --git a/src/compiler/node-properties.cc
b/src/compiler/node-properties.cc
index
eb216781d18fae37fd765194873cb4677e11c456..ac768a7d37f1781f8404c8ad0414ba93997bda8b
100644
--- a/src/compiler/node-properties.cc
+++ b/src/compiler/node-properties.cc
@@ -214,7 +214,9 @@ void NodeProperties::CollectControlProjections(Node*
node, Node** projections,
std::memset(projections, 0, sizeof(*projections) * projection_count);
#endif
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;
switch (use->opcode()) {
case IrOpcode::kIfTrue:
Index: test/unittests/compiler/common-operator-unittest.cc
diff --git a/test/unittests/compiler/common-operator-unittest.cc
b/test/unittests/compiler/common-operator-unittest.cc
index
2d1e0dcc30694b5e0bf84b4533ae0fc38a6d5d3b..26e861c1b67684cb7b8fa040318dd1c20c6dd642
100644
--- a/test/unittests/compiler/common-operator-unittest.cc
+++ b/test/unittests/compiler/common-operator-unittest.cc
@@ -225,11 +225,11 @@ TEST_F(CommonOperatorTest, IfException) {
EXPECT_EQ(IrOpcode::kIfException, op->opcode());
EXPECT_EQ(Operator::kKontrol, op->properties());
EXPECT_EQ(0, op->ValueInputCount());
- EXPECT_EQ(0, op->EffectInputCount());
+ EXPECT_EQ(1, op->EffectInputCount());
EXPECT_EQ(1, op->ControlInputCount());
- EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
+ EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(1, op->ValueOutputCount());
- EXPECT_EQ(0, op->EffectOutputCount());
+ EXPECT_EQ(1, op->EffectOutputCount());
EXPECT_EQ(1, op->ControlOutputCount());
}
}
Index: test/unittests/compiler/graph-reducer-unittest.cc
diff --git a/test/unittests/compiler/graph-reducer-unittest.cc
b/test/unittests/compiler/graph-reducer-unittest.cc
index
d3e97975786d8c30cb9af5dd11dbb1f32dfd7b04..06befae59efbde0c541897567399dae7daf27902
100644
--- a/test/unittests/compiler/graph-reducer-unittest.cc
+++ b/test/unittests/compiler/graph-reducer-unittest.cc
@@ -340,10 +340,11 @@ TEST_F(AdvancedReducerTest,
ReplaceWithValue_ControlUse1) {
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) {
CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1));
+ Node* effect = graph()->NewNode(&kMockOperator);
Node* dead = graph()->NewNode(&kMockOperator);
Node* node = graph()->NewNode(&kMockOpControl, start);
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_exception_control = graph()->NewNode(common.Merge(1),
exception);
Node* replacement = graph()->NewNode(&kMockOperator);
@@ -364,10 +365,11 @@ TEST_F(AdvancedReducerTest,
ReplaceWithValue_ControlUse2) {
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) {
CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1));
+ Node* effect = graph()->NewNode(&kMockOperator);
Node* dead = graph()->NewNode(&kMockOperator);
Node* node = graph()->NewNode(&kMockOpControl, start);
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_exception_value = graph()->NewNode(common.Return(), exception);
Node* replacement = graph()->NewNode(&kMockOperator);
Index: test/unittests/compiler/node-properties-unittest.cc
diff --git a/test/unittests/compiler/node-properties-unittest.cc
b/test/unittests/compiler/node-properties-unittest.cc
index
bcc21384155ea8035e935b9898612aa136694b0b..463948d43f4e33de2d05901d1c943ded2b97ae15
100644
--- a/test/unittests/compiler/node-properties-unittest.cc
+++ b/test/unittests/compiler/node-properties-unittest.cc
@@ -17,8 +17,16 @@ namespace compiler {
class NodePropertiesTest : public TestWithZone {
public:
- Node* NewMockNode(const Operator* op, int input_count, Node** inputs) {
- return Node::New(zone(), 0, op, input_count, inputs, false);
+ Node* NewMockNode(const Operator* op) {
+ 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,
const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
"MockCallOperator", 0, 0, 0, 0, 0, 2);
+const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
+
} // namespace
TEST_F(NodePropertiesTest, ReplaceUses) {
CommonOperatorBuilder common(zone());
- IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
- Node* node = NewMockNode(&kMockOperator, 0, nullptr);
- Node* use_value = NewMockNode(common.Return(), 1, &node);
- Node* use_effect = NewMockNode(common.EffectPhi(1), 1, &node);
- Node* use_success = NewMockNode(common.IfSuccess(), 1, &node);
- Node* use_exception = NewMockNode(common.IfException(kNoHint), 1, &node);
- Node* r_value = NewMockNode(&kMockOperator, 0, nullptr);
- Node* r_effect = NewMockNode(&kMockOperator, 0, nullptr);
- Node* r_success = NewMockNode(&kMockOperator, 0, nullptr);
- Node* r_exception = NewMockNode(&kMockOperator, 0, nullptr);
+ Node* node = NewMockNode(&kMockOperator);
+ Node* effect = NewMockNode(&kMockOperator);
+ Node* use_value = NewMockNode(common.Return(), node);
+ Node* use_effect = NewMockNode(common.EffectPhi(1), node);
+ Node* use_success = NewMockNode(common.IfSuccess(), node);
+ Node* use_exception = NewMockNode(common.IfException(kNoHint), effect,
node);
+ Node* r_value = NewMockNode(&kMockOperator);
+ Node* r_effect = NewMockNode(&kMockOperator);
+ Node* r_success = NewMockNode(&kMockOperator);
+ Node* r_exception = NewMockNode(&kMockOperator);
NodeProperties::ReplaceUses(node, r_value, r_effect, r_success,
r_exception);
EXPECT_EQ(r_value, use_value->InputAt(0));
EXPECT_EQ(r_effect, use_effect->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(1, r_value->UseCount());
EXPECT_EQ(1, r_effect->UseCount());
@@ -63,9 +73,9 @@ TEST_F(NodePropertiesTest, ReplaceUses) {
TEST_F(NodePropertiesTest, FindProjection) {
CommonOperatorBuilder common(zone());
- Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
- Node* proj0 = Node::New(zone(), 1, common.Projection(0), 1, &start,
false);
- Node* proj1 = Node::New(zone(), 2, common.Projection(1), 1, &start,
false);
+ Node* start = NewMockNode(common.Start(1));
+ Node* proj0 = NewMockNode(common.Projection(0), start);
+ Node* proj1 = NewMockNode(common.Projection(1), start);
EXPECT_EQ(proj0, NodeProperties::FindProjection(start, 0));
EXPECT_EQ(proj1, NodeProperties::FindProjection(start, 1));
EXPECT_THAT(NodeProperties::FindProjection(start, 2), IsNull());
@@ -76,9 +86,9 @@ TEST_F(NodePropertiesTest, FindProjection) {
TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
Node* result[2];
CommonOperatorBuilder common(zone());
- Node* branch = Node::New(zone(), 1, common.Branch(), 0, nullptr, false);
- Node* if_false = Node::New(zone(), 2, common.IfFalse(), 1, &branch,
false);
- Node* if_true = Node::New(zone(), 3, common.IfTrue(), 1, &branch, false);
+ Node* branch = NewMockNode(common.Branch());
+ Node* if_false = NewMockNode(common.IfFalse(), branch);
+ Node* if_true = NewMockNode(common.IfTrue(), branch);
NodeProperties::CollectControlProjections(branch, result,
arraysize(result));
EXPECT_EQ(if_true, result[0]);
EXPECT_EQ(if_false, result[1]);
@@ -88,10 +98,9 @@ TEST_F(NodePropertiesTest,
CollectControlProjections_Branch) {
TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
Node* result[2];
CommonOperatorBuilder common(zone());
- IfExceptionHint h = IfExceptionHint::kLocallyUncaught;
- Node* call = Node::New(zone(), 1, &kMockCallOperator, 0, nullptr, false);
- Node* if_ex = Node::New(zone(), 2, common.IfException(h), 1, &call,
false);
- Node* if_ok = Node::New(zone(), 3, common.IfSuccess(), 1, &call, false);
+ Node* call = NewMockNode(&kMockCallOperator);
+ Node* if_ex = NewMockNode(common.IfException(kNoHint), call, call);
+ Node* if_ok = NewMockNode(common.IfSuccess(), call);
NodeProperties::CollectControlProjections(call, result,
arraysize(result));
EXPECT_EQ(if_ok, result[0]);
EXPECT_EQ(if_ex, result[1]);
@@ -101,10 +110,10 @@ TEST_F(NodePropertiesTest,
CollectControlProjections_Call) {
TEST_F(NodePropertiesTest, CollectControlProjections_Switch) {
Node* result[3];
CommonOperatorBuilder common(zone());
- Node* sw = Node::New(zone(), 1, common.Switch(3), 0, nullptr, false);
- Node* if_default = Node::New(zone(), 2, common.IfDefault(), 1, &sw,
false);
- Node* if_value1 = Node::New(zone(), 3, common.IfValue(1), 1, &sw, false);
- Node* if_value2 = Node::New(zone(), 4, common.IfValue(2), 1, &sw, false);
+ Node* sw = NewMockNode(common.Switch(3));
+ Node* if_default = NewMockNode(common.IfDefault(), sw);
+ Node* if_value1 = NewMockNode(common.IfValue(1), sw);
+ Node* if_value2 = NewMockNode(common.IfValue(2), sw);
NodeProperties::CollectControlProjections(sw, result, arraysize(result));
EXPECT_THAT(result[0], AnyOf(if_value1, if_value2));
EXPECT_THAT(result[1], AnyOf(if_value1, if_value2));
Index: test/unittests/compiler/scheduler-unittest.cc
diff --git a/test/unittests/compiler/scheduler-unittest.cc
b/test/unittests/compiler/scheduler-unittest.cc
index
b94cb03c00c44ba75e3e91f3bf5d6efd5d35ea27..45c636b27a7e9d2b1b09679110f6d181b1c0e115
100644
--- a/test/unittests/compiler/scheduler-unittest.cc
+++ b/test/unittests/compiler/scheduler-unittest.cc
@@ -1060,11 +1060,11 @@ TARGET_TEST_F(SchedulerTest, CallException) {
Node* c1 = graph()->NewNode(&kMockCall, start);
Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1);
Node* ex1 = graph()->NewNode(
- common()->IfException(IfExceptionHint::kLocallyUncaught), c1);
+ common()->IfException(IfExceptionHint::kLocallyUncaught), c1, c1);
Node* c2 = graph()->NewNode(&kMockCall, ok1);
Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2);
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* m = graph()->NewNode(common()->Merge(2), ok2, hdl);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0,
m);
Index: test/unittests/compiler/tail-call-optimization-unittest.cc
diff --git a/test/unittests/compiler/tail-call-optimization-unittest.cc
b/test/unittests/compiler/tail-call-optimization-unittest.cc
index
37e37d5182d9f2465ed42be351ba62877c772fae..b8f38602e86c0615e360402573fa3cbe1435714c
100644
--- a/test/unittests/compiler/tail-call-optimization-unittest.cc
+++ b/test/unittests/compiler/tail-call-optimization-unittest.cc
@@ -60,7 +60,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) {
graph()->start(), graph()->start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
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* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end);
@@ -126,7 +126,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) {
graph()->start(), graph()->start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
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* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end);
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.