Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/state-values-utils.h"
6 : #include "src/bit-vector.h"
7 : #include "test/unittests/compiler/graph-unittest.h"
8 : #include "test/unittests/compiler/node-test-utils.h"
9 : #include "test/unittests/test-utils.h"
10 : #include "testing/gmock/include/gmock/gmock.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace compiler {
15 :
16 7 : class StateValuesIteratorTest : public GraphTest {
17 : public:
18 7 : StateValuesIteratorTest() : GraphTest(3) {}
19 :
20 6 : Node* StateValuesFromVector(NodeVector* nodes) {
21 12 : int count = static_cast<int>(nodes->size());
22 : return graph()->NewNode(
23 : common()->StateValues(count, SparseInputMask::Dense()), count,
24 6 : count == 0 ? nullptr : &(nodes->front()));
25 : }
26 : };
27 :
28 :
29 13160 : TEST_F(StateValuesIteratorTest, SimpleIteration) {
30 1 : NodeVector inputs(zone());
31 1 : const int count = 10;
32 11 : for (int i = 0; i < count; i++) {
33 20 : inputs.push_back(Int32Constant(i));
34 : }
35 1 : Node* state_values = StateValuesFromVector(&inputs);
36 1 : int i = 0;
37 20 : for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
38 40 : EXPECT_THAT(node.node, IsInt32Constant(i));
39 10 : i++;
40 : }
41 1 : EXPECT_EQ(count, i);
42 1 : }
43 :
44 :
45 13160 : TEST_F(StateValuesIteratorTest, EmptyIteration) {
46 1 : NodeVector inputs(zone());
47 1 : Node* state_values = StateValuesFromVector(&inputs);
48 1 : for (auto node : StateValuesAccess(state_values)) {
49 : USE(node);
50 0 : FAIL();
51 : }
52 : }
53 :
54 :
55 13160 : TEST_F(StateValuesIteratorTest, NestedIteration) {
56 1 : NodeVector inputs(zone());
57 1 : int count = 0;
58 9 : for (int i = 0; i < 8; i++) {
59 8 : if (i == 2) {
60 : // Single nested in index 2.
61 1 : NodeVector nested_inputs(zone());
62 9 : for (int j = 0; j < 8; j++) {
63 16 : nested_inputs.push_back(Int32Constant(count++));
64 : }
65 2 : inputs.push_back(StateValuesFromVector(&nested_inputs));
66 7 : } else if (i == 5) {
67 : // Double nested at index 5.
68 1 : NodeVector nested_inputs(zone());
69 9 : for (int j = 0; j < 8; j++) {
70 8 : if (j == 7) {
71 1 : NodeVector doubly_nested_inputs(zone());
72 3 : for (int k = 0; k < 2; k++) {
73 4 : doubly_nested_inputs.push_back(Int32Constant(count++));
74 : }
75 2 : nested_inputs.push_back(StateValuesFromVector(&doubly_nested_inputs));
76 : } else {
77 14 : nested_inputs.push_back(Int32Constant(count++));
78 : }
79 : }
80 2 : inputs.push_back(StateValuesFromVector(&nested_inputs));
81 : } else {
82 12 : inputs.push_back(Int32Constant(count++));
83 : }
84 : }
85 1 : Node* state_values = StateValuesFromVector(&inputs);
86 1 : int i = 0;
87 46 : for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
88 92 : EXPECT_THAT(node.node, IsInt32Constant(i));
89 23 : i++;
90 : }
91 1 : EXPECT_EQ(count, i);
92 1 : }
93 :
94 :
95 13160 : TEST_F(StateValuesIteratorTest, TreeFromVector) {
96 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
97 49 : TRACED_FOREACH(int, count, sizes) {
98 6 : JSOperatorBuilder javascript(zone());
99 6 : MachineOperatorBuilder machine(zone());
100 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
101 6 : &machine);
102 :
103 : // Generate the input vector.
104 6 : NodeVector inputs(zone());
105 35109 : for (int i = 0; i < count; i++) {
106 70206 : inputs.push_back(Int32Constant(i));
107 : }
108 :
109 : // Build the tree.
110 6 : StateValuesCache builder(&jsgraph);
111 : Node* values_node = builder.GetNodeForValues(
112 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
113 12 : nullptr);
114 :
115 : // Check the tree contents with vector.
116 : int i = 0;
117 70206 : for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
118 140412 : EXPECT_THAT(node.node, IsInt32Constant(i));
119 35103 : i++;
120 : }
121 18 : EXPECT_EQ(inputs.size(), static_cast<size_t>(i));
122 6 : }
123 1 : }
124 :
125 13160 : TEST_F(StateValuesIteratorTest, TreeFromVectorWithLiveness) {
126 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
127 49 : TRACED_FOREACH(int, count, sizes) {
128 6 : JSOperatorBuilder javascript(zone());
129 6 : MachineOperatorBuilder machine(zone());
130 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
131 6 : &machine);
132 :
133 : // Generate the input vector.
134 6 : NodeVector inputs(zone());
135 35109 : for (int i = 0; i < count; i++) {
136 70206 : inputs.push_back(Int32Constant(i));
137 : }
138 : // Generate the input liveness.
139 6 : BitVector liveness(count, zone());
140 35109 : for (int i = 0; i < count; i++) {
141 35103 : if (i % 3 == 0) {
142 : liveness.Add(i);
143 : }
144 : }
145 :
146 : // Build the tree.
147 6 : StateValuesCache builder(&jsgraph);
148 : Node* values_node = builder.GetNodeForValues(
149 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
150 12 : &liveness);
151 :
152 : // Check the tree contents with vector.
153 : int i = 0;
154 70206 : for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
155 35103 : if (liveness.Contains(i)) {
156 46812 : EXPECT_THAT(node.node, IsInt32Constant(i));
157 : } else {
158 46800 : EXPECT_EQ(node.node, nullptr);
159 : }
160 35103 : i++;
161 : }
162 18 : EXPECT_EQ(inputs.size(), static_cast<size_t>(i));
163 6 : }
164 1 : }
165 :
166 13160 : TEST_F(StateValuesIteratorTest, BuildTreeIdentical) {
167 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
168 49 : TRACED_FOREACH(int, count, sizes) {
169 6 : JSOperatorBuilder javascript(zone());
170 6 : MachineOperatorBuilder machine(zone());
171 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
172 6 : &machine);
173 :
174 : // Generate the input vector.
175 6 : NodeVector inputs(zone());
176 35109 : for (int i = 0; i < count; i++) {
177 70206 : inputs.push_back(Int32Constant(i));
178 : }
179 :
180 : // Build two trees from the same data.
181 6 : StateValuesCache builder(&jsgraph);
182 : Node* node1 = builder.GetNodeForValues(
183 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
184 12 : nullptr);
185 : Node* node2 = builder.GetNodeForValues(
186 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
187 12 : nullptr);
188 :
189 : // The trees should be equal since the data was the same.
190 6 : EXPECT_EQ(node1, node2);
191 6 : }
192 1 : }
193 :
194 13160 : TEST_F(StateValuesIteratorTest, BuildTreeWithLivenessIdentical) {
195 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
196 49 : TRACED_FOREACH(int, count, sizes) {
197 6 : JSOperatorBuilder javascript(zone());
198 6 : MachineOperatorBuilder machine(zone());
199 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
200 6 : &machine);
201 :
202 : // Generate the input vector.
203 6 : NodeVector inputs(zone());
204 35109 : for (int i = 0; i < count; i++) {
205 70206 : inputs.push_back(Int32Constant(i));
206 : }
207 : // Generate the input liveness.
208 6 : BitVector liveness(count, zone());
209 35109 : for (int i = 0; i < count; i++) {
210 35103 : if (i % 3 == 0) {
211 : liveness.Add(i);
212 : }
213 : }
214 :
215 : // Build two trees from the same data.
216 6 : StateValuesCache builder(&jsgraph);
217 : Node* node1 = builder.GetNodeForValues(
218 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
219 12 : &liveness);
220 : Node* node2 = builder.GetNodeForValues(
221 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
222 12 : &liveness);
223 :
224 : // The trees should be equal since the data was the same.
225 6 : EXPECT_EQ(node1, node2);
226 6 : }
227 1 : }
228 :
229 : } // namespace compiler
230 : } // namespace internal
231 7893 : } // namespace v8
|