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));