Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.
Original commit message:
Version 4.1.0.21 (cherry-pick)
Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412
Unlink pages from the space page list after evacuation.
BUG=430201
LOG=N
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/953813002
Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/test/unittests/compiler/change-lowering-unittest.cc b/test/unittests/compiler/change-lowering-unittest.cc
new file mode 100644
index 0000000..060b1c1
--- /dev/null
+++ b/test/unittests/compiler/change-lowering-unittest.cc
@@ -0,0 +1,463 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/code-stubs.h"
+#include "src/compiler/change-lowering.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/simplified-operator.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::_;
+using testing::AllOf;
+using testing::BitEq;
+using testing::Capture;
+using testing::CaptureEq;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class ChangeLoweringTest : public GraphTest {
+ public:
+ ChangeLoweringTest() : simplified_(zone()) {}
+ ~ChangeLoweringTest() OVERRIDE {}
+
+ virtual MachineType WordRepresentation() const = 0;
+
+ protected:
+ int HeapNumberValueOffset() const {
+ STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0);
+ return (HeapNumber::kValueOffset / kApiPointerSize) * PointerSize() -
+ kHeapObjectTag;
+ }
+ bool Is32() const { return WordRepresentation() == kRepWord32; }
+ int PointerSize() const {
+ switch (WordRepresentation()) {
+ case kRepWord32:
+ return 4;
+ case kRepWord64:
+ return 8;
+ default:
+ break;
+ }
+ UNREACHABLE();
+ return 0;
+ }
+ int SmiMaxValue() const { return -(SmiMinValue() + 1); }
+ int SmiMinValue() const {
+ return static_cast<int>(0xffffffffu << (SmiValueSize() - 1));
+ }
+ int SmiShiftAmount() const { return kSmiTagSize + SmiShiftSize(); }
+ int SmiShiftSize() const {
+ return Is32() ? SmiTagging<4>::SmiShiftSize()
+ : SmiTagging<8>::SmiShiftSize();
+ }
+ int SmiValueSize() const {
+ return Is32() ? SmiTagging<4>::SmiValueSize()
+ : SmiTagging<8>::SmiValueSize();
+ }
+
+ Reduction Reduce(Node* node) {
+ MachineOperatorBuilder machine(zone(), WordRepresentation());
+ JSOperatorBuilder javascript(zone());
+ JSGraph jsgraph(graph(), common(), &javascript, &machine);
+ CompilationInfo info(isolate(), zone());
+ Linkage linkage(zone(), &info);
+ ChangeLowering reducer(&jsgraph, &linkage);
+ return reducer.Reduce(node);
+ }
+
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
+
+ Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
+ AllocateHeapNumberStub(isolate()).GetCode())),
+ IsNumberConstant(BitEq(0.0)), effect_matcher,
+ control_matcher);
+ }
+ Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return IsLoad(kMachFloat64, value_matcher,
+ IsIntPtrConstant(HeapNumberValueOffset()), graph()->start(),
+ control_matcher);
+ }
+ Matcher<Node*> IsIntPtrConstant(int value) {
+ return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
+ }
+ Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher) {
+ return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
+ : IsWord64Equal(lhs_matcher, rhs_matcher);
+ }
+
+ private:
+ SimplifiedOperatorBuilder simplified_;
+};
+
+
+// -----------------------------------------------------------------------------
+// Common.
+
+
+class ChangeLoweringCommonTest
+ : public ChangeLoweringTest,
+ public ::testing::WithParamInterface<MachineType> {
+ public:
+ ~ChangeLoweringCommonTest() OVERRIDE {}
+
+ MachineType WordRepresentation() const FINAL { return GetParam(); }
+};
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeBitToBool(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(),
+ IsSelect(static_cast<MachineType>(kTypeBool | kRepTagged), val,
+ IsTrueConstant(), IsFalseConstant()));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant()));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* finish = reduction.replacement();
+ Capture<Node*> heap_number;
+ EXPECT_THAT(
+ finish,
+ IsFinish(
+ AllOf(CaptureEq(&heap_number),
+ IsAllocateHeapNumber(IsValueEffect(val), graph()->start())),
+ IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+ CaptureEq(&heap_number),
+ IsIntPtrConstant(HeapNumberValueOffset()), val,
+ CaptureEq(&heap_number), graph()->start())));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, StringAdd) {
+ Node* node =
+ graph()->NewNode(simplified()->StringAdd(), Parameter(0), Parameter(1));
+ Reduction reduction = Reduce(node);
+ EXPECT_FALSE(reduction.Changed());
+}
+
+
+INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest,
+ ::testing::Values(kRepWord32, kRepWord64));
+
+
+// -----------------------------------------------------------------------------
+// 32-bit
+
+
+class ChangeLowering32Test : public ChangeLoweringTest {
+ public:
+ ~ChangeLowering32Test() OVERRIDE {}
+ MachineType WordRepresentation() const FINAL { return kRepWord32; }
+};
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
+ NodeProperties::SetBounds(val, Bounds(Type::None(), Type::Signed32()));
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> add, branch, heap_number, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(kMachAnyTagged,
+ IsFinish(AllOf(CaptureEq(&heap_number),
+ IsAllocateHeapNumber(_, CaptureEq(&if_true))),
+ IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+ CaptureEq(&heap_number),
+ IsIntPtrConstant(HeapNumberValueOffset()),
+ IsChangeInt32ToFloat64(val),
+ CaptureEq(&heap_number), CaptureEq(&if_true))),
+ IsProjection(
+ 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(CaptureEq(&branch),
+ IsBranch(IsProjection(1, CaptureEq(&add)),
+ graph()->start()))))));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTaggedSmall) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
+ NodeProperties::SetBounds(val, Bounds(Type::None(), Type::SignedSmall()));
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* change = reduction.replacement();
+ Capture<Node*> add, branch, heap_number, if_true;
+ EXPECT_THAT(change, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(
+ kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)),
+ IsChangeInt32ToFloat64(
+ IsWord32Sar(val, IsInt32Constant(SmiShiftAmount()))),
+ IsMerge(
+ AllOf(CaptureEq(&if_true),
+ IsIfTrue(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
+ graph()->start())))),
+ IsIfFalse(CaptureEq(&branch)))));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(kMachInt32,
+ IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
+ IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
+ graph()->start()))))));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(kMachUint32,
+ IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
+ IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
+ graph()->start()))))));
+}
+
+
+TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, heap_number, if_false;
+ EXPECT_THAT(
+ phi,
+ IsPhi(
+ kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())),
+ IsFinish(AllOf(CaptureEq(&heap_number),
+ IsAllocateHeapNumber(_, CaptureEq(&if_false))),
+ IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+ CaptureEq(&heap_number),
+ IsInt32Constant(HeapNumberValueOffset()),
+ IsChangeUint32ToFloat64(val),
+ CaptureEq(&heap_number), CaptureEq(&if_false))),
+ IsMerge(
+ IsIfTrue(AllOf(CaptureEq(&branch),
+ IsBranch(IsUint32LessThanOrEqual(
+ val, IsInt32Constant(SmiMaxValue())),
+ graph()->start()))),
+ AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
+}
+
+
+// -----------------------------------------------------------------------------
+// 64-bit
+
+
+class ChangeLowering64Test : public ChangeLoweringTest {
+ public:
+ ~ChangeLowering64Test() OVERRIDE {}
+ MachineType WordRepresentation() const FINAL { return kRepWord64; }
+};
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ EXPECT_THAT(reduction.replacement(),
+ IsWord64Shl(IsChangeInt32ToInt64(val),
+ IsInt64Constant(SmiShiftAmount())));
+}
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(
+ kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)),
+ IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(
+ IsWord64Sar(val, IsInt64Constant(SmiShiftAmount())))),
+ IsMerge(
+ AllOf(CaptureEq(&if_true),
+ IsIfTrue(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
+ graph()->start())))),
+ IsIfFalse(CaptureEq(&branch)))));
+}
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(kMachInt32,
+ IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
+ IsTruncateInt64ToInt32(
+ IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
+ graph()->start()))))));
+}
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, if_true;
+ EXPECT_THAT(
+ phi,
+ IsPhi(kMachUint32,
+ IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
+ IsTruncateInt64ToInt32(
+ IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))),
+ IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+ IsIfFalse(AllOf(
+ CaptureEq(&branch),
+ IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
+ graph()->start()))))));
+}
+
+
+TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
+
+ Node* val = Parameter(0);
+ Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
+ Reduction reduction = Reduce(node);
+ ASSERT_TRUE(reduction.Changed());
+
+ Node* phi = reduction.replacement();
+ Capture<Node*> branch, heap_number, if_false;
+ EXPECT_THAT(
+ phi,
+ IsPhi(
+ kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val),
+ IsInt64Constant(SmiShiftAmount())),
+ IsFinish(AllOf(CaptureEq(&heap_number),
+ IsAllocateHeapNumber(_, CaptureEq(&if_false))),
+ IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+ CaptureEq(&heap_number),
+ IsInt64Constant(HeapNumberValueOffset()),
+ IsChangeUint32ToFloat64(val),
+ CaptureEq(&heap_number), CaptureEq(&if_false))),
+ IsMerge(
+ IsIfTrue(AllOf(CaptureEq(&branch),
+ IsBranch(IsUint32LessThanOrEqual(
+ val, IsInt32Constant(SmiMaxValue())),
+ graph()->start()))),
+ AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8