Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 62abeda..72cfc51 100644
--- a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -1584,7 +1584,7 @@
StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
MachineType::Float32());
m.Return(
- m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
+ m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Stream const s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
@@ -1667,7 +1667,7 @@
StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
MachineType::Float64());
m.Return(
- m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
+ m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Stream const s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
@@ -2544,8 +2544,28 @@
}
+TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) {
+ TRACED_FORRANGE(int32_t, shl, 1, 31) {
+ TRACED_FORRANGE(int32_t, sar, shl, 31) {
+ if ((shl == sar) && (sar == 16)) continue; // Sxth.
+ if ((shl == sar) && (sar == 24)) continue; // Sxtb.
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)),
+ m.Int32Constant(sar)));
+ Stream s = m.Build(ARMv7);
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmSbfx, s[0]->arch_opcode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1)));
+ EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2)));
+ }
+ }
+}
+
+
TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
- TRACED_FORRANGE(int32_t, width, 1, 32) {
+ TRACED_FORRANGE(int32_t, width, 9, 23) {
+ if (width == 16) continue; // Uxth.
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Word32And(m.Parameter(0),
m.Int32Constant(0xffffffffu >> (32 - width))));
@@ -2556,7 +2576,8 @@
EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
}
- TRACED_FORRANGE(int32_t, width, 1, 32) {
+ TRACED_FORRANGE(int32_t, width, 9, 23) {
+ if (width == 16) continue; // Uxth.
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
m.Parameter(0)));
@@ -2572,7 +2593,7 @@
TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
TRACED_FORRANGE(int32_t, lsb, 0, 31) {
- TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
+ TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Word32And(
m.Parameter(0),
@@ -2589,7 +2610,7 @@
}
}
TRACED_FORRANGE(int32_t, lsb, 0, 31) {
- TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
+ TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(
m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
@@ -2828,8 +2849,11 @@
TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
- TRACED_FORRANGE(int32_t, lsb, 0, 31) {
+ TRACED_FORRANGE(int32_t, lsb, 1, 31) {
TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
+ if (((width == 8) || (width == 16)) &&
+ ((lsb == 8) || (lsb == 16) || (lsb == 24)))
+ continue; // Uxtb/h ror.
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
m.Int32Constant(0xffffffffu >> (32 - width))));
@@ -2841,8 +2865,11 @@
EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
}
}
- TRACED_FORRANGE(int32_t, lsb, 0, 31) {
+ TRACED_FORRANGE(int32_t, lsb, 1, 31) {
TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
+ if (((width == 8) || (width == 16)) &&
+ ((lsb == 8) || (lsb == 16) || (lsb == 24)))
+ continue; // Uxtb/h ror.
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
@@ -2857,6 +2884,62 @@
}
+TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xff) {
+ TRACED_FORRANGE(int32_t, shr, 1, 3) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
+ m.Int32Constant(0xff));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+ }
+ TRACED_FORRANGE(int32_t, shr, 1, 3) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r = m.Word32And(m.Int32Constant(0xff),
+ m.Word32Shr(p0, m.Int32Constant(shr * 8)));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+ }
+}
+
+
+TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xffff) {
+ TRACED_FORRANGE(int32_t, shr, 1, 3) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
+ m.Int32Constant(0xffff));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+ }
+ TRACED_FORRANGE(int32_t, shr, 1, 3) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r = m.Word32And(m.Int32Constant(0xffff),
+ m.Word32Shr(p0, m.Int32Constant(shr * 8)));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
+ }
+}
+
+
TEST_F(InstructionSelectorTest, Word32Clz) {
StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
Node* const p0 = m.Parameter(0);
diff --git a/test/unittests/compiler/escape-analysis-unittest.cc b/test/unittests/compiler/escape-analysis-unittest.cc
index b088367..d5e12ba 100644
--- a/test/unittests/compiler/escape-analysis-unittest.cc
+++ b/test/unittests/compiler/escape-analysis-unittest.cc
@@ -9,7 +9,7 @@
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
-#include "src/types-inl.h"
+#include "src/types.h"
#include "src/zone-containers.h"
#include "test/unittests/compiler/graph-unittest.h"
@@ -85,6 +85,20 @@
allocation, value, effect, control);
}
+ Node* StoreElement(const ElementAccess& access, Node* allocation, Node* index,
+ Node* value, Node* effect = nullptr,
+ Node* control = nullptr) {
+ if (!effect) {
+ effect = effect_;
+ }
+ if (!control) {
+ control = control_;
+ }
+ return effect_ =
+ graph()->NewNode(simplified()->StoreElement(access), allocation,
+ index, value, effect, control);
+ }
+
Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr,
Node* control = nullptr) {
if (!effect) {
@@ -131,12 +145,18 @@
return control_ = graph()->NewNode(common()->Merge(2), control1, control2);
}
- FieldAccess AccessAtIndex(int offset) {
+ FieldAccess FieldAccessAtIndex(int offset) {
FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
MachineType::AnyTagged()};
return access;
}
+ ElementAccess MakeElementAccess(int header_size) {
+ ElementAccess access = {kTaggedBase, header_size, Type::Any(),
+ MachineType::AnyTagged()};
+ return access;
+ }
+
// ---------------------------------Assertion Helper--------------------------
void ExpectReplacement(Node* node, Node* rep) {
@@ -166,6 +186,7 @@
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
Node* effect() { return effect_; }
+ Node* control() { return control_; }
private:
SimplifiedOperatorBuilder simplified_;
@@ -185,9 +206,9 @@
Node* object1 = Constant(1);
BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize));
- Store(AccessAtIndex(0), allocation, object1);
+ Store(FieldAccessAtIndex(0), allocation, object1);
Node* finish = FinishRegion(allocation);
- Node* load = Load(AccessAtIndex(0), finish);
+ Node* load = Load(FieldAccessAtIndex(0), finish);
Node* result = Return(load);
EndGraph();
@@ -202,13 +223,39 @@
}
+TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) {
+ Node* object1 = Constant(1);
+ Node* object2 = Constant(2);
+ BeginRegion();
+ Node* allocation = Allocate(Constant(kPointerSize));
+ Store(FieldAccessAtIndex(0), allocation, object1);
+ Node* index =
+ graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
+ object1, object2, control());
+ StoreElement(MakeElementAccess(0), allocation, index, object1);
+ Node* finish = FinishRegion(allocation);
+ Node* load = Load(FieldAccessAtIndex(0), finish);
+ Node* result = Return(load);
+ EndGraph();
+
+ Analysis();
+
+ ExpectEscaped(allocation);
+ ExpectReplacement(load, nullptr);
+
+ Transformation();
+
+ ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0));
+}
+
+
TEST_F(EscapeAnalysisTest, StraightEscape) {
Node* object1 = Constant(1);
BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize));
- Store(AccessAtIndex(0), allocation, object1);
+ Store(FieldAccessAtIndex(0), allocation, object1);
Node* finish = FinishRegion(allocation);
- Node* load = Load(AccessAtIndex(0), finish);
+ Node* load = Load(FieldAccessAtIndex(0), finish);
Node* result = Return(allocation);
EndGraph();
graph()->end()->AppendInput(zone(), load);
@@ -229,15 +276,15 @@
BeginRegion();
Node* allocation1 = Allocate(Constant(kPointerSize));
- Store(AccessAtIndex(0), allocation1, object1);
+ Store(FieldAccessAtIndex(0), allocation1, object1);
Node* finish1 = FinishRegion(allocation1);
BeginRegion();
Node* allocation2 = Allocate(Constant(kPointerSize));
- Store(AccessAtIndex(0), allocation2, finish1);
+ Store(FieldAccessAtIndex(0), allocation2, finish1);
Node* finish2 = FinishRegion(allocation2);
- Node* load = Load(AccessAtIndex(0), finish2);
+ Node* load = Load(FieldAccessAtIndex(0), finish2);
Node* result = Return(load);
EndGraph();
Analysis();
@@ -257,16 +304,18 @@
Node* object2 = Constant(2);
BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize));
- Store(AccessAtIndex(0), allocation, object1);
+ Store(FieldAccessAtIndex(0), allocation, object1);
Node* finish = FinishRegion(allocation);
Branch();
Node* ifFalse = IfFalse();
Node* ifTrue = IfTrue();
- Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish, ifFalse);
- Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue);
+ Node* effect1 =
+ Store(FieldAccessAtIndex(0), allocation, object1, finish, ifFalse);
+ Node* effect2 =
+ Store(FieldAccessAtIndex(0), allocation, object2, finish, ifTrue);
Node* merge = Merge2(ifFalse, ifTrue);
Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
- Node* load = Load(AccessAtIndex(0), finish, phi, merge);
+ Node* load = Load(FieldAccessAtIndex(0), finish, phi, merge);
Node* result = Return(load, phi);
EndGraph();
graph()->end()->AppendInput(zone(), result);
@@ -283,14 +332,81 @@
}
+TEST_F(EscapeAnalysisTest, BranchEscapeOne) {
+ Node* object1 = Constant(1);
+ Node* object2 = Constant(2);
+ Node* index = graph()->NewNode(common()->Parameter(0), start());
+ BeginRegion();
+ Node* allocation = Allocate(Constant(kPointerSize));
+ Store(FieldAccessAtIndex(0), allocation, object1);
+ Node* finish = FinishRegion(allocation);
+ Branch();
+ Node* ifFalse = IfFalse();
+ Node* ifTrue = IfTrue();
+ Node* effect1 =
+ Store(FieldAccessAtIndex(0), allocation, object1, finish, ifFalse);
+ Node* effect2 = StoreElement(MakeElementAccess(0), allocation, index, object2,
+ finish, ifTrue);
+ Node* merge = Merge2(ifFalse, ifTrue);
+ Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge);
+ Node* load = Load(FieldAccessAtIndex(0), finish, phi, merge);
+ Node* result = Return(load, phi);
+ EndGraph();
+
+ Analysis();
+
+ ExpectEscaped(allocation);
+ ExpectReplacement(load, nullptr);
+
+ Transformation();
+
+ ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0));
+}
+
+
+TEST_F(EscapeAnalysisTest, BranchEscapeThroughStore) {
+ Node* object1 = Constant(1);
+ Node* object2 = Constant(2);
+ BeginRegion();
+ Node* allocation = Allocate(Constant(kPointerSize));
+ Store(FieldAccessAtIndex(0), allocation, object1);
+ FinishRegion(allocation);
+ BeginRegion();
+ Node* allocation2 = Allocate(Constant(kPointerSize));
+ Store(FieldAccessAtIndex(0), allocation, object2);
+ Node* finish2 = FinishRegion(allocation2);
+ Branch();
+ Node* ifFalse = IfFalse();
+ Node* ifTrue = IfTrue();
+ Node* effect1 =
+ Store(FieldAccessAtIndex(0), allocation, allocation2, finish2, ifFalse);
+ Node* merge = Merge2(ifFalse, ifTrue);
+ Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, finish2, merge);
+ Node* load = Load(FieldAccessAtIndex(0), finish2, phi, merge);
+ Node* result = Return(allocation, phi);
+ EndGraph();
+ graph()->end()->AppendInput(zone(), load);
+
+ Analysis();
+
+ ExpectEscaped(allocation);
+ ExpectEscaped(allocation2);
+ ExpectReplacement(load, nullptr);
+
+ Transformation();
+
+ ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0));
+}
+
+
TEST_F(EscapeAnalysisTest, DanglingLoadOrder) {
Node* object1 = Constant(1);
Node* object2 = Constant(2);
Node* allocation = Allocate(Constant(kPointerSize));
- Node* store1 = Store(AccessAtIndex(0), allocation, object1);
- Node* load1 = Load(AccessAtIndex(0), allocation);
- Node* store2 = Store(AccessAtIndex(0), allocation, object2);
- Node* load2 = Load(AccessAtIndex(0), allocation, store1);
+ Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1);
+ Node* load1 = Load(FieldAccessAtIndex(0), allocation);
+ Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2);
+ Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1);
Node* result = Return(load2);
EndGraph();
graph()->end()->AppendInput(zone(), store2);
@@ -312,9 +428,9 @@
Node* object1 = Constant(1);
BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize));
- Store(AccessAtIndex(0), allocation, object1);
+ Store(FieldAccessAtIndex(0), allocation, object1);
Node* finish = FinishRegion(allocation);
- Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish);
+ Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish);
Branch();
Node* ifFalse = IfFalse();
Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish);
@@ -328,7 +444,7 @@
Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect1, ifFalse);
Node* ifTrue = IfTrue();
- Node* load = Load(AccessAtIndex(0), finish, effect1, ifTrue);
+ Node* load = Load(FieldAccessAtIndex(0), finish, effect1, ifTrue);
Node* result = Return(load, effect1, ifTrue);
EndGraph();
graph()->end()->AppendInput(zone(), deopt);
@@ -351,10 +467,10 @@
Node* object1 = Constant(1);
BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize * 2));
- Store(AccessAtIndex(0), allocation, object1);
- Store(AccessAtIndex(kPointerSize), allocation, allocation);
+ Store(FieldAccessAtIndex(0), allocation, object1);
+ Store(FieldAccessAtIndex(kPointerSize), allocation, allocation);
Node* finish = FinishRegion(allocation);
- Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish);
+ Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish);
Branch();
Node* ifFalse = IfFalse();
Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish);
@@ -368,7 +484,7 @@
Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect1, ifFalse);
Node* ifTrue = IfTrue();
- Node* load = Load(AccessAtIndex(0), finish, effect1, ifTrue);
+ Node* load = Load(FieldAccessAtIndex(0), finish, effect1, ifTrue);
Node* result = Return(load, effect1, ifTrue);
EndGraph();
graph()->end()->AppendInput(zone(), deopt);
diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc
index 89c0a65..16030f8 100644
--- a/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/test/unittests/compiler/instruction-selector-unittest.cc
@@ -40,7 +40,7 @@
instruction_blocks);
SourcePositionTable source_position_table(graph());
InstructionSelector selector(test_->zone(), node_count, &linkage, &sequence,
- schedule, &source_position_table,
+ schedule, &source_position_table, nullptr,
source_position_mode, features);
selector.SelectInstructions();
if (FLAG_trace_turbo) {
@@ -148,7 +148,7 @@
int parameter_count, int local_count) {
return common()->CreateFrameStateFunctionInfo(
FrameStateType::kJavaScriptFunction, parameter_count, local_count,
- Handle<SharedFunctionInfo>(), CALL_MAINTAINS_NATIVE_CONTEXT);
+ Handle<SharedFunctionInfo>());
}
diff --git a/test/unittests/compiler/instruction-selector-unittest.h b/test/unittests/compiler/instruction-selector-unittest.h
index fc7c144..f1397fa 100644
--- a/test/unittests/compiler/instruction-selector-unittest.h
+++ b/test/unittests/compiler/instruction-selector-unittest.h
@@ -92,7 +92,7 @@
CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
MachineSignature::Builder builder(zone, 1, 0);
builder.AddReturn(return_type);
- return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+ return MakeSimpleCallDescriptor(zone, builder.Build());
}
CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
@@ -100,7 +100,7 @@
MachineSignature::Builder builder(zone, 1, 1);
builder.AddReturn(return_type);
builder.AddParam(parameter0_type);
- return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+ return MakeSimpleCallDescriptor(zone, builder.Build());
}
CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
@@ -110,7 +110,7 @@
builder.AddReturn(return_type);
builder.AddParam(parameter0_type);
builder.AddParam(parameter1_type);
- return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+ return MakeSimpleCallDescriptor(zone, builder.Build());
}
CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
@@ -122,11 +122,48 @@
builder.AddParam(parameter0_type);
builder.AddParam(parameter1_type);
builder.AddParam(parameter2_type);
- return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
+ return MakeSimpleCallDescriptor(zone, builder.Build());
}
private:
InstructionSelectorTest* test_;
+
+ // Create a simple call descriptor for testing.
+ CallDescriptor* MakeSimpleCallDescriptor(Zone* zone,
+ MachineSignature* msig) {
+ LocationSignature::Builder locations(zone, msig->return_count(),
+ msig->parameter_count());
+
+ // Add return location(s).
+ const int return_count = static_cast<int>(msig->return_count());
+ for (int i = 0; i < return_count; i++) {
+ locations.AddReturn(LinkageLocation::ForCallerFrameSlot(-1 - i));
+ }
+
+ // Just put all parameters on the stack.
+ const int parameter_count = static_cast<int>(msig->parameter_count());
+ for (int i = 0; i < parameter_count; i++) {
+ locations.AddParam(LinkageLocation::ForCallerFrameSlot(-1 - i));
+ }
+
+ const RegList kCalleeSaveRegisters = 0;
+ const RegList kCalleeSaveFPRegisters = 0;
+
+ MachineType target_type = MachineType::Pointer();
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallAddress, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ msig, // machine_sig
+ locations.Build(), // location_sig
+ 0, // stack_parameter_count
+ Operator::kNoProperties, // properties
+ kCalleeSaveRegisters, // callee-saved registers
+ kCalleeSaveFPRegisters, // callee-saved fp regs
+ CallDescriptor::kNoFlags, // flags
+ "iselect-test-call");
+ }
};
class Stream final {
diff --git a/test/unittests/compiler/int64-lowering-unittest.cc b/test/unittests/compiler/int64-lowering-unittest.cc
new file mode 100644
index 0000000..eff6d4a
--- /dev/null
+++ b/test/unittests/compiler/int64-lowering-unittest.cc
@@ -0,0 +1,299 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/int64-lowering.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node.h"
+
+#include "src/compiler/node-properties.h"
+
+#include "src/signature.h"
+
+#include "src/wasm/wasm-module.h"
+
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::AllOf;
+using testing::Capture;
+using testing::CaptureEq;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class Int64LoweringTest : public GraphTest {
+ public:
+ Int64LoweringTest() : GraphTest(), machine_(zone()) {
+ value_[0] = 0x1234567890abcdef;
+ value_[1] = 0x1edcba098765432f;
+ value_[2] = 0x1133557799886644;
+ }
+
+ MachineOperatorBuilder* machine() { return &machine_; }
+
+ void LowerGraph(Node* node, Signature<MachineRepresentation>* signature) {
+ Node* ret = graph()->NewNode(common()->Return(), node, graph()->start(),
+ graph()->start());
+ NodeProperties::MergeControlToEnd(graph(), common(), ret);
+
+ Int64Lowering lowering(graph(), machine(), common(), zone(), signature);
+ lowering.LowerGraph();
+ }
+
+ void LowerGraph(Node* node, MachineRepresentation return_type,
+ MachineRepresentation rep = MachineRepresentation::kWord32,
+ int num_params = 0) {
+ Signature<MachineRepresentation>::Builder sig_builder(zone(), 1,
+ num_params);
+ sig_builder.AddReturn(return_type);
+ for (int i = 0; i < num_params; i++) {
+ sig_builder.AddParam(rep);
+ }
+ LowerGraph(node, sig_builder.Build());
+ }
+
+ void CompareCallDescriptors(const CallDescriptor* lhs,
+ const CallDescriptor* rhs) {
+ EXPECT_THAT(lhs->CalleeSavedFPRegisters(), rhs->CalleeSavedFPRegisters());
+ EXPECT_THAT(lhs->CalleeSavedRegisters(), rhs->CalleeSavedRegisters());
+ EXPECT_THAT(lhs->FrameStateCount(), rhs->FrameStateCount());
+ EXPECT_THAT(lhs->InputCount(), rhs->InputCount());
+ for (size_t i = 0; i < lhs->InputCount(); i++) {
+ EXPECT_THAT(lhs->GetInputLocation(i), rhs->GetInputLocation(i));
+ EXPECT_THAT(lhs->GetInputType(i), rhs->GetInputType(i));
+ }
+ EXPECT_THAT(lhs->ReturnCount(), rhs->ReturnCount());
+ for (size_t i = 0; i < lhs->ReturnCount(); i++) {
+ EXPECT_THAT(lhs->GetReturnLocation(i), rhs->GetReturnLocation(i));
+ EXPECT_THAT(lhs->GetReturnType(i), rhs->GetReturnType(i));
+ }
+ EXPECT_THAT(lhs->flags(), rhs->flags());
+ EXPECT_THAT(lhs->kind(), rhs->kind());
+ }
+
+ int64_t value(int i) { return value_[i]; }
+
+ int32_t low_word_value(int i) {
+ return static_cast<int32_t>(value_[i] & 0xffffffff);
+ }
+
+ int32_t high_word_value(int i) {
+ return static_cast<int32_t>(value_[i] >> 32);
+ }
+
+ private:
+ MachineOperatorBuilder machine_;
+ int64_t value_[3];
+};
+
+TEST_F(Int64LoweringTest, Int64Constant) {
+ if (4 != kPointerSize) return;
+
+ LowerGraph(Int64Constant(value(0)), MachineRepresentation::kWord64);
+ EXPECT_THAT(graph()->end()->InputAt(1),
+ IsReturn2(IsInt32Constant(low_word_value(0)),
+ IsInt32Constant(high_word_value(0)), start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Int64Load) {
+ if (4 != kPointerSize) return;
+
+ int32_t base = 0x1234;
+ int32_t index = 0x5678;
+
+ LowerGraph(graph()->NewNode(machine()->Load(MachineType::Int64()),
+ Int32Constant(base), Int32Constant(index),
+ start(), start()),
+ MachineRepresentation::kWord64);
+
+ Capture<Node*> high_word_load;
+ Matcher<Node*> high_word_load_matcher =
+ IsLoad(MachineType::Int32(), IsInt32Constant(base),
+ IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), start(),
+ start());
+
+ EXPECT_THAT(
+ graph()->end()->InputAt(1),
+ IsReturn2(IsLoad(MachineType::Int32(), IsInt32Constant(base),
+ IsInt32Constant(index), AllOf(CaptureEq(&high_word_load),
+ high_word_load_matcher),
+ start()),
+ AllOf(CaptureEq(&high_word_load), high_word_load_matcher),
+ start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Int64Store) {
+ if (4 != kPointerSize) return;
+
+ // We have to build the TF graph explicitly here because Store does not return
+ // a value.
+
+ int32_t base = 1111;
+ int32_t index = 2222;
+ int32_t return_value = 0x5555;
+
+ Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
+ sig_builder.AddReturn(MachineRepresentation::kWord32);
+
+ Node* store = graph()->NewNode(
+ machine()->Store(StoreRepresentation(MachineRepresentation::kWord64,
+ WriteBarrierKind::kNoWriteBarrier)),
+ Int32Constant(base), Int32Constant(index), Int64Constant(value(0)),
+ start(), start());
+
+ Node* ret = graph()->NewNode(common()->Return(), Int32Constant(return_value),
+ store, start());
+
+ NodeProperties::MergeControlToEnd(graph(), common(), ret);
+
+ Int64Lowering lowering(graph(), machine(), common(), zone(),
+ sig_builder.Build());
+ lowering.LowerGraph();
+
+ const StoreRepresentation rep(MachineRepresentation::kWord32,
+ kNoWriteBarrier);
+
+ EXPECT_THAT(
+ graph()->end()->InputAt(1),
+ IsReturn(
+ IsInt32Constant(return_value),
+ IsStore(
+ rep, IsInt32Constant(base), IsInt32Constant(index),
+ IsInt32Constant(low_word_value(0)),
+ IsStore(rep, IsInt32Constant(base),
+ IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)),
+ IsInt32Constant(high_word_value(0)), start(), start()),
+ start()),
+ start()));
+}
+
+TEST_F(Int64LoweringTest, Int64And) {
+ if (4 != kPointerSize) return;
+
+ LowerGraph(graph()->NewNode(machine()->Word64And(), Int64Constant(value(0)),
+ Int64Constant(value(1))),
+ MachineRepresentation::kWord64);
+ EXPECT_THAT(graph()->end()->InputAt(1),
+ IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
+ IsInt32Constant(low_word_value(1))),
+ IsWord32And(IsInt32Constant(high_word_value(0)),
+ IsInt32Constant(high_word_value(1))),
+ start(), start()));
+}
+
+TEST_F(Int64LoweringTest, TruncateInt64ToInt32) {
+ if (4 != kPointerSize) return;
+
+ LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
+ Int64Constant(value(0))),
+ MachineRepresentation::kWord32);
+ EXPECT_THAT(graph()->end()->InputAt(1),
+ IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Parameter) {
+ if (4 != kPointerSize) return;
+
+ LowerGraph(Parameter(0), MachineRepresentation::kWord64,
+ MachineRepresentation::kWord64, 1);
+
+ EXPECT_THAT(graph()->end()->InputAt(1),
+ IsReturn2(IsParameter(0), IsParameter(1), start(), start()));
+}
+
+TEST_F(Int64LoweringTest, Parameter2) {
+ if (4 != kPointerSize) return;
+
+ Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 5);
+ sig_builder.AddReturn(MachineRepresentation::kWord32);
+
+ sig_builder.AddParam(MachineRepresentation::kWord32);
+ sig_builder.AddParam(MachineRepresentation::kWord64);
+ sig_builder.AddParam(MachineRepresentation::kFloat64);
+ sig_builder.AddParam(MachineRepresentation::kWord64);
+ sig_builder.AddParam(MachineRepresentation::kWord32);
+
+ int start_parameter = start()->op()->ValueOutputCount();
+ LowerGraph(Parameter(4), sig_builder.Build());
+
+ EXPECT_THAT(graph()->end()->InputAt(1),
+ IsReturn(IsParameter(6), start(), start()));
+ // The parameter of the start node should increase by 2, because we lowered
+ // two parameter nodes.
+ EXPECT_THAT(start()->op()->ValueOutputCount(), start_parameter + 2);
+}
+
+TEST_F(Int64LoweringTest, CallI64Return) {
+ if (4 != kPointerSize) return;
+
+ int32_t function = 0x9999;
+
+ Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
+ sig_builder.AddReturn(MachineRepresentation::kWord64);
+
+ compiler::CallDescriptor* desc =
+ wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build());
+
+ LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
+ start(), start()),
+ MachineRepresentation::kWord64);
+
+ Capture<Node*> call;
+ Matcher<Node*> call_matcher =
+ IsCall(testing::_, IsInt32Constant(function), start(), start());
+
+ EXPECT_THAT(graph()->end()->InputAt(1),
+ IsReturn2(IsProjection(0, AllOf(CaptureEq(&call), call_matcher)),
+ IsProjection(1, AllOf(CaptureEq(&call), call_matcher)),
+ start(), start()));
+
+ CompareCallDescriptors(
+ OpParameter<const CallDescriptor*>(
+ graph()->end()->InputAt(1)->InputAt(0)->InputAt(0)),
+ wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
+}
+
+TEST_F(Int64LoweringTest, CallI64Parameter) {
+ if (4 != kPointerSize) return;
+
+ int32_t function = 0x9999;
+
+ Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 3);
+ sig_builder.AddReturn(MachineRepresentation::kWord32);
+ sig_builder.AddParam(MachineRepresentation::kWord64);
+ sig_builder.AddParam(MachineRepresentation::kWord32);
+ sig_builder.AddParam(MachineRepresentation::kWord64);
+
+ compiler::CallDescriptor* desc =
+ wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build());
+
+ LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function),
+ Int64Constant(value(0)),
+ Int32Constant(low_word_value(1)),
+ Int64Constant(value(2)), start(), start()),
+ MachineRepresentation::kWord32);
+
+ EXPECT_THAT(
+ graph()->end()->InputAt(1),
+ IsReturn(IsCall(testing::_, IsInt32Constant(function),
+ IsInt32Constant(low_word_value(0)),
+ IsInt32Constant(high_word_value(0)),
+ IsInt32Constant(low_word_value(1)),
+ IsInt32Constant(low_word_value(2)),
+ IsInt32Constant(high_word_value(2)), start(), start()),
+ start(), start()));
+
+ CompareCallDescriptors(
+ OpParameter<const CallDescriptor*>(
+ graph()->end()->InputAt(1)->InputAt(0)),
+ wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/compiler/interpreter-assembler-unittest.cc b/test/unittests/compiler/interpreter-assembler-unittest.cc
deleted file mode 100644
index f57ca05..0000000
--- a/test/unittests/compiler/interpreter-assembler-unittest.cc
+++ /dev/null
@@ -1,687 +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 "test/unittests/compiler/interpreter-assembler-unittest.h"
-
-#include "src/code-factory.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/node.h"
-#include "src/interface-descriptors.h"
-#include "src/isolate.h"
-#include "test/unittests/compiler/compiler-test-utils.h"
-#include "test/unittests/compiler/node-test-utils.h"
-
-using ::testing::_;
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-const interpreter::Bytecode kBytecodes[] = {
-#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
- BYTECODE_LIST(DEFINE_BYTECODE)
-#undef DEFINE_BYTECODE
-};
-
-
-Matcher<Node*> IsIntPtrConstant(const intptr_t value) {
- return kPointerSize == 8 ? IsInt64Constant(static_cast<int64_t>(value))
- : IsInt32Constant(static_cast<int32_t>(value));
-}
-
-
-Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
- const Matcher<Node*>& rhs_matcher) {
- return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
- : IsInt32Add(lhs_matcher, rhs_matcher);
-}
-
-
-Matcher<Node*> IsIntPtrSub(const Matcher<Node*>& lhs_matcher,
- const Matcher<Node*>& rhs_matcher) {
- return kPointerSize == 8 ? IsInt64Sub(lhs_matcher, rhs_matcher)
- : IsInt32Sub(lhs_matcher, rhs_matcher);
-}
-
-
-Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
- const Matcher<Node*>& rhs_matcher) {
- return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
- : IsWord32Shl(lhs_matcher, rhs_matcher);
-}
-
-
-Matcher<Node*> IsWordSar(const Matcher<Node*>& lhs_matcher,
- const Matcher<Node*>& rhs_matcher) {
- return kPointerSize == 8 ? IsWord64Sar(lhs_matcher, rhs_matcher)
- : IsWord32Sar(lhs_matcher, rhs_matcher);
-}
-
-
-Matcher<Node*> IsWordOr(const Matcher<Node*>& lhs_matcher,
- const Matcher<Node*>& rhs_matcher) {
- return kPointerSize == 8 ? IsWord64Or(lhs_matcher, rhs_matcher)
- : IsWord32Or(lhs_matcher, rhs_matcher);
-}
-
-
-Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
- const Matcher<LoadRepresentation>& rep_matcher,
- const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) {
- return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
-}
-
-
-Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
- const Matcher<StoreRepresentation>& rep_matcher,
- const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& value_matcher) {
- return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
- value_matcher, _, _);
-}
-
-
-Matcher<Node*>
-InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
- int offset) {
- return IsLoad(
- MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
-}
-
-
-Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
- IsBytecodeOperandSignExtended(int offset) {
- Matcher<Node*> load_matcher = IsLoad(
- MachineType::Int8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
- if (kPointerSize == 8) {
- load_matcher = IsChangeInt32ToInt64(load_matcher);
- }
- return load_matcher;
-}
-
-
-Matcher<Node*>
-InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperandShort(
- int offset) {
- if (TargetSupportsUnalignedAccess()) {
- return IsLoad(
- MachineType::Uint16(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
- } else {
- Matcher<Node*> first_byte = IsLoad(
- MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
- Matcher<Node*> second_byte = IsLoad(
- MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset + 1)));
-#if V8_TARGET_LITTLE_ENDIAN
- return IsWordOr(IsWordShl(second_byte, IsInt32Constant(kBitsPerByte)),
- first_byte);
-#elif V8_TARGET_BIG_ENDIAN
- return IsWordOr(IsWordShl(first_byte, IsInt32Constant(kBitsPerByte)),
- second_byte);
-#else
-#error "Unknown Architecture"
-#endif
- }
-}
-
-
-Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
- IsBytecodeOperandShortSignExtended(int offset) {
- Matcher<Node*> load_matcher;
- if (TargetSupportsUnalignedAccess()) {
- load_matcher = IsLoad(
- MachineType::Int16(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
- } else {
-#if V8_TARGET_LITTLE_ENDIAN
- int hi_byte_offset = offset + 1;
- int lo_byte_offset = offset;
-
-#elif V8_TARGET_BIG_ENDIAN
- int hi_byte_offset = offset;
- int lo_byte_offset = offset + 1;
-#else
-#error "Unknown Architecture"
-#endif
- Matcher<Node*> hi_byte = IsLoad(
- MachineType::Int8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(hi_byte_offset)));
- hi_byte = IsWord32Shl(hi_byte, IsInt32Constant(kBitsPerByte));
- Matcher<Node*> lo_byte = IsLoad(
- MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(lo_byte_offset)));
- load_matcher = IsWord32Or(hi_byte, lo_byte);
- }
-
- if (kPointerSize == 8) {
- load_matcher = IsChangeInt32ToInt64(load_matcher);
- }
- return load_matcher;
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- m.Dispatch();
- Graph* graph = m.graph();
-
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
-
- Matcher<Node*> next_bytecode_offset_matcher =
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
- Matcher<Node*> target_bytecode_matcher =
- m.IsLoad(MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- next_bytecode_offset_matcher);
- Matcher<Node*> code_target_matcher =
- m.IsLoad(MachineType::Pointer(),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsWord32Shl(target_bytecode_matcher,
- IsInt32Constant(kPointerSizeLog2)));
-
- EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
- EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
- EXPECT_THAT(
- tail_call_node,
- IsTailCall(m.call_descriptor(), code_target_matcher,
- IsParameter(Linkage::kInterpreterAccumulatorParameter),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- next_bytecode_offset_matcher,
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
- int jump_offsets[] = {-9710, -77, 0, +3, +97109};
- TRACED_FOREACH(int, jump_offset, jump_offsets) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- m.Jump(m.Int32Constant(jump_offset));
- Graph* graph = m.graph();
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
-
- Matcher<Node*> next_bytecode_offset_matcher =
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(jump_offset));
- Matcher<Node*> target_bytecode_matcher =
- m.IsLoad(MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- next_bytecode_offset_matcher);
- Matcher<Node*> code_target_matcher =
- m.IsLoad(MachineType::Pointer(),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsWord32Shl(target_bytecode_matcher,
- IsInt32Constant(kPointerSizeLog2)));
-
- EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
- EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
- EXPECT_THAT(
- tail_call_node,
- IsTailCall(m.call_descriptor(), code_target_matcher,
- IsParameter(Linkage::kInterpreterAccumulatorParameter),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- next_bytecode_offset_matcher,
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
- static const int kJumpIfTrueOffset = 73;
-
- MachineOperatorBuilder machine(zone());
-
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* lhs = m.IntPtrConstant(0);
- Node* rhs = m.IntPtrConstant(1);
- m.JumpIfWordEqual(lhs, rhs, m.Int32Constant(kJumpIfTrueOffset));
- Graph* graph = m.graph();
- Node* end = graph->end();
- EXPECT_EQ(2, end->InputCount());
-
- int jump_offsets[] = {kJumpIfTrueOffset,
- interpreter::Bytecodes::Size(bytecode)};
- for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
- Matcher<Node*> next_bytecode_offset_matcher =
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(jump_offsets[i]));
- Matcher<Node*> target_bytecode_matcher =
- m.IsLoad(MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- next_bytecode_offset_matcher);
- Matcher<Node*> code_target_matcher =
- m.IsLoad(MachineType::Pointer(),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsWord32Shl(target_bytecode_matcher,
- IsInt32Constant(kPointerSizeLog2)));
- EXPECT_THAT(
- end->InputAt(i),
- IsTailCall(m.call_descriptor(), code_target_matcher,
- IsParameter(Linkage::kInterpreterAccumulatorParameter),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- next_bytecode_offset_matcher,
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
-
- // TODO(oth): test control flow paths.
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, Return) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- m.Return();
- Graph* graph = m.graph();
-
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
-
- EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
- EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
- Handle<HeapObject> exit_trampoline =
- isolate()->builtins()->InterpreterExitTrampoline();
- EXPECT_THAT(
- tail_call_node,
- IsTailCall(m.call_descriptor(), IsHeapConstant(exit_trampoline),
- IsParameter(Linkage::kInterpreterAccumulatorParameter),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsParameter(Linkage::kInterpreterDispatchTableParameter),
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode);
- for (int i = 0; i < number_of_operands; i++) {
- int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i);
- switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
- case interpreter::OperandType::kCount8:
- EXPECT_THAT(m.BytecodeOperandCount(i), m.IsBytecodeOperand(offset));
- break;
- case interpreter::OperandType::kIdx8:
- EXPECT_THAT(m.BytecodeOperandIdx(i), m.IsBytecodeOperand(offset));
- break;
- case interpreter::OperandType::kImm8:
- EXPECT_THAT(m.BytecodeOperandImm(i),
- m.IsBytecodeOperandSignExtended(offset));
- break;
- case interpreter::OperandType::kMaybeReg8:
- case interpreter::OperandType::kReg8:
- case interpreter::OperandType::kRegPair8:
- EXPECT_THAT(m.BytecodeOperandReg(i),
- m.IsBytecodeOperandSignExtended(offset));
- break;
- case interpreter::OperandType::kCount16:
- EXPECT_THAT(m.BytecodeOperandCount(i),
- m.IsBytecodeOperandShort(offset));
- break;
- case interpreter::OperandType::kIdx16:
- EXPECT_THAT(m.BytecodeOperandIdx(i),
- m.IsBytecodeOperandShort(offset));
- break;
- case interpreter::OperandType::kReg16:
- EXPECT_THAT(m.BytecodeOperandReg(i),
- m.IsBytecodeOperandShortSignExtended(offset));
- break;
- case interpreter::OperandType::kNone:
- UNREACHABLE();
- break;
- }
- }
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- // Should be incoming accumulator if not set.
- EXPECT_THAT(m.GetAccumulator(),
- IsParameter(Linkage::kInterpreterAccumulatorParameter));
-
- // Should be set by SedtAccumulator.
- Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
- m.SetAccumulator(accumulator_value_1);
- EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
- Node* accumulator_value_2 = m.Int32Constant(42);
- m.SetAccumulator(accumulator_value_2);
- EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
-
- // Should be passed to next bytecode handler on dispatch.
- m.Dispatch();
- Graph* graph = m.graph();
-
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
-
- EXPECT_THAT(tail_call_node,
- IsTailCall(m.call_descriptor(), _, accumulator_value_2, _, _, _,
- _, _, _));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* reg_index_node = m.Int32Constant(44);
- Node* reg_location_node = m.RegisterLocation(reg_index_node);
- EXPECT_THAT(
- reg_location_node,
- IsIntPtrAdd(
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* reg_index_node = m.Int32Constant(44);
- Node* load_reg_node = m.LoadRegister(reg_index_node);
- EXPECT_THAT(
- load_reg_node,
- m.IsLoad(MachineType::AnyTagged(),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* store_value = m.Int32Constant(0xdeadbeef);
- Node* reg_index_node = m.Int32Constant(44);
- Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
- EXPECT_THAT(
- store_reg_node,
- m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
- kNoWriteBarrier),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
- store_value));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* value = m.Int32Constant(44);
- EXPECT_THAT(m.SmiTag(value),
- IsWordShl(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
- EXPECT_THAT(m.SmiUntag(value),
- IsWordSar(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* a = m.Int32Constant(0);
- Node* b = m.Int32Constant(1);
- Node* add = m.IntPtrAdd(a, b);
- EXPECT_THAT(add, IsIntPtrAdd(a, b));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* a = m.Int32Constant(0);
- Node* b = m.Int32Constant(1);
- Node* add = m.IntPtrSub(a, b);
- EXPECT_THAT(add, IsIntPtrSub(a, b));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* a = m.Int32Constant(0);
- Node* add = m.WordShl(a, 10);
- EXPECT_THAT(add, IsWordShl(a, IsInt32Constant(10)));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* index = m.Int32Constant(2);
- Node* load_constant = m.LoadConstantPoolEntry(index);
- Matcher<Node*> constant_pool_matcher = m.IsLoad(
- MachineType::AnyTagged(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
- EXPECT_THAT(
- load_constant,
- m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
- IsIntPtrAdd(
- IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
- IsWordShl(index, IsInt32Constant(kPointerSizeLog2)))));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- int index = 3;
- Node* fixed_array = m.IntPtrConstant(0xdeadbeef);
- Node* load_element = m.LoadFixedArrayElement(fixed_array, index);
- EXPECT_THAT(
- load_element,
- m.IsLoad(MachineType::AnyTagged(), fixed_array,
- IsIntPtrAdd(
- IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
- IsWordShl(IsInt32Constant(index),
- IsInt32Constant(kPointerSizeLog2)))));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* object = m.IntPtrConstant(0xdeadbeef);
- int offset = 16;
- Node* load_field = m.LoadObjectField(object, offset);
- EXPECT_THAT(load_field,
- m.IsLoad(MachineType::AnyTagged(), object,
- IsIntPtrConstant(offset - kHeapObjectTag)));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* context = m.Int32Constant(1);
- Node* slot_index = m.Int32Constant(22);
- Node* load_context_slot = m.LoadContextSlot(context, slot_index);
-
- Matcher<Node*> offset =
- IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
- IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
- EXPECT_THAT(load_context_slot,
- m.IsLoad(MachineType::AnyTagged(), context, offset));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* context = m.Int32Constant(1);
- Node* slot_index = m.Int32Constant(22);
- Node* value = m.Int32Constant(100);
- Node* store_context_slot = m.StoreContextSlot(context, slot_index, value);
-
- Matcher<Node*> offset =
- IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
- IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
- EXPECT_THAT(store_context_slot,
- m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
- kFullWriteBarrier),
- context, offset, value));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* arg1 = m.Int32Constant(2);
- Node* arg2 = m.Int32Constant(3);
- Node* call_runtime = m.CallRuntime(Runtime::kAdd, arg1, arg2);
- EXPECT_THAT(
- call_runtime,
- IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
- const int kResultSizes[] = {1, 2};
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- TRACED_FOREACH(int, result_size, kResultSizes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
-
- Node* function_id = m.Int32Constant(0);
- Node* first_arg = m.Int32Constant(1);
- Node* arg_count = m.Int32Constant(2);
-
- Matcher<Node*> function_table = IsExternalConstant(
- ExternalReference::runtime_function_table_address(isolate()));
- Matcher<Node*> function = IsIntPtrAdd(
- function_table,
- IsInt32Mul(function_id, IsInt32Constant(sizeof(Runtime::Function))));
- Matcher<Node*> function_entry =
- m.IsLoad(MachineType::Pointer(), function,
- IsInt32Constant(offsetof(Runtime::Function, entry)));
-
- Node* call_runtime =
- m.CallRuntime(function_id, first_arg, arg_count, result_size);
- EXPECT_THAT(
- call_runtime,
- IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
- function_entry,
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, CallIC) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- LoadWithVectorDescriptor descriptor(isolate());
- Node* target = m.Int32Constant(1);
- Node* arg1 = m.Int32Constant(2);
- Node* arg2 = m.Int32Constant(3);
- Node* arg3 = m.Int32Constant(4);
- Node* arg4 = m.Int32Constant(5);
- Node* call_ic = m.CallIC(descriptor, target, arg1, arg2, arg3, arg4);
- EXPECT_THAT(
- call_ic,
- IsCall(_, target, arg1, arg2, arg3, arg4,
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Callable builtin = CodeFactory::InterpreterPushArgsAndCall(isolate());
- Node* function = m.Int32Constant(0);
- Node* first_arg = m.Int32Constant(1);
- Node* arg_count = m.Int32Constant(2);
- Node* call_js = m.CallJS(function, first_arg, arg_count);
- EXPECT_THAT(
- call_js,
- IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
- function, IsParameter(Linkage::kInterpreterContextParameter), _,
- _));
- }
-}
-
-
-TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* feedback_vector = m.LoadTypeFeedbackVector();
-
- Matcher<Node*> load_function_matcher =
- m.IsLoad(MachineType::AnyTagged(),
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
- IsIntPtrConstant(
- InterpreterFrameConstants::kFunctionFromRegisterPointer));
- Matcher<Node*> load_shared_function_info_matcher =
- m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
- IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
- kHeapObjectTag));
-
- EXPECT_THAT(
- feedback_vector,
- m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher,
- IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
- kHeapObjectTag)));
- }
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/test/unittests/compiler/interpreter-assembler-unittest.h b/test/unittests/compiler/interpreter-assembler-unittest.h
deleted file mode 100644
index 15fa38b..0000000
--- a/test/unittests/compiler/interpreter-assembler-unittest.h
+++ /dev/null
@@ -1,57 +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.
-
-#ifndef V8_UNITTESTS_COMPILER_INTERPRETER_ASSEMBLER_UNITTEST_H_
-#define V8_UNITTESTS_COMPILER_INTERPRETER_ASSEMBLER_UNITTEST_H_
-
-#include "src/compiler/interpreter-assembler.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/machine-operator.h"
-#include "test/unittests/test-utils.h"
-#include "testing/gmock-support.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-using ::testing::Matcher;
-
-class InterpreterAssemblerTest : public TestWithIsolateAndZone {
- public:
- InterpreterAssemblerTest() {}
- ~InterpreterAssemblerTest() override {}
-
- class InterpreterAssemblerForTest final : public InterpreterAssembler {
- public:
- InterpreterAssemblerForTest(InterpreterAssemblerTest* test,
- interpreter::Bytecode bytecode)
- : InterpreterAssembler(test->isolate(), test->zone(), bytecode) {}
- ~InterpreterAssemblerForTest() override {}
-
- Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher);
- Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
- const Matcher<Node*>& base_matcher,
- const Matcher<Node*>& index_matcher,
- const Matcher<Node*>& value_matcher);
-
- Matcher<Node*> IsBytecodeOperand(int offset);
- Matcher<Node*> IsBytecodeOperandSignExtended(int offset);
- Matcher<Node*> IsBytecodeOperandShort(int offset);
- Matcher<Node*> IsBytecodeOperandShortSignExtended(int offset);
-
- using InterpreterAssembler::call_descriptor;
- using InterpreterAssembler::graph;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InterpreterAssemblerForTest);
- };
-};
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_UNITTESTS_COMPILER_INTERPRETER_ASSEMBLER_UNITTEST_H_
diff --git a/test/unittests/compiler/js-builtin-reducer-unittest.cc b/test/unittests/compiler/js-builtin-reducer-unittest.cc
index 78e9253..9e14cda 100644
--- a/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -64,10 +64,6 @@
Type::Integral32()};
-const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
-
-
-// TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
Type* const kNumberTypes[] = {
Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
@@ -88,15 +84,13 @@
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Node* call = graph()->NewNode(javascript()->CallFunction(2, language_mode),
- function, UndefinedConstant(), context,
- frame_state, frame_state, effect, control);
- Reduction r = Reduce(call);
+ Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
+ UndefinedConstant(), context, frame_state,
+ frame_state, effect, control);
+ Reduction r = Reduce(call);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
- }
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
}
@@ -107,18 +101,15 @@
Node* control = graph()->start();
Node* context = UndefinedConstant();
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, language_mode),
- function, UndefinedConstant(), p0, context,
- frame_state, frame_state, effect, control);
- Reduction r = Reduce(call);
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ frame_state, effect, control);
+ Reduction r = Reduce(call);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), p0);
- }
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), p0);
}
}
@@ -130,22 +121,18 @@
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- TRACED_FOREACH(Type*, t0, kIntegral32Types) {
- TRACED_FOREACH(Type*, t1, kIntegral32Types) {
- Node* p0 = Parameter(t0, 0);
- Node* p1 = Parameter(t1, 1);
- Node* call =
- graph()->NewNode(javascript()->CallFunction(4, language_mode),
- function, UndefinedConstant(), p0, p1, context,
- frame_state, frame_state, effect, control);
- Reduction r = Reduce(call);
+ TRACED_FOREACH(Type*, t0, kIntegral32Types) {
+ TRACED_FOREACH(Type*, t1, kIntegral32Types) {
+ Node* p0 = Parameter(t0, 0);
+ Node* p1 = Parameter(t1, 1);
+ Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+ UndefinedConstant(), p0, p1, context,
+ frame_state, frame_state, effect, control);
+ Reduction r = Reduce(call);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsSelect(MachineRepresentation::kNone,
- IsNumberLessThan(p1, p0), p0, p1));
- }
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
+ IsNumberLessThan(p1, p0), p0, p1));
}
}
}
@@ -162,20 +149,17 @@
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- TRACED_FOREACH(Type*, t0, kIntegral32Types) {
- TRACED_FOREACH(Type*, t1, kIntegral32Types) {
- Node* p0 = Parameter(t0, 0);
- Node* p1 = Parameter(t1, 1);
- Node* call =
- graph()->NewNode(javascript()->CallFunction(4, language_mode),
- function, UndefinedConstant(), p0, p1, context,
- frame_state, frame_state, effect, control);
- Reduction r = Reduce(call);
+ TRACED_FOREACH(Type*, t0, kIntegral32Types) {
+ TRACED_FOREACH(Type*, t1, kIntegral32Types) {
+ Node* p0 = Parameter(t0, 0);
+ Node* p1 = Parameter(t1, 1);
+ Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+ UndefinedConstant(), p0, p1, context,
+ frame_state, frame_state, effect, control);
+ Reduction r = Reduce(call);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
- }
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
}
}
}
@@ -192,18 +176,15 @@
Node* control = graph()->start();
Node* context = UndefinedConstant();
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, language_mode),
- function, UndefinedConstant(), p0, context,
- frame_state, frame_state, effect, control);
- Reduction r = Reduce(call);
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ frame_state, effect, control);
+ Reduction r = Reduce(call);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
- }
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
}
}
diff --git a/test/unittests/compiler/js-context-relaxation-unittest.cc b/test/unittests/compiler/js-context-relaxation-unittest.cc
deleted file mode 100644
index a44bd02..0000000
--- a/test/unittests/compiler/js-context-relaxation-unittest.cc
+++ /dev/null
@@ -1,285 +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/js-context-relaxation.h"
-#include "src/compiler/js-graph.h"
-#include "test/unittests/compiler/graph-unittest.h"
-#include "test/unittests/compiler/node-test-utils.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class JSContextRelaxationTest : public GraphTest {
- public:
- JSContextRelaxationTest() : GraphTest(3), javascript_(zone()) {}
- ~JSContextRelaxationTest() override {}
-
- protected:
- Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
- MachineOperatorBuilder::kNoFlags) {
- MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
- flags);
- JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
- &machine);
- // TODO(titzer): mock the GraphReducer here for better unit testing.
- GraphReducer graph_reducer(zone(), graph());
- JSContextRelaxation reducer;
- return reducer.Reduce(node);
- }
-
- Node* EmptyFrameState() {
- MachineOperatorBuilder machine(zone());
- JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
- &machine);
- return jsgraph.EmptyFrameState();
- }
-
- Node* ShallowFrameStateChain(Node* outer_context,
- ContextCallingMode context_calling_mode) {
- const FrameStateFunctionInfo* const frame_state_function_info =
- common()->CreateFrameStateFunctionInfo(
- FrameStateType::kJavaScriptFunction, 3, 0,
- Handle<SharedFunctionInfo>(), context_calling_mode);
- const Operator* op = common()->FrameState(BailoutId::None(),
- OutputFrameStateCombine::Ignore(),
- frame_state_function_info);
- return graph()->NewNode(op, graph()->start(), graph()->start(),
- graph()->start(), outer_context, graph()->start(),
- graph()->start());
- }
-
- Node* DeepFrameStateChain(Node* outer_context,
- ContextCallingMode context_calling_mode) {
- const FrameStateFunctionInfo* const frame_state_function_info =
- common()->CreateFrameStateFunctionInfo(
- FrameStateType::kJavaScriptFunction, 3, 0,
- Handle<SharedFunctionInfo>(), context_calling_mode);
- const Operator* op = common()->FrameState(BailoutId::None(),
- OutputFrameStateCombine::Ignore(),
- frame_state_function_info);
- Node* shallow_frame_state =
- ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- return graph()->NewNode(op, graph()->start(), graph()->start(),
- graph()->start(), graph()->start(),
- graph()->start(), shallow_frame_state);
- }
-
- JSOperatorBuilder* javascript() { return &javascript_; }
-
- private:
- JSOperatorBuilder javascript_;
-};
-
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionShallowFrameStateChainNoCrossCtx) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- Node* const frame_state =
- ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state, frame_state, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionShallowFrameStateChainCrossCtx) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- Node* const frame_state =
- ShallowFrameStateChain(outer_context, CALL_CHANGES_NATIVE_CONTEXT);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state, frame_state, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_FALSE(r.Changed());
- EXPECT_EQ(context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepFrameStateChainNoCrossCtx) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- Node* const frame_state =
- DeepFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state, frame_state, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepFrameStateChainCrossCtx) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- Node* const frame_state =
- DeepFrameStateChain(outer_context, CALL_CHANGES_NATIVE_CONTEXT);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state, frame_state, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_FALSE(r.Changed());
- EXPECT_EQ(context, NodeProperties::GetContextInput(node));
-}
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepContextChainFullRelaxForCatch) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- const Operator* op = javascript()->CreateCatchContext(Handle<String>());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* nested_context = graph()->NewNode(
- op, graph()->start(), graph()->start(), outer_context, effect, control);
- Node* const frame_state_2 =
- ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state_2, frame_state_2, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepContextChainFullRelaxForWith) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- const Operator* op = javascript()->CreateWithContext();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* nested_context = graph()->NewNode(
- op, graph()->start(), graph()->start(), outer_context, effect, control);
- Node* const frame_state_2 =
- ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state_2, frame_state_2, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepContextChainFullRelaxForBlock) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::null();
- const Operator* op = javascript()->CreateBlockContext(scope_info);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* nested_context =
- graph()->NewNode(op, graph()->start(), outer_context, effect, control);
- Node* const frame_state_2 =
- ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state_2, frame_state_2, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepContextChainPartialRelaxForScript) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::null();
- const Operator* op = javascript()->CreateScriptContext(scope_info);
- Node* const frame_state_1 =
- ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* nested_context = graph()->NewNode(op, graph()->start(), outer_context,
- frame_state_1, effect, control);
- Node* const frame_state_2 =
- ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state_2, frame_state_2, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(nested_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepContextChainPartialRelaxForModule) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- const Operator* op = javascript()->CreateModuleContext();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* nested_context = graph()->NewNode(
- op, graph()->start(), graph()->start(), outer_context, effect, control);
- Node* const frame_state_2 =
- ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state_2, frame_state_2, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_TRUE(r.Changed());
- EXPECT_EQ(nested_context, NodeProperties::GetContextInput(node));
-}
-
-
-TEST_F(JSContextRelaxationTest,
- RelaxJSCallFunctionDeepContextChainPartialNoRelax) {
- Node* const input0 = Parameter(0);
- Node* const input1 = Parameter(1);
- Node* const context = Parameter(2);
- Node* const outer_context = Parameter(3);
- const Operator* op = javascript()->CreateFunctionContext(0);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Node* nested_context =
- graph()->NewNode(op, graph()->start(), outer_context, effect, control);
- Node* const frame_state_2 =
- ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
- Node* node = graph()->NewNode(
- javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
- context, frame_state_2, frame_state_2, effect, control);
- Reduction const r = Reduce(node);
- EXPECT_FALSE(r.Changed());
- EXPECT_EQ(context, NodeProperties::GetContextInput(node));
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/test/unittests/compiler/js-create-lowering-unittest.cc b/test/unittests/compiler/js-create-lowering-unittest.cc
new file mode 100644
index 0000000..837c574
--- /dev/null
+++ b/test/unittests/compiler/js-create-lowering-unittest.cc
@@ -0,0 +1,236 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/js-create-lowering.h"
+#include "src/code-factory.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/operator-properties.h"
+#include "src/isolate-inl.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::_;
+using testing::BitEq;
+using testing::IsNaN;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class JSCreateLoweringTest : public TypedGraphTest {
+ public:
+ JSCreateLoweringTest()
+ : TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {}
+ ~JSCreateLoweringTest() override {}
+
+ protected:
+ Reduction Reduce(Node* node) {
+ MachineOperatorBuilder machine(zone());
+ SimplifiedOperatorBuilder simplified(zone());
+ JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
+ &machine);
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph,
+ MaybeHandle<LiteralsArray>(), zone());
+ return reducer.Reduce(node);
+ }
+
+ Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
+ Node* state_values = graph()->NewNode(common()->StateValues(0));
+ return graph()->NewNode(
+ common()->FrameState(
+ BailoutId::None(), OutputFrameStateCombine::Ignore(),
+ common()->CreateFrameStateFunctionInfo(
+ FrameStateType::kJavaScriptFunction, 1, 0, shared)),
+ state_values, state_values, state_values, NumberConstant(0),
+ UndefinedConstant(), outer_frame_state);
+ }
+
+ JSOperatorBuilder* javascript() { return &javascript_; }
+
+ private:
+ JSOperatorBuilder javascript_;
+ CompilationDependencies deps_;
+};
+
+TEST_F(JSCreateLoweringTest, JSCreate) {
+ Handle<JSFunction> function = isolate()->object_function();
+ Node* const target = Parameter(Type::Constant(function, graph()->zone()));
+ Node* const context = Parameter(Type::Any());
+ Node* const effect = graph()->start();
+ Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target,
+ context, EmptyFrameState(), effect));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsFinishRegion(
+ IsAllocate(IsNumberConstant(function->initial_map()->instance_size()),
+ IsBeginRegion(effect), _),
+ _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateArguments
+
+TEST_F(JSCreateLoweringTest, JSCreateArgumentsViaStub) {
+ Node* const closure = Parameter(Type::Any());
+ Node* const context = UndefinedConstant();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
+ Node* const frame_state = FrameState(shared, graph()->start());
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
+ closure, context, frame_state, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsCall(_, IsHeapConstant(
+ CodeFactory::FastNewStrictArguments(isolate()).code()),
+ closure, context, frame_state, effect, control));
+}
+
+TEST_F(JSCreateLoweringTest, JSCreateArgumentsRestParameterViaStub) {
+ Node* const closure = Parameter(Type::Any());
+ Node* const context = UndefinedConstant();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
+ Node* const frame_state = FrameState(shared, graph()->start());
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
+ closure, context, frame_state, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsCall(_, IsHeapConstant(
+ CodeFactory::FastNewRestParameter(isolate()).code()),
+ closure, context, frame_state, effect, control));
+}
+
+TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) {
+ Node* const closure = Parameter(Type::Any());
+ Node* const context = UndefinedConstant();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
+ Node* const frame_state_outer = FrameState(shared, graph()->start());
+ Node* const frame_state_inner = FrameState(shared, frame_state_outer);
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->CreateArguments(CreateArgumentsType::kMappedArguments),
+ closure, context, frame_state_inner, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFinishRegion(
+ IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize),
+ _, control),
+ _));
+}
+
+TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) {
+ Node* const closure = Parameter(Type::Any());
+ Node* const context = UndefinedConstant();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
+ Node* const frame_state_outer = FrameState(shared, graph()->start());
+ Node* const frame_state_inner = FrameState(shared, frame_state_outer);
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
+ closure, context, frame_state_inner, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFinishRegion(
+ IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize),
+ _, control),
+ _));
+}
+
+TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
+ Node* const closure = Parameter(Type::Any());
+ Node* const context = UndefinedConstant();
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
+ Node* const frame_state_outer = FrameState(shared, graph()->start());
+ Node* const frame_state_inner = FrameState(shared, frame_state_outer);
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
+ closure, context, frame_state_inner, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFinishRegion(
+ IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateFunctionContext
+
+TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
+ Node* const closure = Parameter(Type::Any());
+ Node* const context = Parameter(Type::Any());
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction const r =
+ Reduce(graph()->NewNode(javascript()->CreateFunctionContext(8), closure,
+ context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
+ 8 + Context::MIN_CONTEXT_SLOTS)),
+ IsBeginRegion(_), control),
+ _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateWithContext
+
+TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
+ Node* const object = Parameter(Type::Receiver());
+ Node* const closure = Parameter(Type::Function());
+ Node* const context = Parameter(Type::Any());
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
+ closure, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
+ Context::MIN_CONTEXT_SLOTS)),
+ IsBeginRegion(_), control),
+ _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateCatchContext
+
+TEST_F(JSCreateLoweringTest, JSCreateCatchContext) {
+ Handle<String> name = factory()->length_string();
+ Node* const exception = Parameter(Type::Receiver());
+ Node* const closure = Parameter(Type::Function());
+ Node* const context = Parameter(Type::Any());
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception,
+ closure, context, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
+ Context::MIN_CONTEXT_SLOTS + 1)),
+ IsBeginRegion(_), control),
+ _));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index f38f8ea..919c1b2 100644
--- a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
@@ -7,7 +7,6 @@
#include "src/compiler/js-graph.h"
#include "src/compiler/js-intrinsic-lowering.h"
#include "src/compiler/js-operator.h"
-#include "src/types-inl.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"
@@ -24,9 +23,9 @@
namespace internal {
namespace compiler {
-class JSIntrinsicLoweringTest : public TypedGraphTest {
+class JSIntrinsicLoweringTest : public GraphTest {
public:
- JSIntrinsicLoweringTest() : TypedGraphTest(3), javascript_(zone()) {}
+ JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {}
~JSIntrinsicLoweringTest() override {}
protected:
@@ -162,37 +161,6 @@
// -----------------------------------------------------------------------------
-// %_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(
- MachineRepresentation::kTagged, 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
@@ -224,38 +192,6 @@
// -----------------------------------------------------------------------------
-// %_IsFunction
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsFunction) {
- Node* const input = Parameter(Type::Any());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(
- graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsFunction, 1),
- input, context, effect, control));
- ASSERT_TRUE(r.Changed());
-
- Node* phi = r.replacement();
- Capture<Node*> branch, if_false;
- EXPECT_THAT(
- phi,
- IsPhi(
- MachineRepresentation::kTagged, IsFalseConstant(),
- IsUint32LessThanOrEqual(
- IsInt32Constant(FIRST_FUNCTION_TYPE),
- IsLoadField(AccessBuilder::ForMapInstanceType(),
- IsLoadField(AccessBuilder::ForMap(), input, effect,
- CaptureEq(&if_false)),
- effect, _)),
- IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
- IsBranch(IsObjectIsSmi(input), control))),
- AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-// -----------------------------------------------------------------------------
// %_IsRegExp
@@ -290,75 +226,16 @@
// %_IsJSReceiver
-TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiverWithAny) {
- Node* const input = Parameter(Type::Any());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(graph()->NewNode(
- javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
- context, effect, control));
- ASSERT_TRUE(r.Changed());
-
- Node* phi = r.replacement();
- Capture<Node *> branch, if_false;
- EXPECT_THAT(
- phi,
- IsPhi(
- MachineRepresentation::kTagged, IsFalseConstant(),
- IsUint32LessThanOrEqual(
- IsInt32Constant(FIRST_JS_RECEIVER_TYPE),
- IsLoadField(AccessBuilder::ForMapInstanceType(),
- IsLoadField(AccessBuilder::ForMap(), input, effect,
- CaptureEq(&if_false)),
- effect, _)),
- IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
- IsBranch(IsObjectIsSmi(input), control))),
- AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiverWithReceiver) {
- Node* const input = Parameter(Type::Receiver());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(graph()->NewNode(
- javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
- context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsTrueConstant());
-}
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiverWithUndefined) {
- Node* const input = Parameter(Type::Undefined());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(graph()->NewNode(
- javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
- context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsFalseConstant());
-}
-
-
-// -----------------------------------------------------------------------------
-// %_JSValueGetValue
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineJSValueGetValue) {
+TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiver) {
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::kInlineJSValueGetValue, 1), input,
+ javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
context, effect, control));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsLoadField(AccessBuilder::ForValue(), input, effect, control));
+ EXPECT_THAT(r.replacement(), IsObjectIsReceiver(input));
}
diff --git a/test/unittests/compiler/js-operator-unittest.cc b/test/unittests/compiler/js-operator-unittest.cc
index e0db771..15b1427 100644
--- a/test/unittests/compiler/js-operator-unittest.cc
+++ b/test/unittests/compiler/js-operator-unittest.cc
@@ -12,34 +12,8 @@
namespace internal {
namespace compiler {
-namespace {
-
-const LanguageMode kLanguageModes[] = {SLOPPY, STRICT, STRONG};
-
-
-#if GTEST_HAS_COMBINE
-
-template <typename T>
-class JSOperatorTestWithLanguageModeAndParam
- : public TestWithZone,
- public ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> {
- protected:
- LanguageMode language_mode() const {
- return ::testing::get<0>(B::GetParam());
- }
- const T& GetParam() const { return ::testing::get<1>(B::GetParam()); }
-
- private:
- typedef ::testing::WithParamInterface<::testing::tuple<LanguageMode, T>> B;
-};
-
-#endif // GTEST_HAS_COMBINE
-
-} // namespace
-
-
// -----------------------------------------------------------------------------
-// Shared operators without language mode.
+// Shared operators.
namespace {
@@ -56,7 +30,6 @@
int control_output_count;
};
-
const SharedOperator kSharedOperators[] = {
#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
effect_input_count, control_input_count, value_output_count, \
@@ -71,6 +44,10 @@
SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(StrictEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
SHARED(StrictNotEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
+ 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(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToString, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
@@ -148,123 +125,6 @@
INSTANTIATE_TEST_CASE_P(JSOperatorTest, JSSharedOperatorTest,
::testing::ValuesIn(kSharedOperators));
-
-// -----------------------------------------------------------------------------
-// Shared operators with language mode.
-
-
-#if GTEST_HAS_COMBINE
-
-namespace {
-
-struct SharedOperatorWithLanguageMode {
- const Operator* (JSOperatorBuilder::*constructor)(LanguageMode);
- IrOpcode::Value opcode;
- Operator::Properties properties;
- int value_input_count;
- int frame_state_input_count;
- int effect_input_count;
- int control_input_count;
- int value_output_count;
- int effect_output_count;
- int control_output_count;
-};
-
-
-const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
-#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
- effect_input_count, control_input_count, value_output_count, \
- effect_output_count, control_output_count) \
- { \
- &JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties, \
- value_input_count, frame_state_input_count, effect_input_count, \
- control_input_count, value_output_count, effect_output_count, \
- control_output_count \
- }
- 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),
-#undef SHARED
-};
-
-
-std::ostream& operator<<(std::ostream& os,
- const SharedOperatorWithLanguageMode& sop) {
- return os << IrOpcode::Mnemonic(sop.opcode);
-}
-
-} // namespace
-
-
-class JSSharedOperatorWithLanguageModeTest
- : public JSOperatorTestWithLanguageModeAndParam<
- SharedOperatorWithLanguageMode> {};
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, InstancesAreGloballyShared) {
- const SharedOperatorWithLanguageMode& sop = GetParam();
- JSOperatorBuilder javascript1(zone());
- JSOperatorBuilder javascript2(zone());
- EXPECT_EQ((javascript1.*sop.constructor)(language_mode()),
- (javascript2.*sop.constructor)(language_mode()));
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, NumberOfInputsAndOutputs) {
- JSOperatorBuilder javascript(zone());
- const SharedOperatorWithLanguageMode& sop = GetParam();
- const Operator* op = (javascript.*sop.constructor)(language_mode());
-
- const int context_input_count = 1;
- EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
- EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
- EXPECT_EQ(sop.frame_state_input_count,
- OperatorProperties::GetFrameStateInputCount(op));
- EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
- EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
- EXPECT_EQ(sop.value_input_count + context_input_count +
- sop.frame_state_input_count + sop.effect_input_count +
- sop.control_input_count,
- OperatorProperties::GetTotalInputCount(op));
-
- EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
- EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
- EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, OpcodeIsCorrect) {
- JSOperatorBuilder javascript(zone());
- const SharedOperatorWithLanguageMode& sop = GetParam();
- const Operator* op = (javascript.*sop.constructor)(language_mode());
- EXPECT_EQ(sop.opcode, op->opcode());
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, Parameter) {
- JSOperatorBuilder javascript(zone());
- const SharedOperatorWithLanguageMode& sop = GetParam();
- const Operator* op = (javascript.*sop.constructor)(language_mode());
- EXPECT_EQ(language_mode(), OpParameter<LanguageMode>(op));
-}
-
-
-TEST_P(JSSharedOperatorWithLanguageModeTest, Properties) {
- JSOperatorBuilder javascript(zone());
- const SharedOperatorWithLanguageMode& sop = GetParam();
- const Operator* op = (javascript.*sop.constructor)(language_mode());
- EXPECT_EQ(sop.properties, op->properties());
-}
-
-
-INSTANTIATE_TEST_CASE_P(
- JSOperatorTest, JSSharedOperatorWithLanguageModeTest,
- ::testing::Combine(::testing::ValuesIn(kLanguageModes),
- ::testing::ValuesIn(kSharedOperatorsWithLanguageMode)));
-
-#endif // GTEST_HAS_COMBINE
-
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc
index 6fc89bb..e37d4a2 100644
--- a/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -92,18 +92,6 @@
return reducer.Reduce(node);
}
- Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
- Node* state_values = graph()->NewNode(common()->StateValues(0));
- return graph()->NewNode(
- common()->FrameState(BailoutId::None(),
- OutputFrameStateCombine::Ignore(),
- common()->CreateFrameStateFunctionInfo(
- FrameStateType::kJavaScriptFunction, 1, 0,
- shared, CALL_MAINTAINS_NATIVE_CONTEXT)),
- state_values, state_values, state_values, NumberConstant(0),
- UndefinedConstant(), outer_frame_state);
- }
-
Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
JSArrayBuffer::Setup(buffer, isolate(), true, bytes, byte_length);
@@ -435,15 +423,12 @@
Node* const effect = graph()->start();
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, hints), lhs,
- NumberConstant(rhs), context, EmptyFrameState(),
- EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
- }
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftLeft(hints), lhs, NumberConstant(rhs), context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
}
}
@@ -455,13 +440,11 @@
Node* const context = UndefinedConstant();
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, hints), lhs, rhs, context,
- EmptyFrameState(), EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
- }
+ Reduction r = Reduce(graph()->NewNode(javascript()->ShiftLeft(hints), lhs,
+ rhs, context, EmptyFrameState(),
+ EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
}
@@ -476,15 +459,12 @@
Node* const effect = graph()->start();
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, hints), lhs,
- NumberConstant(rhs), context, EmptyFrameState(),
- EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
- }
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftRight(hints), lhs, NumberConstant(rhs), context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
}
}
@@ -496,13 +476,11 @@
Node* const context = UndefinedConstant();
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, hints), lhs, rhs, context,
- EmptyFrameState(), EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
- }
+ Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRight(hints), lhs,
+ rhs, context, EmptyFrameState(),
+ EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
}
@@ -518,15 +496,12 @@
Node* const effect = graph()->start();
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, hints), lhs,
- NumberConstant(rhs), context, EmptyFrameState(), EmptyFrameState(),
- effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
- }
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ShiftRightLogical(hints), lhs, NumberConstant(rhs),
+ context, EmptyFrameState(), EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
}
}
@@ -538,13 +513,11 @@
Node* const context = UndefinedConstant();
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, hints), lhs, rhs,
- context, EmptyFrameState(), EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
- }
+ Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRightLogical(hints),
+ lhs, rhs, context, EmptyFrameState(),
+ EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
}
@@ -627,37 +600,34 @@
NewArrayBuffer(backing_store, sizeof(backing_store));
VectorSlotPair feedback;
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
- 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());
+ 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(language_mode, feedback),
- base, key, vector, context, EmptyFrameState(),
- EmptyFrameState(), effect, control));
+ 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), 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));
}
}
@@ -669,32 +639,29 @@
NewArrayBuffer(backing_store, sizeof(backing_store));
VectorSlotPair feedback;
TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) {
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Handle<JSTypedArray> array =
- factory()->NewJSTypedArray(type, buffer, 0, kLength);
- ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true);
+ 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* vector = UndefinedConstant();
- Node* context = UndefinedConstant();
- Node* effect = graph()->start();
- Node* control = graph()->start();
- Reduction r = Reduce(
- graph()->NewNode(javascript()->LoadProperty(language_mode, feedback),
- base, key, vector, context, EmptyFrameState(),
- EmptyFrameState(), 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), 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));
- }
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsLoadElement(access,
+ IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
+ key, effect, control));
}
}
@@ -847,15 +814,12 @@
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction const r = Reduce(
- graph()->NewNode(javascript()->LoadNamed(language_mode, name, feedback),
- receiver, vector, context, EmptyFrameState(),
- EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
- receiver, effect, control));
- }
+ Reduction const r = Reduce(graph()->NewNode(
+ javascript()->LoadNamed(name, feedback), receiver, vector, context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
+ receiver, effect, control));
}
@@ -869,14 +833,11 @@
Node* const context = Parameter(Type::Internal(), 2);
Node* const effect = graph()->start();
Node* const control = graph()->start();
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
- Reduction const r = Reduce(
- graph()->NewNode(javascript()->LoadNamed(language_mode, name, feedback),
- receiver, vector, context, EmptyFrameState(),
- EmptyFrameState(), effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(function_prototype));
- }
+ Reduction const r = Reduce(graph()->NewNode(
+ javascript()->LoadNamed(name, feedback), receiver, vector, context,
+ EmptyFrameState(), EmptyFrameState(), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsHeapConstant(function_prototype));
}
@@ -886,7 +847,6 @@
TEST_F(JSTypedLoweringTest, JSAddWithString) {
BinaryOperationHints const hints = BinaryOperationHints::Any();
- TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
Node* lhs = Parameter(Type::String(), 0);
Node* rhs = Parameter(Type::String(), 1);
Node* context = Parameter(Type::Any(), 2);
@@ -894,300 +854,15 @@
Node* frame_state1 = EmptyFrameState();
Node* effect = graph()->start();
Node* control = graph()->start();
- Reduction r = Reduce(
- graph()->NewNode(javascript()->Add(language_mode, hints), lhs, rhs,
- context, frame_state0, frame_state1, effect, control));
+ Reduction r =
+ Reduce(graph()->NewNode(javascript()->Add(hints), lhs, rhs, context,
+ frame_state0, frame_state1, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsCall(_, IsHeapConstant(CodeFactory::StringAdd(
isolate(), STRING_ADD_CHECK_NONE,
NOT_TENURED).code()),
lhs, rhs, context, frame_state0, effect, control));
- }
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreate
-
-
-TEST_F(JSTypedLoweringTest, JSCreate) {
- Handle<JSFunction> function = isolate()->object_function();
- Node* const target = Parameter(Type::Constant(function, graph()->zone()));
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target,
- context, EmptyFrameState(), effect));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(function->initial_map()->instance_size()),
- IsBeginRegion(effect), _),
- _));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateArguments
-
-
-TEST_F(JSTypedLoweringTest, JSCreateArgumentsViaStub) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
- Node* const frame_state = FrameState(shared, graph()->start());
- Reduction r = Reduce(
- graph()->NewNode(javascript()->CreateArguments(
- CreateArgumentsParameters::kMappedArguments, 0),
- closure, context, frame_state, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsCall(_, IsHeapConstant(CodeFactory::ArgumentsAccess(
- isolate(), false, false)
- .code()),
- closure, IsNumberConstant(0), _, effect, control));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateArgumentsRestArrayViaStub) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
- Node* const frame_state = FrameState(shared, graph()->start());
- Reduction r = Reduce(graph()->NewNode(
- javascript()->CreateArguments(CreateArgumentsParameters::kRestArray, 0),
- closure, context, frame_state, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsCall(_,
- IsHeapConstant(CodeFactory::RestArgumentsAccess(isolate()).code()),
- IsNumberConstant(0), _, IsNumberConstant(0), _, effect, control));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateArgumentsInlinedMapped) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
- Node* const frame_state_outer = FrameState(shared, graph()->start());
- Node* const frame_state_inner = FrameState(shared, frame_state_outer);
- Reduction r = Reduce(
- graph()->NewNode(javascript()->CreateArguments(
- CreateArgumentsParameters::kMappedArguments, 0),
- closure, context, frame_state_inner, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(Heap::kSloppyArgumentsObjectSize),
- _, control),
- _));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateArgumentsInlinedUnmapped) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
- Node* const frame_state_outer = FrameState(shared, graph()->start());
- Node* const frame_state_inner = FrameState(shared, frame_state_outer);
- Reduction r = Reduce(
- graph()->NewNode(javascript()->CreateArguments(
- CreateArgumentsParameters::kUnmappedArguments, 0),
- closure, context, frame_state_inner, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(Heap::kStrictArgumentsObjectSize),
- _, control),
- _));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateArgumentsInlinedRestArray) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
- Node* const frame_state_outer = FrameState(shared, graph()->start());
- Node* const frame_state_inner = FrameState(shared, frame_state_outer);
- Reduction r = Reduce(graph()->NewNode(
- javascript()->CreateArguments(CreateArgumentsParameters::kRestArray, 0),
- closure, context, frame_state_inner, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateClosure
-
-
-TEST_F(JSTypedLoweringTest, JSCreateClosure) {
- Node* const context = UndefinedConstant();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
- Reduction r =
- Reduce(graph()->NewNode(javascript()->CreateClosure(shared, NOT_TENURED),
- context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsCall(_, IsHeapConstant(CodeFactory::FastNewClosure(
- isolate(), shared->language_mode(),
- shared->kind()).code()),
- IsHeapConstant(shared), effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateLiteralArray
-
-
-TEST_F(JSTypedLoweringTest, JSCreateLiteralArray) {
- Handle<FixedArray> const constant_elements = factory()->NewFixedArray(12);
- int const literal_flags = ArrayLiteral::kShallowElements;
- int const literal_index = 1;
- Node* const closure = Parameter(0);
- Node* const context = Parameter(1);
- Node* const frame_state = EmptyFrameState();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(
- graph()->NewNode(javascript()->CreateLiteralArray(
- constant_elements, literal_flags, literal_index),
- closure, context, frame_state, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsCall(_, IsHeapConstant(
- CodeFactory::FastCloneShallowArray(isolate()).code()),
- closure, IsNumberConstant(literal_index),
- IsHeapConstant(constant_elements), context, frame_state, effect,
- control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateLiteralObject
-
-
-TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) {
- Handle<FixedArray> const constant_properties =
- factory()->NewFixedArray(6 * 2);
- int const literal_flags = ObjectLiteral::kShallowProperties;
- int const literal_index = 1;
- Node* const closure = Parameter(0);
- Node* const context = Parameter(1);
- Node* const frame_state = EmptyFrameState();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(
- graph()->NewNode(javascript()->CreateLiteralObject(
- constant_properties, literal_flags, literal_index),
- closure, context, frame_state, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsCall(_, IsHeapConstant(
- CodeFactory::FastCloneShallowObject(isolate(), 6).code()),
- closure, IsNumberConstant(literal_index),
- IsHeapConstant(constant_properties), _, context, frame_state,
- effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateFunctionContext
-
-
-TEST_F(JSTypedLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r =
- Reduce(graph()->NewNode(javascript()->CreateFunctionContext(8), closure,
- context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
- 8 + Context::MIN_CONTEXT_SLOTS)),
- IsBeginRegion(_), control),
- _));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSCreateFunctionContextViaStub) {
- Node* const closure = Parameter(Type::Any());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r =
- Reduce(graph()->NewNode(javascript()->CreateFunctionContext(32), closure,
- context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsCall(_, IsHeapConstant(
- CodeFactory::FastNewContext(isolate(), 32).code()),
- closure, context, effect, control));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateWithContext
-
-
-TEST_F(JSTypedLoweringTest, JSCreateWithContext) {
- Node* const object = Parameter(Type::Receiver());
- Node* const closure = Parameter(Type::Function());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction r =
- Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
- closure, context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
- Context::MIN_CONTEXT_SLOTS)),
- IsBeginRegion(_), control),
- _));
-}
-
-
-// -----------------------------------------------------------------------------
-// JSCreateCatchContext
-
-
-TEST_F(JSTypedLoweringTest, JSCreateCatchContext) {
- Handle<String> name = factory()->length_string();
- Node* const exception = Parameter(Type::Receiver());
- Node* const closure = Parameter(Type::Function());
- Node* const context = Parameter(Type::Any());
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction r =
- Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception,
- closure, context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
- Context::MIN_CONTEXT_SLOTS + 1)),
- IsBeginRegion(_), control),
- _));
}
diff --git a/test/unittests/compiler/liveness-analyzer-unittest.cc b/test/unittests/compiler/liveness-analyzer-unittest.cc
index b77830a..efc823d 100644
--- a/test/unittests/compiler/liveness-analyzer-unittest.cc
+++ b/test/unittests/compiler/liveness-analyzer-unittest.cc
@@ -61,7 +61,7 @@
const FrameStateFunctionInfo* state_info =
common()->CreateFrameStateFunctionInfo(
FrameStateType::kJavaScriptFunction, 0, locals_count_,
- Handle<SharedFunctionInfo>(), CALL_MAINTAINS_NATIVE_CONTEXT);
+ Handle<SharedFunctionInfo>());
const Operator* op = common()->FrameState(
BailoutId(ast_num), OutputFrameStateCombine::Ignore(), state_info);
diff --git a/test/unittests/compiler/move-optimizer-unittest.cc b/test/unittests/compiler/move-optimizer-unittest.cc
index 413c58b..5ccd0c6 100644
--- a/test/unittests/compiler/move-optimizer-unittest.cc
+++ b/test/unittests/compiler/move-optimizer-unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/move-optimizer.h"
+#include "src/compiler/pipeline.h"
#include "test/unittests/compiler/instruction-sequence-unittest.h"
namespace v8 {
@@ -227,8 +228,8 @@
ctant_def->GetParallelMove(Instruction::GapPosition::END);
ParallelMove* last_start =
last->GetParallelMove(Instruction::GapPosition::START);
- CHECK(inst1_start == nullptr || inst1_start->size() == 0);
- CHECK(inst1_end == nullptr || inst1_end->size() == 0);
+ CHECK(inst1_start == nullptr || NonRedundantSize(inst1_start) == 0);
+ CHECK(inst1_end == nullptr || NonRedundantSize(inst1_end) == 0);
CHECK(last_start->size() == 2);
int redundants = 0;
int assignment = 0;
@@ -246,6 +247,98 @@
}
+TEST_F(MoveOptimizerTest, SubsetMovesMerge) {
+ StartBlock();
+ EndBlock(Branch(Imm(), 1, 2));
+
+ StartBlock();
+ EndBlock(Jump(2));
+ Instruction* last_move_b1 = LastInstruction();
+ AddMove(last_move_b1, Reg(0), Reg(1));
+ AddMove(last_move_b1, Reg(2), Reg(3));
+
+ StartBlock();
+ EndBlock(Jump(1));
+ Instruction* last_move_b2 = LastInstruction();
+ AddMove(last_move_b2, Reg(0), Reg(1));
+ AddMove(last_move_b2, Reg(4), Reg(5));
+
+ StartBlock();
+ EndBlock(Last());
+
+ Instruction* last = LastInstruction();
+
+ Optimize();
+
+ ParallelMove* last_move = last->parallel_moves()[0];
+ CHECK_EQ(1, NonRedundantSize(last_move));
+ CHECK(Contains(last_move, Reg(0), Reg(1)));
+
+ ParallelMove* b1_move = last_move_b1->parallel_moves()[0];
+ CHECK_EQ(1, NonRedundantSize(b1_move));
+ CHECK(Contains(b1_move, Reg(2), Reg(3)));
+
+ ParallelMove* b2_move = last_move_b2->parallel_moves()[0];
+ CHECK_EQ(1, NonRedundantSize(b2_move));
+ CHECK(Contains(b2_move, Reg(4), Reg(5)));
+}
+
+
+TEST_F(MoveOptimizerTest, GapConflictSubsetMovesDoNotMerge) {
+ StartBlock();
+ EndBlock(Branch(Imm(), 1, 2));
+
+ StartBlock();
+ EndBlock(Jump(2));
+ Instruction* last_move_b1 = LastInstruction();
+ AddMove(last_move_b1, Reg(0), Reg(1));
+ AddMove(last_move_b1, Reg(2), Reg(0));
+ AddMove(last_move_b1, Reg(4), Reg(5));
+
+ StartBlock();
+ EndBlock(Jump(1));
+ Instruction* last_move_b2 = LastInstruction();
+ AddMove(last_move_b2, Reg(0), Reg(1));
+ AddMove(last_move_b2, Reg(4), Reg(5));
+
+ StartBlock();
+ EndBlock(Last());
+
+ Instruction* last = LastInstruction();
+
+ Optimize();
+
+ ParallelMove* last_move = last->parallel_moves()[0];
+ CHECK_EQ(1, NonRedundantSize(last_move));
+ CHECK(Contains(last_move, Reg(4), Reg(5)));
+
+ ParallelMove* b1_move = last_move_b1->parallel_moves()[0];
+ CHECK_EQ(2, NonRedundantSize(b1_move));
+ CHECK(Contains(b1_move, Reg(0), Reg(1)));
+ CHECK(Contains(b1_move, Reg(2), Reg(0)));
+
+ ParallelMove* b2_move = last_move_b2->parallel_moves()[0];
+ CHECK_EQ(1, NonRedundantSize(b2_move));
+ CHECK(Contains(b1_move, Reg(0), Reg(1)));
+}
+
+TEST_F(MoveOptimizerTest, ClobberedDestinationsAreEliminated) {
+ StartBlock();
+ EmitNop();
+ Instruction* first_instr = LastInstruction();
+ AddMove(first_instr, Reg(0), Reg(1));
+ EmitOI(Reg(1), 0, nullptr);
+ Instruction* last_instr = LastInstruction();
+ EndBlock();
+ Optimize();
+
+ ParallelMove* first_move = first_instr->parallel_moves()[0];
+ CHECK_EQ(0, NonRedundantSize(first_move));
+
+ ParallelMove* last_move = last_instr->parallel_moves()[0];
+ CHECK_EQ(0, NonRedundantSize(last_move));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc
index 54168ee..ee4cf54 100644
--- a/test/unittests/compiler/node-test-utils.cc
+++ b/test/unittests/compiler/node-test-utils.cc
@@ -323,13 +323,30 @@
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kReturn),
value_matcher_(value_matcher),
+ value2_matcher_(_),
effect_matcher_(effect_matcher),
- control_matcher_(control_matcher) {}
+ control_matcher_(control_matcher),
+ has_second_return_value_(false) {}
+
+ IsReturnMatcher(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& value2_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kReturn),
+ value_matcher_(value_matcher),
+ value2_matcher_(value2_matcher),
+ effect_matcher_(effect_matcher),
+ control_matcher_(control_matcher),
+ has_second_return_value_(true) {}
void DescribeTo(std::ostream* os) const final {
NodeMatcher::DescribeTo(os);
*os << " whose value (";
value_matcher_.DescribeTo(os);
+ if (has_second_return_value_) {
+ *os << ") and second value (";
+ value2_matcher_.DescribeTo(os);
+ }
*os << ") and effect (";
effect_matcher_.DescribeTo(os);
*os << ") and control (";
@@ -341,6 +358,9 @@
return (NodeMatcher::MatchAndExplain(node, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
"value", value_matcher_, listener) &&
+ (!has_second_return_value_ ||
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+ "value2", value2_matcher_, listener)) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
effect_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetControlInput(node),
@@ -349,8 +369,10 @@
private:
const Matcher<Node*> value_matcher_;
+ const Matcher<Node*> value2_matcher_;
const Matcher<Node*> effect_matcher_;
const Matcher<Node*> control_matcher_;
+ bool has_second_return_value_;
};
@@ -1467,7 +1489,6 @@
return MakeMatcher(new NodeMatcher(IrOpcode::kDead));
}
-
Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher) {
return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control0_matcher));
}
@@ -1577,6 +1598,13 @@
new IsReturnMatcher(value_matcher, effect_matcher, control_matcher));
}
+Matcher<Node*> IsReturn2(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& value2_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(new IsReturnMatcher(value_matcher, value2_matcher,
+ effect_matcher, control_matcher));
+}
Matcher<Node*> IsTerminate(const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
@@ -1675,6 +1703,15 @@
return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
}
+Matcher<Node*> IsCall(const Matcher<const CallDescriptor*>& descriptor_matcher,
+ const Matcher<Node*>& value0_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher) {
+ std::vector<Matcher<Node*>> value_matchers;
+ value_matchers.push_back(value0_matcher);
+ return MakeMatcher(new IsCallMatcher(descriptor_matcher, value_matchers,
+ effect_matcher, control_matcher));
+}
Matcher<Node*> IsCall(const Matcher<const CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
@@ -2106,6 +2143,7 @@
IS_UNOP_MATCHER(Float64ExtractHighWord32)
IS_UNOP_MATCHER(NumberToInt32)
IS_UNOP_MATCHER(NumberToUint32)
+IS_UNOP_MATCHER(ObjectIsReceiver)
IS_UNOP_MATCHER(ObjectIsSmi)
IS_UNOP_MATCHER(Word32Clz)
#undef IS_UNOP_MATCHER
diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h
index 8592f30..03f2a3b 100644
--- a/test/unittests/compiler/node-test-utils.h
+++ b/test/unittests/compiler/node-test-utils.h
@@ -17,11 +17,8 @@
template <typename T>
class Handle;
class HeapObject;
-template <class>
-class TypeImpl;
+class Type;
enum TypeofMode : int;
-struct ZoneTypeConfig;
-typedef TypeImpl<ZoneTypeConfig> Type;
namespace compiler {
@@ -70,6 +67,10 @@
Matcher<Node*> IsReturn(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsReturn2(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& value2_matcher,
+ const Matcher<Node*>& effect_matcher,
+ const Matcher<Node*>& control_matcher);
Matcher<Node*> IsTerminate(const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsExternalConstant(
@@ -246,6 +247,7 @@
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsObjectIsReceiver(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsObjectIsSmi(const Matcher<Node*>& value_matcher);
Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
diff --git a/test/unittests/compiler/scheduler-rpo-unittest.cc b/test/unittests/compiler/scheduler-rpo-unittest.cc
new file mode 100644
index 0000000..713ee6e
--- /dev/null
+++ b/test/unittests/compiler/scheduler-rpo-unittest.cc
@@ -0,0 +1,533 @@
+// 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/schedule.h"
+#include "src/compiler/scheduler.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::AnyOf;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class SchedulerRPOTest : public TestWithZone {
+ public:
+ SchedulerRPOTest() {}
+
+ void CheckRPONumbers(BasicBlockVector* order, size_t expected,
+ bool loops_allowed) {
+ CHECK(expected == order->size());
+ for (int i = 0; i < static_cast<int>(order->size()); i++) {
+ CHECK(order->at(i)->rpo_number() == i);
+ if (!loops_allowed) {
+ CHECK(!order->at(i)->loop_end());
+ CHECK(!order->at(i)->loop_header());
+ }
+ }
+ }
+
+ void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) {
+ BasicBlock* header = blocks[0];
+ BasicBlock* end = header->loop_end();
+ CHECK(end);
+ CHECK_GT(end->rpo_number(), 0);
+ CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
+ for (int i = 0; i < body_size; i++) {
+ CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
+ CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
+ CHECK(header->LoopContains(blocks[i]));
+ CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
+ }
+ if (header->rpo_number() > 0) {
+ CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
+ }
+ if (end->rpo_number() < static_cast<int>(order->size())) {
+ CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
+ }
+ }
+
+ struct TestLoop {
+ int count;
+ BasicBlock** nodes;
+ BasicBlock* header() { return nodes[0]; }
+ BasicBlock* last() { return nodes[count - 1]; }
+ ~TestLoop() { delete[] nodes; }
+ };
+
+ TestLoop* CreateLoop(Schedule* schedule, int count) {
+ TestLoop* loop = new TestLoop();
+ loop->count = count;
+ loop->nodes = new BasicBlock*[count];
+ for (int i = 0; i < count; i++) {
+ loop->nodes[i] = schedule->NewBasicBlock();
+ if (i > 0) {
+ schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]);
+ }
+ }
+ schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]);
+ return loop;
+ }
+};
+
+TEST_F(SchedulerRPOTest, Degenerate1) {
+ Schedule schedule(zone());
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 1, false);
+ EXPECT_EQ(schedule.start(), order->at(0));
+}
+
+TEST_F(SchedulerRPOTest, Degenerate2) {
+ Schedule schedule(zone());
+
+ schedule.AddGoto(schedule.start(), schedule.end());
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 2, false);
+ EXPECT_EQ(schedule.start(), order->at(0));
+ EXPECT_EQ(schedule.end(), order->at(1));
+}
+
+TEST_F(SchedulerRPOTest, Line) {
+ for (int i = 0; i < 10; i++) {
+ Schedule schedule(zone());
+
+ BasicBlock* last = schedule.start();
+ for (int j = 0; j < i; j++) {
+ BasicBlock* block = schedule.NewBasicBlock();
+ block->set_deferred(i & 1);
+ schedule.AddGoto(last, block);
+ last = block;
+ }
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 1 + i, false);
+
+ for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
+ BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
+ if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
+ EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number());
+ }
+ }
+ }
+}
+
+TEST_F(SchedulerRPOTest, SelfLoop) {
+ Schedule schedule(zone());
+ schedule.AddSuccessorForTesting(schedule.start(), schedule.start());
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 1, true);
+ BasicBlock* loop[] = {schedule.start()};
+ CheckLoop(order, loop, 1);
+}
+
+TEST_F(SchedulerRPOTest, EntryLoop) {
+ Schedule schedule(zone());
+ BasicBlock* body = schedule.NewBasicBlock();
+ schedule.AddSuccessorForTesting(schedule.start(), body);
+ schedule.AddSuccessorForTesting(body, schedule.start());
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 2, true);
+ BasicBlock* loop[] = {schedule.start(), body};
+ CheckLoop(order, loop, 2);
+}
+
+TEST_F(SchedulerRPOTest, EndLoop) {
+ Schedule schedule(zone());
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
+ schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 3, true);
+ CheckLoop(order, loop1->nodes, loop1->count);
+}
+
+TEST_F(SchedulerRPOTest, EndLoopNested) {
+ Schedule schedule(zone());
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
+ schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
+ schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 3, true);
+ CheckLoop(order, loop1->nodes, loop1->count);
+}
+
+TEST_F(SchedulerRPOTest, Diamond) {
+ Schedule schedule(zone());
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(A, C);
+ schedule.AddSuccessorForTesting(B, D);
+ schedule.AddSuccessorForTesting(C, D);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 4, false);
+
+ EXPECT_EQ(0, A->rpo_number());
+ EXPECT_THAT(B->rpo_number(), AnyOf(1, 2));
+ EXPECT_THAT(C->rpo_number(), AnyOf(1, 2));
+ EXPECT_EQ(3, D->rpo_number());
+}
+
+TEST_F(SchedulerRPOTest, Loop1) {
+ Schedule schedule(zone());
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, C);
+ schedule.AddSuccessorForTesting(C, B);
+ schedule.AddSuccessorForTesting(C, D);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 4, true);
+ BasicBlock* loop[] = {B, C};
+ CheckLoop(order, loop, 2);
+}
+
+TEST_F(SchedulerRPOTest, Loop2) {
+ Schedule schedule(zone());
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, C);
+ schedule.AddSuccessorForTesting(C, B);
+ schedule.AddSuccessorForTesting(B, D);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 4, true);
+ BasicBlock* loop[] = {B, C};
+ CheckLoop(order, loop, 2);
+}
+
+TEST_F(SchedulerRPOTest, LoopN) {
+ for (int i = 0; i < 11; i++) {
+ Schedule schedule(zone());
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.NewBasicBlock();
+ BasicBlock* F = schedule.NewBasicBlock();
+ BasicBlock* G = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, C);
+ schedule.AddSuccessorForTesting(C, D);
+ schedule.AddSuccessorForTesting(D, E);
+ schedule.AddSuccessorForTesting(E, F);
+ schedule.AddSuccessorForTesting(F, B);
+ schedule.AddSuccessorForTesting(B, G);
+
+ // Throw in extra backedges from time to time.
+ if (i == 1) schedule.AddSuccessorForTesting(B, B);
+ if (i == 2) schedule.AddSuccessorForTesting(C, B);
+ if (i == 3) schedule.AddSuccessorForTesting(D, B);
+ if (i == 4) schedule.AddSuccessorForTesting(E, B);
+ if (i == 5) schedule.AddSuccessorForTesting(F, B);
+
+ // Throw in extra loop exits from time to time.
+ if (i == 6) schedule.AddSuccessorForTesting(B, G);
+ if (i == 7) schedule.AddSuccessorForTesting(C, G);
+ if (i == 8) schedule.AddSuccessorForTesting(D, G);
+ if (i == 9) schedule.AddSuccessorForTesting(E, G);
+ if (i == 10) schedule.AddSuccessorForTesting(F, G);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 7, true);
+ BasicBlock* loop[] = {B, C, D, E, F};
+ CheckLoop(order, loop, 5);
+ }
+}
+
+TEST_F(SchedulerRPOTest, LoopNest1) {
+ Schedule schedule(zone());
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.NewBasicBlock();
+ BasicBlock* F = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, C);
+ schedule.AddSuccessorForTesting(C, D);
+ schedule.AddSuccessorForTesting(D, C);
+ schedule.AddSuccessorForTesting(D, E);
+ schedule.AddSuccessorForTesting(E, B);
+ schedule.AddSuccessorForTesting(E, F);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 6, true);
+ BasicBlock* loop1[] = {B, C, D, E};
+ CheckLoop(order, loop1, 4);
+
+ BasicBlock* loop2[] = {C, D};
+ CheckLoop(order, loop2, 2);
+}
+
+TEST_F(SchedulerRPOTest, LoopNest2) {
+ Schedule schedule(zone());
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.NewBasicBlock();
+ BasicBlock* F = schedule.NewBasicBlock();
+ BasicBlock* G = schedule.NewBasicBlock();
+ BasicBlock* H = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, C);
+ schedule.AddSuccessorForTesting(C, D);
+ schedule.AddSuccessorForTesting(D, E);
+ schedule.AddSuccessorForTesting(E, F);
+ schedule.AddSuccessorForTesting(F, G);
+ schedule.AddSuccessorForTesting(G, H);
+
+ schedule.AddSuccessorForTesting(E, D);
+ schedule.AddSuccessorForTesting(F, C);
+ schedule.AddSuccessorForTesting(G, B);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 8, true);
+ BasicBlock* loop1[] = {B, C, D, E, F, G};
+ CheckLoop(order, loop1, 6);
+
+ BasicBlock* loop2[] = {C, D, E, F};
+ CheckLoop(order, loop2, 4);
+
+ BasicBlock* loop3[] = {D, E};
+ CheckLoop(order, loop3, 2);
+}
+
+TEST_F(SchedulerRPOTest, LoopFollow1) {
+ Schedule schedule(zone());
+
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
+ base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* E = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
+ schedule.AddSuccessorForTesting(loop2->last(), E);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
+}
+
+TEST_F(SchedulerRPOTest, LoopFollow2) {
+ Schedule schedule(zone());
+
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
+ base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* S = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->header(), S);
+ schedule.AddSuccessorForTesting(S, loop2->header());
+ schedule.AddSuccessorForTesting(loop2->last(), E);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
+}
+
+TEST_F(SchedulerRPOTest, LoopFollowN) {
+ for (int size = 1; size < 5; size++) {
+ for (int exit = 0; exit < size; exit++) {
+ Schedule schedule(zone());
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+ base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
+ BasicBlock* A = schedule.start();
+ BasicBlock* E = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header());
+ schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
+ }
+ }
+}
+
+TEST_F(SchedulerRPOTest, NestedLoopFollow1) {
+ Schedule schedule(zone());
+
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
+ base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.end();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
+ schedule.AddSuccessorForTesting(loop2->last(), C);
+ schedule.AddSuccessorForTesting(C, E);
+ schedule.AddSuccessorForTesting(C, B);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+
+ EXPECT_EQ(schedule.BasicBlockCount(), order->size());
+ CheckLoop(order, loop1->nodes, loop1->count);
+ CheckLoop(order, loop2->nodes, loop2->count);
+
+ BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
+ CheckLoop(order, loop3, 4);
+}
+
+TEST_F(SchedulerRPOTest, LoopBackedges1) {
+ int size = 8;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ Schedule schedule(zone());
+ BasicBlock* A = schedule.start();
+ BasicBlock* E = schedule.end();
+
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->last(), E);
+
+ schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
+ schedule.AddSuccessorForTesting(loop1->nodes[j], E);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+ CheckLoop(order, loop1->nodes, loop1->count);
+ }
+ }
+}
+
+TEST_F(SchedulerRPOTest, LoopOutedges1) {
+ int size = 8;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ Schedule schedule(zone());
+ BasicBlock* A = schedule.start();
+ BasicBlock* D = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.end();
+
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->last(), E);
+
+ schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
+ schedule.AddSuccessorForTesting(loop1->nodes[j], D);
+ schedule.AddSuccessorForTesting(D, E);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+ CheckLoop(order, loop1->nodes, loop1->count);
+ }
+ }
+}
+
+TEST_F(SchedulerRPOTest, LoopOutedges2) {
+ int size = 8;
+ for (int i = 0; i < size; i++) {
+ Schedule schedule(zone());
+ BasicBlock* A = schedule.start();
+ BasicBlock* E = schedule.end();
+
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->last(), E);
+
+ for (int j = 0; j < size; j++) {
+ BasicBlock* O = schedule.NewBasicBlock();
+ schedule.AddSuccessorForTesting(loop1->nodes[j], O);
+ schedule.AddSuccessorForTesting(O, E);
+ }
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+ CheckLoop(order, loop1->nodes, loop1->count);
+ }
+}
+
+TEST_F(SchedulerRPOTest, LoopOutloops1) {
+ int size = 8;
+ for (int i = 0; i < size; i++) {
+ Schedule schedule(zone());
+ BasicBlock* A = schedule.start();
+ BasicBlock* E = schedule.end();
+ base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
+ schedule.AddSuccessorForTesting(A, loop1->header());
+ schedule.AddSuccessorForTesting(loop1->last(), E);
+
+ TestLoop** loopN = new TestLoop*[size];
+ for (int j = 0; j < size; j++) {
+ loopN[j] = CreateLoop(&schedule, 2);
+ schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header());
+ schedule.AddSuccessorForTesting(loopN[j]->last(), E);
+ }
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, schedule.BasicBlockCount(), true);
+ CheckLoop(order, loop1->nodes, loop1->count);
+
+ for (int j = 0; j < size; j++) {
+ CheckLoop(order, loopN[j]->nodes, loopN[j]->count);
+ delete loopN[j];
+ }
+ delete[] loopN;
+ }
+}
+
+TEST_F(SchedulerRPOTest, LoopMultibackedge) {
+ Schedule schedule(zone());
+
+ BasicBlock* A = schedule.start();
+ BasicBlock* B = schedule.NewBasicBlock();
+ BasicBlock* C = schedule.NewBasicBlock();
+ BasicBlock* D = schedule.NewBasicBlock();
+ BasicBlock* E = schedule.NewBasicBlock();
+
+ schedule.AddSuccessorForTesting(A, B);
+ schedule.AddSuccessorForTesting(B, C);
+ schedule.AddSuccessorForTesting(B, D);
+ schedule.AddSuccessorForTesting(B, E);
+ schedule.AddSuccessorForTesting(C, B);
+ schedule.AddSuccessorForTesting(D, B);
+ schedule.AddSuccessorForTesting(E, B);
+
+ BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
+ CheckRPONumbers(order, 5, true);
+
+ BasicBlock* loop1[] = {B, C, D, E};
+ CheckLoop(order, loop1, 4);
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/compiler/scheduler-unittest.cc b/test/unittests/compiler/scheduler-unittest.cc
index 523c8ce..6cf0734 100644
--- a/test/unittests/compiler/scheduler-unittest.cc
+++ b/test/unittests/compiler/scheduler-unittest.cc
@@ -71,67 +71,6 @@
};
-class SchedulerRPOTest : public SchedulerTest {
- public:
- SchedulerRPOTest() {}
-
- // TODO(titzer): pull RPO tests out to their own file.
- void CheckRPONumbers(BasicBlockVector* order, size_t expected,
- bool loops_allowed) {
- CHECK(expected == order->size());
- for (int i = 0; i < static_cast<int>(order->size()); i++) {
- CHECK(order->at(i)->rpo_number() == i);
- if (!loops_allowed) {
- CHECK(!order->at(i)->loop_end());
- CHECK(!order->at(i)->loop_header());
- }
- }
- }
-
- void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) {
- BasicBlock* header = blocks[0];
- BasicBlock* end = header->loop_end();
- CHECK(end);
- CHECK_GT(end->rpo_number(), 0);
- CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
- for (int i = 0; i < body_size; i++) {
- CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
- CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
- CHECK(header->LoopContains(blocks[i]));
- CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
- }
- if (header->rpo_number() > 0) {
- CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
- }
- if (end->rpo_number() < static_cast<int>(order->size())) {
- CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
- }
- }
-
- struct TestLoop {
- int count;
- BasicBlock** nodes;
- BasicBlock* header() { return nodes[0]; }
- BasicBlock* last() { return nodes[count - 1]; }
- ~TestLoop() { delete[] nodes; }
- };
-
- TestLoop* CreateLoop(Schedule* schedule, int count) {
- TestLoop* loop = new TestLoop();
- loop->count = count;
- loop->nodes = new BasicBlock* [count];
- for (int i = 0; i < count; i++) {
- loop->nodes[i] = schedule->NewBasicBlock();
- if (i > 0) {
- schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]);
- }
- }
- schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]);
- return loop;
- }
-};
-
-
namespace {
const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure,
@@ -146,491 +85,6 @@
} // namespace
-// -----------------------------------------------------------------------------
-// Special reverse-post-order block ordering.
-
-
-TEST_F(SchedulerRPOTest, Degenerate1) {
- Schedule schedule(zone());
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 1, false);
- EXPECT_EQ(schedule.start(), order->at(0));
-}
-
-
-TEST_F(SchedulerRPOTest, Degenerate2) {
- Schedule schedule(zone());
-
- schedule.AddGoto(schedule.start(), schedule.end());
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 2, false);
- EXPECT_EQ(schedule.start(), order->at(0));
- EXPECT_EQ(schedule.end(), order->at(1));
-}
-
-
-TEST_F(SchedulerRPOTest, Line) {
- for (int i = 0; i < 10; i++) {
- Schedule schedule(zone());
-
- BasicBlock* last = schedule.start();
- for (int j = 0; j < i; j++) {
- BasicBlock* block = schedule.NewBasicBlock();
- block->set_deferred(i & 1);
- schedule.AddGoto(last, block);
- last = block;
- }
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 1 + i, false);
-
- for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
- BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
- if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
- EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number());
- }
- }
- }
-}
-
-
-TEST_F(SchedulerRPOTest, SelfLoop) {
- Schedule schedule(zone());
- schedule.AddSuccessorForTesting(schedule.start(), schedule.start());
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 1, true);
- BasicBlock* loop[] = {schedule.start()};
- CheckLoop(order, loop, 1);
-}
-
-
-TEST_F(SchedulerRPOTest, EntryLoop) {
- Schedule schedule(zone());
- BasicBlock* body = schedule.NewBasicBlock();
- schedule.AddSuccessorForTesting(schedule.start(), body);
- schedule.AddSuccessorForTesting(body, schedule.start());
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 2, true);
- BasicBlock* loop[] = {schedule.start(), body};
- CheckLoop(order, loop, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, EndLoop) {
- Schedule schedule(zone());
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
- schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 3, true);
- CheckLoop(order, loop1->nodes, loop1->count);
-}
-
-
-TEST_F(SchedulerRPOTest, EndLoopNested) {
- Schedule schedule(zone());
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
- schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 3, true);
- CheckLoop(order, loop1->nodes, loop1->count);
-}
-
-
-TEST_F(SchedulerRPOTest, Diamond) {
- Schedule schedule(zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(A, C);
- schedule.AddSuccessorForTesting(B, D);
- schedule.AddSuccessorForTesting(C, D);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 4, false);
-
- EXPECT_EQ(0, A->rpo_number());
- EXPECT_THAT(B->rpo_number(), AnyOf(1, 2));
- EXPECT_THAT(C->rpo_number(), AnyOf(1, 2));
- EXPECT_EQ(3, D->rpo_number());
-}
-
-
-TEST_F(SchedulerRPOTest, Loop1) {
- Schedule schedule(zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, B);
- schedule.AddSuccessorForTesting(C, D);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 4, true);
- BasicBlock* loop[] = {B, C};
- CheckLoop(order, loop, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, Loop2) {
- Schedule schedule(zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, B);
- schedule.AddSuccessorForTesting(B, D);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 4, true);
- BasicBlock* loop[] = {B, C};
- CheckLoop(order, loop, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopN) {
- for (int i = 0; i < 11; i++) {
- Schedule schedule(zone());
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.NewBasicBlock();
- BasicBlock* G = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, D);
- schedule.AddSuccessorForTesting(D, E);
- schedule.AddSuccessorForTesting(E, F);
- schedule.AddSuccessorForTesting(F, B);
- schedule.AddSuccessorForTesting(B, G);
-
- // Throw in extra backedges from time to time.
- if (i == 1) schedule.AddSuccessorForTesting(B, B);
- if (i == 2) schedule.AddSuccessorForTesting(C, B);
- if (i == 3) schedule.AddSuccessorForTesting(D, B);
- if (i == 4) schedule.AddSuccessorForTesting(E, B);
- if (i == 5) schedule.AddSuccessorForTesting(F, B);
-
- // Throw in extra loop exits from time to time.
- if (i == 6) schedule.AddSuccessorForTesting(B, G);
- if (i == 7) schedule.AddSuccessorForTesting(C, G);
- if (i == 8) schedule.AddSuccessorForTesting(D, G);
- if (i == 9) schedule.AddSuccessorForTesting(E, G);
- if (i == 10) schedule.AddSuccessorForTesting(F, G);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 7, true);
- BasicBlock* loop[] = {B, C, D, E, F};
- CheckLoop(order, loop, 5);
- }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopNest1) {
- Schedule schedule(zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, D);
- schedule.AddSuccessorForTesting(D, C);
- schedule.AddSuccessorForTesting(D, E);
- schedule.AddSuccessorForTesting(E, B);
- schedule.AddSuccessorForTesting(E, F);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 6, true);
- BasicBlock* loop1[] = {B, C, D, E};
- CheckLoop(order, loop1, 4);
-
- BasicBlock* loop2[] = {C, D};
- CheckLoop(order, loop2, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopNest2) {
- Schedule schedule(zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.NewBasicBlock();
- BasicBlock* G = schedule.NewBasicBlock();
- BasicBlock* H = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, D);
- schedule.AddSuccessorForTesting(D, E);
- schedule.AddSuccessorForTesting(E, F);
- schedule.AddSuccessorForTesting(F, G);
- schedule.AddSuccessorForTesting(G, H);
-
- schedule.AddSuccessorForTesting(E, D);
- schedule.AddSuccessorForTesting(F, C);
- schedule.AddSuccessorForTesting(G, B);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 8, true);
- BasicBlock* loop1[] = {B, C, D, E, F, G};
- CheckLoop(order, loop1, 6);
-
- BasicBlock* loop2[] = {C, D, E, F};
- CheckLoop(order, loop2, 4);
-
- BasicBlock* loop3[] = {D, E};
- CheckLoop(order, loop3, 2);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopFollow1) {
- Schedule schedule(zone());
-
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
- base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
- schedule.AddSuccessorForTesting(loop2->last(), E);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
- EXPECT_EQ(schedule.BasicBlockCount(), order->size());
- CheckLoop(order, loop1->nodes, loop1->count);
- CheckLoop(order, loop2->nodes, loop2->count);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopFollow2) {
- Schedule schedule(zone());
-
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
- base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
- BasicBlock* A = schedule.start();
- BasicBlock* S = schedule.NewBasicBlock();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->header(), S);
- schedule.AddSuccessorForTesting(S, loop2->header());
- schedule.AddSuccessorForTesting(loop2->last(), E);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
- EXPECT_EQ(schedule.BasicBlockCount(), order->size());
- CheckLoop(order, loop1->nodes, loop1->count);
- CheckLoop(order, loop2->nodes, loop2->count);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopFollowN) {
- for (int size = 1; size < 5; size++) {
- for (int exit = 0; exit < size; exit++) {
- Schedule schedule(zone());
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header());
- schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
- EXPECT_EQ(schedule.BasicBlockCount(), order->size());
- CheckLoop(order, loop1->nodes, loop1->count);
- CheckLoop(order, loop2->nodes, loop2->count);
- }
- }
-}
-
-
-TEST_F(SchedulerRPOTest, NestedLoopFollow1) {
- Schedule schedule(zone());
-
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
- base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, loop1->header());
- schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
- schedule.AddSuccessorForTesting(loop2->last(), C);
- schedule.AddSuccessorForTesting(C, E);
- schedule.AddSuccessorForTesting(C, B);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
-
- EXPECT_EQ(schedule.BasicBlockCount(), order->size());
- CheckLoop(order, loop1->nodes, loop1->count);
- CheckLoop(order, loop2->nodes, loop2->count);
-
- BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
- CheckLoop(order, loop3, 4);
-}
-
-
-TEST_F(SchedulerRPOTest, LoopBackedges1) {
- int size = 8;
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- Schedule schedule(zone());
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
- schedule.AddSuccessorForTesting(loop1->nodes[j], E);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoop(order, loop1->nodes, loop1->count);
- }
- }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopOutedges1) {
- int size = 8;
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- Schedule schedule(zone());
- BasicBlock* A = schedule.start();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.end();
-
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
- schedule.AddSuccessorForTesting(loop1->nodes[j], D);
- schedule.AddSuccessorForTesting(D, E);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoop(order, loop1->nodes, loop1->count);
- }
- }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopOutedges2) {
- int size = 8;
- for (int i = 0; i < size; i++) {
- Schedule schedule(zone());
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- for (int j = 0; j < size; j++) {
- BasicBlock* O = schedule.NewBasicBlock();
- schedule.AddSuccessorForTesting(loop1->nodes[j], O);
- schedule.AddSuccessorForTesting(O, E);
- }
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoop(order, loop1->nodes, loop1->count);
- }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopOutloops1) {
- int size = 8;
- for (int i = 0; i < size; i++) {
- Schedule schedule(zone());
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
- base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- TestLoop** loopN = new TestLoop* [size];
- for (int j = 0; j < size; j++) {
- loopN[j] = CreateLoop(&schedule, 2);
- schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header());
- schedule.AddSuccessorForTesting(loopN[j]->last(), E);
- }
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoop(order, loop1->nodes, loop1->count);
-
- for (int j = 0; j < size; j++) {
- CheckLoop(order, loopN[j]->nodes, loopN[j]->count);
- delete loopN[j];
- }
- delete[] loopN;
- }
-}
-
-
-TEST_F(SchedulerRPOTest, LoopMultibackedge) {
- Schedule schedule(zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(B, D);
- schedule.AddSuccessorForTesting(B, E);
- schedule.AddSuccessorForTesting(C, B);
- schedule.AddSuccessorForTesting(D, B);
- schedule.AddSuccessorForTesting(E, B);
-
- BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
- CheckRPONumbers(order, 5, true);
-
- BasicBlock* loop1[] = {B, C, D, E};
- CheckLoop(order, loop1, 4);
-}
-
-
-// -----------------------------------------------------------------------------
-// Graph end-to-end scheduling.
-
-
TEST_F(SchedulerTest, BuildScheduleEmpty) {
graph()->SetStart(graph()->NewNode(common()->Start(0)));
graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
diff --git a/test/unittests/compiler/simplified-operator-unittest.cc b/test/unittests/compiler/simplified-operator-unittest.cc
index 871189a..bd8509f 100644
--- a/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/test/unittests/compiler/simplified-operator-unittest.cc
@@ -6,7 +6,7 @@
#include "src/compiler/operator.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/simplified-operator.h"
-#include "src/types-inl.h"
+#include "src/types.h"
#include "test/unittests/test-utils.h"
namespace v8 {
@@ -65,6 +65,8 @@
PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
PURE(ChangeBitToBool, Operator::kNoProperties, 1),
+ PURE(ObjectIsNumber, Operator::kNoProperties, 1),
+ PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
PURE(ObjectIsSmi, Operator::kNoProperties, 1)
#undef PURE
};
diff --git a/test/unittests/compiler/typer-unittest.cc b/test/unittests/compiler/typer-unittest.cc
index 6e4d4d5..9d664a6 100644
--- a/test/unittests/compiler/typer-unittest.cc
+++ b/test/unittests/compiler/typer-unittest.cc
@@ -49,7 +49,7 @@
}
}
- Types<Type, Type*, Zone> types_;
+ Types types_;
JSOperatorBuilder javascript_;
BinaryOperationHints const hints_ = BinaryOperationHints::Any();
Node* context_node_;
@@ -115,7 +115,7 @@
return result;
}
- double RandomInt(Type::RangeType* range) {
+ double RandomInt(RangeType* range) {
return RandomInt(range->Min(), range->Max());
}
@@ -149,12 +149,12 @@
void TestBinaryArithOp(const Operator* op, BinaryFunction opfun) {
TestBinaryArithOpCloseToZero(op, opfun, 8);
for (int i = 0; i < 100; ++i) {
- Type::RangeType* r1 = RandomRange()->AsRange();
- Type::RangeType* r2 = RandomRange()->AsRange();
+ Type* r1 = RandomRange();
+ Type* r2 = RandomRange();
Type* expected_type = TypeBinaryOp(op, r1, r2);
for (int i = 0; i < 10; i++) {
- double x1 = RandomInt(r1);
- double x2 = RandomInt(r2);
+ double x1 = RandomInt(r1->AsRange());
+ double x2 = RandomInt(r2->AsRange());
double result_value = opfun(x1, x2);
Type* result_type = Type::Constant(
isolate()->factory()->NewNumber(result_value), zone());
@@ -166,12 +166,12 @@
template <class BinaryFunction>
void TestBinaryCompareOp(const Operator* op, BinaryFunction opfun) {
for (int i = 0; i < 100; ++i) {
- Type::RangeType* r1 = RandomRange()->AsRange();
- Type::RangeType* r2 = RandomRange()->AsRange();
+ Type* r1 = RandomRange();
+ Type* r2 = RandomRange();
Type* expected_type = TypeBinaryOp(op, r1, r2);
for (int i = 0; i < 10; i++) {
- double x1 = RandomInt(r1);
- double x2 = RandomInt(r2);
+ double x1 = RandomInt(r1->AsRange());
+ double x2 = RandomInt(r2->AsRange());
bool result_value = opfun(x1, x2);
Type* result_type =
Type::Constant(result_value ? isolate()->factory()->true_value()
@@ -185,12 +185,12 @@
template <class BinaryFunction>
void TestBinaryBitOp(const Operator* op, BinaryFunction opfun) {
for (int i = 0; i < 100; ++i) {
- Type::RangeType* r1 = RandomRange(true)->AsRange();
- Type::RangeType* r2 = RandomRange(true)->AsRange();
+ Type* r1 = RandomRange(true);
+ Type* r2 = RandomRange(true);
Type* expected_type = TypeBinaryOp(op, r1, r2);
for (int i = 0; i < 10; i++) {
- int32_t x1 = static_cast<int32_t>(RandomInt(r1));
- int32_t x2 = static_cast<int32_t>(RandomInt(r2));
+ int32_t x1 = static_cast<int32_t>(RandomInt(r1->AsRange()));
+ int32_t x2 = static_cast<int32_t>(RandomInt(r2->AsRange()));
double result_value = opfun(x1, x2);
Type* result_type = Type::Constant(
isolate()->factory()->NewNumber(result_value), zone());
@@ -240,109 +240,72 @@
TEST_F(TyperTest, TypeJSAdd) {
- TestBinaryArithOp(javascript_.Add(LanguageMode::SLOPPY, hints_),
- std::plus<double>());
- TestBinaryArithOp(javascript_.Add(LanguageMode::STRONG, hints_),
- std::plus<double>());
+ TestBinaryArithOp(javascript_.Add(hints_), std::plus<double>());
}
TEST_F(TyperTest, TypeJSSubtract) {
- TestBinaryArithOp(javascript_.Subtract(LanguageMode::SLOPPY, hints_),
- std::minus<double>());
- TestBinaryArithOp(javascript_.Subtract(LanguageMode::STRONG, hints_),
- std::minus<double>());
+ TestBinaryArithOp(javascript_.Subtract(hints_), std::minus<double>());
}
TEST_F(TyperTest, TypeJSMultiply) {
- TestBinaryArithOp(javascript_.Multiply(LanguageMode::SLOPPY, hints_),
- std::multiplies<double>());
- TestBinaryArithOp(javascript_.Multiply(LanguageMode::STRONG, hints_),
- std::multiplies<double>());
+ TestBinaryArithOp(javascript_.Multiply(hints_), std::multiplies<double>());
}
TEST_F(TyperTest, TypeJSDivide) {
- TestBinaryArithOp(javascript_.Divide(LanguageMode::SLOPPY, hints_),
- std::divides<double>());
- TestBinaryArithOp(javascript_.Divide(LanguageMode::STRONG, hints_),
- std::divides<double>());
+ TestBinaryArithOp(javascript_.Divide(hints_), std::divides<double>());
}
TEST_F(TyperTest, TypeJSModulus) {
- TestBinaryArithOp(javascript_.Modulus(LanguageMode::SLOPPY, hints_), modulo);
- TestBinaryArithOp(javascript_.Modulus(LanguageMode::STRONG, hints_), modulo);
+ TestBinaryArithOp(javascript_.Modulus(hints_), modulo);
}
TEST_F(TyperTest, TypeJSBitwiseOr) {
- TestBinaryBitOp(javascript_.BitwiseOr(LanguageMode::SLOPPY, hints_), bit_or);
- TestBinaryBitOp(javascript_.BitwiseOr(LanguageMode::STRONG, hints_), bit_or);
+ TestBinaryBitOp(javascript_.BitwiseOr(hints_), bit_or);
}
TEST_F(TyperTest, TypeJSBitwiseAnd) {
- TestBinaryBitOp(javascript_.BitwiseAnd(LanguageMode::SLOPPY, hints_),
- bit_and);
- TestBinaryBitOp(javascript_.BitwiseAnd(LanguageMode::STRONG, hints_),
- bit_and);
+ TestBinaryBitOp(javascript_.BitwiseAnd(hints_), bit_and);
}
TEST_F(TyperTest, TypeJSBitwiseXor) {
- TestBinaryBitOp(javascript_.BitwiseXor(LanguageMode::SLOPPY, hints_),
- bit_xor);
- TestBinaryBitOp(javascript_.BitwiseXor(LanguageMode::STRONG, hints_),
- bit_xor);
+ TestBinaryBitOp(javascript_.BitwiseXor(hints_), bit_xor);
}
TEST_F(TyperTest, TypeJSShiftLeft) {
- TestBinaryBitOp(javascript_.ShiftLeft(LanguageMode::SLOPPY, hints_),
- shift_left);
- TestBinaryBitOp(javascript_.ShiftLeft(LanguageMode::STRONG, hints_),
- shift_left);
+ TestBinaryBitOp(javascript_.ShiftLeft(hints_), shift_left);
}
TEST_F(TyperTest, TypeJSShiftRight) {
- TestBinaryBitOp(javascript_.ShiftRight(LanguageMode::SLOPPY, hints_),
- shift_right);
- TestBinaryBitOp(javascript_.ShiftRight(LanguageMode::STRONG, hints_),
- shift_right);
+ TestBinaryBitOp(javascript_.ShiftRight(hints_), shift_right);
}
TEST_F(TyperTest, TypeJSLessThan) {
- TestBinaryCompareOp(javascript_.LessThan(LanguageMode::SLOPPY),
- std::less<double>());
- TestBinaryCompareOp(javascript_.LessThan(LanguageMode::STRONG),
- std::less<double>());
+ TestBinaryCompareOp(javascript_.LessThan(), std::less<double>());
}
TEST_F(TyperTest, TypeJSLessThanOrEqual) {
- TestBinaryCompareOp(javascript_.LessThanOrEqual(LanguageMode::SLOPPY),
- std::less_equal<double>());
- TestBinaryCompareOp(javascript_.LessThanOrEqual(LanguageMode::STRONG),
- std::less_equal<double>());
+ TestBinaryCompareOp(javascript_.LessThanOrEqual(), std::less_equal<double>());
}
TEST_F(TyperTest, TypeJSGreaterThan) {
- TestBinaryCompareOp(javascript_.GreaterThan(LanguageMode::SLOPPY),
- std::greater<double>());
- TestBinaryCompareOp(javascript_.GreaterThan(LanguageMode::STRONG),
- std::greater<double>());
+ TestBinaryCompareOp(javascript_.GreaterThan(), std::greater<double>());
}
TEST_F(TyperTest, TypeJSGreaterThanOrEqual) {
- TestBinaryCompareOp(javascript_.GreaterThanOrEqual(LanguageMode::SLOPPY),
- std::greater_equal<double>());
- TestBinaryCompareOp(javascript_.GreaterThanOrEqual(LanguageMode::STRONG),
+ TestBinaryCompareOp(javascript_.GreaterThanOrEqual(),
std::greater_equal<double>());
}
@@ -381,27 +344,15 @@
TEST_BINARY_MONOTONICITY(NotEqual)
TEST_BINARY_MONOTONICITY(StrictEqual)
TEST_BINARY_MONOTONICITY(StrictNotEqual)
-#undef TEST_BINARY_MONOTONICITY
-
-
-#define TEST_BINARY_MONOTONICITY(name) \
- TEST_F(TyperTest, Monotonicity_##name) { \
- TestBinaryMonotonicity(javascript_.name(LanguageMode::SLOPPY)); \
- TestBinaryMonotonicity(javascript_.name(LanguageMode::STRONG)); \
- }
TEST_BINARY_MONOTONICITY(LessThan)
TEST_BINARY_MONOTONICITY(GreaterThan)
TEST_BINARY_MONOTONICITY(LessThanOrEqual)
TEST_BINARY_MONOTONICITY(GreaterThanOrEqual)
#undef TEST_BINARY_MONOTONICITY
-
-#define TEST_BINARY_MONOTONICITY(name) \
- TEST_F(TyperTest, Monotonicity_##name) { \
- TestBinaryMonotonicity( \
- javascript_.name(LanguageMode::SLOPPY, BinaryOperationHints::Any())); \
- TestBinaryMonotonicity( \
- javascript_.name(LanguageMode::STRONG, BinaryOperationHints::Any())); \
+#define TEST_BINARY_MONOTONICITY(name) \
+ TEST_F(TyperTest, Monotonicity_##name) { \
+ TestBinaryMonotonicity(javascript_.name(BinaryOperationHints::Any())); \
}
TEST_BINARY_MONOTONICITY(BitwiseOr)
TEST_BINARY_MONOTONICITY(BitwiseXor)