v8/test/unittests/compiler/state-values-utils-unittest.cc
jarin cd67e97a7e [turbofan] Cache for reusing parts of value vector nodes in frame states.
Instead of the current approach of storing flat vectors in frame states (and possibly reusing the last vector in AST graph builder), this change list builds a tree for the values and tries to reuse the nodes for different frame states. At the moment, we only use this for the local variable part of frame state, but nothing prevents us from using this for all parts.

This change provides two new classes: one for creating the tree (StateValuesCache) and one for iterating the trees (StateValuesAccess).

BUG=

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

Cr-Commit-Position: refs/heads/master@{#27222}
2015-03-16 13:43:13 +00:00

150 lines
4.4 KiB
C++

// 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/state-values-utils.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace v8 {
namespace internal {
namespace compiler {
class StateValuesIteratorTest : public GraphTest {
public:
StateValuesIteratorTest() : GraphTest(3) {}
Node* StateValuesFromVector(NodeVector* nodes) {
int count = static_cast<int>(nodes->size());
return graph()->NewNode(common()->StateValues(count), count,
count == 0 ? nullptr : &(nodes->front()));
}
};
TEST_F(StateValuesIteratorTest, SimpleIteration) {
NodeVector inputs(zone());
const int count = 10;
for (int i = 0; i < count; i++) {
inputs.push_back(Int32Constant(i));
}
Node* state_values = StateValuesFromVector(&inputs);
int i = 0;
for (Node* node : StateValuesAccess(state_values)) {
EXPECT_THAT(node, IsInt32Constant(i));
i++;
}
EXPECT_EQ(count, i);
}
TEST_F(StateValuesIteratorTest, EmptyIteration) {
NodeVector inputs(zone());
Node* state_values = StateValuesFromVector(&inputs);
for (Node* node : StateValuesAccess(state_values)) {
USE(node);
FAIL();
}
}
TEST_F(StateValuesIteratorTest, NestedIteration) {
NodeVector inputs(zone());
int count = 0;
for (int i = 0; i < 8; i++) {
if (i == 2) {
// Single nested in index 2.
NodeVector nested_inputs(zone());
for (int j = 0; j < 8; j++) {
nested_inputs.push_back(Int32Constant(count++));
}
inputs.push_back(StateValuesFromVector(&nested_inputs));
} else if (i == 5) {
// Double nested at index 5.
NodeVector nested_inputs(zone());
for (int j = 0; j < 8; j++) {
if (j == 7) {
NodeVector doubly_nested_inputs(zone());
for (int k = 0; k < 2; k++) {
doubly_nested_inputs.push_back(Int32Constant(count++));
}
nested_inputs.push_back(StateValuesFromVector(&doubly_nested_inputs));
} else {
nested_inputs.push_back(Int32Constant(count++));
}
}
inputs.push_back(StateValuesFromVector(&nested_inputs));
} else {
inputs.push_back(Int32Constant(count++));
}
}
Node* state_values = StateValuesFromVector(&inputs);
int i = 0;
for (Node* node : StateValuesAccess(state_values)) {
EXPECT_THAT(node, IsInt32Constant(i));
i++;
}
EXPECT_EQ(count, i);
}
TEST_F(StateValuesIteratorTest, TreeFromVector) {
int sizes[] = {0, 1, 2, 100, 5000, 30000};
TRACED_FOREACH(int, count, sizes) {
JSOperatorBuilder javascript(zone());
MachineOperatorBuilder machine(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
// Generate the input vector.
NodeVector inputs(zone());
for (int i = 0; i < count; i++) {
inputs.push_back(Int32Constant(i));
}
// Build the tree.
StateValuesCache builder(&jsgraph);
Node* values_node = builder.GetNodeForValues(
inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size());
// Check the tree contents with vector.
int i = 0;
for (Node* node : StateValuesAccess(values_node)) {
EXPECT_THAT(node, IsInt32Constant(i));
i++;
}
EXPECT_EQ(inputs.size(), static_cast<size_t>(i));
}
}
TEST_F(StateValuesIteratorTest, BuildTreeIdentical) {
int sizes[] = {0, 1, 2, 100, 5000, 30000};
TRACED_FOREACH(int, count, sizes) {
JSOperatorBuilder javascript(zone());
MachineOperatorBuilder machine(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
// Generate the input vector.
NodeVector inputs(zone());
for (int i = 0; i < count; i++) {
inputs.push_back(Int32Constant(i));
}
// Build two trees from the same data.
StateValuesCache builder(&jsgraph);
Node* node1 = builder.GetNodeForValues(
inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size());
Node* node2 = builder.GetNodeForValues(
inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size());
// The trees should be equal since the data was the same.
EXPECT_EQ(node1, node2);
}
}
} // namespace compiler
} // namespace internal
} // namespace v8