// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/compiler/graph.h" #include "src/compiler/graph-reducer.h" #include "src/compiler/operator.h" #include "test/unittests/test-utils.h" #include "testing/gmock/include/gmock/gmock.h" using testing::_; using testing::DefaultValue; using testing::Return; using testing::Sequence; using testing::StrictMock; namespace v8 { namespace internal { namespace compiler { namespace { SimpleOperator OP0(0, Operator::kNoWrite, 0, 1, "op0"); SimpleOperator OP1(1, Operator::kNoProperties, 1, 1, "op1"); struct MockReducer : public Reducer { MOCK_METHOD1(Reduce, Reduction(Node*)); }; } // namespace class GraphReducerTest : public TestWithZone { public: GraphReducerTest() : graph_(zone()) {} static void SetUpTestCase() { TestWithZone::SetUpTestCase(); DefaultValue::Set(Reducer::NoChange()); } static void TearDownTestCase() { DefaultValue::Clear(); TestWithZone::TearDownTestCase(); } protected: void ReduceNode(Node* node, Reducer* r) { GraphReducer reducer(graph()); reducer.AddReducer(r); reducer.ReduceNode(node); } void ReduceNode(Node* node, Reducer* r1, Reducer* r2) { GraphReducer reducer(graph()); reducer.AddReducer(r1); reducer.AddReducer(r2); reducer.ReduceNode(node); } void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) { GraphReducer reducer(graph()); reducer.AddReducer(r1); reducer.AddReducer(r2); reducer.AddReducer(r3); reducer.ReduceNode(node); } Graph* graph() { return &graph_; } private: Graph graph_; }; TEST_F(GraphReducerTest, NodeIsDeadAfterReplace) { StrictMock r; Node* node0 = graph()->NewNode(&OP0); Node* node1 = graph()->NewNode(&OP1, node0); Node* node2 = graph()->NewNode(&OP1, node0); EXPECT_CALL(r, Reduce(node1)).WillOnce(Return(Reducer::Replace(node2))); ReduceNode(node1, &r); EXPECT_FALSE(node0->IsDead()); EXPECT_TRUE(node1->IsDead()); EXPECT_FALSE(node2->IsDead()); } TEST_F(GraphReducerTest, ReduceOnceForEveryReducer) { StrictMock r1, r2; Node* node0 = graph()->NewNode(&OP0); EXPECT_CALL(r1, Reduce(node0)); EXPECT_CALL(r2, Reduce(node0)); ReduceNode(node0, &r1, &r2); } TEST_F(GraphReducerTest, ReduceAgainAfterChanged) { Sequence s1, s2, s3; StrictMock r1, r2, r3; Node* node0 = graph()->NewNode(&OP0); EXPECT_CALL(r1, Reduce(node0)); EXPECT_CALL(r2, Reduce(node0)); EXPECT_CALL(r3, Reduce(node0)).InSequence(s1, s2, s3).WillOnce( Return(Reducer::Changed(node0))); EXPECT_CALL(r1, Reduce(node0)).InSequence(s1); EXPECT_CALL(r2, Reduce(node0)).InSequence(s2); EXPECT_CALL(r3, Reduce(node0)).InSequence(s3); ReduceNode(node0, &r1, &r2, &r3); } } // namespace compiler } // namespace internal } // namespace v8