Commit 8f4d9a0a authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Allow ReplaceWithValue to kill control.

This allows any AdvancedReducer to remove exception projections from
graphs. This is the common case when JS-operators are being replaced
with pure values. The old NodeProperties::ReplaceWithValue is being
deprecated in favor of AdvancedReducer::ReplaceWithValue.

R=titzer@chromium.org
TEST=unittests/AdvancedReducerTest

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

Cr-Commit-Position: refs/heads/master@{#28810}
parent 16bbd48f
...@@ -425,7 +425,7 @@ class ControlReducerImpl final : public AdvancedReducer { ...@@ -425,7 +425,7 @@ class ControlReducerImpl final : public AdvancedReducer {
void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph, void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph,
int max_phis_for_select) { int max_phis_for_select) {
GraphReducer graph_reducer(jsgraph->graph(), zone); GraphReducer graph_reducer(zone, jsgraph->graph());
ControlReducerImpl impl(&graph_reducer, zone, jsgraph); ControlReducerImpl impl(&graph_reducer, zone, jsgraph);
impl.max_phis_for_select_ = max_phis_for_select; impl.max_phis_for_select_ = max_phis_for_select;
graph_reducer.AddReducer(&impl); graph_reducer.AddReducer(&impl);
......
...@@ -25,8 +25,11 @@ enum class GraphReducer::State : uint8_t { ...@@ -25,8 +25,11 @@ enum class GraphReducer::State : uint8_t {
}; };
GraphReducer::GraphReducer(Graph* graph, Zone* zone) GraphReducer::GraphReducer(Zone* zone, Graph* graph, Node* dead_value,
Node* dead_control)
: graph_(graph), : graph_(graph),
dead_value_(dead_value),
dead_control_(dead_control),
state_(graph, 4), state_(graph, 4),
reducers_(zone), reducers_(zone),
revisit_(zone), revisit_(zone),
...@@ -212,7 +215,7 @@ void GraphReducer::Replace(Node* node, Node* replacement, NodeId max_id) { ...@@ -212,7 +215,7 @@ void GraphReducer::Replace(Node* node, Node* replacement, NodeId max_id) {
void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect, void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect,
Node* control) { Node* control) {
if (!effect && node->op()->EffectInputCount() > 0) { if (effect == nullptr && node->op()->EffectInputCount() > 0) {
effect = NodeProperties::GetEffectInput(node); effect = NodeProperties::GetEffectInput(node);
} }
if (control == nullptr && node->op()->ControlInputCount() > 0) { if (control == nullptr && node->op()->ControlInputCount() > 0) {
...@@ -226,9 +229,11 @@ void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect, ...@@ -226,9 +229,11 @@ void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect,
if (user->opcode() == IrOpcode::kIfSuccess) { if (user->opcode() == IrOpcode::kIfSuccess) {
Replace(user, control); Replace(user, control);
} else if (user->opcode() == IrOpcode::kIfException) { } else if (user->opcode() == IrOpcode::kIfException) {
// TODO(titzer): replace with dead control from JSGraph, and for (Edge e : user->use_edges()) {
// require the control reducer to propagate it. if (NodeProperties::IsValueEdge(e)) e.UpdateTo(dead_value_);
UNREACHABLE(); if (NodeProperties::IsControlEdge(e)) e.UpdateTo(dead_control_);
}
user->Kill();
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -77,9 +77,8 @@ class AdvancedReducer : public Reducer { ...@@ -77,9 +77,8 @@ class AdvancedReducer : public Reducer {
// Replace value uses of {node} with {value} and effect uses of {node} with // Replace value uses of {node} with {value} and effect uses of {node} with
// {effect}. If {effect == NULL}, then use the effect input to {node}. All // {effect}. If {effect == NULL}, then use the effect input to {node}. All
// control uses will be relaxed assuming {node} cannot throw. // control uses will be relaxed assuming {node} cannot throw.
virtual void ReplaceWithValue(Node* node, Node* value, virtual void ReplaceWithValue(Node* node, Node* value, Node* effect,
Node* effect = nullptr, Node* control) = 0;
Node* control = nullptr) = 0;
}; };
explicit AdvancedReducer(Editor* editor) : editor_(editor) {} explicit AdvancedReducer(Editor* editor) : editor_(editor) {}
...@@ -107,15 +106,13 @@ class AdvancedReducer : public Reducer { ...@@ -107,15 +106,13 @@ class AdvancedReducer : public Reducer {
// uses of {node} with the effect and control input to {node}. // uses of {node} with the effect and control input to {node}.
// TODO(turbofan): replace the effect input to {node} with {graph->start()}. // TODO(turbofan): replace the effect input to {node} with {graph->start()}.
void RelaxEffectsAndControls(Node* node) { void RelaxEffectsAndControls(Node* node) {
DCHECK_NOT_NULL(editor_); ReplaceWithValue(node, node, nullptr, nullptr);
editor_->ReplaceWithValue(node, node, nullptr, nullptr);
} }
// Relax the control uses of {node} by immediately replacing them with the // Relax the control uses of {node} by immediately replacing them with the
// control input to {node}. // control input to {node}.
void RelaxControls(Node* node) { void RelaxControls(Node* node) {
DCHECK_NOT_NULL(editor_); ReplaceWithValue(node, node, node, nullptr);
editor_->ReplaceWithValue(node, node, node, nullptr);
} }
private: private:
...@@ -124,10 +121,11 @@ class AdvancedReducer : public Reducer { ...@@ -124,10 +121,11 @@ class AdvancedReducer : public Reducer {
// Performs an iterative reduction of a node graph. // Performs an iterative reduction of a node graph.
class GraphReducer final : public AdvancedReducer::Editor { class GraphReducer : public AdvancedReducer::Editor {
public: public:
GraphReducer(Graph* graph, Zone* zone); GraphReducer(Zone* zone, Graph* graph, Node* dead_value = nullptr,
~GraphReducer() final; Node* dead_control = nullptr);
~GraphReducer();
Graph* graph() const { return graph_; } Graph* graph() const { return graph_; }
...@@ -156,8 +154,8 @@ class GraphReducer final : public AdvancedReducer::Editor { ...@@ -156,8 +154,8 @@ class GraphReducer final : public AdvancedReducer::Editor {
// Replace value uses of {node} with {value} and effect uses of {node} with // Replace value uses of {node} with {value} and effect uses of {node} with
// {effect}. If {effect == NULL}, then use the effect input to {node}. All // {effect}. If {effect == NULL}, then use the effect input to {node}. All
// control uses will be relaxed assuming {node} cannot throw. // control uses will be relaxed assuming {node} cannot throw.
void ReplaceWithValue(Node* node, Node* value, Node* effect = nullptr, void ReplaceWithValue(Node* node, Node* value, Node* effect,
Node* control = nullptr) final; Node* control) final;
// Replace all uses of {node} with {replacement} if the id of {replacement} is // Replace all uses of {node} with {replacement} if the id of {replacement} is
// less than or equal to {max_id}. Otherwise, replace all uses of {node} whose // less than or equal to {max_id}. Otherwise, replace all uses of {node} whose
...@@ -173,6 +171,8 @@ class GraphReducer final : public AdvancedReducer::Editor { ...@@ -173,6 +171,8 @@ class GraphReducer final : public AdvancedReducer::Editor {
void Revisit(Node* node) final; void Revisit(Node* node) final;
Graph* const graph_; Graph* const graph_;
Node* dead_value_;
Node* dead_control_;
NodeMarker<State> state_; NodeMarker<State> state_;
ZoneVector<Reducer*> reducers_; ZoneVector<Reducer*> reducers_;
ZoneStack<Node*> revisit_; ZoneStack<Node*> revisit_;
......
...@@ -277,7 +277,7 @@ Reduction JSInliner::Reduce(Node* node) { ...@@ -277,7 +277,7 @@ Reduction JSInliner::Reduce(Node* node) {
AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph);
graph_builder.CreateGraph(true, false); graph_builder.CreateGraph(true, false);
JSContextSpecializer context_specializer(&jsgraph); JSContextSpecializer context_specializer(&jsgraph);
GraphReducer graph_reducer(&graph, local_zone_); GraphReducer graph_reducer(local_zone_, &graph);
graph_reducer.AddReducer(&context_specializer); graph_reducer.AddReducer(&context_specializer);
graph_reducer.ReduceGraph(); graph_reducer.ReduceGraph();
......
...@@ -410,6 +410,15 @@ class SourcePositionWrapper final : public Reducer { ...@@ -410,6 +410,15 @@ class SourcePositionWrapper final : public Reducer {
}; };
class JSGraphReducer final : public GraphReducer {
public:
JSGraphReducer(JSGraph* jsgraph, Zone* zone)
: GraphReducer(zone, jsgraph->graph(), jsgraph->TheHoleConstant(),
jsgraph->DeadControl()) {}
~JSGraphReducer() final {}
};
void AddReducer(PipelineData* data, GraphReducer* graph_reducer, void AddReducer(PipelineData* data, GraphReducer* graph_reducer,
Reducer* reducer) { Reducer* reducer) {
if (data->info()->is_source_positions_enabled()) { if (data->info()->is_source_positions_enabled()) {
...@@ -488,7 +497,7 @@ struct ContextSpecializerPhase { ...@@ -488,7 +497,7 @@ struct ContextSpecializerPhase {
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
JSContextSpecializer spec(data->jsgraph()); JSContextSpecializer spec(data->jsgraph());
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
AddReducer(data, &graph_reducer, &spec); AddReducer(data, &graph_reducer, &spec);
graph_reducer.ReduceGraph(); graph_reducer.ReduceGraph();
} }
...@@ -499,7 +508,7 @@ struct InliningPhase { ...@@ -499,7 +508,7 @@ struct InliningPhase {
static const char* phase_name() { return "inlining"; } static const char* phase_name() { return "inlining"; }
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled() JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled()
? JSInliner::kGeneralInlining ? JSInliner::kGeneralInlining
: JSInliner::kRestrictedInlining, : JSInliner::kRestrictedInlining,
...@@ -535,7 +544,7 @@ struct JSTypeFeedbackPhase { ...@@ -535,7 +544,7 @@ struct JSTypeFeedbackPhase {
TypeFeedbackOracle oracle(data->isolate(), temp_zone, TypeFeedbackOracle oracle(data->isolate(), temp_zone,
data->info()->unoptimized_code(), data->info()->unoptimized_code(),
data->info()->feedback_vector(), native_context); data->info()->feedback_vector(), native_context);
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
Handle<GlobalObject> global_object = Handle<GlobalObject>::null(); Handle<GlobalObject> global_object = Handle<GlobalObject>::null();
if (data->info()->has_global_object()) { if (data->info()->has_global_object()) {
global_object = global_object =
...@@ -559,7 +568,7 @@ struct TypedLoweringPhase { ...@@ -559,7 +568,7 @@ struct TypedLoweringPhase {
static const char* phase_name() { return "typed lowering"; } static const char* phase_name() { return "typed lowering"; }
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
LoadElimination load_elimination; LoadElimination load_elimination;
JSBuiltinReducer builtin_reducer(data->jsgraph()); JSBuiltinReducer builtin_reducer(data->jsgraph());
JSTypedLowering typed_lowering(&graph_reducer, data->jsgraph(), temp_zone); JSTypedLowering typed_lowering(&graph_reducer, data->jsgraph(), temp_zone);
...@@ -589,7 +598,7 @@ struct SimplifiedLoweringPhase { ...@@ -589,7 +598,7 @@ struct SimplifiedLoweringPhase {
ValueNumberingReducer vn_reducer(temp_zone); ValueNumberingReducer vn_reducer(temp_zone);
MachineOperatorReducer machine_reducer(data->jsgraph()); MachineOperatorReducer machine_reducer(data->jsgraph());
CommonOperatorReducer common_reducer(data->jsgraph()); CommonOperatorReducer common_reducer(data->jsgraph());
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
AddReducer(data, &graph_reducer, &vn_reducer); AddReducer(data, &graph_reducer, &vn_reducer);
AddReducer(data, &graph_reducer, &machine_reducer); AddReducer(data, &graph_reducer, &machine_reducer);
AddReducer(data, &graph_reducer, &common_reducer); AddReducer(data, &graph_reducer, &common_reducer);
...@@ -617,7 +626,7 @@ struct ChangeLoweringPhase { ...@@ -617,7 +626,7 @@ struct ChangeLoweringPhase {
ChangeLowering lowering(data->jsgraph()); ChangeLowering lowering(data->jsgraph());
MachineOperatorReducer machine_reducer(data->jsgraph()); MachineOperatorReducer machine_reducer(data->jsgraph());
CommonOperatorReducer common_reducer(data->jsgraph()); CommonOperatorReducer common_reducer(data->jsgraph());
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
AddReducer(data, &graph_reducer, &vn_reducer); AddReducer(data, &graph_reducer, &vn_reducer);
AddReducer(data, &graph_reducer, &lowering); AddReducer(data, &graph_reducer, &lowering);
AddReducer(data, &graph_reducer, &machine_reducer); AddReducer(data, &graph_reducer, &machine_reducer);
...@@ -666,7 +675,7 @@ struct GenericLoweringPhase { ...@@ -666,7 +675,7 @@ struct GenericLoweringPhase {
data->jsgraph()); data->jsgraph());
SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common()); SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common());
TailCallOptimization tco(data->common(), data->graph()); TailCallOptimization tco(data->common(), data->graph());
GraphReducer graph_reducer(data->graph(), temp_zone); JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
AddReducer(data, &graph_reducer, &generic); AddReducer(data, &graph_reducer, &generic);
AddReducer(data, &graph_reducer, &select); AddReducer(data, &graph_reducer, &select);
// TODO(turbofan): TCO is currently limited to stubs. // TODO(turbofan): TCO is currently limited to stubs.
......
...@@ -439,7 +439,7 @@ void Typer::Run() { ...@@ -439,7 +439,7 @@ void Typer::Run() {
} }
Visitor visitor(this); Visitor visitor(this);
GraphReducer graph_reducer(graph(), zone()); GraphReducer graph_reducer(zone(), graph());
graph_reducer.AddReducer(&visitor); graph_reducer.AddReducer(&visitor);
graph_reducer.ReduceGraph(); graph_reducer.ReduceGraph();
} }
......
...@@ -194,7 +194,11 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -194,7 +194,11 @@ void Verifier::Visitor::Check(Node* node) {
break; break;
case IrOpcode::kDead: case IrOpcode::kDead:
// Dead is never connected to the graph. // Dead is never connected to the graph.
UNREACHABLE(); // TODO(mstarzinger): Make the GraphReducer immediately perform control
// reduction in case control is killed. This will prevent {Dead} from
// being reachable after a phase finished. Then re-enable below assert.
// UNREACHABLE();
break;
case IrOpcode::kBranch: { case IrOpcode::kBranch: {
// Branch uses are IfTrue and IfFalse. // Branch uses are IfTrue and IfFalse.
int count_true = 0, count_false = 0; int count_true = 0, count_false = 0;
......
...@@ -97,9 +97,6 @@ ...@@ -97,9 +97,6 @@
############################################################################## ##############################################################################
# TurboFan compiler failures. # TurboFan compiler failures.
# TODO(mstarzinger): control edges are messed up in exception tests.
'test-run-jsexceptions/*': [PASS, NO_VARIANTS],
# Some tests are just too slow to run for now. # Some tests are just too slow to run for now.
'test-api/Threading*': [PASS, NO_VARIANTS], 'test-api/Threading*': [PASS, NO_VARIANTS],
'test-heap/IncrementalMarkingStepMakesBigProgressWithLargeObjects': [PASS, NO_VARIANTS], 'test-heap/IncrementalMarkingStepMakesBigProgressWithLargeObjects': [PASS, NO_VARIANTS],
......
...@@ -130,7 +130,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { ...@@ -130,7 +130,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
typer.Run(); typer.Run();
ChangeLowering change_lowering(&jsgraph); ChangeLowering change_lowering(&jsgraph);
SelectLowering select_lowering(this->graph(), this->common()); SelectLowering select_lowering(this->graph(), this->common());
GraphReducer reducer(this->graph(), this->zone()); GraphReducer reducer(this->zone(), this->graph());
reducer.AddReducer(&change_lowering); reducer.AddReducer(&change_lowering);
reducer.AddReducer(&select_lowering); reducer.AddReducer(&select_lowering);
reducer.ReduceNode(change); reducer.ReduceNode(change);
......
...@@ -231,7 +231,7 @@ TEST(SpecializeToContext) { ...@@ -231,7 +231,7 @@ TEST(SpecializeToContext) {
CheckEffectInput(load, effect_use); CheckEffectInput(load, effect_use);
// Perform the reduction on the entire graph. // Perform the reduction on the entire graph.
GraphReducer graph_reducer(t.graph(), t.main_zone()); GraphReducer graph_reducer(t.main_zone(), t.graph());
graph_reducer.AddReducer(&spec); graph_reducer.AddReducer(&spec);
graph_reducer.ReduceGraph(); graph_reducer.ReduceGraph();
......
...@@ -90,7 +90,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope { ...@@ -90,7 +90,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
Node* reduce(Node* node) { Node* reduce(Node* node) {
JSGraph jsgraph(main_isolate(), &graph, &common, &javascript, &machine); JSGraph jsgraph(main_isolate(), &graph, &common, &javascript, &machine);
// TODO(titzer): mock the GraphReducer here for better unit testing. // TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(&graph, main_zone()); GraphReducer graph_reducer(main_zone(), &graph);
JSTypedLowering reducer(&graph_reducer, &jsgraph, main_zone()); JSTypedLowering reducer(&graph_reducer, &jsgraph, main_zone());
Reduction reduction = reducer.Reduce(node); Reduction reduction = reducer.Reduce(node);
if (reduction.Changed()) return reduction.replacement(); if (reduction.Changed()) return reduction.replacement();
......
...@@ -13,10 +13,7 @@ TEST(Throw) { ...@@ -13,10 +13,7 @@ TEST(Throw) {
i::FLAG_turbo_exceptions = true; i::FLAG_turbo_exceptions = true;
FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})"); FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})");
// TODO(mstarzinger)
#if 0
T.CheckThrows(T.true_value(), T.NewObject("new Error")); T.CheckThrows(T.true_value(), T.NewObject("new Error"));
#endif
T.CheckCall(T.Val(23), T.false_value(), T.Val(23)); T.CheckCall(T.Val(23), T.false_value(), T.Val(23));
} }
...@@ -56,14 +53,11 @@ TEST(ThrowMessageDirectly) { ...@@ -56,14 +53,11 @@ TEST(ThrowMessageDirectly) {
FunctionTester T(src); FunctionTester T(src);
v8::Handle<v8::Message> message; v8::Handle<v8::Message> message;
// TODO(mstarzinger)
#if 0
message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?"))); CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?")));
message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!"))); CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!")));
#endif
} }
...@@ -80,14 +74,11 @@ TEST(ThrowMessageIndirectly) { ...@@ -80,14 +74,11 @@ TEST(ThrowMessageIndirectly) {
FunctionTester T(src); FunctionTester T(src);
v8::Handle<v8::Message> message; v8::Handle<v8::Message> message;
// TODO(mstarzinger)
#if 0
message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?"))); CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?")));
message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!"))); CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!")));
#endif
} }
......
...@@ -60,7 +60,7 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> { ...@@ -60,7 +60,7 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
lowering.LowerAllNodes(); lowering.LowerAllNodes();
ChangeLowering lowering(&jsgraph); ChangeLowering lowering(&jsgraph);
GraphReducer reducer(this->graph(), this->zone()); GraphReducer reducer(this->zone(), this->graph());
reducer.AddReducer(&lowering); reducer.AddReducer(&lowering);
reducer.ReduceGraph(); reducer.ReduceGraph();
Verifier::Run(this->graph()); Verifier::Run(this->graph());
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h" #include "src/compiler/graph.h"
#include "src/compiler/node.h" #include "src/compiler/node.h"
#include "src/compiler/operator.h" #include "src/compiler/operator.h"
...@@ -10,9 +11,11 @@ ...@@ -10,9 +11,11 @@
using testing::_; using testing::_;
using testing::DefaultValue; using testing::DefaultValue;
using testing::ElementsAre;
using testing::Return; using testing::Return;
using testing::Sequence; using testing::Sequence;
using testing::StrictMock; using testing::StrictMock;
using testing::UnorderedElementsAre;
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -264,6 +267,124 @@ TEST_F(AdvancedReducerTest, Revisit) { ...@@ -264,6 +267,124 @@ TEST_F(AdvancedReducerTest, Revisit) {
} }
namespace {
struct ReplaceWithValueReducer final : public AdvancedReducer {
explicit ReplaceWithValueReducer(Editor* editor) : AdvancedReducer(editor) {}
Reduction Reduce(Node* node) final { return NoChange(); }
using AdvancedReducer::ReplaceWithValue;
};
const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
"MockOperator", 0, 0, 0, 1, 0, 0);
const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties,
"MockOpEffect", 0, 1, 0, 1, 1, 0);
const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties,
"MockOpControl", 0, 0, 1, 1, 0, 1);
const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
} // namespace
TEST_F(AdvancedReducerTest, ReplaceWithValue_ValueUse) {
CommonOperatorBuilder common(zone());
Node* node = graph()->NewNode(&kMockOperator);
Node* use_value = graph()->NewNode(common.Return(), node);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), nullptr, nullptr);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(replacement, use_value->InputAt(0));
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(1, replacement->UseCount());
EXPECT_THAT(replacement->uses(), ElementsAre(use_value));
}
TEST_F(AdvancedReducerTest, ReplaceWithValue_EffectUse) {
CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1));
Node* node = graph()->NewNode(&kMockOpEffect, start);
Node* use_effect = graph()->NewNode(common.EffectPhi(1), node);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), nullptr, nullptr);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(start, use_effect->InputAt(0));
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(2, start->UseCount());
EXPECT_EQ(0, replacement->UseCount());
EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node));
}
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse1) {
CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1));
Node* node = graph()->NewNode(&kMockOpControl, start);
Node* success = graph()->NewNode(common.IfSuccess(), node);
Node* use_control = graph()->NewNode(common.Merge(1), success);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), nullptr, nullptr);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(start, use_control->InputAt(0));
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(2, start->UseCount());
EXPECT_EQ(0, replacement->UseCount());
EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
}
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) {
CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1));
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* use_control = graph()->NewNode(common.Merge(1), success);
Node* use_exception_control = graph()->NewNode(common.Merge(1), exception);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), nullptr, dead);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(start, use_control->InputAt(0));
EXPECT_EQ(dead, use_exception_control->InputAt(0));
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(2, start->UseCount());
EXPECT_EQ(1, dead->UseCount());
EXPECT_EQ(0, replacement->UseCount());
EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
EXPECT_THAT(dead->uses(), ElementsAre(use_exception_control));
}
TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) {
CommonOperatorBuilder common(zone());
Node* start = graph()->NewNode(common.Start(1));
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* use_control = graph()->NewNode(common.Merge(1), success);
Node* use_exception_value = graph()->NewNode(common.Return(), exception);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), dead, nullptr);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(start, use_control->InputAt(0));
EXPECT_EQ(dead, use_exception_value->InputAt(0));
EXPECT_EQ(0, node->UseCount());
EXPECT_EQ(2, start->UseCount());
EXPECT_EQ(1, dead->UseCount());
EXPECT_EQ(0, replacement->UseCount());
EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
EXPECT_THAT(dead->uses(), ElementsAre(use_exception_value));
}
class GraphReducerTest : public TestWithZone { class GraphReducerTest : public TestWithZone {
public: public:
GraphReducerTest() : graph_(zone()) {} GraphReducerTest() : graph_(zone()) {}
...@@ -280,20 +401,20 @@ class GraphReducerTest : public TestWithZone { ...@@ -280,20 +401,20 @@ class GraphReducerTest : public TestWithZone {
protected: protected:
void ReduceNode(Node* node, Reducer* r) { void ReduceNode(Node* node, Reducer* r) {
GraphReducer reducer(graph(), zone()); GraphReducer reducer(zone(), graph());
reducer.AddReducer(r); reducer.AddReducer(r);
reducer.ReduceNode(node); reducer.ReduceNode(node);
} }
void ReduceNode(Node* node, Reducer* r1, Reducer* r2) { void ReduceNode(Node* node, Reducer* r1, Reducer* r2) {
GraphReducer reducer(graph(), zone()); GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1); reducer.AddReducer(r1);
reducer.AddReducer(r2); reducer.AddReducer(r2);
reducer.ReduceNode(node); reducer.ReduceNode(node);
} }
void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) { void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) {
GraphReducer reducer(graph(), zone()); GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1); reducer.AddReducer(r1);
reducer.AddReducer(r2); reducer.AddReducer(r2);
reducer.AddReducer(r3); reducer.AddReducer(r3);
...@@ -301,20 +422,20 @@ class GraphReducerTest : public TestWithZone { ...@@ -301,20 +422,20 @@ class GraphReducerTest : public TestWithZone {
} }
void ReduceGraph(Reducer* r1) { void ReduceGraph(Reducer* r1) {
GraphReducer reducer(graph(), zone()); GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1); reducer.AddReducer(r1);
reducer.ReduceGraph(); reducer.ReduceGraph();
} }
void ReduceGraph(Reducer* r1, Reducer* r2) { void ReduceGraph(Reducer* r1, Reducer* r2) {
GraphReducer reducer(graph(), zone()); GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1); reducer.AddReducer(r1);
reducer.AddReducer(r2); reducer.AddReducer(r2);
reducer.ReduceGraph(); reducer.ReduceGraph();
} }
void ReduceGraph(Reducer* r1, Reducer* r2, Reducer* r3) { void ReduceGraph(Reducer* r1, Reducer* r2, Reducer* r3) {
GraphReducer reducer(graph(), zone()); GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1); reducer.AddReducer(r1);
reducer.AddReducer(r2); reducer.AddReducer(r2);
reducer.AddReducer(r3); reducer.AddReducer(r3);
......
...@@ -34,7 +34,7 @@ class JSIntrinsicLoweringTest : public GraphTest { ...@@ -34,7 +34,7 @@ class JSIntrinsicLoweringTest : public GraphTest {
MachineOperatorBuilder machine(zone(), kMachPtr, flags); MachineOperatorBuilder machine(zone(), kMachPtr, flags);
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
// TODO(titzer): mock the GraphReducer here for better unit testing. // TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(graph(), zone()); GraphReducer graph_reducer(zone(), graph());
JSIntrinsicLowering reducer(&graph_reducer, &jsgraph, JSIntrinsicLowering reducer(&graph_reducer, &jsgraph,
JSIntrinsicLowering::kDeoptimizationEnabled); JSIntrinsicLowering::kDeoptimizationEnabled);
return reducer.Reduce(node); return reducer.Reduce(node);
......
...@@ -43,7 +43,7 @@ class JSTypeFeedbackTest : public TypedGraphTest { ...@@ -43,7 +43,7 @@ class JSTypeFeedbackTest : public TypedGraphTest {
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
JSTypeFeedbackTable table(zone()); JSTypeFeedbackTable table(zone());
// TODO(titzer): mock the GraphReducer here for better unit testing. // TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(graph(), zone()); GraphReducer graph_reducer(zone(), graph());
JSTypeFeedbackSpecializer reducer(&graph_reducer, &jsgraph, &table, nullptr, JSTypeFeedbackSpecializer reducer(&graph_reducer, &jsgraph, &table, nullptr,
global_object, mode, &dependencies_); global_object, mode, &dependencies_);
return reducer.Reduce(node); return reducer.Reduce(node);
......
...@@ -81,7 +81,7 @@ class JSTypedLoweringTest : public TypedGraphTest { ...@@ -81,7 +81,7 @@ class JSTypedLoweringTest : public TypedGraphTest {
MachineOperatorBuilder machine(zone()); MachineOperatorBuilder machine(zone());
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
// TODO(titzer): mock the GraphReducer here for better unit testing. // TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(graph(), zone()); GraphReducer graph_reducer(zone(), graph());
JSTypedLowering reducer(&graph_reducer, &jsgraph, zone()); JSTypedLowering reducer(&graph_reducer, &jsgraph, zone());
return reducer.Reduce(node); return reducer.Reduce(node);
} }
......
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