// Copyright 2015 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/common-operator.h" #include "src/compiler/node-properties.h" #include "test/unittests/test-utils.h" #include "testing/gmock/include/gmock/gmock.h" using testing::AnyOf; using testing::ElementsAre; using testing::IsNull; namespace v8 { namespace internal { namespace compiler { class NodePropertiesTest : public TestWithZone { public: 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); } }; namespace { const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties, "MockOperator", 0, 0, 0, 1, 1, 2); 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()); 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(1)); EXPECT_EQ(0, node->UseCount()); EXPECT_EQ(1, r_value->UseCount()); EXPECT_EQ(1, r_effect->UseCount()); EXPECT_EQ(1, r_success->UseCount()); EXPECT_EQ(1, r_exception->UseCount()); EXPECT_THAT(r_value->uses(), ElementsAre(use_value)); EXPECT_THAT(r_effect->uses(), ElementsAre(use_effect)); EXPECT_THAT(r_success->uses(), ElementsAre(use_success)); EXPECT_THAT(r_exception->uses(), ElementsAre(use_exception)); } TEST_F(NodePropertiesTest, FindProjection) { CommonOperatorBuilder common(zone()); 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()); EXPECT_THAT(NodeProperties::FindProjection(start, 1234567890), IsNull()); } TEST_F(NodePropertiesTest, CollectControlProjections_Branch) { Node* result[2]; CommonOperatorBuilder common(zone()); 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]); } TEST_F(NodePropertiesTest, CollectControlProjections_Call) { Node* result[2]; CommonOperatorBuilder common(zone()); 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]); } TEST_F(NodePropertiesTest, CollectControlProjections_Switch) { Node* result[3]; CommonOperatorBuilder common(zone()); 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)); EXPECT_EQ(if_default, result[2]); } } // namespace compiler } // namespace internal } // namespace v8