b7dc9c580a
With this change, we remember the types of frame state inputs (in a new operator, called TypedStateValues). Instead of inferring the value types when building translations, we used the recorded types. The original approach was not reliable because the passes after simplified lowering can change node types, and this in turn confuses the translation builder. BUG=chromium:468727 LOG=n R=bmeurer@chromium.org Review URL: https://codereview.chromium.org/1015423002 Cr-Commit-Position: refs/heads/master@{#27310}
150 lines
4.4 KiB
C++
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 (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
|
|
EXPECT_THAT(node.node, IsInt32Constant(i));
|
|
i++;
|
|
}
|
|
EXPECT_EQ(count, i);
|
|
}
|
|
|
|
|
|
TEST_F(StateValuesIteratorTest, EmptyIteration) {
|
|
NodeVector inputs(zone());
|
|
Node* state_values = StateValuesFromVector(&inputs);
|
|
for (auto 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 (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
|
|
EXPECT_THAT(node.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 (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
|
|
EXPECT_THAT(node.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
|