summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2015-08-23 06:09:40 -0700
committerRod Vagg <rod@vagg.org>2015-09-06 21:38:01 +1000
commit9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch)
tree4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/test/unittests
parent46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff)
downloadandroid-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.gz
android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.bz2
android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.zip
deps: upgrade V8 to 4.5.103.24
Upgrade to the latest branch-head for V8 4.5. For the full commit log see https://github.com/v8/v8-git-mirror/commits/4.5.103.24 PR-URL: https://github.com/nodejs/node/pull/2509 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/test/unittests')
-rw-r--r--deps/v8/test/unittests/base/bits-unittest.cc19
-rw-r--r--deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc563
-rw-r--r--deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc342
-rw-r--r--deps/v8/test/unittests/compiler/common-operator-unittest.cc52
-rw-r--r--deps/v8/test/unittests/compiler/control-equivalence-unittest.cc6
-rw-r--r--deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc20
-rw-r--r--deps/v8/test/unittests/compiler/control-reducer-unittest.cc326
-rw-r--r--deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc375
-rw-r--r--deps/v8/test/unittests/compiler/graph-reducer-unittest.cc165
-rw-r--r--deps/v8/test/unittests/compiler/graph-reducer-unittest.h1
-rw-r--r--deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc85
-rw-r--r--deps/v8/test/unittests/compiler/graph-unittest.cc19
-rw-r--r--deps/v8/test/unittests/compiler/graph-unittest.h2
-rw-r--r--deps/v8/test/unittests/compiler/instruction-selector-unittest.cc110
-rw-r--r--deps/v8/test/unittests/compiler/instruction-selector-unittest.h19
-rw-r--r--deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc4
-rw-r--r--deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc34
-rw-r--r--deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc71
-rw-r--r--deps/v8/test/unittests/compiler/js-operator-unittest.cc9
-rw-r--r--deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc389
-rw-r--r--deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc321
-rw-r--r--deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc10
-rw-r--r--deps/v8/test/unittests/compiler/load-elimination-unittest.cc4
-rw-r--r--deps/v8/test/unittests/compiler/loop-peeling-unittest.cc3
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc84
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-unittest.cc237
-rw-r--r--deps/v8/test/unittests/compiler/node-properties-unittest.cc114
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.cc197
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.h24
-rw-r--r--deps/v8/test/unittests/compiler/node-unittest.cc92
-rw-r--r--deps/v8/test/unittests/compiler/scheduler-unittest.cc1382
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-unittest.cc1
-rw-r--r--deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc22
-rw-r--r--deps/v8/test/unittests/counters-unittest.cc28
-rw-r--r--deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc395
-rw-r--r--deps/v8/test/unittests/heap/heap-unittest.cc48
-rw-r--r--deps/v8/test/unittests/heap/memory-reducer-unittest.cc331
-rw-r--r--deps/v8/test/unittests/libplatform/default-platform-unittest.cc88
-rw-r--r--deps/v8/test/unittests/unittests.gyp5
39 files changed, 3266 insertions, 2731 deletions
diff --git a/deps/v8/test/unittests/base/bits-unittest.cc b/deps/v8/test/unittests/base/bits-unittest.cc
index 9caba8484e..3d17a050db 100644
--- a/deps/v8/test/unittests/base/bits-unittest.cc
+++ b/deps/v8/test/unittests/base/bits-unittest.cc
@@ -255,6 +255,25 @@ TEST(Bits, SignedMod32) {
}
+TEST(Bits, UnsignedAddOverflow32) {
+ uint32_t val = 0;
+ EXPECT_FALSE(UnsignedAddOverflow32(0, 0, &val));
+ EXPECT_EQ(0u, val);
+ EXPECT_TRUE(
+ UnsignedAddOverflow32(std::numeric_limits<uint32_t>::max(), 1u, &val));
+ EXPECT_EQ(std::numeric_limits<uint32_t>::min(), val);
+ EXPECT_TRUE(UnsignedAddOverflow32(std::numeric_limits<uint32_t>::max(),
+ std::numeric_limits<uint32_t>::max(),
+ &val));
+ TRACED_FORRANGE(uint32_t, i, 1, 50) {
+ TRACED_FORRANGE(uint32_t, j, 1, i) {
+ EXPECT_FALSE(UnsignedAddOverflow32(i, j, &val));
+ EXPECT_EQ(i + j, val);
+ }
+ }
+}
+
+
TEST(Bits, UnsignedDiv32) {
TRACED_FORRANGE(uint32_t, i, 0, 50) {
EXPECT_EQ(0u, UnsignedDiv32(i, 0));
diff --git a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index 744f18f0bd..7e67b31616 100644
--- a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -47,7 +47,7 @@ Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
int64_t value) {
switch (type) {
case kMachInt32:
- return m.Int32Constant(value);
+ return m.Int32Constant(static_cast<int32_t>(value));
break;
case kMachInt64:
@@ -642,7 +642,9 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
if (shift.mi.machine_type != kMachInt32) continue;
if (shift.mi.arch_opcode == kArm64Ror32) continue;
- TRACED_FORRANGE(int, imm, 0, 31) {
+ // The available shift operand range is `0 <= imm < 32`, but we also test
+ // that immediates outside this range are handled properly (modulo-32).
+ TRACED_FORRANGE(int, imm, -32, 63) {
StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
m.Return((m.Int32Add)(
(m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
@@ -663,7 +665,9 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
if (shift.mi.machine_type != kMachInt64) continue;
if (shift.mi.arch_opcode == kArm64Ror) continue;
- TRACED_FORRANGE(int, imm, 0, 63) {
+ // The available shift operand range is `0 <= imm < 64`, but we also test
+ // that immediates outside this range are handled properly (modulo-64).
+ TRACED_FORRANGE(int, imm, -64, 127) {
StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
m.Return((m.Int64Add)(
(m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
@@ -1641,6 +1645,102 @@ TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
+ // x * (2^k + 1) + c -> x + (x << k) + c
+ TRACED_FORRANGE(int32_t, k, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Int32Add(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // (2^k + 1) * x + c -> x + (x << k) + c
+ TRACED_FORRANGE(int32_t, k, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Int32Add(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c + x * (2^k + 1) -> c + x + (x << k)
+ TRACED_FORRANGE(int32_t, k, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Int32Add(m.Parameter(0),
+ m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c + (2^k + 1) * x -> c + x + (x << k)
+ TRACED_FORRANGE(int32_t, k, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Int32Add(m.Parameter(0),
+ m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c - x * (2^k + 1) -> c - x + (x << k)
+ TRACED_FORRANGE(int32_t, k, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Int32Sub(m.Parameter(0),
+ m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c - (2^k + 1) * x -> c - x + (x << k)
+ TRACED_FORRANGE(int32_t, k, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ m.Return(
+ m.Int32Sub(m.Parameter(0),
+ m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
}
@@ -1671,6 +1771,102 @@ TEST_F(InstructionSelectorTest, Int64MulWithImmediate) {
EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
+ // x * (2^k + 1) + c -> x + (x << k) + c
+ TRACED_FORRANGE(int64_t, k, 1, 62) {
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
+ m.Return(
+ m.Int64Add(m.Int64Mul(m.Parameter(0), m.Int64Constant((1L << k) + 1)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // (2^k + 1) * x + c -> x + (x << k) + c
+ TRACED_FORRANGE(int64_t, k, 1, 62) {
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
+ m.Return(
+ m.Int64Add(m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(0)),
+ m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c + x * (2^k + 1) -> c + x + (x << k)
+ TRACED_FORRANGE(int64_t, k, 1, 62) {
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
+ m.Return(
+ m.Int64Add(m.Parameter(0),
+ m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c + (2^k + 1) * x -> c + x + (x << k)
+ TRACED_FORRANGE(int64_t, k, 1, 62) {
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
+ m.Return(
+ m.Int64Add(m.Parameter(0),
+ m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c - x * (2^k + 1) -> c - x + (x << k)
+ TRACED_FORRANGE(int64_t, k, 1, 62) {
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
+ m.Return(
+ m.Int64Sub(m.Parameter(0),
+ m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Sub, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // c - (2^k + 1) * x -> c - x + (x << k)
+ TRACED_FORRANGE(int64_t, k, 1, 62) {
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
+ m.Return(
+ m.Int64Sub(m.Parameter(0),
+ m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64Sub, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
}
@@ -2041,6 +2237,190 @@ TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
}
+TEST_F(InstructionSelectorTest, Word32EqualWithWord32Shift) {
+ TRACED_FOREACH(Shift, shift, kShiftInstructions) {
+ // Skip non 32-bit shifts or ror operations.
+ if (shift.mi.machine_type != kMachInt32 ||
+ shift.mi.arch_opcode == kArm64Ror32) {
+ continue;
+ }
+
+ TRACED_FORRANGE(int32_t, imm, -32, 63) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
+ m.Return(m.Word32Equal(p0, r));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ TRACED_FORRANGE(int32_t, imm, -32, 63) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
+ m.Return(m.Word32Equal(r, p0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendByte) {
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r = m.Word32And(p1, m.Int32Constant(0xff));
+ m.Return(m.Word32Equal(p0, r));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r = m.Word32And(p1, m.Int32Constant(0xff));
+ m.Return(m.Word32Equal(r, p0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendHalfword) {
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r = m.Word32And(p1, m.Int32Constant(0xffff));
+ m.Return(m.Word32Equal(p0, r));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r = m.Word32And(p1, m.Int32Constant(0xffff));
+ m.Return(m.Word32Equal(r, p0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendByte) {
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r =
+ m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24));
+ m.Return(m.Word32Equal(p0, r));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r =
+ m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24));
+ m.Return(m.Word32Equal(r, p0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendHalfword) {
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r =
+ m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16));
+ m.Return(m.Word32Equal(p0, r));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+ {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* r =
+ m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16));
+ m.Return(m.Word32Equal(r, p0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ }
+}
+
+
// -----------------------------------------------------------------------------
// Miscellaneous
@@ -2202,14 +2582,17 @@ TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
- TRACED_FORRANGE(int32_t, lsb, 1, 31) {
+ // The available shift operand range is `0 <= imm < 32`, but we also test
+ // that immediates outside this range are handled properly (modulo-32).
+ TRACED_FORRANGE(int32_t, shift, -32, 63) {
+ int32_t lsb = shift & 0x1f;
TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
uint32_t jnk = rng()->NextInt();
- jnk >>= 32 - lsb;
+ jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
- m.Int32Constant(lsb)));
+ m.Int32Constant(shift)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
@@ -2218,14 +2601,15 @@ TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
}
}
- TRACED_FORRANGE(int32_t, lsb, 1, 31) {
+ TRACED_FORRANGE(int32_t, shift, -32, 63) {
+ int32_t lsb = shift & 0x1f;
TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
uint32_t jnk = rng()->NextInt();
- jnk >>= 32 - lsb;
+ jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
- m.Int32Constant(lsb)));
+ m.Int32Constant(shift)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
@@ -2238,15 +2622,18 @@ TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
- TRACED_FORRANGE(int32_t, lsb, 1, 63) {
+ // The available shift operand range is `0 <= imm < 64`, but we also test
+ // that immediates outside this range are handled properly (modulo-64).
+ TRACED_FORRANGE(int32_t, shift, -64, 127) {
+ int32_t lsb = shift & 0x3f;
TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
uint64_t jnk = rng()->NextInt64();
- jnk >>= 64 - lsb;
+ jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
uint64_t msk =
((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
StreamBuilder m(this, kMachInt64, kMachInt64);
m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
- m.Int64Constant(lsb)));
+ m.Int64Constant(shift)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
@@ -2255,15 +2642,16 @@ TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
}
}
- TRACED_FORRANGE(int32_t, lsb, 1, 63) {
+ TRACED_FORRANGE(int32_t, shift, -64, 127) {
+ int32_t lsb = shift & 0x3f;
TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
uint64_t jnk = rng()->NextInt64();
- jnk >>= 64 - lsb;
+ jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
uint64_t msk =
((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
StreamBuilder m(this, kMachInt64, kMachInt64);
m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
- m.Int64Constant(lsb)));
+ m.Int64Constant(shift)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
@@ -2276,11 +2664,14 @@ TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
- TRACED_FORRANGE(int32_t, lsb, 1, 31) {
+ // The available shift operand range is `0 <= imm < 32`, but we also test
+ // that immediates outside this range are handled properly (modulo-32).
+ TRACED_FORRANGE(int32_t, shift, -32, 63) {
+ int32_t lsb = shift & 0x1f;
TRACED_FORRANGE(int32_t, width, 1, 31) {
uint32_t msk = (1 << width) - 1;
StreamBuilder m(this, kMachInt32, kMachInt32);
- m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
+ m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
m.Int32Constant(msk)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
@@ -2291,12 +2682,14 @@ TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
}
}
- TRACED_FORRANGE(int32_t, lsb, 1, 31) {
+ TRACED_FORRANGE(int32_t, shift, -32, 63) {
+ int32_t lsb = shift & 0x1f;
TRACED_FORRANGE(int32_t, width, 1, 31) {
uint32_t msk = (1 << width) - 1;
StreamBuilder m(this, kMachInt32, kMachInt32);
- m.Return(m.Word32And(m.Int32Constant(msk),
- m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
+ m.Return(
+ m.Word32And(m.Int32Constant(msk),
+ m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
@@ -2310,11 +2703,14 @@ TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
- TRACED_FORRANGE(int64_t, lsb, 1, 63) {
+ // The available shift operand range is `0 <= imm < 64`, but we also test
+ // that immediates outside this range are handled properly (modulo-64).
+ TRACED_FORRANGE(int64_t, shift, -64, 127) {
+ int64_t lsb = shift & 0x3f;
TRACED_FORRANGE(int64_t, width, 1, 63) {
uint64_t msk = (V8_UINT64_C(1) << width) - 1;
StreamBuilder m(this, kMachInt64, kMachInt64);
- m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)),
+ m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)),
m.Int64Constant(msk)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
@@ -2325,12 +2721,14 @@ TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
}
}
- TRACED_FORRANGE(int64_t, lsb, 1, 63) {
+ TRACED_FORRANGE(int64_t, shift, -64, 127) {
+ int64_t lsb = shift & 0x3f;
TRACED_FORRANGE(int64_t, width, 1, 63) {
uint64_t msk = (V8_UINT64_C(1) << width) - 1;
StreamBuilder m(this, kMachInt64, kMachInt64);
- m.Return(m.Word64And(m.Int64Constant(msk),
- m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb))));
+ m.Return(
+ m.Word64And(m.Int64Constant(msk),
+ m.Word64Shr(m.Parameter(0), m.Int64Constant(shift))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
@@ -2365,6 +2763,87 @@ TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
}
+TEST_F(InstructionSelectorTest, Int32MulHighWithSar) {
+ TRACED_FORRANGE(int32_t, shift, -32, 63) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const n = m.Word32Sar(m.Int32MulHigh(p0, p1), m.Int32Constant(shift));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
+ ASSERT_EQ(2U, s[1]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
+ EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
+ ASSERT_EQ(1U, s[1]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, Int32MulHighWithAdd) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const a = m.Int32Add(m.Int32MulHigh(p0, p1), p0);
+ // Test only one shift constant here, as we're only interested in it being a
+ // 32-bit operation; the shift amount is irrelevant.
+ Node* const n = m.Word32Sar(a, m.Int32Constant(1));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(3U, s.size());
+ EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_ASR_I, s[1]->addressing_mode());
+ ASSERT_EQ(3U, s[1]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
+ EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(2)));
+ ASSERT_EQ(1U, s[1]->OutputCount());
+ EXPECT_EQ(kArm64Asr32, s[2]->arch_opcode());
+ ASSERT_EQ(2U, s[2]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(0)));
+ EXPECT_EQ(1, s.ToInt64(s[2]->InputAt(1)));
+ ASSERT_EQ(1U, s[2]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[2]->Output()));
+}
+
+
+TEST_F(InstructionSelectorTest, Uint32MulHighWithShr) {
+ TRACED_FORRANGE(int32_t, shift, -32, 63) {
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const n =
+ m.Word32Shr(m.Uint32MulHigh(p0, p1), m.Int32Constant(shift));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64Umull, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kArm64Lsr, s[1]->arch_opcode());
+ ASSERT_EQ(2U, s[1]->InputCount());
+ EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
+ EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
+ ASSERT_EQ(1U, s[1]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
+ }
+}
+
+
TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
TRACED_FORRANGE(int32_t, shift, 1, 31) {
StreamBuilder m(this, kMachInt32, kMachInt32);
@@ -2429,6 +2908,40 @@ TEST_F(InstructionSelectorTest, Word32ShrWithWord32Shl) {
}
+TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
+ TRACED_FORRANGE(int32_t, shift, 1, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
+ m.Int32Constant(shift));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Ubfiz32, s[0]->arch_opcode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+ TRACED_FORRANGE(int32_t, shift, 0, 30) {
+ StreamBuilder m(this, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
+ m.Int32Constant(shift + 1));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Lsl32, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+}
+
+
TEST_F(InstructionSelectorTest, Word32Clz) {
StreamBuilder m(this, kMachUint32, kMachUint32);
Node* const p0 = m.Parameter(0);
diff --git a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
index d6822e8b09..13d2d6707a 100644
--- a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
@@ -4,14 +4,16 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/common-operator-reducer.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/machine-type.h"
#include "src/compiler/operator.h"
+#include "src/compiler/simplified-operator.h"
+#include "test/unittests/compiler/graph-reducer-unittest.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
+using testing::StrictMock;
+
namespace v8 {
namespace internal {
namespace compiler {
@@ -19,23 +21,30 @@ namespace compiler {
class CommonOperatorReducerTest : public GraphTest {
public:
explicit CommonOperatorReducerTest(int num_parameters = 1)
- : GraphTest(num_parameters), machine_(zone()) {}
+ : GraphTest(num_parameters), machine_(zone()), simplified_(zone()) {}
~CommonOperatorReducerTest() override {}
protected:
- Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
- MachineOperatorBuilder::kNoFlags) {
- JSOperatorBuilder javascript(zone());
+ Reduction Reduce(
+ AdvancedReducer::Editor* editor, Node* node,
+ MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) {
MachineOperatorBuilder machine(zone(), kMachPtr, flags);
- JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
- CommonOperatorReducer reducer(&jsgraph);
+ CommonOperatorReducer reducer(editor, graph(), common(), &machine);
return reducer.Reduce(node);
}
+ Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::kNoFlags) {
+ StrictMock<MockAdvancedReducerEditor> editor;
+ return Reduce(&editor, node, flags);
+ }
+
MachineOperatorBuilder* machine() { return &machine_; }
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
private:
MachineOperatorBuilder machine_;
+ SimplifiedOperatorBuilder simplified_;
};
@@ -58,32 +67,213 @@ const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0);
// -----------------------------------------------------------------------------
+// Branch
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithInt32ZeroConstant) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch =
+ graph()->NewNode(common()->Branch(hint), Int32Constant(0), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(if_true, IsDead()));
+ EXPECT_CALL(editor, Replace(if_false, control));
+ Reduction const r = Reduce(&editor, branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithInt32OneConstant) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch =
+ graph()->NewNode(common()->Branch(hint), Int32Constant(1), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(if_true, control));
+ EXPECT_CALL(editor, Replace(if_false, IsDead()));
+ Reduction const r = Reduce(&editor, branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithInt64ZeroConstant) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch =
+ graph()->NewNode(common()->Branch(hint), Int64Constant(0), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(if_true, IsDead()));
+ EXPECT_CALL(editor, Replace(if_false, control));
+ Reduction const r = Reduce(&editor, branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithInt64OneConstant) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch =
+ graph()->NewNode(common()->Branch(hint), Int64Constant(1), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(if_true, control));
+ EXPECT_CALL(editor, Replace(if_false, IsDead()));
+ Reduction const r = Reduce(&editor, branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch =
+ graph()->NewNode(common()->Branch(hint), FalseConstant(), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(if_true, IsDead()));
+ EXPECT_CALL(editor, Replace(if_false, control));
+ Reduction const r = Reduce(&editor, branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithTrueConstant) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch =
+ graph()->NewNode(common()->Branch(hint), TrueConstant(), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(if_true, control));
+ EXPECT_CALL(editor, Replace(if_false, IsDead()));
+ Reduction const r = Reduce(&editor, branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) {
+ Node* const value = Parameter(0);
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch = graph()->NewNode(
+ common()->Branch(hint),
+ graph()->NewNode(simplified()->BooleanNot(), value), control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Reduction const r = Reduce(branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(branch, r.replacement());
+ EXPECT_THAT(branch, IsBranch(value, control));
+ EXPECT_THAT(if_false, IsIfTrue(branch));
+ EXPECT_THAT(if_true, IsIfFalse(branch));
+ EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op()));
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Merge
+
+
+TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond0) {
+ Node* const value = Parameter(0);
+ Node* const control = graph()->start();
+ Node* const branch = graph()->NewNode(common()->Branch(), value, control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->Merge(2), if_true, if_false));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(control, r.replacement());
+ EXPECT_THAT(branch, IsDead());
+}
+
+
+TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond1) {
+ Node* const value = Parameter(0);
+ Node* const control = graph()->start();
+ Node* const branch = graph()->NewNode(common()->Branch(), value, control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->Merge(2), if_false, if_true));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(control, r.replacement());
+ EXPECT_THAT(branch, IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
// EffectPhi
-TEST_F(CommonOperatorReducerTest, RedundantEffectPhi) {
+TEST_F(CommonOperatorReducerTest, EffectPhiWithMerge) {
const int kMaxInputs = 64;
Node* inputs[kMaxInputs];
Node* const input = graph()->NewNode(&kOp0);
TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
int const value_input_count = input_count - 1;
for (int i = 0; i < value_input_count; ++i) {
+ inputs[i] = graph()->start();
+ }
+ Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
+ value_input_count, inputs);
+ for (int i = 0; i < value_input_count; ++i) {
inputs[i] = input;
}
- inputs[value_input_count] = graph()->start();
- Reduction r = Reduce(graph()->NewNode(
- common()->EffectPhi(value_input_count), input_count, inputs));
+ inputs[value_input_count] = merge;
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r =
+ Reduce(&editor, graph()->NewNode(common()->EffectPhi(value_input_count),
+ input_count, inputs));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(input, r.replacement());
}
}
+TEST_F(CommonOperatorReducerTest, EffectPhiWithLoop) {
+ Node* const e0 = graph()->NewNode(&kOp0);
+ Node* const loop =
+ graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
+ loop->ReplaceInput(1, loop);
+ Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e0, loop);
+ ephi->ReplaceInput(1, ephi);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(loop));
+ Reduction const r = Reduce(&editor, ephi);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(e0, r.replacement());
+}
+
+
// -----------------------------------------------------------------------------
// Phi
-TEST_F(CommonOperatorReducerTest, RedundantPhi) {
+TEST_F(CommonOperatorReducerTest, PhiWithMerge) {
const int kMaxInputs = 64;
Node* inputs[kMaxInputs];
Node* const input = graph()->NewNode(&kOp0);
@@ -93,14 +283,17 @@ TEST_F(CommonOperatorReducerTest, RedundantPhi) {
for (int i = 0; i < value_input_count; ++i) {
inputs[i] = graph()->start();
}
- Node* merge = graph()->NewNode(common()->Merge(value_input_count),
- value_input_count, inputs);
+ Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
+ value_input_count, inputs);
for (int i = 0; i < value_input_count; ++i) {
inputs[i] = input;
}
inputs[value_input_count] = merge;
- Reduction r = Reduce(graph()->NewNode(
- common()->Phi(type, value_input_count), input_count, inputs));
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(
+ &editor, graph()->NewNode(common()->Phi(type, value_input_count),
+ input_count, inputs));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(input, r.replacement());
}
@@ -108,6 +301,22 @@ TEST_F(CommonOperatorReducerTest, RedundantPhi) {
}
+TEST_F(CommonOperatorReducerTest, PhiWithLoop) {
+ Node* const p0 = Parameter(0);
+ Node* const loop =
+ graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
+ loop->ReplaceInput(1, loop);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), p0, p0, loop);
+ phi->ReplaceInput(1, phi);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(loop));
+ Reduction const r = Reduce(&editor, phi);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(p0, r.replacement());
+}
+
+
TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) {
Node* p0 = Parameter(0);
Node* c0 = Float32Constant(0.0);
@@ -120,7 +329,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) {
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi =
graph()->NewNode(common()->Phi(kMachFloat32, 2), vtrue, vfalse, merge);
- Reduction r = Reduce(phi);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(&editor, phi);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
}
@@ -138,7 +349,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat64Abs) {
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi =
graph()->NewNode(common()->Phi(kMachFloat64, 2), vtrue, vfalse, merge);
- Reduction r = Reduce(phi);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(&editor, phi);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
}
@@ -153,7 +366,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat32Max) {
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi = graph()->NewNode(common()->Phi(kMachFloat32, 2), p1, p0, merge);
- Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat32Max);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Max);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat32Max(p1, p0));
}
@@ -168,7 +383,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat64Max) {
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi = graph()->NewNode(common()->Phi(kMachFloat64, 2), p1, p0, merge);
- Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat64Max);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Max);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Max(p1, p0));
}
@@ -183,7 +400,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat32Min) {
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi = graph()->NewNode(common()->Phi(kMachFloat32, 2), p0, p1, merge);
- Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat32Min);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Min);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat32Min(p0, p1));
}
@@ -198,17 +417,48 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat64Min) {
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi = graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge);
- Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat64Min);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(merge));
+ Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Min);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Min(p0, p1));
}
// -----------------------------------------------------------------------------
+// Return
+
+
+TEST_F(CommonOperatorReducerTest, ReturnWithPhiAndEffectPhiAndMerge) {
+ Node* cond = Parameter(2);
+ Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start());
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = graph()->start();
+ Node* vtrue = Parameter(0);
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* efalse = graph()->start();
+ Node* vfalse = Parameter(1);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
+ Node* phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vtrue, vfalse, merge);
+ Node* ret = graph()->NewNode(common()->Return(), phi, ephi, merge);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(merge, IsDead()));
+ Reduction const r = Reduce(&editor, ret);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ EXPECT_THAT(graph()->end(), IsEnd(ret, IsReturn(vtrue, etrue, if_true),
+ IsReturn(vfalse, efalse, if_false)));
+}
+
+
+// -----------------------------------------------------------------------------
// Select
-TEST_F(CommonOperatorReducerTest, RedundantSelect) {
+TEST_F(CommonOperatorReducerTest, SelectWithSameThenAndElse) {
Node* const input = graph()->NewNode(&kOp0);
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
TRACED_FOREACH(MachineType, type, kMachineTypes) {
@@ -221,6 +471,50 @@ TEST_F(CommonOperatorReducerTest, RedundantSelect) {
}
+TEST_F(CommonOperatorReducerTest, SelectWithInt32ZeroConstant) {
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* select = graph()->NewNode(common()->Select(kMachAnyTagged),
+ Int32Constant(0), p0, p1);
+ Reduction r = Reduce(select);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(p1, r.replacement());
+}
+
+
+TEST_F(CommonOperatorReducerTest, SelectWithInt32OneConstant) {
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* select = graph()->NewNode(common()->Select(kMachAnyTagged),
+ Int32Constant(1), p0, p1);
+ Reduction r = Reduce(select);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(p0, r.replacement());
+}
+
+
+TEST_F(CommonOperatorReducerTest, SelectWithInt64ZeroConstant) {
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* select = graph()->NewNode(common()->Select(kMachAnyTagged),
+ Int64Constant(0), p0, p1);
+ Reduction r = Reduce(select);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(p1, r.replacement());
+}
+
+
+TEST_F(CommonOperatorReducerTest, SelectWithInt64OneConstant) {
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* select = graph()->NewNode(common()->Select(kMachAnyTagged),
+ Int64Constant(1), p0, p1);
+ Reduction r = Reduce(select);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(p0, r.replacement());
+}
+
+
TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) {
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
diff --git a/deps/v8/test/unittests/compiler/common-operator-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-unittest.cc
index 4f4d9f70d0..8765c13271 100644
--- a/deps/v8/test/unittests/compiler/common-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/common-operator-unittest.cc
@@ -48,15 +48,13 @@ const SharedOperator kSharedOperators[] = {
value_input_count, effect_input_count, control_input_count, \
value_output_count, effect_output_count, control_output_count \
}
- SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1),
- SHARED(End, Operator::kKontrol, 0, 0, 1, 0, 0, 0),
+ SHARED(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1),
SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
- SHARED(IfException, Operator::kKontrol, 0, 0, 1, 1, 0, 1),
SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1),
SHARED(Return, Operator::kNoThrow, 1, 1, 1, 0, 0, 1),
- SHARED(Terminate, Operator::kNoThrow, 0, 1, 1, 0, 0, 1)
+ SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)
#undef SHARED
};
@@ -162,6 +160,9 @@ const double kDoubleValues[] = {-std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::signaling_NaN()};
+const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000};
+
+
const int32_t kInt32Values[] = {
std::numeric_limits<int32_t>::min(), -1914954528, -1698749618, -1578693386,
-1577976073, -1573998034, -1529085059, -1499540537, -1299205097,
@@ -176,14 +177,31 @@ const int32_t kInt32Values[] = {
2008792749, 2045320228, std::numeric_limits<int32_t>::max()};
-const BranchHint kHints[] = {BranchHint::kNone, BranchHint::kTrue,
- BranchHint::kFalse};
+const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kTrue,
+ BranchHint::kFalse};
} // namespace
+TEST_F(CommonOperatorTest, End) {
+ TRACED_FOREACH(size_t, input_count, kInputCounts) {
+ const Operator* const op = common()->End(input_count);
+ EXPECT_EQ(IrOpcode::kEnd, op->opcode());
+ EXPECT_EQ(Operator::kKontrol, op->properties());
+ EXPECT_EQ(0, op->ValueInputCount());
+ EXPECT_EQ(0, op->EffectInputCount());
+ EXPECT_EQ(input_count, static_cast<uint32_t>(op->ControlInputCount()));
+ EXPECT_EQ(input_count, static_cast<uint32_t>(
+ OperatorProperties::GetTotalInputCount(op)));
+ EXPECT_EQ(0, op->ValueOutputCount());
+ EXPECT_EQ(0, op->EffectOutputCount());
+ EXPECT_EQ(0, op->ControlOutputCount());
+ }
+}
+
+
TEST_F(CommonOperatorTest, Branch) {
- TRACED_FOREACH(BranchHint, hint, kHints) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
const Operator* const op = common()->Branch(hint);
EXPECT_EQ(IrOpcode::kBranch, op->opcode());
EXPECT_EQ(Operator::kKontrol, op->properties());
@@ -199,6 +217,24 @@ TEST_F(CommonOperatorTest, Branch) {
}
+TEST_F(CommonOperatorTest, IfException) {
+ static const IfExceptionHint kIfExceptionHints[] = {
+ IfExceptionHint::kLocallyCaught, IfExceptionHint::kLocallyUncaught};
+ TRACED_FOREACH(IfExceptionHint, hint, kIfExceptionHints) {
+ const Operator* const op = common()->IfException(hint);
+ EXPECT_EQ(IrOpcode::kIfException, op->opcode());
+ EXPECT_EQ(Operator::kKontrol, op->properties());
+ EXPECT_EQ(0, op->ValueInputCount());
+ EXPECT_EQ(1, op->EffectInputCount());
+ EXPECT_EQ(1, op->ControlInputCount());
+ EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
+ EXPECT_EQ(1, op->ValueOutputCount());
+ EXPECT_EQ(1, op->EffectOutputCount());
+ EXPECT_EQ(1, op->ControlOutputCount());
+ }
+}
+
+
TEST_F(CommonOperatorTest, Switch) {
TRACED_FOREACH(size_t, cases, kCases) {
const Operator* const op = common()->Switch(cases);
@@ -238,7 +274,7 @@ TEST_F(CommonOperatorTest, Select) {
kMachInt32, kMachUint32, kMachInt64, kMachUint64,
kMachFloat32, kMachFloat64, kMachAnyTagged};
TRACED_FOREACH(MachineType, type, kTypes) {
- TRACED_FOREACH(BranchHint, hint, kHints) {
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
const Operator* const op = common()->Select(type, hint);
EXPECT_EQ(IrOpcode::kSelect, op->opcode());
EXPECT_EQ(Operator::kPure, op->properties());
diff --git a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
index 515bd061ef..47be5407f7 100644
--- a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
+++ b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
@@ -27,7 +27,7 @@ class ControlEquivalenceTest : public GraphTest {
protected:
void ComputeEquivalence(Node* node) {
- graph()->SetEnd(graph()->NewNode(common()->End(), node));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), node));
if (FLAG_trace_turbo) {
OFStream os(stdout);
os << AsDOT(*graph());
@@ -41,7 +41,7 @@ class ControlEquivalenceTest : public GraphTest {
}
bool IsEquivalenceClass(size_t length, Node** nodes) {
- BitVector in_class(graph()->NodeCount(), zone());
+ BitVector in_class(static_cast<int>(graph()->NodeCount()), zone());
size_t expected_class = classes_[nodes[0]->id()];
for (size_t i = 0; i < length; ++i) {
in_class.Add(nodes[i]->id());
@@ -79,7 +79,7 @@ class ControlEquivalenceTest : public GraphTest {
}
Node* End(Node* control) {
- return Store(graph()->NewNode(common()->End(), control));
+ return Store(graph()->NewNode(common()->End(1), control));
}
private:
diff --git a/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc b/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
index 190930edac..444f5f5fee 100644
--- a/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "src/compiler/control-flow-optimizer.h"
-#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "test/unittests/compiler/graph-unittest.h"
@@ -21,28 +20,21 @@ namespace compiler {
class ControlFlowOptimizerTest : public GraphTest {
public:
explicit ControlFlowOptimizerTest(int num_parameters = 3)
- : GraphTest(num_parameters),
- machine_(zone()),
- javascript_(zone()),
- jsgraph_(isolate(), graph(), common(), javascript(), machine()) {}
+ : GraphTest(num_parameters), machine_(zone()), javascript_(zone()) {}
~ControlFlowOptimizerTest() override {}
protected:
void Optimize() {
- ControlFlowOptimizer optimizer(jsgraph(), zone());
+ ControlFlowOptimizer optimizer(graph(), common(), machine(), zone());
optimizer.Optimize();
}
- Node* EmptyFrameState() { return jsgraph()->EmptyFrameState(); }
-
- JSGraph* jsgraph() { return &jsgraph_; }
JSOperatorBuilder* javascript() { return &javascript_; }
MachineOperatorBuilder* machine() { return &machine_; }
private:
MachineOperatorBuilder machine_;
JSOperatorBuilder javascript_;
- JSGraph jsgraph_;
};
@@ -62,7 +54,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* merge =
graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
- graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
Optimize();
Capture<Node*> switch_capture;
EXPECT_THAT(end(),
@@ -77,7 +69,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
Node* input = Parameter(0);
Node* context = Parameter(1);
Node* index = graph()->NewNode(javascript()->ToNumber(), input, context,
- EmptyFrameState(), start(), start());
+ start(), start(), start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), index);
Node* branch0 = graph()->NewNode(
common()->Branch(),
@@ -93,7 +85,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* merge =
graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
- graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
Optimize();
Capture<Node*> switch_capture;
EXPECT_THAT(
@@ -119,7 +111,7 @@ TEST_F(ControlFlowOptimizerTest, CloneBranch) {
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
- graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
Optimize();
Capture<Node*> branch1_capture, branch2_capture;
EXPECT_THAT(
diff --git a/deps/v8/test/unittests/compiler/control-reducer-unittest.cc b/deps/v8/test/unittests/compiler/control-reducer-unittest.cc
deleted file mode 100644
index 2f65caadc3..0000000000
--- a/deps/v8/test/unittests/compiler/control-reducer-unittest.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-// 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/control-reducer.h"
-#include "src/compiler/diamond.h"
-#include "src/compiler/graph-visualizer.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "test/unittests/compiler/graph-unittest.h"
-#include "test/unittests/compiler/node-test-utils.h"
-#include "testing/gmock-support.h"
-
-using testing::_;
-using testing::AllOf;
-using testing::Capture;
-using testing::CaptureEq;
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class ControlReducerTest : public TypedGraphTest {
- public:
- ControlReducerTest()
- : TypedGraphTest(1),
- machine_(zone()),
- javascript_(zone()),
- jsgraph_(isolate(), graph(), common(), &javascript_, &machine_) {}
-
- protected:
- MachineOperatorBuilder machine_;
- JSOperatorBuilder javascript_;
- JSGraph jsgraph_;
-
- void ReduceGraph(int max_phis_for_select = 0) {
- if (FLAG_trace_turbo_graph) {
- OFStream os(stdout);
- os << "-- Graph before control reduction" << std::endl;
- os << AsRPO(*graph());
- }
- ControlReducer::ReduceGraph(zone(), jsgraph(), max_phis_for_select);
- if (FLAG_trace_turbo_graph) {
- OFStream os(stdout);
- os << "-- Graph after control reduction" << std::endl;
- os << AsRPO(*graph());
- }
- }
-
- JSGraph* jsgraph() { return &jsgraph_; }
-};
-
-
-TEST_F(ControlReducerTest, NonTerminatingLoop) {
- Node* loop = graph()->NewNode(common()->Loop(2), graph()->start());
- loop->AppendInput(graph()->zone(), loop);
- ReduceGraph();
- EXPECT_THAT(
- graph()->end(),
- IsEnd(IsMerge(graph()->start(),
- IsTerminate(graph()->start(),
- AllOf(loop, IsLoop(graph()->start(), loop))))));
-}
-
-
-TEST_F(ControlReducerTest, NonTerminatingLoopWithEffectPhi) {
- Node* loop = graph()->NewNode(common()->Loop(2), graph()->start());
- loop->AppendInput(graph()->zone(), loop);
- Node* ephi = graph()->NewNode(common()->EffectPhi(2), graph()->start());
- ephi->AppendInput(graph()->zone(), ephi);
- ephi->AppendInput(graph()->zone(), loop);
- ReduceGraph();
- EXPECT_THAT(
- graph()->end(),
- IsEnd(IsMerge(
- graph()->start(),
- IsTerminate(AllOf(ephi, IsEffectPhi(graph()->start(), ephi, loop)),
- AllOf(loop, IsLoop(graph()->start(), loop))))));
-}
-
-
-TEST_F(ControlReducerTest, NonTerminatingLoopWithTwoEffectPhis) {
- Node* loop = graph()->NewNode(common()->Loop(2), graph()->start());
- loop->AppendInput(graph()->zone(), loop);
- Node* ephi1 = graph()->NewNode(common()->EffectPhi(2), graph()->start());
- ephi1->AppendInput(graph()->zone(), ephi1);
- ephi1->AppendInput(graph()->zone(), loop);
- Node* ephi2 = graph()->NewNode(common()->EffectPhi(2), graph()->start());
- ephi2->AppendInput(graph()->zone(), ephi2);
- ephi2->AppendInput(graph()->zone(), loop);
- ReduceGraph();
- EXPECT_THAT(
- graph()->end(),
- IsEnd(IsMerge(
- graph()->start(),
- IsTerminate(
- IsEffectSet(
- AllOf(ephi1, IsEffectPhi(graph()->start(), ephi1, loop)),
- AllOf(ephi2, IsEffectPhi(graph()->start(), ephi2, loop))),
- AllOf(loop, IsLoop(graph()->start(), loop))))));
-}
-
-
-TEST_F(ControlReducerTest, NonTerminatingLoopWithDeadEnd) {
- Node* loop = graph()->NewNode(common()->Loop(2), graph()->start());
- loop->AppendInput(graph()->zone(), loop);
- graph()->end()->ReplaceInput(0, graph()->NewNode(common()->Dead()));
- ReduceGraph();
- EXPECT_THAT(graph()->end(),
- IsEnd(IsTerminate(graph()->start(),
- AllOf(loop, IsLoop(graph()->start(), loop)))));
-}
-
-
-TEST_F(ControlReducerTest, PhiAsInputToBranch_true) {
- Node* p0 = Parameter(0);
- Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
- Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(1),
- jsgraph()->Int32Constant(2), merge1);
-
- Node* branch2 = graph()->NewNode(common()->Branch(), phi1, merge1);
- Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
- Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
- Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
- Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(11),
- jsgraph()->Int32Constant(22), merge2);
-
- Node* ret =
- graph()->NewNode(common()->Return(), result, graph()->start(), merge2);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph();
-
- // First diamond is not reduced.
- EXPECT_THAT(merge1, IsMerge(IsIfTrue(branch1), IsIfFalse(branch1)));
-
- // Second diamond should be folded away.
- EXPECT_THAT(graph()->end(),
- IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), merge1)));
-}
-
-
-TEST_F(ControlReducerTest, PhiAsInputToBranch_false) {
- Node* p0 = Parameter(0);
- Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
- Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(0),
- jsgraph()->BooleanConstant(false), merge1);
-
- Node* branch2 = graph()->NewNode(common()->Branch(), phi1, merge1);
- Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
- Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
- Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
- Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(11),
- jsgraph()->Int32Constant(22), merge2);
-
- Node* ret =
- graph()->NewNode(common()->Return(), result, graph()->start(), merge2);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph();
-
- // First diamond is not reduced.
- EXPECT_THAT(merge1, IsMerge(IsIfTrue(branch1), IsIfFalse(branch1)));
-
- // Second diamond should be folded away.
- EXPECT_THAT(graph()->end(),
- IsEnd(IsReturn(IsInt32Constant(22), graph()->start(), merge1)));
-}
-
-
-TEST_F(ControlReducerTest, PhiAsInputToBranch_unknown_true) {
- Node* p0 = Parameter(0);
- Node* phi0 = graph()->NewNode(common()->Phi(kMachInt32, 2), p0,
- jsgraph()->Int32Constant(1), graph()->start());
- Node* branch1 = graph()->NewNode(common()->Branch(), phi0, graph()->start());
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
- Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(111),
- jsgraph()->Int32Constant(222), merge1);
-
- Node* ret =
- graph()->NewNode(common()->Return(), phi1, graph()->start(), merge1);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph();
-
- // Branch should not be folded.
- EXPECT_THAT(phi1,
- IsPhi(kMachInt32, IsInt32Constant(111), IsInt32Constant(222),
- IsMerge(IsIfTrue(branch1), IsIfFalse(branch1))));
- EXPECT_THAT(graph()->end(), IsEnd(IsReturn(phi1, graph()->start(), merge1)));
-}
-
-
-TEST_F(ControlReducerTest, RangeAsInputToBranch_true1) {
- Node* p0 = Parameter(Type::Range(1, 2, zone()), 0);
- Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* merge1 = graph()->NewNode(common()->Merge(1), if_true1, if_false1);
- Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(11),
- jsgraph()->Int32Constant(44), merge1);
-
- Node* ret =
- graph()->NewNode(common()->Return(), result, graph()->start(), merge1);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph();
-
- // Diamond should be folded away.
- EXPECT_THAT(
- graph()->end(),
- IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), graph()->start())));
-}
-
-
-TEST_F(ControlReducerTest, RangeAsInputToBranch_true2) {
- Node* p0 = Parameter(Type::Range(-2, -1, zone()), 0);
- Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* merge1 = graph()->NewNode(common()->Merge(1), if_true1, if_false1);
- Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2),
- jsgraph()->Int32Constant(11),
- jsgraph()->Int32Constant(44), merge1);
-
- Node* ret =
- graph()->NewNode(common()->Return(), result, graph()->start(), merge1);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph();
-
- // Diamond should be folded away.
- EXPECT_THAT(
- graph()->end(),
- IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), graph()->start())));
-}
-
-
-TEST_F(ControlReducerTest, SelectPhi) {
- Node* p0 = Parameter(0);
- const MachineType kType = kMachInt32;
- Diamond d(graph(), common(), p0);
- Node* phi =
- d.Phi(kType, jsgraph()->Int32Constant(1), jsgraph()->Int32Constant(2));
-
- Node* ret =
- graph()->NewNode(common()->Return(), phi, graph()->start(), d.merge);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph(1);
-
- // Phi should be replaced with a select.
- EXPECT_THAT(graph()->end(),
- IsEnd(IsReturn(
- IsSelect(kType, p0, IsInt32Constant(1), IsInt32Constant(2)),
- graph()->start(), graph()->start())));
-}
-
-
-TEST_F(ControlReducerTest, SelectPhis_fail) {
- Node* p0 = Parameter(0);
- const MachineType kType = kMachInt32;
- Diamond d(graph(), common(), p0);
- Node* phi =
- d.Phi(kType, jsgraph()->Int32Constant(1), jsgraph()->Int32Constant(2));
- Node* phi2 =
- d.Phi(kType, jsgraph()->Int32Constant(11), jsgraph()->Int32Constant(22));
- USE(phi2);
- Node* ret =
- graph()->NewNode(common()->Return(), phi, graph()->start(), d.merge);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph(1);
-
- // Diamond should not be replaced with a select (too many phis).
- EXPECT_THAT(ret, IsReturn(phi, graph()->start(), d.merge));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-}
-
-
-TEST_F(ControlReducerTest, SelectTwoPhis) {
- Node* p0 = Parameter(0);
- const MachineType kType = kMachInt32;
- Diamond d(graph(), common(), p0);
- Node* phi1 =
- d.Phi(kType, jsgraph()->Int32Constant(1), jsgraph()->Int32Constant(2));
- Node* phi2 =
- d.Phi(kType, jsgraph()->Int32Constant(2), jsgraph()->Int32Constant(3));
- MachineOperatorBuilder machine(zone());
- Node* add = graph()->NewNode(machine.Int32Add(), phi1, phi2);
- Node* ret =
- graph()->NewNode(common()->Return(), add, graph()->start(), d.merge);
- graph()->end()->ReplaceInput(0, ret);
-
- ReduceGraph(2);
-
- // Phis should be replaced with two selects.
- EXPECT_THAT(
- ret,
- IsReturn(IsInt32Add(
- IsSelect(kType, p0, IsInt32Constant(1), IsInt32Constant(2)),
- IsSelect(kType, p0, IsInt32Constant(2), IsInt32Constant(3))),
- graph()->start(), graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-}
-
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc b/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc
new file mode 100644
index 0000000000..8284fd8775
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc
@@ -0,0 +1,375 @@
+// 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/dead-code-elimination.h"
+#include "test/unittests/compiler/graph-reducer-unittest.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::StrictMock;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class DeadCodeEliminationTest : public GraphTest {
+ public:
+ explicit DeadCodeEliminationTest(int num_parameters = 4)
+ : GraphTest(num_parameters) {}
+ ~DeadCodeEliminationTest() override {}
+
+ protected:
+ Reduction Reduce(AdvancedReducer::Editor* editor, Node* node) {
+ DeadCodeElimination reducer(editor, graph(), common());
+ return reducer.Reduce(node);
+ }
+
+ Reduction Reduce(Node* node) {
+ StrictMock<MockAdvancedReducerEditor> editor;
+ return Reduce(&editor, node);
+ }
+};
+
+
+namespace {
+
+const MachineType kMachineTypes[] = {
+ kMachFloat32, kMachFloat64, kMachInt8, kMachUint8, kMachInt16,
+ kMachUint16, kMachInt32, kMachUint32, kMachInt64, kMachUint64,
+ kMachPtr, kMachAnyTagged, kRepBit, kRepWord8, kRepWord16,
+ kRepWord32, kRepWord64, kRepFloat32, kRepFloat64, kRepTagged};
+
+
+const int kMaxInputs = 16;
+
+
+const Operator kOp0(0, Operator::kNoProperties, "Op0", 1, 1, 1, 1, 1, 1);
+
+} // namespace
+
+
+// -----------------------------------------------------------------------------
+// General dead propagation
+
+
+TEST_F(DeadCodeEliminationTest, GeneralDeadPropagation) {
+ Node* const value = Parameter(0);
+ Node* const effect = graph()->start();
+ Node* const dead = graph()->NewNode(common()->Dead());
+ Node* const node = graph()->NewNode(&kOp0, value, effect, dead);
+ Reduction const r = Reduce(node);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// Branch
+
+
+TEST_F(DeadCodeEliminationTest, BranchWithDeadControlInput) {
+ BranchHint const kHints[] = {BranchHint::kNone, BranchHint::kTrue,
+ BranchHint::kFalse};
+ TRACED_FOREACH(BranchHint, hint, kHints) {
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->Branch(hint), Parameter(0),
+ graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// IfTrue
+
+
+TEST_F(DeadCodeEliminationTest, IfTrueWithDeadInput) {
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->IfTrue(), graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// IfFalse
+
+
+TEST_F(DeadCodeEliminationTest, IfFalseWithDeadInput) {
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->IfFalse(), graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// IfSuccess
+
+
+TEST_F(DeadCodeEliminationTest, IfSuccessWithDeadInput) {
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->IfSuccess(), graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+
+// -----------------------------------------------------------------------------
+// IfException
+
+
+TEST_F(DeadCodeEliminationTest, IfExceptionWithDeadControlInput) {
+ IfExceptionHint const kHints[] = {IfExceptionHint::kLocallyCaught,
+ IfExceptionHint::kLocallyUncaught};
+ TRACED_FOREACH(IfExceptionHint, hint, kHints) {
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->IfException(hint), graph()->start(),
+ graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// End
+
+
+TEST_F(DeadCodeEliminationTest, EndWithDeadAndStart) {
+ Node* const dead = graph()->NewNode(common()->Dead());
+ Node* const start = graph()->start();
+ Reduction const r = Reduce(graph()->NewNode(common()->End(2), dead, start));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsEnd(start));
+}
+
+
+TEST_F(DeadCodeEliminationTest, EndWithOnlyDeadInputs) {
+ Node* inputs[kMaxInputs];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->NewNode(common()->Dead());
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->End(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Merge
+
+
+TEST_F(DeadCodeEliminationTest, MergeWithOnlyDeadInputs) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->NewNode(common()->Dead());
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->Merge(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(DeadCodeEliminationTest, MergeWithOneLiveAndOneDeadInput) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const e0 = graph()->NewNode(&kOp0, v0, graph()->start(), c0);
+ Node* const e1 = graph()->NewNode(&kOp0, v1, graph()->start(), c1);
+ Node* const merge = graph()->NewNode(common()->Merge(2), c0, c1);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), v0, v1, merge);
+ Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e1, merge);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(phi, v0));
+ EXPECT_CALL(editor, Replace(ephi, e0));
+ Reduction const r = Reduce(&editor, merge);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(c0, r.replacement());
+}
+
+
+TEST_F(DeadCodeEliminationTest, MergeWithTwoLiveAndTwoDeadInputs) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const v2 = Parameter(2);
+ Node* const v3 = Parameter(3);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const c2 = graph()->NewNode(common()->Dead());
+ Node* const c3 = graph()->NewNode(&kOp0, v3, graph()->start(), c0);
+ Node* const e0 = graph()->start();
+ Node* const e1 = graph()->NewNode(&kOp0, v1, e0, c0);
+ Node* const e2 = graph()->NewNode(&kOp0, v2, e1, c0);
+ Node* const e3 = graph()->NewNode(&kOp0, v3, graph()->start(), c3);
+ Node* const merge = graph()->NewNode(common()->Merge(4), c0, c1, c2, c3);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 4), v0, v1, v2, v3, merge);
+ Node* const ephi =
+ graph()->NewNode(common()->EffectPhi(4), e0, e1, e2, e3, merge);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(phi));
+ EXPECT_CALL(editor, Revisit(ephi));
+ Reduction const r = Reduce(&editor, merge);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsMerge(c0, c3));
+ EXPECT_THAT(phi, IsPhi(kMachAnyTagged, v0, v3, r.replacement()));
+ EXPECT_THAT(ephi, IsEffectPhi(e0, e3, r.replacement()));
+}
+
+
+// -----------------------------------------------------------------------------
+// Loop
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithDeadFirstInput) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ inputs[0] = graph()->NewNode(common()->Dead());
+ for (int i = 1; i < input_count; ++i) {
+ inputs[i] = graph()->start();
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->Loop(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithOnlyDeadInputs) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->NewNode(common()->Dead());
+ }
+ Reduction const r = Reduce(
+ graph()->NewNode(common()->Loop(input_count), input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithOneLiveAndOneDeadInput) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const e0 = graph()->NewNode(&kOp0, v0, graph()->start(), c0);
+ Node* const e1 = graph()->NewNode(&kOp0, v1, graph()->start(), c1);
+ Node* const loop = graph()->NewNode(common()->Loop(2), c0, c1);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 2), v0, v1, loop);
+ Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e1, loop);
+ Node* const terminate = graph()->NewNode(common()->Terminate(), ephi, loop);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Replace(phi, v0));
+ EXPECT_CALL(editor, Replace(ephi, e0));
+ EXPECT_CALL(editor, Replace(terminate, IsDead()));
+ Reduction const r = Reduce(&editor, loop);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(c0, r.replacement());
+}
+
+
+TEST_F(DeadCodeEliminationTest, LoopWithTwoLiveAndTwoDeadInputs) {
+ Node* const v0 = Parameter(0);
+ Node* const v1 = Parameter(1);
+ Node* const v2 = Parameter(2);
+ Node* const v3 = Parameter(3);
+ Node* const c0 =
+ graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start());
+ Node* const c1 = graph()->NewNode(common()->Dead());
+ Node* const c2 = graph()->NewNode(common()->Dead());
+ Node* const c3 = graph()->NewNode(&kOp0, v3, graph()->start(), c0);
+ Node* const e0 = graph()->start();
+ Node* const e1 = graph()->NewNode(&kOp0, v1, e0, c0);
+ Node* const e2 = graph()->NewNode(&kOp0, v2, e1, c0);
+ Node* const e3 = graph()->NewNode(&kOp0, v3, graph()->start(), c3);
+ Node* const loop = graph()->NewNode(common()->Loop(4), c0, c1, c2, c3);
+ Node* const phi =
+ graph()->NewNode(common()->Phi(kMachAnyTagged, 4), v0, v1, v2, v3, loop);
+ Node* const ephi =
+ graph()->NewNode(common()->EffectPhi(4), e0, e1, e2, e3, loop);
+ StrictMock<MockAdvancedReducerEditor> editor;
+ EXPECT_CALL(editor, Revisit(phi));
+ EXPECT_CALL(editor, Revisit(ephi));
+ Reduction const r = Reduce(&editor, loop);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsLoop(c0, c3));
+ EXPECT_THAT(phi, IsPhi(kMachAnyTagged, v0, v3, r.replacement()));
+ EXPECT_THAT(ephi, IsEffectPhi(e0, e3, r.replacement()));
+}
+
+
+// -----------------------------------------------------------------------------
+// Phi
+
+
+TEST_F(DeadCodeEliminationTest, PhiWithDeadControlInput) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FOREACH(MachineType, type, kMachineTypes) {
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = Parameter(i);
+ }
+ inputs[input_count] = graph()->NewNode(common()->Dead());
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->Phi(type, input_count), input_count + 1, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// EffectPhi
+
+
+TEST_F(DeadCodeEliminationTest, EffectPhiWithDeadControlInput) {
+ Node* inputs[kMaxInputs + 1];
+ TRACED_FORRANGE(int, input_count, 1, kMaxInputs) {
+ for (int i = 0; i < input_count; ++i) {
+ inputs[i] = graph()->start();
+ }
+ inputs[input_count] = graph()->NewNode(common()->Dead());
+ Reduction const r = Reduce(graph()->NewNode(
+ common()->EffectPhi(input_count), input_count + 1, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Terminate
+
+
+TEST_F(DeadCodeEliminationTest, TerminateWithDeadControlInput) {
+ Reduction const r =
+ Reduce(graph()->NewNode(common()->Terminate(), graph()->start(),
+ graph()->NewNode(common()->Dead())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsDead());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc b/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc
index ea981ccaf3..3ca6052af9 100644
--- a/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc
@@ -2,6 +2,7 @@
// 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/graph.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
@@ -10,9 +11,11 @@
using testing::_;
using testing::DefaultValue;
+using testing::ElementsAre;
using testing::Return;
using testing::Sequence;
using testing::StrictMock;
+using testing::UnorderedElementsAre;
namespace v8 {
namespace internal {
@@ -264,6 +267,124 @@ TEST_F(AdvancedReducerTest, Revisit) {
}
+namespace {
+
+struct ReplaceWithValueReducer final : public AdvancedReducer {
+ explicit ReplaceWithValueReducer(Editor* editor) : AdvancedReducer(editor) {}
+ Reduction Reduce(Node* node) final { return NoChange(); }
+ using AdvancedReducer::ReplaceWithValue;
+};
+
+const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
+ "MockOperator", 0, 0, 0, 1, 0, 0);
+const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties,
+ "MockOpEffect", 0, 1, 0, 1, 1, 0);
+const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties,
+ "MockOpControl", 0, 0, 1, 1, 0, 1);
+
+const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
+
+} // namespace
+
+
+TEST_F(AdvancedReducerTest, ReplaceWithValue_ValueUse) {
+ CommonOperatorBuilder common(zone());
+ Node* node = graph()->NewNode(&kMockOperator);
+ Node* use_value = graph()->NewNode(common.Return(), node);
+ Node* replacement = graph()->NewNode(&kMockOperator);
+ GraphReducer graph_reducer(zone(), graph(), nullptr);
+ ReplaceWithValueReducer r(&graph_reducer);
+ r.ReplaceWithValue(node, replacement);
+ EXPECT_EQ(replacement, use_value->InputAt(0));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(1, replacement->UseCount());
+ EXPECT_THAT(replacement->uses(), ElementsAre(use_value));
+}
+
+
+TEST_F(AdvancedReducerTest, ReplaceWithValue_EffectUse) {
+ CommonOperatorBuilder common(zone());
+ Node* start = graph()->NewNode(common.Start(1));
+ Node* node = graph()->NewNode(&kMockOpEffect, start);
+ Node* use_effect = graph()->NewNode(common.EffectPhi(1), node);
+ Node* replacement = graph()->NewNode(&kMockOperator);
+ GraphReducer graph_reducer(zone(), graph(), nullptr);
+ ReplaceWithValueReducer r(&graph_reducer);
+ r.ReplaceWithValue(node, replacement);
+ EXPECT_EQ(start, use_effect->InputAt(0));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(2, start->UseCount());
+ EXPECT_EQ(0, replacement->UseCount());
+ EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node));
+}
+
+
+TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse1) {
+ CommonOperatorBuilder common(zone());
+ Node* start = graph()->NewNode(common.Start(1));
+ Node* node = graph()->NewNode(&kMockOpControl, start);
+ Node* success = graph()->NewNode(common.IfSuccess(), node);
+ Node* use_control = graph()->NewNode(common.Merge(1), success);
+ Node* replacement = graph()->NewNode(&kMockOperator);
+ GraphReducer graph_reducer(zone(), graph(), nullptr);
+ ReplaceWithValueReducer r(&graph_reducer);
+ r.ReplaceWithValue(node, replacement);
+ EXPECT_EQ(start, use_control->InputAt(0));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(2, start->UseCount());
+ EXPECT_EQ(0, replacement->UseCount());
+ EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
+}
+
+
+TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) {
+ CommonOperatorBuilder common(zone());
+ Node* start = graph()->NewNode(common.Start(1));
+ Node* effect = graph()->NewNode(&kMockOperator);
+ Node* dead = graph()->NewNode(&kMockOperator);
+ Node* node = graph()->NewNode(&kMockOpControl, start);
+ Node* success = graph()->NewNode(common.IfSuccess(), node);
+ Node* exception = graph()->NewNode(common.IfException(kNoHint), effect, node);
+ Node* use_control = graph()->NewNode(common.Merge(1), success);
+ Node* replacement = graph()->NewNode(&kMockOperator);
+ GraphReducer graph_reducer(zone(), graph(), dead);
+ ReplaceWithValueReducer r(&graph_reducer);
+ r.ReplaceWithValue(node, replacement);
+ EXPECT_EQ(start, use_control->InputAt(0));
+ EXPECT_EQ(dead, exception->InputAt(1));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(2, start->UseCount());
+ EXPECT_EQ(1, dead->UseCount());
+ EXPECT_EQ(0, replacement->UseCount());
+ EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
+ EXPECT_THAT(dead->uses(), ElementsAre(exception));
+}
+
+
+TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) {
+ CommonOperatorBuilder common(zone());
+ Node* start = graph()->NewNode(common.Start(1));
+ Node* effect = graph()->NewNode(&kMockOperator);
+ Node* dead = graph()->NewNode(&kMockOperator);
+ Node* node = graph()->NewNode(&kMockOpControl, start);
+ Node* success = graph()->NewNode(common.IfSuccess(), node);
+ Node* exception = graph()->NewNode(common.IfException(kNoHint), effect, node);
+ Node* use_control = graph()->NewNode(common.Merge(1), success);
+ Node* replacement = graph()->NewNode(&kMockOperator);
+ GraphReducer graph_reducer(zone(), graph(), dead);
+ ReplaceWithValueReducer r(&graph_reducer);
+ r.ReplaceWithValue(node, replacement);
+ EXPECT_EQ(start, use_control->InputAt(0));
+ EXPECT_EQ(dead, exception->InputAt(1));
+ EXPECT_EQ(0, node->UseCount());
+ EXPECT_EQ(2, start->UseCount());
+ EXPECT_EQ(1, dead->UseCount());
+ EXPECT_EQ(0, replacement->UseCount());
+ EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
+ EXPECT_THAT(dead->uses(), ElementsAre(exception));
+}
+
+
class GraphReducerTest : public TestWithZone {
public:
GraphReducerTest() : graph_(zone()) {}
@@ -280,20 +401,20 @@ class GraphReducerTest : public TestWithZone {
protected:
void ReduceNode(Node* node, Reducer* r) {
- GraphReducer reducer(graph(), zone());
+ GraphReducer reducer(zone(), graph());
reducer.AddReducer(r);
reducer.ReduceNode(node);
}
void ReduceNode(Node* node, Reducer* r1, Reducer* r2) {
- GraphReducer reducer(graph(), zone());
+ GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.ReduceNode(node);
}
void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) {
- GraphReducer reducer(graph(), zone());
+ GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.AddReducer(r3);
@@ -301,20 +422,20 @@ class GraphReducerTest : public TestWithZone {
}
void ReduceGraph(Reducer* r1) {
- GraphReducer reducer(graph(), zone());
+ GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1);
reducer.ReduceGraph();
}
void ReduceGraph(Reducer* r1, Reducer* r2) {
- GraphReducer reducer(graph(), zone());
+ GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.ReduceGraph();
}
void ReduceGraph(Reducer* r1, Reducer* r2, Reducer* r3) {
- GraphReducer reducer(graph(), zone());
+ GraphReducer reducer(zone(), graph());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.AddReducer(r3);
@@ -401,7 +522,7 @@ TEST_F(GraphReducerTest, ReduceInPlace1) {
// Tests A* => B* with in-place updates.
InPlaceABReducer r;
for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpB0, n1->op());
@@ -421,7 +542,7 @@ TEST_F(GraphReducerTest, ReduceInPlace2) {
// Tests A* => B* with in-place updates.
InPlaceABReducer r;
for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpB0, n1->op());
@@ -446,7 +567,7 @@ TEST_F(GraphReducerTest, ReduceNew1) {
NewABReducer r(graph());
// Tests A* => B* while creating new nodes.
for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
if (i == 0) {
EXPECT_NE(before, graph()->NodeCount());
@@ -473,12 +594,12 @@ TEST_F(GraphReducerTest, ReduceNew1) {
TEST_F(GraphReducerTest, Wrapping1) {
Node* end = graph()->NewNode(&kOpA0);
graph()->SetEnd(end);
- EXPECT_EQ(1, graph()->NodeCount());
+ EXPECT_EQ(1U, graph()->NodeCount());
A0Wrapper r(graph());
ReduceGraph(&r);
- EXPECT_EQ(2, graph()->NodeCount());
+ EXPECT_EQ(2U, graph()->NodeCount());
Node* nend = graph()->end();
EXPECT_NE(end, nend);
@@ -491,12 +612,12 @@ TEST_F(GraphReducerTest, Wrapping1) {
TEST_F(GraphReducerTest, Wrapping2) {
Node* end = graph()->NewNode(&kOpB0);
graph()->SetEnd(end);
- EXPECT_EQ(1, graph()->NodeCount());
+ EXPECT_EQ(1U, graph()->NodeCount());
B0Wrapper r(graph());
ReduceGraph(&r);
- EXPECT_EQ(3, graph()->NodeCount());
+ EXPECT_EQ(3U, graph()->NodeCount());
Node* nend = graph()->end();
EXPECT_NE(end, nend);
@@ -520,7 +641,7 @@ TEST_F(GraphReducerTest, Forwarding1) {
// Tests A1(x) => x
for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpA0, n1->op());
@@ -540,7 +661,7 @@ TEST_F(GraphReducerTest, Forwarding2) {
// Tests reducing A2(A1(x), A1(y)) => A2(x, y).
for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpA0, n1->op());
@@ -565,8 +686,8 @@ TEST_F(GraphReducerTest, Forwarding3) {
A1Forwarder r;
- for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ for (size_t i = 0; i < 3; i++) {
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpA0, n1->op());
@@ -587,8 +708,8 @@ TEST_F(GraphReducerTest, ReduceForward1) {
B1Forwarder f;
// Tests first reducing A => B, then B1(x) => x.
- for (int i = 0; i < 3; i++) {
- int before = graph()->NodeCount();
+ for (size_t i = 0; i < 3; i++) {
+ size_t before = graph()->NodeCount();
ReduceGraph(&r, &f);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpB0, n1->op());
@@ -620,7 +741,7 @@ TEST_F(GraphReducerTest, Sorter1) {
graph()->SetEnd(end);
- int before = graph()->NodeCount();
+ size_t before = graph()->NodeCount();
ReduceGraph(&r);
EXPECT_EQ(before, graph()->NodeCount());
EXPECT_EQ(&kOpA0, n1->op());
@@ -715,8 +836,8 @@ TEST_F(GraphReducerTest, Order) {
InPlaceBCReducer bcr;
// Tests A* => C* with in-place updates.
- for (int j = 0; j < 3; j++) {
- int before = graph()->NodeCount();
+ for (size_t j = 0; j < 3; j++) {
+ size_t before = graph()->NodeCount();
if (i == 0) {
ReduceGraph(&abr, &bcr);
} else {
diff --git a/deps/v8/test/unittests/compiler/graph-reducer-unittest.h b/deps/v8/test/unittests/compiler/graph-reducer-unittest.h
index 4cde964709..2b0651da13 100644
--- a/deps/v8/test/unittests/compiler/graph-reducer-unittest.h
+++ b/deps/v8/test/unittests/compiler/graph-reducer-unittest.h
@@ -15,6 +15,7 @@ namespace compiler {
struct MockAdvancedReducerEditor : public AdvancedReducer::Editor {
MOCK_METHOD1(Revisit, void(Node*));
MOCK_METHOD2(Replace, void(Node*, Node*));
+ MOCK_METHOD4(ReplaceWithValue, void(Node*, Node*, Node*, Node*));
};
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc b/deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc
new file mode 100644
index 0000000000..36892e6ee8
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc
@@ -0,0 +1,85 @@
+// 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/graph-trimmer.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "testing/gmock-support.h"
+
+using testing::ElementsAre;
+using testing::UnorderedElementsAre;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class GraphTrimmerTest : public GraphTest {
+ public:
+ GraphTrimmerTest() : GraphTest(1) {}
+
+ protected:
+ void TrimGraph(Node* root) {
+ Node* const roots[1] = {root};
+ GraphTrimmer trimmer(zone(), graph());
+ trimmer.TrimGraph(&roots[0], &roots[arraysize(roots)]);
+ }
+ void TrimGraph() {
+ GraphTrimmer trimmer(zone(), graph());
+ trimmer.TrimGraph();
+ }
+};
+
+
+namespace {
+
+const Operator kDead0(IrOpcode::kDead, Operator::kNoProperties, "Dead0", 0, 0,
+ 1, 0, 0, 0);
+const Operator kLive0(IrOpcode::kDead, Operator::kNoProperties, "Live0", 0, 0,
+ 1, 0, 0, 1);
+
+} // namespace
+
+
+TEST_F(GraphTrimmerTest, Empty) {
+ Node* const start = graph()->NewNode(common()->Start(0));
+ Node* const end = graph()->NewNode(common()->End(1), start);
+ graph()->SetStart(start);
+ graph()->SetEnd(end);
+ TrimGraph();
+ EXPECT_EQ(end, graph()->end());
+ EXPECT_EQ(start, graph()->start());
+ EXPECT_EQ(start, end->InputAt(0));
+}
+
+
+TEST_F(GraphTrimmerTest, DeadUseOfStart) {
+ Node* const dead0 = graph()->NewNode(&kDead0, graph()->start());
+ graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
+ TrimGraph();
+ EXPECT_THAT(dead0->inputs(), ElementsAre(nullptr));
+ EXPECT_THAT(graph()->start()->uses(), ElementsAre(graph()->end()));
+}
+
+
+TEST_F(GraphTrimmerTest, DeadAndLiveUsesOfStart) {
+ Node* const dead0 = graph()->NewNode(&kDead0, graph()->start());
+ Node* const live0 = graph()->NewNode(&kLive0, graph()->start());
+ graph()->SetEnd(graph()->NewNode(common()->End(1), live0));
+ TrimGraph();
+ EXPECT_THAT(dead0->inputs(), ElementsAre(nullptr));
+ EXPECT_THAT(graph()->start()->uses(), ElementsAre(live0));
+ EXPECT_THAT(live0->uses(), ElementsAre(graph()->end()));
+}
+
+
+TEST_F(GraphTrimmerTest, Roots) {
+ Node* const live0 = graph()->NewNode(&kLive0, graph()->start());
+ Node* const live1 = graph()->NewNode(&kLive0, graph()->start());
+ graph()->SetEnd(graph()->NewNode(common()->End(1), live0));
+ TrimGraph(live1);
+ EXPECT_THAT(graph()->start()->uses(), UnorderedElementsAre(live0, live1));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/graph-unittest.cc b/deps/v8/test/unittests/compiler/graph-unittest.cc
index 9da3950e54..6b8546b95a 100644
--- a/deps/v8/test/unittests/compiler/graph-unittest.cc
+++ b/deps/v8/test/unittests/compiler/graph-unittest.cc
@@ -13,7 +13,7 @@ namespace compiler {
GraphTest::GraphTest(int num_parameters) : common_(zone()), graph_(zone()) {
graph()->SetStart(graph()->NewNode(common()->Start(num_parameters)));
- graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start()));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
}
@@ -81,6 +81,16 @@ Node* GraphTest::UndefinedConstant() {
}
+Node* GraphTest::EmptyFrameState() {
+ Node* state_values = graph()->NewNode(common()->StateValues(0));
+ return graph()->NewNode(
+ common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
+ nullptr),
+ state_values, state_values, state_values, NumberConstant(0),
+ UndefinedConstant(), graph()->start());
+}
+
+
Matcher<Node*> GraphTest::IsFalseConstant() {
return IsHeapConstant(
Unique<HeapObject>::CreateImmovable(factory()->false_value()));
@@ -100,8 +110,7 @@ Matcher<Node*> GraphTest::IsUndefinedConstant() {
TypedGraphTest::TypedGraphTest(int num_parameters)
- : GraphTest(num_parameters),
- typer_(isolate(), graph(), MaybeHandle<Context>()) {}
+ : GraphTest(num_parameters), typer_(isolate(), graph()) {}
TypedGraphTest::~TypedGraphTest() {}
@@ -126,8 +135,8 @@ TEST_F(GraphTest, NewNode) {
Node* n0 = graph()->NewNode(&kDummyOperator);
Node* n1 = graph()->NewNode(&kDummyOperator);
EXPECT_NE(n0, n1);
- EXPECT_LT(0, n0->id());
- EXPECT_LT(0, n1->id());
+ EXPECT_LT(0u, n0->id());
+ EXPECT_LT(0u, n1->id());
EXPECT_NE(n0->id(), n1->id());
EXPECT_EQ(&kDummyOperator, n0->op());
EXPECT_EQ(&kDummyOperator, n1->op());
diff --git a/deps/v8/test/unittests/compiler/graph-unittest.h b/deps/v8/test/unittests/compiler/graph-unittest.h
index c905f30c6a..2318fa61f8 100644
--- a/deps/v8/test/unittests/compiler/graph-unittest.h
+++ b/deps/v8/test/unittests/compiler/graph-unittest.h
@@ -50,6 +50,8 @@ class GraphTest : public TestWithContext, public TestWithIsolateAndZone {
Node* TrueConstant();
Node* UndefinedConstant();
+ Node* EmptyFrameState();
+
Matcher<Node*> IsFalseConstant();
Matcher<Node*> IsTrueConstant();
Matcher<Node*> IsUndefinedConstant();
diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
index dfdb4c2b1f..acab91b009 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
@@ -148,6 +148,15 @@ bool InstructionSelectorTest::Stream::IsUsedAtStart(
}
+const FrameStateFunctionInfo*
+InstructionSelectorTest::StreamBuilder::GetFrameStateFunctionInfo(
+ int parameter_count, int local_count) {
+ return common()->CreateFrameStateFunctionInfo(
+ FrameStateType::kJavaScriptFunction, parameter_count, local_count,
+ Handle<SharedFunctionInfo>());
+}
+
+
// -----------------------------------------------------------------------------
// Return.
@@ -198,7 +207,8 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnZero) {
TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) {
StreamBuilder m(this, kMachInt32, kMachFloat64);
- m.Return(m.TruncateFloat64ToInt32(m.Parameter(0)));
+ m.Return(
+ m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, m.Parameter(0)));
Stream s = m.Build(kAllInstructions);
ASSERT_EQ(4U, s.size());
EXPECT_EQ(kArchNop, s[0]->arch_opcode());
@@ -363,9 +373,10 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
Node* context_dummy = m.Int32Constant(0);
Node* state_node = m.NewNode(
- m.common()->FrameState(JS_FRAME, bailout_id,
- OutputFrameStateCombine::Push()),
- parameters, locals, stack, context_dummy, m.UndefinedConstant());
+ m.common()->FrameState(bailout_id, OutputFrameStateCombine::Push(),
+ m.GetFrameStateFunctionInfo(1, 0)),
+ parameters, locals, stack, context_dummy, function_node,
+ m.UndefinedConstant());
Node* call = m.CallJS0(function_node, receiver, context, state_node);
m.Return(call);
@@ -411,9 +422,10 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
Node* context_sentinel = m.Int32Constant(0);
Node* frame_state_before = m.NewNode(
- m.common()->FrameState(JS_FRAME, bailout_id_before,
- OutputFrameStateCombine::Push()),
- parameters, locals, stack, context_sentinel, m.UndefinedConstant());
+ m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(),
+ m.GetFrameStateFunctionInfo(1, 1)),
+ parameters, locals, stack, context_sentinel, function_node,
+ m.UndefinedConstant());
// Build the call.
Node* call = m.CallFunctionStub0(function_node, receiver, context,
@@ -437,7 +449,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
size_t num_operands =
1 + // Code object.
1 +
- 4 + // Frame state deopt id + one input for each value in frame state.
+ 5 + // Frame state deopt id + one input for each value in frame state.
1 + // Function.
1; // Context.
ASSERT_EQ(num_operands, call_instr->InputCount());
@@ -455,21 +467,23 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
EXPECT_EQ(1u, desc_before->parameters_count());
EXPECT_EQ(1u, desc_before->locals_count());
EXPECT_EQ(1u, desc_before->stack_count());
- EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
- EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(3))); // This should be a context.
+ EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(3)));
+ EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(4))); // This should be a context.
// We inserted 0 here.
- EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(4)));
- EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(5))->IsUndefined());
- EXPECT_EQ(kMachInt32, desc_before->GetType(0));
- EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1)); // context is always
+ EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(5)));
+ EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(6))->IsUndefined());
+ EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); // function is always
// tagged/any.
- EXPECT_EQ(kMachFloat64, desc_before->GetType(2));
- EXPECT_EQ(kMachAnyTagged, desc_before->GetType(3));
+ EXPECT_EQ(kMachInt32, desc_before->GetType(1));
+ EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2)); // context is always
+ // tagged/any.
+ EXPECT_EQ(kMachFloat64, desc_before->GetType(3));
+ EXPECT_EQ(kMachAnyTagged, desc_before->GetType(4));
// Function.
- EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(6)));
+ EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(7)));
// Context.
- EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(7)));
+ EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(8)));
EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
@@ -501,10 +515,11 @@ TARGET_TEST_F(InstructionSelectorTest,
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64));
Node* stack =
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65));
- Node* frame_state_parent =
- m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_parent,
- OutputFrameStateCombine::Ignore()),
- parameters, locals, stack, context, m.UndefinedConstant());
+ Node* frame_state_parent = m.NewNode(
+ m.common()->FrameState(bailout_id_parent,
+ OutputFrameStateCombine::Ignore(),
+ m.GetFrameStateFunctionInfo(1, 1)),
+ parameters, locals, stack, context, function_node, m.UndefinedConstant());
Node* context2 = m.Int32Constant(46);
Node* parameters2 =
@@ -513,10 +528,11 @@ TARGET_TEST_F(InstructionSelectorTest,
m.Float64Constant(0.25));
Node* stack2 = m.NewNode(m.common()->TypedStateValues(&int32x2_type),
m.Int32Constant(44), m.Int32Constant(45));
- Node* frame_state_before =
- m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before,
- OutputFrameStateCombine::Push()),
- parameters2, locals2, stack2, context2, frame_state_parent);
+ Node* frame_state_before = m.NewNode(
+ m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(),
+ m.GetFrameStateFunctionInfo(1, 1)),
+ parameters2, locals2, stack2, context2, function_node,
+ frame_state_parent);
// Build the call.
Node* call = m.CallFunctionStub0(function_node, receiver, context2,
@@ -540,8 +556,8 @@ TARGET_TEST_F(InstructionSelectorTest,
size_t num_operands =
1 + // Code object.
1 + // Frame state deopt id
- 5 + // One input for each value in frame state + context.
- 4 + // One input for each value in the parent frame state + context.
+ 6 + // One input for each value in frame state + context.
+ 5 + // One input for each value in the parent frame state + context.
1 + // Function.
1; // Context.
EXPECT_EQ(num_operands, call_instr->InputCount());
@@ -558,34 +574,36 @@ TARGET_TEST_F(InstructionSelectorTest,
EXPECT_EQ(1u, desc_before_outer->locals_count());
EXPECT_EQ(1u, desc_before_outer->stack_count());
// Values from parent environment.
- EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(2)));
- EXPECT_EQ(kMachInt32, desc_before_outer->GetType(0));
+ EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0));
+ EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(3)));
+ EXPECT_EQ(kMachInt32, desc_before_outer->GetType(1));
// Context:
- EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(3)));
- EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(1));
- EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(4)));
- EXPECT_EQ(kMachInt32, desc_before_outer->GetType(2));
- EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(5)));
+ EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(4)));
+ EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(2));
+ EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(5)));
EXPECT_EQ(kMachInt32, desc_before_outer->GetType(3));
+ EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(6)));
+ EXPECT_EQ(kMachInt32, desc_before_outer->GetType(4));
// Values from the nested frame.
EXPECT_EQ(1u, desc_before->parameters_count());
EXPECT_EQ(1u, desc_before->locals_count());
EXPECT_EQ(2u, desc_before->stack_count());
- EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(6)));
- EXPECT_EQ(kMachInt32, desc_before->GetType(0));
- EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(7)));
- EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1));
- EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(8)));
- EXPECT_EQ(kMachFloat64, desc_before->GetType(2));
- EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(9)));
- EXPECT_EQ(kMachInt32, desc_before->GetType(3));
- EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(10)));
+ EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0));
+ EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(8)));
+ EXPECT_EQ(kMachInt32, desc_before->GetType(1));
+ EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(9)));
+ EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2));
+ EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(10)));
+ EXPECT_EQ(kMachFloat64, desc_before->GetType(3));
+ EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(11)));
EXPECT_EQ(kMachInt32, desc_before->GetType(4));
+ EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(12)));
+ EXPECT_EQ(kMachInt32, desc_before->GetType(5));
// Function.
- EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(11)));
+ EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(13)));
// Context.
- EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(12)));
+ EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14)));
// Continuation.
EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h b/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
index a23d531a3a..15d3b2005f 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
+++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
@@ -37,22 +37,25 @@ class InstructionSelectorTest : public TestWithContext,
class StreamBuilder final : public RawMachineAssembler {
public:
StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
- : RawMachineAssembler(test->isolate(),
- new (test->zone()) Graph(test->zone()),
- MakeMachineSignature(test->zone(), return_type)),
+ : RawMachineAssembler(
+ test->isolate(), new (test->zone()) Graph(test->zone()),
+ MakeMachineSignature(test->zone(), return_type), kMachPtr,
+ MachineOperatorBuilder::kAllOptionalOps),
test_(test) {}
StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
MachineType parameter0_type)
: RawMachineAssembler(
test->isolate(), new (test->zone()) Graph(test->zone()),
- MakeMachineSignature(test->zone(), return_type, parameter0_type)),
+ MakeMachineSignature(test->zone(), return_type, parameter0_type),
+ kMachPtr, MachineOperatorBuilder::kAllOptionalOps),
test_(test) {}
StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
MachineType parameter0_type, MachineType parameter1_type)
: RawMachineAssembler(
test->isolate(), new (test->zone()) Graph(test->zone()),
MakeMachineSignature(test->zone(), return_type, parameter0_type,
- parameter1_type)),
+ parameter1_type),
+ kMachPtr, MachineOperatorBuilder::kAllOptionalOps),
test_(test) {}
StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
MachineType parameter0_type, MachineType parameter1_type,
@@ -60,7 +63,8 @@ class InstructionSelectorTest : public TestWithContext,
: RawMachineAssembler(
test->isolate(), new (test->zone()) Graph(test->zone()),
MakeMachineSignature(test->zone(), return_type, parameter0_type,
- parameter1_type, parameter2_type)),
+ parameter1_type, parameter2_type),
+ kMachPtr, MachineOperatorBuilder::kAllOptionalOps),
test_(test) {}
Stream Build(CpuFeature feature) {
@@ -77,6 +81,9 @@ class InstructionSelectorTest : public TestWithContext,
InstructionSelector::SourcePositionMode source_position_mode =
InstructionSelector::kAllSourcePositions);
+ const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count,
+ int local_count);
+
private:
MachineSignature* MakeMachineSignature(Zone* zone,
MachineType return_type) {
diff --git a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
index f659b07887..1ff441f746 100644
--- a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
+++ b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
@@ -429,8 +429,8 @@ InstructionBlock* InstructionSequenceTest::NewBlock() {
}
}
// Construct instruction block.
- auto instruction_block =
- new (zone()) InstructionBlock(zone(), rpo, loop_header, loop_end, false);
+ auto instruction_block = new (zone())
+ InstructionBlock(zone(), rpo, loop_header, loop_end, false, false);
instruction_blocks_.push_back(instruction_block);
current_block_ = instruction_block;
sequence()->StartBlock(rpo);
diff --git a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
index 090f610066..b452ba56c5 100644
--- a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -26,7 +26,9 @@ class JSBuiltinReducerTest : public TypedGraphTest {
MachineOperatorBuilder::Flag::kNoFlags) {
MachineOperatorBuilder machine(zone(), kMachPtr, flags);
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
- JSBuiltinReducer reducer(&jsgraph);
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ JSBuiltinReducer reducer(&graph_reducer, &jsgraph);
return reducer.Reduce(node);
}
@@ -77,10 +79,14 @@ Type* const kNumberTypes[] = {
TEST_F(JSBuiltinReducerTest, MathMax0) {
Node* function = MathFunction("max");
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* frame_state = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Node* call = graph()->NewNode(
javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS, language_mode),
- function, UndefinedConstant());
+ function, UndefinedConstant(), frame_state, frame_state, effect,
+ control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@@ -92,12 +98,16 @@ TEST_F(JSBuiltinReducerTest, MathMax0) {
TEST_F(JSBuiltinReducerTest, MathMax1) {
Node* function = MathFunction("max");
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* frame_state = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(
javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode),
- function, UndefinedConstant(), p0);
+ function, UndefinedConstant(), p0, frame_state, frame_state, effect,
+ control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@@ -110,6 +120,9 @@ TEST_F(JSBuiltinReducerTest, MathMax1) {
TEST_F(JSBuiltinReducerTest, MathMax2) {
Node* function = MathFunction("max");
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* frame_state = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
TRACED_FOREACH(Type*, t0, kIntegral32Types) {
TRACED_FOREACH(Type*, t1, kIntegral32Types) {
@@ -118,7 +131,8 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
Node* call =
graph()->NewNode(javascript()->CallFunction(
4, NO_CALL_FUNCTION_FLAGS, language_mode),
- function, UndefinedConstant(), p0, p1);
+ function, UndefinedConstant(), p0, p1, frame_state,
+ frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@@ -137,6 +151,9 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
TEST_F(JSBuiltinReducerTest, MathImul) {
Node* function = MathFunction("imul");
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* frame_state = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
TRACED_FOREACH(Type*, t0, kIntegral32Types) {
TRACED_FOREACH(Type*, t1, kIntegral32Types) {
@@ -145,7 +162,8 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
Node* call =
graph()->NewNode(javascript()->CallFunction(
4, NO_CALL_FUNCTION_FLAGS, language_mode),
- function, UndefinedConstant(), p0, p1);
+ function, UndefinedConstant(), p0, p1, frame_state,
+ frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
@@ -163,12 +181,16 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
TEST_F(JSBuiltinReducerTest, MathFround) {
Node* function = MathFunction("fround");
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* frame_state = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* call = graph()->NewNode(
javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode),
- function, UndefinedConstant(), p0);
+ function, UndefinedConstant(), p0, frame_state, frame_state, effect,
+ control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
diff --git a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index bc343060ca..92be4e43e0 100644
--- a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
@@ -33,7 +33,10 @@ class JSIntrinsicLoweringTest : public GraphTest {
MachineOperatorBuilder::kNoFlags) {
MachineOperatorBuilder machine(zone(), kMachPtr, flags);
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
- JSIntrinsicLowering reducer(&jsgraph);
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ JSIntrinsicLowering reducer(&graph_reducer, &jsgraph,
+ JSIntrinsicLowering::kDeoptimizationEnabled);
return reducer.Reduce(node);
}
@@ -171,6 +174,68 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
// -----------------------------------------------------------------------------
+// %_IsDate
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineIsDate) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsDate, 1),
+ input, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+
+ Node* phi = r.replacement();
+ Capture<Node*> branch, if_false;
+ EXPECT_THAT(
+ phi,
+ IsPhi(
+ static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
+ IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
+ IsLoadField(AccessBuilder::ForMap(), input,
+ effect, CaptureEq(&if_false)),
+ effect, _),
+ IsInt32Constant(JS_DATE_TYPE)),
+ IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
+ IsBranch(IsObjectIsSmi(input), control))),
+ AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
+}
+
+
+// -----------------------------------------------------------------------------
+// %_IsTypedArray
+
+
+TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) {
+ Node* const input = Parameter(0);
+ Node* const context = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r = Reduce(graph()->NewNode(
+ javascript()->CallRuntime(Runtime::kInlineIsTypedArray, 1), input,
+ context, effect, control));
+ ASSERT_TRUE(r.Changed());
+
+ Node* phi = r.replacement();
+ Capture<Node*> branch, if_false;
+ EXPECT_THAT(
+ phi,
+ IsPhi(
+ static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
+ IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
+ IsLoadField(AccessBuilder::ForMap(), input,
+ effect, CaptureEq(&if_false)),
+ effect, _),
+ IsInt32Constant(JS_TYPED_ARRAY_TYPE)),
+ IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
+ IsBranch(IsObjectIsSmi(input), control))),
+ AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
+}
+
+
+// -----------------------------------------------------------------------------
// %_IsFunction
@@ -264,7 +329,7 @@ TEST_F(JSIntrinsicLoweringTest, Likely) {
Node* const to_boolean =
graph()->NewNode(javascript()->ToBoolean(), likely, context);
Diamond d(graph(), common(), to_boolean);
- graph()->SetEnd(graph()->NewNode(common()->End(), d.merge));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), d.merge));
ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op()));
Reduction const r = Reduce(likely);
@@ -359,7 +424,7 @@ TEST_F(JSIntrinsicLoweringTest, Unlikely) {
Node* const to_boolean =
graph()->NewNode(javascript()->ToBoolean(), unlikely, context);
Diamond d(graph(), common(), to_boolean);
- graph()->SetEnd(graph()->NewNode(common()->End(), d.merge));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), d.merge));
ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op()));
Reduction const r = Reduce(unlikely);
diff --git a/deps/v8/test/unittests/compiler/js-operator-unittest.cc b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
index a8a2d8c38a..0f33ddea8d 100644
--- a/deps/v8/test/unittests/compiler/js-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
@@ -186,10 +186,10 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
control_input_count, value_output_count, effect_output_count, \
control_output_count \
}
- SHARED(LessThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
- SHARED(GreaterThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
- SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
- SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+ SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
+ SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseOr, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseXor, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(BitwiseAnd, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
@@ -201,7 +201,6 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
- SHARED(StoreProperty, Operator::kNoProperties, 3, 2, 1, 1, 0, 1, 2),
#undef SHARED
};
diff --git a/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc b/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc
index 08fe68a8ba..d52242ec7d 100644
--- a/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc
@@ -34,15 +34,18 @@ class JSTypeFeedbackTest : public TypedGraphTest {
~JSTypeFeedbackTest() override { dependencies_.Rollback(); }
protected:
- Reduction Reduce(Node* node) {
+ Reduction Reduce(Node* node,
+ JSTypeFeedbackSpecializer::DeoptimizationMode mode) {
Handle<GlobalObject> global_object(
isolate()->native_context()->global_object(), isolate());
MachineOperatorBuilder machine(zone());
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
JSTypeFeedbackTable table(zone());
- JSTypeFeedbackSpecializer reducer(&jsgraph, &table, nullptr, global_object,
- &dependencies_);
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ JSTypeFeedbackSpecializer reducer(&graph_reducer, &jsgraph, &table, nullptr,
+ global_object, mode, &dependencies_);
return reducer.Reduce(node);
}
@@ -71,19 +74,23 @@ class JSTypeFeedbackTest : public TypedGraphTest {
result.Assert();
}
- Node* ReturnLoadNamedFromGlobal(const char* string, Node* effect,
- Node* control) {
- VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(),
- FeedbackVectorICSlot::Invalid());
- Node* global = Parameter(Type::GlobalObject());
+ Node* ReturnLoadNamedFromGlobal(
+ const char* string, Node* effect, Node* control,
+ JSTypeFeedbackSpecializer::DeoptimizationMode mode) {
+ VectorSlotPair feedback;
+ Node* global = UndefinedConstant();
+ Node* vector = UndefinedConstant();
Node* context = UndefinedConstant();
Unique<Name> name = Unique<Name>::CreateUninitialized(
- isolate()->factory()->NewStringFromAsciiChecked(string));
- Node* load = graph()->NewNode(javascript()->LoadNamed(name, feedback),
- global, context);
- if (FLAG_turbo_deoptimization) {
- load->AppendInput(zone(), EmptyFrameState());
+ isolate()->factory()->InternalizeUtf8String(string));
+ const Operator* op = javascript()->LoadGlobal(name, feedback);
+ Node* load = graph()->NewNode(op, global, vector, context);
+ if (mode == JSTypeFeedbackSpecializer::kDeoptimizationEnabled) {
+ for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op);
+ i++) {
+ load->AppendInput(zone(), EmptyFrameState());
+ }
}
load->AppendInput(zone(), effect);
load->AppendInput(zone(), control);
@@ -98,180 +105,240 @@ class JSTypeFeedbackTest : public TypedGraphTest {
CompilationDependencies dependencies_;
};
-#define WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION \
- for (int i = FLAG_turbo_deoptimization = 0; i < 2; \
- FLAG_turbo_deoptimization = ++i)
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmi) {
+ const int kValue = 111;
+ const char* kName = "banana";
+ SetGlobalProperty(kName, kValue);
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_smi) {
- const int const_value = 111;
- const char* property_name = "banana";
- SetGlobalProperty(property_name, const_value);
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
- WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
- Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
- graph()->start());
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ EXPECT_FALSE(r.Changed());
+ EXPECT_TRUE(dependencies()->IsEmpty());
+}
- Reduction r = Reduce(ret->InputAt(0));
- if (FLAG_turbo_deoptimization) {
- // Check LoadNamed(global) => HeapConstant[const_value]
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(const_value));
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmiWithDeoptimization) {
+ const int kValue = 111;
+ const char* kName = "banana";
+ SetGlobalProperty(kName, kValue);
- EXPECT_THAT(ret, IsReturn(IsNumberConstant(const_value), graph()->start(),
- graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
- } else {
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
- }
- }
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+ // Check LoadNamed(global) => HeapConstant[kValue]
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(kValue));
+
+ EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(),
+ graph()->start()));
+ EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+ EXPECT_FALSE(dependencies()->IsEmpty());
+ dependencies()->Rollback();
}
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_derble) {
- const double const_value = -11.25;
- const char* property_name = "kiwi";
- SetGlobalProperty(property_name, const_value);
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumber) {
+ const double kValue = -11.25;
+ const char* kName = "kiwi";
+ SetGlobalProperty(kName, kValue);
- WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
- Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
- graph()->start());
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
- Reduction r = Reduce(ret->InputAt(0));
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- if (FLAG_turbo_deoptimization) {
- // Check LoadNamed(global) => HeapConstant[const_value]
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(const_value));
+ EXPECT_FALSE(r.Changed());
+ EXPECT_TRUE(dependencies()->IsEmpty());
+}
- EXPECT_THAT(ret, IsReturn(IsNumberConstant(const_value), graph()->start(),
- graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
- EXPECT_FALSE(dependencies()->IsEmpty());
- } else {
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
- }
- }
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumberWithDeoptimization) {
+ const double kValue = -11.25;
+ const char* kName = "kiwi";
+ SetGlobalProperty(kName, kValue);
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+ // Check LoadNamed(global) => HeapConstant[kValue]
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(kValue));
+
+ EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(),
+ graph()->start()));
+ EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+ EXPECT_FALSE(dependencies()->IsEmpty());
}
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_string) {
- Unique<HeapObject> const_value = Unique<HeapObject>::CreateImmovable(
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstString) {
+ Unique<HeapObject> kValue = Unique<HeapObject>::CreateImmovable(
isolate()->factory()->undefined_string());
- const char* property_name = "mango";
- SetGlobalProperty(property_name, const_value.handle());
-
- WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
- Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
- graph()->start());
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
- Reduction r = Reduce(ret->InputAt(0));
-
- if (FLAG_turbo_deoptimization) {
- // Check LoadNamed(global) => HeapConstant[const_value]
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(const_value));
-
- EXPECT_THAT(ret, IsReturn(IsHeapConstant(const_value), graph()->start(),
- graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
- } else {
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
- }
- }
+ const char* kName = "mango";
+ SetGlobalProperty(kName, kValue.handle());
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ ASSERT_FALSE(r.Changed());
+ EXPECT_TRUE(dependencies()->IsEmpty());
}
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCell_smi) {
- const char* property_name = "melon";
- SetGlobalProperty(property_name, 123);
- SetGlobalProperty(property_name, 124);
-
- WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
- Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
- graph()->start());
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
- Reduction r = Reduce(ret->InputAt(0));
-
- if (FLAG_turbo_deoptimization) {
- // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
- ASSERT_TRUE(r.Changed());
- FieldAccess access = AccessBuilder::ForPropertyCellValue();
- Capture<Node*> cell_capture;
- Matcher<Node*> load_field_match = IsLoadField(
- access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
- EXPECT_THAT(r.replacement(), load_field_match);
-
- HeapObjectMatcher<PropertyCell> cell(cell_capture.value());
- EXPECT_TRUE(cell.HasValue());
- EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
-
- EXPECT_THAT(
- ret, IsReturn(load_field_match, load_field_match, graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
- } else {
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
- }
- }
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstStringWithDeoptimization) {
+ Unique<HeapObject> kValue = Unique<HeapObject>::CreateImmovable(
+ isolate()->factory()->undefined_string());
+ const char* kName = "mango";
+ SetGlobalProperty(kName, kValue.handle());
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+ // Check LoadNamed(global) => HeapConstant[kValue]
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsHeapConstant(kValue));
+
+ EXPECT_THAT(ret, IsReturn(IsHeapConstant(kValue), graph()->start(),
+ graph()->start()));
+ EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+ EXPECT_FALSE(dependencies()->IsEmpty());
+ dependencies()->Rollback();
}
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCell_string) {
- const char* property_name = "pineapple";
- SetGlobalProperty(property_name, isolate()->factory()->undefined_string());
- SetGlobalProperty(property_name, isolate()->factory()->undefined_value());
-
- WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
- Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
- graph()->start());
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
- Reduction r = Reduce(ret->InputAt(0));
-
- if (FLAG_turbo_deoptimization) {
- // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
- ASSERT_TRUE(r.Changed());
- FieldAccess access = AccessBuilder::ForPropertyCellValue();
- Capture<Node*> cell_capture;
- Matcher<Node*> load_field_match = IsLoadField(
- access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
- EXPECT_THAT(r.replacement(), load_field_match);
-
- HeapObjectMatcher<PropertyCell> cell(cell_capture.value());
- EXPECT_TRUE(cell.HasValue());
- EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
-
- EXPECT_THAT(
- ret, IsReturn(load_field_match, load_field_match, graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
- } else {
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
- }
- }
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmi) {
+ const char* kName = "melon";
+ SetGlobalProperty(kName, 123);
+ SetGlobalProperty(kName, 124);
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ ASSERT_FALSE(r.Changed());
+ EXPECT_TRUE(dependencies()->IsEmpty());
}
+
+
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmiWithDeoptimization) {
+ const char* kName = "melon";
+ SetGlobalProperty(kName, 123);
+ SetGlobalProperty(kName, 124);
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+ // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
+ ASSERT_TRUE(r.Changed());
+ FieldAccess access = AccessBuilder::ForPropertyCellValue();
+ Capture<Node*> cell_capture;
+ Matcher<Node*> load_field_match = IsLoadField(
+ access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
+ EXPECT_THAT(r.replacement(), load_field_match);
+
+ HeapObjectMatcher cell(cell_capture.value());
+ EXPECT_TRUE(cell.HasValue());
+ EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
+
+ EXPECT_THAT(ret,
+ IsReturn(load_field_match, load_field_match, graph()->start()));
+ EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+ EXPECT_FALSE(dependencies()->IsEmpty());
+ dependencies()->Rollback();
}
+
+
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellString) {
+ const char* kName = "pineapple";
+ SetGlobalProperty(kName, isolate()->factory()->undefined_string());
+ SetGlobalProperty(kName, isolate()->factory()->undefined_value());
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+ ASSERT_FALSE(r.Changed());
+ EXPECT_TRUE(dependencies()->IsEmpty());
}
+
+
+TEST_F(JSTypeFeedbackTest,
+ JSLoadNamedGlobalPropertyCellStringWithDeoptimization) {
+ const char* kName = "pineapple";
+ SetGlobalProperty(kName, isolate()->factory()->undefined_string());
+ SetGlobalProperty(kName, isolate()->factory()->undefined_value());
+
+ Node* ret = ReturnLoadNamedFromGlobal(
+ kName, graph()->start(), graph()->start(),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
+
+ Reduction r = Reduce(ret->InputAt(0),
+ JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+ // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
+ ASSERT_TRUE(r.Changed());
+ FieldAccess access = AccessBuilder::ForPropertyCellValue();
+ Capture<Node*> cell_capture;
+ Matcher<Node*> load_field_match = IsLoadField(
+ access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
+ EXPECT_THAT(r.replacement(), load_field_match);
+
+ HeapObjectMatcher cell(cell_capture.value());
+ EXPECT_TRUE(cell.HasValue());
+ EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
+
+ EXPECT_THAT(ret,
+ IsReturn(load_field_match, load_field_match, graph()->start()));
+ EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+ EXPECT_FALSE(dependencies()->IsEmpty());
+ dependencies()->Rollback();
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
index 9e7b1eecbd..a12d79f02b 100644
--- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -80,16 +80,12 @@ class JSTypedLoweringTest : public TypedGraphTest {
Reduction Reduce(Node* node) {
MachineOperatorBuilder machine(zone());
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
- JSTypedLowering reducer(&jsgraph, zone());
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ JSTypedLowering reducer(&graph_reducer, &jsgraph, zone());
return reducer.Reduce(node);
}
- Node* EmptyFrameState() {
- MachineOperatorBuilder machine(zone());
- JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
- return jsgraph.EmptyFrameState();
- }
-
Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
Runtime::SetupArrayBuffer(isolate(), buffer, true, bytes, byte_length);
@@ -434,18 +430,27 @@ TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) {
TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
Node* const the_hole = HeapConstant(factory()->the_hole_value());
Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
TRACED_FOREACH(Type*, type, kJSTypes) {
Node* const lhs = Parameter(type);
- Reduction r = Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs,
- the_hole, context, effect, control));
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant());
}
}
+TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
+ Node* const lhs = Parameter(Type::Unique(), 0);
+ Node* const rhs = Parameter(Type::Unique(), 1);
+ Node* const context = Parameter(Type::Any(), 2);
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
+}
+
+
// -----------------------------------------------------------------------------
// JSShiftLeft
@@ -457,13 +462,12 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) {
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ShiftLeft(language_mode), lhs,
- NumberConstant(rhs), context, effect,
- control));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftLeft(language_mode), lhs, NumberConstant(rhs),
+ context, EmptyFrameState(), EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
- IsWord32Shl(lhs, IsNumberConstant(BitEq(rhs))));
+ IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
}
}
}
@@ -476,12 +480,11 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ShiftLeft(language_mode), lhs,
- rhs, context, effect, control));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftLeft(language_mode), lhs, rhs, context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsWord32Shl(lhs, IsWord32And(rhs, IsInt32Constant(0x1f))));
+ EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
}
}
@@ -497,13 +500,12 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) {
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction r =
- Reduce(graph()->NewNode(javascript()-> ShiftRight(language_mode), lhs,
- NumberConstant(rhs), context, effect,
- control));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftRight(language_mode), lhs, NumberConstant(rhs),
+ context, EmptyFrameState(), EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
- IsWord32Sar(lhs, IsNumberConstant(BitEq(rhs))));
+ IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
}
}
}
@@ -516,12 +518,11 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction r = Reduce(graph()->NewNode(javascript()->
- ShiftRight(language_mode), lhs, rhs,
- context, effect, control));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftRight(language_mode), lhs, rhs, context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsWord32Sar(lhs, IsWord32And(rhs, IsInt32Constant(0x1f))));
+ EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
}
}
@@ -538,14 +539,13 @@ TEST_F(JSTypedLoweringTest,
Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) {
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction r =
- Reduce(graph()->NewNode(javascript()->
- ShiftRightLogical(language_mode), lhs,
- NumberConstant(rhs), context, effect,
- control));
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->ShiftRightLogical(language_mode), lhs,
+ NumberConstant(rhs), context, EmptyFrameState(),
+ EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
- IsWord32Shr(lhs, IsNumberConstant(BitEq(rhs))));
+ IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
}
}
}
@@ -559,12 +559,11 @@ TEST_F(JSTypedLoweringTest,
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction r = Reduce(graph()->NewNode(javascript()->
- ShiftRightLogical(language_mode), lhs,
- rhs, context, effect, control));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftRightLogical(language_mode), lhs, rhs, context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsWord32Shr(lhs, IsWord32And(rhs, IsInt32Constant(0x1f))));
+ EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
}
}
@@ -646,36 +645,39 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
double backing_store[kLength];
Handle<JSArrayBuffer> buffer =
NewArrayBuffer(backing_store, sizeof(backing_store));
- VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(),
- FeedbackVectorICSlot::Invalid());
+ VectorSlotPair feedback;
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
- Handle<JSTypedArray> array =
- factory()->NewJSTypedArray(type, buffer, 0, kLength);
- int const element_size = static_cast<int>(array->element_size());
-
- Node* key = Parameter(
- Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
- Node* base = HeapConstant(array);
- Node* context = UndefinedConstant();
- Node* effect = graph()->start();
- Node* control = graph()->start();
- Reduction r =
- Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key,
- context, EmptyFrameState(), effect, control));
+ TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+ Handle<JSTypedArray> array =
+ factory()->NewJSTypedArray(type, buffer, 0, kLength);
+ int const element_size = static_cast<int>(array->element_size());
+
+ Node* key = Parameter(
+ Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
+ Node* base = HeapConstant(array);
+ Node* vector = UndefinedConstant();
+ Node* context = UndefinedConstant();
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->LoadProperty(feedback, language_mode),
+ base, key, vector, context, EmptyFrameState(),
+ EmptyFrameState(), effect, control));
- Matcher<Node*> offset_matcher =
- element_size == 1
- ? key
- : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
+ Matcher<Node*> offset_matcher =
+ element_size == 1
+ ? key
+ : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsLoadBuffer(BufferAccess(type),
- IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
- offset_matcher,
- IsNumberConstant(array->byte_length()->Number()), effect,
- control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsLoadBuffer(BufferAccess(type),
+ IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+ offset_matcher,
+ IsNumberConstant(array->byte_length()->Number()), effect,
+ control));
+ }
}
}
@@ -685,31 +687,34 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
double backing_store[kLength];
Handle<JSArrayBuffer> buffer =
NewArrayBuffer(backing_store, sizeof(backing_store));
- VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(),
- FeedbackVectorICSlot::Invalid());
+ VectorSlotPair feedback;
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
- Handle<JSTypedArray> array =
- factory()->NewJSTypedArray(type, buffer, 0, kLength);
- ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
-
- int min = random_number_generator()->NextInt(static_cast<int>(kLength));
- int max = random_number_generator()->NextInt(static_cast<int>(kLength));
- if (min > max) std::swap(min, max);
- Node* key = Parameter(Type::Range(min, max, zone()));
- Node* base = HeapConstant(array);
- Node* context = UndefinedConstant();
- Node* effect = graph()->start();
- Node* control = graph()->start();
- Reduction r =
- Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key,
- context, EmptyFrameState(), effect, control));
+ TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+ Handle<JSTypedArray> array =
+ factory()->NewJSTypedArray(type, buffer, 0, kLength);
+ ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsLoadElement(access,
- IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
- key, effect, control));
+ int min = random_number_generator()->NextInt(static_cast<int>(kLength));
+ int max = random_number_generator()->NextInt(static_cast<int>(kLength));
+ if (min > max) std::swap(min, max);
+ Node* key = Parameter(Type::Range(min, max, zone()));
+ Node* base = HeapConstant(array);
+ Node* vector = UndefinedConstant();
+ Node* context = UndefinedConstant();
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->LoadProperty(feedback, language_mode),
+ base, key, vector, context, EmptyFrameState(),
+ EmptyFrameState(), effect, control));
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsLoadElement(access,
+ IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+ key, effect, control));
+ }
}
}
@@ -734,11 +739,13 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
Node* base = HeapConstant(array);
Node* value =
Parameter(AccessBuilder::ForTypedArrayElement(type, true).type);
+ Node* vector = UndefinedConstant();
Node* context = UndefinedConstant();
Node* effect = graph()->start();
Node* control = graph()->start();
- Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
- base, key, value, context);
+ VectorSlotPair feedback;
+ const Operator* op = javascript()->StoreProperty(language_mode, feedback);
+ Node* node = graph()->NewNode(op, base, key, value, vector, context);
for (int i = 0;
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
node->AppendInput(zone(), EmptyFrameState());
@@ -780,11 +787,13 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
Node* base = HeapConstant(array);
Node* value = Parameter(Type::Any());
+ Node* vector = UndefinedConstant();
Node* context = UndefinedConstant();
Node* effect = graph()->start();
Node* control = graph()->start();
- Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
- base, key, value, context);
+ VectorSlotPair feedback;
+ const Operator* op = javascript()->StoreProperty(language_mode, feedback);
+ Node* node = graph()->NewNode(op, base, key, value, vector, context);
for (int i = 0;
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
node->AppendInput(zone(), EmptyFrameState());
@@ -839,11 +848,13 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
Node* key = Parameter(Type::Range(min, max, zone()));
Node* base = HeapConstant(array);
Node* value = Parameter(access.type);
+ Node* vector = UndefinedConstant();
Node* context = UndefinedConstant();
Node* effect = graph()->start();
Node* control = graph()->start();
- Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode),
- base, key, value, context);
+ VectorSlotPair feedback;
+ const Operator* op = javascript()->StoreProperty(language_mode, feedback);
+ Node* node = graph()->NewNode(op, base, key, value, vector, context);
for (int i = 0;
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
node->AppendInput(zone(), EmptyFrameState());
@@ -876,18 +887,18 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedGlobalConstants) {
IsNumberConstant(IsNaN()) // --
};
- VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(),
- FeedbackVectorICSlot::Invalid());
- Node* global = Parameter(Type::GlobalObject());
+ VectorSlotPair feedback;
+ Node* global = UndefinedConstant();
+ Node* vector = UndefinedConstant();
Node* context = UndefinedConstant();
Node* effect = graph()->start();
Node* control = graph()->start();
for (size_t i = 0; i < arraysize(names); i++) {
Unique<Name> name = Unique<Name>::CreateImmovable(names[i]);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->LoadNamed(name, feedback), global,
- context, EmptyFrameState(), effect, control));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->LoadGlobal(name, feedback), global, vector, context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), matches[i]);
@@ -896,9 +907,106 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedGlobalConstants) {
// -----------------------------------------------------------------------------
-// JSCreateClosure
+// JSLoadDynamicGlobal
+
+
+TEST_F(JSTypedLoweringTest, JSLoadDynamicGlobal) {
+ Node* const context = Parameter(Type::Any());
+ Node* const vector = UndefinedConstant();
+ Node* const frame_state = EmptyFrameState();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<String> name = factory()->object_string();
+ VectorSlotPair feedback;
+ for (int i = 0; i < DynamicGlobalAccess::kMaxCheckDepth; ++i) {
+ uint32_t bitset = 1 << i; // Only single check.
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->LoadDynamicGlobal(name, bitset, feedback, NOT_CONTEXTUAL),
+ vector, context, context, frame_state, frame_state, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsPhi(kMachAnyTagged, _, _,
+ IsMerge(
+ IsIfTrue(IsBranch(
+ IsReferenceEqual(
+ Type::Tagged(),
+ IsLoadContext(
+ ContextAccess(i, Context::EXTENSION_INDEX, false),
+ context),
+ IsNumberConstant(BitEq(0.0))),
+ control)),
+ _)));
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// JSLoadDynamicContext
+
+
+TEST_F(JSTypedLoweringTest, JSLoadDynamicContext) {
+ Node* const context = Parameter(Type::Any());
+ Node* const frame_state = EmptyFrameState();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<String> name = factory()->object_string();
+ for (int i = 0; i < DynamicContextAccess::kMaxCheckDepth; ++i) {
+ uint32_t bitset = 1 << i; // Only single check.
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->LoadDynamicContext(name, bitset, 23, 42),
+ context, context, frame_state, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsPhi(kMachAnyTagged,
+ IsLoadContext(ContextAccess(23, 42, false), context), _,
+ IsMerge(
+ IsIfTrue(IsBranch(
+ IsReferenceEqual(
+ Type::Tagged(),
+ IsLoadContext(
+ ContextAccess(i, Context::EXTENSION_INDEX, false),
+ context),
+ IsNumberConstant(BitEq(0.0))),
+ control)),
+ _)));
+ }
+}
#if V8_TURBOFAN_TARGET
+
+// -----------------------------------------------------------------------------
+// JSAdd
+
+
+TEST_F(JSTypedLoweringTest, JSAddWithString) {
+ TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+ Node* lhs = Parameter(Type::String(), 0);
+ Node* rhs = Parameter(Type::String(), 1);
+ Node* context = Parameter(Type::Any(), 2);
+ Node* frame_state0 = EmptyFrameState();
+ Node* frame_state1 = EmptyFrameState();
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Reduction r = Reduce(graph()->NewNode(javascript()->Add(language_mode), lhs,
+ rhs, context, frame_state0,
+ frame_state1, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
+ CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE,
+ NOT_TENURED).code())),
+ lhs, rhs, context, frame_state0, effect, control));
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// JSCreateClosure
+
+
TEST_F(JSTypedLoweringTest, JSCreateClosure) {
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
@@ -965,7 +1073,8 @@ TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) {
CodeFactory::FastCloneShallowObject(isolate(), 6).code())),
input0, input1, input2, _, context, frame_state, effect, control));
}
-#endif
+
+#endif // V8_TURBOFAN_TARGET
// -----------------------------------------------------------------------------
diff --git a/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
index d5a95ccd1d..1e142550d5 100644
--- a/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
@@ -57,8 +57,13 @@ class LivenessAnalysisTest : public GraphTest {
Node* locals =
graph()->NewNode(locals_op, locals_count_, &local_inputs.front());
+ const FrameStateFunctionInfo* state_info =
+ common()->CreateFrameStateFunctionInfo(
+ FrameStateType::kJavaScriptFunction, 0, locals_count_,
+ Handle<SharedFunctionInfo>());
+
const Operator* op = common()->FrameState(
- JS_FRAME, BailoutId(ast_num), OutputFrameStateCombine::Ignore());
+ BailoutId(ast_num), OutputFrameStateCombine::Ignore(), state_info);
Node* result = graph()->NewNode(op, empty_values_, locals, empty_values_,
jsgraph()->UndefinedConstant(),
jsgraph()->UndefinedConstant());
@@ -93,8 +98,7 @@ class LivenessAnalysisTest : public GraphTest {
}
DCHECK(frame_state->opcode() == IrOpcode::kFrameState);
- FrameStateCallInfo state_info =
- OpParameter<FrameStateCallInfo>(frame_state);
+ FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
int ast_num = state_info.bailout_id().ToInt();
int first_const = intconst_from_bailout_id(ast_num, locals_count_);
diff --git a/deps/v8/test/unittests/compiler/load-elimination-unittest.cc b/deps/v8/test/unittests/compiler/load-elimination-unittest.cc
index 52c3143e2a..3ad11cf43f 100644
--- a/deps/v8/test/unittests/compiler/load-elimination-unittest.cc
+++ b/deps/v8/test/unittests/compiler/load-elimination-unittest.cc
@@ -19,7 +19,9 @@ class LoadEliminationTest : public GraphTest {
protected:
Reduction Reduce(Node* node) {
- LoadElimination reducer;
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ LoadElimination reducer(&graph_reducer);
return reducer.Reduce(node);
}
diff --git a/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc b/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc
index d3eff716a7..c725a27cc0 100644
--- a/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc
+++ b/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc
@@ -478,7 +478,8 @@ TEST_F(LoopPeelingTest, TwoExitLoopWithCall_nope) {
Node* call = graph()->NewNode(&kMockCall, b1.if_true);
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
- Node* if_exception = graph()->NewNode(common()->IfException(), call);
+ Node* if_exception = graph()->NewNode(
+ common()->IfException(IfExceptionHint::kLocallyUncaught), call);
loop->ReplaceInput(1, if_success);
Node* merge = graph()->NewNode(common()->Merge(2), b1.if_false, if_exception);
diff --git a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
index 9836be4fb2..ce11fdef81 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -234,6 +234,10 @@ const uint32_t kUint32Values[] = {
0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
+const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript,
+ TruncationMode::kRoundToZero};
+
+
struct ComparisonBinaryOperator {
const Operator* (MachineOperatorBuilder::*constructor)();
const char* constructor_name;
@@ -258,53 +262,6 @@ const ComparisonBinaryOperator kComparisonBinaryOperators[] = {
// -----------------------------------------------------------------------------
-// Unary operators
-
-
-namespace {
-
-struct UnaryOperator {
- const Operator* (MachineOperatorBuilder::*constructor)();
- const char* constructor_name;
-};
-
-
-std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) {
- return os << unop.constructor_name;
-}
-
-
-static const UnaryOperator kUnaryOperators[] = {
- {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"},
- {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"},
- {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"},
- {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"},
- {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"},
- {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"},
- {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"},
- {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}};
-
-} // namespace
-
-
-typedef MachineOperatorReducerTestWithParam<UnaryOperator>
- MachineUnaryOperatorReducerTest;
-
-
-TEST_P(MachineUnaryOperatorReducerTest, Parameter) {
- const UnaryOperator unop = GetParam();
- Reduction reduction =
- Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0)));
- EXPECT_FALSE(reduction.Changed());
-}
-
-
-INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest,
- MachineUnaryOperatorReducerTest,
- ::testing::ValuesIn(kUnaryOperators));
-
-
-// -----------------------------------------------------------------------------
// ChangeFloat64ToFloat32
@@ -459,19 +416,22 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
TEST_F(MachineOperatorReducerTest,
TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
- Node* value = Parameter(0);
- Reduction reduction = Reduce(graph()->NewNode(
- machine()->TruncateFloat64ToInt32(),
- graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_EQ(value, reduction.replacement());
+ TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
+ Node* value = Parameter(0);
+ Reduction reduction = Reduce(graph()->NewNode(
+ machine()->TruncateFloat64ToInt32(mode),
+ graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_EQ(value, reduction.replacement());
+ }
}
TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction reduction = Reduce(graph()->NewNode(
- machine()->TruncateFloat64ToInt32(), Float64Constant(x)));
+ machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript),
+ Float64Constant(x)));
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
}
@@ -482,13 +442,15 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
Node* const p0 = Parameter(0);
Node* const p1 = Parameter(1);
Node* const merge = graph()->start();
- Reduction reduction = Reduce(graph()->NewNode(
- machine()->TruncateFloat64ToInt32(),
- graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(reduction.replacement(),
- IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0),
- IsTruncateFloat64ToInt32(p1), merge));
+ TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
+ Reduction reduction = Reduce(graph()->NewNode(
+ machine()->TruncateFloat64ToInt32(mode),
+ graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(),
+ IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0),
+ IsTruncateFloat64ToInt32(p1), merge));
+ }
}
diff --git a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
index 31f55793c3..fca53e2bd8 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
@@ -149,130 +149,199 @@ INSTANTIATE_TEST_CASE_P(
::testing::Combine(::testing::ValuesIn(kMachineTypes),
::testing::Values(kNoWriteBarrier,
kFullWriteBarrier))));
-
+#endif
// -----------------------------------------------------------------------------
// Pure operators.
-
namespace {
struct PureOperator {
const Operator* (MachineOperatorBuilder::*constructor)();
- IrOpcode::Value opcode;
+ char const* const constructor_name;
int value_input_count;
int control_input_count;
int value_output_count;
};
-std::ostream& operator<<(std::ostream& os, const PureOperator& pop) {
- return os << IrOpcode::Mnemonic(pop.opcode);
+std::ostream& operator<<(std::ostream& os, PureOperator const& pop) {
+ return os << pop.constructor_name;
}
-
const PureOperator kPureOperators[] = {
#define PURE(Name, value_input_count, control_input_count, value_output_count) \
{ \
- &MachineOperatorBuilder::Name, IrOpcode::k##Name, value_input_count, \
+ &MachineOperatorBuilder::Name, #Name, value_input_count, \
control_input_count, value_output_count \
}
- PURE(Word32And, 2, 0, 1), PURE(Word32Or, 2, 0, 1), PURE(Word32Xor, 2, 0, 1),
- PURE(Word32Shl, 2, 0, 1), PURE(Word32Shr, 2, 0, 1),
- PURE(Word32Sar, 2, 0, 1), PURE(Word32Ror, 2, 0, 1),
- PURE(Word32Equal, 2, 0, 1), PURE(Word32Clz, 1, 0, 1),
- PURE(Word64And, 2, 0, 1), PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1),
- PURE(Word64Shl, 2, 0, 1), PURE(Word64Shr, 2, 0, 1),
- PURE(Word64Sar, 2, 0, 1), PURE(Word64Ror, 2, 0, 1),
- PURE(Word64Equal, 2, 0, 1), PURE(Int32Add, 2, 0, 1),
- PURE(Int32AddWithOverflow, 2, 0, 2), PURE(Int32Sub, 2, 0, 1),
- PURE(Int32SubWithOverflow, 2, 0, 2), PURE(Int32Mul, 2, 0, 1),
- PURE(Int32MulHigh, 2, 0, 1), PURE(Int32Div, 2, 1, 1),
- PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1), PURE(Uint32Mod, 2, 1, 1),
- PURE(Int32LessThan, 2, 0, 1), PURE(Int32LessThanOrEqual, 2, 0, 1),
- PURE(Uint32LessThan, 2, 0, 1), PURE(Uint32LessThanOrEqual, 2, 0, 1),
- PURE(Int64Add, 2, 0, 1), PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1),
- PURE(Int64Div, 2, 0, 1), PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1),
- PURE(Uint64Mod, 2, 0, 1), PURE(Int64LessThan, 2, 0, 1),
- PURE(Int64LessThanOrEqual, 2, 0, 1), PURE(Uint64LessThan, 2, 0, 1),
- PURE(ChangeFloat32ToFloat64, 1, 0, 1), PURE(ChangeFloat64ToInt32, 1, 0, 1),
- PURE(ChangeFloat64ToUint32, 1, 0, 1), PURE(ChangeInt32ToInt64, 1, 0, 1),
- PURE(ChangeUint32ToFloat64, 1, 0, 1), PURE(ChangeUint32ToUint64, 1, 0, 1),
- PURE(TruncateFloat64ToFloat32, 1, 0, 1),
- PURE(TruncateFloat64ToInt32, 1, 0, 1), PURE(TruncateInt64ToInt32, 1, 0, 1),
- PURE(Float32Add, 2, 0, 1), PURE(Float32Sub, 2, 0, 1),
- PURE(Float32Mul, 2, 0, 1), PURE(Float32Div, 2, 0, 1),
- PURE(Float32Abs, 1, 0, 1), PURE(Float32Sqrt, 1, 0, 1),
- PURE(Float32Equal, 2, 0, 1), PURE(Float32LessThan, 2, 0, 1),
- PURE(Float32LessThanOrEqual, 2, 0, 1), PURE(Float32Max, 2, 0, 1),
- PURE(Float32Min, 2, 0, 1), PURE(Float64Add, 2, 0, 1),
- PURE(Float64Sub, 2, 0, 1), PURE(Float64Mul, 2, 0, 1),
- PURE(Float64Div, 2, 0, 1), PURE(Float64Mod, 2, 0, 1),
- PURE(Float64Abs, 1, 0, 1), PURE(Float64Sqrt, 1, 0, 1),
- PURE(Float64Equal, 2, 0, 1), PURE(Float64LessThan, 2, 0, 1),
- PURE(Float64LessThanOrEqual, 2, 0, 1), PURE(Float64Max, 2, 0, 1),
- PURE(Float64Min, 2, 0, 1), PURE(LoadStackPointer, 0, 0, 1),
- PURE(Float64RoundDown, 1, 0, 1), PURE(Float64RoundTruncate, 1, 0, 1),
- PURE(Float64RoundTiesAway, 1, 0, 1), PURE(Float64ExtractLowWord32, 1, 0, 1),
- PURE(Float64ExtractHighWord32, 1, 0, 1),
- PURE(Float64InsertLowWord32, 2, 0, 1),
- PURE(Float64InsertHighWord32, 2, 0, 1)
+ PURE(Word32And, 2, 0, 1), // --
+ PURE(Word32Or, 2, 0, 1), // --
+ PURE(Word32Xor, 2, 0, 1), // --
+ PURE(Word32Shl, 2, 0, 1), // --
+ PURE(Word32Shr, 2, 0, 1), // --
+ PURE(Word32Sar, 2, 0, 1), // --
+ PURE(Word32Ror, 2, 0, 1), // --
+ PURE(Word32Equal, 2, 0, 1), // --
+ PURE(Word32Clz, 1, 0, 1), // --
+ PURE(Word64And, 2, 0, 1), // --
+ PURE(Word64Or, 2, 0, 1), // --
+ PURE(Word64Xor, 2, 0, 1), // --
+ PURE(Word64Shl, 2, 0, 1), // --
+ PURE(Word64Shr, 2, 0, 1), // --
+ PURE(Word64Sar, 2, 0, 1), // --
+ PURE(Word64Ror, 2, 0, 1), // --
+ PURE(Word64Equal, 2, 0, 1), // --
+ PURE(Int32Add, 2, 0, 1), // --
+ PURE(Int32AddWithOverflow, 2, 0, 2), // --
+ PURE(Int32Sub, 2, 0, 1), // --
+ PURE(Int32SubWithOverflow, 2, 0, 2), // --
+ PURE(Int32Mul, 2, 0, 1), // --
+ PURE(Int32MulHigh, 2, 0, 1), // --
+ PURE(Int32Div, 2, 1, 1), // --
+ PURE(Uint32Div, 2, 1, 1), // --
+ PURE(Int32Mod, 2, 1, 1), // --
+ PURE(Uint32Mod, 2, 1, 1), // --
+ PURE(Int32LessThan, 2, 0, 1), // --
+ PURE(Int32LessThanOrEqual, 2, 0, 1), // --
+ PURE(Uint32LessThan, 2, 0, 1), // --
+ PURE(Uint32LessThanOrEqual, 2, 0, 1), // --
+ PURE(Int64Add, 2, 0, 1), // --
+ PURE(Int64Sub, 2, 0, 1), // --
+ PURE(Int64Mul, 2, 0, 1), // --
+ PURE(Int64Div, 2, 1, 1), // --
+ PURE(Uint64Div, 2, 1, 1), // --
+ PURE(Int64Mod, 2, 1, 1), // --
+ PURE(Uint64Mod, 2, 1, 1), // --
+ PURE(Int64LessThan, 2, 0, 1), // --
+ PURE(Int64LessThanOrEqual, 2, 0, 1), // --
+ PURE(Uint64LessThan, 2, 0, 1), // --
+ PURE(Uint64LessThanOrEqual, 2, 0, 1), // --
+ PURE(ChangeFloat32ToFloat64, 1, 0, 1), // --
+ PURE(ChangeFloat64ToInt32, 1, 0, 1), // --
+ PURE(ChangeFloat64ToUint32, 1, 0, 1), // --
+ PURE(ChangeInt32ToInt64, 1, 0, 1), // --
+ PURE(ChangeUint32ToFloat64, 1, 0, 1), // --
+ PURE(ChangeUint32ToUint64, 1, 0, 1), // --
+ PURE(TruncateFloat64ToFloat32, 1, 0, 1), // --
+ PURE(TruncateInt64ToInt32, 1, 0, 1), // --
+ PURE(Float32Abs, 1, 0, 1), // --
+ PURE(Float32Add, 2, 0, 1), // --
+ PURE(Float32Sub, 2, 0, 1), // --
+ PURE(Float32Mul, 2, 0, 1), // --
+ PURE(Float32Div, 2, 0, 1), // --
+ PURE(Float32Sqrt, 1, 0, 1), // --
+ PURE(Float32Equal, 2, 0, 1), // --
+ PURE(Float32LessThan, 2, 0, 1), // --
+ PURE(Float32LessThanOrEqual, 2, 0, 1), // --
+ PURE(Float64Abs, 1, 0, 1), // --
+ PURE(Float64Add, 2, 0, 1), // --
+ PURE(Float64Sub, 2, 0, 1), // --
+ PURE(Float64Mul, 2, 0, 1), // --
+ PURE(Float64Div, 2, 0, 1), // --
+ PURE(Float64Mod, 2, 0, 1), // --
+ PURE(Float64Sqrt, 1, 0, 1), // --
+ PURE(Float64Equal, 2, 0, 1), // --
+ PURE(Float64LessThan, 2, 0, 1), // --
+ PURE(Float64LessThanOrEqual, 2, 0, 1), // --
+ PURE(LoadStackPointer, 0, 0, 1), // --
+ PURE(Float64ExtractLowWord32, 1, 0, 1), // --
+ PURE(Float64ExtractHighWord32, 1, 0, 1), // --
+ PURE(Float64InsertLowWord32, 2, 0, 1), // --
+ PURE(Float64InsertHighWord32, 2, 0, 1), // --
#undef PURE
};
-
-typedef MachineOperatorTestWithParam<PureOperator> MachinePureOperatorTest;
-
} // namespace
+class MachinePureOperatorTest : public TestWithZone {
+ protected:
+ MachineType word_type() { return kMachPtr; }
+};
-TEST_P(MachinePureOperatorTest, InstancesAreGloballyShared) {
- const PureOperator& pop = GetParam();
- MachineOperatorBuilder machine1(zone(), type());
- MachineOperatorBuilder machine2(zone(), type());
- EXPECT_EQ((machine1.*pop.constructor)(), (machine2.*pop.constructor)());
+
+TEST_F(MachinePureOperatorTest, PureOperators) {
+ TRACED_FOREACH(MachineType, machine_rep1, kMachineReps) {
+ MachineOperatorBuilder machine1(zone(), machine_rep1);
+ TRACED_FOREACH(MachineType, machine_rep2, kMachineReps) {
+ MachineOperatorBuilder machine2(zone(), machine_rep2);
+ TRACED_FOREACH(PureOperator, pop, kPureOperators) {
+ const Operator* op1 = (machine1.*pop.constructor)();
+ const Operator* op2 = (machine2.*pop.constructor)();
+ EXPECT_EQ(op1, op2);
+ EXPECT_EQ(pop.value_input_count, op1->ValueInputCount());
+ EXPECT_EQ(pop.control_input_count, op1->ControlInputCount());
+ EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount());
+ }
+ }
+ }
}
-TEST_P(MachinePureOperatorTest, NumberOfInputsAndOutputs) {
- MachineOperatorBuilder machine(zone(), type());
- const PureOperator& pop = GetParam();
- const Operator* op = (machine.*pop.constructor)();
+// Optional operators.
- EXPECT_EQ(pop.value_input_count, op->ValueInputCount());
- EXPECT_EQ(0, op->EffectInputCount());
- EXPECT_EQ(pop.control_input_count, op->ControlInputCount());
- EXPECT_EQ(pop.value_input_count + pop.control_input_count,
- OperatorProperties::GetTotalInputCount(op));
+namespace {
- EXPECT_EQ(pop.value_output_count, op->ValueOutputCount());
- EXPECT_EQ(0, op->EffectOutputCount());
- EXPECT_EQ(0, op->ControlOutputCount());
-}
+struct OptionalOperatorEntry {
+ const OptionalOperator (MachineOperatorBuilder::*constructor)();
+ MachineOperatorBuilder::Flag enabling_flag;
+ char const* const constructor_name;
+ int value_input_count;
+ int control_input_count;
+ int value_output_count;
+};
-TEST_P(MachinePureOperatorTest, MarkedAsPure) {
- MachineOperatorBuilder machine(zone(), type());
- const PureOperator& pop = GetParam();
- const Operator* op = (machine.*pop.constructor)();
- EXPECT_TRUE(op->HasProperty(Operator::kPure));
+std::ostream& operator<<(std::ostream& os, OptionalOperatorEntry const& pop) {
+ return os << pop.constructor_name;
}
+const OptionalOperatorEntry kOptionalOperators[] = {
+#define OPTIONAL_ENTRY(Name, value_input_count, control_input_count, \
+ value_output_count) \
+ { \
+ &MachineOperatorBuilder::Name, MachineOperatorBuilder::k##Name, #Name, \
+ value_input_count, control_input_count, value_output_count \
+ }
+ OPTIONAL_ENTRY(Float32Max, 2, 0, 1), // --
+ OPTIONAL_ENTRY(Float32Min, 2, 0, 1), // --
+ OPTIONAL_ENTRY(Float64Max, 2, 0, 1), // --
+ OPTIONAL_ENTRY(Float64Min, 2, 0, 1), // --
+ OPTIONAL_ENTRY(Float64RoundDown, 1, 0, 1), // --
+ OPTIONAL_ENTRY(Float64RoundTruncate, 1, 0, 1), // --
+ OPTIONAL_ENTRY(Float64RoundTiesAway, 1, 0, 1), // --
+#undef OPTIONAL_ENTRY
+};
+} // namespace
-TEST_P(MachinePureOperatorTest, OpcodeIsCorrect) {
- MachineOperatorBuilder machine(zone(), type());
- const PureOperator& pop = GetParam();
- const Operator* op = (machine.*pop.constructor)();
- EXPECT_EQ(pop.opcode, op->opcode());
-}
+class MachineOptionalOperatorTest : public TestWithZone {
+ protected:
+ MachineType word_type() { return kMachPtr; }
+};
-INSTANTIATE_TEST_CASE_P(
- MachineOperatorTest, MachinePureOperatorTest,
- ::testing::Combine(::testing::ValuesIn(kMachineReps),
- ::testing::ValuesIn(kPureOperators)));
-#endif // GTEST_HAS_COMBINE
+TEST_F(MachineOptionalOperatorTest, OptionalOperators) {
+ TRACED_FOREACH(OptionalOperatorEntry, pop, kOptionalOperators) {
+ TRACED_FOREACH(MachineType, machine_rep1, kMachineReps) {
+ MachineOperatorBuilder machine1(zone(), machine_rep1, pop.enabling_flag);
+ TRACED_FOREACH(MachineType, machine_rep2, kMachineReps) {
+ MachineOperatorBuilder machine2(zone(), machine_rep2,
+ pop.enabling_flag);
+ const Operator* op1 = (machine1.*pop.constructor)().op();
+ const Operator* op2 = (machine2.*pop.constructor)().op();
+ EXPECT_EQ(op1, op2);
+ EXPECT_EQ(pop.value_input_count, op1->ValueInputCount());
+ EXPECT_EQ(pop.control_input_count, op1->ControlInputCount());
+ EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount());
+
+ MachineOperatorBuilder machine3(zone(), word_type());
+ EXPECT_TRUE((machine1.*pop.constructor)().IsSupported());
+ EXPECT_FALSE((machine3.*pop.constructor)().IsSupported());
+ }
+ }
+ }
+}
// -----------------------------------------------------------------------------
diff --git a/deps/v8/test/unittests/compiler/node-properties-unittest.cc b/deps/v8/test/unittests/compiler/node-properties-unittest.cc
index 2bec4faf4d..463948d43f 100644
--- a/deps/v8/test/unittests/compiler/node-properties-unittest.cc
+++ b/deps/v8/test/unittests/compiler/node-properties-unittest.cc
@@ -10,78 +10,72 @@
using testing::AnyOf;
using testing::ElementsAre;
using testing::IsNull;
-using testing::UnorderedElementsAre;
namespace v8 {
namespace internal {
namespace compiler {
-typedef TestWithZone NodePropertiesTest;
-
+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, 0, 0);
-const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties,
- "MockOpEffect", 0, 1, 0, 1, 1, 0);
-const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties,
- "MockOpControl", 0, 0, 1, 1, 0, 1);
+ "MockOperator", 0, 0, 0, 1, 1, 2);
const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
"MockCallOperator", 0, 0, 0, 0, 0, 2);
-} // namespace
-
-
-TEST_F(NodePropertiesTest, ReplaceWithValue_ValueUse) {
- CommonOperatorBuilder common(zone());
- Node* node = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
- Node* use_value = Node::New(zone(), 0, common.Return(), 1, &node, false);
- Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
- NodeProperties::ReplaceWithValue(node, replacement);
- EXPECT_EQ(replacement, use_value->InputAt(0));
- EXPECT_EQ(0, node->UseCount());
- EXPECT_EQ(1, replacement->UseCount());
- EXPECT_THAT(replacement->uses(), ElementsAre(use_value));
-}
-
+const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
-TEST_F(NodePropertiesTest, ReplaceWithValue_EffectUse) {
- CommonOperatorBuilder common(zone());
- Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
- Node* node = Node::New(zone(), 0, &kMockOpEffect, 1, &start, false);
- Node* use_effect = Node::New(zone(), 0, common.EffectPhi(1), 1, &node, false);
- Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
- NodeProperties::ReplaceWithValue(node, replacement);
- EXPECT_EQ(start, use_effect->InputAt(0));
- EXPECT_EQ(0, node->UseCount());
- EXPECT_EQ(2, start->UseCount());
- EXPECT_EQ(0, replacement->UseCount());
- EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node));
-}
+} // namespace
-TEST_F(NodePropertiesTest, ReplaceWithValue_ControlUse) {
+TEST_F(NodePropertiesTest, ReplaceUses) {
CommonOperatorBuilder common(zone());
- Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
- Node* node = Node::New(zone(), 0, &kMockOpControl, 1, &start, false);
- Node* success = Node::New(zone(), 0, common.IfSuccess(), 1, &node, false);
- Node* use_control = Node::New(zone(), 0, common.Merge(1), 1, &success, false);
- Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false);
- NodeProperties::ReplaceWithValue(node, replacement);
- EXPECT_EQ(start, use_control->InputAt(0));
+ 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(2, start->UseCount());
- EXPECT_EQ(0, replacement->UseCount());
- EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node));
+ 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 = Node::New(zone(), 0, common.Start(1), 0, nullptr, false);
- Node* proj0 = Node::New(zone(), 1, common.Projection(0), 1, &start, false);
- Node* proj1 = Node::New(zone(), 2, common.Projection(1), 1, &start, false);
+ 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());
@@ -92,9 +86,9 @@ TEST_F(NodePropertiesTest, FindProjection) {
TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
Node* result[2];
CommonOperatorBuilder common(zone());
- Node* branch = Node::New(zone(), 1, common.Branch(), 0, nullptr, false);
- Node* if_false = Node::New(zone(), 2, common.IfFalse(), 1, &branch, false);
- Node* if_true = Node::New(zone(), 3, common.IfTrue(), 1, &branch, false);
+ 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]);
@@ -104,9 +98,9 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
Node* result[2];
CommonOperatorBuilder common(zone());
- Node* call = Node::New(zone(), 1, &kMockCallOperator, 0, nullptr, false);
- Node* if_ex = Node::New(zone(), 2, common.IfException(), 1, &call, false);
- Node* if_ok = Node::New(zone(), 3, common.IfSuccess(), 1, &call, false);
+ 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]);
@@ -116,10 +110,10 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
TEST_F(NodePropertiesTest, CollectControlProjections_Switch) {
Node* result[3];
CommonOperatorBuilder common(zone());
- Node* sw = Node::New(zone(), 1, common.Switch(3), 0, nullptr, false);
- Node* if_default = Node::New(zone(), 2, common.IfDefault(), 1, &sw, false);
- Node* if_value1 = Node::New(zone(), 3, common.IfValue(1), 1, &sw, false);
- Node* if_value2 = Node::New(zone(), 4, common.IfValue(2), 1, &sw, false);
+ 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));
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.cc b/deps/v8/test/unittests/compiler/node-test-utils.cc
index e6201ec67f..520ce0159e 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.cc
+++ b/deps/v8/test/unittests/compiler/node-test-utils.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "src/assembler.h"
+#include "src/compiler/js-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
#include "src/unique.h"
@@ -748,6 +749,32 @@ class IsTailCallMatcher final : public NodeMatcher {
};
+class IsReferenceEqualMatcher final : public NodeMatcher {
+ public:
+ IsReferenceEqualMatcher(const Matcher<Type*>& type_matcher,
+ const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher)
+ : NodeMatcher(IrOpcode::kReferenceEqual),
+ type_matcher_(type_matcher),
+ lhs_matcher_(lhs_matcher),
+ rhs_matcher_(rhs_matcher) {}
+
+ bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ // TODO(bmeurer): The type parameter is currently ignored.
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs",
+ lhs_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs",
+ rhs_matcher_, listener));
+ }
+
+ private:
+ const Matcher<Type*> type_matcher_;
+ const Matcher<Node*> lhs_matcher_;
+ const Matcher<Node*> rhs_matcher_;
+};
+
+
class IsAllocateMatcher final : public NodeMatcher {
public:
IsAllocateMatcher(const Matcher<Node*>& size_matcher,
@@ -1160,24 +1187,32 @@ class IsLoadMatcher final : public NodeMatcher {
};
-class IsToNumberMatcher final : public NodeMatcher {
+class IsStoreMatcher final : public NodeMatcher {
public:
- IsToNumberMatcher(const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& context_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kJSToNumber),
+ IsStoreMatcher(const Matcher<StoreRepresentation>& rep_matcher,
+ const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& index_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kStore),
+ rep_matcher_(rep_matcher),
base_matcher_(base_matcher),
- context_matcher_(context_matcher),
+ index_matcher_(index_matcher),
+ value_matcher_(value_matcher),
effect_matcher_(effect_matcher),
control_matcher_(control_matcher) {}
void DescribeTo(std::ostream* os) const final {
NodeMatcher::DescribeTo(os);
- *os << " whose base (";
+ *os << " whose rep (";
+ rep_matcher_.DescribeTo(os);
+ *os << "), base (";
base_matcher_.DescribeTo(os);
- *os << "), context (";
- context_matcher_.DescribeTo(os);
+ *os << "), index (";
+ index_matcher_.DescribeTo(os);
+ *os << "), value (";
+ value_matcher_.DescribeTo(os);
*os << "), effect (";
effect_matcher_.DescribeTo(os);
*os << ") and control (";
@@ -1187,10 +1222,14 @@ class IsToNumberMatcher final : public NodeMatcher {
bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(OpParameter<StoreRepresentation>(node), "rep",
+ rep_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
base_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetContextInput(node),
- "context", context_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+ "index", index_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2),
+ "value", value_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
effect_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetControlInput(node),
@@ -1198,39 +1237,33 @@ class IsToNumberMatcher final : public NodeMatcher {
}
private:
+ const Matcher<StoreRepresentation> rep_matcher_;
const Matcher<Node*> base_matcher_;
- const Matcher<Node*> context_matcher_;
+ const Matcher<Node*> index_matcher_;
+ const Matcher<Node*> value_matcher_;
const Matcher<Node*> effect_matcher_;
const Matcher<Node*> control_matcher_;
};
-class IsStoreMatcher final : public NodeMatcher {
+class IsToNumberMatcher final : public NodeMatcher {
public:
- IsStoreMatcher(const Matcher<StoreRepresentation>& rep_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kStore),
- rep_matcher_(rep_matcher),
+ IsToNumberMatcher(const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& context_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kJSToNumber),
base_matcher_(base_matcher),
- index_matcher_(index_matcher),
- value_matcher_(value_matcher),
+ context_matcher_(context_matcher),
effect_matcher_(effect_matcher),
control_matcher_(control_matcher) {}
void DescribeTo(std::ostream* os) const final {
NodeMatcher::DescribeTo(os);
- *os << " whose rep (";
- rep_matcher_.DescribeTo(os);
- *os << "), base (";
+ *os << " whose base (";
base_matcher_.DescribeTo(os);
- *os << "), index (";
- index_matcher_.DescribeTo(os);
- *os << "), value (";
- value_matcher_.DescribeTo(os);
+ *os << "), context (";
+ context_matcher_.DescribeTo(os);
*os << "), effect (";
effect_matcher_.DescribeTo(os);
*os << ") and control (";
@@ -1240,14 +1273,10 @@ class IsStoreMatcher final : public NodeMatcher {
bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
return (NodeMatcher::MatchAndExplain(node, listener) &&
- PrintMatchAndExplain(OpParameter<StoreRepresentation>(node), "rep",
- rep_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
base_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
- "index", index_matcher_, listener) &&
- PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2),
- "value", value_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetContextInput(node),
+ "context", context_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
effect_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetControlInput(node),
@@ -1255,15 +1284,44 @@ class IsStoreMatcher final : public NodeMatcher {
}
private:
- const Matcher<StoreRepresentation> rep_matcher_;
const Matcher<Node*> base_matcher_;
- const Matcher<Node*> index_matcher_;
- const Matcher<Node*> value_matcher_;
+ const Matcher<Node*> context_matcher_;
const Matcher<Node*> effect_matcher_;
const Matcher<Node*> control_matcher_;
};
+class IsLoadContextMatcher final : public NodeMatcher {
+ public:
+ IsLoadContextMatcher(const Matcher<ContextAccess>& access_matcher,
+ const Matcher<Node*>& context_matcher)
+ : NodeMatcher(IrOpcode::kJSLoadContext),
+ access_matcher_(access_matcher),
+ context_matcher_(context_matcher) {}
+
+ void DescribeTo(std::ostream* os) const final {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose access (";
+ access_matcher_.DescribeTo(os);
+ *os << ") and context (";
+ context_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(OpParameter<ContextAccess>(node), "access",
+ access_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetContextInput(node),
+ "context", context_matcher_, listener));
+ }
+
+ private:
+ const Matcher<ContextAccess> access_matcher_;
+ const Matcher<Node*> context_matcher_;
+};
+
+
class IsBinopMatcher final : public NodeMatcher {
public:
IsBinopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& lhs_matcher,
@@ -1320,8 +1378,28 @@ class IsUnopMatcher final : public NodeMatcher {
} // namespace
-Matcher<Node*> IsEnd(const Matcher<Node*>& control_matcher) {
- return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control_matcher));
+Matcher<Node*> IsDead() {
+ return MakeMatcher(new NodeMatcher(IrOpcode::kDead));
+}
+
+
+Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher) {
+ return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control0_matcher));
+}
+
+
+Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher,
+ const Matcher<Node*>& control1_matcher) {
+ return MakeMatcher(new IsControl2Matcher(IrOpcode::kEnd, control0_matcher,
+ control1_matcher));
+}
+
+
+Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher,
+ const Matcher<Node*>& control1_matcher,
+ const Matcher<Node*>& control2_matcher) {
+ return MakeMatcher(new IsControl3Matcher(IrOpcode::kEnd, control0_matcher,
+ control1_matcher, control2_matcher));
}
@@ -1600,6 +1678,14 @@ Matcher<Node*> IsTailCall(
}
+Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher,
+ const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher) {
+ return MakeMatcher(
+ new IsReferenceEqualMatcher(type_matcher, lhs_matcher, rhs_matcher));
+}
+
+
Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
@@ -1686,15 +1772,6 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
}
-Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& context_matcher,
- const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher) {
- return MakeMatcher(new IsToNumberMatcher(base_matcher, context_matcher,
- effect_matcher, control_matcher));
-}
-
-
Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher,
@@ -1707,6 +1784,21 @@ Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
}
+Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher,
+ const Matcher<Node*>& context_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(new IsToNumberMatcher(base_matcher, context_matcher,
+ effect_matcher, control_matcher));
+}
+
+
+Matcher<Node*> IsLoadContext(const Matcher<ContextAccess>& access_matcher,
+ const Matcher<Node*>& context_matcher) {
+ return MakeMatcher(new IsLoadContextMatcher(access_matcher, context_matcher));
+}
+
+
#define IS_BINOP_MATCHER(Name) \
Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher, \
const Matcher<Node*>& rhs_matcher) { \
@@ -1717,6 +1809,9 @@ IS_BINOP_MATCHER(NumberEqual)
IS_BINOP_MATCHER(NumberLessThan)
IS_BINOP_MATCHER(NumberSubtract)
IS_BINOP_MATCHER(NumberMultiply)
+IS_BINOP_MATCHER(NumberShiftLeft)
+IS_BINOP_MATCHER(NumberShiftRight)
+IS_BINOP_MATCHER(NumberShiftRightLogical)
IS_BINOP_MATCHER(Word32And)
IS_BINOP_MATCHER(Word32Sar)
IS_BINOP_MATCHER(Word32Shl)
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.h b/deps/v8/test/unittests/compiler/node-test-utils.h
index 9c4646b2f0..a64d9f009a 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.h
+++ b/deps/v8/test/unittests/compiler/node-test-utils.h
@@ -17,12 +17,17 @@ class ExternalReference;
class HeapObject;
template <class T>
class Unique;
+template <class>
+class TypeImpl;
+struct ZoneTypeConfig;
+typedef TypeImpl<ZoneTypeConfig> Type;
namespace compiler {
// Forward declarations.
class BufferAccess;
class CallDescriptor;
+class ContextAccess;
struct ElementAccess;
struct FieldAccess;
class Node;
@@ -31,7 +36,13 @@ class Node;
using ::testing::Matcher;
-Matcher<Node*> IsEnd(const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsDead();
+Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher);
+Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher,
+ const Matcher<Node*>& control1_matcher);
+Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher,
+ const Matcher<Node*>& control1_matcher,
+ const Matcher<Node*>& control2_matcher);
Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsMerge(const Matcher<Node*>& control0_matcher,
@@ -125,6 +136,9 @@ Matcher<Node*> IsTailCall(
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsBooleanNot(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher,
+ const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberEqual(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberLessThan(const Matcher<Node*>& lhs_matcher,
@@ -133,6 +147,12 @@ Matcher<Node*> IsNumberSubtract(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsNumberMultiply(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberShiftLeft(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberShiftRight(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberShiftRightLogical(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
@@ -255,6 +275,8 @@ Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher,
const Matcher<Node*>& context_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsLoadContext(const Matcher<ContextAccess>& access_matcher,
+ const Matcher<Node*>& context_matcher);
Matcher<Node*> IsNumberToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher);
diff --git a/deps/v8/test/unittests/compiler/node-unittest.cc b/deps/v8/test/unittests/compiler/node-unittest.cc
index 6b61bd5c1c..5341f69716 100644
--- a/deps/v8/test/unittests/compiler/node-unittest.cc
+++ b/deps/v8/test/unittests/compiler/node-unittest.cc
@@ -32,7 +32,7 @@ const Operator kOp2(kOpcode2, Operator::kNoProperties, "Op2", 2, 0, 0, 1, 0, 0);
TEST_F(NodeTest, New) {
Node* const node = Node::New(zone(), 1, &kOp0, 0, nullptr, false);
- EXPECT_EQ(1, node->id());
+ EXPECT_EQ(1U, node->id());
EXPECT_EQ(0, node->UseCount());
EXPECT_TRUE(node->uses().empty());
EXPECT_EQ(0, node->InputCount());
@@ -166,6 +166,96 @@ TEST_F(NodeTest, AppendInput) {
EXPECT_THAT(node->inputs(), ElementsAre(n0, n1, n0, n0, n1));
}
+
+TEST_F(NodeTest, TrimThenAppend) {
+ Node* n0 = Node::New(zone(), 0, &kOp0, 0, nullptr, false);
+ Node* n1 = Node::New(zone(), 1, &kOp0, 0, nullptr, false);
+ Node* n2 = Node::New(zone(), 2, &kOp0, 0, nullptr, false);
+ Node* n3 = Node::New(zone(), 3, &kOp0, 0, nullptr, false);
+ Node* n4 = Node::New(zone(), 4, &kOp0, 0, nullptr, false);
+ Node* n5 = Node::New(zone(), 5, &kOp0, 0, nullptr, false);
+ Node* n6 = Node::New(zone(), 6, &kOp0, 0, nullptr, false);
+ Node* n7 = Node::New(zone(), 7, &kOp0, 0, nullptr, false);
+ Node* n8 = Node::New(zone(), 8, &kOp0, 0, nullptr, false);
+ Node* n9 = Node::New(zone(), 9, &kOp0, 0, nullptr, false);
+ Node* node = Node::New(zone(), 12345, &kOp0, 0, nullptr, true);
+
+ EXPECT_TRUE(node->inputs().empty());
+
+ node->AppendInput(zone(), n0);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n0));
+
+ node->TrimInputCount(0);
+ EXPECT_TRUE(node->inputs().empty());
+
+ node->AppendInput(zone(), n1);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1));
+
+ node->AppendInput(zone(), n2);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n2));
+
+ node->TrimInputCount(1);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1));
+
+ node->AppendInput(zone(), n3);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3));
+
+ node->AppendInput(zone(), n4);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4));
+
+ node->AppendInput(zone(), n5);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5));
+
+ node->AppendInput(zone(), n6);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n6));
+
+ node->AppendInput(zone(), n7);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n6, n7));
+
+ node->TrimInputCount(4);
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5));
+
+ node->AppendInput(zone(), n8);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n8));
+
+ node->AppendInput(zone(), n9);
+ EXPECT_FALSE(node->inputs().empty());
+ EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n8, n9));
+}
+
+
+TEST_F(NodeTest, BigNodes) {
+ static const int kMaxSize = 512;
+ Node* inputs[kMaxSize];
+
+ Node* n0 = Node::New(zone(), 0, &kOp0, 0, nullptr, false);
+ Node* n1 = Node::New(zone(), 1, &kOp1, 1, &n0, false);
+
+ for (int i = 0; i < kMaxSize; i++) {
+ inputs[i] = i & 1 ? n0 : n1;
+ }
+
+ for (int size = 13; size <= kMaxSize; size += 9) {
+ Node* node = Node::New(zone(), 12345, &kOp0, size, inputs, false);
+ EXPECT_EQ(size, node->InputCount());
+
+ for (int i = 0; i < size; i++) {
+ EXPECT_EQ(inputs[i], node->InputAt(i));
+ }
+ }
+}
+
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/scheduler-unittest.cc b/deps/v8/test/unittests/compiler/scheduler-unittest.cc
index 4de15492b2..45c636b27a 100644
--- a/deps/v8/test/unittests/compiler/scheduler-unittest.cc
+++ b/deps/v8/test/unittests/compiler/scheduler-unittest.cc
@@ -631,7 +631,7 @@ TEST_F(SchedulerRPOTest, LoopMultibackedge) {
TEST_F(SchedulerTest, BuildScheduleEmpty) {
graph()->SetStart(graph()->NewNode(common()->Start(0)));
- graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start()));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
}
@@ -643,22 +643,23 @@ TEST_F(SchedulerTest, BuildScheduleOneParameter) {
Node* ret = graph()->NewNode(common()->Return(), p1, graph()->start(),
graph()->start());
- graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+ graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
}
TEST_F(SchedulerTest, BuildScheduleIfSplit) {
- graph()->SetStart(graph()->NewNode(common()->Start(3)));
+ graph()->SetStart(graph()->NewNode(common()->Start(5)));
Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
Node* p2 = graph()->NewNode(common()->Parameter(1), graph()->start());
Node* p3 = graph()->NewNode(common()->Parameter(2), graph()->start());
Node* p4 = graph()->NewNode(common()->Parameter(3), graph()->start());
Node* p5 = graph()->NewNode(common()->Parameter(4), graph()->start());
- Node* cmp = graph()->NewNode(js()->LessThanOrEqual(LanguageMode::SLOPPY), p1,
- p2, p3, graph()->start(), graph()->start());
+ Node* cmp =
+ graph()->NewNode(js()->LessThanOrEqual(LanguageMode::SLOPPY), p1, p2, p3,
+ p4, p5, graph()->start(), graph()->start());
Node* branch = graph()->NewNode(common()->Branch(), cmp, graph()->start());
Node* true_branch = graph()->NewNode(common()->IfTrue(), branch);
Node* false_branch = graph()->NewNode(common()->IfFalse(), branch);
@@ -667,1341 +668,12 @@ TEST_F(SchedulerTest, BuildScheduleIfSplit) {
graph()->NewNode(common()->Return(), p4, graph()->start(), true_branch);
Node* ret2 =
graph()->NewNode(common()->Return(), p5, graph()->start(), false_branch);
- Node* merge = graph()->NewNode(common()->Merge(2), ret1, ret2);
- graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+ graph()->SetEnd(graph()->NewNode(common()->End(2), ret1, ret2));
ComputeAndVerifySchedule(13);
}
-TEST_F(SchedulerTest, BuildScheduleIfSplitWithEffects) {
- const Operator* op;
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c, y) {
- // if (a < b) {
- // return a + b - c * c - a + y;
- // } else {
- // return c * c - a;
- // }
- // }
- Node* nil = graph()->NewNode(common()->Dead());
- op = common()->End();
- Node* n39 = graph()->NewNode(op, nil);
- USE(n39);
- op = common()->Merge(2);
- Node* n37 = graph()->NewNode(op, nil, nil);
- USE(n37);
- op = common()->Return();
- Node* n29 = graph()->NewNode(op, nil, nil, nil);
- USE(n29);
- op = common()->Return();
- Node* n36 = graph()->NewNode(op, nil, nil, nil);
- USE(n36);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n27 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n27);
- op = common()->IfSuccess();
- Node* n28 = graph()->NewNode(op, nil);
- USE(n28);
- op = js()->Subtract(LanguageMode::SLOPPY);
- Node* n34 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n34);
- op = common()->IfSuccess();
- Node* n35 = graph()->NewNode(op, nil);
- USE(n35);
- op = js()->Subtract(LanguageMode::SLOPPY);
- Node* n25 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n25);
- op = common()->Parameter(4);
- Node* n5 = graph()->NewNode(op, nil);
- USE(n5);
- op = common()->Parameter(5);
- Node* n7 = graph()->NewNode(op, nil);
- USE(n7);
- op = common()->FrameState(JS_FRAME, BailoutId(-1),
- OutputFrameStateCombine::Ignore());
- Node* n13 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n13);
- op = common()->IfSuccess();
- Node* n26 = graph()->NewNode(op, nil);
- USE(n26);
- op = js()->Multiply(LanguageMode::SLOPPY);
- Node* n32 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n32);
- op = common()->Parameter(1);
- Node* n2 = graph()->NewNode(op, nil);
- USE(n2);
- op = common()->IfSuccess();
- Node* n33 = graph()->NewNode(op, nil);
- USE(n33);
- op = js()->Subtract(LanguageMode::SLOPPY);
- Node* n23 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n23);
- op = common()->IfSuccess();
- Node* n24 = graph()->NewNode(op, nil);
- USE(n24);
- op = common()->Start(4);
- Node* n0 = graph()->NewNode(op);
- USE(n0);
- op = common()->StateValues(0);
- Node* n11 = graph()->NewNode(op);
- USE(n11);
- op = common()->NumberConstant(0);
- Node* n12 = graph()->NewNode(op);
- USE(n12);
- op = common()->HeapConstant(unique_constant);
- Node* n6 = graph()->NewNode(op);
- USE(n6);
- op = common()->Parameter(3);
- Node* n4 = graph()->NewNode(op, nil);
- USE(n4);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n15 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n15);
- op = common()->IfFalse();
- Node* n31 = graph()->NewNode(op, nil);
- USE(n31);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n19 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n19);
- op = js()->Multiply(LanguageMode::SLOPPY);
- Node* n21 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n21);
- op = common()->IfSuccess();
- Node* n22 = graph()->NewNode(op, nil);
- USE(n22);
- op = common()->Parameter(2);
- Node* n3 = graph()->NewNode(op, nil);
- USE(n3);
- op = js()->StackCheck();
- Node* n9 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n9);
- op = common()->IfSuccess();
- Node* n10 = graph()->NewNode(op, nil);
- USE(n10);
- op = common()->Branch();
- Node* n17 = graph()->NewNode(op, nil, nil);
- USE(n17);
- op = common()->IfTrue();
- Node* n18 = graph()->NewNode(op, nil);
- USE(n18);
- op = common()->IfSuccess();
- Node* n20 = graph()->NewNode(op, nil);
- USE(n20);
- op = common()->IfSuccess();
- Node* n16 = graph()->NewNode(op, nil);
- USE(n16);
- n39->ReplaceInput(0, n37);
- n37->ReplaceInput(0, n29);
- n37->ReplaceInput(1, n36);
- n29->ReplaceInput(0, n27);
- n29->ReplaceInput(1, n27);
- n29->ReplaceInput(2, n28);
- n36->ReplaceInput(0, n34);
- n36->ReplaceInput(1, n34);
- n36->ReplaceInput(2, n35);
- n27->ReplaceInput(0, n25);
- n27->ReplaceInput(1, n5);
- n27->ReplaceInput(2, n7);
- n27->ReplaceInput(3, n13);
- n27->ReplaceInput(4, n13);
- n27->ReplaceInput(5, n25);
- n27->ReplaceInput(6, n26);
- n28->ReplaceInput(0, n27);
- n34->ReplaceInput(0, n32);
- n34->ReplaceInput(1, n2);
- n34->ReplaceInput(2, n7);
- n34->ReplaceInput(3, n13);
- n34->ReplaceInput(4, n13);
- n34->ReplaceInput(5, n32);
- n34->ReplaceInput(6, n33);
- n35->ReplaceInput(0, n34);
- n25->ReplaceInput(0, n23);
- n25->ReplaceInput(1, n2);
- n25->ReplaceInput(2, n7);
- n25->ReplaceInput(3, n13);
- n25->ReplaceInput(4, n13);
- n25->ReplaceInput(5, n23);
- n25->ReplaceInput(6, n24);
- n5->ReplaceInput(0, n0);
- n7->ReplaceInput(0, n0);
- n13->ReplaceInput(0, n11);
- n13->ReplaceInput(1, n11);
- n13->ReplaceInput(2, n11);
- n13->ReplaceInput(3, n12);
- n13->ReplaceInput(4, n6);
- n26->ReplaceInput(0, n25);
- n32->ReplaceInput(0, n4);
- n32->ReplaceInput(1, n4);
- n32->ReplaceInput(2, n7);
- n32->ReplaceInput(3, n13);
- n32->ReplaceInput(4, n13);
- n32->ReplaceInput(5, n15);
- n32->ReplaceInput(6, n31);
- n2->ReplaceInput(0, n0);
- n33->ReplaceInput(0, n32);
- n23->ReplaceInput(0, n19);
- n23->ReplaceInput(1, n21);
- n23->ReplaceInput(2, n7);
- n23->ReplaceInput(3, n13);
- n23->ReplaceInput(4, n13);
- n23->ReplaceInput(5, n21);
- n23->ReplaceInput(6, n22);
- n24->ReplaceInput(0, n23);
- n4->ReplaceInput(0, n0);
- n15->ReplaceInput(0, n2);
- n15->ReplaceInput(1, n3);
- n15->ReplaceInput(2, n7);
- n15->ReplaceInput(3, n13);
- n15->ReplaceInput(4, n9);
- n15->ReplaceInput(5, n10);
- n31->ReplaceInput(0, n17);
- n19->ReplaceInput(0, n2);
- n19->ReplaceInput(1, n3);
- n19->ReplaceInput(2, n7);
- n19->ReplaceInput(3, n13);
- n19->ReplaceInput(4, n13);
- n19->ReplaceInput(5, n15);
- n19->ReplaceInput(6, n18);
- n21->ReplaceInput(0, n4);
- n21->ReplaceInput(1, n4);
- n21->ReplaceInput(2, n7);
- n21->ReplaceInput(3, n13);
- n21->ReplaceInput(4, n13);
- n21->ReplaceInput(5, n19);
- n21->ReplaceInput(6, n20);
- n22->ReplaceInput(0, n21);
- n3->ReplaceInput(0, n0);
- n9->ReplaceInput(0, n7);
- n9->ReplaceInput(1, n13);
- n9->ReplaceInput(2, n0);
- n9->ReplaceInput(3, n0);
- n10->ReplaceInput(0, n9);
- n17->ReplaceInput(0, n15);
- n17->ReplaceInput(1, n16);
- n18->ReplaceInput(0, n17);
- n20->ReplaceInput(0, n19);
- n16->ReplaceInput(0, n15);
-
- graph()->SetStart(n0);
- graph()->SetEnd(n39);
-
- ComputeAndVerifySchedule(34);
-}
-
-
-TEST_F(SchedulerTest, BuildScheduleSimpleLoop) {
- const Operator* op;
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b) {
- // while (a < b) {
- // a++;
- // }
- // return a;
- // }
- Node* nil = graph()->NewNode(common()->Dead());
- op = common()->End();
- Node* n34 = graph()->NewNode(op, nil);
- USE(n34);
- op = common()->Return();
- Node* n32 = graph()->NewNode(op, nil, nil, nil);
- USE(n32);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n13 = graph()->NewNode(op, nil, nil, nil);
- USE(n13);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n16 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n16);
- op = common()->IfFalse();
- Node* n22 = graph()->NewNode(op, nil);
- USE(n22);
- op = common()->Parameter(1);
- Node* n2 = graph()->NewNode(op, nil);
- USE(n2);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n29);
- op = common()->Loop(2);
- Node* n12 = graph()->NewNode(op, nil, nil);
- USE(n12);
- op = common()->Parameter(2);
- Node* n3 = graph()->NewNode(op, nil);
- USE(n3);
- op = common()->Parameter(3);
- Node* n5 = graph()->NewNode(op, nil);
- USE(n5);
- op = common()->FrameState(JS_FRAME, BailoutId(-1),
- OutputFrameStateCombine::Ignore());
- Node* n11 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n11);
- op = common()->EffectPhi(2);
- Node* n14 = graph()->NewNode(op, nil, nil, nil);
- USE(n14);
- op = common()->Branch();
- Node* n19 = graph()->NewNode(op, nil, nil);
- USE(n19);
- op = common()->Start(2);
- Node* n0 = graph()->NewNode(op);
- USE(n0);
- op = js()->ToNumber();
- Node* n26 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n26);
- op = common()->NumberConstant(1);
- Node* n28 = graph()->NewNode(op);
- USE(n28);
- op = common()->IfSuccess();
- Node* n27 = graph()->NewNode(op, nil);
- USE(n27);
- op = common()->IfSuccess();
- Node* n8 = graph()->NewNode(op, nil);
- USE(n8);
- op = common()->IfSuccess();
- Node* n30 = graph()->NewNode(op, nil);
- USE(n30);
- op = common()->StateValues(0);
- Node* n9 = graph()->NewNode(op);
- USE(n9);
- op = common()->NumberConstant(0);
- Node* n10 = graph()->NewNode(op);
- USE(n10);
- op = common()->HeapConstant(unique_constant);
- Node* n4 = graph()->NewNode(op);
- USE(n4);
- op = js()->StackCheck();
- Node* n7 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n7);
- op = js()->ToBoolean();
- Node* n18 = graph()->NewNode(op, nil, nil);
- USE(n18);
- op = common()->IfSuccess();
- Node* n17 = graph()->NewNode(op, nil);
- USE(n17);
- op = js()->StackCheck();
- Node* n24 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n24);
- op = common()->IfSuccess();
- Node* n25 = graph()->NewNode(op, nil);
- USE(n25);
- op = common()->IfTrue();
- Node* n20 = graph()->NewNode(op, nil);
- USE(n20);
- n34->ReplaceInput(0, n32);
- n32->ReplaceInput(0, n13);
- n32->ReplaceInput(1, n16);
- n32->ReplaceInput(2, n22);
- n13->ReplaceInput(0, n2);
- n13->ReplaceInput(1, n29);
- n13->ReplaceInput(2, n12);
- n16->ReplaceInput(0, n13);
- n16->ReplaceInput(1, n3);
- n16->ReplaceInput(2, n5);
- n16->ReplaceInput(3, n11);
- n16->ReplaceInput(4, n14);
- n16->ReplaceInput(5, n12);
- n22->ReplaceInput(0, n19);
- n2->ReplaceInput(0, n0);
- n29->ReplaceInput(0, n26);
- n29->ReplaceInput(1, n28);
- n29->ReplaceInput(2, n5);
- n29->ReplaceInput(3, n11);
- n29->ReplaceInput(4, n11);
- n29->ReplaceInput(5, n26);
- n29->ReplaceInput(6, n27);
- n12->ReplaceInput(0, n8);
- n12->ReplaceInput(1, n30);
- n3->ReplaceInput(0, n0);
- n5->ReplaceInput(0, n0);
- n11->ReplaceInput(0, n9);
- n11->ReplaceInput(1, n9);
- n11->ReplaceInput(2, n9);
- n11->ReplaceInput(3, n10);
- n11->ReplaceInput(4, n4);
- n14->ReplaceInput(0, n7);
- n14->ReplaceInput(1, n29);
- n14->ReplaceInput(2, n12);
- n19->ReplaceInput(0, n18);
- n19->ReplaceInput(1, n17);
- n26->ReplaceInput(0, n13);
- n26->ReplaceInput(1, n5);
- n26->ReplaceInput(2, n11);
- n26->ReplaceInput(3, n24);
- n26->ReplaceInput(4, n25);
- n27->ReplaceInput(0, n26);
- n8->ReplaceInput(0, n7);
- n30->ReplaceInput(0, n29);
- n7->ReplaceInput(0, n5);
- n7->ReplaceInput(1, n11);
- n7->ReplaceInput(2, n0);
- n7->ReplaceInput(3, n0);
- n18->ReplaceInput(0, n16);
- n18->ReplaceInput(1, n5);
- n17->ReplaceInput(0, n16);
- n24->ReplaceInput(0, n5);
- n24->ReplaceInput(1, n11);
- n24->ReplaceInput(2, n16);
- n24->ReplaceInput(3, n20);
- n25->ReplaceInput(0, n24);
- n20->ReplaceInput(0, n19);
-
- graph()->SetStart(n0);
- graph()->SetEnd(n34);
-
- ComputeAndVerifySchedule(30);
-}
-
-
-TEST_F(SchedulerTest, BuildScheduleComplexLoops) {
- const Operator* op;
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // while (a < b) {
- // a++;
- // while (c < b) {
- // c++;
- // }
- // }
- // while (a < b) {
- // a += 2;
- // }
- // return a;
- // }
- Node* nil = graph()->NewNode(common()->Dead());
- op = common()->End();
- Node* n71 = graph()->NewNode(op, nil);
- USE(n71);
- op = common()->Return();
- Node* n69 = graph()->NewNode(op, nil, nil, nil);
- USE(n69);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n53 = graph()->NewNode(op, nil, nil, nil);
- USE(n53);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n55 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n55);
- op = common()->IfFalse();
- Node* n61 = graph()->NewNode(op, nil);
- USE(n61);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n14 = graph()->NewNode(op, nil, nil, nil);
- USE(n14);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n66 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n66);
- op = common()->Loop(2);
- Node* n52 = graph()->NewNode(op, nil, nil);
- USE(n52);
- op = common()->Parameter(2);
- Node* n3 = graph()->NewNode(op, nil);
- USE(n3);
- op = common()->Parameter(4);
- Node* n6 = graph()->NewNode(op, nil);
- USE(n6);
- op = common()->FrameState(JS_FRAME, BailoutId(-1),
- OutputFrameStateCombine::Ignore());
- Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- op = common()->EffectPhi(2);
- Node* n54 = graph()->NewNode(op, nil, nil, nil);
- USE(n54);
- op = common()->Branch();
- Node* n58 = graph()->NewNode(op, nil, nil);
- USE(n58);
- op = common()->Parameter(1);
- Node* n2 = graph()->NewNode(op, nil);
- USE(n2);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n31 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n31);
- op = common()->Loop(2);
- Node* n13 = graph()->NewNode(op, nil, nil);
- USE(n13);
- op = common()->NumberConstant(2);
- Node* n65 = graph()->NewNode(op);
- USE(n65);
- op = js()->StackCheck();
- Node* n63 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n63);
- op = common()->IfSuccess();
- Node* n64 = graph()->NewNode(op, nil);
- USE(n64);
- op = common()->IfFalse();
- Node* n24 = graph()->NewNode(op, nil);
- USE(n24);
- op = common()->IfSuccess();
- Node* n67 = graph()->NewNode(op, nil);
- USE(n67);
- op = common()->Start(3);
- Node* n0 = graph()->NewNode(op);
- USE(n0);
- op = common()->StateValues(0);
- Node* n10 = graph()->NewNode(op);
- USE(n10);
- op = common()->NumberConstant(0);
- Node* n11 = graph()->NewNode(op);
- USE(n11);
- op = common()->HeapConstant(unique_constant);
- Node* n5 = graph()->NewNode(op);
- USE(n5);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n18 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n18);
- op = js()->ToBoolean();
- Node* n57 = graph()->NewNode(op, nil, nil);
- USE(n57);
- op = common()->IfSuccess();
- Node* n56 = graph()->NewNode(op, nil);
- USE(n56);
- op = js()->ToNumber();
- Node* n28 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n28);
- op = common()->NumberConstant(1);
- Node* n30 = graph()->NewNode(op);
- USE(n30);
- op = common()->IfSuccess();
- Node* n29 = graph()->NewNode(op, nil);
- USE(n29);
- op = common()->IfSuccess();
- Node* n9 = graph()->NewNode(op, nil);
- USE(n9);
- op = common()->IfFalse();
- Node* n42 = graph()->NewNode(op, nil);
- USE(n42);
- op = common()->IfTrue();
- Node* n59 = graph()->NewNode(op, nil);
- USE(n59);
- op = common()->Branch();
- Node* n21 = graph()->NewNode(op, nil, nil);
- USE(n21);
- op = common()->EffectPhi(2);
- Node* n16 = graph()->NewNode(op, nil, nil, nil);
- USE(n16);
- op = js()->StackCheck();
- Node* n26 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n26);
- op = common()->IfSuccess();
- Node* n27 = graph()->NewNode(op, nil);
- USE(n27);
- op = js()->StackCheck();
- Node* n8 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n8);
- op = common()->Branch();
- Node* n39 = graph()->NewNode(op, nil, nil);
- USE(n39);
- op = js()->ToBoolean();
- Node* n20 = graph()->NewNode(op, nil, nil);
- USE(n20);
- op = common()->IfSuccess();
- Node* n19 = graph()->NewNode(op, nil);
- USE(n19);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n36 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n36);
- op = common()->IfTrue();
- Node* n22 = graph()->NewNode(op, nil);
- USE(n22);
- op = js()->ToBoolean();
- Node* n38 = graph()->NewNode(op, nil, nil);
- USE(n38);
- op = common()->IfSuccess();
- Node* n37 = graph()->NewNode(op, nil);
- USE(n37);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n34 = graph()->NewNode(op, nil, nil, nil);
- USE(n34);
- op = common()->EffectPhi(2);
- Node* n35 = graph()->NewNode(op, nil, nil, nil);
- USE(n35);
- op = common()->Loop(2);
- Node* n33 = graph()->NewNode(op, nil, nil);
- USE(n33);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n15 = graph()->NewNode(op, nil, nil, nil);
- USE(n15);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n48 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n48);
- op = common()->IfSuccess();
- Node* n32 = graph()->NewNode(op, nil);
- USE(n32);
- op = common()->IfSuccess();
- Node* n49 = graph()->NewNode(op, nil);
- USE(n49);
- op = common()->Parameter(3);
- Node* n4 = graph()->NewNode(op, nil);
- USE(n4);
- op = js()->ToNumber();
- Node* n46 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n46);
- op = common()->IfSuccess();
- Node* n47 = graph()->NewNode(op, nil);
- USE(n47);
- op = js()->StackCheck();
- Node* n44 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n44);
- op = common()->IfSuccess();
- Node* n45 = graph()->NewNode(op, nil);
- USE(n45);
- op = common()->IfTrue();
- Node* n40 = graph()->NewNode(op, nil);
- USE(n40);
- n71->ReplaceInput(0, n69);
- n69->ReplaceInput(0, n53);
- n69->ReplaceInput(1, n55);
- n69->ReplaceInput(2, n61);
- n53->ReplaceInput(0, n14);
- n53->ReplaceInput(1, n66);
- n53->ReplaceInput(2, n52);
- n55->ReplaceInput(0, n53);
- n55->ReplaceInput(1, n3);
- n55->ReplaceInput(2, n6);
- n55->ReplaceInput(3, n12);
- n55->ReplaceInput(4, n54);
- n55->ReplaceInput(5, n52);
- n61->ReplaceInput(0, n58);
- n14->ReplaceInput(0, n2);
- n14->ReplaceInput(1, n31);
- n14->ReplaceInput(2, n13);
- n66->ReplaceInput(0, n53);
- n66->ReplaceInput(1, n65);
- n66->ReplaceInput(2, n6);
- n66->ReplaceInput(3, n12);
- n66->ReplaceInput(4, n12);
- n66->ReplaceInput(5, n63);
- n66->ReplaceInput(6, n64);
- n52->ReplaceInput(0, n24);
- n52->ReplaceInput(1, n67);
- n3->ReplaceInput(0, n0);
- n6->ReplaceInput(0, n0);
- n12->ReplaceInput(0, n10);
- n12->ReplaceInput(1, n10);
- n12->ReplaceInput(2, n10);
- n12->ReplaceInput(3, n11);
- n12->ReplaceInput(4, n5);
- n54->ReplaceInput(0, n18);
- n54->ReplaceInput(1, n66);
- n54->ReplaceInput(2, n52);
- n58->ReplaceInput(0, n57);
- n58->ReplaceInput(1, n56);
- n2->ReplaceInput(0, n0);
- n31->ReplaceInput(0, n28);
- n31->ReplaceInput(1, n30);
- n31->ReplaceInput(2, n6);
- n31->ReplaceInput(3, n12);
- n31->ReplaceInput(4, n12);
- n31->ReplaceInput(5, n28);
- n31->ReplaceInput(6, n29);
- n13->ReplaceInput(0, n9);
- n13->ReplaceInput(1, n42);
- n63->ReplaceInput(0, n6);
- n63->ReplaceInput(1, n12);
- n63->ReplaceInput(2, n55);
- n63->ReplaceInput(3, n59);
- n64->ReplaceInput(0, n63);
- n24->ReplaceInput(0, n21);
- n67->ReplaceInput(0, n66);
- n18->ReplaceInput(0, n14);
- n18->ReplaceInput(1, n3);
- n18->ReplaceInput(2, n6);
- n18->ReplaceInput(3, n12);
- n18->ReplaceInput(4, n16);
- n18->ReplaceInput(5, n13);
- n57->ReplaceInput(0, n55);
- n57->ReplaceInput(1, n6);
- n56->ReplaceInput(0, n55);
- n28->ReplaceInput(0, n14);
- n28->ReplaceInput(1, n6);
- n28->ReplaceInput(2, n12);
- n28->ReplaceInput(3, n26);
- n28->ReplaceInput(4, n27);
- n29->ReplaceInput(0, n28);
- n9->ReplaceInput(0, n8);
- n42->ReplaceInput(0, n39);
- n59->ReplaceInput(0, n58);
- n21->ReplaceInput(0, n20);
- n21->ReplaceInput(1, n19);
- n16->ReplaceInput(0, n8);
- n16->ReplaceInput(1, n36);
- n16->ReplaceInput(2, n13);
- n26->ReplaceInput(0, n6);
- n26->ReplaceInput(1, n12);
- n26->ReplaceInput(2, n18);
- n26->ReplaceInput(3, n22);
- n27->ReplaceInput(0, n26);
- n8->ReplaceInput(0, n6);
- n8->ReplaceInput(1, n12);
- n8->ReplaceInput(2, n0);
- n8->ReplaceInput(3, n0);
- n39->ReplaceInput(0, n38);
- n39->ReplaceInput(1, n37);
- n20->ReplaceInput(0, n18);
- n20->ReplaceInput(1, n6);
- n19->ReplaceInput(0, n18);
- n36->ReplaceInput(0, n34);
- n36->ReplaceInput(1, n3);
- n36->ReplaceInput(2, n6);
- n36->ReplaceInput(3, n12);
- n36->ReplaceInput(4, n35);
- n36->ReplaceInput(5, n33);
- n22->ReplaceInput(0, n21);
- n38->ReplaceInput(0, n36);
- n38->ReplaceInput(1, n6);
- n37->ReplaceInput(0, n36);
- n34->ReplaceInput(0, n15);
- n34->ReplaceInput(1, n48);
- n34->ReplaceInput(2, n33);
- n35->ReplaceInput(0, n31);
- n35->ReplaceInput(1, n48);
- n35->ReplaceInput(2, n33);
- n33->ReplaceInput(0, n32);
- n33->ReplaceInput(1, n49);
- n15->ReplaceInput(0, n4);
- n15->ReplaceInput(1, n34);
- n15->ReplaceInput(2, n13);
- n48->ReplaceInput(0, n46);
- n48->ReplaceInput(1, n30);
- n48->ReplaceInput(2, n6);
- n48->ReplaceInput(3, n12);
- n48->ReplaceInput(4, n12);
- n48->ReplaceInput(5, n46);
- n48->ReplaceInput(6, n47);
- n32->ReplaceInput(0, n31);
- n49->ReplaceInput(0, n48);
- n4->ReplaceInput(0, n0);
- n46->ReplaceInput(0, n34);
- n46->ReplaceInput(1, n6);
- n46->ReplaceInput(2, n12);
- n46->ReplaceInput(3, n44);
- n46->ReplaceInput(4, n45);
- n47->ReplaceInput(0, n46);
- n44->ReplaceInput(0, n6);
- n44->ReplaceInput(1, n12);
- n44->ReplaceInput(2, n36);
- n44->ReplaceInput(3, n40);
- n45->ReplaceInput(0, n44);
- n40->ReplaceInput(0, n39);
-
- graph()->SetStart(n0);
- graph()->SetEnd(n71);
-
- ComputeAndVerifySchedule(65);
-}
-
-
-TEST_F(SchedulerTest, BuildScheduleBreakAndContinue) {
- const Operator* op;
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // var d = 0;
- // while (a < b) {
- // a++;
- // while (c < b) {
- // c++;
- // if (d == 0) break;
- // a++;
- // }
- // if (a == 1) continue;
- // d++;
- // }
- // return a + d;
- // }
- Node* nil = graph()->NewNode(common()->Dead());
- op = common()->End();
- Node* n86 = graph()->NewNode(op, nil);
- USE(n86);
- op = common()->Return();
- Node* n84 = graph()->NewNode(op, nil, nil, nil);
- USE(n84);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n82 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n82);
- op = common()->IfSuccess();
- Node* n83 = graph()->NewNode(op, nil);
- USE(n83);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n15 = graph()->NewNode(op, nil, nil, nil);
- USE(n15);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n17 = graph()->NewNode(op, nil, nil, nil);
- USE(n17);
- op = common()->Parameter(4);
- Node* n6 = graph()->NewNode(op, nil);
- USE(n6);
- op = common()->FrameState(JS_FRAME, BailoutId(-1),
- OutputFrameStateCombine::Ignore());
- Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n19 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n19);
- op = common()->IfFalse();
- Node* n25 = graph()->NewNode(op, nil);
- USE(n25);
- op = common()->Parameter(1);
- Node* n2 = graph()->NewNode(op, nil);
- USE(n2);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n35 = graph()->NewNode(op, nil, nil, nil);
- USE(n35);
- op = common()->Loop(2);
- Node* n14 = graph()->NewNode(op, nil, nil);
- USE(n14);
- op = common()->NumberConstant(0);
- Node* n11 = graph()->NewNode(op);
- USE(n11);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n81 = graph()->NewNode(op, nil, nil, nil);
- USE(n81);
- op = common()->Start(3);
- Node* n0 = graph()->NewNode(op);
- USE(n0);
- op = common()->StateValues(0);
- Node* n10 = graph()->NewNode(op);
- USE(n10);
- op = common()->HeapConstant(unique_constant);
- Node* n5 = graph()->NewNode(op);
- USE(n5);
- op = common()->Parameter(2);
- Node* n3 = graph()->NewNode(op, nil);
- USE(n3);
- op = common()->EffectPhi(2);
- Node* n18 = graph()->NewNode(op, nil, nil, nil);
- USE(n18);
- op = common()->Branch();
- Node* n22 = graph()->NewNode(op, nil, nil);
- USE(n22);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n32 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n32);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n64 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n64);
- op = common()->Loop(2);
- Node* n34 = graph()->NewNode(op, nil, nil);
- USE(n34);
- op = common()->IfSuccess();
- Node* n9 = graph()->NewNode(op, nil);
- USE(n9);
- op = common()->Merge(2);
- Node* n72 = graph()->NewNode(op, nil, nil);
- USE(n72);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n78 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n78);
- op = js()->StackCheck();
- Node* n8 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n8);
- op = common()->EffectPhi(2);
- Node* n80 = graph()->NewNode(op, nil, nil, nil);
- USE(n80);
- op = js()->ToBoolean();
- Node* n21 = graph()->NewNode(op, nil, nil);
- USE(n21);
- op = common()->IfSuccess();
- Node* n20 = graph()->NewNode(op, nil);
- USE(n20);
- op = js()->ToNumber();
- Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n29);
- op = common()->NumberConstant(1);
- Node* n31 = graph()->NewNode(op);
- USE(n31);
- op = common()->IfSuccess();
- Node* n30 = graph()->NewNode(op, nil);
- USE(n30);
- op = js()->ToNumber();
- Node* n62 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n62);
- op = common()->IfSuccess();
- Node* n63 = graph()->NewNode(op, nil);
- USE(n63);
- op = common()->IfSuccess();
- Node* n33 = graph()->NewNode(op, nil);
- USE(n33);
- op = common()->IfSuccess();
- Node* n65 = graph()->NewNode(op, nil);
- USE(n65);
- op = common()->IfTrue();
- Node* n71 = graph()->NewNode(op, nil);
- USE(n71);
- op = common()->IfSuccess();
- Node* n79 = graph()->NewNode(op, nil);
- USE(n79);
- op = js()->ToNumber();
- Node* n76 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n76);
- op = common()->IfSuccess();
- Node* n77 = graph()->NewNode(op, nil);
- USE(n77);
- op = js()->Equal();
- Node* n67 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n67);
- op = js()->StackCheck();
- Node* n27 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n27);
- op = common()->IfSuccess();
- Node* n28 = graph()->NewNode(op, nil);
- USE(n28);
- op = js()->Equal();
- Node* n52 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n52);
- op = common()->IfFalse();
- Node* n60 = graph()->NewNode(op, nil);
- USE(n60);
- op = common()->Branch();
- Node* n70 = graph()->NewNode(op, nil, nil);
- USE(n70);
- op = common()->IfFalse();
- Node* n74 = graph()->NewNode(op, nil);
- USE(n74);
- op = common()->EffectPhi(2);
- Node* n57 = graph()->NewNode(op, nil, nil, nil);
- USE(n57);
- op = common()->Merge(2);
- Node* n45 = graph()->NewNode(op, nil, nil);
- USE(n45);
- op = common()->IfTrue();
- Node* n23 = graph()->NewNode(op, nil);
- USE(n23);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n50 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n50);
- op = common()->IfSuccess();
- Node* n51 = graph()->NewNode(op, nil);
- USE(n51);
- op = common()->Branch();
- Node* n55 = graph()->NewNode(op, nil, nil);
- USE(n55);
- op = js()->ToBoolean();
- Node* n69 = graph()->NewNode(op, nil, nil);
- USE(n69);
- op = common()->IfSuccess();
- Node* n68 = graph()->NewNode(op, nil);
- USE(n68);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n38 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n38);
- op = common()->IfFalse();
- Node* n44 = graph()->NewNode(op, nil);
- USE(n44);
- op = common()->IfTrue();
- Node* n56 = graph()->NewNode(op, nil);
- USE(n56);
- op = js()->ToNumber();
- Node* n48 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n48);
- op = common()->IfSuccess();
- Node* n49 = graph()->NewNode(op, nil);
- USE(n49);
- op = js()->ToBoolean();
- Node* n54 = graph()->NewNode(op, nil, nil);
- USE(n54);
- op = common()->IfSuccess();
- Node* n53 = graph()->NewNode(op, nil);
- USE(n53);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n36 = graph()->NewNode(op, nil, nil, nil);
- USE(n36);
- op = common()->EffectPhi(2);
- Node* n37 = graph()->NewNode(op, nil, nil, nil);
- USE(n37);
- op = common()->Branch();
- Node* n41 = graph()->NewNode(op, nil, nil);
- USE(n41);
- op = js()->StackCheck();
- Node* n46 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n46);
- op = common()->IfSuccess();
- Node* n47 = graph()->NewNode(op, nil);
- USE(n47);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n16 = graph()->NewNode(op, nil, nil, nil);
- USE(n16);
- op = js()->ToBoolean();
- Node* n40 = graph()->NewNode(op, nil, nil);
- USE(n40);
- op = common()->IfSuccess();
- Node* n39 = graph()->NewNode(op, nil);
- USE(n39);
- op = common()->IfTrue();
- Node* n42 = graph()->NewNode(op, nil);
- USE(n42);
- op = common()->Parameter(3);
- Node* n4 = graph()->NewNode(op, nil);
- USE(n4);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n58 = graph()->NewNode(op, nil, nil, nil);
- USE(n58);
- n86->ReplaceInput(0, n84);
- n84->ReplaceInput(0, n82);
- n84->ReplaceInput(1, n82);
- n84->ReplaceInput(2, n83);
- n82->ReplaceInput(0, n15);
- n82->ReplaceInput(1, n17);
- n82->ReplaceInput(2, n6);
- n82->ReplaceInput(3, n12);
- n82->ReplaceInput(4, n12);
- n82->ReplaceInput(5, n19);
- n82->ReplaceInput(6, n25);
- n83->ReplaceInput(0, n82);
- n15->ReplaceInput(0, n2);
- n15->ReplaceInput(1, n35);
- n15->ReplaceInput(2, n14);
- n17->ReplaceInput(0, n11);
- n17->ReplaceInput(1, n81);
- n17->ReplaceInput(2, n14);
- n6->ReplaceInput(0, n0);
- n12->ReplaceInput(0, n10);
- n12->ReplaceInput(1, n10);
- n12->ReplaceInput(2, n10);
- n12->ReplaceInput(3, n11);
- n12->ReplaceInput(4, n5);
- n19->ReplaceInput(0, n15);
- n19->ReplaceInput(1, n3);
- n19->ReplaceInput(2, n6);
- n19->ReplaceInput(3, n12);
- n19->ReplaceInput(4, n18);
- n19->ReplaceInput(5, n14);
- n25->ReplaceInput(0, n22);
- n2->ReplaceInput(0, n0);
- n35->ReplaceInput(0, n32);
- n35->ReplaceInput(1, n64);
- n35->ReplaceInput(2, n34);
- n14->ReplaceInput(0, n9);
- n14->ReplaceInput(1, n72);
- n81->ReplaceInput(0, n17);
- n81->ReplaceInput(1, n78);
- n81->ReplaceInput(2, n72);
- n3->ReplaceInput(0, n0);
- n18->ReplaceInput(0, n8);
- n18->ReplaceInput(1, n80);
- n18->ReplaceInput(2, n14);
- n22->ReplaceInput(0, n21);
- n22->ReplaceInput(1, n20);
- n32->ReplaceInput(0, n29);
- n32->ReplaceInput(1, n31);
- n32->ReplaceInput(2, n6);
- n32->ReplaceInput(3, n12);
- n32->ReplaceInput(4, n12);
- n32->ReplaceInput(5, n29);
- n32->ReplaceInput(6, n30);
- n64->ReplaceInput(0, n62);
- n64->ReplaceInput(1, n31);
- n64->ReplaceInput(2, n6);
- n64->ReplaceInput(3, n12);
- n64->ReplaceInput(4, n12);
- n64->ReplaceInput(5, n62);
- n64->ReplaceInput(6, n63);
- n34->ReplaceInput(0, n33);
- n34->ReplaceInput(1, n65);
- n9->ReplaceInput(0, n8);
- n72->ReplaceInput(0, n71);
- n72->ReplaceInput(1, n79);
- n78->ReplaceInput(0, n76);
- n78->ReplaceInput(1, n31);
- n78->ReplaceInput(2, n6);
- n78->ReplaceInput(3, n12);
- n78->ReplaceInput(4, n12);
- n78->ReplaceInput(5, n76);
- n78->ReplaceInput(6, n77);
- n8->ReplaceInput(0, n6);
- n8->ReplaceInput(1, n12);
- n8->ReplaceInput(2, n0);
- n8->ReplaceInput(3, n0);
- n80->ReplaceInput(0, n67);
- n80->ReplaceInput(1, n78);
- n80->ReplaceInput(2, n72);
- n21->ReplaceInput(0, n19);
- n21->ReplaceInput(1, n6);
- n20->ReplaceInput(0, n19);
- n29->ReplaceInput(0, n15);
- n29->ReplaceInput(1, n6);
- n29->ReplaceInput(2, n12);
- n29->ReplaceInput(3, n27);
- n29->ReplaceInput(4, n28);
- n30->ReplaceInput(0, n29);
- n62->ReplaceInput(0, n35);
- n62->ReplaceInput(1, n6);
- n62->ReplaceInput(2, n12);
- n62->ReplaceInput(3, n52);
- n62->ReplaceInput(4, n60);
- n63->ReplaceInput(0, n62);
- n33->ReplaceInput(0, n32);
- n65->ReplaceInput(0, n64);
- n71->ReplaceInput(0, n70);
- n79->ReplaceInput(0, n78);
- n76->ReplaceInput(0, n17);
- n76->ReplaceInput(1, n6);
- n76->ReplaceInput(2, n12);
- n76->ReplaceInput(3, n67);
- n76->ReplaceInput(4, n74);
- n77->ReplaceInput(0, n76);
- n67->ReplaceInput(0, n35);
- n67->ReplaceInput(1, n31);
- n67->ReplaceInput(2, n6);
- n67->ReplaceInput(3, n12);
- n67->ReplaceInput(4, n57);
- n67->ReplaceInput(5, n45);
- n27->ReplaceInput(0, n6);
- n27->ReplaceInput(1, n12);
- n27->ReplaceInput(2, n19);
- n27->ReplaceInput(3, n23);
- n28->ReplaceInput(0, n27);
- n52->ReplaceInput(0, n17);
- n52->ReplaceInput(1, n11);
- n52->ReplaceInput(2, n6);
- n52->ReplaceInput(3, n12);
- n52->ReplaceInput(4, n50);
- n52->ReplaceInput(5, n51);
- n60->ReplaceInput(0, n55);
- n70->ReplaceInput(0, n69);
- n70->ReplaceInput(1, n68);
- n74->ReplaceInput(0, n70);
- n57->ReplaceInput(0, n38);
- n57->ReplaceInput(1, n52);
- n57->ReplaceInput(2, n45);
- n45->ReplaceInput(0, n44);
- n45->ReplaceInput(1, n56);
- n23->ReplaceInput(0, n22);
- n50->ReplaceInput(0, n48);
- n50->ReplaceInput(1, n31);
- n50->ReplaceInput(2, n6);
- n50->ReplaceInput(3, n12);
- n50->ReplaceInput(4, n12);
- n50->ReplaceInput(5, n48);
- n50->ReplaceInput(6, n49);
- n51->ReplaceInput(0, n50);
- n55->ReplaceInput(0, n54);
- n55->ReplaceInput(1, n53);
- n69->ReplaceInput(0, n67);
- n69->ReplaceInput(1, n6);
- n68->ReplaceInput(0, n67);
- n38->ReplaceInput(0, n36);
- n38->ReplaceInput(1, n3);
- n38->ReplaceInput(2, n6);
- n38->ReplaceInput(3, n12);
- n38->ReplaceInput(4, n37);
- n38->ReplaceInput(5, n34);
- n44->ReplaceInput(0, n41);
- n56->ReplaceInput(0, n55);
- n48->ReplaceInput(0, n36);
- n48->ReplaceInput(1, n6);
- n48->ReplaceInput(2, n12);
- n48->ReplaceInput(3, n46);
- n48->ReplaceInput(4, n47);
- n49->ReplaceInput(0, n48);
- n54->ReplaceInput(0, n52);
- n54->ReplaceInput(1, n6);
- n53->ReplaceInput(0, n52);
- n36->ReplaceInput(0, n16);
- n36->ReplaceInput(1, n50);
- n36->ReplaceInput(2, n34);
- n37->ReplaceInput(0, n32);
- n37->ReplaceInput(1, n64);
- n37->ReplaceInput(2, n34);
- n41->ReplaceInput(0, n40);
- n41->ReplaceInput(1, n39);
- n46->ReplaceInput(0, n6);
- n46->ReplaceInput(1, n12);
- n46->ReplaceInput(2, n38);
- n46->ReplaceInput(3, n42);
- n47->ReplaceInput(0, n46);
- n16->ReplaceInput(0, n4);
- n16->ReplaceInput(1, n58);
- n16->ReplaceInput(2, n14);
- n40->ReplaceInput(0, n38);
- n40->ReplaceInput(1, n6);
- n39->ReplaceInput(0, n38);
- n42->ReplaceInput(0, n41);
- n4->ReplaceInput(0, n0);
- n58->ReplaceInput(0, n36);
- n58->ReplaceInput(1, n50);
- n58->ReplaceInput(2, n45);
-
- graph()->SetStart(n0);
- graph()->SetEnd(n86);
-
- ComputeAndVerifySchedule(83);
-}
-
-
-TEST_F(SchedulerTest, BuildScheduleSimpleLoopWithCodeMotion) {
- const Operator* op;
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateImmovable(factory()->undefined_value());
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // while (a < b) {
- // a += b + c;
- // }
- // return a;
- // }
- Node* nil = graph()->NewNode(common()->Dead());
- op = common()->End();
- Node* n34 = graph()->NewNode(op, nil);
- USE(n34);
- op = common()->Return();
- Node* n32 = graph()->NewNode(op, nil, nil, nil);
- USE(n32);
- op = common()->Phi(kMachAnyTagged, 2);
- Node* n14 = graph()->NewNode(op, nil, nil, nil);
- USE(n14);
- op = js()->LessThan(LanguageMode::SLOPPY);
- Node* n17 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil);
- USE(n17);
- op = common()->IfFalse();
- Node* n23 = graph()->NewNode(op, nil);
- USE(n23);
- op = common()->Parameter(1);
- Node* n2 = graph()->NewNode(op, nil);
- USE(n2);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n29);
- op = common()->Loop(2);
- Node* n13 = graph()->NewNode(op, nil, nil);
- USE(n13);
- op = common()->Parameter(2);
- Node* n3 = graph()->NewNode(op, nil);
- USE(n3);
- op = common()->Parameter(4);
- Node* n6 = graph()->NewNode(op, nil);
- USE(n6);
- op = common()->FrameState(JS_FRAME, BailoutId(-1),
- OutputFrameStateCombine::Ignore());
- Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- op = common()->EffectPhi(2);
- Node* n15 = graph()->NewNode(op, nil, nil, nil);
- USE(n15);
- op = common()->Branch();
- Node* n20 = graph()->NewNode(op, nil, nil);
- USE(n20);
- op = common()->Start(3);
- Node* n0 = graph()->NewNode(op);
- USE(n0);
- op = js()->Add(LanguageMode::SLOPPY);
- Node* n27 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil);
- USE(n27);
- op = common()->IfSuccess();
- Node* n28 = graph()->NewNode(op, nil);
- USE(n28);
- op = common()->IfSuccess();
- Node* n9 = graph()->NewNode(op, nil);
- USE(n9);
- op = common()->IfSuccess();
- Node* n30 = graph()->NewNode(op, nil);
- USE(n30);
- op = common()->StateValues(0);
- Node* n10 = graph()->NewNode(op);
- USE(n10);
- op = common()->NumberConstant(0);
- Node* n11 = graph()->NewNode(op);
- USE(n11);
- op = common()->HeapConstant(unique_constant);
- Node* n5 = graph()->NewNode(op);
- USE(n5);
- op = js()->StackCheck();
- Node* n8 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n8);
- op = js()->ToBoolean();
- Node* n19 = graph()->NewNode(op, nil, nil);
- USE(n19);
- op = common()->IfSuccess();
- Node* n18 = graph()->NewNode(op, nil);
- USE(n18);
- op = common()->Parameter(3);
- Node* n4 = graph()->NewNode(op, nil);
- USE(n4);
- op = js()->StackCheck();
- Node* n25 = graph()->NewNode(op, nil, nil, nil, nil);
- USE(n25);
- op = common()->IfSuccess();
- Node* n26 = graph()->NewNode(op, nil);
- USE(n26);
- op = common()->IfTrue();
- Node* n21 = graph()->NewNode(op, nil);
- USE(n21);
- n34->ReplaceInput(0, n32);
- n32->ReplaceInput(0, n14);
- n32->ReplaceInput(1, n17);
- n32->ReplaceInput(2, n23);
- n14->ReplaceInput(0, n2);
- n14->ReplaceInput(1, n29);
- n14->ReplaceInput(2, n13);
- n17->ReplaceInput(0, n14);
- n17->ReplaceInput(1, n3);
- n17->ReplaceInput(2, n6);
- n17->ReplaceInput(3, n12);
- n17->ReplaceInput(4, n15);
- n17->ReplaceInput(5, n13);
- n23->ReplaceInput(0, n20);
- n2->ReplaceInput(0, n0);
- n29->ReplaceInput(0, n14);
- n29->ReplaceInput(1, n27);
- n29->ReplaceInput(2, n6);
- n29->ReplaceInput(3, n12);
- n29->ReplaceInput(4, n12);
- n29->ReplaceInput(5, n27);
- n29->ReplaceInput(6, n28);
- n13->ReplaceInput(0, n9);
- n13->ReplaceInput(1, n30);
- n3->ReplaceInput(0, n0);
- n6->ReplaceInput(0, n0);
- n12->ReplaceInput(0, n10);
- n12->ReplaceInput(1, n10);
- n12->ReplaceInput(2, n10);
- n12->ReplaceInput(3, n11);
- n12->ReplaceInput(4, n5);
- n15->ReplaceInput(0, n8);
- n15->ReplaceInput(1, n29);
- n15->ReplaceInput(2, n13);
- n20->ReplaceInput(0, n19);
- n20->ReplaceInput(1, n18);
- n27->ReplaceInput(0, n3);
- n27->ReplaceInput(1, n4);
- n27->ReplaceInput(2, n6);
- n27->ReplaceInput(3, n12);
- n27->ReplaceInput(4, n12);
- n27->ReplaceInput(5, n25);
- n27->ReplaceInput(6, n26);
- n28->ReplaceInput(0, n27);
- n9->ReplaceInput(0, n8);
- n30->ReplaceInput(0, n29);
- n8->ReplaceInput(0, n6);
- n8->ReplaceInput(1, n12);
- n8->ReplaceInput(2, n0);
- n8->ReplaceInput(3, n0);
- n19->ReplaceInput(0, n17);
- n19->ReplaceInput(1, n6);
- n18->ReplaceInput(0, n17);
- n4->ReplaceInput(0, n0);
- n25->ReplaceInput(0, n6);
- n25->ReplaceInput(1, n12);
- n25->ReplaceInput(2, n17);
- n25->ReplaceInput(3, n21);
- n26->ReplaceInput(0, n25);
- n21->ReplaceInput(0, n20);
-
- graph()->SetStart(n0);
- graph()->SetEnd(n34);
-
- ComputeAndVerifySchedule(30);
-}
-
-
namespace {
Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, Node* cond) {
@@ -2025,7 +697,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond1) {
Node* p0 = graph()->NewNode(common()->Parameter(0), start);
Node* d1 = CreateDiamond(graph(), common(), p0);
Node* ret = graph()->NewNode(common()->Return(), d1, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2043,7 +715,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond2) {
Node* d2 = CreateDiamond(graph(), common(), p1);
Node* add = graph()->NewNode(&kIntAdd, d1, d2);
Node* ret = graph()->NewNode(common()->Return(), add, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2062,7 +734,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond3) {
Node* add = graph()->NewNode(&kIntAdd, d1, d2);
Node* d3 = CreateDiamond(graph(), common(), add);
Node* ret = graph()->NewNode(common()->Return(), d3, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2099,7 +771,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamonds) {
Node* ephi1 = graph()->NewNode(common()->EffectPhi(2), start, map, m);
Node* ret = graph()->NewNode(common()->Return(), phi, ephi1, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2143,7 +815,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithChain) {
Node* add = graph()->NewNode(&kIntAdd, phiA2, phiB2);
Node* ret = graph()->NewNode(common()->Return(), add, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2177,7 +849,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithLoop) {
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), fv, ind, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2210,7 +882,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond1) {
ind->ReplaceInput(1, phi1); // close induction variable.
Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
- Node* end = graph()->NewNode(common()->End(), ret, f);
+ Node* end = graph()->NewNode(common()->End(2), ret, f);
graph()->SetEnd(end);
@@ -2244,7 +916,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond2) {
ind->ReplaceInput(1, add); // close induction variable.
Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
- Node* end = graph()->NewNode(common()->End(), ret, f);
+ Node* end = graph()->NewNode(common()->End(2), ret, f);
graph()->SetEnd(end);
@@ -2290,7 +962,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond3) {
ind->ReplaceInput(1, add); // close induction variable.
Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
- Node* end = graph()->NewNode(common()->End(), ret, f);
+ Node* end = graph()->NewNode(common()->End(2), ret, f);
graph()->SetEnd(end);
@@ -2324,7 +996,7 @@ TARGET_TEST_F(SchedulerTest, PhisPushedDownToDifferentBranches) {
graph()->NewNode(common()->Phi(kMachAnyTagged, 2), phi, phi2, m2);
Node* ret = graph()->NewNode(common()->Return(), phi3, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2345,7 +1017,7 @@ TARGET_TEST_F(SchedulerTest, BranchHintTrue) {
Node* m = graph()->NewNode(common()->Merge(2), t, f);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), tv, fv, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2369,7 +1041,7 @@ TARGET_TEST_F(SchedulerTest, BranchHintFalse) {
Node* m = graph()->NewNode(common()->Merge(2), t, f);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), tv, fv, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
- Node* end = graph()->NewNode(common()->End(), ret, start);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2387,15 +1059,17 @@ TARGET_TEST_F(SchedulerTest, CallException) {
Node* p0 = graph()->NewNode(common()->Parameter(0), start);
Node* c1 = graph()->NewNode(&kMockCall, start);
Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1);
- Node* ex1 = graph()->NewNode(common()->IfException(), c1);
+ Node* ex1 = graph()->NewNode(
+ common()->IfException(IfExceptionHint::kLocallyUncaught), c1, c1);
Node* c2 = graph()->NewNode(&kMockCall, ok1);
Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2);
- Node* ex2 = graph()->NewNode(common()->IfException(), c2);
+ Node* ex2 = graph()->NewNode(
+ common()->IfException(IfExceptionHint::kLocallyUncaught), c2, c2);
Node* hdl = graph()->NewNode(common()->Merge(2), ex1, ex2);
Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
- Node* end = graph()->NewNode(common()->End(), ret);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2414,7 +1088,7 @@ TARGET_TEST_F(SchedulerTest, TailCall) {
Node* p0 = graph()->NewNode(common()->Parameter(0), start);
Node* call = graph()->NewNode(&kMockTailCall, p0, start, start);
- Node* end = graph()->NewNode(common()->End(), call);
+ Node* end = graph()->NewNode(common()->End(1), call);
graph()->SetEnd(end);
@@ -2437,7 +1111,7 @@ TARGET_TEST_F(SchedulerTest, Switch) {
Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d);
Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 3), v0, v1, vd, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
- Node* end = graph()->NewNode(common()->End(), ret);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2460,7 +1134,7 @@ TARGET_TEST_F(SchedulerTest, FloatingSwitch) {
Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d);
Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 3), v0, v1, vd, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
- Node* end = graph()->NewNode(common()->End(), ret);
+ Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
@@ -2480,7 +1154,7 @@ TARGET_TEST_F(SchedulerTest, Terminate) {
Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop);
effect->ReplaceInput(1, terminate);
- Node* end = graph()->NewNode(common()->End(), terminate);
+ Node* end = graph()->NewNode(common()->End(1), terminate);
graph()->SetEnd(end);
diff --git a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
index a5dad5a415..07728913b1 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
@@ -54,7 +54,6 @@ const PureOperator kPureOperators[] = {
PURE(StringEqual, Operator::kCommutative, 2),
PURE(StringLessThan, Operator::kNoProperties, 2),
PURE(StringLessThanOrEqual, Operator::kNoProperties, 2),
- PURE(StringAdd, Operator::kNoProperties, 2),
PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
diff --git a/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc b/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc
index 5ac1f8e796..449299bb1d 100644
--- a/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc
+++ b/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc
@@ -33,7 +33,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject0) {
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kNoFlags);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
@@ -53,15 +53,16 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) {
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
graph()->start(), graph()->start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
- Node* if_exception = graph()->NewNode(common()->IfException(), call);
+ Node* if_exception = graph()->NewNode(
+ common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
- Node* end = graph()->NewNode(common()->End(), if_exception);
+ Node* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end);
Reduction r = Reduce(ret);
ASSERT_FALSE(r.Changed());
@@ -76,7 +77,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject2) {
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
@@ -98,7 +99,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction0) {
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kNoFlags);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
@@ -118,15 +119,16 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) {
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
graph()->start(), graph()->start());
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
- Node* if_exception = graph()->NewNode(common()->IfException(), call);
+ Node* if_exception = graph()->NewNode(
+ common()->IfException(IfExceptionHint::kLocallyUncaught), call, call);
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
- Node* end = graph()->NewNode(common()->End(), if_exception);
+ Node* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end);
Reduction r = Reduce(ret);
ASSERT_FALSE(r.Changed());
@@ -141,7 +143,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction2) {
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
diff --git a/deps/v8/test/unittests/counters-unittest.cc b/deps/v8/test/unittests/counters-unittest.cc
index dd60a0d9c1..822a5c552e 100644
--- a/deps/v8/test/unittests/counters-unittest.cc
+++ b/deps/v8/test/unittests/counters-unittest.cc
@@ -49,7 +49,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample1) {
FLAG_histogram_interval = 10;
AddSample(10, 1000);
AddSample(20, 1000);
- EXPECT_EQ(1, samples()->size());
+ EXPECT_EQ(1U, samples()->size());
EXPECT_EQ(1000, (*samples())[0]);
}
@@ -58,7 +58,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample2) {
FLAG_histogram_interval = 10;
AddSample(10, 500);
AddSample(20, 1000);
- EXPECT_EQ(1, samples()->size());
+ EXPECT_EQ(1U, samples()->size());
EXPECT_EQ(750, (*samples())[0]);
}
@@ -69,7 +69,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample3) {
AddSample(15, 500);
AddSample(15, 1000);
AddSample(20, 1000);
- EXPECT_EQ(1, samples()->size());
+ EXPECT_EQ(1U, samples()->size());
EXPECT_EQ(750, (*samples())[0]);
}
@@ -79,7 +79,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample4) {
AddSample(10, 500);
AddSample(15, 750);
AddSample(20, 1000);
- EXPECT_EQ(1, samples()->size());
+ EXPECT_EQ(1U, samples()->size());
EXPECT_EQ(750, (*samples())[0]);
}
@@ -88,7 +88,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples1) {
FLAG_histogram_interval = 10;
AddSample(10, 1000);
AddSample(30, 1000);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ(1000, (*samples())[0]);
EXPECT_EQ(1000, (*samples())[1]);
}
@@ -99,7 +99,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples2) {
AddSample(10, 1000);
AddSample(20, 1000);
AddSample(30, 1000);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ(1000, (*samples())[0]);
EXPECT_EQ(1000, (*samples())[1]);
}
@@ -111,7 +111,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples3) {
AddSample(20, 1000);
AddSample(20, 500);
AddSample(30, 500);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ(1000, (*samples())[0]);
EXPECT_EQ(500, (*samples())[1]);
}
@@ -121,7 +121,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples4) {
FLAG_histogram_interval = 10;
AddSample(10, 1000);
AddSample(30, 0);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ(750, (*samples())[0]);
EXPECT_EQ(250, (*samples())[1]);
}
@@ -131,7 +131,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples5) {
FLAG_histogram_interval = 10;
AddSample(10, 0);
AddSample(30, 1000);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ(250, (*samples())[0]);
EXPECT_EQ(750, (*samples())[1]);
}
@@ -142,7 +142,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples6) {
AddSample(10, 0);
AddSample(15, 1000);
AddSample(30, 1000);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ((500 + 1000) / 2, (*samples())[0]);
EXPECT_EQ(1000, (*samples())[1]);
}
@@ -154,7 +154,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples7) {
AddSample(15, 1000);
AddSample(25, 0);
AddSample(30, 1000);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ((500 + 750) / 2, (*samples())[0]);
EXPECT_EQ((250 + 500) / 2, (*samples())[1]);
}
@@ -166,7 +166,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples8) {
AddSample(15, 0);
AddSample(25, 1000);
AddSample(30, 0);
- EXPECT_EQ(2, samples()->size());
+ EXPECT_EQ(2U, samples()->size());
EXPECT_EQ((500 + 250) / 2, (*samples())[0]);
EXPECT_EQ((750 + 500) / 2, (*samples())[1]);
}
@@ -177,7 +177,7 @@ TEST_F(AggregatedMemoryHistogramTest, ManySamples1) {
const int kMaxSamples = 1000;
AddSample(0, 0);
AddSample(10 * kMaxSamples, 10 * kMaxSamples);
- EXPECT_EQ(kMaxSamples, samples()->size());
+ EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size());
for (int i = 0; i < kMaxSamples; i++) {
EXPECT_EQ(i * 10 + 5, (*samples())[i]);
}
@@ -189,7 +189,7 @@ TEST_F(AggregatedMemoryHistogramTest, ManySamples2) {
const int kMaxSamples = 1000;
AddSample(0, 0);
AddSample(10 * (2 * kMaxSamples), 10 * (2 * kMaxSamples));
- EXPECT_EQ(kMaxSamples, samples()->size());
+ EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size());
for (int i = 0; i < kMaxSamples; i++) {
EXPECT_EQ(i * 10 + 5, (*samples())[i]);
}
diff --git a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc
index 54d3bd52bb..c75fde492e 100644
--- a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc
+++ b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc
@@ -25,7 +25,6 @@ class GCIdleTimeHandlerTest : public ::testing::Test {
result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate;
result.size_of_objects = kSizeOfObjects;
result.incremental_marking_stopped = false;
- result.can_start_incremental_marking = true;
result.sweeping_in_progress = false;
result.sweeping_completed = false;
result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed;
@@ -38,56 +37,6 @@ class GCIdleTimeHandlerTest : public ::testing::Test {
return result;
}
- void TransitionToReduceMemoryMode(
- const GCIdleTimeHandler::HeapState& heap_state) {
- handler()->NotifyScavenge();
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle;
- bool incremental = !heap_state.incremental_marking_stopped ||
- heap_state.can_start_incremental_marking;
- for (int i = 0; i < limit; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- if (incremental) {
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- } else {
- EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type);
- }
- }
- handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode());
- }
-
- void TransitionToDoneMode(const GCIdleTimeHandler::HeapState& heap_state,
- double idle_time_ms,
- GCIdleTimeActionType expected) {
- EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode());
- int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts;
- for (int i = 0; i < limit; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(expected, action.type);
- EXPECT_TRUE(action.reduce_memory);
- handler()->NotifyMarkCompact();
- handler()->NotifyIdleMarkCompact();
- }
- handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode());
- }
-
- void TransitionToReduceLatencyMode(
- const GCIdleTimeHandler::HeapState& heap_state) {
- EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode());
- int limit = GCIdleTimeHandler::kMarkCompactsBeforeMutatorIsActive;
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- for (int i = 0; i < limit; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DONE, action.type);
- handler()->NotifyMarkCompact();
- }
- handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
- }
-
static const size_t kSizeOfObjects = 100 * MB;
static const size_t kMarkCompactSpeed = 200 * KB;
static const size_t kMarkingSpeed = 200 * KB;
@@ -219,6 +168,18 @@ TEST_F(GCIdleTimeHandlerTest, DoScavengeHighScavengeSpeed) {
}
+TEST_F(GCIdleTimeHandlerTest, DoNotScavengeSmallNewSpaceSize) {
+ GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
+ heap_state.used_new_space_size = (MB / 2) - 1;
+ heap_state.scavenge_speed_in_bytes_per_ms = kNewSpaceCapacity;
+ int idle_time_ms = 16;
+ EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge(
+ idle_time_ms, heap_state.new_space_capacity,
+ heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms,
+ heap_state.new_space_allocation_throughput_in_bytes_per_ms));
+}
+
+
TEST_F(GCIdleTimeHandlerTest, ShouldDoMarkCompact) {
size_t idle_time_ms = GCIdleTimeHandler::kMaxScheduledIdleTime;
EXPECT_TRUE(GCIdleTimeHandler::ShouldDoMarkCompact(idle_time_ms, 0, 0));
@@ -251,11 +212,8 @@ TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) {
heap_state.contexts_disposed = 1;
heap_state.incremental_marking_stopped = true;
double idle_time_ms = 0;
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
}
@@ -266,11 +224,8 @@ TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) {
GCIdleTimeHandler::kHighContextDisposalRate - 1;
heap_state.incremental_marking_stopped = true;
double idle_time_ms = 0;
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_FULL_GC, action.type);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_FULL_GC, action.type);
}
@@ -280,42 +235,34 @@ TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
heap_state.contexts_disposal_rate = 1.0;
heap_state.incremental_marking_stopped = true;
double idle_time_ms = 0;
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_FULL_GC, action.type);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_FULL_GC, action.type);
}
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.contexts_disposed = 1;
- heap_state.contexts_disposal_rate = 1.0;
- heap_state.incremental_marking_stopped = true;
+ heap_state.contexts_disposal_rate =
+ GCIdleTimeHandler::kHighContextDisposalRate;
size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
double idle_time_ms =
static_cast<double>(heap_state.size_of_objects / speed - 1);
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
}
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.contexts_disposed = 1;
- heap_state.contexts_disposal_rate = 1.0;
+ heap_state.contexts_disposal_rate =
+ GCIdleTimeHandler::kHighContextDisposalRate;
size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
double idle_time_ms =
static_cast<double>(heap_state.size_of_objects / speed - 1);
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
}
@@ -323,197 +270,106 @@ TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms;
double idle_time_ms = 10;
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_GT(speed * static_cast<size_t>(idle_time_ms),
- static_cast<size_t>(action.parameter));
- EXPECT_LT(0, action.parameter);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ EXPECT_GT(speed * static_cast<size_t>(idle_time_ms),
+ static_cast<size_t>(action.parameter));
+ EXPECT_LT(0, action.parameter);
}
TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms;
double idle_time_ms = 10;
- for (int mode = 0; mode < 1; mode++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_GT(speed * static_cast<size_t>(idle_time_ms),
- static_cast<size_t>(action.parameter));
- EXPECT_LT(0, action.parameter);
- TransitionToReduceMemoryMode(heap_state);
- }
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ EXPECT_GT(speed * static_cast<size_t>(idle_time_ms),
+ static_cast<size_t>(action.parameter));
+ EXPECT_LT(0, action.parameter);
}
TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
double idle_time_ms =
static_cast<double>(heap_state.size_of_objects / speed - 1);
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- TransitionToReduceMemoryMode(heap_state);
- action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ EXPECT_EQ(DONE, action.type);
}
TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- for (int mode = 0; mode < 1; mode++) {
- heap_state.sweeping_in_progress = true;
- heap_state.sweeping_completed = true;
- double idle_time_ms = 10.0;
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type);
- heap_state.sweeping_in_progress = false;
- heap_state.sweeping_completed = false;
- TransitionToReduceMemoryMode(heap_state);
- }
+ heap_state.sweeping_in_progress = true;
+ heap_state.sweeping_completed = true;
+ double idle_time_ms = 10.0;
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type);
}
TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- for (int mode = 0; mode < 1; mode++) {
- heap_state.sweeping_in_progress = true;
- heap_state.sweeping_completed = false;
- double idle_time_ms = 10.0;
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- heap_state.sweeping_in_progress = false;
- heap_state.sweeping_completed = false;
- TransitionToReduceMemoryMode(heap_state);
- }
+ heap_state.sweeping_in_progress = true;
+ heap_state.sweeping_completed = false;
+ double idle_time_ms = 10.0;
+ GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ EXPECT_EQ(DO_NOTHING, action.type);
}
TEST_F(GCIdleTimeHandlerTest, Scavenge) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
int idle_time_ms = 10;
- for (int mode = 0; mode < 1; mode++) {
- heap_state.used_new_space_size =
- heap_state.new_space_capacity -
- (kNewSpaceAllocationThroughput * idle_time_ms);
- GCIdleTimeAction action =
- handler()->Compute(static_cast<double>(idle_time_ms), heap_state);
- EXPECT_EQ(DO_SCAVENGE, action.type);
- heap_state.used_new_space_size = 0;
- TransitionToReduceMemoryMode(heap_state);
- }
+ heap_state.used_new_space_size =
+ heap_state.new_space_capacity -
+ (kNewSpaceAllocationThroughput * idle_time_ms);
+ GCIdleTimeAction action =
+ handler()->Compute(static_cast<double>(idle_time_ms), heap_state);
+ EXPECT_EQ(DO_SCAVENGE, action.type);
+ heap_state.used_new_space_size = 0;
}
TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
int idle_time_ms = 10;
- heap_state.can_start_incremental_marking = false;
- heap_state.incremental_marking_stopped = true;
- for (int mode = 0; mode < 1; mode++) {
- heap_state.used_new_space_size =
- heap_state.new_space_capacity -
- (kNewSpaceAllocationThroughput * idle_time_ms);
- GCIdleTimeAction action =
- handler()->Compute(static_cast<double>(idle_time_ms), heap_state);
- EXPECT_EQ(DO_SCAVENGE, action.type);
- heap_state.used_new_space_size = 0;
- action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- TransitionToReduceMemoryMode(heap_state);
- }
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, StopEventually1) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- bool stopped = false;
- for (int i = 0; i < kMaxNotifications && !stopped; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- if (action.type == DO_INCREMENTAL_MARKING || action.type == DO_FULL_GC) {
- handler()->NotifyMarkCompact();
- handler()->NotifyIdleMarkCompact();
- }
- if (action.type == DONE) stopped = true;
- }
- EXPECT_TRUE(stopped);
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, StopEventually2) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
- double idle_time_ms =
- static_cast<double>(heap_state.size_of_objects / speed + 1);
- TransitionToReduceMemoryMode(heap_state);
- TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC);
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
+ heap_state.used_new_space_size =
+ heap_state.new_space_capacity -
+ (kNewSpaceAllocationThroughput * idle_time_ms);
+ GCIdleTimeAction action =
+ handler()->Compute(static_cast<double>(idle_time_ms), heap_state);
+ EXPECT_EQ(DO_SCAVENGE, action.type);
+ heap_state.used_new_space_size = 0;
+ action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state);
EXPECT_EQ(DONE, action.type);
}
-TEST_F(GCIdleTimeHandlerTest, StopEventually3) {
+TEST_F(GCIdleTimeHandlerTest, DoNotStartIncrementalMarking) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = 10;
- TransitionToReduceMemoryMode(heap_state);
- TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING);
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DONE, action.type);
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop1) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
- double idle_time_ms =
- static_cast<double>(heap_state.size_of_objects / speed + 1);
- TransitionToReduceMemoryMode(heap_state);
- TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC);
+ double idle_time_ms = 10.0;
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DONE, action.type);
- TransitionToReduceLatencyMode(heap_state);
- heap_state.can_start_incremental_marking = true;
- action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_FALSE(action.reduce_memory);
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
}
-TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop2) {
+TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = 10;
- TransitionToReduceMemoryMode(heap_state);
- TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING);
+ double idle_time_ms = 10.0;
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DONE, action.type);
- TransitionToReduceLatencyMode(heap_state);
- heap_state.can_start_incremental_marking = true;
+ heap_state.incremental_marking_stopped = false;
action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_FALSE(action.reduce_memory);
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
}
@@ -529,7 +385,6 @@ TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) {
TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
for (int i = 0; i < kMaxNotifications; i++) {
GCIdleTimeAction action = handler()->Compute(10, heap_state);
EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type);
@@ -537,105 +392,16 @@ TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) {
}
-TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfScavenges) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle;
- for (int i = 0; i < kMaxNotifications; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type);
- if ((i + 1) % limit == 0) handler()->NotifyScavenge();
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
- }
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfMarkCompacts) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle;
- for (int i = 0; i < kMaxNotifications; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type);
- if ((i + 1) % limit == 0) handler()->NotifyMarkCompact();
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
- }
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToReduceLatency) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts;
- for (int idle_gc = 0; idle_gc < limit; idle_gc++) {
- TransitionToReduceMemoryMode(heap_state);
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_TRUE(action.reduce_memory);
- EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode());
- for (int i = 0; i < idle_gc; i++) {
- action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_TRUE(action.reduce_memory);
- // ReduceMemory mode should tolerate one mutator GC per idle GC.
- handler()->NotifyScavenge();
- // Notify idle GC.
- handler()->NotifyMarkCompact();
- handler()->NotifyIdleMarkCompact();
- }
- // Transition to ReduceLatency mode after doing |idle_gc| idle GCs.
- handler()->NotifyScavenge();
- action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- EXPECT_FALSE(action.reduce_memory);
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
- }
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToDone) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
- double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime;
- int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts;
- TransitionToReduceMemoryMode(heap_state);
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_TRUE(action.reduce_memory);
- for (int i = 0; i < limit; i++) {
- action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_TRUE(action.reduce_memory);
- EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode());
- // ReduceMemory mode should tolerate one mutator GC per idle GC.
- handler()->NotifyScavenge();
- // Notify idle GC.
- handler()->NotifyMarkCompact();
- handler()->NotifyIdleMarkCompact();
- }
- action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DONE, action.type);
-}
-
-
TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) {
// Regression test for crbug.com/489323.
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
// Simulate sweeping being in-progress but not complete.
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
heap_state.sweeping_in_progress = true;
heap_state.sweeping_completed = false;
double idle_time_ms = 10.0;
- for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) {
+ for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimes; i++) {
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DO_NOTHING, action.type);
}
@@ -651,34 +417,11 @@ TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
// Simulate incremental marking stopped and not eligible to start.
heap_state.incremental_marking_stopped = true;
- heap_state.can_start_incremental_marking = false;
double idle_time_ms = 10.0;
- for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- }
- // We should return DONE after not making progress for some time.
+ // We should return DONE if we cannot start incremental marking.
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DONE, action.type);
}
-
-TEST_F(GCIdleTimeHandlerTest, BackgroundReduceLatencyToReduceMemory) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = false;
- heap_state.can_start_incremental_marking = true;
- double idle_time_ms = GCIdleTimeHandler::kMinBackgroundIdleTime;
- handler()->NotifyScavenge();
- EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode());
- int limit =
- GCIdleTimeHandler::kBackgroundIdleNotificationsBeforeMutatorIsIdle;
- for (int i = 0; i < limit; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- }
- handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode());
-}
-
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/heap/heap-unittest.cc b/deps/v8/test/unittests/heap/heap-unittest.cc
new file mode 100644
index 0000000000..9492faf9f3
--- /dev/null
+++ b/deps/v8/test/unittests/heap/heap-unittest.cc
@@ -0,0 +1,48 @@
+// 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 <cmath>
+#include <limits>
+
+#include "src/objects.h"
+#include "src/objects-inl.h"
+
+#include "src/handles.h"
+#include "src/handles-inl.h"
+
+#include "src/heap/heap.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+
+double Round(double x) {
+ // Round to three digits.
+ return floor(x * 1000 + 0.5) / 1000;
+}
+
+
+void CheckEqualRounded(double expected, double actual) {
+ expected = Round(expected);
+ actual = Round(actual);
+ EXPECT_DOUBLE_EQ(expected, actual);
+}
+
+
+TEST(Heap, HeapGrowingFactor) {
+ CheckEqualRounded(Heap::kMaxHeapGrowingFactor,
+ Heap::HeapGrowingFactor(34, 1));
+ CheckEqualRounded(3.553, Heap::HeapGrowingFactor(45, 1));
+ CheckEqualRounded(2.830, Heap::HeapGrowingFactor(50, 1));
+ CheckEqualRounded(1.478, Heap::HeapGrowingFactor(100, 1));
+ CheckEqualRounded(1.193, Heap::HeapGrowingFactor(200, 1));
+ CheckEqualRounded(1.121, Heap::HeapGrowingFactor(300, 1));
+ CheckEqualRounded(Heap::HeapGrowingFactor(300, 1),
+ Heap::HeapGrowingFactor(600, 2));
+ CheckEqualRounded(Heap::kMinHeapGrowingFactor,
+ Heap::HeapGrowingFactor(400, 1));
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/heap/memory-reducer-unittest.cc b/deps/v8/test/unittests/heap/memory-reducer-unittest.cc
new file mode 100644
index 0000000000..3301d13b7e
--- /dev/null
+++ b/deps/v8/test/unittests/heap/memory-reducer-unittest.cc
@@ -0,0 +1,331 @@
+// 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 <limits>
+
+#include "src/flags.h"
+#include "src/heap/memory-reducer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+
+MemoryReducer::State DoneState() {
+ return MemoryReducer::State(MemoryReducer::kDone, 0, 0.0, 1.0);
+}
+
+
+MemoryReducer::State WaitState(int started_gcs, double next_gc_start_ms) {
+ return MemoryReducer::State(MemoryReducer::kWait, started_gcs,
+ next_gc_start_ms, 1.0);
+}
+
+
+MemoryReducer::State RunState(int started_gcs, double next_gc_start_ms) {
+ return MemoryReducer::State(MemoryReducer::kRun, started_gcs,
+ next_gc_start_ms, 1.0);
+}
+
+
+MemoryReducer::Event MarkCompactEvent(double time_ms,
+ bool next_gc_likely_to_collect_more) {
+ MemoryReducer::Event event;
+ event.type = MemoryReducer::kMarkCompact;
+ event.time_ms = time_ms;
+ event.next_gc_likely_to_collect_more = next_gc_likely_to_collect_more;
+ return event;
+}
+
+
+MemoryReducer::Event MarkCompactEventGarbageLeft(double time_ms) {
+ return MarkCompactEvent(time_ms, true);
+}
+
+
+MemoryReducer::Event MarkCompactEventNoGarbageLeft(double time_ms) {
+ return MarkCompactEvent(time_ms, false);
+}
+
+
+MemoryReducer::Event TimerEvent(double time_ms, bool low_allocation_rate,
+ bool can_start_incremental_gc) {
+ MemoryReducer::Event event;
+ event.type = MemoryReducer::kTimer;
+ event.time_ms = time_ms;
+ event.low_allocation_rate = low_allocation_rate;
+ event.can_start_incremental_gc = can_start_incremental_gc;
+ return event;
+}
+
+
+MemoryReducer::Event TimerEventLowAllocationRate(double time_ms) {
+ return TimerEvent(time_ms, true, true);
+}
+
+
+MemoryReducer::Event TimerEventHighAllocationRate(double time_ms) {
+ return TimerEvent(time_ms, false, true);
+}
+
+
+MemoryReducer::Event TimerEventPendingGC(double time_ms) {
+ return TimerEvent(time_ms, true, false);
+}
+
+
+MemoryReducer::Event ContextDisposedEvent(double time_ms) {
+ MemoryReducer::Event event;
+ event.type = MemoryReducer::kContextDisposed;
+ event.time_ms = time_ms;
+ return event;
+}
+
+
+MemoryReducer::Event BackgroundIdleNotificationEvent(
+ double time_ms, bool can_start_incremental_gc = true) {
+ MemoryReducer::Event event;
+ event.type = MemoryReducer::kBackgroundIdleNotification;
+ event.time_ms = time_ms;
+ event.can_start_incremental_gc = can_start_incremental_gc;
+ return event;
+}
+
+
+TEST(MemoryReducer, FromDoneToDone) {
+ MemoryReducer::State state0(DoneState()), state1(DoneState());
+
+ state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(0));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+
+ state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(0));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+
+ state1 = MemoryReducer::Step(state0, TimerEventPendingGC(0));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+
+ state1 = MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(0));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+}
+
+
+TEST(MemoryReducer, FromDoneToWait) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(DoneState()), state1(DoneState());
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms);
+ EXPECT_EQ(0, state1.started_gcs);
+ EXPECT_EQ(2, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms);
+ EXPECT_EQ(0, state1.started_gcs);
+ EXPECT_EQ(2, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, ContextDisposedEvent(0));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(0, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+}
+
+
+TEST(MemoryReducer, FromWaitToWait) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState());
+
+ state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+
+ state1 = MemoryReducer::Step(
+ state0, TimerEventLowAllocationRate(state0.next_gc_start_ms - 1));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+
+ state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+
+ state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(2000, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(2000, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs);
+
+ state1 =
+ MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(2000, false));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+
+ state0.last_gc_time_ms = 0;
+ state1 = MemoryReducer::Step(
+ state0,
+ TimerEventHighAllocationRate(MemoryReducer::kWatchdogDelayMs + 1));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(MemoryReducer::kWatchdogDelayMs + 1 + MemoryReducer::kLongDelayMs,
+ state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state0.last_gc_time_ms = 1;
+ state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state0.started_gcs = MemoryReducer::kMaxNumberOfGCs;
+ state1 = MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+}
+
+
+TEST(MemoryReducer, FromWaitToRun) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(WaitState(0, 1000.0)), state1(DoneState());
+
+ state1 = MemoryReducer::Step(
+ state0, TimerEventLowAllocationRate(state0.next_gc_start_ms + 1));
+ EXPECT_EQ(MemoryReducer::kRun, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs);
+
+ state1 = MemoryReducer::Step(
+ state0,
+ TimerEventHighAllocationRate(MemoryReducer::kWatchdogDelayMs + 2));
+ EXPECT_EQ(MemoryReducer::kRun, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+}
+
+
+TEST(MemoryReducer, FromWaitToDone) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(WaitState(2, 0.0)), state1(DoneState());
+
+ state0.started_gcs = MemoryReducer::kMaxNumberOfGCs;
+
+ state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(2000));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+}
+
+
+TEST(MemoryReducer, FromRunToRun) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(RunState(1, 0.0)), state1(DoneState());
+
+ state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(2000));
+ EXPECT_EQ(MemoryReducer::kRun, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000));
+ EXPECT_EQ(MemoryReducer::kRun, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000));
+ EXPECT_EQ(MemoryReducer::kRun, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+
+ state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
+ EXPECT_EQ(MemoryReducer::kRun, state1.action);
+ EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
+}
+
+
+TEST(MemoryReducer, FromRunToDone) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState());
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs);
+ EXPECT_EQ(2000, state1.last_gc_time_ms);
+
+ state0.started_gcs = MemoryReducer::kMaxNumberOfGCs;
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000));
+ EXPECT_EQ(MemoryReducer::kDone, state1.action);
+ EXPECT_EQ(0, state1.next_gc_start_ms);
+ EXPECT_EQ(2000, state1.last_gc_time_ms);
+}
+
+
+TEST(MemoryReducer, FromRunToWait) {
+ if (!FLAG_incremental_marking) return;
+
+ MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState());
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(2000, state1.last_gc_time_ms);
+
+ state0.started_gcs = 1;
+
+ state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000));
+ EXPECT_EQ(MemoryReducer::kWait, state1.action);
+ EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms);
+ EXPECT_EQ(state0.started_gcs, state1.started_gcs);
+ EXPECT_EQ(2000, state1.last_gc_time_ms);
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/libplatform/default-platform-unittest.cc b/deps/v8/test/unittests/libplatform/default-platform-unittest.cc
index d2c160e558..814b27bc51 100644
--- a/deps/v8/test/unittests/libplatform/default-platform-unittest.cc
+++ b/deps/v8/test/unittests/libplatform/default-platform-unittest.cc
@@ -19,6 +19,17 @@ struct MockTask : public Task {
MOCK_METHOD0(Die, void());
};
+
+class DefaultPlatformWithMockTime : public DefaultPlatform {
+ public:
+ DefaultPlatformWithMockTime() : time_(0) {}
+ double MonotonicallyIncreasingTime() override { return time_; }
+ void IncreaseTime(double seconds) { time_ += seconds; }
+
+ private:
+ double time_;
+};
+
} // namespace
@@ -39,5 +50,82 @@ TEST(DefaultPlatformTest, PumpMessageLoop) {
EXPECT_FALSE(platform.PumpMessageLoop(isolate));
}
+
+TEST(DefaultPlatformTest, PumpMessageLoopDelayed) {
+ InSequence s;
+
+ int dummy;
+ Isolate* isolate = reinterpret_cast<Isolate*>(&dummy);
+
+ DefaultPlatformWithMockTime platform;
+ EXPECT_FALSE(platform.PumpMessageLoop(isolate));
+
+ StrictMock<MockTask>* task1 = new StrictMock<MockTask>;
+ StrictMock<MockTask>* task2 = new StrictMock<MockTask>;
+ platform.CallDelayedOnForegroundThread(isolate, task2, 100);
+ platform.CallDelayedOnForegroundThread(isolate, task1, 10);
+
+ EXPECT_FALSE(platform.PumpMessageLoop(isolate));
+
+ platform.IncreaseTime(11);
+ EXPECT_CALL(*task1, Run());
+ EXPECT_CALL(*task1, Die());
+ EXPECT_TRUE(platform.PumpMessageLoop(isolate));
+
+ EXPECT_FALSE(platform.PumpMessageLoop(isolate));
+
+ platform.IncreaseTime(90);
+ EXPECT_CALL(*task2, Run());
+ EXPECT_CALL(*task2, Die());
+ EXPECT_TRUE(platform.PumpMessageLoop(isolate));
+}
+
+
+TEST(DefaultPlatformTest, PumpMessageLoopNoStarvation) {
+ InSequence s;
+
+ int dummy;
+ Isolate* isolate = reinterpret_cast<Isolate*>(&dummy);
+
+ DefaultPlatformWithMockTime platform;
+ EXPECT_FALSE(platform.PumpMessageLoop(isolate));
+
+ StrictMock<MockTask>* task1 = new StrictMock<MockTask>;
+ StrictMock<MockTask>* task2 = new StrictMock<MockTask>;
+ StrictMock<MockTask>* task3 = new StrictMock<MockTask>;
+ platform.CallOnForegroundThread(isolate, task1);
+ platform.CallDelayedOnForegroundThread(isolate, task2, 10);
+ platform.IncreaseTime(11);
+
+ EXPECT_CALL(*task1, Run());
+ EXPECT_CALL(*task1, Die());
+ EXPECT_TRUE(platform.PumpMessageLoop(isolate));
+
+ platform.CallOnForegroundThread(isolate, task3);
+
+ EXPECT_CALL(*task2, Run());
+ EXPECT_CALL(*task2, Die());
+ EXPECT_TRUE(platform.PumpMessageLoop(isolate));
+ EXPECT_CALL(*task3, Run());
+ EXPECT_CALL(*task3, Die());
+ EXPECT_TRUE(platform.PumpMessageLoop(isolate));
+}
+
+
+TEST(DefaultPlatformTest, PendingDelayedTasksAreDestroyedOnShutdown) {
+ InSequence s;
+
+ int dummy;
+ Isolate* isolate = reinterpret_cast<Isolate*>(&dummy);
+
+ {
+ DefaultPlatformWithMockTime platform;
+ StrictMock<MockTask>* task = new StrictMock<MockTask>;
+ platform.CallDelayedOnForegroundThread(isolate, task, 10);
+ EXPECT_CALL(*task, Die());
+ }
+}
+
+
} // namespace platform
} // namespace v8
diff --git a/deps/v8/test/unittests/unittests.gyp b/deps/v8/test/unittests/unittests.gyp
index 7a298a9074..00658b3fda 100644
--- a/deps/v8/test/unittests/unittests.gyp
+++ b/deps/v8/test/unittests/unittests.gyp
@@ -44,10 +44,11 @@
'compiler/compiler-test-utils.h',
'compiler/control-equivalence-unittest.cc',
'compiler/control-flow-optimizer-unittest.cc',
- 'compiler/control-reducer-unittest.cc',
+ 'compiler/dead-code-elimination-unittest.cc',
'compiler/diamond-unittest.cc',
'compiler/graph-reducer-unittest.cc',
'compiler/graph-reducer-unittest.h',
+ 'compiler/graph-trimmer-unittest.cc',
'compiler/graph-unittest.cc',
'compiler/graph-unittest.h',
'compiler/instruction-selector-unittest.cc',
@@ -88,6 +89,8 @@
'libplatform/task-queue-unittest.cc',
'libplatform/worker-thread-unittest.cc',
'heap/gc-idle-time-handler-unittest.cc',
+ 'heap/memory-reducer-unittest.cc',
+ 'heap/heap-unittest.cc',
'run-all-unittests.cc',
'test-utils.h',
'test-utils.cc',