summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2016-04-07 14:06:55 -0700
committerAli Ijaz Sheikh <ofrobots@google.com>2016-04-14 10:03:39 -0700
commit52af5c4eebf4de8638aef0338bd826656312a02a (patch)
tree628dc9fb0b558c3a73a2160706fef368876fe548 /deps/v8/test/unittests
parent6e3e8acc7cc7ebd3d67db5ade1247b8b558efe09 (diff)
downloadandroid-node-v8-52af5c4eebf4de8638aef0338bd826656312a02a.tar.gz
android-node-v8-52af5c4eebf4de8638aef0338bd826656312a02a.tar.bz2
android-node-v8-52af5c4eebf4de8638aef0338bd826656312a02a.zip
deps: upgrade V8 to 5.0.71.32
* Pick up the branch head for V8 5.0 stable [1] * Edit v8 gitignore to allow trace_event copy * Update V8 DEP trace_event as per deps/v8/DEPS [2] [1] https://chromium.googlesource.com/v8/v8.git/+/3c67831 [2] https://chromium.googlesource.com/chromium/src/base/trace_event/common/+/4b09207e447ae5bd34643b4c6321bee7b76d35f9 Ref: https://github.com/nodejs/node/pull/5945 PR-URL: https://github.com/nodejs/node/pull/6111 Reviewed-By: targos - Michaƫl Zasso <mic.besace@gmail.com> Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: indutny - Fedor Indutny <fedor.indutny@gmail.com>
Diffstat (limited to 'deps/v8/test/unittests')
-rw-r--r--deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc99
-rw-r--r--deps/v8/test/unittests/compiler/escape-analysis-unittest.cc164
-rw-r--r--deps/v8/test/unittests/compiler/instruction-selector-unittest.cc4
-rw-r--r--deps/v8/test/unittests/compiler/instruction-selector-unittest.h45
-rw-r--r--deps/v8/test/unittests/compiler/int64-lowering-unittest.cc299
-rw-r--r--deps/v8/test/unittests/compiler/interpreter-assembler-unittest.h57
-rw-r--r--deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc109
-rw-r--r--deps/v8/test/unittests/compiler/js-context-relaxation-unittest.cc285
-rw-r--r--deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc236
-rw-r--r--deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc133
-rw-r--r--deps/v8/test/unittests/compiler/js-operator-unittest.cc150
-rw-r--r--deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc515
-rw-r--r--deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/move-optimizer-unittest.cc97
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.cc42
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.h10
-rw-r--r--deps/v8/test/unittests/compiler/scheduler-rpo-unittest.cc533
-rw-r--r--deps/v8/test/unittests/compiler/scheduler-unittest.cc546
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-unittest.cc4
-rw-r--r--deps/v8/test/unittests/compiler/typer-unittest.cc111
-rw-r--r--deps/v8/test/unittests/heap/memory-reducer-unittest.cc11
-rw-r--r--deps/v8/test/unittests/heap/slot-set-unittest.cc143
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc289
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc17
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-register-allocator-unittest.cc218
-rw-r--r--deps/v8/test/unittests/interpreter/bytecodes-unittest.cc135
-rw-r--r--deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc11
-rw-r--r--deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.cc (renamed from deps/v8/test/unittests/compiler/interpreter-assembler-unittest.cc)385
-rw-r--r--deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.h57
-rw-r--r--deps/v8/test/unittests/interpreter/register-translator-unittest.cc260
-rw-r--r--deps/v8/test/unittests/unittests.gyp11
-rw-r--r--deps/v8/test/unittests/wasm/ast-decoder-unittest.cc319
-rw-r--r--deps/v8/test/unittests/wasm/encoder-unittest.cc20
-rw-r--r--deps/v8/test/unittests/wasm/loop-assignment-analysis-unittest.cc211
-rw-r--r--deps/v8/test/unittests/wasm/module-decoder-unittest.cc287
-rw-r--r--deps/v8/test/unittests/wasm/wasm-macro-gen-unittest.cc14
36 files changed, 3412 insertions, 2417 deletions
diff --git a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 62abeda1b5..72cfc51d58 100644
--- a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -1584,7 +1584,7 @@ TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) {
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 @@ TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) {
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, Uint32ModWithParametersForSUDIVAndMLS) {
}
+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 @@ TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
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, Word32AndWithUbfxImmediateForARMv7) {
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 @@ 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.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
@@ -2828,8 +2849,11 @@ TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
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 @@ TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
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, Word32AndWithWord32ShrWithImmediateForARMv7) {
}
+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/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc b/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc
index b088367a58..d5e12ba0db 100644
--- a/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc
+++ b/deps/v8/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 @@ class EscapeAnalysisTest : public GraphTest {
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 @@ class EscapeAnalysisTest : public GraphTest {
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 @@ class EscapeAnalysisTest : public GraphTest {
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
Node* effect() { return effect_; }
+ Node* control() { return control_; }
private:
SimplifiedOperatorBuilder simplified_;
@@ -185,9 +206,9 @@ TEST_F(EscapeAnalysisTest, StraightNonEscape) {
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, StraightNonEscape) {
}
+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 @@ TEST_F(EscapeAnalysisTest, StoreLoadEscape) {
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 @@ TEST_F(EscapeAnalysisTest, BranchNonEscape) {
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, BranchNonEscape) {
}
+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 @@ TEST_F(EscapeAnalysisTest, DeoptReplacement) {
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 @@ TEST_F(EscapeAnalysisTest, DeoptReplacement) {
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 @@ TEST_F(EscapeAnalysisTest, DeoptReplacementIdentity) {
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 @@ TEST_F(EscapeAnalysisTest, DeoptReplacementIdentity) {
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/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
index 89c0a654e9..16030f80d7 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
@@ -40,7 +40,7 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
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 @@ InstructionSelectorTest::StreamBuilder::GetFrameStateFunctionInfo(
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/deps/v8/test/unittests/compiler/instruction-selector-unittest.h b/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
index fc7c144939..f1397faa06 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
+++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
@@ -92,7 +92,7 @@ class InstructionSelectorTest : public TestWithContext,
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 @@ class InstructionSelectorTest : public TestWithContext,
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 @@ class InstructionSelectorTest : public TestWithContext,
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 @@ class InstructionSelectorTest : public TestWithContext,
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/deps/v8/test/unittests/compiler/int64-lowering-unittest.cc b/deps/v8/test/unittests/compiler/int64-lowering-unittest.cc
new file mode 100644
index 0000000000..eff6d4a931
--- /dev/null
+++ b/deps/v8/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/deps/v8/test/unittests/compiler/interpreter-assembler-unittest.h b/deps/v8/test/unittests/compiler/interpreter-assembler-unittest.h
deleted file mode 100644
index 15fa38b1be..0000000000
--- a/deps/v8/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/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
index 78e9253a17..9e14cda7fb 100644
--- a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -64,10 +64,6 @@ Type* const kIntegral32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
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 @@ TEST_F(JSBuiltinReducerTest, MathMax0) {
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 @@ TEST_F(JSBuiltinReducerTest, MathMax1) {
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 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
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);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsSelect(MachineRepresentation::kNone,
- IsNumberLessThan(p1, p0), p0, p1));
- }
+ 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));
}
}
}
@@ -162,20 +149,17 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
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);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsInt32Mul(p0, p1));
- }
+ 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));
}
}
}
@@ -192,18 +176,15 @@ TEST_F(JSBuiltinReducerTest, MathFround) {
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/deps/v8/test/unittests/compiler/js-context-relaxation-unittest.cc b/deps/v8/test/unittests/compiler/js-context-relaxation-unittest.cc
deleted file mode 100644
index a44bd0278d..0000000000
--- a/deps/v8/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/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
new file mode 100644
index 0000000000..837c5742d9
--- /dev/null
+++ b/deps/v8/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/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index f38f8eaac7..919c1b2237 100644
--- a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/deps/v8/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 v8 {
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 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
// -----------------------------------------------------------------------------
-// %_IsDate
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineIsDate) {
- Node* const input = Parameter(0);
- Node* const context = Parameter(1);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(
- graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsDate, 1),
- input, context, effect, control));
- ASSERT_TRUE(r.Changed());
-
- Node* phi = r.replacement();
- Capture<Node*> branch, if_false;
- EXPECT_THAT(
- phi,
- IsPhi(
- 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 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) {
// -----------------------------------------------------------------------------
-// %_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 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsRegExp) {
// %_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/deps/v8/test/unittests/compiler/js-operator-unittest.cc b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
index e0db771458..15b1427871 100644
--- a/deps/v8/test/unittests/compiler/js-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
@@ -12,34 +12,8 @@ namespace v8 {
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 @@ struct SharedOperator {
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 @@ const SharedOperator kSharedOperators[] = {
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 @@ TEST_P(JSSharedOperatorTest, Properties) {
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/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
index 6fc89bb0ea..e37d4a2913 100644
--- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -92,18 +92,6 @@ class JSTypedLoweringTest : public TypedGraphTest {
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 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
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 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
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 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
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 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
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 @@ TEST_F(JSTypedLoweringTest,
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 @@ TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) {
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 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
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());
-
- 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));
+ Handle<JSTypedArray> array =
+ factory()->NewJSTypedArray(type, buffer, 0, kLength);
+ int const element_size = static_cast<int>(array->element_size());
+
+ Node* key = Parameter(
+ Type::Range(kMinInt / element_size, kMaxInt / element_size, zone()));
+ Node* base = HeapConstant(array);
+ Node* vector = UndefinedConstant();
+ Node* context = UndefinedConstant();
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->LoadProperty(feedback), 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 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
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);
-
- 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));
+ 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(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 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) {
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 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedFunctionPrototype) {
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, JSLoadNamedFunctionPrototype) {
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 @@ TEST_F(JSTypedLoweringTest, JSAddWithString) {
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/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
index b77830aa5e..efc823dba6 100644
--- a/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc
@@ -61,7 +61,7 @@ class LivenessAnalysisTest : public GraphTest {
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/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc b/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc
index 413c58b6fe..5ccd0c6727 100644
--- a/deps/v8/test/unittests/compiler/move-optimizer-unittest.cc
+++ b/deps/v8/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 @@ TEST_F(MoveOptimizerTest, GapsCanMoveOverInstruction) {
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, GapsCanMoveOverInstruction) {
}
+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/deps/v8/test/unittests/compiler/node-test-utils.cc b/deps/v8/test/unittests/compiler/node-test-utils.cc
index 54168ee70b..ee4cf5446e 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.cc
+++ b/deps/v8/test/unittests/compiler/node-test-utils.cc
@@ -323,13 +323,30 @@ class IsReturnMatcher final : public NodeMatcher {
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 @@ class IsReturnMatcher final : public NodeMatcher {
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 @@ class IsReturnMatcher final : public NodeMatcher {
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 @@ Matcher<Node*> IsDead() {
return MakeMatcher(new NodeMatcher(IrOpcode::kDead));
}
-
Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher) {
return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control0_matcher));
}
@@ -1577,6 +1598,13 @@ Matcher<Node*> IsReturn(const Matcher<Node*>& value_matcher,
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 @@ Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
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(Float64ExtractLowWord32)
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/deps/v8/test/unittests/compiler/node-test-utils.h b/deps/v8/test/unittests/compiler/node-test-utils.h
index 8592f30566..03f2a3b88f 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.h
+++ b/deps/v8/test/unittests/compiler/node-test-utils.h
@@ -17,11 +17,8 @@ class ExternalReference;
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*> IsFinishRegion(const Matcher<Node*>& value_matcher,
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 @@ Matcher<Node*> IsStoreElement(const Matcher<ElementAccess>& access_matcher,
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/deps/v8/test/unittests/compiler/scheduler-rpo-unittest.cc b/deps/v8/test/unittests/compiler/scheduler-rpo-unittest.cc
new file mode 100644
index 0000000000..713ee6e742
--- /dev/null
+++ b/deps/v8/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/deps/v8/test/unittests/compiler/scheduler-unittest.cc b/deps/v8/test/unittests/compiler/scheduler-unittest.cc
index 523c8ce9d4..6cf07345a2 100644
--- a/deps/v8/test/unittests/compiler/scheduler-unittest.cc
+++ b/deps/v8/test/unittests/compiler/scheduler-unittest.cc
@@ -71,67 +71,6 @@ class SchedulerTest : public TestWithIsolateAndZone {
};
-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 @@ const Operator kMockTailCall(IrOpcode::kTailCall, Operator::kNoProperties,
} // 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/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
index 871189ad79..bd8509ff97 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/deps/v8/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 @@ const PureOperator kPureOperators[] = {
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/deps/v8/test/unittests/compiler/typer-unittest.cc b/deps/v8/test/unittests/compiler/typer-unittest.cc
index 6e4d4d589f..9d664a6d3a 100644
--- a/deps/v8/test/unittests/compiler/typer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/typer-unittest.cc
@@ -49,7 +49,7 @@ class TyperTest : public TypedGraphTest {
}
}
- Types<Type, Type*, Zone> types_;
+ Types types_;
JSOperatorBuilder javascript_;
BinaryOperationHints const hints_ = BinaryOperationHints::Any();
Node* context_node_;
@@ -115,7 +115,7 @@ class TyperTest : public TypedGraphTest {
return result;
}
- double RandomInt(Type::RangeType* range) {
+ double RandomInt(RangeType* range) {
return RandomInt(range->Min(), range->Max());
}
@@ -149,12 +149,12 @@ class TyperTest : public TypedGraphTest {
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 @@ class TyperTest : public TypedGraphTest {
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 @@ class TyperTest : public TypedGraphTest {
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 @@ int32_t bit_xor(int32_t x, int32_t y) { return x ^ y; }
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(Equal)
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)
diff --git a/deps/v8/test/unittests/heap/memory-reducer-unittest.cc b/deps/v8/test/unittests/heap/memory-reducer-unittest.cc
index 1088f0127d..4787bc66d2 100644
--- a/deps/v8/test/unittests/heap/memory-reducer-unittest.cc
+++ b/deps/v8/test/unittests/heap/memory-reducer-unittest.cc
@@ -74,10 +74,9 @@ MemoryReducer::Event TimerEventPendingGC(double time_ms) {
return TimerEvent(time_ms, true, false);
}
-
-MemoryReducer::Event ContextDisposedEvent(double time_ms) {
+MemoryReducer::Event PossibleGarbageEvent(double time_ms) {
MemoryReducer::Event event;
- event.type = MemoryReducer::kContextDisposed;
+ event.type = MemoryReducer::kPossibleGarbage;
event.time_ms = time_ms;
return event;
}
@@ -114,7 +113,7 @@ TEST(MemoryReducer, FromDoneToWait) {
EXPECT_EQ(0, state1.started_gcs);
EXPECT_EQ(2, state1.last_gc_time_ms);
- state1 = MemoryReducer::Step(state0, ContextDisposedEvent(0));
+ state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(0));
EXPECT_EQ(MemoryReducer::kWait, state1.action);
EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms);
EXPECT_EQ(0, state1.started_gcs);
@@ -127,7 +126,7 @@ TEST(MemoryReducer, FromWaitToWait) {
MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState());
- state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
+ state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000));
EXPECT_EQ(MemoryReducer::kWait, state1.action);
EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
EXPECT_EQ(state0.started_gcs, state1.started_gcs);
@@ -250,7 +249,7 @@ TEST(MemoryReducer, FromRunToRun) {
EXPECT_EQ(state0.started_gcs, state1.started_gcs);
EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms);
- state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000));
+ state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000));
EXPECT_EQ(MemoryReducer::kRun, state1.action);
EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms);
EXPECT_EQ(state0.started_gcs, state1.started_gcs);
diff --git a/deps/v8/test/unittests/heap/slot-set-unittest.cc b/deps/v8/test/unittests/heap/slot-set-unittest.cc
new file mode 100644
index 0000000000..376188915a
--- /dev/null
+++ b/deps/v8/test/unittests/heap/slot-set-unittest.cc
@@ -0,0 +1,143 @@
+// 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 <limits>
+
+#include "src/globals.h"
+#include "src/heap/slot-set.h"
+#include "src/heap/spaces.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+
+TEST(SlotSet, InsertAndLookup1) {
+ SlotSet set;
+ set.SetPageStart(0);
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ EXPECT_FALSE(set.Lookup(i));
+ }
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ set.Insert(i);
+ }
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ EXPECT_TRUE(set.Lookup(i));
+ }
+}
+
+TEST(SlotSet, InsertAndLookup2) {
+ SlotSet set;
+ set.SetPageStart(0);
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 7 == 0) {
+ set.Insert(i);
+ }
+ }
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 7 == 0) {
+ EXPECT_TRUE(set.Lookup(i));
+ } else {
+ EXPECT_FALSE(set.Lookup(i));
+ }
+ }
+}
+
+TEST(SlotSet, Iterate) {
+ SlotSet set;
+ set.SetPageStart(0);
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 7 == 0) {
+ set.Insert(i);
+ }
+ }
+
+ set.Iterate([](Address slot_address) {
+ uintptr_t intaddr = reinterpret_cast<uintptr_t>(slot_address);
+ if (intaddr % 3 == 0) {
+ return SlotSet::KEEP_SLOT;
+ } else {
+ return SlotSet::REMOVE_SLOT;
+ }
+ });
+
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 21 == 0) {
+ EXPECT_TRUE(set.Lookup(i));
+ } else {
+ EXPECT_FALSE(set.Lookup(i));
+ }
+ }
+}
+
+TEST(SlotSet, Remove) {
+ SlotSet set;
+ set.SetPageStart(0);
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 7 == 0) {
+ set.Insert(i);
+ }
+ }
+
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 3 != 0) {
+ set.Remove(i);
+ }
+ }
+
+ for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ if (i % 21 == 0) {
+ EXPECT_TRUE(set.Lookup(i));
+ } else {
+ EXPECT_FALSE(set.Lookup(i));
+ }
+ }
+}
+
+void CheckRemoveRangeOn(uint32_t start, uint32_t end) {
+ SlotSet set;
+ set.SetPageStart(0);
+ uint32_t first = start == 0 ? 0 : start - kPointerSize;
+ uint32_t last = end == Page::kPageSize ? end - kPointerSize : end;
+ for (uint32_t i = first; i <= last; i += kPointerSize) {
+ set.Insert(i);
+ }
+ set.RemoveRange(start, end);
+ if (first != start) {
+ EXPECT_TRUE(set.Lookup(first));
+ }
+ if (last == end) {
+ EXPECT_TRUE(set.Lookup(last));
+ }
+ for (uint32_t i = start; i < end; i += kPointerSize) {
+ EXPECT_FALSE(set.Lookup(i));
+ }
+}
+
+TEST(SlotSet, RemoveRange) {
+ CheckRemoveRangeOn(0, Page::kPageSize);
+ CheckRemoveRangeOn(1 * kPointerSize, 1023 * kPointerSize);
+ for (uint32_t start = 0; start <= 32; start++) {
+ CheckRemoveRangeOn(start * kPointerSize, (start + 1) * kPointerSize);
+ CheckRemoveRangeOn(start * kPointerSize, (start + 2) * kPointerSize);
+ const uint32_t kEnds[] = {32, 64, 100, 128, 1024, 1500, 2048};
+ for (int i = 0; i < sizeof(kEnds) / sizeof(uint32_t); i++) {
+ for (int k = -3; k <= 3; k++) {
+ uint32_t end = (kEnds[i] + k);
+ if (start < end) {
+ CheckRemoveRangeOn(start * kPointerSize, end * kPointerSize);
+ }
+ }
+ }
+ }
+ SlotSet set;
+ set.SetPageStart(0);
+ set.Insert(Page::kPageSize / 2);
+ set.RemoveRange(0, Page::kPageSize);
+ for (uint32_t i = 0; i < Page::kPageSize; i += kPointerSize) {
+ EXPECT_FALSE(set.Lookup(i));
+ }
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc
index 2140aa83c7..839215f743 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc
@@ -21,14 +21,16 @@ class BytecodeArrayBuilderTest : public TestWithIsolateAndZone {
TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
- BytecodeArrayBuilder builder(isolate(), zone());
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
- builder.set_locals_count(200);
- builder.set_context_count(1);
- builder.set_parameter_count(0);
- CHECK_EQ(builder.locals_count(), 200);
+ CHECK_EQ(builder.locals_count(), 131);
CHECK_EQ(builder.context_count(), 1);
- CHECK_EQ(builder.fixed_register_count(), 201);
+ CHECK_EQ(builder.fixed_register_count(), 132);
+
+ // Emit argument creation operations.
+ builder.CreateArguments(CreateArgumentsType::kMappedArguments)
+ .CreateArguments(CreateArgumentsType::kUnmappedArguments)
+ .CreateArguments(CreateArgumentsType::kRestParameter);
// Emit constant loads.
builder.LoadLiteral(Smi::FromInt(0))
@@ -40,32 +42,23 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.LoadTrue()
.LoadFalse();
- // Emit accumulator transfers. Stores followed by loads to the same register
- // are not generated. Hence, a dummy instruction in between.
Register reg(0);
+ Register other(reg.index() + 1);
+ Register wide(128);
+
builder.LoadAccumulatorWithRegister(reg)
.LoadNull()
.StoreAccumulatorInRegister(reg);
// Emit register-register transfer.
- Register other(1);
builder.MoveRegister(reg, other);
-
- // Emit register-register exchanges.
- Register wide(150);
- builder.ExchangeRegisters(reg, wide);
- builder.ExchangeRegisters(wide, reg);
- Register wider(151);
- builder.ExchangeRegisters(wide, wider);
+ builder.MoveRegister(reg, wide);
// Emit global load / store operations.
Factory* factory = isolate()->factory();
Handle<String> name = factory->NewStringFromStaticChars("var_name");
- builder.LoadGlobal(name, 1, LanguageMode::SLOPPY,
- TypeofMode::NOT_INSIDE_TYPEOF)
- .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::NOT_INSIDE_TYPEOF)
- .LoadGlobal(name, 1, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF)
- .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF)
+ builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF)
+ .LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF)
.StoreGlobal(name, 1, LanguageMode::SLOPPY)
.StoreGlobal(name, 1, LanguageMode::STRICT);
@@ -76,12 +69,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.StoreContextSlot(reg, 1);
// Emit load / store property operations.
- builder.LoadNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
- .LoadKeyedProperty(reg, 0, LanguageMode::SLOPPY)
+ builder.LoadNamedProperty(reg, name, 0)
+ .LoadKeyedProperty(reg, 0)
.StoreNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
.StoreKeyedProperty(reg, reg, 0, LanguageMode::SLOPPY)
- .LoadNamedProperty(reg, name, 0, LanguageMode::STRICT)
- .LoadKeyedProperty(reg, 0, LanguageMode::STRICT)
.StoreNamedProperty(reg, name, 0, LanguageMode::STRICT)
.StoreKeyedProperty(reg, reg, 0, LanguageMode::STRICT);
@@ -97,65 +88,64 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
false);
builder.CreateClosure(shared_info, NOT_TENURED);
- // Emit argument creation operations.
- builder.CreateArguments(CreateArgumentsType::kMappedArguments)
- .CreateArguments(CreateArgumentsType::kUnmappedArguments);
-
// Emit literal creation operations.
builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0)
.CreateArrayLiteral(factory->NewFixedArray(1), 0, 0)
.CreateObjectLiteral(factory->NewFixedArray(1), 0, 0);
// Call operations.
- builder.Call(reg, reg, 0, 0)
- .Call(reg, reg, 0, 1024)
+ builder.Call(reg, other, 1, 0)
+ .Call(reg, wide, 1, 0)
+ .TailCall(reg, other, 1, 0)
+ .TailCall(reg, wide, 1, 0)
.CallRuntime(Runtime::kIsArray, reg, 1)
- .CallRuntimeForPair(Runtime::kLoadLookupSlot, reg, 1, reg)
- .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1);
+ .CallRuntime(Runtime::kIsArray, wide, 1)
+ .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg, 1, other)
+ .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, wide, 1, other)
+ .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1)
+ .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, wide, 1);
// Emit binary operator invocations.
- builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::SUB, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::MUL, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::DIV, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::MOD, reg, Strength::WEAK);
+ builder.BinaryOperation(Token::Value::ADD, reg)
+ .BinaryOperation(Token::Value::SUB, reg)
+ .BinaryOperation(Token::Value::MUL, reg)
+ .BinaryOperation(Token::Value::DIV, reg)
+ .BinaryOperation(Token::Value::MOD, reg);
// Emit bitwise operator invocations
- builder.BinaryOperation(Token::Value::BIT_OR, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::BIT_XOR, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::BIT_AND, reg, Strength::WEAK);
+ builder.BinaryOperation(Token::Value::BIT_OR, reg)
+ .BinaryOperation(Token::Value::BIT_XOR, reg)
+ .BinaryOperation(Token::Value::BIT_AND, reg);
// Emit shift operator invocations
- builder.BinaryOperation(Token::Value::SHL, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::SAR, reg, Strength::WEAK)
- .BinaryOperation(Token::Value::SHR, reg, Strength::WEAK);
+ builder.BinaryOperation(Token::Value::SHL, reg)
+ .BinaryOperation(Token::Value::SAR, reg)
+ .BinaryOperation(Token::Value::SHR, reg);
// Emit count operatior invocations
- builder.CountOperation(Token::Value::ADD, Strength::WEAK)
- .CountOperation(Token::Value::SUB, Strength::WEAK);
+ builder.CountOperation(Token::Value::ADD).CountOperation(Token::Value::SUB);
// Emit unary operator invocations.
builder.LogicalNot().TypeOf();
// Emit delete
- builder.Delete(reg, LanguageMode::SLOPPY)
- .Delete(reg, LanguageMode::STRICT)
- .DeleteLookupSlot();
+ builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
// Emit new.
builder.New(reg, reg, 0);
+ builder.New(wide, wide, 0);
// Emit test operator invocations.
- builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
- .CompareOperation(Token::Value::NE, reg, Strength::WEAK)
- .CompareOperation(Token::Value::EQ_STRICT, reg, Strength::WEAK)
- .CompareOperation(Token::Value::NE_STRICT, reg, Strength::WEAK)
- .CompareOperation(Token::Value::LT, reg, Strength::WEAK)
- .CompareOperation(Token::Value::GT, reg, Strength::WEAK)
- .CompareOperation(Token::Value::LTE, reg, Strength::WEAK)
- .CompareOperation(Token::Value::GTE, reg, Strength::WEAK)
- .CompareOperation(Token::Value::INSTANCEOF, reg, Strength::WEAK)
- .CompareOperation(Token::Value::IN, reg, Strength::WEAK);
+ builder.CompareOperation(Token::Value::EQ, reg)
+ .CompareOperation(Token::Value::NE, reg)
+ .CompareOperation(Token::Value::EQ_STRICT, reg)
+ .CompareOperation(Token::Value::NE_STRICT, reg)
+ .CompareOperation(Token::Value::LT, reg)
+ .CompareOperation(Token::Value::GT, reg)
+ .CompareOperation(Token::Value::LTE, reg)
+ .CompareOperation(Token::Value::GTE, reg)
+ .CompareOperation(Token::Value::INSTANCEOF, reg)
+ .CompareOperation(Token::Value::IN, reg);
// Emit cast operator invocations.
builder.CastAccumulatorToNumber()
@@ -168,50 +158,58 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Short jumps with Imm8 operands
builder.Jump(&start)
.JumpIfNull(&start)
- .JumpIfUndefined(&start);
+ .JumpIfUndefined(&start)
+ .JumpIfNotHole(&start);
+
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
- builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ builder.CompareOperation(Token::Value::EQ, reg)
.JumpIfTrue(&start)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfFalse(&start);
// Perform an operation that returns a non-boolean operation to
// generate JumpIfToBooleanTrue/False.
- builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ builder.BinaryOperation(Token::Value::ADD, reg)
.JumpIfTrue(&start)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&start);
// Insert dummy ops to force longer jumps
for (int i = 0; i < 128; i++) {
builder.LoadTrue();
}
// Longer jumps requiring Constant operand
- builder.Jump(&start)
- .JumpIfNull(&start)
- .JumpIfUndefined(&start);
+ builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
+ &start);
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
- builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ builder.CompareOperation(Token::Value::EQ, reg)
.JumpIfTrue(&start)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfFalse(&start);
// Perform an operation that returns a non-boolean operation to
// generate JumpIfToBooleanTrue/False.
- builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ builder.BinaryOperation(Token::Value::ADD, reg)
.JumpIfTrue(&start)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&start);
- // Emit throw in it's own basic block so that the rest of the code isn't
- // omitted due to being dead.
+ // Emit stack check bytecode.
+ builder.StackCheck();
+
+ // Emit throw and re-throw in it's own basic block so that the rest of the
+ // code isn't omitted due to being dead.
BytecodeLabel after_throw;
- builder.Jump(&after_throw)
- .Throw()
- .Bind(&after_throw);
+ builder.Jump(&after_throw).Throw().Bind(&after_throw);
+ BytecodeLabel after_rethrow;
+ builder.Jump(&after_rethrow).ReThrow().Bind(&after_rethrow);
- builder.ForInPrepare(reg, reg, reg)
+ builder.ForInPrepare(reg)
.ForInDone(reg, reg)
- .ForInNext(reg, reg, reg, reg)
+ .ForInNext(reg, reg, reg)
+ .ForInStep(reg);
+ builder.ForInPrepare(wide)
+ .ForInDone(reg, other)
+ .ForInNext(wide, wide, wide)
.ForInStep(reg);
// Wide constant pool loads
@@ -223,28 +221,21 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name");
// Emit wide global load / store operations.
- builder.LoadGlobal(name, 1024, LanguageMode::SLOPPY,
- TypeofMode::NOT_INSIDE_TYPEOF)
- .LoadGlobal(wide_name, 1, LanguageMode::STRICT,
- TypeofMode::NOT_INSIDE_TYPEOF)
- .LoadGlobal(name, 1024, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF)
- .LoadGlobal(wide_name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF)
+ builder.LoadGlobal(name, 1024, TypeofMode::NOT_INSIDE_TYPEOF)
+ .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
.StoreGlobal(name, 1024, LanguageMode::SLOPPY)
.StoreGlobal(wide_name, 1, LanguageMode::STRICT);
// Emit wide load / store property operations.
- builder.LoadNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
- .LoadKeyedProperty(reg, 2056, LanguageMode::SLOPPY)
+ builder.LoadNamedProperty(reg, wide_name, 0)
+ .LoadKeyedProperty(reg, 2056)
.StoreNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
.StoreKeyedProperty(reg, reg, 2056, LanguageMode::SLOPPY)
- .LoadNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
- .LoadKeyedProperty(reg, 2056, LanguageMode::STRICT)
.StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
.StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
// Emit wide context operations.
- builder.LoadContextSlot(reg, 1024)
- .StoreContextSlot(reg, 1024);
+ builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024);
// Emit wide load / store lookup slots.
builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
@@ -265,26 +256,31 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
// Longer jumps requiring ConstantWide operand
- builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start);
+ builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
+ &start);
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
- builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ builder.CompareOperation(Token::Value::EQ, reg)
.JumpIfTrue(&start)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfFalse(&start);
// Perform an operation that returns a non-boolean operation to
// generate JumpIfToBooleanTrue/False.
- builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ builder.BinaryOperation(Token::Value::ADD, reg)
.JumpIfTrue(&start)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&start);
+ builder.Debugger();
+
builder.Return();
// Generate BytecodeArray.
Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
CHECK_EQ(the_array->frame_size(),
- builder.fixed_register_count() * kPointerSize);
+ (builder.fixed_and_temporary_register_count() +
+ builder.translation_register_count()) *
+ kPointerSize);
// Build scorecard of bytecodes encountered in the BytecodeArray.
std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
@@ -301,9 +297,11 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
CHECK_EQ(final_bytecode, Bytecode::kReturn);
CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
-#define CHECK_BYTECODE_PRESENT(Name, ...) \
- /* Check Bytecode is marked in scorecard */ \
- CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);
+#define CHECK_BYTECODE_PRESENT(Name, ...) \
+ /* Check Bytecode is marked in scorecard, unless it's a debug break */ \
+ if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \
+ CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \
+ }
BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
#undef CHECK_BYTECODE_PRESENT
}
@@ -313,12 +311,9 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
for (int locals = 0; locals < 5; locals++) {
for (int contexts = 0; contexts < 4; contexts++) {
for (int temps = 0; temps < 3; temps++) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(locals);
- builder.set_context_count(contexts);
-
- BytecodeRegisterAllocator temporaries(&builder);
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals);
+ BytecodeRegisterAllocator temporaries(
+ zone(), builder.temporary_register_allocator());
for (int i = 0; i < temps; i++) {
builder.StoreAccumulatorInRegister(temporaries.NewRegister());
}
@@ -349,11 +344,7 @@ TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
TEST_F(BytecodeArrayBuilderTest, Parameters) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(10);
- builder.set_locals_count(0);
- builder.set_context_count(0);
-
+ BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0);
Register param0(builder.Parameter(0));
Register param9(builder.Parameter(9));
CHECK_EQ(param9.index() - param0.index(), 9);
@@ -361,12 +352,9 @@ TEST_F(BytecodeArrayBuilderTest, Parameters) {
TEST_F(BytecodeArrayBuilderTest, RegisterType) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(10);
- builder.set_locals_count(3);
- builder.set_context_count(0);
-
- BytecodeRegisterAllocator register_allocator(&builder);
+ BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3);
+ BytecodeRegisterAllocator register_allocator(
+ zone(), builder.temporary_register_allocator());
Register temp0 = register_allocator.NewRegister();
Register param0(builder.Parameter(0));
Register param9(builder.Parameter(9));
@@ -387,11 +375,7 @@ TEST_F(BytecodeArrayBuilderTest, RegisterType) {
TEST_F(BytecodeArrayBuilderTest, Constants) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
-
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
Factory* factory = isolate()->factory();
Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14);
Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2);
@@ -402,7 +386,8 @@ TEST_F(BytecodeArrayBuilderTest, Constants) {
.LoadLiteral(large_smi)
.LoadLiteral(heap_num_1)
.LoadLiteral(heap_num_1)
- .LoadLiteral(heap_num_2_copy);
+ .LoadLiteral(heap_num_2_copy)
+ .Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray();
// Should only have one entry for each identical constant.
@@ -413,23 +398,19 @@ TEST_F(BytecodeArrayBuilderTest, Constants) {
TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
static const int kFarJumpDistance = 256;
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
-
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
Register reg(0);
BytecodeLabel far0, far1, far2, far3, far4;
BytecodeLabel near0, near1, near2, near3, near4;
builder.Jump(&near0)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfTrue(&near1)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfFalse(&near2)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfTrue(&near3)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&near4)
.Bind(&near0)
.Bind(&near1)
@@ -437,13 +418,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
.Bind(&near3)
.Bind(&near4)
.Jump(&far0)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfTrue(&far1)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfFalse(&far2)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfTrue(&far3)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&far4);
for (int i = 0; i < kFarJumpDistance - 18; i++) {
builder.LoadUndefined();
@@ -529,38 +510,31 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
Register reg(0);
BytecodeLabel label0, label1, label2, label3, label4;
builder.Bind(&label0)
.Jump(&label0)
.Bind(&label1)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfTrue(&label1)
.Bind(&label2)
- .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+ .CompareOperation(Token::Value::EQ, reg)
.JumpIfFalse(&label2)
.Bind(&label3)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfTrue(&label3)
.Bind(&label4)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&label4);
for (int i = 0; i < 63; i++) {
builder.Jump(&label4);
}
- builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
- .JumpIfFalse(&label4);
- builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
- .JumpIfTrue(&label3);
- builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
- .JumpIfFalse(&label2);
- builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
- .JumpIfTrue(&label1);
+ builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
+ builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3);
+ builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
+ builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1);
builder.Jump(&label0);
builder.Return();
@@ -625,10 +599,7 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
// Labels can only have 1 forward reference, but
// can be referred to mulitple times once bound.
@@ -656,16 +627,11 @@ TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
static const int kRepeats = 3;
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
-
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
for (int i = 0; i < kRepeats; i++) {
BytecodeLabel label;
builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label);
}
-
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray();
@@ -686,7 +652,6 @@ TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
CHECK(iterator.done());
}
-
} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
index cd9f120cad..f2dcd7107c 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
@@ -22,11 +22,7 @@ class BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
// Use a builder to create an array with containing multiple bytecodes
// with 0, 1 and 2 operands.
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(3);
- builder.set_locals_count(2);
- builder.set_context_count(0);
-
+ BytecodeArrayBuilder builder(isolate(), zone(), 3, 2, 0);
Factory* factory = isolate()->factory();
Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718);
Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647);
@@ -46,9 +42,10 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
.LoadLiteral(smi_0)
.LoadLiteral(smi_1)
.LoadAccumulatorWithRegister(reg_0)
- .LoadNamedProperty(reg_1, name, feedback_slot, LanguageMode::SLOPPY)
+ .LoadNamedProperty(reg_1, name, feedback_slot)
.StoreAccumulatorInRegister(reg_2)
.CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
+ .Debugger()
.Return();
// Test iterator sees the expected output from the builder.
@@ -82,7 +79,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
CHECK(!iterator.done());
iterator.Advance();
- CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadICSloppy);
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
CHECK_EQ(iterator.GetIndexOperand(1), name_index);
CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
@@ -98,7 +95,11 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)),
Runtime::kLoadIC_Miss);
CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
- CHECK_EQ(iterator.GetCountOperand(2), 1);
+ CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
+ CHECK(!iterator.done());
+ iterator.Advance();
+
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
CHECK(!iterator.done());
iterator.Advance();
diff --git a/deps/v8/test/unittests/interpreter/bytecode-register-allocator-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
index 0620322162..ec29935b2f 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
@@ -12,51 +12,219 @@ namespace v8 {
namespace internal {
namespace interpreter {
+class TemporaryRegisterAllocatorTest : public TestWithIsolateAndZone {
+ public:
+ TemporaryRegisterAllocatorTest() : allocator_(zone(), 0) {}
+ ~TemporaryRegisterAllocatorTest() override {}
+ TemporaryRegisterAllocator* allocator() { return &allocator_; }
+
+ private:
+ TemporaryRegisterAllocator allocator_;
+};
+
+TEST_F(TemporaryRegisterAllocatorTest, FirstAllocation) {
+ CHECK_EQ(allocator()->allocation_count(), 0);
+ int reg0_index = allocator()->BorrowTemporaryRegister();
+ CHECK_EQ(reg0_index, 0);
+ CHECK_EQ(allocator()->allocation_count(), 1);
+ CHECK(allocator()->RegisterIsLive(Register(reg0_index)));
+ allocator()->ReturnTemporaryRegister(reg0_index);
+ CHECK(!allocator()->RegisterIsLive(Register(reg0_index)));
+ CHECK_EQ(allocator()->allocation_count(), 1);
+ CHECK(allocator()->first_temporary_register() == Register(0));
+ CHECK(allocator()->last_temporary_register() == Register(0));
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, SimpleAllocations) {
+ for (int i = 0; i < 13; i++) {
+ int reg_index = allocator()->BorrowTemporaryRegister();
+ CHECK_EQ(reg_index, i);
+ CHECK_EQ(allocator()->allocation_count(), i + 1);
+ }
+ for (int i = 0; i < 13; i++) {
+ CHECK(allocator()->RegisterIsLive(Register(i)));
+ allocator()->ReturnTemporaryRegister(i);
+ CHECK(!allocator()->RegisterIsLive(Register(i)));
+ int reg_index = allocator()->BorrowTemporaryRegister();
+ CHECK_EQ(reg_index, i);
+ CHECK_EQ(allocator()->allocation_count(), 13);
+ }
+ for (int i = 0; i < 13; i++) {
+ CHECK(allocator()->RegisterIsLive(Register(i)));
+ allocator()->ReturnTemporaryRegister(i);
+ CHECK(!allocator()->RegisterIsLive(Register(i)));
+ }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, SimpleRangeAllocation) {
+ static const int kRunLength = 7;
+ int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+ CHECK(!allocator()->RegisterIsLive(Register(start)));
+ for (int i = 0; i < kRunLength; i++) {
+ CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+ allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+ CHECK(allocator()->RegisterIsLive(Register(start + i)));
+ }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingFree) {
+ static const int kFreeCount = 3;
+ static const int kRunLength = 6;
+
+ for (int i = 0; i < kFreeCount; i++) {
+ int to_free = allocator()->BorrowTemporaryRegister();
+ CHECK_EQ(to_free, i);
+ }
+ for (int i = 0; i < kFreeCount; i++) {
+ allocator()->ReturnTemporaryRegister(i);
+ }
+
+ int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+ CHECK(!allocator()->RegisterIsLive(Register(start)));
+ for (int i = 0; i < kRunLength; i++) {
+ CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+ allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+ CHECK(allocator()->RegisterIsLive(Register(start + i)));
+ }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingHole) {
+ static const int kPreAllocatedCount = 7;
+ static const int kPreAllocatedFreeCount = 6;
+ static const int kRunLength = 8;
+
+ for (int i = 0; i < kPreAllocatedCount; i++) {
+ int to_free = allocator()->BorrowTemporaryRegister();
+ CHECK_EQ(to_free, i);
+ }
+ for (int i = 0; i < kPreAllocatedFreeCount; i++) {
+ allocator()->ReturnTemporaryRegister(i);
+ }
+ int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+ CHECK(!allocator()->RegisterIsLive(Register(start)));
+ CHECK_EQ(start, kPreAllocatedCount);
+ for (int i = 0; i < kRunLength; i++) {
+ CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+ allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+ CHECK(allocator()->RegisterIsLive(Register(start + i)));
+ }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAvailableInTemporaries) {
+ static const int kNotRunLength = 13;
+ static const int kRunLength = 8;
+
+ // Allocate big batch
+ for (int i = 0; i < kNotRunLength * 2 + kRunLength; i++) {
+ int allocated = allocator()->BorrowTemporaryRegister();
+ CHECK_EQ(allocated, i);
+ }
+ // Free every other register either side of target.
+ for (int i = 0; i < kNotRunLength; i++) {
+ if ((i & 2) == 1) {
+ allocator()->ReturnTemporaryRegister(i);
+ allocator()->ReturnTemporaryRegister(kNotRunLength + kRunLength + i);
+ }
+ }
+ // Free all registers for target.
+ for (int i = kNotRunLength; i < kNotRunLength + kRunLength; i++) {
+ allocator()->ReturnTemporaryRegister(i);
+ }
+
+ int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+ CHECK_EQ(start, kNotRunLength);
+ for (int i = 0; i < kRunLength; i++) {
+ CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+ allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+ CHECK(allocator()->RegisterIsLive(Register(start + i)));
+ }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAvoidsTranslationBoundary) {
+ int boundary = RegisterTranslator::DistanceToTranslationWindow(Register(0));
+ int limit = boundary + 64;
+
+ for (int run_length = 2; run_length < 32; run_length += 7) {
+ ZoneVector<int> run_starts(zone());
+ for (int start = 0; start < limit; start += run_length) {
+ int run_start =
+ allocator()->PrepareForConsecutiveTemporaryRegisters(run_length);
+ run_starts.push_back(run_start);
+ for (int i = 0; i < run_length; i++) {
+ allocator()->BorrowConsecutiveTemporaryRegister(run_start + i);
+ }
+ CHECK(run_start >= boundary || run_start + run_length <= boundary);
+ }
+ for (size_t batch = 0; batch < run_starts.size(); batch++) {
+ for (int i = run_starts[batch]; i < run_starts[batch] + run_length; i++) {
+ allocator()->ReturnTemporaryRegister(i);
+ }
+ }
+ }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, NotInRange) {
+ for (int i = 0; i < 10; i++) {
+ int reg = allocator()->BorrowTemporaryRegisterNotInRange(2, 5);
+ CHECK(reg == i || (reg > 2 && reg == i + 4));
+ }
+ for (int i = 0; i < 10; i++) {
+ if (i < 2) {
+ allocator()->ReturnTemporaryRegister(i);
+ } else {
+ allocator()->ReturnTemporaryRegister(i + 4);
+ }
+ }
+ int reg0 = allocator()->BorrowTemporaryRegisterNotInRange(0, 3);
+ CHECK_EQ(reg0, 4);
+ int reg1 = allocator()->BorrowTemporaryRegisterNotInRange(3, 10);
+ CHECK_EQ(reg1, 2);
+ int reg2 = allocator()->BorrowTemporaryRegisterNotInRange(2, 6);
+ CHECK_EQ(reg2, 1);
+ allocator()->ReturnTemporaryRegister(reg0);
+ allocator()->ReturnTemporaryRegister(reg1);
+ allocator()->ReturnTemporaryRegister(reg2);
+}
+
class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone {
public:
BytecodeRegisterAllocatorTest() {}
~BytecodeRegisterAllocatorTest() override {}
};
-
TEST_F(BytecodeRegisterAllocatorTest, TemporariesRecycled) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
int first;
{
- BytecodeRegisterAllocator temporaries(&builder);
- first = temporaries.NewRegister().index();
- temporaries.NewRegister();
- temporaries.NewRegister();
- temporaries.NewRegister();
+ BytecodeRegisterAllocator allocator(zone(),
+ builder.temporary_register_allocator());
+ first = allocator.NewRegister().index();
+ allocator.NewRegister();
+ allocator.NewRegister();
+ allocator.NewRegister();
}
int second;
{
- BytecodeRegisterAllocator temporaries(&builder);
- second = temporaries.NewRegister().index();
+ BytecodeRegisterAllocator allocator(zone(),
+ builder.temporary_register_allocator());
+ second = allocator.NewRegister().index();
}
CHECK_EQ(first, second);
}
-
TEST_F(BytecodeRegisterAllocatorTest, ConsecutiveRegisters) {
- BytecodeArrayBuilder builder(isolate(), zone());
- builder.set_parameter_count(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
-
- BytecodeRegisterAllocator temporaries(&builder);
- temporaries.PrepareForConsecutiveAllocations(4);
- Register reg0 = temporaries.NextConsecutiveRegister();
- Register other = temporaries.NewRegister();
- Register reg1 = temporaries.NextConsecutiveRegister();
- Register reg2 = temporaries.NextConsecutiveRegister();
- Register reg3 = temporaries.NextConsecutiveRegister();
+ BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
+ BytecodeRegisterAllocator allocator(zone(),
+ builder.temporary_register_allocator());
+ allocator.PrepareForConsecutiveAllocations(4);
+ Register reg0 = allocator.NextConsecutiveRegister();
+ Register other = allocator.NewRegister();
+ Register reg1 = allocator.NextConsecutiveRegister();
+ Register reg2 = allocator.NextConsecutiveRegister();
+ Register reg3 = allocator.NextConsecutiveRegister();
USE(other);
CHECK(Register::AreContiguous(reg0, reg1, reg2, reg3));
diff --git a/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc b/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc
index 812ee46c9c..212e02996b 100644
--- a/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc
@@ -9,19 +9,39 @@
#include "src/interpreter/bytecodes.h"
#include "test/unittests/test-utils.h"
-
namespace v8 {
namespace internal {
namespace interpreter {
TEST(OperandConversion, Registers) {
- for (int i = 0; i < 128; i++) {
- uint8_t operand_value = Register(i).ToOperand();
- Register r = Register::FromOperand(operand_value);
- CHECK_EQ(i, r.index());
+ int register_count = Register::MaxRegisterIndex() + 1;
+ int step = register_count / 7;
+ for (int i = 0; i < register_count; i += step) {
+ if (i <= kMaxInt8) {
+ uint8_t operand0 = Register(i).ToOperand();
+ Register reg0 = Register::FromOperand(operand0);
+ CHECK_EQ(i, reg0.index());
+ }
+
+ uint16_t operand1 = Register(i).ToWideOperand();
+ Register reg1 = Register::FromWideOperand(operand1);
+ CHECK_EQ(i, reg1.index());
+
+ uint32_t operand2 = Register(i).ToRawOperand();
+ Register reg2 = Register::FromRawOperand(operand2);
+ CHECK_EQ(i, reg2.index());
}
-}
+ for (int i = 0; i <= kMaxUInt8; i++) {
+ uint8_t operand = static_cast<uint8_t>(i);
+ Register reg = Register::FromOperand(operand);
+ if (i > 0 && i < -kMinInt8) {
+ CHECK(reg.is_parameter());
+ } else {
+ CHECK(!reg.is_parameter());
+ }
+ }
+}
TEST(OperandConversion, Parameters) {
int parameter_counts[] = {7, 13, 99};
@@ -38,26 +58,115 @@ TEST(OperandConversion, Parameters) {
}
}
-
TEST(OperandConversion, RegistersParametersNoOverlap) {
- std::vector<uint8_t> operand_count(256);
+ int register_count = Register::MaxRegisterIndex() + 1;
+ int parameter_count = Register::MaxParameterIndex() + 1;
+ int32_t register_space_size = base::bits::RoundUpToPowerOfTwo32(
+ static_cast<uint32_t>(register_count + parameter_count));
+ uint32_t range = static_cast<uint32_t>(register_space_size);
+ std::vector<uint8_t> operand_count(range);
- for (int i = 0; i <= kMaxInt8; i++) {
+ for (int i = 0; i < register_count; i += 1) {
Register r = Register(i);
- uint8_t operand = r.ToOperand();
+ uint32_t operand = r.ToWideOperand();
+ CHECK_LT(operand, operand_count.size());
operand_count[operand] += 1;
CHECK_EQ(operand_count[operand], 1);
}
- int parameter_count = Register::MaxParameterIndex() + 1;
- for (int i = 0; i < parameter_count; i++) {
+ for (int i = 0; i < parameter_count; i += 1) {
Register r = Register::FromParameterIndex(i, parameter_count);
- uint8_t operand = r.ToOperand();
+ uint32_t operand = r.ToWideOperand();
+ CHECK_LT(operand, operand_count.size());
operand_count[operand] += 1;
CHECK_EQ(operand_count[operand], 1);
}
}
+TEST(Bytecodes, HasAnyRegisterOperands) {
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kAdd), 1);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCall), 2);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntime), 1);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeWide), 1);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeForPair),
+ 2);
+ CHECK_EQ(
+ Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeForPairWide),
+ 2);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kDeletePropertyStrict),
+ 1);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kForInPrepare), 1);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kForInPrepareWide), 1);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kInc), 0);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kJumpIfTrue), 0);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kNew), 2);
+ CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kToName), 0);
+}
+
+TEST(Bytecodes, RegisterOperandBitmaps) {
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kAdd), 1);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kCallRuntimeForPair),
+ 10);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kStar), 1);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kMov), 3);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kTestIn), 1);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInPrepare), 1);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInDone), 3);
+ CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInNext), 7);
+}
+
+TEST(Bytecodes, RegisterOperands) {
+ CHECK(Bytecodes::IsRegisterOperandType(OperandType::kReg8));
+ CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::kReg8));
+ CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::kReg8));
+ CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::kRegOut8));
+ CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::kRegOut8));
+
+#define IS_REGISTER_OPERAND_TYPE(Name, _) \
+ CHECK(Bytecodes::IsRegisterOperandType(OperandType::k##Name));
+ REGISTER_OPERAND_TYPE_LIST(IS_REGISTER_OPERAND_TYPE)
+#undef IS_REGISTER_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_OPERAND_TYPE(Name, _) \
+ CHECK(!Bytecodes::IsRegisterOperandType(OperandType::k##Name));
+ NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_OPERAND_TYPE
+
+#define IS_REGISTER_INPUT_OPERAND_TYPE(Name, _) \
+ CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::k##Name));
+ REGISTER_INPUT_OPERAND_TYPE_LIST(IS_REGISTER_INPUT_OPERAND_TYPE)
+#undef IS_REGISTER_INPUT_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_INPUT_OPERAND_TYPE(Name, _) \
+ CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::k##Name));
+ NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_INPUT_OPERAND_TYPE);
+ REGISTER_OUTPUT_OPERAND_TYPE_LIST(IS_NOT_REGISTER_INPUT_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_INPUT_OPERAND_TYPE
+
+#define IS_REGISTER_OUTPUT_OPERAND_TYPE(Name, _) \
+ CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::k##Name));
+ REGISTER_OUTPUT_OPERAND_TYPE_LIST(IS_REGISTER_OUTPUT_OPERAND_TYPE)
+#undef IS_REGISTER_OUTPUT_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE(Name, _) \
+ CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::k##Name));
+ NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE)
+ REGISTER_INPUT_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_INPUT_OPERAND_TYPE
+}
+
+TEST(Bytecodes, DebugBreak) {
+ for (uint32_t i = 0; i < Bytecodes::ToByte(Bytecode::kLast); i++) {
+ Bytecode bytecode = Bytecodes::FromByte(i);
+ Bytecode debugbreak = Bytecodes::GetDebugBreak(bytecode);
+ if (!Bytecodes::IsDebugBreak(debugbreak)) {
+ PrintF("Bytecode %s has no matching debug break with length %d\n",
+ Bytecodes::ToString(bytecode), Bytecodes::Size(bytecode));
+ CHECK(false);
+ }
+ }
+}
+
} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc b/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc
index ea5d1bb8c3..b3ec5ff668 100644
--- a/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc
@@ -33,13 +33,11 @@ STATIC_CONST_MEMBER_DEFINITION const size_t
TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) {
ConstantArrayBuilder builder(isolate(), zone());
for (size_t i = 0; i < kMaxCapacity; i++) {
- Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
- builder.Insert(object);
- CHECK_EQ(builder.size(), i + 1);
- CHECK(builder.At(i)->SameValue(*object));
+ builder.Insert(handle(Smi::FromInt(static_cast<int>(i)), isolate()));
}
+ CHECK_EQ(builder.size(), kMaxCapacity);
for (size_t i = 0; i < kMaxCapacity; i++) {
- CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), static_cast<double>(i));
+ CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), i);
}
}
@@ -158,8 +156,7 @@ TEST_F(ConstantArrayBuilderTest, ToFixedArray) {
builder.Insert(object);
CHECK(builder.At(i)->SameValue(*object));
}
- Handle<FixedArray> constant_array =
- builder.ToFixedArray(isolate()->factory());
+ Handle<FixedArray> constant_array = builder.ToFixedArray();
CHECK_EQ(constant_array->length(), kNumberOfElements);
for (size_t i = 0; i < kNumberOfElements; i++) {
CHECK(constant_array->get(static_cast<int>(i))->SameValue(*builder.At(i)));
diff --git a/deps/v8/test/unittests/compiler/interpreter-assembler-unittest.cc b/deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.cc
index f57ca05b3f..3375a6b817 100644
--- a/deps/v8/test/unittests/compiler/interpreter-assembler-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.cc
@@ -2,7 +2,7 @@
// 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 "test/unittests/interpreter/interpreter-assembler-unittest.h"
#include "src/code-factory.h"
#include "src/compiler/graph.h"
@@ -16,7 +16,10 @@ using ::testing::_;
namespace v8 {
namespace internal {
-namespace compiler {
+
+using namespace compiler;
+
+namespace interpreter {
const interpreter::Bytecode kBytecodes[] = {
#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
@@ -24,55 +27,47 @@ const interpreter::Bytecode kBytecodes[] = {
#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,
@@ -81,52 +76,57 @@ Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
value_matcher, _, _);
}
-
Matcher<Node*>
InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
int offset) {
return IsLoad(
MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ 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)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ 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)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ IsInt32Constant(offset)));
} else {
Matcher<Node*> first_byte = IsLoad(
MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ IsInt32Constant(offset)));
Matcher<Node*> second_byte = IsLoad(
MachineType::Uint8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(offset + 1)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ IsInt32Constant(offset + 1)));
#if V8_TARGET_LITTLE_ENDIAN
return IsWordOr(IsWordShl(second_byte, IsInt32Constant(kBitsPerByte)),
first_byte);
@@ -139,16 +139,17 @@ InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperandShort(
}
}
-
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)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ IsInt32Constant(offset)));
} else {
#if V8_TARGET_LITTLE_ENDIAN
int hi_byte_offset = offset + 1;
@@ -162,15 +163,19 @@ Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
#endif
Matcher<Node*> hi_byte = IsLoad(
MachineType::Int8(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
- IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
- IsInt32Constant(hi_byte_offset)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ 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)));
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsIntPtrAdd(
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ IsInt32Constant(lo_byte_offset)));
load_matcher = IsWord32Or(hi_byte, lo_byte);
}
@@ -180,7 +185,6 @@ Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
return load_matcher;
}
-
TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -191,35 +195,37 @@ TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
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);
+ Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
+ Matcher<Node*> target_bytecode_matcher = m.IsLoad(
+ MachineType::Uint8(),
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ next_bytecode_offset_matcher);
+ Matcher<Node*> code_target_matcher = m.IsLoad(
+ MachineType::Pointer(),
+ IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+ IsWord32Shl(target_bytecode_matcher,
+ IsInt32Constant(kPointerSizeLog2)));
+
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), _, _));
+ IsTailCall(
+ _, code_target_matcher,
+ IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+ IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+ next_bytecode_offset_matcher,
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+ IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+ _));
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
+ // If debug code is enabled we emit extra code in Jump.
+ if (FLAG_debug_code) return;
+
int jump_offsets[] = {-9710, -77, 0, +3, +97109};
TRACED_FOREACH(int, jump_offset, jump_offsets) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -230,38 +236,39 @@ TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
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*> next_bytecode_offset_matcher = IsIntPtrAdd(
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ 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);
+ m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
+ Matcher<Node*> code_target_matcher = m.IsLoad(
+ MachineType::Pointer(),
+ IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+ IsWord32Shl(target_bytecode_matcher,
+ IsInt32Constant(kPointerSizeLog2)));
+
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), _, _));
+ IsTailCall(
+ _, code_target_matcher,
+ IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+ IsParameter(
+ InterpreterDispatchDescriptor::kRegisterFileParameter),
+ next_bytecode_offset_matcher, _,
+ IsParameter(
+ InterpreterDispatchDescriptor::kDispatchTableParameter),
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+ _));
}
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
static const int kJumpIfTrueOffset = 73;
+ // If debug code is enabled we emit extra code in Jump.
+ if (FLAG_debug_code) return;
+
MachineOperatorBuilder machine(zone());
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -276,61 +283,64 @@ TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
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*> next_bytecode_offset_matcher = IsIntPtrAdd(
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ 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)));
+ m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
+ Matcher<Node*> code_target_matcher = m.IsLoad(
+ MachineType::Pointer(),
+ IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+ 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), _, _));
+ IsTailCall(
+ _, code_target_matcher,
+ IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+ IsParameter(
+ InterpreterDispatchDescriptor::kRegisterFileParameter),
+ next_bytecode_offset_matcher, _,
+ IsParameter(
+ InterpreterDispatchDescriptor::kDispatchTableParameter),
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+ _));
}
// TODO(oth): test control flow paths.
}
}
+TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) {
+ // If debug code is enabled we emit extra code in InterpreterReturn.
+ if (FLAG_debug_code) return;
-TARGET_TEST_F(InterpreterAssemblerTest, Return) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
- m.Return();
+ m.InterpreterReturn();
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), _, _));
+ IsTailCall(
+ _, IsHeapConstant(exit_trampoline),
+ IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+ IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+ IsParameter(
+ InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+ _,
+ IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+ _));
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -338,7 +348,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
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:
+ case interpreter::OperandType::kRegCount8:
EXPECT_THAT(m.BytecodeOperandCount(i), m.IsBytecodeOperand(offset));
break;
case interpreter::OperandType::kIdx8:
@@ -350,11 +360,14 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
break;
case interpreter::OperandType::kMaybeReg8:
case interpreter::OperandType::kReg8:
+ case interpreter::OperandType::kRegOut8:
+ case interpreter::OperandType::kRegOutPair8:
+ case interpreter::OperandType::kRegOutTriple8:
case interpreter::OperandType::kRegPair8:
EXPECT_THAT(m.BytecodeOperandReg(i),
m.IsBytecodeOperandSignExtended(offset));
break;
- case interpreter::OperandType::kCount16:
+ case interpreter::OperandType::kRegCount16:
EXPECT_THAT(m.BytecodeOperandCount(i),
m.IsBytecodeOperandShort(offset));
break;
@@ -362,7 +375,12 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
EXPECT_THAT(m.BytecodeOperandIdx(i),
m.IsBytecodeOperandShort(offset));
break;
+ case interpreter::OperandType::kMaybeReg16:
case interpreter::OperandType::kReg16:
+ case interpreter::OperandType::kRegOut16:
+ case interpreter::OperandType::kRegOutPair16:
+ case interpreter::OperandType::kRegOutTriple16:
+ case interpreter::OperandType::kRegPair16:
EXPECT_THAT(m.BytecodeOperandReg(i),
m.IsBytecodeOperandShortSignExtended(offset));
break;
@@ -374,15 +392,15 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
}
}
-
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));
+ EXPECT_THAT(
+ m.GetAccumulator(),
+ IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
- // Should be set by SedtAccumulator.
+ // Should be set by SetAccumulator.
Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
m.SetAccumulator(accumulator_value_1);
EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
@@ -399,11 +417,18 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
Node* tail_call_node = end->InputAt(0);
EXPECT_THAT(tail_call_node,
- IsTailCall(m.call_descriptor(), _, accumulator_value_2, _, _, _,
- _, _, _));
+ IsTailCall(_, _, accumulator_value_2, _, _, _, _, _, _));
}
}
+TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+ InterpreterAssemblerForTest m(this, bytecode);
+ Node* context_node = m.Int32Constant(100);
+ m.SetContext(context_node);
+ EXPECT_THAT(m.GetContext(), context_node);
+ }
+}
TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -413,12 +438,11 @@ TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
EXPECT_THAT(
reg_location_node,
IsIntPtrAdd(
- IsParameter(Linkage::kInterpreterRegisterFileParameter),
+ IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -426,13 +450,13 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
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))));
+ m.IsLoad(
+ MachineType::AnyTagged(),
+ IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+ IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -441,15 +465,15 @@ TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
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));
+ m.IsStore(
+ StoreRepresentation(MachineRepresentation::kTagged,
+ kNoWriteBarrier),
+ IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+ IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
+ store_value));
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -461,7 +485,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -472,7 +495,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -483,7 +505,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -493,7 +514,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -501,7 +521,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
Node* load_constant = m.LoadConstantPoolEntry(index);
Matcher<Node*> constant_pool_matcher = m.IsLoad(
MachineType::AnyTagged(),
- IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
+ IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
EXPECT_THAT(
load_constant,
@@ -512,7 +532,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -529,7 +548,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -542,7 +560,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -558,7 +575,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
@@ -577,21 +593,22 @@ TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
}
}
-
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);
+ Node* context =
+ m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+ Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
EXPECT_THAT(
call_runtime,
IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+ _));
}
}
-
TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
const int kResultSizes[] = {1, 2};
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
@@ -602,6 +619,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
Node* function_id = m.Int32Constant(0);
Node* first_arg = m.Int32Constant(1);
Node* arg_count = m.Int32Constant(2);
+ Node* context =
+ m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
Matcher<Node*> function_table = IsExternalConstant(
ExternalReference::runtime_function_table_address(isolate()));
@@ -612,63 +631,53 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
m.IsLoad(MachineType::Pointer(), function,
IsInt32Constant(offsetof(Runtime::Function, entry)));
- Node* call_runtime =
- m.CallRuntime(function_id, first_arg, arg_count, result_size);
+ Node* call_runtime = m.CallRuntimeN(function_id, context, first_arg,
+ arg_count, result_size);
EXPECT_THAT(
call_runtime,
IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
function_entry,
- IsParameter(Linkage::kInterpreterContextParameter), _, _));
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter),
+ _, _));
}
}
}
-
-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), _,
- _));
+ TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
+ TailCallMode::kAllow};
+ TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+ InterpreterAssemblerForTest m(this, bytecode);
+ Callable builtin =
+ CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
+ Node* function = m.Int32Constant(0);
+ Node* first_arg = m.Int32Constant(1);
+ Node* arg_count = m.Int32Constant(2);
+ Node* context =
+ m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+ Node* call_js =
+ m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
+ EXPECT_THAT(
+ call_js,
+ IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
+ function,
+ IsParameter(InterpreterDispatchDescriptor::kContextParameter),
+ _, _));
+ }
}
}
-
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_function_matcher = m.IsLoad(
+ MachineType::AnyTagged(),
+ IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+ IsIntPtrConstant(
+ InterpreterFrameConstants::kFunctionFromRegisterPointer));
Matcher<Node*> load_shared_function_info_matcher =
m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
@@ -682,6 +691,6 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
}
}
-} // namespace compiler
+} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.h b/deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.h
new file mode 100644
index 0000000000..321c72490b
--- /dev/null
+++ b/deps/v8/test/unittests/interpreter/interpreter-assembler-unittest.h
@@ -0,0 +1,57 @@
+// 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_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
+#define V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
+
+#include "src/compiler/machine-operator.h"
+#include "src/interpreter/interpreter-assembler.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock-support.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+using ::testing::Matcher;
+
+class InterpreterAssemblerTest : public TestWithIsolateAndZone {
+ public:
+ InterpreterAssemblerTest() {}
+ ~InterpreterAssemblerTest() override {}
+
+ class InterpreterAssemblerForTest final : public InterpreterAssembler {
+ public:
+ InterpreterAssemblerForTest(InterpreterAssemblerTest* test,
+ Bytecode bytecode)
+ : InterpreterAssembler(test->isolate(), test->zone(), bytecode) {}
+ ~InterpreterAssemblerForTest() override {}
+
+ Matcher<compiler::Node*> IsLoad(
+ const Matcher<compiler::LoadRepresentation>& rep_matcher,
+ const Matcher<compiler::Node*>& base_matcher,
+ const Matcher<compiler::Node*>& index_matcher);
+ Matcher<compiler::Node*> IsStore(
+ const Matcher<compiler::StoreRepresentation>& rep_matcher,
+ const Matcher<compiler::Node*>& base_matcher,
+ const Matcher<compiler::Node*>& index_matcher,
+ const Matcher<compiler::Node*>& value_matcher);
+
+ Matcher<compiler::Node*> IsBytecodeOperand(int offset);
+ Matcher<compiler::Node*> IsBytecodeOperandSignExtended(int offset);
+ Matcher<compiler::Node*> IsBytecodeOperandShort(int offset);
+ Matcher<compiler::Node*> IsBytecodeOperandShortSignExtended(int offset);
+
+ using InterpreterAssembler::graph;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InterpreterAssemblerForTest);
+ };
+};
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
+
+#endif // V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
diff --git a/deps/v8/test/unittests/interpreter/register-translator-unittest.cc b/deps/v8/test/unittests/interpreter/register-translator-unittest.cc
new file mode 100644
index 0000000000..e9f65a6af0
--- /dev/null
+++ b/deps/v8/test/unittests/interpreter/register-translator-unittest.cc
@@ -0,0 +1,260 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stack>
+
+#include "src/v8.h"
+
+#include "src/interpreter/register-translator.h"
+#include "src/isolate.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class RegisterTranslatorTest : public TestWithIsolateAndZone,
+ private RegisterMover {
+ public:
+ RegisterTranslatorTest() : translator_(this), move_count_(0) {
+ window_start_ =
+ RegisterTranslator::DistanceToTranslationWindow(Register(0));
+ window_width_ =
+ Register::MaxRegisterIndexForByteOperand() - window_start_ + 1;
+ }
+
+ ~RegisterTranslatorTest() override {}
+
+ bool PopMoveAndMatch(Register from, Register to) {
+ if (!moves_.empty()) {
+ CHECK(from.is_valid() && to.is_valid());
+ const std::pair<Register, Register> top = moves_.top();
+ moves_.pop();
+ return top.first == from && top.second == to;
+ } else {
+ return false;
+ }
+ }
+
+ int move_count() const { return move_count_; }
+ RegisterTranslator* translator() { return &translator_; }
+
+ int window_start() const { return window_start_; }
+ int window_width() const { return window_width_; }
+ int window_limit() const { return window_start_ + window_width_; }
+
+ protected:
+ static const char* const kBadOperandRegex;
+
+ private:
+ void MoveRegisterUntranslated(Register from, Register to) override {
+ moves_.push(std::make_pair(from, to));
+ move_count_++;
+ }
+
+ RegisterTranslator translator_;
+ std::stack<std::pair<Register, Register>> moves_;
+ int move_count_;
+ int window_start_;
+ int window_width_;
+};
+
+const char* const RegisterTranslatorTest::kBadOperandRegex =
+ ".*OperandType::kReg8 \\|\\| .*OperandType::kRegOut8\\) && "
+ "RegisterIsMovableToWindow.*";
+
+TEST_F(RegisterTranslatorTest, TestFrameSizeAdjustmentsForTranslationWindow) {
+ EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(0, 0));
+ EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(10, 10));
+ EXPECT_EQ(window_width(),
+ RegisterTranslator::RegisterCountAdjustment(173, 0));
+ EXPECT_EQ(window_width(),
+ RegisterTranslator::RegisterCountAdjustment(173, 137));
+ EXPECT_EQ(window_width(),
+ RegisterTranslator::RegisterCountAdjustment(173, 137));
+ // TODO(oth): Add a kMaxParameters8 that derives this info from the frame.
+ int param_limit = FLAG_enable_embedded_constant_pool ? 119 : 120;
+ EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(0, param_limit));
+ EXPECT_EQ(window_limit(),
+ RegisterTranslator::RegisterCountAdjustment(0, 128));
+ EXPECT_EQ(window_limit(),
+ RegisterTranslator::RegisterCountAdjustment(0, 129));
+ EXPECT_EQ(window_limit() - 32,
+ RegisterTranslator::RegisterCountAdjustment(32, 129));
+}
+
+TEST_F(RegisterTranslatorTest, TestInTranslationWindow) {
+ EXPECT_GE(window_start(), 0);
+ EXPECT_FALSE(
+ RegisterTranslator::InTranslationWindow(Register(window_start() - 1)));
+ EXPECT_TRUE(RegisterTranslator::InTranslationWindow(
+ Register(Register::MaxRegisterIndexForByteOperand())));
+ EXPECT_FALSE(RegisterTranslator::InTranslationWindow(
+ Register(Register::MaxRegisterIndexForByteOperand() + 1)));
+ for (int index = window_start(); index < window_limit(); index += 1) {
+ EXPECT_TRUE(RegisterTranslator::InTranslationWindow(Register(index)));
+ }
+}
+
+TEST_F(RegisterTranslatorTest, FitsInReg8Operand) {
+ EXPECT_GT(window_start(), 0);
+ EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(
+ Register::FromParameterIndex(0, 3)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(
+ Register::FromParameterIndex(2, 3)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(Register(0)));
+ EXPECT_TRUE(
+ RegisterTranslator::FitsInReg8Operand(Register(window_start() - 1)));
+ EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(kMaxInt8)));
+ EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(kMaxInt8 + 1)));
+ for (int index = window_start(); index < window_limit(); index += 1) {
+ EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(index)));
+ }
+}
+
+TEST_F(RegisterTranslatorTest, FitsInReg16Operand) {
+ EXPECT_GT(window_start(), 0);
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+ Register::FromParameterIndex(0, 3)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+ Register::FromParameterIndex(2, 3)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+ Register::FromParameterIndex(0, 999)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+ Register::FromParameterIndex(0, Register::MaxParameterIndex() + 1)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(0)));
+ EXPECT_TRUE(
+ RegisterTranslator::FitsInReg16Operand(Register(window_start() - 1)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(kMaxInt8 + 1)));
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(kMaxInt8 + 2)));
+ for (int index = 0; index <= kMaxInt16 - window_width(); index += 1) {
+ EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(index)));
+ }
+ for (int index = Register::MaxRegisterIndex() - window_width() + 1;
+ index < Register::MaxRegisterIndex() + 2; index += 1) {
+ EXPECT_FALSE(RegisterTranslator::FitsInReg16Operand(Register(index)));
+ }
+}
+
+TEST_F(RegisterTranslatorTest, NoTranslationRequired) {
+ Register window_reg(window_start());
+ Register local_reg(57);
+ uint32_t operands[] = {local_reg.ToRawOperand()};
+ translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(0, move_count());
+
+ Register param_reg = Register::FromParameterIndex(129, 130);
+ operands[0] = param_reg.ToRawOperand();
+ translator()->TranslateInputRegisters(Bytecode::kAdd, operands, 1);
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(0, move_count());
+}
+
+TEST_F(RegisterTranslatorTest, TranslationRequired) {
+ Register window_reg(window_start());
+ Register local_reg(137);
+ Register local_reg_translated(local_reg.index() + window_width());
+
+ uint32_t operands[] = {local_reg.ToRawOperand()};
+ translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+ EXPECT_EQ(1, move_count());
+ EXPECT_TRUE(PopMoveAndMatch(local_reg_translated, window_reg));
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(1, move_count());
+ EXPECT_FALSE(PopMoveAndMatch(window_reg, local_reg_translated));
+
+ operands[0] = local_reg.ToRawOperand();
+ translator()->TranslateInputRegisters(Bytecode::kStar, operands, 1);
+ EXPECT_EQ(1, move_count());
+ EXPECT_FALSE(PopMoveAndMatch(local_reg_translated, window_reg));
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(2, move_count());
+ EXPECT_TRUE(PopMoveAndMatch(window_reg, local_reg_translated));
+
+ Register param_reg = Register::FromParameterIndex(0, 130);
+ operands[0] = {param_reg.ToRawOperand()};
+ translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+ EXPECT_EQ(3, move_count());
+ EXPECT_TRUE(PopMoveAndMatch(param_reg, window_reg));
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(3, move_count());
+ EXPECT_FALSE(PopMoveAndMatch(window_reg, param_reg));
+
+ operands[0] = {param_reg.ToRawOperand()};
+ translator()->TranslateInputRegisters(Bytecode::kStar, operands, 1);
+ EXPECT_EQ(3, move_count());
+ EXPECT_FALSE(PopMoveAndMatch(local_reg_translated, window_reg));
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(4, move_count());
+ EXPECT_TRUE(PopMoveAndMatch(window_reg, param_reg));
+}
+
+TEST_F(RegisterTranslatorTest, RangeTranslation) {
+ Register window0(window_start());
+ Register window1(window_start() + 1);
+ Register window2(window_start() + 2);
+ uint32_t operands[3];
+
+ // Bytecode::kNew with valid range operand.
+ Register constructor0(0);
+ Register args0(1);
+ operands[0] = constructor0.ToRawOperand();
+ operands[1] = args0.ToRawOperand();
+ operands[2] = 1;
+ translator()->TranslateInputRegisters(Bytecode::kNew, operands, 3);
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(0, move_count());
+
+ // Bytecode::kNewWide with valid range operand.
+ Register constructor1(128);
+ Register constructor1_translated(constructor1.index() + window_width());
+ Register args1(129);
+ Register args1_translated(args1.index() + window_width());
+ operands[0] = constructor1.ToRawOperand();
+ operands[1] = args1.ToRawOperand();
+ operands[2] = 3;
+ translator()->TranslateInputRegisters(Bytecode::kNewWide, operands, 3);
+ translator()->TranslateOutputRegisters();
+ EXPECT_EQ(0, move_count());
+}
+
+TEST_F(RegisterTranslatorTest, BadRange0) {
+ // Bytecode::kNew with invalid range operand (kMaybeReg8).
+ Register constructor1(128);
+ Register args1(129);
+ uint32_t operands[] = {constructor1.ToRawOperand(), args1.ToRawOperand(), 3};
+ ASSERT_DEATH_IF_SUPPORTED(
+ translator()->TranslateInputRegisters(Bytecode::kNew, operands, 3),
+ kBadOperandRegex);
+}
+
+TEST_F(RegisterTranslatorTest, BadRange1) {
+ // Bytecode::kForInPrepare with invalid range operand (kRegTriple8)
+ Register for_in_state(160);
+ Register for_in_state_translated(for_in_state.index() + window_width());
+ uint32_t operands[] = {for_in_state.ToRawOperand()};
+ ASSERT_DEATH_IF_SUPPORTED(translator()->TranslateInputRegisters(
+ Bytecode::kForInPrepare, operands, 1),
+ kBadOperandRegex);
+}
+
+TEST_F(RegisterTranslatorTest, BadRange2) {
+ // Bytecode::kForInNext with invalid range operand (kRegPair8)
+ Register receiver(192);
+ Register receiver_translated(receiver.index() + window_width());
+ Register index(193);
+ Register index_translated(index.index() + window_width());
+ Register cache_info_pair(194);
+ Register cache_info_pair_translated(cache_info_pair.index() + window_width());
+ uint32_t operands[] = {receiver.ToRawOperand(), index.ToRawOperand(),
+ cache_info_pair.ToRawOperand()};
+ ASSERT_DEATH_IF_SUPPORTED(
+ translator()->TranslateInputRegisters(Bytecode::kForInNext, operands, 3),
+ kBadOperandRegex);
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/unittests.gyp b/deps/v8/test/unittests/unittests.gyp
index 5339da35fd..638fd847bf 100644
--- a/deps/v8/test/unittests/unittests.gyp
+++ b/deps/v8/test/unittests/unittests.gyp
@@ -60,10 +60,9 @@
'compiler/instruction-selector-unittest.h',
'compiler/instruction-sequence-unittest.cc',
'compiler/instruction-sequence-unittest.h',
- 'compiler/interpreter-assembler-unittest.cc',
- 'compiler/interpreter-assembler-unittest.h',
+ 'compiler/int64-lowering-unittest.cc',
'compiler/js-builtin-reducer-unittest.cc',
- 'compiler/js-context-relaxation-unittest.cc',
+ 'compiler/js-create-lowering-unittest.cc',
'compiler/js-intrinsic-lowering-unittest.cc',
'compiler/js-operator-unittest.cc',
'compiler/js-typed-lowering-unittest.cc',
@@ -86,6 +85,7 @@
'compiler/schedule-unittest.cc',
'compiler/select-lowering-unittest.cc',
'compiler/scheduler-unittest.cc',
+ 'compiler/scheduler-rpo-unittest.cc',
'compiler/simplified-operator-reducer-unittest.cc',
'compiler/simplified-operator-unittest.cc',
'compiler/state-values-utils-unittest.cc',
@@ -99,6 +99,9 @@
'interpreter/bytecode-array-iterator-unittest.cc',
'interpreter/bytecode-register-allocator-unittest.cc',
'interpreter/constant-array-builder-unittest.cc',
+ 'interpreter/interpreter-assembler-unittest.cc',
+ 'interpreter/interpreter-assembler-unittest.h',
+ 'interpreter/register-translator-unittest.cc',
'libplatform/default-platform-unittest.cc',
'libplatform/task-queue-unittest.cc',
'libplatform/worker-thread-unittest.cc',
@@ -107,6 +110,7 @@
'heap/memory-reducer-unittest.cc',
'heap/heap-unittest.cc',
'heap/scavenge-job-unittest.cc',
+ 'heap/slot-set-unittest.cc',
'locked-queue-unittest.cc',
'run-all-unittests.cc',
'runtime/runtime-interpreter-unittest.cc',
@@ -114,6 +118,7 @@
'test-utils.cc',
'wasm/ast-decoder-unittest.cc',
'wasm/encoder-unittest.cc',
+ 'wasm/loop-assignment-analysis-unittest.cc',
'wasm/module-decoder-unittest.cc',
'wasm/wasm-macro-gen-unittest.cc',
],
diff --git a/deps/v8/test/unittests/wasm/ast-decoder-unittest.cc b/deps/v8/test/unittests/wasm/ast-decoder-unittest.cc
index 923c554604..672158714a 100644
--- a/deps/v8/test/unittests/wasm/ast-decoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/ast-decoder-unittest.cc
@@ -35,6 +35,8 @@ static const WasmOpcode kInt32BinopOpcodes[] = {
kExprI32Shl, kExprI32ShrU, kExprI32ShrS, kExprI32Eq, kExprI32LtS,
kExprI32LeS, kExprI32LtU, kExprI32LeU};
+#define WASM_BRV_IF_ZERO(depth, val) \
+ kExprBrIf, static_cast<byte>(depth), val, WASM_ZERO
#define EXPECT_VERIFIES(env, x) Verify(kSuccess, env, x, x + arraysize(x))
@@ -87,10 +89,10 @@ class WasmDecoderTest : public TestWithZone {
static void init_env(FunctionEnv* env, FunctionSig* sig) {
env->module = nullptr;
env->sig = sig;
- env->local_int32_count = 0;
- env->local_int64_count = 0;
- env->local_float32_count = 0;
- env->local_float64_count = 0;
+ env->local_i32_count = 0;
+ env->local_i64_count = 0;
+ env->local_f32_count = 0;
+ env->local_f64_count = 0;
env->SumLocals();
}
@@ -179,9 +181,9 @@ static FunctionEnv CreateInt32FunctionEnv(FunctionSig* sig, int count) {
FunctionEnv env;
env.module = nullptr;
env.sig = sig;
- env.local_int32_count = count;
- env.local_float64_count = 0;
- env.local_float32_count = 0;
+ env.local_i32_count = count;
+ env.local_f64_count = 0;
+ env.local_f32_count = 0;
env.total_locals = static_cast<unsigned>(count + sig->parameter_count());
return env;
}
@@ -251,9 +253,6 @@ TEST_F(WasmDecoderTest, Int64Const) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, Float32Const) {
byte code[] = {kExprF32Const, 0, 0, 0, 0};
float* ptr = reinterpret_cast<float*>(code + 1);
@@ -273,8 +272,6 @@ TEST_F(WasmDecoderTest, Float64Const) {
}
}
-#endif
-
TEST_F(WasmDecoderTest, Int32Const_off_end) {
byte code[] = {kExprI32Const, 0xaa, 0xbb, 0xcc, 0x44};
@@ -338,7 +335,7 @@ TEST_F(WasmDecoderTest, GetLocal_off_end) {
TEST_F(WasmDecoderTest, GetLocal_varint) {
- env_i_i.local_int32_count = 1000000000;
+ env_i_i.local_i32_count = 1000000000;
env_i_i.total_locals += 1000000000;
{
@@ -532,16 +529,11 @@ TEST_F(WasmDecoderTest, ExprBlock1b) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, ExprBlock1c) {
static const byte code[] = {kExprBlock, 1, kExprF32Const, 0, 0, 0, 0};
EXPECT_VERIFIES(&env_f_ff, code);
}
-#endif
-
TEST_F(WasmDecoderTest, IfEmpty) {
static const byte code[] = {kExprIf, kExprGetLocal, 0, kExprNop};
@@ -704,9 +696,6 @@ TEST_F(WasmDecoderTest, ReturnVoid2) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, ReturnVoid3) {
EXPECT_VERIFIES_INLINE(&env_v_v, kExprI8Const, 0);
EXPECT_VERIFIES_INLINE(&env_v_v, kExprI32Const, 0, 0, 0, 0);
@@ -717,8 +706,6 @@ TEST_F(WasmDecoderTest, ReturnVoid3) {
EXPECT_VERIFIES_INLINE(&env_v_i, kExprGetLocal, 0);
}
-#endif
-
TEST_F(WasmDecoderTest, Unreachable1) {
EXPECT_VERIFIES_INLINE(&env_v_v, kExprUnreachable);
@@ -881,9 +868,6 @@ TEST_F(WasmDecoderTest, MacrosStmt) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, MacrosBreak) {
EXPECT_VERIFIES_INLINE(&env_v_v, WASM_LOOP(1, WASM_BREAK(0)));
@@ -895,8 +879,6 @@ TEST_F(WasmDecoderTest, MacrosBreak) {
WASM_LOOP(1, WASM_BREAKV(0, WASM_F64(0.0))));
}
-#endif
-
TEST_F(WasmDecoderTest, MacrosContinue) {
EXPECT_VERIFIES_INLINE(&env_v_v, WASM_LOOP(1, WASM_CONTINUE(0)));
@@ -1204,14 +1186,13 @@ namespace {
class TestModuleEnv : public ModuleEnv {
public:
TestModuleEnv() {
- mem_start = 0;
- mem_end = 0;
+ instance = nullptr;
module = &mod;
linker = nullptr;
- function_code = nullptr;
mod.globals = new std::vector<WasmGlobal>;
mod.signatures = new std::vector<FunctionSig*>;
mod.functions = new std::vector<WasmFunction>;
+ mod.import_table = new std::vector<WasmImport>;
}
byte AddGlobal(MachineType mem_type) {
mod.globals->push_back({0, mem_type, 0, false});
@@ -1228,6 +1209,11 @@ class TestModuleEnv : public ModuleEnv {
CHECK(mod.functions->size() <= 127);
return static_cast<byte>(mod.functions->size() - 1);
}
+ byte AddImport(FunctionSig* sig) {
+ mod.import_table->push_back({sig, 0, 0});
+ CHECK(mod.import_table->size() <= 127);
+ return static_cast<byte>(mod.import_table->size() - 1);
+ }
private:
WasmModule mod;
@@ -1265,9 +1251,6 @@ TEST_F(WasmDecoderTest, CallsWithTooFewArguments) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, CallsWithSpilloverArgs) {
static LocalType a_i_ff[] = {kAstI32, kAstF32, kAstF32};
FunctionSig sig_i_ff(1, 2, a_i_ff);
@@ -1331,8 +1314,6 @@ TEST_F(WasmDecoderTest, CallsWithMismatchedSigs3) {
EXPECT_FAILURE_INLINE(env, WASM_CALL_FUNCTION(1, WASM_F32(17.6)));
}
-#endif
-
TEST_F(WasmDecoderTest, SimpleIndirectCalls) {
FunctionEnv* env = &env_i_i;
@@ -1389,6 +1370,39 @@ TEST_F(WasmDecoderTest, IndirectCallsWithMismatchedSigs3) {
EXPECT_FAILURE_INLINE(env, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_F32(17.6)));
}
+TEST_F(WasmDecoderTest, SimpleImportCalls) {
+ FunctionEnv* env = &env_i_i;
+ TestModuleEnv module_env;
+ env->module = &module_env;
+
+ byte f0 = module_env.AddImport(sigs.i_v());
+ byte f1 = module_env.AddImport(sigs.i_i());
+ byte f2 = module_env.AddImport(sigs.i_ii());
+
+ EXPECT_VERIFIES_INLINE(env, WASM_CALL_IMPORT0(f0));
+ EXPECT_VERIFIES_INLINE(env, WASM_CALL_IMPORT(f1, WASM_I8(22)));
+ EXPECT_VERIFIES_INLINE(env, WASM_CALL_IMPORT(f2, WASM_I8(32), WASM_I8(72)));
+}
+
+TEST_F(WasmDecoderTest, ImportCallsWithMismatchedSigs3) {
+ FunctionEnv* env = &env_i_i;
+ TestModuleEnv module_env;
+ env->module = &module_env;
+
+ byte f0 = module_env.AddImport(sigs.i_f());
+
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT0(f0));
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f0, WASM_I8(17)));
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f0, WASM_I64(27)));
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f0, WASM_F64(37.2)));
+
+ byte f1 = module_env.AddImport(sigs.i_d());
+
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT0(f1));
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f1, WASM_I8(16)));
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f1, WASM_I64(16)));
+ EXPECT_FAILURE_INLINE(env, WASM_CALL_IMPORT(f1, WASM_F32(17.6)));
+}
TEST_F(WasmDecoderTest, Int32Globals) {
FunctionEnv* env = &env_i_i;
@@ -1575,28 +1589,22 @@ TEST_F(WasmDecoderTest, BreakNesting3) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, BreaksWithMultipleTypes) {
EXPECT_FAILURE_INLINE(
- &env_i_i,
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(7)), WASM_F32(7.7)));
- EXPECT_FAILURE_INLINE(&env_i_i,
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(7)),
- WASM_BRV_IF(0, WASM_ZERO, WASM_F32(7.7))));
+ &env_i_i, WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)), WASM_F32(7.7)));
+
EXPECT_FAILURE_INLINE(&env_i_i,
- WASM_BLOCK(3, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(8)),
- WASM_BRV_IF(0, WASM_ZERO, WASM_I8(0)),
- WASM_BRV_IF(0, WASM_ZERO, WASM_F32(7.7))));
+ WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)),
+ WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
EXPECT_FAILURE_INLINE(&env_i_i,
- WASM_BLOCK(3, WASM_BRV_IF(0, WASM_ZERO, WASM_I8(9)),
- WASM_BRV_IF(0, WASM_ZERO, WASM_F32(7.7)),
- WASM_BRV_IF(0, WASM_ZERO, WASM_I8(11))));
+ WASM_BLOCK(3, WASM_BRV_IF_ZERO(0, WASM_I8(8)),
+ WASM_BRV_IF_ZERO(0, WASM_I8(0)),
+ WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
+ EXPECT_FAILURE_INLINE(&env_i_i, WASM_BLOCK(3, WASM_BRV_IF_ZERO(0, WASM_I8(9)),
+ WASM_BRV_IF_ZERO(0, WASM_F32(7.7)),
+ WASM_BRV_IF_ZERO(0, WASM_I8(11))));
}
-#endif
-
TEST_F(WasmDecoderTest, BreakNesting_6_levels) {
for (int mask = 0; mask < 64; mask++) {
@@ -1630,9 +1638,6 @@ TEST_F(WasmDecoderTest, BreakNesting_6_levels) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, ExprBreak_TypeCheck) {
FunctionEnv* envs[] = {&env_i_i, &env_l_l, &env_f_ff, &env_d_dd};
for (size_t i = 0; i < arraysize(envs); i++) {
@@ -1655,17 +1660,14 @@ TEST_F(WasmDecoderTest, ExprBreak_TypeCheck) {
WASM_F64(1.2)));
}
-#endif
-
TEST_F(WasmDecoderTest, ExprBreak_TypeCheckAll) {
byte code1[] = {WASM_BLOCK(2,
WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
WASM_GET_LOCAL(1))};
- byte code2[] = {WASM_BLOCK(
- 2, WASM_IF(WASM_ZERO, WASM_BRV_IF(0, WASM_ZERO, WASM_GET_LOCAL(0))),
- WASM_GET_LOCAL(1))};
-
+ byte code2[] = {
+ WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(0))),
+ WASM_GET_LOCAL(1))};
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
@@ -1715,37 +1717,42 @@ TEST_F(WasmDecoderTest, ExprBr_Unify) {
}
}
+TEST_F(WasmDecoderTest, ExprBrIf_cond_type) {
+ FunctionEnv env;
+ byte code[] = {
+ WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))};
+ for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
+ for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
+ LocalType types[] = {kLocalTypes[i], kLocalTypes[j]};
+ FunctionSig sig(0, 2, types);
+ init_env(&env, &sig);
-TEST_F(WasmDecoderTest, ExprBrIf_type) {
- EXPECT_VERIFIES_INLINE(
- &env_i_i,
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)),
- WASM_GET_LOCAL(0)));
- EXPECT_FAILURE_INLINE(
- &env_d_dd,
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)),
- WASM_GET_LOCAL(0)));
+ if (types[1] == kAstI32) {
+ EXPECT_VERIFIES(&env, code);
+ } else {
+ EXPECT_FAILURE(&env, code);
+ }
+ }
+ }
+}
+TEST_F(WasmDecoderTest, ExprBrIf_val_type) {
FunctionEnv env;
+ byte code[] = {
+ WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)),
+ WASM_GET_LOCAL(0))};
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
- LocalType type = kLocalTypes[i];
- LocalType storage[] = {kAstI32, kAstI32, type};
- FunctionSig sig(1, 2, storage);
- init_env(&env, &sig); // (i32, X) -> i32
-
- byte code1[] = {
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)),
- WASM_GET_LOCAL(0))};
-
- byte code2[] = {
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)),
- WASM_GET_LOCAL(0))};
- if (type == kAstI32) {
- EXPECT_VERIFIES(&env, code1);
- EXPECT_VERIFIES(&env, code2);
- } else {
- EXPECT_FAILURE(&env, code1);
- EXPECT_FAILURE(&env, code2);
+ for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
+ LocalType types[] = {kLocalTypes[i], kLocalTypes[i], kLocalTypes[j],
+ kAstI32};
+ FunctionSig sig(1, 3, types);
+ init_env(&env, &sig);
+
+ if (i == j) {
+ EXPECT_VERIFIES(&env, code);
+ } else {
+ EXPECT_FAILURE(&env, code);
+ }
}
}
}
@@ -1761,13 +1768,10 @@ TEST_F(WasmDecoderTest, ExprBrIf_Unify) {
FunctionSig sig(1, 2, storage);
init_env(&env, &sig); // (i32, X) -> i32
- byte code1[] = {
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_ZERO, WASM_GET_LOCAL(which)),
- WASM_GET_LOCAL(which ^ 1))};
- byte code2[] = {
- WASM_LOOP(2, WASM_BRV_IF(1, WASM_ZERO, WASM_GET_LOCAL(which)),
- WASM_GET_LOCAL(which ^ 1))};
-
+ byte code1[] = {WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(which)),
+ WASM_GET_LOCAL(which ^ 1))};
+ byte code2[] = {WASM_LOOP(2, WASM_BRV_IF_ZERO(1, WASM_GET_LOCAL(which)),
+ WASM_GET_LOCAL(which ^ 1))};
if (type == kAstI32) {
EXPECT_VERIFIES(&env, code1);
@@ -1800,6 +1804,12 @@ TEST_F(WasmDecoderTest, TableSwitch0c) {
EXPECT_VERIFIES(&env_v_v, code);
}
+TEST_F(WasmDecoderTest, TableSwitch0d) {
+ static byte code[] = {
+ WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(1)),
+ WASM_I8(67))};
+ EXPECT_VERIFIES(&env_v_v, code);
+}
TEST_F(WasmDecoderTest, TableSwitch1) {
static byte code[] = {WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
@@ -1831,9 +1841,6 @@ TEST_F(WasmDecoderTest, TableSwitch2) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, TableSwitch1b) {
EXPECT_VERIFIES_INLINE(&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_ZERO));
@@ -1845,29 +1852,25 @@ TEST_F(WasmDecoderTest, TableSwitch1b) {
WASM_TABLESWITCH_BODY(WASM_ZERO, WASM_F64(0.0)));
}
-#endif
-
-
-TEST_F(WasmDecoderTest, TableSwitch_br) {
- EXPECT_VERIFIES_INLINE(&env_i_i, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)),
- WASM_GET_LOCAL(0));
+TEST_F(WasmDecoderTest, TableSwitch_br1) {
for (int depth = 0; depth < 2; depth++) {
- EXPECT_VERIFIES_INLINE(
- &env_i_i, WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)),
- WASM_GET_LOCAL(0)));
+ byte code[] = {WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)),
+ WASM_GET_LOCAL(0))};
+ EXPECT_VERIFIES(&env_v_i, code);
+ EXPECT_FAILURE(&env_i_i, code);
}
}
TEST_F(WasmDecoderTest, TableSwitch_invalid_br) {
for (int depth = 1; depth < 4; depth++) {
- EXPECT_FAILURE_INLINE(&env_i_i,
+ EXPECT_FAILURE_INLINE(&env_v_i,
WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)),
WASM_GET_LOCAL(0));
EXPECT_FAILURE_INLINE(
- &env_i_i,
- WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth + 1)),
- WASM_GET_LOCAL(0)));
+ &env_v_i,
+ WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(depth), WASM_CASE_BR(depth)),
+ WASM_GET_LOCAL(0));
}
}
@@ -1880,17 +1883,12 @@ TEST_F(WasmDecoderTest, TableSwitch_invalid_case_ref) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, TableSwitch1_br) {
EXPECT_VERIFIES_INLINE(
&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)),
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_ZERO)));
}
-#endif
-
TEST_F(WasmDecoderTest, TableSwitch2_br) {
EXPECT_VERIFIES_INLINE(
@@ -1914,9 +1912,6 @@ TEST_F(WasmDecoderTest, TableSwitch2x2) {
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST_F(WasmDecoderTest, ExprBreakNesting1) {
EXPECT_VERIFIES_INLINE(&env_v_v, WASM_BLOCK(1, WASM_BRV(0, WASM_ZERO)));
EXPECT_VERIFIES_INLINE(&env_v_v, WASM_BLOCK(1, WASM_BR(0)));
@@ -1934,18 +1929,56 @@ TEST_F(WasmDecoderTest, ExprBreakNesting1) {
EXPECT_VERIFIES_INLINE(&env_v_v, WASM_LOOP(1, WASM_BR(1)));
}
-#endif
-
TEST_F(WasmDecoderTest, Select) {
EXPECT_VERIFIES_INLINE(
+ &env_i_i, WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(&env_f_ff,
+ WASM_SELECT(WASM_F32(0.0), WASM_F32(0.0), WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(&env_d_dd,
+ WASM_SELECT(WASM_F64(0.0), WASM_F64(0.0), WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(&env_l_l,
+ WASM_SELECT(WASM_I64(0), WASM_I64(0), WASM_ZERO));
+}
+
+TEST_F(WasmDecoderTest, Select_fail1) {
+ EXPECT_FAILURE_INLINE(&env_i_i, WASM_SELECT(WASM_F32(0.0), WASM_GET_LOCAL(0),
+ WASM_GET_LOCAL(0)));
+ EXPECT_FAILURE_INLINE(&env_i_i, WASM_SELECT(WASM_GET_LOCAL(0), WASM_F32(0.0),
+ WASM_GET_LOCAL(0)));
+ EXPECT_FAILURE_INLINE(
&env_i_i,
- WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+ WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_F32(0.0)));
}
+TEST_F(WasmDecoderTest, Select_fail2) {
+ for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
+ LocalType type = kLocalTypes[i];
+ if (type == kAstI32) continue;
+
+ LocalType types[] = {type, kAstI32, type};
+ FunctionSig sig(1, 2, types);
+ FunctionEnv env;
+ init_env(&env, &sig);
+
+ EXPECT_VERIFIES_INLINE(
+ &env,
+ WASM_SELECT(WASM_GET_LOCAL(1), WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)));
+
+ EXPECT_FAILURE_INLINE(
+ &env,
+ WASM_SELECT(WASM_GET_LOCAL(1), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+ EXPECT_FAILURE_INLINE(
+ &env,
+ WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)));
+
+ EXPECT_FAILURE_INLINE(
+ &env,
+ WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+ }
+}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
TEST_F(WasmDecoderTest, Select_TypeCheck) {
EXPECT_FAILURE_INLINE(&env_i_i, WASM_SELECT(WASM_F32(9.9), WASM_GET_LOCAL(0),
@@ -1958,22 +1991,18 @@ TEST_F(WasmDecoderTest, Select_TypeCheck) {
&env_i_i, WASM_SELECT(WASM_F32(9.9), WASM_GET_LOCAL(0), WASM_I64(0)));
}
-#endif
-
class WasmOpcodeLengthTest : public TestWithZone {
public:
WasmOpcodeLengthTest() : TestWithZone() {}
};
-
-#define EXPECT_LENGTH(expected, opcode) \
- { \
- static const byte code[] = {opcode, 0, 0, 0, 0, 0, 0, 0, 0}; \
- EXPECT_EQ(expected, OpcodeLength(code)); \
+#define EXPECT_LENGTH(expected, opcode) \
+ { \
+ static const byte code[] = {opcode, 0, 0, 0, 0, 0, 0, 0, 0}; \
+ EXPECT_EQ(expected, OpcodeLength(code, code + sizeof(code))); \
}
-
TEST_F(WasmOpcodeLengthTest, Statements) {
EXPECT_LENGTH(1, kExprNop);
EXPECT_LENGTH(2, kExprBlock);
@@ -1997,6 +2026,7 @@ TEST_F(WasmOpcodeLengthTest, MiscExpressions) {
EXPECT_LENGTH(2, kExprLoadGlobal);
EXPECT_LENGTH(2, kExprStoreGlobal);
EXPECT_LENGTH(2, kExprCallFunction);
+ EXPECT_LENGTH(2, kExprCallImport);
EXPECT_LENGTH(2, kExprCallIndirect);
EXPECT_LENGTH(1, kExprIf);
EXPECT_LENGTH(1, kExprIfElse);
@@ -2014,11 +2044,11 @@ TEST_F(WasmOpcodeLengthTest, VariableLength) {
byte size5[] = {kExprLoadGlobal, 1 | 0x80, 2 | 0x80, 3 | 0x80, 4};
byte size6[] = {kExprLoadGlobal, 1 | 0x80, 2 | 0x80, 3 | 0x80, 4 | 0x80, 5};
- EXPECT_EQ(2, OpcodeLength(size2));
- EXPECT_EQ(3, OpcodeLength(size3));
- EXPECT_EQ(4, OpcodeLength(size4));
- EXPECT_EQ(5, OpcodeLength(size5));
- EXPECT_EQ(6, OpcodeLength(size6));
+ EXPECT_EQ(2, OpcodeLength(size2, size2 + sizeof(size2)));
+ EXPECT_EQ(3, OpcodeLength(size3, size3 + sizeof(size3)));
+ EXPECT_EQ(4, OpcodeLength(size4, size4 + sizeof(size4)));
+ EXPECT_EQ(5, OpcodeLength(size5, size5 + sizeof(size5)));
+ EXPECT_EQ(6, OpcodeLength(size6, size6 + sizeof(size6)));
}
@@ -2183,14 +2213,12 @@ class WasmOpcodeArityTest : public TestWithZone {
WasmOpcodeArityTest() : TestWithZone() {}
};
-
-#define EXPECT_ARITY(expected, ...) \
- { \
- static const byte code[] = {__VA_ARGS__}; \
- EXPECT_EQ(expected, OpcodeArity(&env, code)); \
+#define EXPECT_ARITY(expected, ...) \
+ { \
+ static const byte code[] = {__VA_ARGS__}; \
+ EXPECT_EQ(expected, OpcodeArity(&env, code, code + sizeof(code))); \
}
-
TEST_F(WasmOpcodeArityTest, Control) {
FunctionEnv env;
EXPECT_ARITY(0, kExprNop);
@@ -2249,12 +2277,16 @@ TEST_F(WasmOpcodeArityTest, Calls) {
module.AddSignature(sigs.f_ff());
module.AddSignature(sigs.i_d());
+ module.AddImport(sigs.f_ff());
+ module.AddImport(sigs.i_d());
+
{
FunctionEnv env;
WasmDecoderTest::init_env(&env, sigs.i_ii());
env.module = &module;
EXPECT_ARITY(2, kExprCallFunction, 0);
+ EXPECT_ARITY(2, kExprCallImport, 0);
EXPECT_ARITY(3, kExprCallIndirect, 0);
EXPECT_ARITY(1, kExprBr);
EXPECT_ARITY(2, kExprBrIf);
@@ -2266,6 +2298,7 @@ TEST_F(WasmOpcodeArityTest, Calls) {
env.module = &module;
EXPECT_ARITY(1, kExprCallFunction, 1);
+ EXPECT_ARITY(1, kExprCallImport, 1);
EXPECT_ARITY(2, kExprCallIndirect, 1);
EXPECT_ARITY(1, kExprBr);
EXPECT_ARITY(2, kExprBrIf);
diff --git a/deps/v8/test/unittests/wasm/encoder-unittest.cc b/deps/v8/test/unittests/wasm/encoder-unittest.cc
index 156cf6b1e5..e09e71aeb8 100644
--- a/deps/v8/test/unittests/wasm/encoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/encoder-unittest.cc
@@ -56,28 +56,28 @@ TEST_F(EncoderTest, Function_Builder_Variable_Indexing) {
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
- uint16_t local_float32 = function->AddLocal(kAstF32);
+ uint16_t local_f32 = function->AddLocal(kAstF32);
uint16_t param_float32 = function->AddParam(kAstF32);
- uint16_t local_int32 = function->AddLocal(kAstI32);
- uint16_t local_float64 = function->AddLocal(kAstF64);
- uint16_t local_int64 = function->AddLocal(kAstI64);
+ uint16_t local_i32 = function->AddLocal(kAstI32);
+ uint16_t local_f64 = function->AddLocal(kAstF64);
+ uint16_t local_i64 = function->AddLocal(kAstI64);
uint16_t param_int32 = function->AddParam(kAstI32);
- uint16_t local_int32_2 = function->AddLocal(kAstI32);
+ uint16_t local_i32_2 = function->AddLocal(kAstI32);
byte code[] = {kExprGetLocal, static_cast<uint8_t>(param_float32)};
uint32_t local_indices[] = {1};
function->EmitCode(code, sizeof(code), local_indices, 1);
code[1] = static_cast<uint8_t>(param_int32);
function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_int32);
+ code[1] = static_cast<uint8_t>(local_i32);
function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_int32_2);
+ code[1] = static_cast<uint8_t>(local_i32_2);
function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_int64);
+ code[1] = static_cast<uint8_t>(local_i64);
function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_float32);
+ code[1] = static_cast<uint8_t>(local_f32);
function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_float64);
+ code[1] = static_cast<uint8_t>(local_f64);
function->EmitCode(code, sizeof(code), local_indices, 1);
WasmFunctionEncoder* f = function->Build(&zone, builder);
diff --git a/deps/v8/test/unittests/wasm/loop-assignment-analysis-unittest.cc b/deps/v8/test/unittests/wasm/loop-assignment-analysis-unittest.cc
new file mode 100644
index 0000000000..958621970c
--- /dev/null
+++ b/deps/v8/test/unittests/wasm/loop-assignment-analysis-unittest.cc
@@ -0,0 +1,211 @@
+// 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 "test/unittests/test-utils.h"
+
+#include "src/v8.h"
+
+#include "test/cctest/wasm/test-signatures.h"
+
+#include "src/bit-vector.h"
+#include "src/objects.h"
+
+#include "src/wasm/ast-decoder.h"
+#include "src/wasm/wasm-macro-gen.h"
+#include "src/wasm/wasm-module.h"
+
+#define WASM_SET_ZERO(i) WASM_SET_LOCAL(i, WASM_ZERO)
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class WasmLoopAssignmentAnalyzerTest : public TestWithZone {
+ public:
+ WasmLoopAssignmentAnalyzerTest() : TestWithZone(), sigs() {
+ init_env(&env, sigs.v_v());
+ }
+
+ TestSignatures sigs;
+ FunctionEnv env;
+
+ static void init_env(FunctionEnv* env, FunctionSig* sig) {
+ env->module = nullptr;
+ env->sig = sig;
+ env->local_i32_count = 0;
+ env->local_i64_count = 0;
+ env->local_f32_count = 0;
+ env->local_f64_count = 0;
+ env->SumLocals();
+ }
+
+ BitVector* Analyze(const byte* start, const byte* end) {
+ return AnalyzeLoopAssignmentForTesting(zone(), &env, start, end);
+ }
+};
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Empty0) {
+ byte code[] = { 0 };
+ BitVector* assigned = Analyze(code, code);
+ CHECK_NULL(assigned);
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) {
+ byte code[] = {kExprLoop, 0};
+ for (int i = 0; i < 5; i++) {
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ CHECK_EQ(false, assigned->Contains(j));
+ }
+ env.AddLocals(kAstI32, 1);
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
+ env.AddLocals(kAstI32, 5);
+ for (int i = 0; i < 5; i++) {
+ byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i))};
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ CHECK_EQ(j == i, assigned->Contains(j));
+ }
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
+ env.AddLocals(kAstI32, 5);
+ for (int i = 0; i < 5; i++) {
+ byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i)), WASM_SET_ZERO(1)};
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ CHECK_EQ(j == i, assigned->Contains(j));
+ }
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
+ env.AddLocals(kAstI32, 5);
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ byte code[] = {WASM_LOOP(2, WASM_SET_ZERO(i), WASM_SET_ZERO(j))};
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int k = 0; k < assigned->length(); k++) {
+ bool expected = k == i || k == j;
+ CHECK_EQ(expected, assigned->Contains(k));
+ }
+ }
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
+ env.AddLocals(kAstI32, 5);
+ for (int i = 0; i < 5; i++) {
+ byte code[] = {WASM_LOOP(
+ 1, WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))};
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ bool expected = i == j || j == 0 || j == 1;
+ CHECK_EQ(expected, assigned->Contains(j));
+ }
+ }
+}
+
+
+static byte LEBByte(uint32_t val, byte which) {
+ byte b = (val >> (which * 7)) & 0x7F;
+ if (val >> ((which + 1) * 7)) b |= 0x80;
+ return b;
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
+ env.AddLocals(kAstI32, 65000);
+ for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
+ byte code[] = {kExprLoop,
+ 1,
+ kExprSetLocal,
+ LEBByte(i, 0),
+ LEBByte(i, 1),
+ LEBByte(i, 2),
+ 11,
+ 12,
+ 13};
+
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ bool expected = i == j;
+ CHECK_EQ(expected, assigned->Contains(j));
+ }
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
+ env.AddLocals(kAstI32, 3);
+ byte code[] = {
+ WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_SET_ZERO(1)))),
+ WASM_SET_ZERO(0)};
+
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ bool expected = j == 1;
+ CHECK_EQ(expected, assigned->Contains(j));
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
+ env.AddLocals(kAstI32, 5);
+ byte code[] = {
+ WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0),
+ WASM_BRV(0, WASM_SET_LOCAL(
+ 3, WASM_I32_SUB(WASM_GET_LOCAL(0),
+ WASM_I8(1)))))),
+ WASM_GET_LOCAL(0)};
+
+ BitVector* assigned = Analyze(code, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ bool expected = j == 3;
+ CHECK_EQ(expected, assigned->Contains(j));
+ }
+}
+
+
+TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
+ env.AddLocals(kAstI32, 3);
+ const byte kIter = 0;
+ env.AddLocals(kAstF32, 3);
+ const byte kSum = 3;
+
+ byte code[] = {WASM_BLOCK(
+ 3,
+ WASM_WHILE(
+ WASM_GET_LOCAL(kIter),
+ WASM_BLOCK(2, WASM_SET_LOCAL(
+ kSum, WASM_F32_ADD(
+ WASM_GET_LOCAL(kSum),
+ WASM_LOAD_MEM(MachineType::Float32(),
+ WASM_GET_LOCAL(kIter)))),
+ WASM_SET_LOCAL(kIter, WASM_I32_SUB(WASM_GET_LOCAL(kIter),
+ WASM_I8(4))))),
+ WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)),
+ WASM_GET_LOCAL(kIter))};
+
+ BitVector* assigned = Analyze(code + 2, code + arraysize(code));
+ for (int j = 0; j < assigned->length(); j++) {
+ bool expected = j == kIter || j == kSum;
+ CHECK_EQ(expected, assigned->Contains(j));
+ }
+}
+
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/wasm/module-decoder-unittest.cc b/deps/v8/test/unittests/wasm/module-decoder-unittest.cc
index 0738b5909b..467ffcc232 100644
--- a/deps/v8/test/unittests/wasm/module-decoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/module-decoder-unittest.cc
@@ -45,6 +45,15 @@ struct LocalTypePair {
{kLocalF64, kAstF64}};
+// TODO(titzer): use these macros everywhere below.
+#define U32_LE(v) \
+ static_cast<byte>(v), static_cast<byte>((v) >> 8), \
+ static_cast<byte>((v) >> 16), static_cast<byte>((v) >> 24)
+
+
+#define U16_LE(v) static_cast<byte>(v), static_cast<byte>((v) >> 8)
+
+
TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
static const byte data[1]{kDeclEnd};
{
@@ -61,7 +70,7 @@ TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
TEST_F(WasmModuleVerifyTest, OneGlobal) {
- const byte data[] = {
+ static const byte data[] = {
kDeclGlobals,
1,
0,
@@ -100,7 +109,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
- const byte data[] = {
+ static const byte data[] = {
kDeclGlobals, 0, // declare 0 globals
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
@@ -125,7 +134,7 @@ static void AppendUint32v(std::vector<byte>& buffer, uint32_t val) {
TEST_F(WasmModuleVerifyTest, NGlobals) {
- const byte data[] = {
+ static const byte data[] = {
0, 0, 0, 0, // name offset
kMemI32, // memory type
0, // exported
@@ -146,7 +155,7 @@ TEST_F(WasmModuleVerifyTest, NGlobals) {
TEST_F(WasmModuleVerifyTest, GlobalWithInvalidNameOffset) {
- const byte data[] = {
+ static const byte data[] = {
kDeclGlobals,
1, // declare one global
0,
@@ -162,7 +171,7 @@ TEST_F(WasmModuleVerifyTest, GlobalWithInvalidNameOffset) {
TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
- const byte data[] = {
+ static const byte data[] = {
kDeclGlobals,
1, // declare one global
0,
@@ -178,7 +187,7 @@ TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
TEST_F(WasmModuleVerifyTest, TwoGlobals) {
- const byte data[] = {
+ static const byte data[] = {
kDeclGlobals,
2,
0,
@@ -333,10 +342,10 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
- EXPECT_EQ(523, function->local_int32_count);
- EXPECT_EQ(1037, function->local_int64_count);
- EXPECT_EQ(1551, function->local_float32_count);
- EXPECT_EQ(2065, function->local_float64_count);
+ EXPECT_EQ(523, function->local_i32_count);
+ EXPECT_EQ(1037, function->local_i64_count);
+ EXPECT_EQ(1551, function->local_f32_count);
+ EXPECT_EQ(2065, function->local_f64_count);
EXPECT_TRUE(function->exported);
EXPECT_FALSE(function->external);
@@ -373,10 +382,10 @@ TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
EXPECT_EQ(0, function->code_start_offset);
EXPECT_EQ(0, function->code_end_offset);
- EXPECT_EQ(0, function->local_int32_count);
- EXPECT_EQ(0, function->local_int64_count);
- EXPECT_EQ(0, function->local_float32_count);
- EXPECT_EQ(0, function->local_float64_count);
+ EXPECT_EQ(0, function->local_i32_count);
+ EXPECT_EQ(0, function->local_i64_count);
+ EXPECT_EQ(0, function->local_f32_count);
+ EXPECT_EQ(0, function->local_f64_count);
EXPECT_FALSE(function->exported);
EXPECT_TRUE(function->external);
@@ -410,10 +419,10 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
- EXPECT_EQ(0, function->local_int32_count);
- EXPECT_EQ(0, function->local_int64_count);
- EXPECT_EQ(0, function->local_float32_count);
- EXPECT_EQ(0, function->local_float64_count);
+ EXPECT_EQ(0, function->local_i32_count);
+ EXPECT_EQ(0, function->local_i64_count);
+ EXPECT_EQ(0, function->local_f32_count);
+ EXPECT_EQ(0, function->local_f64_count);
EXPECT_FALSE(function->exported);
EXPECT_FALSE(function->external);
@@ -450,10 +459,10 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
- EXPECT_EQ(513, function->local_int32_count);
- EXPECT_EQ(1027, function->local_int64_count);
- EXPECT_EQ(1541, function->local_float32_count);
- EXPECT_EQ(2055, function->local_float64_count);
+ EXPECT_EQ(513, function->local_i32_count);
+ EXPECT_EQ(1027, function->local_i64_count);
+ EXPECT_EQ(1541, function->local_f32_count);
+ EXPECT_EQ(2055, function->local_f64_count);
EXPECT_FALSE(function->exported);
EXPECT_FALSE(function->external);
@@ -463,10 +472,13 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
- static const byte kCodeStartOffset = 2 + kDeclGlobalSize + 4 + 2 + 17;
+ static const byte kDeclMemorySize = 4;
+ static const byte kCodeStartOffset =
+ 2 + kDeclMemorySize + kDeclGlobalSize + 4 + 2 + 17;
static const byte kCodeEndOffset = kCodeStartOffset + 3;
static const byte data[] = {
+ kDeclMemory, 28, 28, 1,
// global#0 --------------------------------------------------
kDeclGlobals, 1, 0, 0, 0, 0, // name offset
kMemU8, // memory type
@@ -531,24 +543,17 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
TEST_F(WasmModuleVerifyTest, OneDataSegment) {
const byte data[] = {
- kDeclDataSegments,
- 1,
- 0xaa,
- 0xbb,
- 0x09,
+ kDeclMemory, 28, 28, 1, kDeclDataSegments, 1, 0xaa, 0xbb, 0x09,
0, // dest addr
- 11,
- 0,
- 0,
+ 11, 0, 0,
0, // source offset
- 3,
- 0,
- 0,
+ 3, 0, 0,
0, // source size
1, // init
};
{
+ EXPECT_VERIFIES(data);
ModuleResult result = DecodeModule(data, data + arraysize(data));
EXPECT_TRUE(result.ok());
EXPECT_EQ(0, result.val->globals->size());
@@ -565,7 +570,7 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) {
if (result.val) delete result.val;
}
- for (size_t size = 1; size < arraysize(data); size++) {
+ for (size_t size = 5; size < arraysize(data); size++) {
// Should fall off end of module bytes.
ModuleResult result = DecodeModule(data, data + size);
EXPECT_FALSE(result.ok());
@@ -576,32 +581,18 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) {
TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
const byte data[] = {
- kDeclDataSegments,
- 2,
- 0xee,
- 0xff,
- 0x07,
+ kDeclMemory, 28, 28, 1, kDeclDataSegments, 2, 0xee, 0xff, 0x07,
0, // dest addr
- 9,
- 0,
- 0,
+ 9, 0, 0,
0, // #0: source offset
- 4,
- 0,
- 0,
+ 4, 0, 0,
0, // source size
0, // init
- 0xcc,
- 0xdd,
- 0x06,
+ 0xcc, 0xdd, 0x06,
0, // #1: dest addr
- 6,
- 0,
- 0,
+ 6, 0, 0,
0, // source offset
- 10,
- 0,
- 0,
+ 10, 0, 0,
0, // source size
1, // init
};
@@ -629,7 +620,7 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
if (result.val) delete result.val;
}
- for (size_t size = 1; size < arraysize(data); size++) {
+ for (size_t size = 5; size < arraysize(data); size++) {
// Should fall off end of module bytes.
ModuleResult result = DecodeModule(data, data + size);
EXPECT_FALSE(result.ok());
@@ -638,6 +629,71 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
}
+TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidSource) {
+ const int dest_addr = 0x100;
+ const byte mem_size_log2 = 15;
+ const int kDataSize = 19;
+
+ for (int source_offset = 0; source_offset < 5 + kDataSize; source_offset++) {
+ for (int source_size = -1; source_size < 5 + kDataSize; source_size += 3) {
+ byte data[] = {
+ kDeclMemory,
+ mem_size_log2,
+ mem_size_log2,
+ 1,
+ kDeclDataSegments,
+ 1,
+ U32_LE(dest_addr),
+ U32_LE(source_offset),
+ U32_LE(source_size),
+ 1, // init
+ };
+
+ STATIC_ASSERT(kDataSize == arraysize(data));
+
+ if (source_offset < kDataSize && source_size >= 0 &&
+ (source_offset + source_size) <= kDataSize) {
+ EXPECT_VERIFIES(data);
+ } else {
+ EXPECT_FAILURE(data);
+ }
+ }
+ }
+}
+
+
+TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) {
+ const int source_size = 3;
+ const int source_offset = 11;
+
+ for (byte mem_size_log2 = 12; mem_size_log2 < 20; mem_size_log2++) {
+ int mem_size = 1 << mem_size_log2;
+
+ for (int dest_addr = mem_size - source_size;
+ dest_addr < mem_size + source_size; dest_addr++) {
+ byte data[] = {
+ kDeclMemory,
+ mem_size_log2,
+ mem_size_log2,
+ 1,
+ kDeclDataSegments,
+ 1,
+ U32_LE(dest_addr),
+ U32_LE(source_offset),
+ U32_LE(source_size),
+ 1, // init
+ };
+
+ if (dest_addr <= (mem_size - source_size)) {
+ EXPECT_VERIFIES(data);
+ } else {
+ EXPECT_FAILURE(data);
+ }
+ }
+ }
+}
+
+
// To make below tests for indirect calls much shorter.
#define FUNCTION(sig_index, external) \
kDeclFunctionImport, static_cast<byte>(sig_index), \
@@ -848,7 +904,7 @@ class WasmFunctionVerifyTest : public TestWithZone {};
TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
- byte data[] = {
+ static const byte data[] = {
0, kLocalVoid, // signature
3, 0, // local int32 count
4, 0, // local int64 count
@@ -868,10 +924,10 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
EXPECT_EQ(0, function->name_offset);
EXPECT_EQ(arraysize(data) - 1, function->code_start_offset);
EXPECT_EQ(arraysize(data), function->code_end_offset);
- EXPECT_EQ(3, function->local_int32_count);
- EXPECT_EQ(4, function->local_int64_count);
- EXPECT_EQ(5, function->local_float32_count);
- EXPECT_EQ(6, function->local_float64_count);
+ EXPECT_EQ(3, function->local_i32_count);
+ EXPECT_EQ(4, function->local_i64_count);
+ EXPECT_EQ(5, function->local_f32_count);
+ EXPECT_EQ(6, function->local_f64_count);
EXPECT_FALSE(function->external);
EXPECT_FALSE(function->exported);
}
@@ -889,7 +945,7 @@ TEST_F(WasmModuleVerifyTest, WLLSectionNoLen) {
TEST_F(WasmModuleVerifyTest, WLLSectionEmpty) {
- const byte data[] = {
+ static const byte data[] = {
kDeclWLL, 0, // empty section
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
@@ -899,7 +955,7 @@ TEST_F(WasmModuleVerifyTest, WLLSectionEmpty) {
TEST_F(WasmModuleVerifyTest, WLLSectionOne) {
- const byte data[] = {
+ static const byte data[] = {
kDeclWLL,
1, // LEB128 1
0, // one byte section
@@ -911,10 +967,10 @@ TEST_F(WasmModuleVerifyTest, WLLSectionOne) {
TEST_F(WasmModuleVerifyTest, WLLSectionTen) {
- const byte data[] = {
+ static const byte data[] = {
kDeclWLL,
- 10, // LEB128 10
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
+ 10, // LEB128 10
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
EXPECT_TRUE(result.ok());
@@ -923,20 +979,19 @@ TEST_F(WasmModuleVerifyTest, WLLSectionTen) {
TEST_F(WasmModuleVerifyTest, WLLSectionOverflow) {
- const byte data[] = {
+ static const byte data[] = {
kDeclWLL,
- 11, // LEB128 11
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
+ 11, // LEB128 11
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, WLLSectionUnderflow) {
- const byte data[] = {
- kDeclWLL,
- 0xff, 0xff, 0xff, 0xff, 0x0f, // LEB128 0xffffffff
- 1, 2, 3, 4, // 4 byte section
+ static const byte data[] = {
+ kDeclWLL, 0xff, 0xff, 0xff, 0xff, 0x0f, // LEB128 0xffffffff
+ 1, 2, 3, 4, // 4 byte section
};
EXPECT_FAILURE(data);
}
@@ -944,14 +999,92 @@ TEST_F(WasmModuleVerifyTest, WLLSectionUnderflow) {
TEST_F(WasmModuleVerifyTest, WLLSectionLoop) {
// Would infinite loop decoding if wrapping and allowed.
- const byte data[] = {
- kDeclWLL,
- 0xfa, 0xff, 0xff, 0xff, 0x0f, // LEB128 0xfffffffa
- 1, 2, 3, 4, // 4 byte section
+ static const byte data[] = {
+ kDeclWLL, 0xfa, 0xff, 0xff, 0xff, 0x0f, // LEB128 0xfffffffa
+ 1, 2, 3, 4, // 4 byte section
};
EXPECT_FAILURE(data);
}
+TEST_F(WasmModuleVerifyTest, ImportTable_empty) {
+ static const byte data[] = {kDeclSignatures, 0, kDeclImportTable, 0};
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_nosigs) {
+ static const byte data[] = {kDeclImportTable, 0};
+ EXPECT_FAILURE(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
+ static const byte data[] = {
+ kDeclSignatures,
+ 0,
+ kDeclImportTable,
+ 1,
+ 0,
+ 0, // sig index
+ 1,
+ 0,
+ 0,
+ 0, // module name
+ 1,
+ 0,
+ 0,
+ 0 // function name
+ };
+ EXPECT_FAILURE(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
+ static const byte data[] = {
+ kDeclSignatures,
+ 1,
+ 0,
+ static_cast<byte>(kAstStmt),
+ kDeclImportTable,
+ 1,
+ 0,
+ 0, // sig index
+ 1,
+ 0,
+ 0,
+ 0, // module name
+ 1,
+ 0,
+ 0,
+ 0 // function name
+ };
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
+ static const byte data[] = {
+ kDeclSignatures,
+ 1,
+ 0,
+ static_cast<byte>(kAstStmt),
+ kDeclImportTable,
+ 1,
+ 0,
+ 0, // sig index
+ 1,
+ 0,
+ 0,
+ 0, // module name
+ 1,
+ 0,
+ 0,
+ 0 // function name
+ };
+
+ for (size_t length = 5; length < sizeof(data); length++) {
+ ModuleResult result = DecodeModule(data, data + length);
+ EXPECT_FALSE(result.ok());
+ if (result.val) delete result.val;
+ }
+}
+
} // namespace wasm
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/wasm/wasm-macro-gen-unittest.cc b/deps/v8/test/unittests/wasm/wasm-macro-gen-unittest.cc
index c5bb5eca00..f3f604b3ed 100644
--- a/deps/v8/test/unittests/wasm/wasm-macro-gen-unittest.cc
+++ b/deps/v8/test/unittests/wasm/wasm-macro-gen-unittest.cc
@@ -131,15 +131,25 @@ TEST_F(WasmMacroGenTest, Expressions) {
EXPECT_SIZE(6, WASM_LOOP(3, WASM_NOP, WASM_NOP, WASM_ZERO));
}
-
-TEST_F(WasmMacroGenTest, FunctionCalls) {
+TEST_F(WasmMacroGenTest, CallFunction) {
EXPECT_SIZE(2, WASM_CALL_FUNCTION0(0));
EXPECT_SIZE(2, WASM_CALL_FUNCTION0(1));
EXPECT_SIZE(2, WASM_CALL_FUNCTION0(11));
EXPECT_SIZE(4, WASM_CALL_FUNCTION(0, WASM_ZERO));
EXPECT_SIZE(6, WASM_CALL_FUNCTION(1, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(WasmMacroGenTest, CallImport) {
+ EXPECT_SIZE(2, WASM_CALL_IMPORT0(0));
+ EXPECT_SIZE(2, WASM_CALL_IMPORT0(1));
+ EXPECT_SIZE(2, WASM_CALL_IMPORT0(11));
+
+ EXPECT_SIZE(4, WASM_CALL_IMPORT(0, WASM_ZERO));
+ EXPECT_SIZE(6, WASM_CALL_IMPORT(1, WASM_ZERO, WASM_ZERO));
+}
+TEST_F(WasmMacroGenTest, CallIndirect) {
EXPECT_SIZE(4, WASM_CALL_INDIRECT0(0, WASM_ZERO));
EXPECT_SIZE(4, WASM_CALL_INDIRECT0(1, WASM_ZERO));
EXPECT_SIZE(4, WASM_CALL_INDIRECT0(11, WASM_ZERO));