Merge V8 5.2.361.47 DO NOT MERGE
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
FPIIM-449
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/test/unittests/atomic-utils-unittest.cc b/test/unittests/base/atomic-utils-unittest.cc
similarity index 98%
rename from test/unittests/atomic-utils-unittest.cc
rename to test/unittests/base/atomic-utils-unittest.cc
index ad33853..06079fe 100644
--- a/test/unittests/atomic-utils-unittest.cc
+++ b/test/unittests/base/atomic-utils-unittest.cc
@@ -4,11 +4,11 @@
#include <limits.h>
-#include "src/atomic-utils.h"
+#include "src/base/atomic-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
-namespace internal {
+namespace base {
TEST(AtomicNumber, Constructor) {
// Test some common types.
@@ -213,5 +213,5 @@
EXPECT_FALSE(a != b);
}
-} // namespace internal
+} // namespace base
} // namespace v8
diff --git a/test/unittests/base/platform/time-unittest.cc b/test/unittests/base/platform/time-unittest.cc
index b3bfbab..784fbf8 100644
--- a/test/unittests/base/platform/time-unittest.cc
+++ b/test/unittests/base/platform/time-unittest.cc
@@ -16,6 +16,7 @@
#endif
#include "src/base/platform/elapsed-timer.h"
+#include "src/base/platform/platform.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
@@ -182,5 +183,32 @@
}
}
+
+// Disable on windows until it is implemented.
+#if V8_OS_ANDROID || V8_OS_WIN
+#define MAYBE_ThreadNow DISABLED_ThreadNow
+#else
+#define MAYBE_ThreadNow ThreadNow
+#endif
+TEST(ThreadTicks, MAYBE_ThreadNow) {
+ if (ThreadTicks::IsSupported()) {
+ TimeTicks begin = TimeTicks::Now();
+ ThreadTicks begin_thread = ThreadTicks::Now();
+ // Make sure that ThreadNow value is non-zero.
+ EXPECT_GT(begin_thread, ThreadTicks());
+ // Sleep for 10 milliseconds to get the thread de-scheduled.
+ OS::Sleep(base::TimeDelta::FromMilliseconds(10));
+ ThreadTicks end_thread = ThreadTicks::Now();
+ TimeTicks end = TimeTicks::Now();
+ TimeDelta delta = end - begin;
+ TimeDelta delta_thread = end_thread - begin_thread;
+ // Make sure that some thread time have elapsed.
+ EXPECT_GT(delta_thread.InMicroseconds(), 0);
+ // But the thread time is at least 9ms less than clock time.
+ TimeDelta difference = delta - delta_thread;
+ EXPECT_GE(difference.InMicroseconds(), 9000);
+ }
+}
+
} // namespace base
} // namespace v8
diff --git a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 72cfc51..b088d8e 100644
--- a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -2954,6 +2954,78 @@
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
+TEST_F(InstructionSelectorTest, Float32Max) {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const n = m.Float32Max(p0, p1);
+ m.Return(n);
+ Stream s = m.Build(ARMv8);
+ // Float32Max is `(b < a) ? a : b`.
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmFloat32Max, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float32Min) {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const n = m.Float32Min(p0, p1);
+ m.Return(n);
+ Stream s = m.Build(ARMv8);
+ // Float32Min is `(a < b) ? a : b`.
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmFloat32Min, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float64Max) {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const n = m.Float64Max(p0, p1);
+ m.Return(n);
+ Stream s = m.Build(ARMv8);
+ // Float64Max is `(b < a) ? a : b`.
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmFloat64Max, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float64Min) {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const n = m.Float64Min(p0, p1);
+ m.Return(n);
+ Stream s = m.Build(ARMv8);
+ // Float64Min is `(a < b) ? a : b`.
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmFloat64Min, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index 73532aa..1c638b2 100644
--- a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -326,6 +326,52 @@
kArm64Float64ToUint32, MachineType::Uint32()},
MachineType::Float64()}};
+// ARM64 instructions that clear the top 32 bits of the destination.
+const MachInst2 kCanElideChangeUint32ToUint64[] = {
+ {&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
+ MachineType::Int32()},
+ {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
+ kArm64Add32, MachineType::Int32()},
+ {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32,
+ MachineType::Int32()},
+ {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
+ kArm64Sub32, MachineType::Int32()},
+ {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32,
+ MachineType::Int32()},
+ {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32,
+ MachineType::Int32()},
+ {&RawMachineAssembler::Int32Mod, "Int32Mod", kArm64Imod32,
+ MachineType::Int32()},
+ {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
+ MachineType::Int32()},
+ {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
+ kArm64Cmp32, MachineType::Int32()},
+ {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
+ MachineType::Uint32()},
+ {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
+ kArm64Cmp32, MachineType::Uint32()},
+ {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kArm64Umod32,
+ MachineType::Uint32()},
+};
+
} // namespace
@@ -2105,6 +2151,71 @@
InstructionSelectorConversionTest,
::testing::ValuesIn(kConversionInstructions));
+typedef InstructionSelectorTestWithParam<MachInst2>
+ InstructionSelectorElidedChangeUint32ToUint64Test;
+
+TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
+ const MachInst2 binop = GetParam();
+ StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
+ binop.machine_type);
+ m.Return(m.ChangeUint32ToUint64(
+ (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
+ Stream s = m.Build();
+ // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+}
+
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
+ InstructionSelectorElidedChangeUint32ToUint64Test,
+ ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
+
+TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
+ // For each case, make sure the `ChangeUint32ToUint64` node turned into a
+ // no-op.
+
+ // Ldrb
+ {
+ StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
+ MachineType::Int32());
+ m.Return(m.ChangeUint32ToUint64(
+ m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Ldrb, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
+ EXPECT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // Ldrh
+ {
+ StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
+ MachineType::Int32());
+ m.Return(m.ChangeUint32ToUint64(
+ m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64Ldrh, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
+ EXPECT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+ // LdrW
+ {
+ StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
+ MachineType::Int32());
+ m.Return(m.ChangeUint32ToUint64(
+ m.Load(MachineType::Uint32(), m.Parameter(0), m.Parameter(1))));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArm64LdrW, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
+ EXPECT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+}
// -----------------------------------------------------------------------------
// Memory access instructions.
@@ -2244,12 +2355,131 @@
EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
ASSERT_EQ(3U, s[0]->InputCount());
- ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
- EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
+ ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
+ EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(0U, s[0]->OutputCount());
}
}
+TEST_P(InstructionSelectorMemoryAccessTest, StoreZero) {
+ const MemoryAccess memacc = GetParam();
+ TRACED_FOREACH(int32_t, index, memacc.immediates) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer());
+ m.Store(memacc.type.representation(), m.Parameter(0),
+ m.Int32Constant(index), m.Int32Constant(0), kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
+ EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
+ ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
+ EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(0)));
+ EXPECT_EQ(0U, s[0]->OutputCount());
+ }
+}
+
+TEST_P(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
+ const MemoryAccess memacc = GetParam();
+ TRACED_FORRANGE(int, immediate_shift, 0, 4) {
+ // 32 bit shift
+ {
+ StreamBuilder m(this, memacc.type, MachineType::Pointer(),
+ MachineType::Int32());
+ Node* const index =
+ m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
+ m.Return(m.Load(memacc.type, m.Parameter(0), index));
+ Stream s = m.Build();
+ if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ EXPECT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ } else {
+ // Make sure we haven't merged the shift into the load instruction.
+ ASSERT_NE(1U, s.size());
+ EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
+ EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ }
+ }
+ // 64 bit shift
+ {
+ StreamBuilder m(this, memacc.type, MachineType::Pointer(),
+ MachineType::Int64());
+ Node* const index =
+ m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
+ m.Return(m.Load(memacc.type, m.Parameter(0), index));
+ Stream s = m.Build();
+ if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ EXPECT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ } else {
+ // Make sure we haven't merged the shift into the load instruction.
+ ASSERT_NE(1U, s.size());
+ EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
+ EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ }
+ }
+ }
+}
+
+TEST_P(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
+ const MemoryAccess memacc = GetParam();
+ TRACED_FORRANGE(int, immediate_shift, 0, 4) {
+ // 32 bit shift
+ {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
+ MachineType::Int32(), memacc.type);
+ Node* const index =
+ m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
+ m.Store(memacc.type.representation(), m.Parameter(0), index,
+ m.Parameter(2), kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ EXPECT_EQ(4U, s[0]->InputCount());
+ EXPECT_EQ(0U, s[0]->OutputCount());
+ } else {
+ // Make sure we haven't merged the shift into the store instruction.
+ ASSERT_NE(1U, s.size());
+ EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
+ EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ }
+ }
+ // 64 bit shift
+ {
+ StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
+ MachineType::Int64(), memacc.type);
+ Node* const index =
+ m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
+ m.Store(memacc.type.representation(), m.Parameter(0), index,
+ m.Parameter(2), kNoWriteBarrier);
+ m.Return(m.Int64Constant(0));
+ Stream s = m.Build();
+ if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ EXPECT_EQ(4U, s[0]->InputCount());
+ EXPECT_EQ(0U, s[0]->OutputCount());
+ } else {
+ // Make sure we haven't merged the shift into the store instruction.
+ ASSERT_NE(1U, s.size());
+ EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
+ EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+ }
+ }
+ }
+}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
InstructionSelectorMemoryAccessTest,
diff --git a/test/unittests/compiler/change-lowering-unittest.cc b/test/unittests/compiler/change-lowering-unittest.cc
deleted file mode 100644
index fd0766c..0000000
--- a/test/unittests/compiler/change-lowering-unittest.cc
+++ /dev/null
@@ -1,628 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/code-stubs.h"
-#include "src/compiler/change-lowering.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/node-properties.h"
-#include "src/compiler/simplified-operator.h"
-#include "test/unittests/compiler/compiler-test-utils.h"
-#include "test/unittests/compiler/graph-unittest.h"
-#include "test/unittests/compiler/node-test-utils.h"
-#include "testing/gmock-support.h"
-
-using testing::_;
-using testing::AllOf;
-using testing::BitEq;
-using testing::Capture;
-using testing::CaptureEq;
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class ChangeLoweringTest : public TypedGraphTest {
- public:
- ChangeLoweringTest() : simplified_(zone()) {}
-
- virtual MachineRepresentation WordRepresentation() const = 0;
-
- protected:
- bool Is32() const {
- return WordRepresentation() == MachineRepresentation::kWord32;
- }
- bool Is64() const {
- return WordRepresentation() == MachineRepresentation::kWord64;
- }
-
- Reduction Reduce(Node* node) {
- MachineOperatorBuilder machine(zone(), WordRepresentation());
- JSOperatorBuilder javascript(zone());
- JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
- &machine);
- ChangeLowering reducer(&jsgraph);
- return reducer.Reduce(node);
- }
-
- SimplifiedOperatorBuilder* simplified() { return &simplified_; }
-
- Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
- const Matcher<Node*>& control_matcher) {
- return IsCall(
- _, IsHeapConstant(AllocateHeapNumberStub(isolate()).GetCode()),
- IsNumberConstant(BitEq(0.0)), effect_matcher, control_matcher);
- }
- Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) {
- return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher),
- IsSmiShiftBitsConstant())
- : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
- }
- Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) {
- return Is64() ? IsTruncateInt64ToInt32(
- IsWord64Sar(value_matcher, IsSmiShiftBitsConstant()))
- : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant());
- }
- Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) {
- return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher),
- IsSmiShiftBitsConstant())
- : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
- }
- Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& control_matcher) {
- return IsLoad(MachineType::Float64(), value_matcher,
- IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
- graph()->start(), control_matcher);
- }
- Matcher<Node*> IsIntPtrConstant(int value) {
- return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
- }
- Matcher<Node*> IsSmiShiftBitsConstant() {
- return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize);
- }
- Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
- const Matcher<Node*>& rhs_matcher) {
- return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
- : IsWord64Equal(lhs_matcher, rhs_matcher);
- }
-
- private:
- SimplifiedOperatorBuilder simplified_;
-};
-
-
-// -----------------------------------------------------------------------------
-// Common.
-
-
-class ChangeLoweringCommonTest
- : public ChangeLoweringTest,
- public ::testing::WithParamInterface<MachineRepresentation> {
- public:
- ~ChangeLoweringCommonTest() override {}
-
- MachineRepresentation WordRepresentation() const final { return GetParam(); }
-};
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
- Node* value = Parameter(Type::Boolean());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kTagged, value,
- IsTrueConstant(), IsFalseConstant()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
- Node* value = Parameter(Type::Number());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
- Node* value = Parameter(Type::SignedSmall());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) {
- Node* value = Parameter(Type::UnsignedSmall());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) {
- Node* value = Parameter(Type::TaggedSigned());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) {
- Node* value = Parameter(Type::TaggedPointer());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32(
- IsLoadHeapNumber(value, graph()->start())));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) {
- Node* value = Parameter(Type::TaggedSigned());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) {
- Node* value = Parameter(Type::TaggedPointer());
- Reduction r =
- Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32(
- IsLoadHeapNumber(value, graph()->start())));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldSmi) {
- FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(),
- MachineType::AnyTagged()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* p1 = Parameter(Type::TaggedSigned());
- Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1,
- graph()->start(), graph()->start());
- Reduction r = Reduce(store);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsStore(StoreRepresentation(MachineRepresentation::kTagged,
- kNoWriteBarrier),
- p0, IsIntPtrConstant(access.offset - access.tag()), p1,
- graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldTagged) {
- FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(),
- MachineType::AnyTagged()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* p1 = Parameter(Type::Tagged());
- Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1,
- graph()->start(), graph()->start());
- Reduction r = Reduce(store);
-
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsStore(StoreRepresentation(MachineRepresentation::kTagged,
- kFullWriteBarrier),
- p0, IsIntPtrConstant(access.offset - access.tag()), p1,
- graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, LoadField) {
- FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(),
- MachineType::AnyTagged()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* load = graph()->NewNode(simplified()->LoadField(access), p0,
- graph()->start(), graph()->start());
- Reduction r = Reduce(load);
-
- ASSERT_TRUE(r.Changed());
- Matcher<Node*> index_match = IsIntPtrConstant(access.offset - access.tag());
- EXPECT_THAT(r.replacement(),
- IsLoad(MachineType::AnyTagged(), p0,
- IsIntPtrConstant(access.offset - access.tag()),
- graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementTagged) {
- ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
- MachineType::AnyTagged()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* p1 = Parameter(Type::Signed32());
- Node* p2 = Parameter(Type::Tagged());
- Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2,
- graph()->start(), graph()->start());
- Reduction r = Reduce(store);
-
- const int element_size_shift =
- ElementSizeLog2Of(access.machine_type.representation());
- ASSERT_TRUE(r.Changed());
- Matcher<Node*> index_match =
- IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)),
- IsInt32Constant(access.header_size - access.tag()));
- if (!Is32()) {
- index_match = IsChangeUint32ToUint64(index_match);
- }
-
- EXPECT_THAT(r.replacement(),
- IsStore(StoreRepresentation(MachineRepresentation::kTagged,
- kFullWriteBarrier),
- p0, index_match, p2, graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementUint8) {
- ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Type::Signed32(), MachineType::Uint8()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* p1 = Parameter(Type::Signed32());
- Node* p2 = Parameter(Type::Signed32());
- Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2,
- graph()->start(), graph()->start());
- Reduction r = Reduce(store);
-
- ASSERT_TRUE(r.Changed());
- Matcher<Node*> index_match =
- IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag()));
- if (!Is32()) {
- index_match = IsChangeUint32ToUint64(index_match);
- }
-
- EXPECT_THAT(r.replacement(),
- IsStore(StoreRepresentation(MachineRepresentation::kWord8,
- kNoWriteBarrier),
- p0, index_match, p2, graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementTagged) {
- ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
- MachineType::AnyTagged()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* p1 = Parameter(Type::Signed32());
- Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1,
- graph()->start(), graph()->start());
- Reduction r = Reduce(load);
-
- const int element_size_shift =
- ElementSizeLog2Of(access.machine_type.representation());
- ASSERT_TRUE(r.Changed());
- Matcher<Node*> index_match =
- IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)),
- IsInt32Constant(access.header_size - access.tag()));
- if (!Is32()) {
- index_match = IsChangeUint32ToUint64(index_match);
- }
-
- EXPECT_THAT(r.replacement(), IsLoad(MachineType::AnyTagged(), p0, index_match,
- graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementInt8) {
- ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Type::Signed32(), MachineType::Int8()};
- Node* p0 = Parameter(Type::TaggedPointer());
- Node* p1 = Parameter(Type::Signed32());
- Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1,
- graph()->start(), graph()->start());
- Reduction r = Reduce(load);
-
- ASSERT_TRUE(r.Changed());
- Matcher<Node*> index_match =
- IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag()));
- if (!Is32()) {
- index_match = IsChangeUint32ToUint64(index_match);
- }
-
- EXPECT_THAT(r.replacement(), IsLoad(MachineType::Int8(), p0, index_match,
- graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, Allocate) {
- Node* p0 = Parameter(Type::Signed32());
- Node* alloc = graph()->NewNode(simplified()->Allocate(TENURED), p0,
- graph()->start(), graph()->start());
- Reduction r = Reduce(alloc);
-
- // Only check that we lowered, but do not specify the exact form since
- // this is subject to change.
- ASSERT_TRUE(r.Changed());
-}
-
-
-INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest,
- ::testing::Values(MachineRepresentation::kWord32,
- MachineRepresentation::kWord64));
-
-
-// -----------------------------------------------------------------------------
-// 32-bit
-
-
-class ChangeLowering32Test : public ChangeLoweringTest {
- public:
- ~ChangeLowering32Test() override {}
- MachineRepresentation WordRepresentation() const final {
- return MachineRepresentation::kWord32;
- }
-};
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
- Node* value = Parameter(Type::Integral32());
- Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> add, branch, heap_number, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(MachineRepresentation::kTagged,
- IsFinishRegion(
- AllOf(CaptureEq(&heap_number),
- IsAllocateHeapNumber(_, CaptureEq(&if_true))),
- IsStore(
- StoreRepresentation(MachineRepresentation::kFloat64,
- kNoWriteBarrier),
- CaptureEq(&heap_number),
- IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
- IsChangeInt32ToFloat64(value), CaptureEq(&heap_number),
- CaptureEq(&if_true))),
- IsProjection(0, AllOf(CaptureEq(&add),
- IsInt32AddWithOverflow(value, value))),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(CaptureEq(&branch),
- IsBranch(IsProjection(1, CaptureEq(&add)),
- graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Number());
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(MachineRepresentation::kFloat64,
- IsLoadHeapNumber(value, CaptureEq(&if_true)),
- IsChangeInt32ToFloat64(IsWord32Sar(
- value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))),
- IsMerge(AllOf(CaptureEq(&if_true),
- IsIfTrue(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord32And(
- value, IsInt32Constant(kSmiTagMask)),
- graph()->start())))),
- IsIfFalse(CaptureEq(&branch)))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Signed32());
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(
- MachineRepresentation::kWord32,
- IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
- IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
- graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Unsigned32());
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(
- MachineRepresentation::kWord32,
- IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
- IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
- graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Number());
- Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, heap_number, if_false;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(
- MachineRepresentation::kTagged,
- IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
- IsFinishRegion(
- AllOf(CaptureEq(&heap_number),
- IsAllocateHeapNumber(_, CaptureEq(&if_false))),
- IsStore(
- StoreRepresentation(MachineRepresentation::kFloat64,
- kNoWriteBarrier),
- CaptureEq(&heap_number),
- IsInt32Constant(HeapNumber::kValueOffset - kHeapObjectTag),
- IsChangeUint32ToFloat64(value), CaptureEq(&heap_number),
- CaptureEq(&if_false))),
- IsMerge(IsIfTrue(AllOf(
- CaptureEq(&branch),
- IsBranch(IsUint32LessThanOrEqual(
- value, IsInt32Constant(Smi::kMaxValue)),
- graph()->start()))),
- AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-// -----------------------------------------------------------------------------
-// 64-bit
-
-
-class ChangeLowering64Test : public ChangeLoweringTest {
- public:
- ~ChangeLowering64Test() override {}
- MachineRepresentation WordRepresentation() const final {
- return MachineRepresentation::kWord64;
- }
-};
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
- Node* value = Parameter(Type::Signed32());
- Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Number());
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(MachineRepresentation::kFloat64,
- IsLoadHeapNumber(value, CaptureEq(&if_true)),
- IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar(
- value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))),
- IsMerge(AllOf(CaptureEq(&if_true),
- IsIfTrue(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord64And(
- value, IsInt64Constant(kSmiTagMask)),
- graph()->start())))),
- IsIfFalse(CaptureEq(&branch)))));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Signed32());
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(
- MachineRepresentation::kWord32,
- IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
- IsTruncateInt64ToInt32(
- IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
- graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Unsigned32());
- Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, if_true;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(
- MachineRepresentation::kWord32,
- IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
- IsTruncateInt64ToInt32(
- IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
- IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
- IsIfFalse(AllOf(
- CaptureEq(&branch),
- IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
- graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-
- Node* value = Parameter(Type::Number());
- Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
- Reduction r = Reduce(node);
- ASSERT_TRUE(r.Changed());
- Capture<Node*> branch, heap_number, if_false;
- EXPECT_THAT(
- r.replacement(),
- IsPhi(
- MachineRepresentation::kTagged,
- IsWord64Shl(IsChangeUint32ToUint64(value),
- IsInt64Constant(kSmiTagSize + kSmiShiftSize)),
- IsFinishRegion(
- AllOf(CaptureEq(&heap_number),
- IsAllocateHeapNumber(_, CaptureEq(&if_false))),
- IsStore(
- StoreRepresentation(MachineRepresentation::kFloat64,
- kNoWriteBarrier),
- CaptureEq(&heap_number),
- IsInt64Constant(HeapNumber::kValueOffset - kHeapObjectTag),
- IsChangeUint32ToFloat64(value), CaptureEq(&heap_number),
- CaptureEq(&if_false))),
- IsMerge(IsIfTrue(AllOf(
- CaptureEq(&branch),
- IsBranch(IsUint32LessThanOrEqual(
- value, IsInt32Constant(Smi::kMaxValue)),
- graph()->start()))),
- AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/test/unittests/compiler/common-operator-reducer-unittest.cc b/test/unittests/compiler/common-operator-reducer-unittest.cc
index 1c16370..510eaad 100644
--- a/test/unittests/compiler/common-operator-reducer-unittest.cc
+++ b/test/unittests/compiler/common-operator-reducer-unittest.cc
@@ -105,40 +105,6 @@
}
-TEST_F(CommonOperatorReducerTest, BranchWithInt64ZeroConstant) {
- TRACED_FOREACH(BranchHint, hint, kBranchHints) {
- Node* const control = graph()->start();
- Node* const branch =
- graph()->NewNode(common()->Branch(hint), Int64Constant(0), control);
- Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
- Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
- StrictMock<MockAdvancedReducerEditor> editor;
- EXPECT_CALL(editor, Replace(if_true, IsDead()));
- EXPECT_CALL(editor, Replace(if_false, control));
- Reduction const r = Reduce(&editor, branch);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsDead());
- }
-}
-
-
-TEST_F(CommonOperatorReducerTest, BranchWithInt64OneConstant) {
- TRACED_FOREACH(BranchHint, hint, kBranchHints) {
- Node* const control = graph()->start();
- Node* const branch =
- graph()->NewNode(common()->Branch(hint), Int64Constant(1), control);
- Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
- Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
- StrictMock<MockAdvancedReducerEditor> editor;
- EXPECT_CALL(editor, Replace(if_true, control));
- EXPECT_CALL(editor, Replace(if_false, IsDead()));
- Reduction const r = Reduce(&editor, branch);
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsDead());
- }
-}
-
-
TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) {
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
Node* const control = graph()->start();
@@ -500,30 +466,6 @@
}
-TEST_F(CommonOperatorReducerTest, SelectWithInt64ZeroConstant) {
- Node* p0 = Parameter(0);
- Node* p1 = Parameter(1);
- Node* select =
- graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
- Int64Constant(0), p0, p1);
- Reduction r = Reduce(select);
- ASSERT_TRUE(r.Changed());
- EXPECT_EQ(p1, r.replacement());
-}
-
-
-TEST_F(CommonOperatorReducerTest, SelectWithInt64OneConstant) {
- Node* p0 = Parameter(0);
- Node* p1 = Parameter(1);
- Node* select =
- graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
- Int64Constant(1), p0, p1);
- Reduction r = Reduce(select);
- ASSERT_TRUE(r.Changed());
- EXPECT_EQ(p0, r.replacement());
-}
-
-
TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) {
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
diff --git a/test/unittests/compiler/effect-control-linearizer-unittest.cc b/test/unittests/compiler/effect-control-linearizer-unittest.cc
new file mode 100644
index 0000000..417444e
--- /dev/null
+++ b/test/unittests/compiler/effect-control-linearizer-unittest.cc
@@ -0,0 +1,330 @@
+// 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/effect-control-linearizer.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/schedule.h"
+#include "src/compiler/simplified-operator.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class EffectControlLinearizerTest : public TypedGraphTest {
+ public:
+ EffectControlLinearizerTest()
+ : TypedGraphTest(3),
+ machine_(zone()),
+ javascript_(zone()),
+ simplified_(zone()),
+ jsgraph_(isolate(), graph(), common(), &javascript_, &simplified_,
+ &machine_) {}
+
+ JSGraph* jsgraph() { return &jsgraph_; }
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
+
+ private:
+ MachineOperatorBuilder machine_;
+ JSOperatorBuilder javascript_;
+ SimplifiedOperatorBuilder simplified_;
+ JSGraph jsgraph_;
+};
+
+namespace {
+
+BasicBlock* AddBlockToSchedule(Schedule* schedule) {
+ BasicBlock* block = schedule->NewBasicBlock();
+ block->set_rpo_number(static_cast<int32_t>(schedule->rpo_order()->size()));
+ schedule->rpo_order()->push_back(block);
+ return block;
+}
+
+} // namespace
+
+TEST_F(EffectControlLinearizerTest, SimpleLoad) {
+ Schedule schedule(zone());
+
+ // Create the graph.
+ Node* heap_number = NumberConstant(0.5);
+ Node* load = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), heap_number,
+ graph()->start(), graph()->start());
+ Node* ret = graph()->NewNode(common()->Return(), load, graph()->start(),
+ graph()->start());
+
+ // Build the basic block structure.
+ BasicBlock* start = schedule.start();
+ schedule.rpo_order()->push_back(start);
+ start->set_rpo_number(0);
+
+ // Populate the basic blocks with nodes.
+ schedule.AddNode(start, graph()->start());
+ schedule.AddNode(start, heap_number);
+ schedule.AddNode(start, load);
+ schedule.AddReturn(start, ret);
+
+ // Run the state effect introducer.
+ EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+ introducer.Run();
+
+ EXPECT_THAT(load,
+ IsLoadField(AccessBuilder::ForHeapNumberValue(), heap_number,
+ graph()->start(), graph()->start()));
+ // The return should have reconnected effect edge to the load.
+ EXPECT_THAT(ret, IsReturn(load, load, graph()->start()));
+}
+
+TEST_F(EffectControlLinearizerTest, DiamondLoad) {
+ Schedule schedule(zone());
+
+ // Create the graph.
+ Node* branch =
+ graph()->NewNode(common()->Branch(), Int32Constant(0), graph()->start());
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* heap_number = NumberConstant(0.5);
+ Node* vtrue = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), heap_number,
+ graph()->start(), if_true);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* vfalse = Float64Constant(2);
+
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* phi = graph()->NewNode(
+ common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge);
+
+ Node* ret =
+ graph()->NewNode(common()->Return(), phi, graph()->start(), merge);
+
+ // Build the basic block structure.
+ BasicBlock* start = schedule.start();
+ schedule.rpo_order()->push_back(start);
+ start->set_rpo_number(0);
+
+ BasicBlock* tblock = AddBlockToSchedule(&schedule);
+ BasicBlock* fblock = AddBlockToSchedule(&schedule);
+ BasicBlock* mblock = AddBlockToSchedule(&schedule);
+
+ // Populate the basic blocks with nodes.
+ schedule.AddNode(start, graph()->start());
+ schedule.AddBranch(start, branch, tblock, fblock);
+
+ schedule.AddNode(tblock, if_true);
+ schedule.AddNode(tblock, heap_number);
+ schedule.AddNode(tblock, vtrue);
+ schedule.AddGoto(tblock, mblock);
+
+ schedule.AddNode(fblock, if_false);
+ schedule.AddNode(fblock, vfalse);
+ schedule.AddGoto(fblock, mblock);
+
+ schedule.AddNode(mblock, merge);
+ schedule.AddNode(mblock, phi);
+ schedule.AddReturn(mblock, ret);
+
+ // Run the state effect introducer.
+ EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+ introducer.Run();
+
+ // The effect input to the return should be an effect phi with the
+ // newly introduced effectful change operators.
+ ASSERT_THAT(
+ ret, IsReturn(phi, IsEffectPhi(vtrue, graph()->start(), merge), merge));
+}
+
+TEST_F(EffectControlLinearizerTest, FloatingDiamondsControlWiring) {
+ Schedule schedule(zone());
+
+ // Create the graph and schedule. Roughly (omitting effects and unimportant
+ // nodes):
+ //
+ // BLOCK 0:
+ // r1: Start
+ // c1: Call
+ // b1: Branch(const0, s1)
+ // |
+ // +-------+------+
+ // | |
+ // BLOCK 1: BLOCK 2:
+ // t1: IfTrue(b1) f1: IfFalse(b1)
+ // | |
+ // +-------+------+
+ // |
+ // BLOCK 3:
+ // m1: Merge(t1, f1)
+ // c2: IfSuccess(c1)
+ // b2: Branch(const0 , s1)
+ // |
+ // +-------+------+
+ // | |
+ // BLOCK 4: BLOCK 5:
+ // t2: IfTrue(b2) f2:IfFalse(b2)
+ // | |
+ // +-------+------+
+ // |
+ // BLOCK 6:
+ // m2: Merge(t2, f2)
+ // r1: Return(c1, c2)
+ MachineType kMachineSignature[] = {MachineType::AnyTagged(),
+ MachineType::AnyTagged()};
+ LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
+ LinkageLocation::ForRegister(1)};
+ const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
+ CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
+ LinkageLocation::ForRegister(0),
+ new (zone()) MachineSignature(1, 1, kMachineSignature),
+ new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
+ Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
+ Node* p0 = Parameter(0);
+ Node* p1 = Parameter(1);
+ Node* const0 = Int32Constant(0);
+ Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
+ graph()->start(), graph()->start());
+ Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
+
+ // First Floating diamond.
+ Node* branch1 =
+ graph()->NewNode(common()->Branch(), const0, graph()->start());
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+
+ // Second floating diamond.
+ Node* branch2 =
+ graph()->NewNode(common()->Branch(), const0, graph()->start());
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+
+ Node* ret =
+ graph()->NewNode(common()->Return(), call, graph()->start(), if_success);
+
+ // Build the basic block structure.
+ BasicBlock* start = schedule.start();
+ schedule.rpo_order()->push_back(start);
+ start->set_rpo_number(0);
+
+ BasicBlock* t1block = AddBlockToSchedule(&schedule);
+ BasicBlock* f1block = AddBlockToSchedule(&schedule);
+ BasicBlock* m1block = AddBlockToSchedule(&schedule);
+
+ BasicBlock* t2block = AddBlockToSchedule(&schedule);
+ BasicBlock* f2block = AddBlockToSchedule(&schedule);
+ BasicBlock* m2block = AddBlockToSchedule(&schedule);
+
+ // Populate the basic blocks with nodes.
+ schedule.AddNode(start, graph()->start());
+ schedule.AddNode(start, p0);
+ schedule.AddNode(start, p1);
+ schedule.AddNode(start, const0);
+ schedule.AddNode(start, call);
+ schedule.AddBranch(start, branch1, t1block, f1block);
+
+ schedule.AddNode(t1block, if_true1);
+ schedule.AddGoto(t1block, m1block);
+
+ schedule.AddNode(f1block, if_false1);
+ schedule.AddGoto(f1block, m1block);
+
+ schedule.AddNode(m1block, merge1);
+ // The scheduler does not always put the IfSuccess node to the corresponding
+ // call's block, simulate that here.
+ schedule.AddNode(m1block, if_success);
+ schedule.AddBranch(m1block, branch2, t2block, f2block);
+
+ schedule.AddNode(t2block, if_true2);
+ schedule.AddGoto(t2block, m2block);
+
+ schedule.AddNode(f2block, if_false2);
+ schedule.AddGoto(f2block, m2block);
+
+ schedule.AddNode(m2block, merge2);
+ schedule.AddReturn(m2block, ret);
+
+ // Run the state effect introducer.
+ EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+ introducer.Run();
+
+ // The effect input to the return should be an effect phi with the
+ // newly introduced effectful change operators.
+ ASSERT_THAT(ret, IsReturn(call, call, merge2));
+ ASSERT_THAT(branch2, IsBranch(const0, merge1));
+ ASSERT_THAT(branch1, IsBranch(const0, if_success));
+ ASSERT_THAT(if_success, IsIfSuccess(call));
+}
+
+TEST_F(EffectControlLinearizerTest, LoopLoad) {
+ Schedule schedule(zone());
+
+ // Create the graph.
+ Node* loop = graph()->NewNode(common()->Loop(1), graph()->start());
+ Node* effect_phi =
+ graph()->NewNode(common()->EffectPhi(1), graph()->start(), loop);
+
+ Node* cond = Int32Constant(0);
+ Node* branch = graph()->NewNode(common()->Branch(), cond, loop);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+
+ loop->AppendInput(zone(), if_false);
+ NodeProperties::ChangeOp(loop, common()->Loop(2));
+
+ effect_phi->InsertInput(zone(), 1, effect_phi);
+ NodeProperties::ChangeOp(effect_phi, common()->EffectPhi(2));
+
+ Node* heap_number = NumberConstant(0.5);
+ Node* load = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), heap_number,
+ graph()->start(), loop);
+
+ Node* ret = graph()->NewNode(common()->Return(), load, effect_phi, if_true);
+
+ // Build the basic block structure.
+ BasicBlock* start = schedule.start();
+ schedule.rpo_order()->push_back(start);
+ start->set_rpo_number(0);
+
+ BasicBlock* lblock = AddBlockToSchedule(&schedule);
+ BasicBlock* fblock = AddBlockToSchedule(&schedule);
+ BasicBlock* rblock = AddBlockToSchedule(&schedule);
+
+ // Populate the basic blocks with nodes.
+ schedule.AddNode(start, graph()->start());
+ schedule.AddGoto(start, lblock);
+
+ schedule.AddNode(lblock, loop);
+ schedule.AddNode(lblock, effect_phi);
+ schedule.AddNode(lblock, heap_number);
+ schedule.AddNode(lblock, load);
+ schedule.AddNode(lblock, cond);
+ schedule.AddBranch(lblock, branch, rblock, fblock);
+
+ schedule.AddNode(fblock, if_false);
+ schedule.AddGoto(fblock, lblock);
+
+ schedule.AddNode(rblock, if_true);
+ schedule.AddReturn(rblock, ret);
+
+ // Run the state effect introducer.
+ EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+ introducer.Run();
+
+ ASSERT_THAT(ret, IsReturn(load, load, if_true));
+ EXPECT_THAT(load, IsLoadField(AccessBuilder::ForHeapNumberValue(),
+ heap_number, effect_phi, loop));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/compiler/escape-analysis-unittest.cc b/test/unittests/compiler/escape-analysis-unittest.cc
index d5e12ba..4c17ef2 100644
--- a/test/unittests/compiler/escape-analysis-unittest.cc
+++ b/test/unittests/compiler/escape-analysis-unittest.cc
@@ -146,14 +146,18 @@
}
FieldAccess FieldAccessAtIndex(int offset) {
- FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
- MachineType::AnyTagged()};
+ FieldAccess access = {kTaggedBase,
+ offset,
+ MaybeHandle<Name>(),
+ Type::Any(),
+ MachineType::AnyTagged(),
+ kFullWriteBarrier};
return access;
}
ElementAccess MakeElementAccess(int header_size) {
ElementAccess access = {kTaggedBase, header_size, Type::Any(),
- MachineType::AnyTagged()};
+ MachineType::AnyTagged(), kFullWriteBarrier};
return access;
}
diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc
index 16030f8..69ae768 100644
--- a/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/test/unittests/compiler/instruction-selector-unittest.cc
@@ -199,11 +199,9 @@
// -----------------------------------------------------------------------------
// Conversions.
-
-TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) {
+TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToWord32WithParameter) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
- m.Return(
- m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, m.Parameter(0)));
+ m.Return(m.TruncateFloat64ToWord32(m.Parameter(0)));
Stream s = m.Build(kAllInstructions);
ASSERT_EQ(4U, s.size());
EXPECT_EQ(kArchNop, s[0]->arch_opcode());
diff --git a/test/unittests/compiler/instruction-sequence-unittest.cc b/test/unittests/compiler/instruction-sequence-unittest.cc
index 51112a6..9360ca4 100644
--- a/test/unittests/compiler/instruction-sequence-unittest.cc
+++ b/test/unittests/compiler/instruction-sequence-unittest.cc
@@ -15,10 +15,9 @@
static const char*
general_register_names_[RegisterConfiguration::kMaxGeneralRegisters];
static const char*
- double_register_names_[RegisterConfiguration::kMaxDoubleRegisters];
+ double_register_names_[RegisterConfiguration::kMaxFPRegisters];
static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
- RegisterConfiguration::kMaxDoubleRegisters)];
-
+ RegisterConfiguration::kMaxFPRegisters)];
namespace {
static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
@@ -35,7 +34,7 @@
loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
*loc++ = 0;
}
- for (int i = 0; i < RegisterConfiguration::kMaxDoubleRegisters; ++i) {
+ for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) {
double_register_names_[i] = loc;
loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
*loc++ = 0;
diff --git a/test/unittests/compiler/int64-lowering-unittest.cc b/test/unittests/compiler/int64-lowering-unittest.cc
index 08f3038..8bc02c5 100644
--- a/test/unittests/compiler/int64-lowering-unittest.cc
+++ b/test/unittests/compiler/int64-lowering-unittest.cc
@@ -301,9 +301,6 @@
wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
}
-// todo(ahaas): I added a list of missing instructions here to make merging
-// easier when I do them one by one.
-// kExprI64Add:
TEST_F(Int64LoweringTest, Int64Add) {
LowerGraph(graph()->NewNode(machine()->Int64Add(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -319,7 +316,7 @@
IsProjection(1, AllOf(CaptureEq(&add), add_matcher)),
start(), start()));
}
-// kExprI64Sub:
+
TEST_F(Int64LoweringTest, Int64Sub) {
LowerGraph(graph()->NewNode(machine()->Int64Sub(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -336,7 +333,6 @@
start(), start()));
}
-// kExprI64Mul:
TEST_F(Int64LoweringTest, Int64Mul) {
LowerGraph(graph()->NewNode(machine()->Int64Mul(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -354,11 +350,6 @@
start(), start()));
}
-// kExprI64DivS:
-// kExprI64DivU:
-// kExprI64RemS:
-// kExprI64RemU:
-// kExprI64Ior:
TEST_F(Int64LoweringTest, Int64Ior) {
LowerGraph(graph()->NewNode(machine()->Word64Or(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -371,7 +362,6 @@
start(), start()));
}
-// kExprI64Xor:
TEST_F(Int64LoweringTest, Int64Xor) {
LowerGraph(graph()->NewNode(machine()->Word64Xor(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -383,7 +373,7 @@
IsInt32Constant(high_word_value(1))),
start(), start()));
}
-// kExprI64Shl:
+
TEST_F(Int64LoweringTest, Int64Shl) {
LowerGraph(graph()->NewNode(machine()->Word64Shl(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -399,7 +389,7 @@
IsProjection(1, AllOf(CaptureEq(&shl), shl_matcher)),
start(), start()));
}
-// kExprI64ShrU:
+
TEST_F(Int64LoweringTest, Int64ShrU) {
LowerGraph(graph()->NewNode(machine()->Word64Shr(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -415,7 +405,7 @@
IsProjection(1, AllOf(CaptureEq(&shr), shr_matcher)),
start(), start()));
}
-// kExprI64ShrS:
+
TEST_F(Int64LoweringTest, Int64ShrS) {
LowerGraph(graph()->NewNode(machine()->Word64Sar(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -431,7 +421,7 @@
IsProjection(1, AllOf(CaptureEq(&sar), sar_matcher)),
start(), start()));
}
-// kExprI64Eq:
+
TEST_F(Int64LoweringTest, Int64Eq) {
LowerGraph(graph()->NewNode(machine()->Word64Equal(), Int64Constant(value(0)),
Int64Constant(value(1))),
@@ -447,27 +437,25 @@
start(), start()));
}
-// kExprI64LtS:
TEST_F(Int64LoweringTest, Int64LtS) {
TestComparison(machine()->Int64LessThan(), IsInt32LessThan, IsUint32LessThan);
}
-// kExprI64LeS:
+
TEST_F(Int64LoweringTest, Int64LeS) {
TestComparison(machine()->Int64LessThanOrEqual(), IsInt32LessThan,
IsUint32LessThanOrEqual);
}
-// kExprI64LtU:
+
TEST_F(Int64LoweringTest, Int64LtU) {
TestComparison(machine()->Uint64LessThan(), IsUint32LessThan,
IsUint32LessThan);
}
-// kExprI64LeU:
+
TEST_F(Int64LoweringTest, Int64LeU) {
TestComparison(machine()->Uint64LessThanOrEqual(), IsUint32LessThan,
IsUint32LessThanOrEqual);
}
-// kExprI32ConvertI64:
TEST_F(Int64LoweringTest, I32ConvertI64) {
LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
Int64Constant(value(0))),
@@ -475,7 +463,7 @@
EXPECT_THAT(graph()->end()->InputAt(1),
IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
}
-// kExprI64SConvertI32:
+
TEST_F(Int64LoweringTest, I64SConvertI32) {
LowerGraph(graph()->NewNode(machine()->ChangeInt32ToInt64(),
Int32Constant(low_word_value(0))),
@@ -501,7 +489,7 @@
IsInt32Constant(31)),
start(), start()));
}
-// kExprI64UConvertI32:
+
TEST_F(Int64LoweringTest, I64UConvertI32) {
LowerGraph(graph()->NewNode(machine()->ChangeUint32ToUint64(),
Int32Constant(low_word_value(0))),
@@ -523,7 +511,7 @@
IsReturn2(IsInt32Constant(low_word_value(0)), IsInt32Constant(0),
start(), start()));
}
-// kExprF64ReinterpretI64:
+
TEST_F(Int64LoweringTest, F64ReinterpretI64) {
LowerGraph(graph()->NewNode(machine()->BitcastInt64ToFloat64(),
Int64Constant(value(0))),
@@ -554,7 +542,7 @@
AllOf(CaptureEq(&store_capture), store_matcher), start()),
start(), start()));
}
-// kExprI64ReinterpretF64:
+
TEST_F(Int64LoweringTest, I64ReinterpretF64) {
LowerGraph(graph()->NewNode(machine()->BitcastFloat64ToInt64(),
Float64Constant(bit_cast<double>(value(0)))),
@@ -583,7 +571,7 @@
AllOf(CaptureEq(&store), store_matcher), start()),
start(), start()));
}
-// kExprI64Clz:
+
TEST_F(Int64LoweringTest, I64Clz) {
LowerGraph(graph()->NewNode(machine()->Word64Clz(), Int64Constant(value(0))),
MachineRepresentation::kWord64);
@@ -606,7 +594,7 @@
AllOf(CaptureEq(&branch_capture), branch_matcher)))),
IsInt32Constant(0), start(), start()));
}
-// kExprI64Ctz:
+
TEST_F(Int64LoweringTest, I64Ctz) {
LowerGraph(graph()->NewNode(machine()->Word64CtzPlaceholder(),
Int64Constant(value(0))),
@@ -628,7 +616,6 @@
AllOf(CaptureEq(&branch_capture), branch_matcher)))),
IsInt32Constant(0), start(), start()));
}
-// kExprI64Popcnt:
TEST_F(Int64LoweringTest, Dfs) {
Node* common = Int64Constant(value(0));
diff --git a/test/unittests/compiler/js-create-lowering-unittest.cc b/test/unittests/compiler/js-create-lowering-unittest.cc
index 837c574..5d95d0d 100644
--- a/test/unittests/compiler/js-create-lowering-unittest.cc
+++ b/test/unittests/compiler/js-create-lowering-unittest.cc
@@ -80,95 +80,74 @@
// -----------------------------------------------------------------------------
// 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));
+ closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize),
- _, control),
- _));
+ EXPECT_THAT(
+ r.replacement(),
+ IsFinishRegion(
+ IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize), _, _),
+ _));
}
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));
+ closure, context, frame_state_inner, effect));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize),
- _, control),
- _));
+ EXPECT_THAT(
+ r.replacement(),
+ IsFinishRegion(
+ IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize), _, _),
+ _));
}
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));
+ closure, context, frame_state_inner, effect));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsFinishRegion(IsAllocate(IsNumberConstant(JSArray::kSize), _, _), _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateClosure
+
+TEST_F(JSCreateLoweringTest, JSCreateClosureViaInlinedAllocation) {
+ 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(),
- IsFinishRegion(
- IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
+ IsFinishRegion(IsAllocate(IsNumberConstant(JSFunction::kSize),
+ IsBeginRegion(_), control),
+ _));
}
// -----------------------------------------------------------------------------
diff --git a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index de0eefc..7c2f459 100644
--- a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
@@ -92,7 +92,7 @@
input, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
- IsFloat64ExtractLowWord32(IsGuard(Type::Number(), input, _)));
+ IsFloat64ExtractLowWord32(IsTypeGuard(Type::Number(), input, _)));
}
@@ -109,8 +109,8 @@
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
input, context, effect, control));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsFloat64ExtractHighWord32(IsGuard(Type::Number(), input, _)));
+ EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(
+ IsTypeGuard(Type::Number(), input, _)));
}
@@ -284,23 +284,6 @@
AllOf(CaptureEq(&if_false0), IsIfFalse(CaptureEq(&branch0))))));
}
-// -----------------------------------------------------------------------------
-// %_GetOrdinaryHasInstance
-
-TEST_F(JSIntrinsicLoweringTest, InlineGetOrdinaryHasInstance) {
- Node* const context = Parameter(0);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- Reduction const r = Reduce(graph()->NewNode(
- javascript()->CallRuntime(Runtime::kInlineGetOrdinaryHasInstance, 0),
- context, effect, control));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsLoadContext(
- ContextAccess(0, Context::ORDINARY_HAS_INSTANCE_INDEX, true), _));
-}
-
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/unittests/compiler/js-operator-unittest.cc b/test/unittests/compiler/js-operator-unittest.cc
index 15b1427..28df6a9 100644
--- a/test/unittests/compiler/js-operator-unittest.cc
+++ b/test/unittests/compiler/js-operator-unittest.cc
@@ -42,8 +42,8 @@
}
SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
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(StrictEqual, Operator::kPure, 2, 0, 0, 0, 1, 0, 0),
+ SHARED(StrictNotEqual, Operator::kPure, 2, 0, 0, 0, 1, 0, 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),
@@ -51,11 +51,10 @@
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),
- SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
- SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
+ SHARED(ToObject, Operator::kFoldable, 1, 1, 1, 1, 1, 1, 2),
SHARED(Create, Operator::kEliminatable, 2, 1, 1, 0, 1, 1, 0),
SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
- SHARED(TypeOf, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
+ SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc
index 1adb5da..904d5f7 100644
--- a/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -212,9 +212,8 @@
TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) {
Node* input = Parameter(Type::Boolean(), 0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(input, r.replacement());
}
@@ -242,9 +241,8 @@
zone()),
0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant());
}
@@ -258,9 +256,8 @@
zone()),
0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant());
}
@@ -269,9 +266,8 @@
TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant());
}
@@ -280,9 +276,8 @@
TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
Node* input = Parameter(Type::OrderedNumber(), 0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0))));
@@ -292,9 +287,8 @@
TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
Node* input = Parameter(Type::String(), 0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
@@ -307,9 +301,8 @@
TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
Node* input = Parameter(Type::Any(), 0);
Node* context = Parameter(Type::Any(), 1);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
- input, context, graph()->start()));
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_FALSE(r.Changed());
}
@@ -391,9 +384,8 @@
Node* const context = UndefinedConstant();
TRACED_FOREACH(Type*, type, kJSTypes) {
Node* const lhs = Parameter(type);
- Reduction r =
- Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole,
- context, graph()->start(), graph()->start()));
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant());
}
@@ -405,8 +397,7 @@
Node* const rhs = Parameter(Type::Unique(), 1);
Node* const context = Parameter(Type::Any(), 2);
Reduction r =
- Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context,
- graph()->start(), graph()->start()));
+ Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
}
@@ -823,24 +814,6 @@
}
-TEST_F(JSTypedLoweringTest, JSLoadNamedFunctionPrototype) {
- VectorSlotPair feedback;
- Handle<Name> name = factory()->prototype_string();
- Handle<JSFunction> function = isolate()->object_function();
- Handle<JSObject> function_prototype(JSObject::cast(function->prototype()));
- Node* const receiver = Parameter(Type::Constant(function, zone()), 0);
- Node* const vector = Parameter(Type::Internal(), 1);
- Node* const context = Parameter(Type::Internal(), 2);
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
- 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));
-}
-
-
// -----------------------------------------------------------------------------
// JSAdd
diff --git a/test/unittests/compiler/load-elimination-unittest.cc b/test/unittests/compiler/load-elimination-unittest.cc
index 38bb151..721d6df 100644
--- a/test/unittests/compiler/load-elimination-unittest.cc
+++ b/test/unittests/compiler/load-elimination-unittest.cc
@@ -14,23 +14,20 @@
class LoadEliminationTest : public TypedGraphTest {
public:
- LoadEliminationTest()
- : TypedGraphTest(3), common_(zone()), simplified_(zone()) {}
+ LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {}
~LoadEliminationTest() override {}
protected:
Reduction Reduce(Node* node) {
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
- LoadElimination reducer(&graph_reducer, graph(), common());
+ LoadElimination reducer(&graph_reducer, graph(), simplified());
return reducer.Reduce(node);
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
- CommonOperatorBuilder* common() { return &common_; }
private:
- CommonOperatorBuilder common_;
SimplifiedOperatorBuilder simplified_;
};
diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc
index 2feba2e..8b65e04 100644
--- a/test/unittests/compiler/machine-operator-reducer-unittest.cc
+++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -236,10 +236,6 @@
0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
-const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript,
- TruncationMode::kRoundToZero};
-
-
struct ComparisonBinaryOperator {
const Operator* (MachineOperatorBuilder::*constructor)();
const char* constructor_name;
@@ -413,51 +409,28 @@
// -----------------------------------------------------------------------------
-// TruncateFloat64ToInt32
-
+// TruncateFloat64ToWord32
TEST_F(MachineOperatorReducerTest,
- TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
- TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
- Node* value = Parameter(0);
- Reduction reduction = Reduce(graph()->NewNode(
- machine()->TruncateFloat64ToInt32(mode),
- graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_EQ(value, reduction.replacement());
- }
+ TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
+ Node* value = Parameter(0);
+ Reduction reduction = Reduce(graph()->NewNode(
+ machine()->TruncateFloat64ToWord32(),
+ graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_EQ(value, reduction.replacement());
}
-
-TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
+TEST_F(MachineOperatorReducerTest, TruncateFloat64ToWord32WithConstant) {
TRACED_FOREACH(double, x, kFloat64Values) {
Reduction reduction = Reduce(graph()->NewNode(
- machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript),
- Float64Constant(x)));
+ machine()->TruncateFloat64ToWord32(), Float64Constant(x)));
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
}
}
-TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
- Node* const p0 = Parameter(0);
- Node* const p1 = Parameter(1);
- Node* const merge = graph()->start();
- TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
- Reduction reduction = Reduce(graph()->NewNode(
- machine()->TruncateFloat64ToInt32(mode),
- graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), p0,
- p1, merge)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(
- reduction.replacement(),
- IsPhi(MachineRepresentation::kWord32, IsTruncateFloat64ToInt32(p0),
- IsTruncateFloat64ToInt32(p1), merge));
- }
-}
-
-
// -----------------------------------------------------------------------------
// TruncateInt64ToInt32
@@ -485,8 +458,30 @@
// -----------------------------------------------------------------------------
-// Word32And
+// RoundFloat64ToInt32
+TEST_F(MachineOperatorReducerTest,
+ RoundFloat64ToInt32WithChangeInt32ToFloat64) {
+ Node* value = Parameter(0);
+ Reduction reduction = Reduce(graph()->NewNode(
+ machine()->RoundFloat64ToInt32(),
+ graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_EQ(value, reduction.replacement());
+}
+
+TEST_F(MachineOperatorReducerTest, RoundFloat64ToInt32WithConstant) {
+ TRACED_FOREACH(double, x, kFloat64Values) {
+ Reduction reduction = Reduce(
+ graph()->NewNode(machine()->RoundFloat64ToInt32(), Float64Constant(x)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(),
+ IsInt32Constant(static_cast<int32_t>(x)));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Word32And
TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
Node* const p0 = Parameter(0);
diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc
index 6e5d39f..6adacc1 100644
--- a/test/unittests/compiler/node-test-utils.cc
+++ b/test/unittests/compiler/node-test-utils.cc
@@ -612,49 +612,6 @@
};
-class IsEffectSetMatcher final : public NodeMatcher {
- public:
- IsEffectSetMatcher(const Matcher<Node*>& effect0_matcher,
- const Matcher<Node*>& effect1_matcher)
- : NodeMatcher(IrOpcode::kEffectSet),
- effect0_matcher_(effect0_matcher),
- effect1_matcher_(effect1_matcher) {}
-
- void DescribeTo(std::ostream* os) const final {
- NodeMatcher::DescribeTo(os);
- *os << "), effect0 (";
- effect0_matcher_.DescribeTo(os);
- *os << ") and effect1 (";
- effect1_matcher_.DescribeTo(os);
- *os << ")";
- }
-
- bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
- if (!NodeMatcher::MatchAndExplain(node, listener)) return false;
-
- Node* effect0 = NodeProperties::GetEffectInput(node, 0);
- Node* effect1 = NodeProperties::GetEffectInput(node, 1);
-
- {
- // Try matching in the reverse order first.
- StringMatchResultListener value_listener;
- if (effect0_matcher_.MatchAndExplain(effect1, &value_listener) &&
- effect1_matcher_.MatchAndExplain(effect0, &value_listener)) {
- return true;
- }
- }
-
- return PrintMatchAndExplain(effect0, "effect0", effect0_matcher_,
- listener) &&
- PrintMatchAndExplain(effect1, "effect1", effect1_matcher_, listener);
- }
-
- private:
- const Matcher<Node*> effect0_matcher_;
- const Matcher<Node*> effect1_matcher_;
-};
-
-
class IsProjectionMatcher final : public NodeMatcher {
public:
IsProjectionMatcher(const Matcher<size_t>& index_matcher,
@@ -1352,12 +1309,12 @@
const Matcher<MachineRepresentation> rep_matcher_;
};
-class IsGuardMatcher final : public NodeMatcher {
+class IsTypeGuardMatcher final : public NodeMatcher {
public:
- IsGuardMatcher(const Matcher<Type*>& type_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kGuard),
+ IsTypeGuardMatcher(const Matcher<Type*>& type_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kTypeGuard),
type_matcher_(type_matcher),
value_matcher_(value_matcher),
control_matcher_(control_matcher) {}
@@ -1818,12 +1775,6 @@
}
-Matcher<Node*> IsEffectSet(const Matcher<Node*>& effect0_matcher,
- const Matcher<Node*>& effect1_matcher) {
- return MakeMatcher(new IsEffectSetMatcher(effect0_matcher, effect1_matcher));
-}
-
-
Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
const Matcher<Node*>& base_matcher) {
return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
@@ -2064,11 +2015,11 @@
effect_matcher, control_matcher));
}
-Matcher<Node*> IsGuard(const Matcher<Type*>& type_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& control_matcher) {
+Matcher<Node*> IsTypeGuard(const Matcher<Type*>& type_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher) {
return MakeMatcher(
- new IsGuardMatcher(type_matcher, value_matcher, control_matcher));
+ new IsTypeGuardMatcher(type_matcher, value_matcher, control_matcher));
}
Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher,
@@ -2204,6 +2155,10 @@
return MakeMatcher(new NodeMatcher(IrOpcode::kLoadFramePointer));
}
+Matcher<Node*> IsLoadParentFramePointer() {
+ return MakeMatcher(new NodeMatcher(IrOpcode::kLoadParentFramePointer));
+}
+
#define IS_QUADOP_MATCHER(Name) \
Matcher<Node*> Is##Name( \
const Matcher<Node*>& a_matcher, const Matcher<Node*>& b_matcher, \
@@ -2284,6 +2239,7 @@
return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
}
IS_UNOP_MATCHER(BooleanNot)
+IS_UNOP_MATCHER(TruncateFloat64ToWord32)
IS_UNOP_MATCHER(ChangeFloat64ToInt32)
IS_UNOP_MATCHER(ChangeFloat64ToUint32)
IS_UNOP_MATCHER(ChangeInt32ToFloat64)
@@ -2291,7 +2247,6 @@
IS_UNOP_MATCHER(ChangeUint32ToFloat64)
IS_UNOP_MATCHER(ChangeUint32ToUint64)
IS_UNOP_MATCHER(TruncateFloat64ToFloat32)
-IS_UNOP_MATCHER(TruncateFloat64ToInt32)
IS_UNOP_MATCHER(TruncateInt64ToInt32)
IS_UNOP_MATCHER(Float32Abs)
IS_UNOP_MATCHER(Float64Abs)
diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h
index dd036c9..4979bd5 100644
--- a/test/unittests/compiler/node-test-utils.h
+++ b/test/unittests/compiler/node-test-utils.h
@@ -97,8 +97,6 @@
Matcher<Node*> IsEffectPhi(const Matcher<Node*>& effect0_matcher,
const Matcher<Node*>& effect1_matcher,
const Matcher<Node*>& merge_matcher);
-Matcher<Node*> IsEffectSet(const Matcher<Node*>& effect0_matcher,
- const Matcher<Node*>& effect1_matcher);
Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
const Matcher<Node*>& base_matcher);
Matcher<Node*> IsCall(const Matcher<const CallDescriptor*>& descriptor_matcher,
@@ -315,6 +313,7 @@
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsJSAdd(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsTruncateFloat64ToWord32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeFloat64ToUint32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
@@ -322,7 +321,6 @@
Matcher<Node*> IsChangeUint32ToFloat64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateFloat64ToFloat32(const Matcher<Node*>& input_matcher);
-Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat32Max(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
@@ -362,6 +360,7 @@
Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsParameter(const Matcher<int> index_matcher);
Matcher<Node*> IsLoadFramePointer();
+Matcher<Node*> IsLoadParentFramePointer();
Matcher<Node*> IsInt32PairAdd(const Matcher<Node*>& a_matcher,
const Matcher<Node*>& b_matcher,
@@ -388,9 +387,9 @@
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsStackSlot();
-Matcher<Node*> IsGuard(const Matcher<Type*>& type_matcher,
- const Matcher<Node*>& value_matcher,
- const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsTypeGuard(const Matcher<Type*>& type_matcher,
+ const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher);
} // namespace compiler
} // namespace internal
diff --git a/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/test/unittests/compiler/simplified-operator-reducer-unittest.cc
index f571898..eec39ab 100644
--- a/test/unittests/compiler/simplified-operator-reducer-unittest.cc
+++ b/test/unittests/compiler/simplified-operator-reducer-unittest.cc
@@ -150,60 +150,54 @@
// -----------------------------------------------------------------------------
-// ChangeBoolToBit
+// ChangeTaggedToBit
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithChangeBoolToBit) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeBitToTaggedWithChangeTaggedToBit) {
Node* param0 = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode(
- simplified()->ChangeBitToBool(),
- graph()->NewNode(simplified()->ChangeBoolToBit(), param0)));
+ simplified()->ChangeBitToTagged(),
+ graph()->NewNode(simplified()->ChangeTaggedToBit(), param0)));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(param0, reduction.replacement());
}
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithZeroConstant) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeBitToTaggedWithZeroConstant) {
Reduction reduction = Reduce(
- graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(0)));
+ graph()->NewNode(simplified()->ChangeBitToTagged(), Int32Constant(0)));
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsFalseConstant());
}
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithOneConstant) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeBitToTaggedWithOneConstant) {
Reduction reduction = Reduce(
- graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(1)));
+ graph()->NewNode(simplified()->ChangeBitToTagged(), Int32Constant(1)));
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsTrueConstant());
}
// -----------------------------------------------------------------------------
-// ChangeBoolToBit
+// ChangeTaggedToBit
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithFalseConstant) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithFalseConstant) {
Reduction reduction = Reduce(
- graph()->NewNode(simplified()->ChangeBoolToBit(), FalseConstant()));
+ graph()->NewNode(simplified()->ChangeTaggedToBit(), FalseConstant()));
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
}
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithTrueConstant) {
- Reduction reduction =
- Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), TrueConstant()));
+TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithTrueConstant) {
+ Reduction reduction = Reduce(
+ graph()->NewNode(simplified()->ChangeTaggedToBit(), TrueConstant()));
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsInt32Constant(1));
}
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithChangeBitToTagged) {
Node* param0 = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode(
- simplified()->ChangeBoolToBit(),
- graph()->NewNode(simplified()->ChangeBitToBool(), param0)));
+ simplified()->ChangeTaggedToBit(),
+ graph()->NewNode(simplified()->ChangeBitToTagged(), param0)));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(param0, reduction.replacement());
}
@@ -401,6 +395,28 @@
}
}
+// -----------------------------------------------------------------------------
+// TruncateTaggedToWord32
+
+TEST_F(SimplifiedOperatorReducerTest,
+ TruncateTaggedToWord3WithChangeFloat64ToTagged) {
+ Node* param0 = Parameter(0);
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->TruncateTaggedToWord32(),
+ graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0));
+}
+
+TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
+ TRACED_FOREACH(double, n, kFloat64Values) {
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->TruncateTaggedToWord32(), NumberConstant(n)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(n)));
+ }
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/unittests/compiler/simplified-operator-unittest.cc b/test/unittests/compiler/simplified-operator-unittest.cc
index bd8509f..ba404a9 100644
--- a/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/test/unittests/compiler/simplified-operator-unittest.cc
@@ -31,7 +31,6 @@
return os << IrOpcode::Mnemonic(pop.opcode);
}
-
const PureOperator kPureOperators[] = {
#define PURE(Name, properties, input_count) \
{ \
@@ -56,15 +55,16 @@
PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
PURE(NumberToInt32, Operator::kNoProperties, 1),
PURE(NumberToUint32, Operator::kNoProperties, 1),
- PURE(PlainPrimitiveToNumber, Operator::kNoProperties, 1),
+ PURE(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1),
PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
- PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
- PURE(ChangeBitToBool, Operator::kNoProperties, 1),
+ PURE(ChangeTaggedToBit, Operator::kNoProperties, 1),
+ PURE(ChangeBitToTagged, Operator::kNoProperties, 1),
+ PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1),
PURE(ObjectIsNumber, Operator::kNoProperties, 1),
PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
PURE(ObjectIsSmi, Operator::kNoProperties, 1)
@@ -203,39 +203,46 @@
const ElementAccess kElementAccesses[] = {
{kTaggedBase, FixedArray::kHeaderSize, Type::Any(),
- MachineType::AnyTagged()},
- {kUntaggedBase, 0, Type::Any(), MachineType::Int8()},
- {kUntaggedBase, 0, Type::Any(), MachineType::Int16()},
- {kUntaggedBase, 0, Type::Any(), MachineType::Int32()},
- {kUntaggedBase, 0, Type::Any(), MachineType::Uint8()},
- {kUntaggedBase, 0, Type::Any(), MachineType::Uint16()},
- {kUntaggedBase, 0, Type::Any(), MachineType::Uint32()},
- {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8()},
- {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8()},
- {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16()},
- {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16()},
- {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32()},
- {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32()},
+ MachineType::AnyTagged(), kFullWriteBarrier},
+ {kUntaggedBase, 0, Type::Any(), MachineType::Int8(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Any(), MachineType::Int16(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Any(), MachineType::Int32(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Any(), MachineType::Uint8(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Any(), MachineType::Uint16(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Any(), MachineType::Uint32(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8(),
+ kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16(),
+ kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32(), kNoWriteBarrier},
+ {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32(),
+ kNoWriteBarrier},
{kUntaggedBase, 0, Type::Number(),
- MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
+ MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
+ kNoWriteBarrier},
{kUntaggedBase, 0, Type::Number(),
- MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone)},
+ MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone),
+ kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
- MachineType::Int8()},
+ MachineType::Int8(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
- MachineType::Uint8()},
+ MachineType::Uint8(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
- MachineType::Int16()},
+ MachineType::Int16(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
- MachineType::Uint16()},
+ MachineType::Uint16(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
- MachineType::Int32()},
+ MachineType::Int32(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
- MachineType::Uint32()},
+ MachineType::Uint32(), kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
- MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
+ MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
+ kNoWriteBarrier},
{kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
- MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)}};
+ MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
+ kNoWriteBarrier}};
} // namespace
diff --git a/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
index 255d836..a569c94 100644
--- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
@@ -22,11 +22,16 @@
TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
+ Factory* factory = isolate()->factory();
CHECK_EQ(builder.locals_count(), 131);
CHECK_EQ(builder.context_count(), 1);
CHECK_EQ(builder.fixed_register_count(), 132);
+ Register reg(0);
+ Register other(reg.index() + 1);
+ Register wide(128);
+
// Emit argument creation operations.
builder.CreateArguments(CreateArgumentsType::kMappedArguments)
.CreateArguments(CreateArgumentsType::kUnmappedArguments)
@@ -34,19 +39,27 @@
// Emit constant loads.
builder.LoadLiteral(Smi::FromInt(0))
+ .StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(8))
+ .StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(10000000))
+ .StoreAccumulatorInRegister(reg)
+ .LoadLiteral(factory->NewStringFromStaticChars("A constant"))
+ .StoreAccumulatorInRegister(reg)
.LoadUndefined()
+ .StoreAccumulatorInRegister(reg)
.LoadNull()
+ .StoreAccumulatorInRegister(reg)
.LoadTheHole()
+ .StoreAccumulatorInRegister(reg)
.LoadTrue()
- .LoadFalse();
+ .StoreAccumulatorInRegister(reg)
+ .LoadFalse()
+ .StoreAccumulatorInRegister(wide);
- Register reg(0);
- Register other(reg.index() + 1);
- Register wide(128);
-
- builder.LoadAccumulatorWithRegister(reg)
+ builder.StackCheck(0)
+ .LoadAccumulatorWithRegister(other)
+ .StoreAccumulatorInRegister(reg)
.LoadNull()
.StoreAccumulatorInRegister(reg);
@@ -55,7 +68,6 @@
builder.MoveRegister(reg, wide);
// Emit global load / store operations.
- Factory* factory = isolate()->factory();
Handle<String> name = factory->NewStringFromStaticChars("var_name");
builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF)
.LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF)
@@ -126,7 +138,10 @@
builder.CountOperation(Token::Value::ADD).CountOperation(Token::Value::SUB);
// Emit unary operator invocations.
- builder.LogicalNot().TypeOf();
+ builder
+ .LogicalNot() // ToBooleanLogicalNot
+ .LogicalNot() // non-ToBoolean LogicalNot
+ .TypeOf();
// Emit delete
builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
@@ -208,7 +223,7 @@
.JumpIfFalse(&start);
// Emit stack check bytecode.
- builder.StackCheck();
+ builder.StackCheck(0);
// 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.
@@ -289,6 +304,10 @@
.BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&start);
+ // Emit generator operations
+ builder.SuspendGenerator(reg)
+ .ResumeGenerator(reg);
+
// Intrinsics handled by the interpreter.
builder.CallRuntime(Runtime::kInlineIsArray, reg, 1)
.CallRuntime(Runtime::kInlineIsArray, wide, 1);
@@ -327,6 +346,9 @@
// Insert entry for illegal bytecode as this is never willingly emitted.
scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
+ // Insert entry for nop bytecode as this often gets optimized out.
+ scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1;
+
// Check return occurs at the end and only once in the BytecodeArray.
CHECK_EQ(final_bytecode, Bytecode::kReturn);
CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
@@ -364,14 +386,11 @@
TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
int index = 1;
- int32_t operand = -index;
Register the_register(index);
CHECK_EQ(the_register.index(), index);
int actual_operand = the_register.ToOperand();
- CHECK_EQ(actual_operand, operand);
-
int actual_index = Register::FromOperand(actual_operand).index();
CHECK_EQ(actual_index, index);
}
@@ -461,7 +480,7 @@
.BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&far4);
for (int i = 0; i < kFarJumpDistance - 18; i++) {
- builder.LoadUndefined();
+ builder.Debugger();
}
builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4);
builder.Return();
@@ -502,7 +521,6 @@
CHECK_EQ(iterator.GetImmediateOperand(0), 2);
iterator.Advance();
-
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
Smi::FromInt(kFarJumpDistance));
@@ -568,7 +586,7 @@
// Add padding to force wide backwards jumps.
for (int i = 0; i < 256; i++) {
- builder.LoadTrue();
+ builder.Debugger();
}
builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
@@ -615,7 +633,7 @@
}
// Check padding to force wide backwards jumps.
for (int i = 0; i < 256; i++) {
- CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaTrue);
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
iterator.Advance();
}
// Ignore binary operation.
@@ -706,85 +724,6 @@
CHECK(iterator.done());
}
-TEST_F(BytecodeArrayBuilderTest, OperandScales) {
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(OperandSize::kByte),
- OperandScale::kSingle);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(OperandSize::kShort),
- OperandScale::kDouble);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(OperandSize::kQuad),
- OperandScale::kQuadruple);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
- OperandSize::kShort, OperandSize::kShort, OperandSize::kShort,
- OperandSize::kShort),
- OperandScale::kDouble);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
- OperandSize::kQuad, OperandSize::kShort, OperandSize::kShort,
- OperandSize::kShort),
- OperandScale::kQuadruple);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
- OperandSize::kShort, OperandSize::kQuad, OperandSize::kShort,
- OperandSize::kShort),
- OperandScale::kQuadruple);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
- OperandSize::kShort, OperandSize::kShort, OperandSize::kQuad,
- OperandSize::kShort),
- OperandScale::kQuadruple);
- CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
- OperandSize::kShort, OperandSize::kShort, OperandSize::kShort,
- OperandSize::kQuad),
- OperandScale::kQuadruple);
-}
-
-TEST_F(BytecodeArrayBuilderTest, SizesForSignOperands) {
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(0) == OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt8) ==
- OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt8) ==
- OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt8 + 1) ==
- OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt8 - 1) ==
- OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt16) ==
- OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt16) ==
- OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt16 + 1) ==
- OperandSize::kQuad);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt16 - 1) ==
- OperandSize::kQuad);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt) ==
- OperandSize::kQuad);
- CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt) ==
- OperandSize::kQuad);
-}
-
-TEST_F(BytecodeArrayBuilderTest, SizesForUnsignOperands) {
- // int overloads
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(0) == OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt8) ==
- OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt8 + 1) ==
- OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt16) ==
- OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt16 + 1) ==
- OperandSize::kQuad);
- // size_t overloads
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(static_cast<size_t>(0)) ==
- OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
- static_cast<size_t>(kMaxUInt8)) == OperandSize::kByte);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
- static_cast<size_t>(kMaxUInt8 + 1)) == OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
- static_cast<size_t>(kMaxUInt16)) == OperandSize::kShort);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
- static_cast<size_t>(kMaxUInt16 + 1)) == OperandSize::kQuad);
- CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
- static_cast<size_t>(kMaxUInt32)) == OperandSize::kQuad);
-}
-
} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
index 43c6caa..aa9effe 100644
--- a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
@@ -37,11 +37,17 @@
int feedback_slot = 97;
builder.LoadLiteral(heap_num_0)
+ .StoreAccumulatorInRegister(reg_0)
.LoadLiteral(heap_num_1)
+ .StoreAccumulatorInRegister(reg_0)
.LoadLiteral(zero)
+ .StoreAccumulatorInRegister(reg_0)
.LoadLiteral(smi_0)
+ .StoreAccumulatorInRegister(reg_0)
.LoadLiteral(smi_1)
+ .StoreAccumulatorInRegister(reg_1)
.LoadAccumulatorWithRegister(reg_0)
+ .StoreAccumulatorInRegister(reg_1)
.LoadNamedProperty(reg_1, name, feedback_slot)
.StoreAccumulatorInRegister(param)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, 1, reg_0)
@@ -64,6 +70,15 @@
offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
iterator.Advance();
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+ CHECK_EQ(iterator.current_offset(), offset);
+ CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+ CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+ CHECK(!iterator.done());
+ offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+ iterator.Advance();
+
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -72,6 +87,15 @@
offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
iterator.Advance();
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+ CHECK_EQ(iterator.current_offset(), offset);
+ CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+ CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+ CHECK(!iterator.done());
+ offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+ iterator.Advance();
+
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -79,6 +103,15 @@
offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
iterator.Advance();
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+ CHECK_EQ(iterator.current_offset(), offset);
+ CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+ CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+ CHECK(!iterator.done());
+ offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+ iterator.Advance();
+
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -87,6 +120,15 @@
offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
iterator.Advance();
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+ CHECK_EQ(iterator.current_offset(), offset);
+ CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+ CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+ CHECK(!iterator.done());
+ offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+ iterator.Advance();
+
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
@@ -96,6 +138,15 @@
kPrefixByteSize;
iterator.Advance();
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+ CHECK_EQ(iterator.current_offset(), offset);
+ CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
+ CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+ CHECK(!iterator.done());
+ offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+ iterator.Advance();
+
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdar);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -104,6 +155,15 @@
offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
iterator.Advance();
+ CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+ CHECK_EQ(iterator.current_offset(), offset);
+ CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
+ CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+ CHECK(!iterator.done());
+ offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+ iterator.Advance();
+
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
diff --git a/test/unittests/interpreter/bytecode-array-writer-unittest.cc b/test/unittests/interpreter/bytecode-array-writer-unittest.cc
new file mode 100644
index 0000000..a1b4910
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-array-writer-unittest.cc
@@ -0,0 +1,233 @@
+// 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/v8.h"
+
+#include "src/interpreter/bytecode-array-writer.h"
+#include "src/interpreter/source-position-table.h"
+#include "src/isolate.h"
+#include "src/utils.h"
+#include "test/unittests/interpreter/bytecode-utils.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone {
+ public:
+ BytecodeArrayWriterUnittest()
+ : source_position_builder_(isolate(), zone()),
+ bytecode_array_writer_(zone(), &source_position_builder_) {}
+ ~BytecodeArrayWriterUnittest() override {}
+
+ void Write(BytecodeNode* node, const BytecodeSourceInfo& info);
+ void Write(Bytecode bytecode,
+ const BytecodeSourceInfo& info = BytecodeSourceInfo());
+ void Write(Bytecode bytecode, uint32_t operand0, OperandScale operand_scale,
+ const BytecodeSourceInfo& info = BytecodeSourceInfo());
+ void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+ OperandScale operand_scale,
+ const BytecodeSourceInfo& info = BytecodeSourceInfo());
+ void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+ uint32_t operand2, OperandScale operand_scale,
+ const BytecodeSourceInfo& info = BytecodeSourceInfo());
+ void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+ uint32_t operand2, uint32_t operand3, OperandScale operand_scale,
+ const BytecodeSourceInfo& info = BytecodeSourceInfo());
+
+ SourcePositionTableBuilder* source_position_builder() {
+ return &source_position_builder_;
+ }
+ BytecodeArrayWriter* writer() { return &bytecode_array_writer_; }
+
+ private:
+ SourcePositionTableBuilder source_position_builder_;
+ BytecodeArrayWriter bytecode_array_writer_;
+};
+
+void BytecodeArrayWriterUnittest::Write(BytecodeNode* node,
+ const BytecodeSourceInfo& info) {
+ if (info.is_valid()) {
+ node->source_info().Update(info);
+ }
+ writer()->Write(node);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode,
+ const BytecodeSourceInfo& info) {
+ BytecodeNode node(bytecode);
+ Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+ OperandScale operand_scale,
+ const BytecodeSourceInfo& info) {
+ BytecodeNode node(bytecode, operand0, operand_scale);
+ Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+ uint32_t operand1,
+ OperandScale operand_scale,
+ const BytecodeSourceInfo& info) {
+ BytecodeNode node(bytecode, operand0, operand1, operand_scale);
+ Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+ uint32_t operand1, uint32_t operand2,
+ OperandScale operand_scale,
+ const BytecodeSourceInfo& info) {
+ BytecodeNode node(bytecode, operand0, operand1, operand2, operand_scale);
+ Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+ uint32_t operand1, uint32_t operand2,
+ uint32_t operand3,
+ OperandScale operand_scale,
+ const BytecodeSourceInfo& info) {
+ BytecodeNode node(bytecode, operand0, operand1, operand2, operand3,
+ operand_scale);
+ Write(&node, info);
+}
+
+TEST_F(BytecodeArrayWriterUnittest, SimpleExample) {
+ CHECK_EQ(writer()->bytecodes()->size(), 0);
+
+ Write(Bytecode::kStackCheck, {10, false});
+ CHECK_EQ(writer()->bytecodes()->size(), 1);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 0);
+
+ Write(Bytecode::kLdaSmi, 0xff, OperandScale::kSingle, {55, true});
+ CHECK_EQ(writer()->bytecodes()->size(), 3);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 0);
+
+ Write(Bytecode::kLdar, Register(1).ToOperand(), OperandScale::kDouble);
+ CHECK_EQ(writer()->bytecodes()->size(), 7);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 2 * kPointerSize);
+
+ Write(Bytecode::kReturn, {70, true});
+ CHECK_EQ(writer()->bytecodes()->size(), 8);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 2 * kPointerSize);
+
+ static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(0xff), B(Wide),
+ B(Ldar), R16(1), B(Return)};
+ CHECK_EQ(writer()->bytecodes()->size(), arraysize(bytes));
+ for (size_t i = 0; i < arraysize(bytes); ++i) {
+ CHECK_EQ(writer()->bytecodes()->at(i), bytes[i]);
+ }
+
+ CHECK_EQ(writer()->FlushForOffset(), arraysize(bytes));
+ writer()->FlushBasicBlock();
+ CHECK_EQ(writer()->bytecodes()->size(), arraysize(bytes));
+
+ PositionTableEntry expected_positions[] = {
+ {0, 10, false}, {1, 55, true}, {7, 70, true}};
+ Handle<ByteArray> source_positions =
+ source_position_builder()->ToSourcePositionTable();
+ SourcePositionTableIterator source_iterator(*source_positions);
+ for (size_t i = 0; i < arraysize(expected_positions); ++i) {
+ const PositionTableEntry& expected = expected_positions[i];
+ CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset);
+ CHECK_EQ(source_iterator.source_position(), expected.source_position);
+ CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
+ source_iterator.Advance();
+ }
+ CHECK(source_iterator.done());
+}
+
+TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
+ static const uint8_t expected_bytes[] = {
+ // clang-format off
+ /* 0 30 E> */ B(StackCheck),
+ /* 1 42 S> */ B(LdaConstant), U8(0),
+ /* 3 42 E> */ B(Star), R8(1),
+ /* 5 68 S> */ B(JumpIfUndefined), U8(38),
+ /* 7 */ B(JumpIfNull), U8(36),
+ /* 9 */ B(ToObject),
+ /* 10 */ B(Star), R8(3),
+ /* 12 */ B(ForInPrepare), R8(4),
+ /* 14 */ B(LdaZero),
+ /* 15 */ B(Star), R8(7),
+ /* 17 63 S> */ B(ForInDone), R8(7), R8(6),
+ /* 20 */ B(JumpIfTrue), U8(23),
+ /* 22 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1),
+ /* 27 */ B(JumpIfUndefined), U8(10),
+ /* 29 */ B(Star), R8(0),
+ /* 31 54 E> */ B(StackCheck),
+ /* 32 */ B(Ldar), R8(0),
+ /* 34 */ B(Star), R8(2),
+ /* 36 85 S> */ B(Return),
+ /* 37 */ B(ForInStep), R8(7),
+ /* 39 */ B(Star), R8(7),
+ /* 41 */ B(Jump), U8(-24),
+ /* 43 */ B(LdaUndefined),
+ /* 44 85 S> */ B(Return),
+ // clang-format on
+ };
+
+ static const PositionTableEntry expected_positions[] = {
+ {0, 30, false}, {1, 42, true}, {3, 42, false}, {5, 68, true},
+ {17, 63, true}, {31, 54, false}, {36, 85, true}, {44, 85, true}};
+
+#define R(i) static_cast<uint32_t>(Register(i).ToOperand())
+ Write(Bytecode::kStackCheck, {30, false});
+ Write(Bytecode::kLdaConstant, U8(0), OperandScale::kSingle, {42, true});
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 0 * kPointerSize);
+ Write(Bytecode::kStar, R(1), OperandScale::kSingle, {42, false});
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 2 * kPointerSize);
+ Write(Bytecode::kJumpIfUndefined, U8(38), OperandScale::kSingle, {68, true});
+ Write(Bytecode::kJumpIfNull, U8(36), OperandScale::kSingle);
+ Write(Bytecode::kToObject);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 2 * kPointerSize);
+ Write(Bytecode::kStar, R(3), OperandScale::kSingle);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 4 * kPointerSize);
+ Write(Bytecode::kForInPrepare, R(4), OperandScale::kSingle);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 7 * kPointerSize);
+ Write(Bytecode::kLdaZero);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 7 * kPointerSize);
+ Write(Bytecode::kStar, R(7), OperandScale::kSingle);
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 8 * kPointerSize);
+ Write(Bytecode::kForInDone, R(7), R(6), OperandScale::kSingle, {63, true});
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 8 * kPointerSize);
+ Write(Bytecode::kJumpIfTrue, U8(23), OperandScale::kSingle);
+ Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1), OperandScale::kSingle);
+ Write(Bytecode::kJumpIfUndefined, U8(10), OperandScale::kSingle);
+ Write(Bytecode::kStar, R(0), OperandScale::kSingle);
+ Write(Bytecode::kStackCheck, {54, false});
+ Write(Bytecode::kLdar, R(0), OperandScale::kSingle);
+ Write(Bytecode::kStar, R(2), OperandScale::kSingle);
+ Write(Bytecode::kReturn, {85, true});
+ Write(Bytecode::kForInStep, R(7), OperandScale::kSingle);
+ Write(Bytecode::kStar, R(7), OperandScale::kSingle);
+ Write(Bytecode::kJump, U8(-24), OperandScale::kSingle);
+ Write(Bytecode::kLdaUndefined);
+ Write(Bytecode::kReturn, {85, true});
+ CHECK_EQ(writer()->GetMaximumFrameSizeUsed(), 8 * kPointerSize);
+#undef R
+
+ CHECK_EQ(writer()->bytecodes()->size(), arraysize(expected_bytes));
+ for (size_t i = 0; i < arraysize(expected_bytes); ++i) {
+ CHECK_EQ(static_cast<int>(writer()->bytecodes()->at(i)),
+ static_cast<int>(expected_bytes[i]));
+ }
+
+ Handle<ByteArray> source_positions =
+ source_position_builder()->ToSourcePositionTable();
+ SourcePositionTableIterator source_iterator(*source_positions);
+ for (size_t i = 0; i < arraysize(expected_positions); ++i) {
+ const PositionTableEntry& expected = expected_positions[i];
+ CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset);
+ CHECK_EQ(source_iterator.source_position(), expected.source_position);
+ CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
+ source_iterator.Advance();
+ }
+ CHECK(source_iterator.done());
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc b/test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc
new file mode 100644
index 0000000..cf4a920
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc
@@ -0,0 +1,385 @@
+// 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/v8.h"
+
+#include "src/factory.h"
+#include "src/interpreter/bytecode-peephole-optimizer.h"
+#include "src/interpreter/constant-array-builder.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodePeepholeOptimizerTest : public BytecodePipelineStage,
+ public TestWithIsolateAndZone {
+ public:
+ BytecodePeepholeOptimizerTest()
+ : constant_array_builder_(isolate(), zone()),
+ peephole_optimizer_(&constant_array_builder_, this) {}
+ ~BytecodePeepholeOptimizerTest() override {}
+
+ size_t FlushForOffset() override {
+ flush_for_offset_count_++;
+ return 0;
+ };
+
+ void FlushBasicBlock() override { flush_basic_block_count_++; }
+
+ void Write(BytecodeNode* node) override {
+ write_count_++;
+ last_written_.Clone(node);
+ }
+
+ BytecodePeepholeOptimizer* optimizer() { return &peephole_optimizer_; }
+ ConstantArrayBuilder* constant_array() { return &constant_array_builder_; }
+
+ int flush_for_offset_count() const { return flush_for_offset_count_; }
+ int flush_basic_block_count() const { return flush_basic_block_count_; }
+ int write_count() const { return write_count_; }
+ const BytecodeNode& last_written() const { return last_written_; }
+
+ private:
+ ConstantArrayBuilder constant_array_builder_;
+ BytecodePeepholeOptimizer peephole_optimizer_;
+
+ int flush_for_offset_count_ = 0;
+ int flush_basic_block_count_ = 0;
+ int write_count_ = 0;
+ BytecodeNode last_written_;
+};
+
+// Sanity tests.
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetPassThrough) {
+ CHECK_EQ(flush_for_offset_count(), 0);
+ CHECK_EQ(optimizer()->FlushForOffset(), 0);
+ CHECK_EQ(flush_for_offset_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetRightSize) {
+ BytecodeNode node(Bytecode::kAdd, Register(0).ToOperand(),
+ OperandScale::kQuadruple);
+ optimizer()->Write(&node);
+ CHECK_EQ(optimizer()->FlushForOffset(), node.Size());
+ CHECK_EQ(flush_for_offset_count(), 1);
+ CHECK_EQ(write_count(), 0);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNop) {
+ BytecodeNode node(Bytecode::kNop);
+ optimizer()->Write(&node);
+ CHECK_EQ(optimizer()->FlushForOffset(), 0);
+ CHECK_EQ(flush_for_offset_count(), 1);
+ CHECK_EQ(write_count(), 0);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNopExpression) {
+ BytecodeNode node(Bytecode::kNop);
+ node.source_info().Update({3, false});
+ optimizer()->Write(&node);
+ CHECK_EQ(optimizer()->FlushForOffset(), 0);
+ CHECK_EQ(flush_for_offset_count(), 1);
+ CHECK_EQ(write_count(), 0);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNopStatement) {
+ BytecodeNode node(Bytecode::kNop);
+ node.source_info().Update({3, true});
+ optimizer()->Write(&node);
+ CHECK_EQ(optimizer()->FlushForOffset(), node.Size());
+ CHECK_EQ(flush_for_offset_count(), 1);
+ CHECK_EQ(write_count(), 0);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushBasicBlockPassThrough) {
+ CHECK_EQ(flush_basic_block_count(), 0);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(flush_basic_block_count(), 1);
+ CHECK_EQ(write_count(), 0);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, WriteOneFlushBasicBlock) {
+ BytecodeNode node(Bytecode::kAdd, Register(0).ToOperand(),
+ OperandScale::kQuadruple);
+ optimizer()->Write(&node);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(node, last_written());
+}
+
+// Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode().
+
+TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) {
+ BytecodeNode first(Bytecode::kLdaNull);
+ BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) {
+ BytecodeNode first(Bytecode::kLdaTrue);
+ BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue);
+ CHECK_EQ(last_written().operand(0), second.operand(0));
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, KeepToBooleanLogicalNot) {
+ BytecodeNode first(Bytecode::kLdaNull);
+ BytecodeNode second(Bytecode::kToBooleanLogicalNot);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ElideToBooleanLogicalNot) {
+ BytecodeNode first(Bytecode::kLdaTrue);
+ BytecodeNode second(Bytecode::kToBooleanLogicalNot);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot);
+}
+
+// Tests covering BytecodePeepholeOptimizer::CanElideCurrent().
+
+TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRy) {
+ BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand(),
+ OperandScale::kSingle);
+ optimizer()->Write(&first);
+ optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRx) {
+ BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRxStatement) {
+ BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ second.source_info().Update({0, true});
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written().bytecode(), Bytecode::kNop);
+ CHECK_EQ(last_written().source_info(), second.source_info());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRxStatementStarRy) {
+ BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ BytecodeNode third(Bytecode::kStar, Register(3).ToOperand(),
+ OperandScale::kSingle);
+ second.source_info().Update({0, true});
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->Write(&third);
+ CHECK_EQ(write_count(), 1);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ // Source position should move |second| to |third| when |second| is elided.
+ third.source_info().Update(second.source_info());
+ CHECK_EQ(last_written(), third);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
+ BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kToName);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) {
+ BytecodeNode first(Bytecode::kToName);
+ BytecodeNode second(Bytecode::kToName);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) {
+ BytecodeNode first(Bytecode::kTypeOf);
+ BytecodeNode second(Bytecode::kToName);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
+ Handle<Object> word =
+ isolate()->factory()->NewStringFromStaticChars("optimizing");
+ size_t index = constant_array()->Insert(word);
+ BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kToName);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) {
+ Handle<Object> word = isolate()->factory()->NewNumber(0.380);
+ size_t index = constant_array()->Insert(word);
+ BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index),
+ OperandScale::kSingle);
+ BytecodeNode second(Bytecode::kToName);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written(), second);
+}
+
+// Tests covering BytecodePeepholeOptimizer::CanElideLast().
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalseNotDiscardable) {
+ BytecodeNode first(Bytecode::kLdaTrue);
+ BytecodeNode second(Bytecode::kLdaFalse);
+ optimizer()->Write(&first);
+ optimizer()->FlushForOffset(); // Prevent discarding of |first|.
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), first);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 2);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) {
+ BytecodeNode first(Bytecode::kLdaTrue);
+ BytecodeNode second(Bytecode::kLdaFalse);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
+ BytecodeNode first(Bytecode::kLdaTrue);
+ first.source_info().Update({3, false});
+ BytecodeNode second(Bytecode::kLdaFalse);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+ second.source_info().Update(first.source_info());
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
+ BytecodeNode first(Bytecode::kNop);
+ BytecodeNode second(Bytecode::kStackCheck);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+ CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
+ BytecodeNode first(Bytecode::kNop);
+ first.source_info().Update({3, false});
+ BytecodeNode second(Bytecode::kStackCheck);
+ optimizer()->Write(&first);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->Write(&second);
+ CHECK_EQ(write_count(), 0);
+ optimizer()->FlushBasicBlock();
+ CHECK_EQ(write_count(), 1);
+ second.source_info().Update(first.source_info());
+ CHECK_EQ(last_written(), second);
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/interpreter/bytecode-pipeline-unittest.cc b/test/unittests/interpreter/bytecode-pipeline-unittest.cc
new file mode 100644
index 0000000..f12391c
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-pipeline-unittest.cc
@@ -0,0 +1,198 @@
+// 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/v8.h"
+
+#include "src/interpreter/bytecode-pipeline.h"
+#include "src/interpreter/bytecode-register-allocator.h"
+#include "src/isolate.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+using BytecodeNodeTest = TestWithIsolateAndZone;
+
+TEST(BytecodeSourceInfo, Operations) {
+ BytecodeSourceInfo x(0, true);
+ CHECK_EQ(x.source_position(), 0);
+ CHECK_EQ(x.is_statement(), true);
+ CHECK_EQ(x.is_valid(), true);
+ x.set_invalid();
+ CHECK_EQ(x.is_statement(), false);
+ CHECK_EQ(x.is_valid(), false);
+
+ x.Update({1, true});
+ BytecodeSourceInfo y(1, true);
+ CHECK(x == y);
+ CHECK(!(x != y));
+
+ x.set_invalid();
+ CHECK(!(x == y));
+ CHECK(x != y);
+
+ y.Update({2, false});
+ CHECK_EQ(y.source_position(), 1);
+ CHECK_EQ(y.is_statement(), true);
+
+ y.Update({2, true});
+ CHECK_EQ(y.source_position(), 2);
+ CHECK_EQ(y.is_statement(), true);
+
+ y.set_invalid();
+ y.Update({3, false});
+ CHECK_EQ(y.source_position(), 3);
+ CHECK_EQ(y.is_statement(), false);
+
+ y.Update({3, true});
+ CHECK_EQ(y.source_position(), 3);
+ CHECK_EQ(y.is_statement(), true);
+}
+
+TEST_F(BytecodeNodeTest, Constructor0) {
+ BytecodeNode node;
+ CHECK_EQ(node.bytecode(), Bytecode::kIllegal);
+ CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Constructor1) {
+ BytecodeNode node(Bytecode::kLdaZero);
+ CHECK_EQ(node.bytecode(), Bytecode::kLdaZero);
+ CHECK_EQ(node.operand_count(), 0);
+ CHECK_EQ(node.operand_scale(), OperandScale::kSingle);
+ CHECK(!node.source_info().is_valid());
+ CHECK_EQ(node.Size(), 1);
+}
+
+TEST_F(BytecodeNodeTest, Constructor2) {
+ uint32_t operands[] = {0x11};
+ BytecodeNode node(Bytecode::kJumpIfTrue, operands[0], OperandScale::kDouble);
+ CHECK_EQ(node.bytecode(), Bytecode::kJumpIfTrue);
+ CHECK_EQ(node.operand_count(), 1);
+ CHECK_EQ(node.operand(0), operands[0]);
+ CHECK_EQ(node.operand_scale(), OperandScale::kDouble);
+ CHECK(!node.source_info().is_valid());
+ CHECK_EQ(node.Size(), 4);
+}
+
+TEST_F(BytecodeNodeTest, Constructor3) {
+ uint32_t operands[] = {0x11, 0x22};
+ BytecodeNode node(Bytecode::kLdaGlobal, operands[0], operands[1],
+ OperandScale::kQuadruple);
+ CHECK_EQ(node.bytecode(), Bytecode::kLdaGlobal);
+ CHECK_EQ(node.operand_count(), 2);
+ CHECK_EQ(node.operand(0), operands[0]);
+ CHECK_EQ(node.operand(1), operands[1]);
+ CHECK_EQ(node.operand_scale(), OperandScale::kQuadruple);
+ CHECK(!node.source_info().is_valid());
+ CHECK_EQ(node.Size(), 10);
+}
+
+TEST_F(BytecodeNodeTest, Constructor4) {
+ uint32_t operands[] = {0x11, 0x22, 0x33};
+ BytecodeNode node(Bytecode::kLoadIC, operands[0], operands[1], operands[2],
+ OperandScale::kSingle);
+ CHECK_EQ(node.operand_count(), 3);
+ CHECK_EQ(node.bytecode(), Bytecode::kLoadIC);
+ CHECK_EQ(node.operand(0), operands[0]);
+ CHECK_EQ(node.operand(1), operands[1]);
+ CHECK_EQ(node.operand(2), operands[2]);
+ CHECK_EQ(node.operand_scale(), OperandScale::kSingle);
+ CHECK(!node.source_info().is_valid());
+ CHECK_EQ(node.Size(), 4);
+}
+
+TEST_F(BytecodeNodeTest, Constructor5) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ CHECK_EQ(node.operand_count(), 4);
+ CHECK_EQ(node.bytecode(), Bytecode::kForInNext);
+ CHECK_EQ(node.operand(0), operands[0]);
+ CHECK_EQ(node.operand(1), operands[1]);
+ CHECK_EQ(node.operand(2), operands[2]);
+ CHECK_EQ(node.operand(3), operands[3]);
+ CHECK_EQ(node.operand_scale(), OperandScale::kDouble);
+ CHECK(!node.source_info().is_valid());
+ CHECK_EQ(node.Size(), 10);
+}
+
+TEST_F(BytecodeNodeTest, Equality) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ CHECK_EQ(node, node);
+ BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
+ operands[2], operands[3], OperandScale::kDouble);
+ CHECK_EQ(node, other);
+}
+
+TEST_F(BytecodeNodeTest, EqualityWithSourceInfo) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ node.source_info().Update({3, true});
+ CHECK_EQ(node, node);
+ BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
+ operands[2], operands[3], OperandScale::kDouble);
+ other.source_info().Update({3, true});
+ CHECK_EQ(node, other);
+}
+
+TEST_F(BytecodeNodeTest, NoEqualityWithDifferentSourceInfo) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ node.source_info().Update({3, true});
+ BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
+ operands[2], operands[3], OperandScale::kDouble);
+ CHECK_NE(node, other);
+}
+
+TEST_F(BytecodeNodeTest, Clone) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ BytecodeNode clone;
+ clone.Clone(&node);
+ CHECK_EQ(clone, node);
+}
+
+TEST_F(BytecodeNodeTest, SetBytecode0) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ BytecodeSourceInfo source_info(77, false);
+ node.source_info().Update(source_info);
+
+ BytecodeNode clone;
+ clone.Clone(&node);
+ clone.set_bytecode(Bytecode::kNop);
+ CHECK_EQ(clone.bytecode(), Bytecode::kNop);
+ CHECK_EQ(clone.operand_count(), 0);
+ CHECK_EQ(clone.operand_scale(), OperandScale::kSingle);
+ CHECK_EQ(clone.source_info(), source_info);
+}
+
+TEST_F(BytecodeNodeTest, SetBytecode1) {
+ uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+ BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+ operands[3], OperandScale::kDouble);
+ BytecodeSourceInfo source_info(77, false);
+ node.source_info().Update(source_info);
+
+ BytecodeNode clone;
+ clone.Clone(&node);
+ clone.set_bytecode(Bytecode::kJump, 0x01aabbcc, OperandScale::kQuadruple);
+ CHECK_EQ(clone.bytecode(), Bytecode::kJump);
+ CHECK_EQ(clone.operand_count(), 1);
+ CHECK_EQ(clone.operand(0), 0x01aabbcc);
+ CHECK_EQ(clone.operand_scale(), OperandScale::kQuadruple);
+ CHECK_EQ(clone.source_info(), source_info);
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/interpreter/bytecode-utils.h b/test/unittests/interpreter/bytecode-utils.h
new file mode 100644
index 0000000..fffb719
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-utils.h
@@ -0,0 +1,37 @@
+// 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_BYTECODE_UTILS_H_
+#define V8_UNITTESTS_INTERPRETER_BYTECODE_UTILS_H_
+
+#include "src/frames.h"
+
+#if V8_TARGET_LITTLE_ENDIAN
+
+#define EXTRACT(x, n) static_cast<uint8_t>((x) >> (8 * n))
+#define U16(i) EXTRACT(i, 0), EXTRACT(i, 1)
+#define U32(i) EXTRACT(i, 0), EXTRACT(i, 1), EXTRACT(i, 2), EXTRACT(i, 3)
+
+#elif V8_TARGET_BIG_ENDIAN
+
+#define EXTRACT(x, n) static_cast<uint8_t>((x) >> (8 * n))
+
+#define U16(i) EXTRACT(i, 1), EXTRACT(i, 0)
+#define U32(i) EXTRACT(i, 3), EXTRACT(i, 2), EXTRACT(i, 1), EXTRACT(i, 0)
+
+#else
+
+#error "Unknown Architecture"
+
+#endif
+
+#define U8(i) static_cast<uint8_t>(i)
+#define B(Name) static_cast<uint8_t>(Bytecode::k##Name)
+#define REG_OPERAND(i) \
+ (InterpreterFrameConstants::kRegisterFileFromFp / kPointerSize - (i))
+#define R8(i) static_cast<uint8_t>(REG_OPERAND(i))
+#define R16(i) U16(REG_OPERAND(i))
+#define R32(i) U32(REG_OPERAND(i))
+
+#endif // V8_UNITTESTS_INTERPRETER_BYTECODE_UTILS_H_
diff --git a/test/unittests/interpreter/bytecodes-unittest.cc b/test/unittests/interpreter/bytecodes-unittest.cc
index b3554c3..eebacb2 100644
--- a/test/unittests/interpreter/bytecodes-unittest.cc
+++ b/test/unittests/interpreter/bytecodes-unittest.cc
@@ -7,6 +7,7 @@
#include "src/v8.h"
#include "src/interpreter/bytecodes.h"
+#include "test/unittests/interpreter/bytecode-utils.h"
#include "test/unittests/test-utils.h"
namespace v8 {
@@ -31,15 +32,6 @@
Register reg2 = Register::FromOperand(operand2);
CHECK_EQ(i, reg2.index());
}
-
- for (int i = 0; i <= kMaxUInt8; i++) {
- Register reg = Register::FromOperand(i);
- if (i > 0) {
- CHECK(reg.is_parameter());
- } else {
- CHECK(!reg.is_parameter());
- }
- }
}
TEST(OperandConversion, Parameters) {
@@ -85,9 +77,13 @@
}
TEST(OperandScaling, ScalableAndNonScalable) {
- for (OperandScale operand_scale = OperandScale::kSingle;
- operand_scale <= OperandScale::kMaxValid;
- operand_scale = Bytecodes::NextOperandScale(operand_scale)) {
+ const OperandScale kOperandScales[] = {
+#define VALUE(Name, _) OperandScale::k##Name,
+ OPERAND_SCALE_LIST(VALUE)
+#undef VALUE
+ };
+
+ for (OperandScale operand_scale : kOperandScales) {
int scale = static_cast<int>(operand_scale);
CHECK_EQ(Bytecodes::Size(Bytecode::kCallRuntime, operand_scale),
1 + 2 + 2 * scale);
@@ -185,23 +181,22 @@
const char* output;
};
-#define B(Name) static_cast<uint8_t>(Bytecode::k##Name)
const BytecodesAndResult cases[] = {
- {{B(LdaSmi), 0x01}, 2, 0, " LdaSmi [1]"},
- {{B(Wide), B(LdaSmi), 0xe8, 0x03}, 4, 0, " LdaSmi.Wide [1000]"},
- {{B(ExtraWide), B(LdaSmi), 0xa0, 0x86, 0x01, 0x00},
+ {{B(LdaSmi), U8(1)}, 2, 0, " LdaSmi [1]"},
+ {{B(Wide), B(LdaSmi), U16(1000)}, 4, 0, " LdaSmi.Wide [1000]"},
+ {{B(ExtraWide), B(LdaSmi), U32(100000)},
6,
0,
"LdaSmi.ExtraWide [100000]"},
- {{B(LdaSmi), 0xff}, 2, 0, " LdaSmi [-1]"},
- {{B(Wide), B(LdaSmi), 0x18, 0xfc}, 4, 0, " LdaSmi.Wide [-1000]"},
- {{B(ExtraWide), B(LdaSmi), 0x60, 0x79, 0xfe, 0xff},
+ {{B(LdaSmi), U8(-1)}, 2, 0, " LdaSmi [-1]"},
+ {{B(Wide), B(LdaSmi), U16(-1000)}, 4, 0, " LdaSmi.Wide [-1000]"},
+ {{B(ExtraWide), B(LdaSmi), U32(-100000)},
6,
0,
"LdaSmi.ExtraWide [-100000]"},
- {{B(Star), 0xfb}, 2, 0, " Star r5"},
- {{B(Wide), B(Star), 0x78, 0xff}, 4, 0, " Star.Wide r136"},
- {{B(Wide), B(Call), 0x7a, 0xff, 0x79, 0xff, 0x02, 0x00, 0xb1, 0x00},
+ {{B(Star), R8(5)}, 2, 0, " Star r5"},
+ {{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"},
+ {{B(Wide), B(Call), R16(134), R16(135), U16(2), U16(177)},
10,
0,
"Call.Wide r134, r135, #2, [177]"},
@@ -210,16 +205,15 @@
2,
3,
" Ldar a1"},
- {{B(Wide), B(CreateObjectLiteral), 0x01, 0x02, 0x03, 0x04, 0xa5},
+ {{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165)},
7,
0,
"CreateObjectLiteral.Wide [513], [1027], #165"},
- {{B(ExtraWide), B(JumpIfNull), 0x15, 0xcd, 0x5b, 0x07},
+ {{B(ExtraWide), B(JumpIfNull), U32(123456789)},
6,
0,
"JumpIfNull.ExtraWide [123456789]"},
};
-#undef B
for (size_t i = 0; i < arraysize(cases); ++i) {
// Generate reference string by prepending formatted bytes.
@@ -260,13 +254,71 @@
}
}
-TEST(OperandScale, PrefixesScale) {
- CHECK(Bytecodes::NextOperandScale(OperandScale::kSingle) ==
- OperandScale::kDouble);
- CHECK(Bytecodes::NextOperandScale(OperandScale::kDouble) ==
- OperandScale::kQuadruple);
- CHECK(Bytecodes::NextOperandScale(OperandScale::kQuadruple) ==
- OperandScale::kInvalid);
+TEST(Bytecodes, OperandScales) {
+ CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kByte),
+ OperandScale::kSingle);
+ CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kShort),
+ OperandScale::kDouble);
+ CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kQuad),
+ OperandScale::kQuadruple);
+ CHECK_EQ(
+ Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
+ OperandSize::kShort, OperandSize::kShort),
+ OperandScale::kDouble);
+ CHECK_EQ(
+ Bytecodes::OperandSizesToScale(OperandSize::kQuad, OperandSize::kShort,
+ OperandSize::kShort, OperandSize::kShort),
+ OperandScale::kQuadruple);
+ CHECK_EQ(
+ Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kQuad,
+ OperandSize::kShort, OperandSize::kShort),
+ OperandScale::kQuadruple);
+ CHECK_EQ(
+ Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
+ OperandSize::kQuad, OperandSize::kShort),
+ OperandScale::kQuadruple);
+ CHECK_EQ(
+ Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
+ OperandSize::kShort, OperandSize::kQuad),
+ OperandScale::kQuadruple);
+}
+
+TEST(Bytecodes, SizesForSignedOperands) {
+ CHECK(Bytecodes::SizeForSignedOperand(0) == OperandSize::kByte);
+ CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8) == OperandSize::kByte);
+ CHECK(Bytecodes::SizeForSignedOperand(kMinInt8) == OperandSize::kByte);
+ CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8 + 1) == OperandSize::kShort);
+ CHECK(Bytecodes::SizeForSignedOperand(kMinInt8 - 1) == OperandSize::kShort);
+ CHECK(Bytecodes::SizeForSignedOperand(kMaxInt16) == OperandSize::kShort);
+ CHECK(Bytecodes::SizeForSignedOperand(kMinInt16) == OperandSize::kShort);
+ CHECK(Bytecodes::SizeForSignedOperand(kMaxInt16 + 1) == OperandSize::kQuad);
+ CHECK(Bytecodes::SizeForSignedOperand(kMinInt16 - 1) == OperandSize::kQuad);
+ CHECK(Bytecodes::SizeForSignedOperand(kMaxInt) == OperandSize::kQuad);
+ CHECK(Bytecodes::SizeForSignedOperand(kMinInt) == OperandSize::kQuad);
+}
+
+TEST(Bytecodes, SizesForUnsignedOperands) {
+ // int overloads
+ CHECK(Bytecodes::SizeForUnsignedOperand(0) == OperandSize::kByte);
+ CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt8) == OperandSize::kByte);
+ CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt8 + 1) ==
+ OperandSize::kShort);
+ CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt16) == OperandSize::kShort);
+ CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt16 + 1) ==
+ OperandSize::kQuad);
+ // size_t overloads
+ CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(0)) ==
+ OperandSize::kByte);
+ CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt8)) ==
+ OperandSize::kByte);
+ CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt8 + 1)) ==
+ OperandSize::kShort);
+ CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt16)) ==
+ OperandSize::kShort);
+ CHECK(Bytecodes::SizeForUnsignedOperand(
+ static_cast<size_t>(kMaxUInt16 + 1)) == OperandSize::kQuad);
+ CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt32)) ==
+ OperandSize::kQuad);
}
TEST(OperandScale, PrefixesRequired) {
diff --git a/test/unittests/interpreter/interpreter-assembler-unittest.cc b/test/unittests/interpreter/interpreter-assembler-unittest.cc
index 0106c57..cd21f09 100644
--- a/test/unittests/interpreter/interpreter-assembler-unittest.cc
+++ b/test/unittests/interpreter/interpreter-assembler-unittest.cc
@@ -313,12 +313,7 @@
TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
- m.Dispatch();
- Graph* graph = m.graph();
-
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
+ Node* tail_call_node = m.Dispatch();
OperandScale operand_scale = OperandScale::kSingle;
Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
@@ -342,12 +337,10 @@
IsTailCall(
_, code_target_matcher,
IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
- IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
next_bytecode_offset_matcher,
IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
- IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
- _));
+ _, _));
}
}
@@ -359,11 +352,7 @@
TRACED_FOREACH(int, jump_offset, jump_offsets) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
- m.Jump(m.IntPtrConstant(jump_offset));
- Graph* graph = m.graph();
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
+ Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
@@ -385,100 +374,14 @@
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) {
- InterpreterAssemblerForTest m(this, bytecode);
- Node* lhs = m.IntPtrConstant(0);
- Node* rhs = m.IntPtrConstant(1);
- m.JumpIfWordEqual(lhs, rhs, m.IntPtrConstant(kJumpIfTrueOffset));
- Graph* graph = m.graph();
- Node* end = graph->end();
- EXPECT_EQ(2, end->InputCount());
-
- OperandScale operand_scale = OperandScale::kSingle;
- int jump_offsets[] = {kJumpIfTrueOffset, interpreter::Bytecodes::Size(
- bytecode, operand_scale)};
- for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
- Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
- IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
- IsIntPtrConstant(jump_offsets[i]));
- Matcher<Node*> target_bytecode_matcher =
- m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
- if (kPointerSize == 8) {
- target_bytecode_matcher =
- IsChangeUint32ToUint64(target_bytecode_matcher);
- }
- Matcher<Node*> code_target_matcher = m.IsLoad(
- MachineType::Pointer(),
- IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
- IsWordShl(target_bytecode_matcher,
- IsIntPtrConstant(kPointerSizeLog2)));
- EXPECT_THAT(
- end->InputAt(i),
- 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;
-
- TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
- InterpreterAssemblerForTest m(this, bytecode);
- m.InterpreterReturn();
- Graph* graph = m.graph();
-
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
-
- Handle<HeapObject> exit_trampoline =
- isolate()->builtins()->InterpreterExitTrampoline();
- EXPECT_THAT(
- tail_call_node,
- IsTailCall(
- _, IsHeapConstant(exit_trampoline),
- IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
- IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
- IsParameter(
- InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
- _,
- IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
- IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
- _));
- }
-}
-
TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
static const OperandScale kOperandScales[] = {
OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
@@ -555,24 +458,21 @@
EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
// Should be passed to next bytecode handler on dispatch.
- m.Dispatch();
- Graph* graph = m.graph();
-
- Node* end = graph->end();
- EXPECT_EQ(1, end->InputCount());
- Node* tail_call_node = end->InputAt(0);
+ Node* tail_call_node = m.Dispatch();
EXPECT_THAT(tail_call_node,
- IsTailCall(_, _, accumulator_value_2, _, _, _, _, _, _));
+ IsTailCall(_, _, accumulator_value_2, _, _, _, _));
}
}
-TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
+TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
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);
+ EXPECT_THAT(
+ m.GetContext(),
+ m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
+ IsIntPtrConstant(Register::current_context().ToOperand()
+ << kPointerSizeLog2)));
}
}
@@ -581,11 +481,10 @@
InterpreterAssemblerForTest m(this, bytecode);
Node* reg_index_node = m.IntPtrConstant(44);
Node* reg_location_node = m.RegisterLocation(reg_index_node);
- EXPECT_THAT(
- reg_location_node,
- IsIntPtrAdd(
- IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
- IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2))));
+ EXPECT_THAT(reg_location_node,
+ IsIntPtrAdd(IsLoadParentFramePointer(),
+ IsWordShl(reg_index_node,
+ IsIntPtrConstant(kPointerSizeLog2))));
}
}
@@ -594,12 +493,10 @@
InterpreterAssemblerForTest m(this, bytecode);
Node* reg_index_node = m.IntPtrConstant(44);
Node* load_reg_node = m.LoadRegister(reg_index_node);
- EXPECT_THAT(
- load_reg_node,
- m.IsLoad(
- MachineType::AnyTagged(),
- IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
- IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2))));
+ EXPECT_THAT(load_reg_node,
+ m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
+ IsWordShl(reg_index_node,
+ IsIntPtrConstant(kPointerSizeLog2))));
}
}
@@ -611,12 +508,11 @@
Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
EXPECT_THAT(
store_reg_node,
- m.IsStore(
- StoreRepresentation(MachineRepresentation::kTagged,
- kNoWriteBarrier),
- IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
- IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2)),
- store_value));
+ m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
+ kNoWriteBarrier),
+ IsLoadParentFramePointer(),
+ IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2)),
+ store_value));
}
}
@@ -624,9 +520,9 @@
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* value = m.Int32Constant(44);
- EXPECT_THAT(
- m.SmiTag(value),
- IsWordShl(value, IsIntPtrConstant(kSmiShiftSize + kSmiTagSize)));
+ EXPECT_THAT(m.SmiTag(value),
+ IsIntPtrConstant(static_cast<intptr_t>(44)
+ << (kSmiShiftSize + kSmiTagSize)));
EXPECT_THAT(
m.SmiUntag(value),
IsWordSar(value, IsIntPtrConstant(kSmiShiftSize + kSmiTagSize)));
@@ -730,14 +626,10 @@
InterpreterAssemblerForTest m(this, bytecode);
Node* arg1 = m.Int32Constant(2);
Node* arg2 = m.Int32Constant(3);
- Node* context =
- m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+ Node* context = m.Int32Constant(4);
Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
- EXPECT_THAT(
- call_runtime,
- IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
- IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
- _));
+ EXPECT_THAT(call_runtime,
+ IsCall(_, _, arg1, arg2, _, IsInt32Constant(2), context, _, _));
}
}
@@ -751,8 +643,7 @@
Node* function_id = m.Int32Constant(0);
Node* first_arg = m.Int32Constant(1);
Node* arg_count = m.Int32Constant(2);
- Node* context =
- m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+ Node* context = m.Int32Constant(4);
Matcher<Node*> function_table = IsExternalConstant(
ExternalReference::runtime_function_table_address(isolate()));
@@ -765,12 +656,9 @@
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(InterpreterDispatchDescriptor::kContextParameter),
- _, _));
+ EXPECT_THAT(call_runtime,
+ IsCall(_, IsHeapConstant(builtin.code()), arg_count,
+ first_arg, function_entry, context, _, _));
}
}
}
@@ -786,16 +674,11 @@
Node* function = m.Int32Constant(0);
Node* first_arg = m.Int32Constant(1);
Node* arg_count = m.Int32Constant(2);
- Node* context =
- m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+ Node* context = m.Int32Constant(3);
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),
- _, _));
+ EXPECT_THAT(call_js, IsCall(_, IsHeapConstant(builtin.code()), arg_count,
+ first_arg, function, context, _, _));
}
}
}
@@ -805,11 +688,10 @@
InterpreterAssemblerForTest m(this, bytecode);
Node* feedback_vector = m.LoadTypeFeedbackVector();
- Matcher<Node*> load_function_matcher = m.IsLoad(
- MachineType::AnyTagged(),
- IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
- IsIntPtrConstant(
- InterpreterFrameConstants::kFunctionFromRegisterPointer));
+ Matcher<Node*> load_function_matcher =
+ m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
+ IsIntPtrConstant(Register::function_closure().ToOperand()
+ << kPointerSizeLog2));
Matcher<Node*> load_shared_function_info_matcher =
m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
diff --git a/test/unittests/interpreter/source-position-table-unittest.cc b/test/unittests/interpreter/source-position-table-unittest.cc
index d62302a..230e57d 100644
--- a/test/unittests/interpreter/source-position-table-unittest.cc
+++ b/test/unittests/interpreter/source-position-table-unittest.cc
@@ -25,7 +25,7 @@
TEST_F(SourcePositionTableTest, EncodeStatement) {
SourcePositionTableBuilder builder(isolate(), zone());
for (int i = 0; i < arraysize(offsets); i++) {
- builder.AddStatementPosition(offsets[i], offsets[i]);
+ builder.AddPosition(offsets[i], offsets[i], true);
}
// To test correctness, we rely on the assertions in ToSourcePositionTable().
@@ -36,8 +36,8 @@
TEST_F(SourcePositionTableTest, EncodeStatementDuplicates) {
SourcePositionTableBuilder builder(isolate(), zone());
for (int i = 0; i < arraysize(offsets); i++) {
- builder.AddStatementPosition(offsets[i], offsets[i]);
- builder.AddStatementPosition(offsets[i], offsets[i] + 1);
+ builder.AddPosition(offsets[i], offsets[i], true);
+ builder.AddPosition(offsets[i], offsets[i] + 1, true);
}
// To test correctness, we rely on the assertions in ToSourcePositionTable().
@@ -48,7 +48,7 @@
TEST_F(SourcePositionTableTest, EncodeExpression) {
SourcePositionTableBuilder builder(isolate(), zone());
for (int i = 0; i < arraysize(offsets); i++) {
- builder.AddExpressionPosition(offsets[i], offsets[i]);
+ builder.AddPosition(offsets[i], offsets[i], false);
}
CHECK(!builder.ToSourcePositionTable().is_null());
}
@@ -60,9 +60,9 @@
for (int i = 0; i < arraysize(offsets); i++) {
accumulator += offsets[i];
if (i % 2) {
- builder.AddStatementPosition(accumulator, accumulator);
+ builder.AddPosition(accumulator, accumulator, true);
} else {
- builder.AddExpressionPosition(accumulator, accumulator);
+ builder.AddPosition(accumulator, accumulator, false);
}
}
@@ -70,9 +70,9 @@
for (int i = 0; i < arraysize(offsets); i++) {
accumulator -= offsets[i];
if (i % 2) {
- builder.AddStatementPosition(accumulator, accumulator);
+ builder.AddPosition(accumulator, accumulator, true);
} else {
- builder.AddExpressionPosition(accumulator, accumulator);
+ builder.AddPosition(accumulator, accumulator, false);
}
}
diff --git a/test/unittests/unittests.gyp b/test/unittests/unittests.gyp
index 003281b..e16ebeb 100644
--- a/test/unittests/unittests.gyp
+++ b/test/unittests/unittests.gyp
@@ -6,7 +6,7 @@
'variables': {
'v8_code': 1,
},
- 'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
+ 'includes': ['../../gypfiles/toolchain.gypi', '../../gypfiles/features.gypi'],
'targets': [
{
'target_name': 'unittests',
@@ -17,13 +17,13 @@
'dependencies': [
'../../testing/gmock.gyp:gmock',
'../../testing/gtest.gyp:gtest',
- '../../tools/gyp/v8.gyp:v8_libplatform',
+ '../../src/v8.gyp:v8_libplatform',
],
'include_dirs': [
'../..',
],
'sources': [ ### gcmole(all) ###
- 'atomic-utils-unittest.cc',
+ 'base/atomic-utils-unittest.cc',
'base/bits-unittest.cc',
'base/cpu-unittest.cc',
'base/division-by-constant-unittest.cc',
@@ -41,7 +41,6 @@
'cancelable-tasks-unittest.cc',
'char-predicates-unittest.cc',
'compiler/branch-elimination-unittest.cc',
- 'compiler/change-lowering-unittest.cc',
'compiler/coalesced-live-ranges-unittest.cc',
'compiler/common-operator-reducer-unittest.cc',
'compiler/common-operator-unittest.cc',
@@ -50,6 +49,7 @@
'compiler/control-flow-optimizer-unittest.cc',
'compiler/dead-code-elimination-unittest.cc',
'compiler/diamond-unittest.cc',
+ 'compiler/effect-control-linearizer-unittest.cc',
'compiler/escape-analysis-unittest.cc',
'compiler/graph-reducer-unittest.cc',
'compiler/graph-reducer-unittest.h',
@@ -96,7 +96,10 @@
'interpreter/bytecodes-unittest.cc',
'interpreter/bytecode-array-builder-unittest.cc',
'interpreter/bytecode-array-iterator-unittest.cc',
+ 'interpreter/bytecode-array-writer-unittest.cc',
+ 'interpreter/bytecode-peephole-optimizer-unittest.cc',
'interpreter/bytecode-register-allocator-unittest.cc',
+ 'interpreter/bytecode-pipeline-unittest.cc',
'interpreter/constant-array-builder-unittest.cc',
'interpreter/interpreter-assembler-unittest.cc',
'interpreter/interpreter-assembler-unittest.h',
@@ -118,8 +121,10 @@
'wasm/ast-decoder-unittest.cc',
'wasm/decoder-unittest.cc',
'wasm/encoder-unittest.cc',
+ 'wasm/leb-helper-unittest.cc',
'wasm/loop-assignment-analysis-unittest.cc',
'wasm/module-decoder-unittest.cc',
+ 'wasm/switch-logic-unittest.cc',
'wasm/wasm-macro-gen-unittest.cc',
],
'conditions': [
@@ -138,11 +143,21 @@
'compiler/ia32/instruction-selector-ia32-unittest.cc',
],
}],
+ ['v8_target_arch=="mips"', {
+ 'sources': [ ### gcmole(arch:mips) ###
+ 'compiler/mips/instruction-selector-mips-unittest.cc',
+ ],
+ }],
['v8_target_arch=="mipsel"', {
'sources': [ ### gcmole(arch:mipsel) ###
'compiler/mips/instruction-selector-mips-unittest.cc',
],
}],
+ ['v8_target_arch=="mips64"', {
+ 'sources': [ ### gcmole(arch:mips64) ###
+ 'compiler/mips64/instruction-selector-mips64-unittest.cc',
+ ],
+ }],
['v8_target_arch=="mips64el"', {
'sources': [ ### gcmole(arch:mips64el) ###
'compiler/mips64/instruction-selector-mips64-unittest.cc',
@@ -169,9 +184,9 @@
['component=="shared_library"', {
# compiler-unittests can't be built against a shared library, so we
# need to depend on the underlying static target in that case.
- 'dependencies': ['../../tools/gyp/v8.gyp:v8_maybe_snapshot'],
+ 'dependencies': ['../../src/v8.gyp:v8_maybe_snapshot'],
}, {
- 'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+ 'dependencies': ['../../src/v8.gyp:v8'],
}],
['os_posix == 1', {
# TODO(svenpanne): This is a temporary work-around to fix the warnings
@@ -198,7 +213,7 @@
'unittests',
],
'includes': [
- '../../build/isolate.gypi',
+ '../../gypfiles/isolate.gypi',
],
'sources': [
'unittests.isolate',
diff --git a/test/unittests/unittests.status b/test/unittests/unittests.status
index 40b5754..84fd087 100644
--- a/test/unittests/unittests.status
+++ b/test/unittests/unittests.status
@@ -11,6 +11,5 @@
'WasmDecoderTest.AllLoadMemCombinations': [SKIP],
'AstDecoderTest.AllLoadMemCombinations': [SKIP],
'AstDecoderTest.AllStoreMemCombinations': [SKIP],
- 'Bytecodes.DecodeBytecodeAndOperands': [SKIP],
}], # 'byteorder == big'
]
diff --git a/test/unittests/wasm/ast-decoder-unittest.cc b/test/unittests/wasm/ast-decoder-unittest.cc
index 0b1b79e..fe10115 100644
--- a/test/unittests/wasm/ast-decoder-unittest.cc
+++ b/test/unittests/wasm/ast-decoder-unittest.cc
@@ -18,9 +18,13 @@
namespace internal {
namespace wasm {
+#define B1(a) kExprBlock, a, kExprEnd
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B3(a, b, c) kExprBlock, a, b, c, kExprEnd
+
static const byte kCodeGetLocal0[] = {kExprGetLocal, 0};
static const byte kCodeGetLocal1[] = {kExprGetLocal, 1};
-static const byte kCodeSetLocal0[] = {kExprSetLocal, 0, kExprI8Const, 0};
+static const byte kCodeSetLocal0[] = {WASM_SET_LOCAL(0, WASM_ZERO)};
static const LocalType kLocalTypes[] = {kAstI32, kAstI64, kAstF32, kAstF64};
static const MachineType machineTypes[] = {
@@ -36,7 +40,7 @@
kExprI32LeS, kExprI32LtU, kExprI32LeU};
#define WASM_BRV_IF_ZERO(depth, val) \
- kExprBrIf, static_cast<byte>(depth), val, WASM_ZERO
+ val, WASM_ZERO, kExprBrIf, ARITY_1, static_cast<byte>(depth)
#define EXPECT_VERIFIES(env, x) Verify(kSuccess, env, x, x + arraysize(x))
@@ -48,7 +52,6 @@
Verify(kSuccess, env, code, code + arraysize(code)); \
} while (false)
-
#define EXPECT_FAILURE_INLINE(env, ...) \
do { \
static byte code[] = {__VA_ARGS__}; \
@@ -65,7 +68,8 @@
public:
typedef std::pair<uint32_t, LocalType> LocalsDecl;
- AstDecoderTest() : module(nullptr) {}
+ AstDecoderTest() : module(nullptr), local_decls(zone()) {}
+
TestSignatures sigs;
ModuleEnv* module;
LocalDeclEncoder local_decls;
@@ -74,7 +78,7 @@
local_decls.AddLocals(count, type);
}
- // Preprends local variable declarations and renders nice error messages for
+ // Prepends local variable declarations and renders nice error messages for
// verification failures.
void Verify(ErrorCode expected, FunctionSig* sig, const byte* start,
const byte* end) {
@@ -107,8 +111,7 @@
void TestBinop(WasmOpcode opcode, FunctionSig* success) {
// op(local[0], local[1])
- byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0, kExprGetLocal,
- 1};
+ byte code[] = {WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
EXPECT_VERIFIES(success, code);
// Try all combinations of return and parameter types.
@@ -134,7 +137,7 @@
void TestUnop(WasmOpcode opcode, LocalType ret_type, LocalType param_type) {
// Return(op(local[0]))
- byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0};
+ byte code[] = {WASM_UNOP(opcode, WASM_GET_LOCAL(0))};
{
LocalType types[] = {ret_type, param_type};
FunctionSig sig(1, 1, types);
@@ -155,7 +158,6 @@
}
};
-
TEST_F(AstDecoderTest, Int8Const) {
byte code[] = {kExprI8Const, 0};
for (int i = -128; i < 128; i++) {
@@ -176,12 +178,6 @@
EXPECT_FAILURE(sigs.i_i(), code);
}
-TEST_F(AstDecoderTest, IncompleteIf2) {
- byte code[] = {kExprIf, kExprI8Const, 0};
- EXPECT_FAILURE(sigs.v_v(), code);
- EXPECT_FAILURE(sigs.i_i(), code);
-}
-
TEST_F(AstDecoderTest, Int8Const_fallthru) {
byte code[] = {kExprI8Const, 0, kExprI8Const, 1};
EXPECT_VERIFIES(sigs.i_i(), code);
@@ -303,199 +299,294 @@
EXPECT_FAILURE(sigs.i_i(), code1);
}
- byte code3[] = {0, kExprGetLocal, 0}; // [opcode] [expr]
+ byte code3[] = {kExprGetLocal, 0, 0}; // [expr] [opcode]
for (size_t i = 0; i < arraysize(kInt32BinopOpcodes); i++) {
- code3[0] = kInt32BinopOpcodes[i];
+ code3[2] = kInt32BinopOpcodes[i];
EXPECT_FAILURE(sigs.i_i(), code3);
}
- byte code4[] = {0, kExprGetLocal, 0, 0}; // [opcode] [expr] [opcode]
+ byte code4[] = {kExprGetLocal, 0, 0, 0}; // [expr] [opcode] [opcode]
for (size_t i = 0; i < arraysize(kInt32BinopOpcodes); i++) {
- code4[0] = kInt32BinopOpcodes[i];
+ code4[2] = kInt32BinopOpcodes[i];
code4[3] = kInt32BinopOpcodes[i];
EXPECT_FAILURE(sigs.i_i(), code4);
}
}
+TEST_F(AstDecoderTest, BinopsAcrossBlock1) {
+ static const byte code[] = {WASM_ZERO, kExprBlock, WASM_ZERO, kExprI32Add,
+ kExprEnd};
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
-//===================================================================
-//== Statements
-//===================================================================
+TEST_F(AstDecoderTest, BinopsAcrossBlock2) {
+ static const byte code[] = {WASM_ZERO, WASM_ZERO, kExprBlock, kExprI32Add,
+ kExprEnd};
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, BinopsAcrossBlock3) {
+ static const byte code[] = {WASM_ZERO, WASM_ZERO, kExprIf, kExprI32Add,
+ kExprElse, kExprI32Add, kExprEnd};
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
TEST_F(AstDecoderTest, Nop) {
static const byte code[] = {kExprNop};
EXPECT_VERIFIES(sigs.v_v(), code);
}
TEST_F(AstDecoderTest, SetLocal0_param) {
- static const byte code[] = {kExprSetLocal, 0, kExprI8Const, 0};
- EXPECT_VERIFIES(sigs.i_i(), code);
+ EXPECT_VERIFIES(sigs.i_i(), kCodeSetLocal0);
+ EXPECT_FAILURE(sigs.f_ff(), kCodeSetLocal0);
+ EXPECT_FAILURE(sigs.d_dd(), kCodeSetLocal0);
}
TEST_F(AstDecoderTest, SetLocal0_local) {
- byte code[] = {kExprSetLocal, 0, kExprI8Const, 0};
+ EXPECT_FAILURE(sigs.i_v(), kCodeSetLocal0);
AddLocals(kAstI32, 1);
- EXPECT_VERIFIES(sigs.i_v(), code);
+ EXPECT_VERIFIES(sigs.i_v(), kCodeSetLocal0);
}
TEST_F(AstDecoderTest, SetLocalN_local) {
for (byte i = 1; i < 8; i++) {
AddLocals(kAstI32, 1);
for (byte j = 0; j < i; j++) {
- byte code[] = {kExprSetLocal, j, kExprI8Const, i};
- EXPECT_VERIFIES(sigs.v_v(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_SET_LOCAL(j, WASM_I8(i)));
}
}
}
+TEST_F(AstDecoderTest, BlockN) {
+ const int kMaxSize = 200;
+ byte buffer[kMaxSize + 2];
+
+ for (int i = 0; i <= kMaxSize; i++) {
+ memset(buffer, kExprNop, sizeof(buffer));
+ buffer[0] = kExprBlock;
+ buffer[i + 1] = kExprEnd;
+ Verify(kSuccess, sigs.v_i(), buffer, buffer + i + 2);
+ }
+}
+
TEST_F(AstDecoderTest, Block0) {
- static const byte code[] = {kExprBlock, 0};
+ static const byte code[] = {kExprBlock, kExprEnd};
EXPECT_VERIFIES(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
}
TEST_F(AstDecoderTest, Block0_fallthru1) {
- static const byte code[] = {kExprBlock, 0, kExprBlock, 0};
+ static const byte code[] = {kExprBlock, kExprBlock, kExprEnd, kExprEnd};
EXPECT_VERIFIES(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, Block0Block0) {
+ static const byte code[] = {kExprBlock, kExprEnd, kExprBlock, kExprEnd};
+ EXPECT_VERIFIES(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, Block0_end_end) {
+ static const byte code[] = {kExprBlock, kExprEnd, kExprEnd};
+ EXPECT_FAILURE(sigs.v_v(), code);
}
TEST_F(AstDecoderTest, Block1) {
- static const byte code[] = {kExprBlock, 1, kExprSetLocal, 0, kExprI8Const, 0};
+ byte code[] = {B1(WASM_SET_LOCAL(0, WASM_ZERO))};
EXPECT_VERIFIES(sigs.i_i(), code);
+ EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_FAILURE(sigs.d_dd(), code);
}
-TEST_F(AstDecoderTest, Block0_fallthru2) {
- static const byte code[] = {kExprBlock, 0, kExprSetLocal, 0, kExprI8Const, 0};
+TEST_F(AstDecoderTest, Block1_i) {
+ byte code[] = {B1(WASM_ZERO)};
EXPECT_VERIFIES(sigs.i_i(), code);
+ EXPECT_FAILURE(sigs.f_ff(), code);
+ EXPECT_FAILURE(sigs.d_dd(), code);
+ EXPECT_FAILURE(sigs.l_ll(), code);
}
-TEST_F(AstDecoderTest, Block2) {
- static const byte code[] = {kExprBlock, 2, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprSetLocal, 0, kExprI8Const, 0}; // --
- EXPECT_VERIFIES(sigs.i_i(), code);
-}
-
-TEST_F(AstDecoderTest, Block2_fallthru) {
- static const byte code[] = {kExprBlock, 2, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprI8Const, 11}; // --
- EXPECT_VERIFIES(sigs.i_i(), code);
-}
-
-TEST_F(AstDecoderTest, BlockN) {
- byte block[] = {kExprBlock, 2};
-
- for (size_t i = 0; i < 10; i++) {
- size_t total = sizeof(block) + sizeof(kCodeSetLocal0) * i;
- byte* code = reinterpret_cast<byte*>(malloc(total));
- memcpy(code, block, sizeof(block));
- code[1] = static_cast<byte>(i);
- for (size_t j = 0; j < i; j++) {
- memcpy(code + sizeof(block) + j * sizeof(kCodeSetLocal0), kCodeSetLocal0,
- sizeof(kCodeSetLocal0));
- }
- Verify(kSuccess, sigs.v_i(), code, code + total);
- free(code);
- }
-}
-
-TEST_F(AstDecoderTest, BlockN_off_end) {
- for (byte i = 2; i < 10; i++) {
- byte code[] = {kExprBlock, i, kExprNop};
- EXPECT_FAILURE(sigs.v_v(), code);
- }
-}
-
-TEST_F(AstDecoderTest, Block1_break) {
- static const byte code[] = {kExprBlock, 1, kExprBr, 0, kExprNop};
- EXPECT_VERIFIES(sigs.v_v(), code);
-}
-
-TEST_F(AstDecoderTest, Block2_break) {
- static const byte code[] = {kExprBlock, 2, kExprNop, kExprBr, 0, kExprNop};
- EXPECT_VERIFIES(sigs.v_v(), code);
+TEST_F(AstDecoderTest, Block1_f) {
+ byte code[] = {B1(WASM_F32(0))};
+ EXPECT_FAILURE(sigs.i_i(), code);
+ EXPECT_VERIFIES(sigs.f_ff(), code);
+ EXPECT_FAILURE(sigs.d_dd(), code);
+ EXPECT_FAILURE(sigs.l_ll(), code);
}
TEST_F(AstDecoderTest, Block1_continue) {
- static const byte code[] = {kExprBlock, 1, kExprBr, 1, kExprNop};
- EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BR(0)));
+ EXPECT_FAILURE_INLINE(sigs.v_v(), B1(WASM_BR(1)));
+ EXPECT_FAILURE_INLINE(sigs.v_v(), B1(WASM_BR(2)));
+ EXPECT_FAILURE_INLINE(sigs.v_v(), B1(WASM_BR(3)));
}
-TEST_F(AstDecoderTest, Block2_continue) {
- static const byte code[] = {kExprBlock, 2, kExprNop, kExprBr, 1, kExprNop};
- EXPECT_FAILURE(sigs.v_v(), code);
+TEST_F(AstDecoderTest, Block1_br) {
+ EXPECT_FAILURE_INLINE(sigs.v_v(), kExprBlock, kExprBr, ARITY_1, DEPTH_0,
+ kExprEnd);
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), kExprBlock, kExprBr, ARITY_0, DEPTH_0,
+ kExprEnd);
}
-TEST_F(AstDecoderTest, ExprBlock0) {
- static const byte code[] = {kExprBlock, 0};
- EXPECT_VERIFIES(sigs.v_v(), code);
+TEST_F(AstDecoderTest, Block2_br) {
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_NOP, WASM_BR(0)));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_BR(0), WASM_NOP));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_BR(0), WASM_BR(0)));
}
-TEST_F(AstDecoderTest, ExprBlock1a) {
- static const byte code[] = {kExprBlock, 1, kExprI8Const, 0};
+TEST_F(AstDecoderTest, Block2) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ B2(WASM_NOP, WASM_SET_LOCAL(0, WASM_ZERO)));
+ EXPECT_FAILURE_INLINE(sigs.i_i(), B2(WASM_SET_LOCAL(0, WASM_ZERO), WASM_NOP));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_SET_LOCAL(0, WASM_ZERO)));
+}
+
+TEST_F(AstDecoderTest, Block2b) {
+ byte code[] = {B2(WASM_SET_LOCAL(0, WASM_ZERO), WASM_ZERO)};
EXPECT_VERIFIES(sigs.i_i(), code);
-}
-
-TEST_F(AstDecoderTest, ExprBlock1b) {
- static const byte code[] = {kExprBlock, 1, kExprI8Const, 0};
+ EXPECT_FAILURE(sigs.v_v(), code);
EXPECT_FAILURE(sigs.f_ff(), code);
}
-TEST_F(AstDecoderTest, ExprBlock1c) {
- static const byte code[] = {kExprBlock, 1, kExprF32Const, 0, 0, 0, 0};
+TEST_F(AstDecoderTest, Block2_fallthru) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_SET_LOCAL(0, WASM_ZERO)),
+ WASM_I8(23));
+}
+
+TEST_F(AstDecoderTest, Block3) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.i_i(), B3(WASM_SET_LOCAL(0, WASM_ZERO), WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_I8(11)));
+}
+
+TEST_F(AstDecoderTest, Block5) {
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), B1(WASM_GET_LOCAL(0)));
+
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), B2(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), B3(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+ EXPECT_VERIFIES_INLINE(sigs.v_i(),
+ WASM_BLOCK(4, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0),
+ WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(),
+ WASM_BLOCK(5, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0),
+ WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+}
+
+TEST_F(AstDecoderTest, BlockF32) {
+ static const byte code[] = {kExprBlock, kExprF32Const, 0, 0, 0, 0, kExprEnd};
EXPECT_VERIFIES(sigs.f_ff(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+ EXPECT_FAILURE(sigs.d_dd(), code);
+}
+
+TEST_F(AstDecoderTest, BlockN_off_end) {
+ byte code[] = {kExprBlock, kExprNop, kExprNop, kExprNop, kExprNop, kExprEnd};
+ EXPECT_VERIFIES(sigs.v_v(), code);
+ for (size_t i = 1; i < arraysize(code); i++) {
+ Verify(kError, sigs.v_v(), code, code + i);
+ }
+}
+
+TEST_F(AstDecoderTest, Block2_continue) {
+ static const byte code[] = {kExprBlock, kExprBr, ARITY_0,
+ DEPTH_1, kExprNop, kExprEnd};
+ EXPECT_FAILURE(sigs.v_v(), code);
+}
+
+TEST_F(AstDecoderTest, NestedBlock_return) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), B1(B1(WASM_RETURN1(WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, BlockBinop) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_I32_AND(B1(WASM_I8(1)), WASM_I8(2)));
+}
+
+TEST_F(AstDecoderTest, BlockBrBinop) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ WASM_I32_AND(B1(WASM_BRV(0, WASM_I8(1))), WASM_I8(2)));
+}
+
+TEST_F(AstDecoderTest, If_empty1) {
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty2) {
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, kExprElse, kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty3) {
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, WASM_ZERO, kExprElse,
+ kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty4) {
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, kExprElse, WASM_ZERO,
+ kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty_stack) {
+ byte code[] = {kExprIf};
+ EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_incomplete1) {
+ byte code[] = {kExprI8Const, 0, kExprIf};
+ EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_incomplete2) {
+ byte code[] = {kExprI8Const, 0, kExprIf, kExprNop};
+ EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_else_else) {
+ byte code[] = {kExprI8Const, 0, kExprIf, kExprElse, kExprElse, kExprEnd};
+ EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
}
TEST_F(AstDecoderTest, IfEmpty) {
- static const byte code[] = {kExprIf, kExprGetLocal, 0, kExprNop};
- EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), kExprGetLocal, 0, kExprIf, kExprEnd);
}
TEST_F(AstDecoderTest, IfSet) {
- static const byte code[] = {kExprIfElse, kExprGetLocal, 0, kExprSetLocal,
- 0, kExprI8Const, 0, kExprNop};
- EXPECT_VERIFIES(sigs.v_i(), code);
-}
-
-TEST_F(AstDecoderTest, IfBlock1) {
- static const byte code[] = {kExprIfElse, kExprGetLocal, 0, kExprBlock,
- 1, kExprSetLocal, 0, kExprI8Const,
- 0, kExprNop};
- EXPECT_VERIFIES(sigs.v_i(), code);
-}
-
-TEST_F(AstDecoderTest, IfBlock2) {
- static const byte code[] = {kExprIf, kExprGetLocal, 0, kExprBlock,
- 2, kExprSetLocal, 0, kExprI8Const,
- 0, kExprSetLocal, 0, kExprI8Const,
- 0};
- EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO)));
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO), WASM_NOP));
}
TEST_F(AstDecoderTest, IfElseEmpty) {
- static const byte code[] = {kExprIfElse, kExprGetLocal, 0, kExprNop,
- kExprNop};
- EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_GET_LOCAL(0), kExprIf, kExprElse,
+ kExprEnd);
+ EXPECT_VERIFIES_INLINE(sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_NOP));
}
-TEST_F(AstDecoderTest, IfElseSet) {
- static const byte code[] = {kExprIfElse,
- kExprGetLocal,
- 0, // --
- kExprSetLocal,
- 0,
- kExprI8Const,
- 0, // --
- kExprSetLocal,
- 0,
- kExprI8Const,
- 1}; // --
- EXPECT_VERIFIES(sigs.v_i(), code);
+TEST_F(AstDecoderTest, IfElseUnreachable1) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.i_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_UNREACHABLE, WASM_GET_LOCAL(0)));
+ EXPECT_VERIFIES_INLINE(
+ sigs.i_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE));
}
-TEST_F(AstDecoderTest, IfElseUnreachable) {
- static const byte code[] = {kExprIfElse, kExprI8Const, 0,
- kExprUnreachable, kExprGetLocal, 0};
+TEST_F(AstDecoderTest, IfElseUnreachable2) {
+ static const byte code[] = {
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_UNREACHABLE, WASM_GET_LOCAL(0))};
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalType types[] = {kAstI32, kLocalTypes[i]};
@@ -509,66 +600,136 @@
}
}
+TEST_F(AstDecoderTest, IfBreak) {
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_BR(0)));
+ EXPECT_FAILURE_INLINE(sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_BR(1)));
+}
+
+TEST_F(AstDecoderTest, IfElseBreak) {
+ EXPECT_VERIFIES_INLINE(sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_BR(0)));
+ EXPECT_FAILURE_INLINE(sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_BR(1)));
+}
+
+TEST_F(AstDecoderTest, Block_else) {
+ byte code[] = {kExprI8Const, 0, kExprBlock, kExprElse, kExprEnd};
+ EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, IfNop) {
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfNopElseNop) {
+ EXPECT_VERIFIES_INLINE(sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, If_end_end) {
+ static const byte code[] = {kExprGetLocal, 0, kExprIf, kExprEnd, kExprEnd};
+ EXPECT_FAILURE(sigs.v_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_falloff) {
+ static const byte code[] = {kExprGetLocal, 0, kExprIf};
+ EXPECT_FAILURE(sigs.v_i(), code);
+}
+
+TEST_F(AstDecoderTest, IfElse_falloff) {
+ static const byte code[] = {kExprGetLocal, 0, kExprIf, kExprNop, kExprElse};
+ EXPECT_FAILURE(sigs.v_i(), code);
+}
+
+TEST_F(AstDecoderTest, IfElseNop) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO), WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfBlock1) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0),
+ B1(WASM_SET_LOCAL(0, WASM_ZERO)), WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfBlock1b) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), B1(WASM_SET_LOCAL(0, WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, IfBlock2a) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_SET_LOCAL(0, WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, IfBlock2b) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_SET_LOCAL(0, WASM_ZERO)),
+ WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfElseSet) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_SET_LOCAL(0, WASM_I8(1))));
+}
+
TEST_F(AstDecoderTest, Loop0) {
- static const byte code[] = {kExprLoop, 0};
+ static const byte code[] = {kExprLoop, kExprEnd};
EXPECT_VERIFIES(sigs.v_v(), code);
}
TEST_F(AstDecoderTest, Loop1) {
- static const byte code[] = {kExprLoop, 1, kExprSetLocal, 0, kExprI8Const, 0};
+ static const byte code[] = {WASM_LOOP(1, WASM_SET_LOCAL(0, WASM_ZERO))};
EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_FAILURE(sigs.v_v(), code);
+ EXPECT_FAILURE(sigs.f_ff(), code);
}
TEST_F(AstDecoderTest, Loop2) {
- static const byte code[] = {kExprLoop, 2, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprSetLocal, 0, kExprI8Const, 0}; // --
- EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_LOOP(2, WASM_SET_LOCAL(0, WASM_ZERO),
+ WASM_SET_LOCAL(0, WASM_ZERO)));
}
TEST_F(AstDecoderTest, Loop1_continue) {
- static const byte code[] = {kExprLoop, 1, kExprBr, 0, kExprNop};
- EXPECT_VERIFIES(sigs.v_v(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BR(0)));
}
TEST_F(AstDecoderTest, Loop1_break) {
- static const byte code[] = {kExprLoop, 1, kExprBr, 1, kExprNop};
- EXPECT_VERIFIES(sigs.v_v(), code);
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BR(1)));
}
TEST_F(AstDecoderTest, Loop2_continue) {
- static const byte code[] = {kExprLoop, 2, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprBr, 0, kExprNop}; // --
- EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_LOOP(2, WASM_SET_LOCAL(0, WASM_ZERO), WASM_BR(0)));
}
TEST_F(AstDecoderTest, Loop2_break) {
- static const byte code[] = {kExprLoop, 2, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprBr, 1, kExprNop}; // --
- EXPECT_VERIFIES(sigs.v_i(), code);
+ EXPECT_VERIFIES_INLINE(
+ sigs.v_i(), WASM_LOOP(2, WASM_SET_LOCAL(0, WASM_ZERO), WASM_BR(1)));
}
TEST_F(AstDecoderTest, ExprLoop0) {
- static const byte code[] = {kExprLoop, 0};
+ static const byte code[] = {kExprLoop, kExprEnd};
EXPECT_VERIFIES(sigs.v_v(), code);
}
TEST_F(AstDecoderTest, ExprLoop1a) {
- static const byte code[] = {kExprLoop, 1, kExprBr, 0, kExprI8Const, 0};
- EXPECT_VERIFIES(sigs.i_i(), code);
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_LOOP(1, WASM_BRV(0, WASM_ZERO)));
}
TEST_F(AstDecoderTest, ExprLoop1b) {
- static const byte code[] = {kExprLoop, 1, kExprBr, 0, kExprI8Const, 0};
- EXPECT_VERIFIES(sigs.i_i(), code);
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_LOOP(1, WASM_BRV(1, WASM_ZERO)));
+ EXPECT_FAILURE_INLINE(sigs.f_ff(), WASM_LOOP(1, WASM_BRV(1, WASM_ZERO)));
}
TEST_F(AstDecoderTest, ExprLoop2_unreachable) {
- static const byte code[] = {kExprLoop, 2, kExprBr, 0,
- kExprI8Const, 0, kExprNop};
- EXPECT_VERIFIES(sigs.i_i(), code);
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_LOOP(2, WASM_BR(0), WASM_NOP));
}
TEST_F(AstDecoderTest, ReturnVoid1) {
@@ -579,7 +740,7 @@
}
TEST_F(AstDecoderTest, ReturnVoid2) {
- static const byte code[] = {kExprBlock, 1, kExprBr, 0, kExprNop};
+ static const byte code[] = {kExprBlock, kExprBr, ARITY_0, DEPTH_0, kExprEnd};
EXPECT_VERIFIES(sigs.v_v(), code);
EXPECT_FAILURE(sigs.i_i(), code);
EXPECT_FAILURE(sigs.i_f(), code);
@@ -598,67 +759,85 @@
TEST_F(AstDecoderTest, Unreachable1) {
EXPECT_VERIFIES_INLINE(sigs.v_v(), kExprUnreachable);
EXPECT_VERIFIES_INLINE(sigs.v_v(), kExprUnreachable, kExprUnreachable);
- EXPECT_VERIFIES_INLINE(sigs.v_v(),
- WASM_BLOCK(2, WASM_UNREACHABLE, WASM_ZERO));
- EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(2, WASM_BR(0), WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_UNREACHABLE, WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_BR(0), WASM_ZERO));
EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(2, WASM_UNREACHABLE, WASM_ZERO));
EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(2, WASM_BR(0), WASM_ZERO));
}
-TEST_F(AstDecoderTest, Codeiness) {
- VERIFY(kExprLoop, 2, // --
- kExprSetLocal, 0, kExprI8Const, 0, // --
- kExprBr, 0, kExprNop); // --
+TEST_F(AstDecoderTest, Unreachable_binop) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_I32_AND(WASM_ZERO, WASM_UNREACHABLE));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_I32_AND(WASM_UNREACHABLE, WASM_ZERO));
}
-TEST_F(AstDecoderTest, ExprIf1) {
- VERIFY(kExprIf, kExprGetLocal, 0, kExprI8Const, 0, kExprI8Const, 1);
- VERIFY(kExprIf, kExprGetLocal, 0, kExprGetLocal, 0, kExprGetLocal, 0);
- VERIFY(kExprIf, kExprGetLocal, 0, kExprI32Add, kExprGetLocal, 0,
- kExprGetLocal, 0, kExprI8Const, 1);
+TEST_F(AstDecoderTest, Unreachable_select) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ WASM_SELECT(WASM_UNREACHABLE, WASM_ZERO, WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ WASM_SELECT(WASM_ZERO, WASM_UNREACHABLE, WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ WASM_SELECT(WASM_ZERO, WASM_ZERO, WASM_UNREACHABLE));
}
-TEST_F(AstDecoderTest, ExprIf_off_end) {
- static const byte kCode[] = {kExprIf, kExprGetLocal, 0, kExprGetLocal,
- 0, kExprGetLocal, 0};
- for (size_t len = 1; len < arraysize(kCode); len++) {
+TEST_F(AstDecoderTest, If1) {
+ EXPECT_VERIFIES_INLINE(
+ sigs.i_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(9), WASM_I8(8)));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(9),
+ WASM_GET_LOCAL(0)));
+ EXPECT_VERIFIES_INLINE(
+ sigs.i_i(),
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_I8(8)));
+}
+
+TEST_F(AstDecoderTest, If_off_end) {
+ static const byte kCode[] = {
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0))};
+ for (size_t len = 3; len < arraysize(kCode); len++) {
Verify(kError, sigs.i_i(), kCode, kCode + len);
}
}
-TEST_F(AstDecoderTest, ExprIf_type) {
- {
- // float|double ? 1 : 2
- static const byte kCode[] = {kExprIfElse, kExprGetLocal, 0, kExprI8Const,
- 1, kExprI8Const, 2};
- EXPECT_FAILURE(sigs.i_f(), kCode);
- EXPECT_FAILURE(sigs.i_d(), kCode);
- }
- {
- // 1 ? float|double : 2
- static const byte kCode[] = {kExprIfElse, kExprI8Const, 1, kExprGetLocal,
- 0, kExprI8Const, 2};
- EXPECT_FAILURE(sigs.i_f(), kCode);
- EXPECT_FAILURE(sigs.i_d(), kCode);
- }
- {
- // stmt ? 0 : 1
- static const byte kCode[] = {kExprIfElse, kExprNop, kExprI8Const,
- 0, kExprI8Const, 1};
- EXPECT_FAILURE(sigs.i_i(), kCode);
- }
- {
- // 0 ? stmt : 1
- static const byte kCode[] = {kExprIfElse, kExprI8Const, 0,
- kExprNop, kExprI8Const, 1};
- EXPECT_FAILURE(sigs.i_i(), kCode);
- }
- {
- // 0 ? 1 : stmt
- static const byte kCode[] = {kExprIfElse, kExprI8Const, 0, kExprI8Const, 1,
- 0, kExprBlock};
- EXPECT_FAILURE(sigs.i_i(), kCode);
- }
+TEST_F(AstDecoderTest, If_type1) {
+ // float|double ? 1 : 2
+ static const byte kCode[] = {
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(0), WASM_I8(2))};
+ EXPECT_VERIFIES(sigs.i_i(), kCode);
+ EXPECT_FAILURE(sigs.i_f(), kCode);
+ EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type2) {
+ // 1 ? float|double : 2
+ static const byte kCode[] = {
+ WASM_IF_ELSE(WASM_I8(1), WASM_GET_LOCAL(0), WASM_I8(1))};
+ EXPECT_VERIFIES(sigs.i_i(), kCode);
+ EXPECT_FAILURE(sigs.i_f(), kCode);
+ EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type3) {
+ // stmt ? 0 : 1
+ static const byte kCode[] = {WASM_IF_ELSE(WASM_NOP, WASM_I8(0), WASM_I8(1))};
+ EXPECT_FAILURE(sigs.i_i(), kCode);
+ EXPECT_FAILURE(sigs.i_f(), kCode);
+ EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type4) {
+ // 0 ? stmt : 1
+ static const byte kCode[] = {
+ WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_I8(1))};
+ EXPECT_FAILURE(sigs.i_i(), kCode);
+ EXPECT_FAILURE(sigs.i_f(), kCode);
+ EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type5) {
+ // 0 ? 1 : stmt
+ static const byte kCode[] = {WASM_IF_ELSE(WASM_ZERO, WASM_I8(1), WASM_NOP)};
+ EXPECT_FAILURE(sigs.i_i(), kCode);
+ EXPECT_FAILURE(sigs.i_f(), kCode);
+ EXPECT_FAILURE(sigs.i_d(), kCode);
}
TEST_F(AstDecoderTest, Int64Local_param) {
@@ -669,8 +848,7 @@
for (byte i = 1; i < 8; i++) {
AddLocals(kAstI64, 1);
for (byte j = 0; j < i; j++) {
- byte code[] = {kExprGetLocal, j};
- EXPECT_VERIFIES(sigs.l_v(), code);
+ EXPECT_VERIFIES_INLINE(sigs.l_v(), WASM_GET_LOCAL(j));
}
}
}
@@ -737,7 +915,7 @@
VERIFY(WASM_IF(WASM_GET_LOCAL(0), WASM_NOP));
VERIFY(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_NOP));
VERIFY(WASM_NOP);
- VERIFY(WASM_BLOCK(1, WASM_NOP));
+ VERIFY(B1(WASM_NOP));
VERIFY(WASM_LOOP(1, WASM_NOP));
VERIFY(WASM_LOOP(1, WASM_BREAK(0)));
VERIFY(WASM_LOOP(1, WASM_CONTINUE(0)));
@@ -760,30 +938,30 @@
}
TEST_F(AstDecoderTest, MacrosVariadic) {
- VERIFY(WASM_BLOCK(2, WASM_NOP, WASM_NOP));
- VERIFY(WASM_BLOCK(3, WASM_NOP, WASM_NOP, WASM_NOP));
+ VERIFY(B2(WASM_NOP, WASM_NOP));
+ VERIFY(B3(WASM_NOP, WASM_NOP, WASM_NOP));
VERIFY(WASM_LOOP(2, WASM_NOP, WASM_NOP));
VERIFY(WASM_LOOP(3, WASM_NOP, WASM_NOP, WASM_NOP));
}
TEST_F(AstDecoderTest, MacrosNestedBlocks) {
- VERIFY(WASM_BLOCK(2, WASM_NOP, WASM_BLOCK(2, WASM_NOP, WASM_NOP)));
- VERIFY(WASM_BLOCK(3, WASM_NOP, // --
- WASM_BLOCK(2, WASM_NOP, WASM_NOP), // --
- WASM_BLOCK(2, WASM_NOP, WASM_NOP))); // --
- VERIFY(WASM_BLOCK(1, WASM_BLOCK(1, WASM_BLOCK(2, WASM_NOP, WASM_NOP))));
+ VERIFY(B2(WASM_NOP, B2(WASM_NOP, WASM_NOP)));
+ VERIFY(B3(WASM_NOP, // --
+ B2(WASM_NOP, WASM_NOP), // --
+ B2(WASM_NOP, WASM_NOP))); // --
+ VERIFY(B1(B1(B2(WASM_NOP, WASM_NOP))));
}
TEST_F(AstDecoderTest, MultipleReturn) {
static LocalType kIntTypes5[] = {kAstI32, kAstI32, kAstI32, kAstI32, kAstI32};
FunctionSig sig_ii_v(2, 0, kIntTypes5);
- EXPECT_VERIFIES_INLINE(&sig_ii_v, WASM_RETURN(WASM_ZERO, WASM_ONE));
- EXPECT_FAILURE_INLINE(&sig_ii_v, WASM_RETURN(WASM_ZERO));
+ EXPECT_VERIFIES_INLINE(&sig_ii_v, WASM_RETURNN(2, WASM_ZERO, WASM_ONE));
+ EXPECT_FAILURE_INLINE(&sig_ii_v, WASM_RETURNN(1, WASM_ZERO));
FunctionSig sig_iii_v(3, 0, kIntTypes5);
EXPECT_VERIFIES_INLINE(&sig_iii_v,
- WASM_RETURN(WASM_ZERO, WASM_ONE, WASM_I8(44)));
- EXPECT_FAILURE_INLINE(&sig_iii_v, WASM_RETURN(WASM_ZERO, WASM_ONE));
+ WASM_RETURNN(3, WASM_ZERO, WASM_ONE, WASM_I8(44)));
+ EXPECT_FAILURE_INLINE(&sig_iii_v, WASM_RETURNN(2, WASM_ZERO, WASM_ONE));
}
TEST_F(AstDecoderTest, MultipleReturn_fallthru) {
@@ -887,78 +1065,57 @@
}
TEST_F(AstDecoderTest, GrowMemory) {
- byte code[] = {kExprGrowMemory, kExprGetLocal, 0};
+ byte code[] = {WASM_UNOP(kExprGrowMemory, WASM_GET_LOCAL(0))};
EXPECT_VERIFIES(sigs.i_i(), code);
EXPECT_FAILURE(sigs.i_d(), code);
}
TEST_F(AstDecoderTest, LoadMemOffset) {
for (int offset = 0; offset < 128; offset += 7) {
- byte code[] = {kExprI32LoadMem, ZERO_ALIGNMENT, static_cast<byte>(offset),
- kExprI8Const, 0};
+ byte code[] = {kExprI8Const, 0, kExprI32LoadMem, ZERO_ALIGNMENT,
+ static_cast<byte>(offset)};
EXPECT_VERIFIES(sigs.i_i(), code);
}
}
TEST_F(AstDecoderTest, StoreMemOffset) {
for (int offset = 0; offset < 128; offset += 7) {
- byte code[] = {
- kExprI32StoreMem, 0, static_cast<byte>(offset), kExprI8Const, 0,
- kExprI8Const, 0};
+ byte code[] = {WASM_STORE_MEM_OFFSET(MachineType::Int32(), offset,
+ WASM_ZERO, WASM_ZERO)};
EXPECT_VERIFIES(sigs.i_i(), code);
}
}
-TEST_F(AstDecoderTest, LoadMemOffset_varint) {
- byte code1[] = {kExprI32LoadMem, ZERO_ALIGNMENT, ZERO_OFFSET, kExprI8Const,
- 0};
- byte code2[] = {kExprI32LoadMem, ZERO_ALIGNMENT, 0x80, 1, kExprI8Const, 0};
- byte code3[] = {
- kExprI32LoadMem, ZERO_ALIGNMENT, 0x81, 0x82, 5, kExprI8Const, 0};
- byte code4[] = {
- kExprI32LoadMem, ZERO_ALIGNMENT, 0x83, 0x84, 0x85, 7, kExprI8Const, 0};
+#define BYTE0(x) ((x)&0x7F)
+#define BYTE1(x) ((x >> 7) & 0x7F)
+#define BYTE2(x) ((x >> 14) & 0x7F)
+#define BYTE3(x) ((x >> 21) & 0x7F)
- EXPECT_VERIFIES(sigs.i_i(), code1);
- EXPECT_VERIFIES(sigs.i_i(), code2);
- EXPECT_VERIFIES(sigs.i_i(), code3);
- EXPECT_VERIFIES(sigs.i_i(), code4);
+#define VARINT1(x) BYTE0(x)
+#define VARINT2(x) BYTE0(x) | 0x80, BYTE1(x)
+#define VARINT3(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x)
+#define VARINT4(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x) | 0x80, BYTE3(x)
+
+TEST_F(AstDecoderTest, LoadMemOffset_varint) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+ VARINT1(0x45));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+ VARINT2(0x3999));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+ VARINT3(0x344445));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+ VARINT4(0x36666667));
}
TEST_F(AstDecoderTest, StoreMemOffset_varint) {
- byte code1[] = {
- kExprI32StoreMem, ZERO_ALIGNMENT, 0, kExprI8Const, 0, kExprI8Const, 0};
- byte code2[] = {kExprI32StoreMem,
- ZERO_ALIGNMENT,
- 0x80,
- 1,
- kExprI8Const,
- 0,
- kExprI8Const,
- 0};
- byte code3[] = {kExprI32StoreMem,
- ZERO_ALIGNMENT,
- 0x81,
- 0x82,
- 5,
- kExprI8Const,
- 0,
- kExprI8Const,
- 0};
- byte code4[] = {kExprI32StoreMem,
- ZERO_ALIGNMENT,
- 0x83,
- 0x84,
- 0x85,
- 7,
- kExprI8Const,
- 0,
- kExprI8Const,
- 0};
-
- EXPECT_VERIFIES(sigs.i_i(), code1);
- EXPECT_VERIFIES(sigs.i_i(), code2);
- EXPECT_VERIFIES(sigs.i_i(), code3);
- EXPECT_VERIFIES(sigs.i_i(), code4);
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+ ZERO_ALIGNMENT, VARINT1(0x33));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+ ZERO_ALIGNMENT, VARINT2(0x1111));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+ ZERO_ALIGNMENT, VARINT3(0x222222));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+ ZERO_ALIGNMENT, VARINT4(0x44444444));
}
TEST_F(AstDecoderTest, AllLoadMemCombinations) {
@@ -966,9 +1123,7 @@
LocalType local_type = kLocalTypes[i];
for (size_t j = 0; j < arraysize(machineTypes); j++) {
MachineType mem_type = machineTypes[j];
- byte code[] = {
- static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(mem_type, false)),
- ZERO_ALIGNMENT, ZERO_OFFSET, kExprI8Const, 0};
+ byte code[] = {WASM_LOAD_MEM(mem_type, WASM_ZERO)};
FunctionSig sig(1, 0, &local_type);
if (local_type == WasmOpcodes::LocalTypeFor(mem_type)) {
EXPECT_VERIFIES(&sig, code);
@@ -984,14 +1139,7 @@
LocalType local_type = kLocalTypes[i];
for (size_t j = 0; j < arraysize(machineTypes); j++) {
MachineType mem_type = machineTypes[j];
- byte code[] = {
- static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(mem_type, true)),
- ZERO_ALIGNMENT,
- ZERO_OFFSET,
- kExprI8Const,
- 0,
- kExprGetLocal,
- 0};
+ byte code[] = {WASM_STORE_MEM(mem_type, WASM_ZERO, WASM_GET_LOCAL(0))};
FunctionSig sig(0, 1, &local_type);
if (local_type == WasmOpcodes::LocalTypeFor(mem_type)) {
EXPECT_VERIFIES(&sig, code);
@@ -1002,7 +1150,6 @@
}
}
-
namespace {
// A helper for tests that require a module environment for functions and
// globals.
@@ -1024,12 +1171,24 @@
return static_cast<byte>(mod.signatures.size() - 1);
}
byte AddFunction(FunctionSig* sig) {
- mod.functions.push_back({sig, 0, 0, 0, 0, 0, 0, 0, false, false});
+ mod.functions.push_back({sig, // sig
+ 0, // func_index
+ 0, // sig_index
+ 0, // name_offset
+ 0, // name_length
+ 0, // code_start_offset
+ 0, // code_end_offset
+ false}); // exported
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});
+ mod.import_table.push_back({sig, // sig
+ 0, // sig_index
+ 0, // module_name_offset
+ 0, // module_name_length
+ 0, // function_name_offset
+ 0}); // function_name_length
CHECK(mod.import_table.size() <= 127);
return static_cast<byte>(mod.import_table.size() - 1);
}
@@ -1048,9 +1207,9 @@
module_env.AddFunction(sigs.i_i());
module_env.AddFunction(sigs.i_ii());
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION(0));
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_I8(27)));
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION(2, WASM_I8(37), WASM_I8(77)));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION0(0));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_I8(27)));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION2(2, WASM_I8(37), WASM_I8(77)));
}
TEST_F(AstDecoderTest, CallsWithTooFewArguments) {
@@ -1063,35 +1222,8 @@
module_env.AddFunction(sigs.f_ff());
EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION0(0));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_ZERO));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(2, WASM_GET_LOCAL(0)));
-}
-
-TEST_F(AstDecoderTest, CallsWithSpilloverArgs) {
- static LocalType a_i_ff[] = {kAstI32, kAstF32, kAstF32};
- FunctionSig sig_i_ff(1, 2, a_i_ff);
-
- TestModuleEnv module_env;
- module = &module_env;
-
- module_env.AddFunction(&sig_i_ff);
-
- EXPECT_VERIFIES_INLINE(sigs.i_i(),
- WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1)));
-
- EXPECT_VERIFIES_INLINE(sigs.i_ff(),
- WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1)));
-
- EXPECT_FAILURE_INLINE(sigs.f_ff(),
- WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1)));
-
- EXPECT_FAILURE_INLINE(
- sigs.i_i(),
- WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1), WASM_F32(0.2)));
-
- EXPECT_VERIFIES_INLINE(
- sigs.f_ff(),
- WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1), WASM_F32(11)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_ZERO));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(2, WASM_GET_LOCAL(0)));
}
TEST_F(AstDecoderTest, CallsWithMismatchedSigs2) {
@@ -1101,9 +1233,9 @@
module_env.AddFunction(sigs.i_i());
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(17)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_F32(17.1)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_F64(17.1)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_I64V_1(17)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_F32(17.1)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_F64(17.1)));
}
TEST_F(AstDecoderTest, CallsWithMismatchedSigs3) {
@@ -1113,15 +1245,15 @@
module_env.AddFunction(sigs.i_f());
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_I8(17)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(27)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_F64(37.2)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_I8(17)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_I64V_1(27)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_F64(37.2)));
module_env.AddFunction(sigs.i_d());
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_I8(16)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_I64V_1(16)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_F32(17.6)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_I8(16)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_I64V_1(16)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_F32(17.6)));
}
TEST_F(AstDecoderTest, SimpleIndirectCalls) {
@@ -1134,9 +1266,9 @@
byte f2 = module_env.AddSignature(sigs.i_ii());
EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO));
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_I8(22)));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I8(22)));
EXPECT_VERIFIES_INLINE(
- sig, WASM_CALL_INDIRECT(f2, WASM_ZERO, WASM_I8(32), WASM_I8(72)));
+ sig, WASM_CALL_INDIRECT2(f2, WASM_ZERO, WASM_I8(32), WASM_I8(72)));
}
TEST_F(AstDecoderTest, IndirectCallsOutOfBounds) {
@@ -1148,11 +1280,11 @@
module_env.AddSignature(sigs.i_v());
EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT0(0, WASM_ZERO));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_I8(22)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I8(22)));
module_env.AddSignature(sigs.i_i());
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_I8(27)));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I8(27)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(2, WASM_ZERO, WASM_I8(27)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(2, WASM_ZERO, WASM_I8(27)));
}
TEST_F(AstDecoderTest, IndirectCallsWithMismatchedSigs3) {
@@ -1162,10 +1294,11 @@
byte f0 = module_env.AddFunction(sigs.i_f());
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f0, WASM_ZERO, WASM_I8(17)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I8(17)));
EXPECT_FAILURE_INLINE(sig,
- WASM_CALL_INDIRECT(f0, WASM_ZERO, WASM_I64V_1(27)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f0, WASM_ZERO, WASM_F64(37.2)));
+ WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I64V_1(27)));
+ EXPECT_FAILURE_INLINE(sig,
+ WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_F64(37.2)));
EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT0(f0, WASM_I8(17)));
EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT0(f0, WASM_I64V_1(27)));
@@ -1173,10 +1306,11 @@
byte f1 = module_env.AddFunction(sigs.i_d());
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_I8(16)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I8(16)));
EXPECT_FAILURE_INLINE(sig,
- WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_I64V_1(16)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_F32(17.6)));
+ WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I64V_1(16)));
+ EXPECT_FAILURE_INLINE(sig,
+ WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_F32(17.6)));
}
TEST_F(AstDecoderTest, SimpleImportCalls) {
@@ -1189,8 +1323,8 @@
byte f2 = module_env.AddImport(sigs.i_ii());
EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT0(f0));
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_I8(22)));
- EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT(f2, WASM_I8(32), WASM_I8(72)));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_I8(22)));
+ EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT2(f2, WASM_I8(32), WASM_I8(72)));
}
TEST_F(AstDecoderTest, ImportCallsWithMismatchedSigs3) {
@@ -1201,16 +1335,16 @@
byte f0 = module_env.AddImport(sigs.i_f());
EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT0(f0));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f0, WASM_I8(17)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f0, WASM_I64V_1(27)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f0, WASM_F64(37.2)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f0, WASM_I8(17)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f0, WASM_I64V_1(27)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f0, WASM_F64(37.2)));
byte f1 = module_env.AddImport(sigs.i_d());
EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT0(f1));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_I8(16)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_I64V_1(16)));
- EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_F32(17.6)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_I8(16)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_I64V_1(16)));
+ EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_F32(17.6)));
}
TEST_F(AstDecoderTest, Int32Globals) {
@@ -1334,11 +1468,29 @@
}
}
+TEST_F(AstDecoderTest, BreakEnd) {
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ B1(WASM_I32_ADD(WASM_BRV(0, WASM_ZERO), WASM_ZERO)));
+ EXPECT_VERIFIES_INLINE(sigs.i_i(),
+ B1(WASM_I32_ADD(WASM_ZERO, WASM_BRV(0, WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, BreakIfBinop) {
+ EXPECT_FAILURE_INLINE(
+ sigs.i_i(),
+ WASM_BLOCK(
+ 1, WASM_I32_ADD(WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO), WASM_ZERO)));
+ EXPECT_FAILURE_INLINE(
+ sigs.i_i(),
+ WASM_BLOCK(
+ 1, WASM_I32_ADD(WASM_ZERO, WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO))));
+}
+
TEST_F(AstDecoderTest, BreakNesting1) {
for (int i = 0; i < 5; i++) {
// (block[2] (loop[2] (if (get p) break[N]) (set p 1)) p)
byte code[] = {WASM_BLOCK(
- 2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(i, WASM_ZERO)),
+ 2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(i + 1, WASM_ZERO)),
WASM_SET_LOCAL(0, WASM_I8(1))),
WASM_GET_LOCAL(0))};
if (i < 3) {
@@ -1353,8 +1505,8 @@
AddLocals(kAstI32, 1);
for (int i = 0; i < 5; i++) {
// (block[2] (loop[2] (if 0 break[N]) (set p 1)) (return p)) (11)
- byte code[] = {WASM_BLOCK(1, WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BREAK(i)),
- WASM_SET_LOCAL(0, WASM_I8(1)))),
+ byte code[] = {B1(WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BREAK(i + 1)),
+ WASM_SET_LOCAL(0, WASM_I8(1)))),
WASM_I8(11)};
if (i < 2) {
EXPECT_VERIFIES(sigs.v_v(), code);
@@ -1367,8 +1519,8 @@
TEST_F(AstDecoderTest, BreakNesting3) {
for (int i = 0; i < 5; i++) {
// (block[1] (loop[1] (block[1] (if 0 break[N])
- byte code[] = {WASM_BLOCK(
- 1, WASM_LOOP(1, WASM_BLOCK(1, WASM_IF(WASM_ZERO, WASM_BREAK(i)))))};
+ byte code[] = {
+ WASM_BLOCK(1, WASM_LOOP(1, B1(WASM_IF(WASM_ZERO, WASM_BREAK(i + 1)))))};
if (i < 3) {
EXPECT_VERIFIES(sigs.v_v(), code);
} else {
@@ -1378,41 +1530,42 @@
}
TEST_F(AstDecoderTest, BreaksWithMultipleTypes) {
- EXPECT_FAILURE_INLINE(
- sigs.i_i(),
- WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)), WASM_F32(7.7)));
+ EXPECT_FAILURE_INLINE(sigs.i_i(),
+ B2(WASM_BRV_IF_ZERO(0, WASM_I8(7)), WASM_F32(7.7)));
- EXPECT_FAILURE_INLINE(sigs.i_i(),
- WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)),
- WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
- EXPECT_FAILURE_INLINE(sigs.i_i(),
- 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(sigs.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))));
+ EXPECT_FAILURE_INLINE(sigs.i_i(), B2(WASM_BRV_IF_ZERO(0, WASM_I8(7)),
+ WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
+ EXPECT_FAILURE_INLINE(sigs.i_i(), B3(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(sigs.i_i(), B3(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))));
}
TEST_F(AstDecoderTest, BreakNesting_6_levels) {
for (int mask = 0; mask < 64; mask++) {
for (int i = 0; i < 14; i++) {
byte code[] = {
- kExprBlock, 1, // --
- kExprBlock, 1, // --
- kExprBlock, 1, // --
- kExprBlock, 1, // --
- kExprBlock, 1, // --
- kExprBlock, 1, // --
- kExprBr, static_cast<byte>(i),
- kExprNop // --
+ kExprBlock, // --
+ kExprBlock, // --
+ kExprBlock, // --
+ kExprBlock, // --
+ kExprBlock, // --
+ kExprBlock, // --
+ kExprBr, ARITY_0, static_cast<byte>(i), // --
+ kExprEnd, // --
+ kExprEnd, // --
+ kExprEnd, // --
+ kExprEnd, // --
+ kExprEnd, // --
+ kExprEnd // --
};
int depth = 6;
for (int l = 0; l < 6; l++) {
if (mask & (1 << l)) {
- code[l * 2] = kExprLoop;
+ code[l] = kExprLoop;
depth++;
}
}
@@ -1432,29 +1585,27 @@
FunctionSig* sig = sigarray[i];
// unify X and X => OK
EXPECT_VERIFIES_INLINE(
- sig, WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
- WASM_GET_LOCAL(0)));
+ sig, B2(WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
+ WASM_GET_LOCAL(0)));
}
// unify i32 and f32 => fail
EXPECT_FAILURE_INLINE(
sigs.i_i(),
- WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_ZERO)), WASM_F32(1.2)));
+ B2(WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_ZERO)), WASM_F32(1.2)));
// unify f64 and f64 => OK
EXPECT_VERIFIES_INLINE(
sigs.d_dd(),
- WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
- WASM_F64(1.2)));
+ B2(WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))), WASM_F64(1.2)));
}
TEST_F(AstDecoderTest, 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_ZERO(0, WASM_GET_LOCAL(0))),
- WASM_GET_LOCAL(1))};
+ byte code2[] = {B2(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++) {
@@ -1479,14 +1630,12 @@
LocalType storage[] = {kAstI32, kAstI32, type};
FunctionSig sig(1, 2, storage);
- byte code1[] = {
- WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(which))),
- WASM_GET_LOCAL(which ^ 1))};
+ byte code1[] = {B2(WASM_IF(WASM_ZERO, WASM_BRV(1, WASM_GET_LOCAL(which))),
+ WASM_GET_LOCAL(which ^ 1))};
byte code2[] = {
- WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BRV(1, WASM_GET_LOCAL(which))),
+ WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BRV(2, WASM_GET_LOCAL(which))),
WASM_GET_LOCAL(which ^ 1))};
-
if (type == kAstI32) {
EXPECT_VERIFIES(&sig, code1);
EXPECT_VERIFIES(&sig, code2);
@@ -1499,8 +1648,7 @@
}
TEST_F(AstDecoderTest, ExprBrIf_cond_type) {
- byte code[] = {
- WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))};
+ byte code[] = {B1(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]};
@@ -1516,9 +1664,8 @@
}
TEST_F(AstDecoderTest, ExprBrIf_val_type) {
- byte code[] = {
- WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)),
- WASM_GET_LOCAL(0))};
+ byte code[] = {B2(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++) {
for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
LocalType types[] = {kLocalTypes[i], kLocalTypes[i], kLocalTypes[j],
@@ -1541,8 +1688,8 @@
LocalType storage[] = {kAstI32, kAstI32, type};
FunctionSig sig(1, 2, storage);
- byte code1[] = {WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(which)),
- WASM_GET_LOCAL(which ^ 1))};
+ byte code1[] = {B2(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))};
@@ -1558,31 +1705,29 @@
}
TEST_F(AstDecoderTest, BrTable0) {
- static byte code[] = {kExprBrTable, 0, 0};
+ static byte code[] = {kExprNop, kExprBrTable, 0, 0};
EXPECT_FAILURE(sigs.v_v(), code);
}
TEST_F(AstDecoderTest, BrTable0b) {
- static byte code[] = {kExprBrTable, 0, 0, kExprI32Const, 11};
+ static byte code[] = {kExprNop, kExprI32Const, 11, kExprBrTable, 0, 0};
EXPECT_FAILURE(sigs.v_v(), code);
EXPECT_FAILURE(sigs.i_i(), code);
}
TEST_F(AstDecoderTest, BrTable0c) {
- static byte code[] = {kExprBrTable, 0, 1, 0, 0, kExprI32Const, 11};
+ static byte code[] = {kExprNop, kExprI32Const, 11, kExprBrTable, 0, 1, 0, 0};
EXPECT_FAILURE(sigs.v_v(), code);
EXPECT_FAILURE(sigs.i_i(), code);
}
TEST_F(AstDecoderTest, BrTable1a) {
- static byte code[] = {
- WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 0, BR_TARGET(0)))};
+ static byte code[] = {B1(WASM_BR_TABLE(WASM_I8(67), 0, BR_TARGET(0)))};
EXPECT_VERIFIES(sigs.v_v(), code);
}
TEST_F(AstDecoderTest, BrTable1b) {
- static byte code[] = {
- WASM_BLOCK(1, WASM_BR_TABLE(WASM_ZERO, 0, BR_TARGET(0)))};
+ static byte code[] = {B1(WASM_BR_TABLE(WASM_ZERO, 0, BR_TARGET(0)))};
EXPECT_VERIFIES(sigs.v_v(), code);
EXPECT_FAILURE(sigs.i_i(), code);
EXPECT_FAILURE(sigs.f_ff(), code);
@@ -1591,7 +1736,7 @@
TEST_F(AstDecoderTest, BrTable2a) {
static byte code[] = {
- WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(0)))};
+ B1(WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(0)))};
EXPECT_VERIFIES(sigs.v_v(), code);
}
@@ -1603,8 +1748,7 @@
}
TEST_F(AstDecoderTest, BrTable_off_end) {
- static byte code[] = {
- WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))};
+ static byte code[] = {B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))};
for (size_t len = 1; len < sizeof(code); len++) {
Verify(kError, sigs.i_i(), code, code + len);
}
@@ -1612,8 +1756,7 @@
TEST_F(AstDecoderTest, BrTable_invalid_br1) {
for (int depth = 0; depth < 4; depth++) {
- byte code[] = {
- WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))};
+ byte code[] = {B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))};
if (depth == 0) {
EXPECT_VERIFIES(sigs.v_i(), code);
} else {
@@ -1635,11 +1778,10 @@
}
TEST_F(AstDecoderTest, ExprBreakNesting1) {
- EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(1, WASM_BRV(0, WASM_ZERO)));
- EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(1, WASM_BR(0)));
- EXPECT_VERIFIES_INLINE(sigs.v_v(),
- WASM_BLOCK(1, WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO)));
- EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(1, WASM_BR_IF(0, WASM_ZERO)));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BRV(0, WASM_ZERO)));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BR(0)));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO)));
+ EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BR_IF(0, WASM_ZERO)));
EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BRV(0, WASM_ZERO)));
EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BR(0)));
@@ -1714,7 +1856,6 @@
WASM_SELECT(WASM_F32(9.9), WASM_GET_LOCAL(0), WASM_I64V_1(0)));
}
-
class WasmOpcodeLengthTest : public TestWithZone {
public:
WasmOpcodeLengthTest() : TestWithZone() {}
@@ -1734,16 +1875,16 @@
TEST_F(WasmOpcodeLengthTest, Statements) {
EXPECT_LENGTH(1, kExprNop);
- EXPECT_LENGTH(2, kExprBlock);
- EXPECT_LENGTH(2, kExprLoop);
+ EXPECT_LENGTH(1, kExprBlock);
+ EXPECT_LENGTH(1, kExprLoop);
EXPECT_LENGTH(1, kExprIf);
- EXPECT_LENGTH(1, kExprIfElse);
+ EXPECT_LENGTH(1, kExprElse);
+ EXPECT_LENGTH(1, kExprEnd);
EXPECT_LENGTH(1, kExprSelect);
- EXPECT_LENGTH(2, kExprBr);
- EXPECT_LENGTH(2, kExprBrIf);
+ EXPECT_LENGTH(3, kExprBr);
+ EXPECT_LENGTH(3, kExprBrIf);
}
-
TEST_F(WasmOpcodeLengthTest, MiscExpressions) {
EXPECT_LENGTH(2, kExprI8Const);
EXPECT_LENGTH(5, kExprF32Const);
@@ -1752,15 +1893,14 @@
EXPECT_LENGTH(2, kExprSetLocal);
EXPECT_LENGTH(2, kExprLoadGlobal);
EXPECT_LENGTH(2, kExprStoreGlobal);
- EXPECT_LENGTH(2, kExprCallFunction);
- EXPECT_LENGTH(2, kExprCallImport);
- EXPECT_LENGTH(2, kExprCallIndirect);
+ EXPECT_LENGTH(3, kExprCallFunction);
+ EXPECT_LENGTH(3, kExprCallImport);
+ EXPECT_LENGTH(3, kExprCallIndirect);
EXPECT_LENGTH(1, kExprIf);
- EXPECT_LENGTH(1, kExprIfElse);
- EXPECT_LENGTH(2, kExprBlock);
- EXPECT_LENGTH(2, kExprLoop);
- EXPECT_LENGTH(2, kExprBr);
- EXPECT_LENGTH(2, kExprBrIf);
+ EXPECT_LENGTH(1, kExprBlock);
+ EXPECT_LENGTH(1, kExprLoop);
+ EXPECT_LENGTH(3, kExprBr);
+ EXPECT_LENGTH(3, kExprBrIf);
}
TEST_F(WasmOpcodeLengthTest, I32Const) {
@@ -1818,13 +1958,11 @@
EXPECT_LENGTH(3, kExprF64StoreMem);
}
-
TEST_F(WasmOpcodeLengthTest, MiscMemExpressions) {
EXPECT_LENGTH(1, kExprMemorySize);
EXPECT_LENGTH(1, kExprGrowMemory);
}
-
TEST_F(WasmOpcodeLengthTest, SimpleExpressions) {
EXPECT_LENGTH(1, kExprI32Add);
EXPECT_LENGTH(1, kExprI32Sub);
@@ -1946,54 +2084,49 @@
EXPECT_LENGTH(1, kExprI64ReinterpretF64);
}
-
class WasmOpcodeArityTest : public TestWithZone {
public:
WasmOpcodeArityTest() : TestWithZone() {}
- TestModuleEnv module;
- TestSignatures sigs;
};
-#define EXPECT_ARITY(expected, ...) \
- { \
- static const byte code[] = {__VA_ARGS__}; \
- EXPECT_EQ(expected, OpcodeArity(&module, sig, code, code + sizeof(code))); \
+#define EXPECT_ARITY(expected, ...) \
+ { \
+ static const byte code[] = {__VA_ARGS__}; \
+ EXPECT_EQ(expected, OpcodeArity(code, code + sizeof(code))); \
}
TEST_F(WasmOpcodeArityTest, Control) {
- FunctionSig* sig = sigs.v_v();
EXPECT_ARITY(0, kExprNop);
EXPECT_ARITY(0, kExprBlock, 0);
- EXPECT_ARITY(1, kExprBlock, 1);
- EXPECT_ARITY(2, kExprBlock, 2);
- EXPECT_ARITY(5, kExprBlock, 5);
- EXPECT_ARITY(10, kExprBlock, 10);
+ EXPECT_ARITY(0, kExprBlock, 1);
+ EXPECT_ARITY(0, kExprBlock, 2);
+ EXPECT_ARITY(0, kExprBlock, 5);
+ EXPECT_ARITY(0, kExprBlock, 10);
EXPECT_ARITY(0, kExprLoop, 0);
- EXPECT_ARITY(1, kExprLoop, 1);
- EXPECT_ARITY(2, kExprLoop, 2);
- EXPECT_ARITY(7, kExprLoop, 7);
- EXPECT_ARITY(11, kExprLoop, 11);
+ EXPECT_ARITY(0, kExprLoop, 1);
+ EXPECT_ARITY(0, kExprLoop, 2);
+ EXPECT_ARITY(0, kExprLoop, 7);
+ EXPECT_ARITY(0, kExprLoop, 11);
- EXPECT_ARITY(2, kExprIf);
- EXPECT_ARITY(3, kExprIfElse);
EXPECT_ARITY(3, kExprSelect);
- EXPECT_ARITY(1, kExprBr);
- EXPECT_ARITY(2, kExprBrIf);
+ EXPECT_ARITY(0, kExprBr);
+ EXPECT_ARITY(1, kExprBrIf);
+ EXPECT_ARITY(1, kExprBrTable);
+
+ EXPECT_ARITY(1, kExprBr, ARITY_1);
+ EXPECT_ARITY(2, kExprBrIf, ARITY_1);
+ EXPECT_ARITY(2, kExprBrTable, ARITY_1);
{
- sig = sigs.v_v();
- EXPECT_ARITY(0, kExprReturn);
- sig = sigs.i_i();
- EXPECT_ARITY(1, kExprReturn);
+ EXPECT_ARITY(0, kExprReturn, ARITY_0);
+ EXPECT_ARITY(1, kExprReturn, ARITY_1);
}
}
-
TEST_F(WasmOpcodeArityTest, Misc) {
- FunctionSig* sig = sigs.v_v();
EXPECT_ARITY(0, kExprI8Const);
EXPECT_ARITY(0, kExprI32Const);
EXPECT_ARITY(0, kExprF32Const);
@@ -2005,41 +2138,37 @@
EXPECT_ARITY(1, kExprStoreGlobal);
}
-
TEST_F(WasmOpcodeArityTest, Calls) {
- module.AddFunction(sigs.i_ii());
- module.AddFunction(sigs.i_i());
-
- module.AddSignature(sigs.f_ff());
- module.AddSignature(sigs.i_d());
-
- module.AddImport(sigs.f_ff());
- module.AddImport(sigs.i_d());
-
{
- FunctionSig* sig = sigs.i_ii();
+ EXPECT_ARITY(2, kExprCallFunction, 2, 0);
+ EXPECT_ARITY(2, kExprCallImport, 2, 0);
+ EXPECT_ARITY(3, kExprCallIndirect, 2, 0);
- EXPECT_ARITY(2, kExprCallFunction, 0);
- EXPECT_ARITY(2, kExprCallImport, 0);
- EXPECT_ARITY(3, kExprCallIndirect, 0);
- EXPECT_ARITY(1, kExprBr);
- EXPECT_ARITY(2, kExprBrIf);
+ EXPECT_ARITY(1, kExprBr, ARITY_1);
+ EXPECT_ARITY(2, kExprBrIf, ARITY_1);
+ EXPECT_ARITY(2, kExprBrTable, ARITY_1);
+
+ EXPECT_ARITY(0, kExprBr, ARITY_0);
+ EXPECT_ARITY(1, kExprBrIf, ARITY_0);
+ EXPECT_ARITY(1, kExprBrTable, ARITY_0);
}
{
- FunctionSig* sig = sigs.v_v();
+ EXPECT_ARITY(1, kExprCallFunction, ARITY_1, 1);
+ EXPECT_ARITY(1, kExprCallImport, ARITY_1, 1);
+ EXPECT_ARITY(2, kExprCallIndirect, ARITY_1, 1);
- EXPECT_ARITY(1, kExprCallFunction, 1);
- EXPECT_ARITY(1, kExprCallImport, 1);
- EXPECT_ARITY(2, kExprCallIndirect, 1);
- EXPECT_ARITY(1, kExprBr);
- EXPECT_ARITY(2, kExprBrIf);
+ EXPECT_ARITY(1, kExprBr, ARITY_1);
+ EXPECT_ARITY(2, kExprBrIf, ARITY_1);
+ EXPECT_ARITY(2, kExprBrTable, ARITY_1);
+
+ EXPECT_ARITY(0, kExprBr, ARITY_0);
+ EXPECT_ARITY(1, kExprBrIf, ARITY_0);
+ EXPECT_ARITY(1, kExprBrTable, ARITY_0);
}
}
-
TEST_F(WasmOpcodeArityTest, LoadsAndStores) {
- FunctionSig* sig = sigs.v_v();
EXPECT_ARITY(1, kExprI32LoadMem8S);
EXPECT_ARITY(1, kExprI32LoadMem8U);
EXPECT_ARITY(1, kExprI32LoadMem16S);
@@ -2067,16 +2196,12 @@
EXPECT_ARITY(2, kExprF64StoreMem);
}
-
TEST_F(WasmOpcodeArityTest, MiscMemExpressions) {
- FunctionSig* sig = sigs.v_v();
EXPECT_ARITY(0, kExprMemorySize);
EXPECT_ARITY(1, kExprGrowMemory);
}
-
TEST_F(WasmOpcodeArityTest, SimpleExpressions) {
- FunctionSig* sig = sigs.v_v();
EXPECT_ARITY(2, kExprI32Add);
EXPECT_ARITY(2, kExprI32Sub);
EXPECT_ARITY(2, kExprI32Mul);
@@ -2246,7 +2371,7 @@
LocalTypeMap map = Expand(decls);
EXPECT_EQ(1, map.size());
- EXPECT_EQ(type, map.at(0));
+ EXPECT_EQ(type, map[0]);
}
}
@@ -2297,7 +2422,7 @@
TEST_F(LocalDeclDecoderTest, UseEncoder) {
const byte* data = nullptr;
const byte* end = nullptr;
- LocalDeclEncoder local_decls;
+ LocalDeclEncoder local_decls(zone());
local_decls.AddLocals(5, kAstF32);
local_decls.AddLocals(1337, kAstI32);
diff --git a/test/unittests/wasm/encoder-unittest.cc b/test/unittests/wasm/encoder-unittest.cc
index 740c054..47885e6 100644
--- a/test/unittests/wasm/encoder-unittest.cc
+++ b/test/unittests/wasm/encoder-unittest.cc
@@ -9,6 +9,8 @@
#include "src/wasm/ast-decoder.h"
#include "src/wasm/encoder.h"
+#include "test/cctest/wasm/test-signatures.h"
+
namespace v8 {
namespace internal {
namespace wasm {
@@ -17,202 +19,10 @@
protected:
void AddLocal(WasmFunctionBuilder* f, LocalType type) {
uint16_t index = f->AddLocal(type);
- const std::vector<uint8_t>& out_index = UnsignedLEB128From(index);
- std::vector<uint8_t> code;
- code.push_back(kExprGetLocal);
- for (size_t i = 0; i < out_index.size(); i++) {
- code.push_back(out_index.at(i));
- }
- uint32_t local_indices[] = {1};
- f->EmitCode(&code[0], static_cast<uint32_t>(code.size()), local_indices, 1);
- }
-
- void CheckReadValue(uint8_t* leb_value, uint32_t expected_result,
- int expected_length,
- ReadUnsignedLEB128ErrorCode expected_error_code) {
- int length;
- uint32_t result;
- ReadUnsignedLEB128ErrorCode error_code =
- ReadUnsignedLEB128Operand(leb_value, leb_value + 5, &length, &result);
- CHECK_EQ(error_code, expected_error_code);
- if (error_code == 0) {
- CHECK_EQ(result, expected_result);
- CHECK_EQ(length, expected_length);
- }
- }
-
- void CheckWriteValue(uint32_t input, int length, uint8_t* vals) {
- const std::vector<uint8_t> result = UnsignedLEB128From(input);
- CHECK_EQ(result.size(), length);
- for (int i = 0; i < length; i++) {
- CHECK_EQ(result.at(i), vals[i]);
- }
+ f->EmitGetLocal(index);
}
};
-
-TEST_F(EncoderTest, Function_Builder_Variable_Indexing) {
- base::AccountingAllocator allocator;
- Zone zone(&allocator);
- WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
- uint16_t f_index = builder->AddFunction();
- WasmFunctionBuilder* function = builder->FunctionAt(f_index);
- uint16_t local_f32 = function->AddLocal(kAstF32);
- uint16_t param_float32 = function->AddParam(kAstF32);
- 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_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_i32);
- function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_i32_2);
- function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_i64);
- function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_f32);
- function->EmitCode(code, sizeof(code), local_indices, 1);
- code[1] = static_cast<uint8_t>(local_f64);
- function->EmitCode(code, sizeof(code), local_indices, 1);
-
- WasmFunctionEncoder* f = function->Build(&zone, builder);
- ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
- byte* buffer = &buffer_vector[0];
- byte* header = buffer;
- byte* body = buffer + f->HeaderSize();
- f->Serialize(buffer, &header, &body);
-}
-
-
-TEST_F(EncoderTest, Function_Builder_Indexing_Variable_Width) {
- base::AccountingAllocator allocator;
- Zone zone(&allocator);
- WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
- uint16_t f_index = builder->AddFunction();
- WasmFunctionBuilder* function = builder->FunctionAt(f_index);
- for (size_t i = 0; i < 128; i++) {
- AddLocal(function, kAstF32);
- }
- AddLocal(function, kAstI32);
-
- WasmFunctionEncoder* f = function->Build(&zone, builder);
- ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
- byte* buffer = &buffer_vector[0];
- byte* header = buffer;
- byte* body = buffer + f->HeaderSize();
- f->Serialize(buffer, &header, &body);
- body = buffer + f->HeaderSize();
-}
-
-TEST_F(EncoderTest, Function_Builder_Block_Variable_Width) {
- base::AccountingAllocator allocator;
- Zone zone(&allocator);
- WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
- uint16_t f_index = builder->AddFunction();
- WasmFunctionBuilder* function = builder->FunctionAt(f_index);
- function->EmitWithVarInt(kExprBlock, 200);
- for (int i = 0; i < 200; ++i) {
- function->Emit(kExprNop);
- }
-
- WasmFunctionEncoder* f = function->Build(&zone, builder);
- CHECK_EQ(f->BodySize(), 204);
-}
-
-TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate) {
- base::AccountingAllocator allocator;
- Zone zone(&allocator);
- WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
- uint16_t f_index = builder->AddFunction();
- WasmFunctionBuilder* function = builder->FunctionAt(f_index);
- function->Emit(kExprLoop);
- uint32_t offset = function->EmitEditableVarIntImmediate();
- for (int i = 0; i < 200; ++i) {
- function->Emit(kExprNop);
- }
- function->EditVarIntImmediate(offset, 200);
-
- WasmFunctionEncoder* f = function->Build(&zone, builder);
- CHECK_EQ(f->BodySize(), 204);
-}
-
-TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate_Locals) {
- base::AccountingAllocator allocator;
- Zone zone(&allocator);
- WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
- uint16_t f_index = builder->AddFunction();
- WasmFunctionBuilder* function = builder->FunctionAt(f_index);
- function->Emit(kExprBlock);
- uint32_t offset = function->EmitEditableVarIntImmediate();
- for (int i = 0; i < 200; ++i) {
- AddLocal(function, kAstI32);
- }
- function->EditVarIntImmediate(offset, 200);
-
- WasmFunctionEncoder* f = function->Build(&zone, builder);
- ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
- byte* buffer = &buffer_vector[0];
- byte* header = buffer;
- byte* body = buffer + f->HeaderSize();
- f->Serialize(buffer, &header, &body);
- body = buffer + f->HeaderSize();
-
- CHECK_EQ(f->BodySize(), 479);
- const uint8_t varint200_low = (200 & 0x7f) | 0x80;
- const uint8_t varint200_high = (200 >> 7) & 0x7f;
- offset = 0;
- CHECK_EQ(body[offset++], 1); // Local decl count.
- CHECK_EQ(body[offset++], varint200_low);
- CHECK_EQ(body[offset++], varint200_high);
- CHECK_EQ(body[offset++], kLocalI32);
- CHECK_EQ(body[offset++], kExprBlock);
- CHECK_EQ(body[offset++], varint200_low);
- CHECK_EQ(body[offset++], varint200_high);
- // GetLocal with one-byte indices.
- for (int i = 0; i <= 127; ++i) {
- CHECK_EQ(body[offset++], kExprGetLocal);
- CHECK_EQ(body[offset++], i);
- }
- // GetLocal with two-byte indices.
- for (int i = 128; i < 200; ++i) {
- CHECK_EQ(body[offset++], kExprGetLocal);
- CHECK_EQ(body[offset++], (i & 0x7f) | 0x80);
- CHECK_EQ(body[offset++], (i >> 7) & 0x7f);
- }
- CHECK_EQ(offset, 479);
-}
-
-TEST_F(EncoderTest, LEB_Functions) {
- byte leb_value[5] = {0, 0, 0, 0, 0};
- CheckReadValue(leb_value, 0, 1, kNoError);
- CheckWriteValue(0, 1, leb_value);
- leb_value[0] = 23;
- CheckReadValue(leb_value, 23, 1, kNoError);
- CheckWriteValue(23, 1, leb_value);
- leb_value[0] = 0x80;
- leb_value[1] = 0x01;
- CheckReadValue(leb_value, 128, 2, kNoError);
- CheckWriteValue(128, 2, leb_value);
- leb_value[0] = 0x80;
- leb_value[1] = 0x80;
- leb_value[2] = 0x80;
- leb_value[3] = 0x80;
- leb_value[4] = 0x01;
- CheckReadValue(leb_value, 0x10000000, 5, kNoError);
- CheckWriteValue(0x10000000, 5, leb_value);
- leb_value[0] = 0x80;
- leb_value[1] = 0x80;
- leb_value[2] = 0x80;
- leb_value[3] = 0x80;
- leb_value[4] = 0x80;
- CheckReadValue(leb_value, -1, -1, kInvalidLEB128);
-}
} // namespace wasm
} // namespace internal
} // namespace v8
diff --git a/test/unittests/wasm/leb-helper-unittest.cc b/test/unittests/wasm/leb-helper-unittest.cc
new file mode 100644
index 0000000..ed9f0a3
--- /dev/null
+++ b/test/unittests/wasm/leb-helper-unittest.cc
@@ -0,0 +1,190 @@
+// 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/wasm/decoder.h"
+#include "src/wasm/leb-helper.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class LEBHelperTest : public TestWithZone {};
+
+TEST_F(LEBHelperTest, sizeof_u32v) {
+ EXPECT_EQ(1, LEBHelper::sizeof_u32v(0));
+ EXPECT_EQ(1, LEBHelper::sizeof_u32v(1));
+ EXPECT_EQ(1, LEBHelper::sizeof_u32v(3));
+
+ for (uint32_t i = 4; i < 128; i++) {
+ EXPECT_EQ(1, LEBHelper::sizeof_u32v(i));
+ }
+
+ for (uint32_t i = (1 << 7); i < (1 << 9); i++) {
+ EXPECT_EQ(2, LEBHelper::sizeof_u32v(i));
+ }
+
+ for (uint32_t i = (1 << 14); i < (1 << 16); i += 33) {
+ EXPECT_EQ(3, LEBHelper::sizeof_u32v(i));
+ }
+
+ for (uint32_t i = (1 << 21); i < (1 << 24); i += 33999) {
+ EXPECT_EQ(4, LEBHelper::sizeof_u32v(i));
+ }
+
+ for (uint32_t i = (1 << 28); i < (1 << 31); i += 33997779) {
+ EXPECT_EQ(5, LEBHelper::sizeof_u32v(i));
+ }
+
+ EXPECT_EQ(5, LEBHelper::sizeof_u32v(0xFFFFFFFF));
+}
+
+TEST_F(LEBHelperTest, sizeof_i32v) {
+ EXPECT_EQ(1, LEBHelper::sizeof_i32v(0));
+ EXPECT_EQ(1, LEBHelper::sizeof_i32v(1));
+ EXPECT_EQ(1, LEBHelper::sizeof_i32v(3));
+
+ for (int32_t i = 0; i < (1 << 6); i++) {
+ EXPECT_EQ(1, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = (1 << 6); i < (1 << 8); i++) {
+ EXPECT_EQ(2, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = (1 << 13); i < (1 << 15); i += 31) {
+ EXPECT_EQ(3, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = (1 << 20); i < (1 << 22); i += 31991) {
+ EXPECT_EQ(4, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = (1 << 27); i < (1 << 29); i += 3199893) {
+ EXPECT_EQ(5, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = -(1 << 6); i <= 0; i++) {
+ EXPECT_EQ(1, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = -(1 << 13); i < -(1 << 6); i++) {
+ EXPECT_EQ(2, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = -(1 << 20); i < -(1 << 18); i += 11) {
+ EXPECT_EQ(3, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = -(1 << 27); i < -(1 << 25); i += 11999) {
+ EXPECT_EQ(4, LEBHelper::sizeof_i32v(i));
+ }
+
+ for (int32_t i = -(1 << 30); i < -(1 << 28); i += 1199999) {
+ EXPECT_EQ(5, LEBHelper::sizeof_i32v(i));
+ }
+}
+
+#define DECLARE_ENCODE_DECODE_CHECKER(ctype, name) \
+ static void CheckEncodeDecode_##name(ctype val) { \
+ static const int kSize = 16; \
+ static byte buffer[kSize]; \
+ byte *ptr = buffer; \
+ LEBHelper::write_##name(&ptr, val); \
+ EXPECT_EQ(LEBHelper::sizeof_##name(val), \
+ static_cast<size_t>(ptr - buffer)); \
+ Decoder decoder(buffer, buffer + kSize); \
+ int length = 0; \
+ ctype result = decoder.checked_read_##name(buffer, 0, &length); \
+ EXPECT_EQ(val, result); \
+ EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \
+ }
+
+DECLARE_ENCODE_DECODE_CHECKER(int32_t, i32v)
+DECLARE_ENCODE_DECODE_CHECKER(uint32_t, u32v)
+DECLARE_ENCODE_DECODE_CHECKER(int64_t, i64v)
+DECLARE_ENCODE_DECODE_CHECKER(uint64_t, u64v)
+
+TEST_F(LEBHelperTest, WriteAndDecode_u32v) {
+ CheckEncodeDecode_u32v(0);
+ CheckEncodeDecode_u32v(1);
+ CheckEncodeDecode_u32v(5);
+ CheckEncodeDecode_u32v(99);
+ CheckEncodeDecode_u32v(298);
+ CheckEncodeDecode_u32v(87348723);
+ CheckEncodeDecode_u32v(77777);
+
+ for (uint32_t val = 0x3a; val != 0; val = val << 1) {
+ CheckEncodeDecode_u32v(val);
+ }
+}
+
+TEST_F(LEBHelperTest, WriteAndDecode_i32v) {
+ CheckEncodeDecode_i32v(0);
+ CheckEncodeDecode_i32v(1);
+ CheckEncodeDecode_i32v(5);
+ CheckEncodeDecode_i32v(99);
+ CheckEncodeDecode_i32v(298);
+ CheckEncodeDecode_i32v(87348723);
+ CheckEncodeDecode_i32v(77777);
+
+ CheckEncodeDecode_i32v(-2);
+ CheckEncodeDecode_i32v(-4);
+ CheckEncodeDecode_i32v(-59);
+ CheckEncodeDecode_i32v(-288);
+ CheckEncodeDecode_i32v(-12608);
+ CheckEncodeDecode_i32v(-87328723);
+ CheckEncodeDecode_i32v(-77377);
+
+ for (uint32_t val = 0x3a; val != 0; val = val << 1) {
+ CheckEncodeDecode_i32v(bit_cast<int32_t>(val));
+ }
+
+ for (uint32_t val = 0xFFFFFF3B; val != 0; val = val << 1) {
+ CheckEncodeDecode_i32v(bit_cast<int32_t>(val));
+ }
+}
+
+TEST_F(LEBHelperTest, WriteAndDecode_u64v) {
+ CheckEncodeDecode_u64v(0);
+ CheckEncodeDecode_u64v(1);
+ CheckEncodeDecode_u64v(5);
+ CheckEncodeDecode_u64v(99);
+ CheckEncodeDecode_u64v(298);
+ CheckEncodeDecode_u64v(87348723);
+ CheckEncodeDecode_u64v(77777);
+
+ for (uint64_t val = 0x3a; val != 0; val = val << 1) {
+ CheckEncodeDecode_u64v(val);
+ }
+}
+
+TEST_F(LEBHelperTest, WriteAndDecode_i64v) {
+ CheckEncodeDecode_i64v(0);
+ CheckEncodeDecode_i64v(1);
+ CheckEncodeDecode_i64v(5);
+ CheckEncodeDecode_i64v(99);
+ CheckEncodeDecode_i64v(298);
+ CheckEncodeDecode_i64v(87348723);
+ CheckEncodeDecode_i64v(77777);
+
+ CheckEncodeDecode_i64v(-2);
+ CheckEncodeDecode_i64v(-4);
+ CheckEncodeDecode_i64v(-59);
+ CheckEncodeDecode_i64v(-288);
+ CheckEncodeDecode_i64v(-87648723);
+ CheckEncodeDecode_i64v(-77377);
+
+ for (uint64_t val = 0x3a; val != 0; val = val << 1) {
+ CheckEncodeDecode_i64v(bit_cast<int64_t>(val));
+ }
+
+ for (uint64_t val = 0xFFFFFFFFFFFFFF3B; val != 0; val = val << 1) {
+ CheckEncodeDecode_i64v(bit_cast<int64_t>(val));
+ }
+}
+} // namespace wasm
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/wasm/loop-assignment-analysis-unittest.cc b/test/unittests/wasm/loop-assignment-analysis-unittest.cc
index e77c1cf..7d97c50 100644
--- a/test/unittests/wasm/loop-assignment-analysis-unittest.cc
+++ b/test/unittests/wasm/loop-assignment-analysis-unittest.cc
@@ -32,14 +32,12 @@
}
};
-
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++) {
@@ -51,7 +49,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
@@ -63,7 +60,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
@@ -75,7 +71,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
@@ -90,7 +85,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
num_locals = 5;
for (int i = 0; i < 5; i++) {
@@ -104,14 +98,12 @@
}
}
-
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) {
num_locals = 65000;
for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
@@ -133,7 +125,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
num_locals = 3;
byte code[] = {
@@ -147,7 +138,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
num_locals = 5;
byte code[] = {
@@ -164,7 +154,6 @@
}
}
-
TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
num_locals = 6;
const byte kIter = 0;
@@ -184,14 +173,13 @@
WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)),
WASM_GET_LOCAL(kIter))};
- BitVector* assigned = Analyze(code + 2, code + arraysize(code));
+ BitVector* assigned = Analyze(code + 1, 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/test/unittests/wasm/module-decoder-unittest.cc b/test/unittests/wasm/module-decoder-unittest.cc
index 44e7865..7090c1f 100644
--- a/test/unittests/wasm/module-decoder-unittest.cc
+++ b/test/unittests/wasm/module-decoder-unittest.cc
@@ -13,18 +13,34 @@
namespace wasm {
#define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16_LE(0)
-#define EMPTY_FUNCTION_SIZE ((size_t)5)
+#define SIZEOF_EMPTY_FUNCTION ((size_t)5)
#define EMPTY_BODY 0
-#define EMPTY_BODY_SIZE ((size_t)1)
+#define SIZEOF_EMPTY_BODY ((size_t)1)
#define NOP_BODY 2, 0, kExprNop
-#define NOP_BODY_SIZE ((size_t)3)
-#define VOID_VOID_SIG 0, kLocalVoid
-#define VOID_VOID_SIG_SIZE ((size_t)2)
-#define INT_INT_SIG 1, kLocalI32, kLocalI32
-#define INT_INT_SIG_SIZE ((size_t)3)
+#define SIZEOF_NOP_BODY ((size_t)3)
-#define SECTION(NAME, EXTRA_SIZE) \
- U32V_1(WASM_SECTION_##NAME##_SIZE + (EXTRA_SIZE)), WASM_SECTION_##NAME
+#define SIG_ENTRY_i_i SIG_ENTRY_x_x(kLocalI32, kLocalI32)
+
+#define UNKNOWN_EMPTY_SECTION_NAME 1, '\0'
+#define UNKNOWN_SECTION_NAME 4, 'l', 'u', 'l', 'z'
+
+#define SECTION(NAME, EXTRA_SIZE) WASM_SECTION_##NAME, U32V_1(EXTRA_SIZE)
+
+#define SIGNATURES_SECTION(count, ...) \
+ SECTION(SIGNATURES, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
+#define FUNCTION_SIGNATURES_SECTION(count, ...) \
+ SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
+
+#define FOO_STRING 3, 'f', 'o', 'o'
+#define NO_LOCAL_NAMES 0
+
+#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
+#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
+#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
+#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
+
+#define SIGNATURES_SECTION_VOID_VOID \
+ SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v), 1, SIG_ENTRY_v_v
#define EXPECT_VERIFIES(data) \
do { \
@@ -49,6 +65,15 @@
} \
} while (false)
+#define EXPECT_OK(result) \
+ do { \
+ EXPECT_TRUE(result.ok()); \
+ if (!result.ok()) { \
+ if (result.val) delete result.val; \
+ return; \
+ } \
+ } while (false)
+
static size_t SizeOfVarInt(size_t value) {
size_t size = 0;
do {
@@ -66,7 +91,7 @@
{kLocalF32, kAstF32},
{kLocalF64, kAstF64}};
-class WasmModuleVerifyTest : public TestWithZone {
+class WasmModuleVerifyTest : public TestWithIsolateAndZone {
public:
ModuleResult DecodeModule(const byte* module_start, const byte* module_end) {
// Add the WASM magic and version number automatically.
@@ -76,14 +101,14 @@
auto temp = new byte[total];
memcpy(temp, header, sizeof(header));
memcpy(temp + sizeof(header), module_start, size);
- ModuleResult result = DecodeWasmModule(nullptr, zone(), temp, temp + total,
- false, kWasmOrigin);
+ ModuleResult result = DecodeWasmModule(isolate(), zone(), temp,
+ temp + total, false, kWasmOrigin);
delete[] temp;
return result;
}
ModuleResult DecodeModuleNoHeader(const byte* module_start,
const byte* module_end) {
- return DecodeWasmModule(nullptr, zone(), module_start, module_end, false,
+ return DecodeWasmModule(isolate(), zone(), module_start, module_end, false,
kWasmOrigin);
}
};
@@ -115,7 +140,7 @@
TEST_F(WasmModuleVerifyTest, OneGlobal) {
static const byte data[] = {
- SECTION(GLOBALS, 7), // --
+ SECTION(GLOBALS, 5), // --
1,
NAME_LENGTH(1),
'g', // name
@@ -126,7 +151,7 @@
{
// Should decode to exactly one global.
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(1, result.val->globals.size());
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(0, result.val->data_segments.size());
@@ -144,18 +169,16 @@
EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
}
-
TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
static const byte data[] = {
SECTION(GLOBALS, 1), // --
0, // declare 0 globals
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
if (result.val) delete result.val;
}
-
static void AppendUint32v(std::vector<byte>& buffer, uint32_t val) {
while (true) {
uint32_t next = val >> 7;
@@ -170,7 +193,6 @@
}
}
-
TEST_F(WasmModuleVerifyTest, NGlobals) {
static const byte data[] = {
NO_NAME, // name length
@@ -180,9 +202,8 @@
for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) {
std::vector<byte> buffer;
- size_t size =
- WASM_SECTION_GLOBALS_SIZE + SizeOfVarInt(i) + i * sizeof(data);
- const byte globals[] = {U32V_5(size), WASM_SECTION_GLOBALS};
+ size_t size = SizeOfVarInt(i) + i * sizeof(data);
+ const byte globals[] = {WASM_SECTION_GLOBALS, U32V_5(size)};
for (size_t g = 0; g != sizeof(globals); ++g) {
buffer.push_back(globals[g]);
}
@@ -192,7 +213,7 @@
}
ModuleResult result = DecodeModule(&buffer[0], &buffer[0] + buffer.size());
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
if (result.val) delete result.val;
}
}
@@ -221,10 +242,9 @@
EXPECT_FAILURE(data);
}
-
TEST_F(WasmModuleVerifyTest, TwoGlobals) {
static const byte data[] = {
- SECTION(GLOBALS, 13),
+ SECTION(GLOBALS, 7),
2,
NO_NAME, // #0: name length
kMemF32, // memory type
@@ -237,7 +257,7 @@
{
// Should decode to exactly two globals.
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(2, result.val->globals.size());
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(0, result.val->data_segments.size());
@@ -261,39 +281,31 @@
EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
}
-
TEST_F(WasmModuleVerifyTest, OneSignature) {
{
- static const byte data[] = {SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1,
- VOID_VOID_SIG};
+ static const byte data[] = {SIGNATURES_SECTION_VOID_VOID};
EXPECT_VERIFIES(data);
}
{
- static const byte data[] = {SECTION(SIGNATURES, 1 + INT_INT_SIG_SIZE), 1,
- INT_INT_SIG};
+ static const byte data[] = {SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_x_x),
+ 1, SIG_ENTRY_i_i};
EXPECT_VERIFIES(data);
}
}
-
TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
static const byte data[] = {
- SECTION(SIGNATURES, 10),
- 3,
- 0,
- kLocalVoid, // void -> void
- 1,
- kLocalI32,
- kLocalF32, // f32 -> i32
- 2,
- kLocalI32,
- kLocalF64,
- kLocalF64, // (f64,f64) -> i32
+ SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_x_x +
+ SIZEOF_SIG_ENTRY_x_xx), // --
+ 3, // --
+ SIG_ENTRY_v_v, // void -> void
+ SIG_ENTRY_x_x(kLocalI32, kLocalF32), // f32 -> i32
+ SIG_ENTRY_x_xx(kLocalI32, kLocalF64, kLocalF64), // f64,f64 -> i32
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(3, result.val->signatures.size());
if (result.val->signatures.size() == 3) {
EXPECT_EQ(0, result.val->signatures[0]->return_count());
@@ -309,10 +321,9 @@
EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
}
-
TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
static const byte data[] = {
- SECTION(FUNCTIONS, 25), 1,
+ SECTION(OLD_FUNCTIONS, 25), 1,
// func#0 ------------------------------------------------------
SIG_INDEX(0), // signature index
NO_NAME, // name length
@@ -323,7 +334,7 @@
U16_LE(699), // local float32 count
U16_LE(599), // local float64 count
0, // exported
- 1 // external
+ 0 // external
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
@@ -331,24 +342,17 @@
if (result.val) delete result.val;
}
-
TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
- const int kCodeStartOffset = 51;
+ const int kCodeStartOffset = 41;
const int kCodeEndOffset = kCodeStartOffset + 1;
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1,
- // sig#0 -------------------------------------------------------
- VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
// func#0 ------------------------------------------------------
- SECTION(FUNCTIONS, 19), 1,
- kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName,
+ SECTION(OLD_FUNCTIONS, 10), 1, kDeclFunctionExport | kDeclFunctionName,
SIG_INDEX(0), // signature index
NAME_LENGTH(2), 'h', 'i', // name
- U16_LE(1466), // local int32 count
- U16_LE(1355), // local int64 count
- U16_LE(1244), // local float32 count
- U16_LE(1133), // local float64 count
1, 0, // size
kExprNop,
};
@@ -356,7 +360,7 @@
{
// Should decode to exactly one function.
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(0, result.val->globals.size());
EXPECT_EQ(1, result.val->signatures.size());
EXPECT_EQ(1, result.val->functions.size());
@@ -365,18 +369,12 @@
WasmFunction* function = &result.val->functions.back();
- EXPECT_EQ(39, function->name_offset);
+ EXPECT_EQ(37, function->name_offset);
EXPECT_EQ(2, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
- EXPECT_EQ(1466, function->local_i32_count);
- EXPECT_EQ(1355, function->local_i64_count);
- EXPECT_EQ(1244, function->local_f32_count);
- EXPECT_EQ(1133, function->local_f64_count);
-
EXPECT_TRUE(function->exported);
- EXPECT_FALSE(function->external);
if (result.val) delete result.val;
}
@@ -384,46 +382,13 @@
EXPECT_OFF_END_FAILURE(data, 16, sizeof(data));
}
-
-TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
- static const byte data[] = {
- SECTION(SIGNATURES, VOID_VOID_SIG_SIZE), 1,
- // sig#0 -------------------------------------------------------
- VOID_VOID_SIG, SECTION(FUNCTIONS, 6), 1,
- // func#0 ------------------------------------------------------
- kDeclFunctionImport, // no name, no locals, imported
- SIG_INDEX(0),
- };
-
- ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(1, result.val->functions.size());
- WasmFunction* function = &result.val->functions.back();
-
- EXPECT_EQ(0, function->name_length);
- EXPECT_EQ(0, function->code_start_offset);
- EXPECT_EQ(0, function->code_end_offset);
-
- 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);
-
- if (result.val) delete result.val;
-}
-
TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
- static const byte kCodeStartOffset = 40;
+ static const byte kCodeStartOffset = 38;
static const byte kCodeEndOffset = kCodeStartOffset + 1;
static const byte data[] = {
- SECTION(SIGNATURES, 3), 1,
- // sig#0 -------------------------------------------------------
- 0, 0, // void -> void
- SECTION(FUNCTIONS, 7), 1,
+ SIGNATURES_SECTION_VOID_VOID, // --
+ SECTION(OLD_FUNCTIONS, 7), 1,
// func#0 ------------------------------------------------------
0, // no name, no locals
0, 0, // signature index
@@ -432,7 +397,7 @@
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(1, result.val->functions.size());
WasmFunction* function = &result.val->functions.back();
@@ -440,86 +405,38 @@
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
- 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);
if (result.val) delete result.val;
}
-
-TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
- static const byte kCodeStartOffset = 48;
- static const byte kCodeEndOffset = kCodeStartOffset + 1;
-
- static const byte data[] = {
- SECTION(SIGNATURES, 3), 1,
- // sig#0 -------------------------------------------------------
- 0, 0, // void -> void
- SECTION(FUNCTIONS, 15), 1,
- // func#0 ------------------------------------------------------
- kDeclFunctionLocals, 0, 0, // signature index
- 1, 2, // local int32 count
- 3, 4, // local int64 count
- 5, 6, // local float32 count
- 7, 8, // local float64 count
- 1, 0, // body size
- kExprNop // body
- };
-
- ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(1, result.val->functions.size());
- WasmFunction* function = &result.val->functions.back();
-
- EXPECT_EQ(0, function->name_length);
- EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
- EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
-
- 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);
-
- if (result.val) delete result.val;
-}
-
-
TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
- static const byte kCodeStartOffset = 75;
+ static const byte kNameOffset = 49;
+ static const byte kCodeStartOffset = 53;
static const byte kCodeEndOffset = kCodeStartOffset + 3;
- static const byte kDataSegmentSourceOffset = kCodeEndOffset + 20;
+ static const byte kDataSegmentSourceOffset = kCodeEndOffset + 22;
static const byte data[] = {
- SECTION(MEMORY, 3), 28, 28, 1,
// global#0 --------------------------------------------------
- SECTION(GLOBALS, 7), 1,
+ SECTION(GLOBALS, 4), 1,
0, // name length
kMemU8, // memory type
0, // exported
// sig#0 -----------------------------------------------------
- SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void
+ SIGNATURES_SECTION_VOID_VOID,
// func#0 ----------------------------------------------------
- SECTION(FUNCTIONS, 20), 1, kDeclFunctionLocals | kDeclFunctionName, 0,
- 0, // signature index
- 2, 'h', 'i', // name
- 1, 2, // local int32 count
- 3, 4, // local int64 count
- 5, 6, // local float32 count
- 7, 8, // local float64 count
- 3, 0, // body size
- kExprNop, // func#0 body
- kExprNop, // func#0 body
- kExprNop, // func#0 body
+ SECTION(OLD_FUNCTIONS, 12), 1,
+ kDeclFunctionName, // --
+ SIG_INDEX(0), // signature index
+ 2, 'h', 'i', // name
+ 3, 0, // body size
+ kExprNop, // func#0 body
+ kExprNop, // func#0 body
+ kExprNop, // func#0 body
+ // memory section --------------------------------------------
+ SECTION(MEMORY, 3), 28, 28, 1,
// segment#0 -------------------------------------------------
- SECTION(DATA_SEGMENTS, 14), 1,
+ SECTION(DATA_SEGMENTS, 10), 1,
U32V_3(0x8b3ae), // dest addr
U32V_1(5), // source size
0, 1, 2, 3, 4, // data bytes
@@ -529,7 +446,7 @@
{
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(1, result.val->globals.size());
EXPECT_EQ(1, result.val->functions.size());
EXPECT_EQ(1, result.val->data_segments.size());
@@ -543,13 +460,12 @@
WasmFunction* function = &result.val->functions.back();
- EXPECT_EQ(63, function->name_offset);
+ EXPECT_EQ(kNameOffset, function->name_offset);
EXPECT_EQ(2, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
EXPECT_FALSE(function->exported);
- EXPECT_FALSE(function->external);
WasmDataSegment* segment = &result.val->data_segments.back();
@@ -562,9 +478,8 @@
}
}
-
TEST_F(WasmModuleVerifyTest, OneDataSegment) {
- const byte kDataSegmentSourceOffset = 39;
+ const byte kDataSegmentSourceOffset = 30;
const byte data[] = {
SECTION(MEMORY, 3),
28,
@@ -582,7 +497,7 @@
{
EXPECT_VERIFIES(data);
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(0, result.val->globals.size());
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(1, result.val->data_segments.size());
@@ -600,17 +515,16 @@
EXPECT_OFF_END_FAILURE(data, 13, sizeof(data));
}
-
TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
- const byte kDataSegment0SourceOffset = 39;
- const byte kDataSegment1SourceOffset = 39 + 8;
+ const byte kDataSegment0SourceOffset = 30;
+ const byte kDataSegment1SourceOffset = 30 + 8;
const byte data[] = {
SECTION(MEMORY, 3),
28,
28,
1,
- SECTION(DATA_SEGMENTS, 31),
+ SECTION(DATA_SEGMENTS, 23),
2, // segment count
U32V_3(0x7ffee), // #0: dest addr
U32V_1(4), // source size
@@ -634,7 +548,7 @@
{
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(0, result.val->globals.size());
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(2, result.val->data_segments.size());
@@ -670,7 +584,7 @@
mem_pages,
mem_pages,
1,
- SECTION(DATA_SEGMENTS, 14),
+ SECTION(DATA_SEGMENTS, 8),
1,
U32V_3(dest_addr),
U32V_1(source_size),
@@ -687,21 +601,18 @@
}
}
-
-// To make below tests for indirect calls much shorter.
-#define FUNCTION(sig_index, external) kDeclFunctionImport, SIG_INDEX(sig_index)
-
TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
static const byte data[] = {
// sig#0 -------------------------------------------------------
- SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void
+ SIGNATURES_SECTION_VOID_VOID,
// func#0 ------------------------------------------------------
- SECTION(FUNCTIONS, 4), 1, FUNCTION(0, 0),
+ SECTION(OLD_FUNCTIONS, 1 + SIZEOF_EMPTY_FUNCTION), 1, // --
+ EMPTY_FUNCTION(0),
// indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 2), 1, U32V_1(0)};
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
if (result.ok()) {
EXPECT_EQ(1, result.val->signatures.size());
EXPECT_EQ(1, result.val->functions.size());
@@ -711,17 +622,19 @@
if (result.val) delete result.val;
}
-
TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
static const byte data[] = {
// sig#0 -------------------------------------------------------
- SECTION(SIGNATURES, 5), 2, 0, 0, // void -> void
- 0, kLocalI32, // void -> i32
+ SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_v_x),
+ 2, // --
+ SIG_ENTRY_v_v, // void -> void
+ SIG_ENTRY_v_x(kLocalI32), // void -> i32
// func#0 ------------------------------------------------------
- SECTION(FUNCTIONS, 13), 4, FUNCTION(0, 1), // --
- FUNCTION(1, 1), // --
- FUNCTION(0, 1), // --
- FUNCTION(1, 1), // --
+ SECTION(OLD_FUNCTIONS, 1 + 4 * SIZEOF_EMPTY_FUNCTION), 4, // --
+ EMPTY_FUNCTION(0), // --
+ EMPTY_FUNCTION(1), // --
+ EMPTY_FUNCTION(0), // --
+ EMPTY_FUNCTION(1), // --
// indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 9), 8,
U32V_1(0), // --
@@ -735,7 +648,7 @@
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
if (result.ok()) {
EXPECT_EQ(2, result.val->signatures.size());
EXPECT_EQ(4, result.val->functions.size());
@@ -747,11 +660,10 @@
if (result.val) delete result.val;
}
-
TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
static const byte data[] = {
// sig#0 -------------------------------------------------------
- SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void
+ SIGNATURES_SECTION_VOID_VOID,
// indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 3), 1, 0, 0,
};
@@ -759,13 +671,13 @@
EXPECT_FAILURE(data);
}
-
TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
static const byte data[] = {
// sig#0 -------------------------------------------------------
- SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void
+ SIGNATURES_SECTION_VOID_VOID,
// functions ---------------------------------------------------
- SECTION(FUNCTIONS, 4), 1, FUNCTION(0, 1),
+ SECTION(OLD_FUNCTIONS, 1 + SIZEOF_EMPTY_FUNCTION), 1, // --
+ EMPTY_FUNCTION(0),
// indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 3), 1, 1, 0,
};
@@ -773,12 +685,10 @@
EXPECT_FAILURE(data);
}
-
class WasmSignatureDecodeTest : public TestWithZone {};
-
TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
- static const byte data[] = {0, 0};
+ static const byte data[] = {SIG_ENTRY_v_v};
base::AccountingAllocator allocator;
Zone zone(&allocator);
FunctionSig* sig =
@@ -789,11 +699,10 @@
EXPECT_EQ(0, sig->return_count());
}
-
TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalTypePair ret_type = kLocalTypes[i];
- const byte data[] = {0, ret_type.code};
+ const byte data[] = {SIG_ENTRY_x(ret_type.code)};
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
@@ -804,11 +713,10 @@
}
}
-
TEST_F(WasmSignatureDecodeTest, Ok_v_t) {
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalTypePair param_type = kLocalTypes[i];
- const byte data[] = {1, 0, param_type.code};
+ const byte data[] = {SIG_ENTRY_v_x(param_type.code)};
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
@@ -819,15 +727,12 @@
}
}
-
TEST_F(WasmSignatureDecodeTest, Ok_t_t) {
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalTypePair ret_type = kLocalTypes[i];
for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
LocalTypePair param_type = kLocalTypes[j];
- const byte data[] = {1, // param count
- ret_type.code, // ret
- param_type.code}; // param
+ const byte data[] = {SIG_ENTRY_x_x(ret_type.code, param_type.code)};
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
@@ -840,16 +745,13 @@
}
}
-
TEST_F(WasmSignatureDecodeTest, Ok_i_tt) {
for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalTypePair p0_type = kLocalTypes[i];
for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
LocalTypePair p1_type = kLocalTypes[j];
- const byte data[] = {2, // param count
- kLocalI32, // ret
- p0_type.code, // p0
- p1_type.code}; // p1
+ const byte data[] = {
+ SIG_ENTRY_x_xx(kLocalI32, p0_type.code, p1_type.code)};
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
@@ -862,7 +764,6 @@
}
}
-
TEST_F(WasmSignatureDecodeTest, Fail_off_end) {
byte data[256];
for (int p = 0; p <= 255; p = p + 1 + p * 3) {
@@ -877,11 +778,10 @@
}
}
-
TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
byte kInvalidType = 76;
- for (int i = 1; i < 3; i++) {
- byte data[] = {2, kLocalI32, kLocalI32, kLocalI32};
+ for (size_t i = 0; i < SIZEOF_SIG_ENTRY_x_xx; i++) {
+ byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)};
data[i] = kInvalidType;
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
@@ -889,46 +789,56 @@
}
}
-
-TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type) {
- static const int kParamCount = 3;
- for (int i = 0; i < kParamCount; i++) {
- byte data[] = {kParamCount, kLocalI32, kLocalI32, kLocalI32, kLocalI32};
- data[i + 2] = kLocalVoid;
- FunctionSig* sig =
- DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
- EXPECT_EQ(nullptr, sig);
- }
+TEST_F(WasmSignatureDecodeTest, Fail_invalid_ret_type1) {
+ static const byte data[] = {SIG_ENTRY_x_x(kLocalVoid, kLocalI32)};
+ FunctionSig* sig =
+ DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
+ EXPECT_EQ(nullptr, sig);
}
+TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type1) {
+ static const byte data[] = {SIG_ENTRY_x_x(kLocalI32, kLocalVoid)};
+ FunctionSig* sig =
+ DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
+ EXPECT_EQ(nullptr, sig);
+}
-class WasmFunctionVerifyTest : public TestWithZone {};
+TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
+ static const byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalVoid)};
+ FunctionSig* sig =
+ DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
+ EXPECT_EQ(nullptr, sig);
+}
+class WasmFunctionVerifyTest : public TestWithIsolateAndZone {};
TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
static const byte data[] = {
- 0, kLocalVoid, // signature
- 4, // locals
- 3, kLocalI32, // --
- 4, kLocalI64, // --
- 5, kLocalF32, // --
- 6, kLocalF64, // --
- kExprNop // body
+ SIG_ENTRY_v_v, // signature entry
+ 4, // locals
+ 3,
+ kLocalI32, // --
+ 4,
+ kLocalI64, // --
+ 5,
+ kLocalF32, // --
+ 6,
+ kLocalF64, // --
+ kExprNop // body
};
- FunctionResult result = DecodeWasmFunction(nullptr, zone(), nullptr, data,
+ FunctionResult result = DecodeWasmFunction(isolate(), zone(), nullptr, data,
data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
if (result.val && result.ok()) {
WasmFunction* function = result.val;
EXPECT_EQ(0, function->sig->parameter_count());
EXPECT_EQ(0, function->sig->return_count());
EXPECT_EQ(0, function->name_offset);
- EXPECT_EQ(2, function->code_start_offset);
+ EXPECT_EQ(SIZEOF_SIG_ENTRY_v_v, function->code_start_offset);
EXPECT_EQ(arraysize(data), function->code_end_offset);
// TODO(titzer): verify encoding of local declarations
- EXPECT_FALSE(function->external);
EXPECT_FALSE(function->exported);
}
@@ -942,47 +852,51 @@
TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) {
const byte data[] = {
- 1, // Section size.
0, // Empty section name.
// No section name, no content, nothing but sadness.
+ 0, // No section content.
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionEmpty) {
const byte data[] = {
- 5, // Section size.
- 4, 'l', 'u', 'l', 'z', // unknown section.
+ UNKNOWN_SECTION_NAME, 0,
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionNonEmpty) {
const byte data[] = {
- 10, // Section size.
- 4, 'l', 'u', 'l', 'z', // unknown section.
- // Section content:
- 0xff, 0xff, 0xff, 0xff, 0xff,
+ UNKNOWN_SECTION_NAME,
+ 5, // section size
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff, // section data
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, SignatureFollowedByEmptyUnknownSection) {
const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
// -----------------------------------------------------------
- 5, // Section size.
- 4, 'l', 'u', 'l', 'z', // unknown section.
+ UNKNOWN_SECTION_NAME,
+ 0 // empty section
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) {
const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
// -----------------------------------------------------------
- 10, // Section size.
- 4, 'l', 'u', 'l', 'z', // unknown section.
+ UNKNOWN_SECTION_NAME,
+ 5, // section size
0xff, 0xff, 0xff, 0xff, 0xff,
};
EXPECT_VERIFIES(data);
@@ -990,29 +904,46 @@
TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSectionWithLongLEB) {
const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
// -----------------------------------------------------------
- 0x85, 0x80, 0x80, 0x80, 0x00, // Section size: 1 but in a 5-byte LEB.
- 4, 'l', 'u', 'l', 'z', // unknown section.
+ UNKNOWN_SECTION_NAME, 0x81, 0x80, 0x80, 0x80,
+ 0x00, // section size: 1 but in a 5-byte LEB
+ 0,
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, UnknownSectionOverflow) {
static const byte data[] = {
- 13, // Section size.
- 1, // Section name length.
- '\0', // Section name.
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
+ UNKNOWN_EMPTY_SECTION_NAME,
+ 9, // section size
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10, // 10 byte section
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) {
static const byte data[] = {
- 0xff, 0xff, 0xff, 0xff, 0x0f, // Section size LEB128 0xffffffff
- 1, '\0', // Section name and name length.
- 1, 2, 3, 4, // 4 byte section
+ UNKNOWN_EMPTY_SECTION_NAME,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0x0f, // Section size LEB128 0xffffffff
+ 1,
+ 2,
+ 3,
+ 4, // 4 byte section
};
EXPECT_FAILURE(data);
}
@@ -1020,27 +951,33 @@
TEST_F(WasmModuleVerifyTest, UnknownSectionLoop) {
// Would infinite loop decoding if wrapping and allowed.
static const byte data[] = {
- 0xfa, 0xff, 0xff, 0xff, 0x0f, // Section size LEB128 0xfffffffa
- 1, '\0', // Section name and name length.
- 1, 2, 3, 4, // 4 byte section
+ UNKNOWN_EMPTY_SECTION_NAME,
+ 1,
+ 2,
+ 3,
+ 4, // 4 byte section
+ 0xfa,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0x0f, // Section size LEB128 0xfffffffa
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
static const byte data[] = {
- 3, // Section size.
- 1,
- '\0', // Section name: LEB128 1, string '\0'
- 0, // one byte section
- SECTION(GLOBALS, 7),
+ UNKNOWN_EMPTY_SECTION_NAME,
+ 1, // section size
+ 0, // one byte section
+ SECTION(GLOBALS, 4),
1,
0, // name length
kMemI32, // memory type
0, // exported
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
- EXPECT_TRUE(result.ok());
+ EXPECT_OK(result);
EXPECT_EQ(1, result.val->globals.size());
EXPECT_EQ(0, result.val->functions.size());
@@ -1062,26 +999,36 @@
EXPECT_VERIFIES(data);
}
-TEST_F(WasmModuleVerifyTest, ImportTable_nosigs) {
+TEST_F(WasmModuleVerifyTest, ImportTable_nosigs1) {
static const byte data[] = {SECTION(IMPORT_TABLE, 1), 0};
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) {
+ static const byte data[] = {
+ SECTION(IMPORT_TABLE, 6), 1, // sig table
+ IMPORT_SIG_INDEX(0), // sig index
+ NAME_LENGTH(1), 'm', // module name
+ NAME_LENGTH(1), 'f', // function name
+ };
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
static const byte data[] = {
- SECTION(SIGNATURES, 1), 0, SECTION(IMPORT_TABLE, 6), 1,
- IMPORT_SIG_INDEX(0), // sig index
- NAME_LENGTH(1), 'm', // module name
- NAME_LENGTH(1), 'f', // function name
+ SECTION(SIGNATURES, 1), 0, // --
+ SECTION(IMPORT_TABLE, 6), 1, // --
+ IMPORT_SIG_INDEX(0), // sig index
+ NAME_LENGTH(1), 'm', // module name
+ NAME_LENGTH(1), 'f', // function name
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1,
- VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
SECTION(IMPORT_TABLE, 6),
1, // --
IMPORT_SIG_INDEX(0), // sig index
@@ -1095,9 +1042,8 @@
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1,
- VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
SECTION(IMPORT_TABLE, 6),
1, // --
IMPORT_SIG_INDEX(0), // sig index
@@ -1110,9 +1056,8 @@
TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1,
- VOID_VOID_SIG,
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
SECTION(IMPORT_TABLE, 6),
1,
IMPORT_SIG_INDEX(0), // sig index
@@ -1126,28 +1071,31 @@
}
TEST_F(WasmModuleVerifyTest, ExportTable_empty1) {
- static const byte data[] = {SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1,
- VOID_VOID_SIG,
- SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
- 1,
- EMPTY_FUNCTION(0),
- SECTION(EXPORT_TABLE, 1),
- 0};
+ static const byte data[] = {
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(OLD_FUNCTIONS, 1 + SIZEOF_EMPTY_FUNCTION),
+ 1,
+ EMPTY_FUNCTION(0),
+ SECTION(EXPORT_TABLE, 1),
+ 0 // --
+ };
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ExportTable_empty2) {
- static const byte data[] = {SECTION(SIGNATURES, 1), 0,
- SECTION(FUNCTIONS, 1), 0,
- SECTION(EXPORT_TABLE, 1), 0};
+ static const byte data[] = {
+ SECTION(SIGNATURES, 1), 0, SECTION(OLD_FUNCTIONS, 1), 0,
+ SECTION(EXPORT_TABLE, 1), 0 // --
+ };
// TODO(titzer): current behavior treats empty functions section as missing.
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions1) {
- static const byte data[] = {SECTION(SIGNATURES, 1), 0,
- SECTION(EXPORT_TABLE, 1), 0};
+ static const byte data[] = {
+ SECTION(SIGNATURES, 1), 0, SECTION(EXPORT_TABLE, 1), 0 // --
+ };
EXPECT_FAILURE(data);
}
@@ -1158,13 +1106,12 @@
TEST_F(WasmModuleVerifyTest, ExportTableOne) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1, // sigs
- VOID_VOID_SIG, // --
- SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(OLD_FUNCTIONS, 1 + SIZEOF_EMPTY_FUNCTION),
1, // functions
EMPTY_FUNCTION(0), // --
- SECTION(EXPORT_TABLE, 7),
+ SECTION(EXPORT_TABLE, 3),
1, // exports
FUNC_INDEX(0), // --
NO_NAME // --
@@ -1174,10 +1121,9 @@
TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1, // sigs
- VOID_VOID_SIG, // --
- SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(OLD_FUNCTIONS, 1 + SIZEOF_EMPTY_FUNCTION),
1, // functions
EMPTY_FUNCTION(0), // --
SECTION(EXPORT_TABLE, 12),
@@ -1199,10 +1145,9 @@
TEST_F(WasmModuleVerifyTest, ExportTableThree) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1, // sigs
- VOID_VOID_SIG, // --
- SECTION(FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(OLD_FUNCTIONS, 1 + 3 * SIZEOF_EMPTY_FUNCTION),
3, // functions
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
@@ -1225,10 +1170,9 @@
TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
for (int i = 0; i < 6; i++) {
const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1, // sigs
- VOID_VOID_SIG, // --
- SECTION(FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(OLD_FUNCTIONS, 1 + 3 * SIZEOF_EMPTY_FUNCTION),
3, // functions
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
@@ -1251,10 +1195,9 @@
TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
static const byte data[] = {
- SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
- 1, // sigs
- VOID_VOID_SIG, // --
- SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(OLD_FUNCTIONS, 1 + SIZEOF_EMPTY_FUNCTION),
1, // functions
EMPTY_FUNCTION(0), // --
SECTION(EXPORT_TABLE, 1 + 6),
@@ -1270,67 +1213,68 @@
}
}
-#define SIGNATURES_SECTION(count, ...) \
- SECTION(SIGNATURES, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
-#define FUNCTION_SIGNATURES_SECTION(count, ...) \
- SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
-
-#define FOO_STRING 3, 'f', 'o', 'o'
-#define NO_LOCAL_NAMES 0
-
-#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
-#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
-#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
-#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
-
TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) {
- static const byte data[] = {SECTION(SIGNATURES, 1), 0,
- SECTION(FUNCTION_SIGNATURES, 1), 0};
+ static const byte data[] = {
+ SECTION(SIGNATURES, 1), 0, // --
+ SECTION(FUNCTION_SIGNATURES, 1), 0 // --
+ }; // --
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionSignatures_one) {
- static const byte data[] = {SIGNATURES_SECTION(1, VOID_VOID_SIG),
- FUNCTION_SIGNATURES_SECTION(1, 0)};
+ static const byte data[] = {
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0) // --
+ };
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) {
- static const byte data[] = {EMPTY_SIGNATURES_SECTION,
- EMPTY_FUNCTION_SIGNATURES_SECTION,
- EMPTY_FUNCTION_BODIES_SECTION};
+ static const byte data[] = {
+ EMPTY_SIGNATURES_SECTION, // --
+ EMPTY_FUNCTION_SIGNATURES_SECTION, // --
+ EMPTY_FUNCTION_BODIES_SECTION // --
+ };
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) {
static const byte data[] = {
- SIGNATURES_SECTION(1, VOID_VOID_SIG), FUNCTION_SIGNATURES_SECTION(1, 0),
- SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), 1, EMPTY_BODY};
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1, EMPTY_BODY // --
+ };
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) {
static const byte data[] = {
- SIGNATURES_SECTION(1, VOID_VOID_SIG), FUNCTION_SIGNATURES_SECTION(1, 0),
- SECTION(FUNCTION_BODIES, 1 + NOP_BODY_SIZE), 1, NOP_BODY};
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ SECTION(FUNCTION_BODIES, 1 + SIZEOF_NOP_BODY), 1, NOP_BODY // --
+ };
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) {
- static const byte data[] = {SIGNATURES_SECTION(1, VOID_VOID_SIG),
- FUNCTION_SIGNATURES_SECTION(2, 0, 0),
- SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), 1,
- EMPTY_BODY};
+ static const byte data[] = {
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
+ SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1, // --
+ EMPTY_BODY // --
+ };
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) {
- static const byte data[] = {SIGNATURES_SECTION(1, VOID_VOID_SIG),
- FUNCTION_SIGNATURES_SECTION(1, 0),
- SECTION(FUNCTION_BODIES, 1 + 2 * NOP_BODY_SIZE),
- 2,
- NOP_BODY,
- NOP_BODY};
+ static const byte data[] = {
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_NOP_BODY), // --
+ 2, // --
+ NOP_BODY, // --
+ NOP_BODY // --
+ };
EXPECT_FAILURE(data);
}
@@ -1343,9 +1287,9 @@
TEST_F(WasmModuleVerifyTest, Names_one_empty) {
static const byte data[] = {
- SIGNATURES_SECTION(1, VOID_VOID_SIG), // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0), // --
- SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE),
+ SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY),
1,
EMPTY_BODY, // --
SECTION(NAMES, 1 + 5),
@@ -1358,9 +1302,9 @@
TEST_F(WasmModuleVerifyTest, Names_two_empty) {
static const byte data[] = {
- SIGNATURES_SECTION(1, VOID_VOID_SIG), // --
- FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
- SECTION(FUNCTION_BODIES, 1 + 2 * EMPTY_BODY_SIZE), // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
+ SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_EMPTY_BODY), // --
2,
EMPTY_BODY,
EMPTY_BODY, // --
diff --git a/test/unittests/wasm/switch-logic-unittest.cc b/test/unittests/wasm/switch-logic-unittest.cc
new file mode 100644
index 0000000..be587c2
--- /dev/null
+++ b/test/unittests/wasm/switch-logic-unittest.cc
@@ -0,0 +1,89 @@
+// 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/wasm/switch-logic.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+class SwitchLogicTest : public TestWithZone {};
+
+void CheckNodeValues(CaseNode* node, int begin, int end) {
+ CHECK_EQ(node->begin, begin);
+ CHECK_EQ(node->end, end);
+}
+
+TEST_F(SwitchLogicTest, Single_Table_Test) {
+ ZoneVector<int> values(zone());
+ values.push_back(14);
+ values.push_back(12);
+ values.push_back(15);
+ values.push_back(19);
+ values.push_back(18);
+ values.push_back(16);
+ CaseNode* root = OrderCases(&values, zone());
+ CHECK_NULL(root->left);
+ CHECK_NULL(root->right);
+ CheckNodeValues(root, 12, 19);
+}
+
+TEST_F(SwitchLogicTest, Balanced_Tree_Test) {
+ ZoneVector<int> values(zone());
+ values.push_back(5);
+ values.push_back(1);
+ values.push_back(6);
+ values.push_back(9);
+ values.push_back(-4);
+ CaseNode* root = OrderCases(&values, zone());
+ CheckNodeValues(root, 5, 5);
+ CheckNodeValues(root->left, -4, -4);
+ CHECK_NULL(root->left->left);
+ CheckNodeValues(root->left->right, 1, 1);
+ CHECK_NULL(root->left->right->left);
+ CHECK_NULL(root->left->right->right);
+ CheckNodeValues(root->right, 6, 6);
+ CHECK_NULL(root->right->left);
+ CheckNodeValues(root->right->right, 9, 9);
+ CHECK_NULL(root->right->right->left);
+ CHECK_NULL(root->right->right->right);
+}
+
+TEST_F(SwitchLogicTest, Hybrid_Test) {
+ ZoneVector<int> values(zone());
+ values.push_back(1);
+ values.push_back(2);
+ values.push_back(3);
+ values.push_back(4);
+ values.push_back(7);
+ values.push_back(10);
+ values.push_back(11);
+ values.push_back(12);
+ values.push_back(13);
+ values.push_back(16);
+ CaseNode* root = OrderCases(&values, zone());
+ CheckNodeValues(root, 7, 7);
+ CheckNodeValues(root->left, 1, 4);
+ CheckNodeValues(root->right, 10, 13);
+ CheckNodeValues(root->right->right, 16, 16);
+}
+
+TEST_F(SwitchLogicTest, Single_Case) {
+ ZoneVector<int> values(zone());
+ values.push_back(3);
+ CaseNode* root = OrderCases(&values, zone());
+ CheckNodeValues(root, 3, 3);
+ CHECK_NULL(root->left);
+ CHECK_NULL(root->right);
+}
+
+TEST_F(SwitchLogicTest, Empty_Case) {
+ ZoneVector<int> values(zone());
+ CaseNode* root = OrderCases(&values, zone());
+ CHECK_NULL(root);
+}
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8
diff --git a/test/unittests/wasm/wasm-macro-gen-unittest.cc b/test/unittests/wasm/wasm-macro-gen-unittest.cc
index ec188c0..1058993 100644
--- a/test/unittests/wasm/wasm-macro-gen-unittest.cc
+++ b/test/unittests/wasm/wasm-macro-gen-unittest.cc
@@ -18,7 +18,6 @@
EXPECT_EQ(size, sizeof(code)); \
} while (false)
-
TEST_F(WasmMacroGenTest, Constants) {
EXPECT_SIZE(2, WASM_ONE);
EXPECT_SIZE(2, WASM_ZERO);
@@ -48,7 +47,6 @@
EXPECT_SIZE(9, WASM_F64(-9818934.0));
}
-
TEST_F(WasmMacroGenTest, Statements) {
EXPECT_SIZE(1, WASM_NOP);
@@ -58,9 +56,9 @@
EXPECT_SIZE(7, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_ZERO));
- EXPECT_SIZE(4, WASM_IF(WASM_ZERO, WASM_NOP));
+ EXPECT_SIZE(5, WASM_IF(WASM_ZERO, WASM_NOP));
- EXPECT_SIZE(5, WASM_IF_ELSE(WASM_ZERO, WASM_NOP, WASM_NOP));
+ EXPECT_SIZE(7, WASM_IF_ELSE(WASM_ZERO, WASM_NOP, WASM_NOP));
EXPECT_SIZE(5, WASM_SELECT(WASM_ZERO, WASM_NOP, WASM_NOP));
@@ -79,16 +77,14 @@
EXPECT_SIZE(5, WASM_LOOP(1, WASM_BR(0)));
EXPECT_SIZE(7, WASM_LOOP(1, WASM_BR_IF(0, WASM_ZERO)));
- EXPECT_SIZE(1, WASM_RETURN0);
- EXPECT_SIZE(3, WASM_RETURN(WASM_ZERO));
- EXPECT_SIZE(5, WASM_RETURN(WASM_ZERO, WASM_ZERO));
+ EXPECT_SIZE(2, WASM_RETURN0);
+ EXPECT_SIZE(4, WASM_RETURN1(WASM_ZERO));
EXPECT_SIZE(1, WASM_UNREACHABLE);
}
-
TEST_F(WasmMacroGenTest, MacroStatements) {
- EXPECT_SIZE(8, WASM_WHILE(WASM_I8(0), WASM_NOP));
+ EXPECT_SIZE(10, WASM_WHILE(WASM_I8(0), WASM_NOP));
EXPECT_SIZE(7, WASM_INC_LOCAL(0));
EXPECT_SIZE(7, WASM_INC_LOCAL_BY(0, 3));
@@ -97,10 +93,10 @@
}
TEST_F(WasmMacroGenTest, BrTable) {
- EXPECT_SIZE(8, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
+ EXPECT_SIZE(9, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
+ EXPECT_SIZE(11, WASM_BR_TABLEV(WASM_ZERO, WASM_ZERO, 1, BR_TARGET(1)));
}
-
TEST_F(WasmMacroGenTest, Expressions) {
EXPECT_SIZE(2, WASM_GET_LOCAL(0));
EXPECT_SIZE(2, WASM_GET_LOCAL(1));
@@ -114,8 +110,8 @@
EXPECT_SIZE(3, WASM_NOT(WASM_ZERO));
- EXPECT_SIZE(4, WASM_BRV(1, WASM_ZERO));
- EXPECT_SIZE(6, WASM_BRV_IF(1, WASM_ZERO, WASM_ZERO));
+ EXPECT_SIZE(5, WASM_BRV(1, WASM_ZERO));
+ EXPECT_SIZE(7, WASM_BRV_IF(1, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(4, WASM_BLOCK(1, WASM_ZERO));
EXPECT_SIZE(5, WASM_BLOCK(2, WASM_NOP, WASM_ZERO));
@@ -127,33 +123,32 @@
}
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(3, WASM_CALL_FUNCTION0(0));
+ EXPECT_SIZE(3, WASM_CALL_FUNCTION0(1));
+ EXPECT_SIZE(3, WASM_CALL_FUNCTION0(11));
- EXPECT_SIZE(4, WASM_CALL_FUNCTION(0, WASM_ZERO));
- EXPECT_SIZE(6, WASM_CALL_FUNCTION(1, WASM_ZERO, WASM_ZERO));
+ EXPECT_SIZE(5, WASM_CALL_FUNCTION1(0, WASM_ZERO));
+ EXPECT_SIZE(7, WASM_CALL_FUNCTION2(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(3, WASM_CALL_IMPORT0(0));
+ EXPECT_SIZE(3, WASM_CALL_IMPORT0(1));
+ EXPECT_SIZE(3, WASM_CALL_IMPORT0(11));
- EXPECT_SIZE(4, WASM_CALL_IMPORT(0, WASM_ZERO));
- EXPECT_SIZE(6, WASM_CALL_IMPORT(1, WASM_ZERO, WASM_ZERO));
+ EXPECT_SIZE(5, WASM_CALL_IMPORT1(0, WASM_ZERO));
+ EXPECT_SIZE(7, WASM_CALL_IMPORT2(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));
+ EXPECT_SIZE(5, WASM_CALL_INDIRECT0(0, WASM_ZERO));
+ EXPECT_SIZE(5, WASM_CALL_INDIRECT0(1, WASM_ZERO));
+ EXPECT_SIZE(5, WASM_CALL_INDIRECT0(11, WASM_ZERO));
- EXPECT_SIZE(6, WASM_CALL_INDIRECT(0, WASM_ZERO, WASM_ZERO));
- EXPECT_SIZE(8, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ EXPECT_SIZE(7, WASM_CALL_INDIRECT1(0, WASM_ZERO, WASM_ZERO));
+ EXPECT_SIZE(9, WASM_CALL_INDIRECT2(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
}
-
TEST_F(WasmMacroGenTest, Int32Ops) {
EXPECT_SIZE(5, WASM_I32_ADD(WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_I32_SUB(WASM_ZERO, WASM_ZERO));
@@ -189,7 +184,6 @@
EXPECT_SIZE(3, WASM_I32_EQZ(WASM_ZERO));
}
-
TEST_F(WasmMacroGenTest, Int64Ops) {
EXPECT_SIZE(5, WASM_I64_ADD(WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_I64_SUB(WASM_ZERO, WASM_ZERO));
@@ -225,7 +219,6 @@
EXPECT_SIZE(3, WASM_I64_EQZ(WASM_ZERO));
}
-
TEST_F(WasmMacroGenTest, Float32Ops) {
EXPECT_SIZE(5, WASM_F32_ADD(WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_F32_SUB(WASM_ZERO, WASM_ZERO));
@@ -250,7 +243,6 @@
EXPECT_SIZE(5, WASM_F32_GE(WASM_ZERO, WASM_ZERO));
}
-
TEST_F(WasmMacroGenTest, Float64Ops) {
EXPECT_SIZE(5, WASM_F64_ADD(WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_F64_SUB(WASM_ZERO, WASM_ZERO));
@@ -275,7 +267,6 @@
EXPECT_SIZE(5, WASM_F64_GE(WASM_ZERO, WASM_ZERO));
}
-
TEST_F(WasmMacroGenTest, Conversions) {
EXPECT_SIZE(3, WASM_I32_SCONVERT_F32(WASM_ZERO));
EXPECT_SIZE(3, WASM_I32_SCONVERT_F64(WASM_ZERO));
@@ -317,7 +308,6 @@
}
}
-
TEST_F(WasmMacroGenTest, LoadsAndStoresWithOffset) {
for (size_t i = 0; i < arraysize(kMemTypes); i++) {
EXPECT_SIZE(5, WASM_LOAD_MEM_OFFSET(kMemTypes[i], 11, WASM_ZERO));