v8/test/unittests/compiler/constant-folding-reducer-unittest.cc
Tobias Tebbi 4f48d04f97 [turbofan] introduce a deterministic tick measurement and assert optimization doesn't take too long
This adds a simple counter to Turbofan that's incremented throughout the compilation, hopefully
frequently enough so we can use it to detect divergence and performance bugs.
In addition, we assert that this counter never gets too high. That's the equivalent of a simple
timeout, just more deterministic. The limitations on Turbofan input size should guarantee that
we never exceed this limit. Since we probably do exceed it rarely, this check is only a DCHECK and
intended to detect performance and divergence issues, but not supposed to be performed in release
builds.

In addition, this CL adds UMA stats to observe the real world distribution of the tick measurement.

Bug: v8:9444

Change-Id: I182dac6ecac64715e3f5885ff5c7c17549351cd0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1695475
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62754}
2019-07-17 07:00:00 +00:00

233 lines
8.5 KiB
C++

// Copyright 2016 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/constant-folding-reducer.h"
#include "src/codegen/code-factory.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
#include "src/execution/isolate-inl.h"
#include "test/unittests/compiler/compiler-test-utils.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"
using testing::IsNaN;
namespace v8 {
namespace internal {
namespace compiler {
namespace constant_folding_reducer_unittest {
namespace {
const double kFloat64Values[] = {
-V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220,
-6.26172e+212, -2.56222e+211, -4.82408e+201, -1.84106e+157,
-1.63662e+127, -1.55772e+100, -1.67813e+72, -2.3382e+55,
-3.179e+30, -1.441e+09, -1.0647e+09, -7.99361e+08,
-5.77375e+08, -2.20984e+08, -32757, -13171,
-9970, -3984, -107, -105,
-92, -77, -61, -0.000208163,
-1.86685e-06, -1.17296e-10, -9.26358e-11, -5.08004e-60,
-1.74753e-65, -1.06561e-71, -5.67879e-79, -5.78459e-130,
-2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
-4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278,
-2.03855e-282, -5.99335e-283, -7.17554e-284, -3.11744e-309,
-0.0, 0.0, 2.22507e-308, 1.30127e-270,
7.62898e-260, 4.00313e-249, 3.16829e-233, 1.85244e-228,
2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94,
1.35292e-90, 2.85394e-83, 1.78323e-77, 5.4967e-57,
1.03207e-25, 4.57401e-25, 1.58738e-05, 2,
125, 2310, 9636, 14802,
17168, 28945, 29305, 4.81336e+07,
1.41207e+08, 4.65962e+08, 1.40499e+09, 2.12648e+09,
8.80006e+30, 1.4446e+45, 1.12164e+54, 2.48188e+89,
6.71121e+102, 3.074e+112, 4.9699e+152, 5.58383e+166,
4.30654e+172, 7.08824e+185, 9.6586e+214, 2.028e+223,
6.63277e+243, 1.56192e+261, 1.23202e+269, 5.72883e+289,
8.5798e+290, 1.40256e+294, 1.79769e+308, V8_INFINITY};
const double kIntegerValues[] = {-V8_INFINITY, INT_MIN, -1000.0, -42.0,
-1.0, 0.0, 1.0, 42.0,
1000.0, INT_MAX, UINT_MAX, V8_INFINITY};
} // namespace
class ConstantFoldingReducerTest : public TypedGraphTest {
public:
ConstantFoldingReducerTest()
: TypedGraphTest(3),
broker_(isolate(), zone(), FLAG_trace_heap_broker),
simplified_(zone()),
deps_(&broker_, zone()) {}
~ConstantFoldingReducerTest() override = default;
protected:
Reduction Reduce(Node* node) {
MachineOperatorBuilder machine(zone());
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph(), tick_counter());
ConstantFoldingReducer reducer(&graph_reducer, &jsgraph, broker());
return reducer.Reduce(node);
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSHeapBroker* broker() { return &broker_; }
private:
JSHeapBroker broker_;
SimplifiedOperatorBuilder simplified_;
CompilationDependencies deps_;
};
TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
{
Reduction r = Reduce(Parameter(
Type::NewConstant(broker(), factory()->minus_zero_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
}
{
Reduction r = Reduce(Parameter(Type::MinusZero()));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
}
{
Reduction r = Reduce(Parameter(Type::Union(
Type::MinusZero(),
Type::NewConstant(broker(), factory()->NewNumber(0), zone()), zone())));
EXPECT_FALSE(r.Changed());
}
}
TEST_F(ConstantFoldingReducerTest, ParameterWithNull) {
Handle<HeapObject> null = factory()->null_value();
{
Reduction r = Reduce(Parameter(Type::NewConstant(broker(), null, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null));
}
{
Reduction r = Reduce(Parameter(Type::Null()));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null));
}
}
TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::signaling_NaN()};
TRACED_FOREACH(double, nan, kNaNs) {
Handle<Object> constant = factory()->NewNumber(nan);
Reduction r =
Reduce(Parameter(Type::NewConstant(broker(), constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
{
Reduction r = Reduce(
Parameter(Type::NewConstant(broker(), factory()->nan_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
{
Reduction r = Reduce(Parameter(Type::NaN()));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
}
TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) {
TRACED_FOREACH(double, value, kFloat64Values) {
Handle<Object> constant = factory()->NewNumber(value);
Reduction r =
Reduce(Parameter(Type::NewConstant(broker(), constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value));
}
TRACED_FOREACH(double, value, kIntegerValues) {
Reduction r = Reduce(Parameter(Type::Range(value, value, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value));
}
}
TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) {
Handle<HeapObject> undefined = factory()->undefined_value();
{
Reduction r = Reduce(Parameter(Type::Undefined()));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
{
Reduction r =
Reduce(Parameter(Type::NewConstant(broker(), undefined, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
}
// -----------------------------------------------------------------------------
// ToBoolean
TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
Node* input = Parameter(
Type::Union(
Type::MinusZero(),
Type::Union(
Type::NaN(),
Type::Union(
Type::Null(),
Type::Union(
Type::Undefined(),
Type::Union(
Type::Undetectable(),
Type::Union(
Type::NewConstant(
broker(), factory()->false_value(), zone()),
Type::Range(0.0, 0.0, zone()), zone()),
zone()),
zone()),
zone()),
zone()),
zone()),
0);
Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant());
}
TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) {
Node* input = Parameter(
Type::Union(
Type::NewConstant(broker(), factory()->true_value(), zone()),
Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
zone()),
0);
Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant());
}
TEST_F(ConstantFoldingReducerTest, ToBooleanWithNonZeroPlainNumber) {
Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant());
}
} // namespace constant_folding_reducer_unittest
} // namespace compiler
} // namespace internal
} // namespace v8